List trainees

GET/api/public/trainees

List trainees of the coach, filterable by label/search.

Authentication

Requires an API key, sent as Authorization: Bearer cp_live_....

API keys carry scopes. Get the catalog of scopes and webhook events lists every scope.

Query parameters

Query parameters
NameTypeDescription
pagestring

Page number (1-based, default 1)

limitstring

Items per page (1-500, default 25)

searchstring

Search by name, email, or phone

labelIdstring

Filter to trainees with this label

emailstring

Match by email (case insensitive)

phonestring

Match by phone number

statusstring

Filter by coaching status. "active" = has an active coaching period. "pending" = invited but not yet approved by the coach; these trainees are not returned by the other filters, and their activeCoachDetails.pendingCoachDate tells you how long they have been waiting. "archived" = removed with DELETE /trainees/{traineeId}; they are excluded from every other filter and from GET /trainees/{traineeId}, which answers 403 for them, so this is the only way to see them. Archived results carry no activeCoachDetails, and support only page, limit, search, email and phone. Bring one back with POST /trainees/{traineeId}/restore.

Allowed values: active inactive pending archived

Request examples

cURL
curl --request GET \
  --url 'https://api.coach-platform.com/api/public/trainees' \
  --header 'Authorization: Bearer cp_live_...'
JavaScript (fetch)
const response = await fetch('https://api.coach-platform.com/api/public/trainees', {
  method: 'GET',
  headers: {
    Authorization: 'Bearer cp_live_...',
  },
});

const data = await response.json();

Responses

200 OK

Successful response

Example body (application/json)
{
  "data": [
    {
      "id": "<string>",
      "name": "<string>",
      "email": "<string>",
      "phoneNumber": "<string>",
      "goal": "<string>",
      "profileImageUrl": "<string>",
      "personalDetails": {},
      "labels": [
        {
          "id": "<string>",
          "text": "<string>",
          "color": "<string>",
          "coachId": "<string>"
        }
      ],
      "assignedEmployees": [
        {
          "id": "<string>",
          "name": "<string>"
        }
      ],
      "activeCoachDetails": {
        "activeEscort": "<string>",
        "pendingCoach": "<string>",
        "pendingCoachDate": "<date-time>"
      },
      "createdAt": "<date-time>"
    }
  ],
  "pagination": {
    "page": 123,
    "limit": 123,
    "total": 123,
    "hasMore": true,
    "truncated": true
  }
}
Response fields (27)
Response fields
NameTypeDescription
dataobject[]
data[].idstring
data[].namestring
data[].emailstring
data[].phoneNumberstring
data[].goalstring
data[].profileImageUrlstring
data[].personalDetailsobject
data[].labelsobject[]
data[].labels[].idstring
data[].labels[].textstring
data[].labels[].colorstring
data[].labels[].coachIdstring
data[].assignedEmployeesobject[]
data[].assignedEmployees[].idstring
data[].assignedEmployees[].namestring
data[].activeCoachDetailsobject
data[].activeCoachDetails.activeEscortstring | null

Id of the escort currently in use for this trainee. Fetch the full escort with GET /escorts/{escortId}.

data[].activeCoachDetails.pendingCoachstring | null

Coach id this trainee is pending approval for. Set when the trainee was invited but has not been approved yet; null once approved. Use ?status=pending on GET /trainees to list only these.

data[].activeCoachDetails.pendingCoachDatestring<date-time> | null

When the trainee entered the pending state. Use it to measure how long approval has been waiting.

data[].createdAtstring<date-time>
paginationobject
pagination.pagenumber
pagination.limitnumber
pagination.totalnumber | null

Total number of matching items. null when the underlying source cannot report an exact count for this page; use hasMore to keep paging.

pagination.hasMoreboolean
pagination.truncatedboolean

Present and true when the result set exceeded the in-memory scan cap and was truncated. Narrow your filters to page through all items.

Error responses

  • 400 Bad Request
  • 401 Unauthorized
  • 403 Forbidden
  • 429 Too Many Requests
  • 500 Internal Server Error

These statuses share the same response body.

Example body (application/json)
{
  "error": {
    "code": "<string>",
    "message": "<string>",
    "fix": "<string>",
    "details": {},
    "retryAfterMs": 123
  }
}
Error fields (6)
Error fields
NameTypeDescription
errorobject
error.codestring
error.messagestring
error.fixstring | null
error.detailsobject | null
error.retryAfterMsnumber | null

This page is also available as Markdown. Browse it in the interactive explorer or download the OpenAPI spec.