Skip to content

Getting Started

API conventions

Pagination, identifiers, timestamps, idempotency, and the response envelope — the rules every endpoint follows.

Every endpoint in the OnCore Core API follows the same handful of rules. Learn them once here and the rest of the reference reads as a list of shapes.

The response envelope#

Every JSON response — success or failure — has the same three top-level keys.

Success
{
  "success": true,
  "data": { "…": "…" },
  "metadata": {
    "timestamp": "2026-07-30T12:00:00.000Z",
    "version": "1.0",
    "path": "/assistants"
  }
}

data carries the payload, metadata carries request context, and success tells you which branch you are on. On failure, error replaces data — see Errors.

Two deliberate exceptions

The embed-facing endpoints — POST /webrtc-call/connect and the /web-chat/* routes — return bare JSON with no envelope, and a fixed { "error": "not_found" } body on 404. That is intentional anti-enumeration behavior, explained in Errors.

Pagination#

List endpoints take limit and offset query parameters.

ParameterTypeDescription
limitintegerPage size. Default 50, maximum 500.
offsetintegerNumber of items to skip. Default 0.
Terminal
curl "https://core-api.heysadie.ai/assistants?limit=25&offset=50" \
  -H "Authorization: ApiKey YOUR_API_KEY"

List responses carry the page in a named array plus a total count, so you can tell when you have reached the end:

Response shape
{
  "success": true,
  "data": {
    "assistants": [{ "…": "…" }],
    "total": 128
  }
}

Walk a full collection by advancing offset until you have seen total items:

Paging through every assistant
const base = "https://core-api.heysadie.ai";
const headers = { Authorization: `ApiKey ${process.env.ONCORE_API_KEY}` };

const all = [];
let offset = 0;

while (true) {
  const res = await fetch(`${base}/assistants?limit=500&offset=${offset}`, { headers });
  const { data } = await res.json();

  all.push(...data.assistants);
  offset += data.assistants.length;

  if (all.length >= data.total || data.assistants.length === 0) break;
}

Offset pagination is not a stable snapshot

Items created or deleted while you page will shift the window, so a long walk can miss or repeat rows. For a consistent view, page quickly and reconcile by id rather than assuming each page is disjoint.

Identifiers#

Every resource is identified by a UUID, and IDs are stable for the lifetime of the resource.

text
0195f1e2-1111-7000-8000-000000000000

IDs are opaque: do not parse them, derive meaning from them, or assume ordering. Placeholders in these docs use the 0195f1e2-… prefix so they are obviously not real.

Timestamps#

All timestamps are ISO 8601 in UTC, with milliseconds:

text
2026-07-30T12:00:00.000Z

Send timestamps in the same format. Parse them with a real date library rather than string slicing — the API may add offsets in future.

Phone numbers#

Phone numbers are always E.164: a leading +, country code, no spaces or punctuation.

text
+15555550123

A number in any other format is rejected with VALIDATION_ERROR.

Content type#

Send Content-Type: application/json on every request with a body. The one exception is document upload, which also accepts multipart/form-data — see the Documents API.

Idempotency#

The API does not currently expose an idempotency-key header. Design your integration accordingly:

  • PATCH and PUT are naturally idempotent — replaying them converges on the same state.
  • DELETE is idempotent in effect; deleting an already-deleted resource returns RESOURCE_NOT_FOUND rather than failing destructively.
  • POST is not. Retrying a create after a timeout can produce a duplicate. Guard it by recording your own request key before the call and reconciling with a GET list filtered by search before you retry.

TODO — verify

Confirm with the API team whether an Idempotency-Key header is planned. If one ships, this section and the retry guidance in Rate limits should be rewritten around it.

Unknown fields#

Treat responses as open: the API may add fields to any object without a breaking change. Deserialize permissively and ignore keys you do not recognize rather than failing on them. See Versioning for what does and does not count as breaking.

Next#

  • Rate limits — what to expect under load, and how to back off.
  • Versioning — how the API changes, and what is guaranteed.
  • Errors — the error envelope and every code it returns.