Pagination & Limits

Pagination

List endpoints are page-based. Pass page as a query parameter; it defaults to 1.

curl 'https://api.blueprint.ai/v2/clinicians/{clinicianId}/clients?page=2' \
  -H 'Access-Token: YOUR_ACCESS_TOKEN' \
  -H 'X-API-Key: YOUR_API_KEY'

Every paginated response has the same envelope:

{
  "data": [
    { "id": "00000000-0000-0000-0000-000000000000", "firstName": "Jordan", "lastName": "Reyes" }
  ],
  "meta": {
    "totalItems": 42,
    "totalPages": 5,
    "itemsPerPage": 10,
    "currentPage": 2
  }
}

Page size is fixed at 10 and cannot be changed. There is no limit, pageSize, or per_page
parameter. Iterate until currentPage === totalPages:

async function listAllClients(clinicianId) {
  const all = []
  let page = 1, totalPages = 1

  do {
    const res = await fetch(
      `${BASE}/clinicians/${clinicianId}/clients?page=${page}`,
      { headers }
    )
    const { data, meta } = await res.json()
    all.push(...data)
    totalPages = meta.totalPages
    page += 1
  } while (page <= totalPages)

  return all
}

Paginated endpoints

GET /organizations · GET /organizations/{organizationId}/clinics ·
GET /organizations/{organizationId}/programs · GET /clinics/{clinicId}/clinicians ·
GET /clinics/{clinicId}/clients · GET /clinics/{clinicId}/assessments ·
GET /clinicians/{clinicianId}/clients · GET /clinicians/{clinicianId}/magic-edit ·
GET /clients/{clientId}/sessions · GET /clients/{clientId}/programs

Filtering

Two list endpoints accept filters alongside page. All filters are optional and combine with AND.

GET /clinics/{clinicId}/clients and GET /clinicians/{clinicianId}/clients:

ParameterNotes
externalIdYour own identifier. The recommended way to find a client you created.
firstName, lastNameExact match
nameFree-text search across first and last name
email, phoneNumberExact match
dateOfBirthISO 8601 date
statusawaiting_invite, active, archived, declined, invite_sent, pending, unknown
clinicianIdClinic-scoped endpoint only

GET /clinics/{clinicId}/clinicians: id, firstName, lastName, email, externalId

GET /clinics/{clinicId}/assessments: defaultOnly

Filtering by externalId is the intended way to reconcile your records with Blueprint's — see
Concepts.

Rate limits

The Partner API enforces rate, burst, and daily quota limits. See
Rate Limiting & Throttling for the default usage plan and
guidance for handling throttled requests.

Idempotency

Idempotency keys are not supported. There is no Idempotency-Key header, so a retried POST
may create a duplicate resource.

Practical guidance:

  • Creates are not safe to blind-retry. If a create times out, search before retrying — use
    ?externalId= for clients and clinicians. Setting externalId on everything you create makes this
    possible; without it you have no way to detect the duplicate.
  • POST /clients/{clientId}/secondary-clinicians is safe to retry. It skips clinicians who are
    already assigned.
  • PATCH and DELETE are naturally idempotent.

Webhook deduplication

Webhook delivery is at-least-once, so you can receive the same event more than once, and the
payload carries no delivery ID to dedupe on. Use the natural key from the payload instead:

Event groupSuggested dedupe key
Progress note eventseventType + progressNoteId
transcript_ready, session_transcript_error, mdm_elements_identifiedeventType + sessionId
assessment_completedeventType + each assessmentScores[].id

Make your handler idempotent on that key. See
Listening to Webhooks.

Field limits and validation rules

FieldRule
phoneNumberMust include a + calling code, e.g. +15555550123. Without it the request fails with 400 phoneNumber should include calling code.
userInstructions (magic edit)Maximum 5000 characters. Whitespace is trimmed.
dateOfBirthISO 8601 date string
fileUrl (create session)Must be a valid absolute URL. See API Only Integrations.
externalIdFree-form string. Expected to be unique within a clinical organization; not enforced.

Did this page help you?