Skip to Content
APIPull

Pull API

The Pull API is the source of truth for partner data. All timestamps are UTC in ISO 8601. Authenticate with a static API key in the Authorization header.

Base URL and authentication

  • Base URL: https://api.dev-ai.coach/v1
  • Production and test use this URL; the issued API key selects the environment.
  • Authentication: Send your API key on every request:
Authorization: Api-Key <API KEY>

You can obtain the API key from the Partner Portal. Keep it secret and do not expose it in client-side code.

Conventions

Pagination

List endpoints support cursor-based pagination:

  • limit (optional) — Max items per page (1–1000, default 100).
  • cursor (optional) — Use the next_cursor value from the previous response to fetch the next page. Omit for the first page.

Responses use this shape:

{ "data": [], "meta": { "limit": 100, "next_cursor": null } }

Use meta.next_cursor unchanged for the next page. A cursor is opaque and tied to the original endpoint and filters. When next_cursor is null, there are no more pages. There is no previous-page cursor.

Time filters

Where supported, use from and to as UTC ISO 8601 date-time query parameters. Items are filtered by the endpoint timestamp (completed_at for workouts, occurred_at for tests, body composition, and deliveries): from is inclusive and to is exclusive. Workouts, tests, and body composition are available for the 30 calendar days before the request date.

Response statuses

  • 200 — Successful GET request, or member names stored (PATCH/POST name endpoints).
  • 202 — User removal accepted.
  • 204 — No body composition measurement is available.
  • 400 — Invalid query parameters, date range, limit, cursor, or request body.
  • 401 — Missing, invalid, revoked, or expired API key; includes WWW-Authenticate: Api-Key.
  • 403 — Authenticated API key is not permitted to perform the operation.
  • 404 — Resource not found or unavailable in your partner scope.
  • 405 — HTTP method is not supported.
  • 429 — Rate limit exceeded. Use the Retry-After response header (seconds) before retrying.
  • 500 — Internal server error.

Error responses are JSON with a detail string describing the issue.

Quick check

Verify connectivity and authentication:

curl -s -H "Authorization: Api-Key <API KEY>" https://api.dev-ai.coach/v1/status

Example response:

{ "status": "ok", "partner_name": "Your Partner", "timestamp": "2025-03-12T10:00:00.000Z" }

Endpoints by use case

Health and self-service

MethodPathDescription
GET/statusHealth check; returns status, partner name, and timestamp.

Webhook delivery audit

Use these to debug missed webhooks or reconcile with your system.

MethodPathDescription
GET/webhooks/deliveriesList webhook delivery records. Optional query: partner_user_id, status (pending, delivered, failed), from, to, limit, cursor.

Users

MethodPathDescription
GET/usersEnumerate partner user IDs with first_name and last_name (paginated).
GET/users/{partner_user_id}Get user summary (names, latest workout, tests, body composition, and streak).
DELETE/users/{partner_user_id}Remove user from this partner’s API access. Clears the member’s names. Emits user.deleted; a repeated delete returns 404.
PATCH/users/{partner_user_id}/nameSet the member’s first name, last name, or both. See Member Names.
POST/users/names:batchSet names for up to 500 members in one request. See Member Names.

first_name and last_name are the names you set through Member Names. They are null until you set them, and they are separate from the name the member chose in the Zing app.

Workouts

MethodPathDescription
GET/users/{partner_user_id}/workoutsList workouts for a user. Optional: from, to, limit, cursor.
GET/workouts/{workout_id}Get full workout detail by ID (includes exercises with duration, weight, reps).

Tests

MethodPathDescription
GET/users/{partner_user_id}/testsList tests for a user. Optional: type (fitness | flexibility), from, to, limit, cursor.
GET/tests/{test_id}Get full test result by ID (includes metrics).

Body composition

MethodPathDescription
GET/users/{partner_user_id}/body_compositionList body composition measurements. Optional: from, to, limit, cursor.
GET/users/{partner_user_id}/body_composition/latestGet latest measurement for the user. Returns 204 if none.

Reporting (usage)

MethodPathDescription
GET/usage/dailyDaily usage for a date. Required query: date (YYYY-MM-DD). Returns active users, workouts, tests by type, body composition count.
GET/usage/monthlyMonthly usage. Required query: date (YYYY-MM). Same metric shape as daily.

Workout response

Completed workout list items have this shape:

