Docs/Foundations

Find the framework route, component prop, SDK method, or HTTP contract you need.

Requests, responses, and retries

Every SDK follows the same API conventions: authenticated server calls, credential-free browser calls, predictable envelopes, cursor pages, and structured errors.

Two JavaScript clients

// Server only
const server = new Incld({
 apiKey: process.env.INCLD_SECRET_KEY!,
 baseUrl: "https://api.incld.dev",
 scope: {
  organizationId: session.organization.id,
  userId: session.user.id,
 },
 timeoutMs: 10_000,
})

// Browser only
const browser = new IncldBrowser({
 baseUrl: "/api/incld",
 timeoutMs: 10_000,
})

IncldBrowser rejects absolute base URLs and ignores custom headers. Incld attaches the bearer key and may send server-only custom headers. Its optional scope protects every request at the API boundary; omit it only for intentional project-administrator jobs.

Wire envelopes

{ "data": { "id": "..." } }

{
 "data": [],
 "meta": { "next_cursor": null, "has_more": false }
}

{
 "error": {
  "code": "validation_failed",
  "message": "The request could not be validated.",
  "fields": { "action": ["is unknown"] },
  "request_id": "req_..."
 }
}

REST JSON is snake_case. JavaScript objects are camelCase. Go uses exported struct fields and Elixir returns decoded maps with the REST keys.

Cursor pagination

let cursor: string | undefined

do {
 const page = await incld.schedules.list({ limit: 100, cursor })
 for (const schedule of page.data) consume(schedule)
 cursor = page.meta.nextCursor ?? undefined
} while (cursor)

Collection endpoints default to 25 records and accept at most 100. Treat cursors as opaque and stop when hasMore is false or nextCursor is null.

Transport options

interface RequestOptions {
 signal?: AbortSignal
 idempotencyKey?: string
 headers?: Record<string, string> // authenticated server client only
}

await incld.approvals.approve(approvalId, "Reviewed", {
 idempotencyKey: `approve:${approvalId}:v1`,
 signal: request.signal,
})

Retry mutations with the same key

Use one stable key for one logical create or decision. Reusing the key returns the original result instead of duplicating a Schedule, Approval, decision, Audit event, or Bulk operation.

Time and identifiers

ValueContract
Timestamps ISO-8601 strings in SDKs; parse at the presentation boundary.
Timezones IANA names such as Australia/Melbourne; never persist display abbreviations.
Action references Stable identifiers such as sync_contacts; action UUIDs are not command inputs.
Resource IDs Opaque strings. Do not infer type or ordering from their representation.
Cursor Opaque string tied to its query. Do not manufacture or reuse it with different filters.