{ "data": [ { "workout_id": "0198f436-d258-7b42-a360-68b1cb923782", "partner_user_id": "partner-usr-123", "completed_at": "2025-03-12T09:00:00.000Z", "updated_at": "2025-03-12T09:15:00.000Z", "duration_seconds": 1800, "category": "training" } ], "meta": { "limit": 100, "next_cursor": null } }

Workout detail

When you receive a workout.completed webhook, fetch the full detail with the workout ID from the payload:

The response includes the same list fields plus a flat exercises array. Each exercise includes exercise_id, group_index, result_index, phase, name, target, duration_seconds, repetitions, and weight (value and unit).

Considerations

  • Rate limits — If you receive 429, back off using Retry-After and use exponential backoff for repeated failures.
  • Idempotency — GET and list endpoints are safe to retry. DELETE is idempotent: a second delete returns 404. The member name endpoints are safe to retry: sending the same names again stores the same values.
  • Partner isolation — You only see data for users belonging to your partner account; user IDs are the same values you send to Zing when creating users.

Monthly usage is month-to-date: values cover the UTC month through the returned calculated_until date.

Request examples

Use the API key in the Authorization header. Replace <API KEY> with the key issued for your environment.

List users

curl -sS \ -H "Authorization: Api-Key <API KEY>" \ "https://api.dev-ai.coach/v1/users"

Example response:

{ "data": [ { "partner_user_id": "partner-usr-123", "first_name": "Jane", "last_name": "Doe" }, { "partner_user_id": "partner-usr-456", "first_name": null, "last_name": null } ], "meta": { "limit": 100, "next_cursor": null } }

Get user summary

curl -sS \ -H "Authorization: Api-Key <API KEY>" \ "https://api.dev-ai.coach/v1/users/partner-usr-123"

Example response:

{ "partner_user_id": "partner-usr-123", "first_name": "Jane", "last_name": "Doe", "created_at": "2026-08-01T08:00:00.000Z", "latest_workout": { "workout_id": "0198f436-d258-7b42-a360-68b1cb923782", "partner_user_id": "partner-usr-123", "completed_at": "2026-08-20T10:15:32.120Z", "updated_at": "2026-08-20T10:16:00.000Z", "duration_seconds": 1800, "category": "training" }, "latest_tests": { "fitness": null, "flexibility": null }, "latest_body_composition": null, "streak": { "date": "2026-08-20", "streak_length": 5 } }

List workouts

curl -sS \ -H "Authorization: Api-Key <API KEY>" \ "https://api.dev-ai.coach/v1/users/partner-usr-123/workouts"

Example response:

{ "data": [ { "workout_id": "0198f436-d258-7b42-a360-68b1cb923782", "partner_user_id": "partner-usr-123", "completed_at": "2026-08-20T10:15:32.120Z", "updated_at": "2026-08-20T10:16:00.000Z", "duration_seconds": 1800, "category": "training" } ], "meta": { "limit": 100, "next_cursor": null } }

Get workout detail

curl -sS \ -H "Authorization: Api-Key <API KEY>" \ "https://api.dev-ai.coach/v1/workouts/0198f436-d258-7b42-a360-68b1cb923782"

Example response:

{ "workout_id": "0198f436-d258-7b42-a360-68b1cb923782", "partner_user_id": "partner-usr-123", "completed_at": "2026-08-20T10:15:32.120Z", "updated_at": "2026-08-20T10:16:00.000Z", "duration_seconds": 1800, "category": "training", "exercises": [ { "exercise_id": "3dd31f8b-668d-4da4-a565-9dfcff5f5a13", "group_index": 0, "result_index": 0, "phase": "main", "name": "Squat", "target": "lower_body", "duration_seconds": null, "repetitions": 12, "weight": { "value": 40, "unit": "kg" } } ] }

List tests

curl -sS \ -H "Authorization: Api-Key <API KEY>" \ "https://api.dev-ai.coach/v1/users/partner-usr-123/tests"

Example response:

{ "data": [ { "test_id": "0198f437-0101-70a6-b22f-3984cd49c9e2", "partner_user_id": "partner-usr-123", "test_type": "fitness", "occurred_at": "2026-08-20T09:30:00.000Z", "updated_at": "2026-08-20T09:31:00.000Z", "score": 82.4 } ], "meta": { "limit": 100, "next_cursor": null } }

Get test detail

curl -sS \ -H "Authorization: Api-Key <API KEY>" \ "https://api.dev-ai.coach/v1/tests/0198f437-0101-70a6-b22f-3984cd49c9e2"

Example response (fitness test):

{ "test_id": "0198f437-0101-70a6-b22f-3984cd49c9e2", "test_type": "fitness", "occurred_at": "2026-08-20T09:30:00.000Z", "fitness_score": 82.4, "fitness_level": 4.2, "fitness_age": 31, "fitness_score_lower_bound": 78, "fitness_score_upper_bound": 86, "sex": "male", "exercises": [ { "exercise_type": "push_ups", "correct_reps": 18, "total_reps": 20, "score": 82.1, "level": 4.2, "movement_quality": 0.9, "avg_speed": 1.4, "max_speed": 2.1, "time_seconds": 45.3, "endurance": 0.8 } ] }

List body composition measurements

curl -sS \ -H "Authorization: Api-Key <API KEY>" \ "https://api.dev-ai.coach/v1/users/partner-usr-123/body_composition"

Example response:

{ "data": [ { "measurement_id": "0198f438-0202-71b7-c33f-4095de50d3f3", "partner_user_id": "partner-usr-123", "occurred_at": "2026-08-20T08:00:00.000Z", "total_body_fat_percentage": 19.5, "weight": 80, "weight_unit": "kg", "fat_mass_index": { "value": 4.7, "category": "HEALTHY", "unit": "kg/m2" } } ], "meta": { "limit": 100, "next_cursor": null } }

Get latest body composition measurement

curl -sS \ -H "Authorization: Api-Key <API KEY>" \ "https://api.dev-ai.coach/v1/users/partner-usr-123/body_composition/latest"

Example response:

{ "measurement_id": "0198f438-0202-71b7-c33f-4095de50d3f3", "partner_user_id": "partner-usr-123", "occurred_at": "2026-08-20T08:00:00.000Z", "total_body_fat_percentage": 19.5, "weight": 80, "weight_unit": "kg", "fat_mass_index": { "value": 4.7, "category": "HEALTHY", "unit": "kg/m2" } }

Get daily usage

curl -sS \ -H "Authorization: Api-Key <API KEY>" \ "https://api.dev-ai.coach/v1/usage/daily?date=2026-08-20"

Example response:

{ "date": "2026-08-20", "active_users": 100, "workouts_completed": 300, "tests_completed_by_type": { "fitness": 15, "flexibility": 10 }, "body_composition_measurements": 7, "calculated_at": "2026-08-21T01:00:00.000Z" }

Get monthly usage

curl -sS \ -H "Authorization: Api-Key <API KEY>" \ "https://api.dev-ai.coach/v1/usage/monthly?date=2026-08"

Example response:

{ "month": "2026-08", "active_users": 100, "workouts_completed": 300, "tests_completed_by_type": { "fitness": 15, "flexibility": 10 }, "body_composition_measurements": 7, "calculated_until": "2026-08-20", "calculated_at": "2026-08-21T02:09:00.000Z" }

List webhook deliveries

curl -sS \ -H "Authorization: Api-Key <API KEY>" \ "https://api.dev-ai.coach/v1/webhooks/deliveries"

Example response:

{ "data": [ { "delivery_id": "0198f439-0303-72c8-d44f-50a6ef61e4f4", "destination_id": "0198f42f-580a-7856-bf69-d1f31ed2ef44", "transport_type": "custom_webhook", "event_id": "0198f435-e1f8-7e65-b8dc-00bc4bd91842", "event_type": "workout.completed", "occurred_at": "2026-08-20T10:15:32.120Z", "partner_user_id": "partner-usr-123", "status": "delivered", "http_status": 200, "attempt_count": 1, "last_error": null, "first_attempt_at": "2026-08-20T10:15:32.450Z", "last_attempt_at": "2026-08-20T10:15:32.450Z", "next_retry_at": null, "delivered_at": "2026-08-20T10:15:32.710Z", "created_at": "2026-08-20T10:15:32.200Z", "event_timestamp_ns": 1787220932120000000 } ], "meta": { "limit": 100, "next_cursor": null } }

For receiving change notifications and implementing a webhook consumer, see Webhooks. For exhaustive endpoint details, parameters, and response schemas, see the Reference (opens in new window).

Last updated on