# Conventions and limits

Source: https://convergingthought.com/docs/api-reference/conventions

> Headers, request IDs, idempotency, pagination, time, and input limits.



Use HTTPS and JSON with the production origin `https://convergingthought.com`. Endpoint paths begin with `/v1`. Request field names and identifiers are case-sensitive. Unknown fields in model request bodies are rejected rather than silently treated as provider options.

## Headers and receipts [#headers-and-receipts]

```http
Authorization: Bearer YOUR_PROJECT_KEY
Content-Type: application/json
Idempotency-Key: 4e4b8ce2-6309-49fb-8abe-76097b50717b
```

The idempotency header is required for inference and internalization. It is not required for reads or manual activation. Public JSON responses include `X-Request-Id` and use `Cache-Control: no-store`. The HTTP request ID identifies a single transport attempt; the job ID identifies durable work across attempts. Save both when debugging.

Accepted model operations return `{ id, status_url }`, with the same relative URL in the `Location` header. Resolve that URL against the platform origin. A list response uses `data`, while an individual job is returned directly; there is no universal `data` wrapper around every endpoint.

## Idempotency [#idempotency]

Keys contain 8–128 characters, begin with a letter or number, and otherwise allow letters, numbers, dots, underscores, colons, and hyphens. A UUID is suitable. Generate the key once per intended operation and store it before sending the request.

Idempotency keys are scoped to a project and tenant namespace, and shared across the two model-operation types within that namespace. Omitted tenant and an explicit matching tenant on a tenant-restricted key resolve to the same identity. Keep the original tenant and submitting API key for retries. Reusing a key for an inference after using it for an internalization is a conflict. Reusing it with changed content, subject, temperature, output limit, or activation choice is also a conflict.

The server compares the validated payload, including applied defaults. Keep the original payload in your application rather than relying on incidental serialization differences. An identical replay recovers the existing job without another reservation. There is no documented short expiration window after which you should deliberately reuse a key for unrelated work.

## Input limits [#input-limits]

| Item                  | Limit                                                             |
| --------------------- | ----------------------------------------------------------------- |
| JSON request body     | 100,000 bytes at the public body reader                           |
| Subject ID            | 1–128 allowed characters                                          |
| Learning content      | 20–16,000 string-length units                                     |
| Inference messages    | 1–64 messages                                                     |
| Each message content  | 1–16,000 string-length units                                      |
| Total message content | Serialized messages and tools: at most 64,000 string-length units |
| Output ceiling        | 1–4,096 tokens, including reasoning                               |
| Temperature           | 0–1 inclusive                                                     |
| Job list page         | 1–100 records; default 50                                         |

Text validation uses JavaScript string length at the public boundary, so some Unicode symbols occupy two units. Token limits and byte limits are different measurements. Leave room below the text cap when constructing multilingual payloads.

## Rate limits and retries [#rate-limits-and-retries]

New model admissions share a project-level limit of 60 per minute. The two operation types use the same fixed minute window. An identical accepted replay is resolved before the new-admission limiter. `429 rate_limited` includes `Retry-After: 60`.

Back off on rate limits and transient transport failures. For a model write, preserve the original key and payload. An HTTP `retryable` flag is advice about the request error, not permission to generate a new paid operation. For a job in reconciliation, stop automatic resubmission and inspect the original job.

## Pagination and time [#pagination-and-time]

Jobs are listed newest first. Pass `next_cursor` back unchanged as `cursor`, with the same endpoint. A `null` cursor means the end. Cursors are opaque; do not construct offsets or parse their contents. The subjects endpoint is a bounded listing rather than a paginated collection.

Public job and subject timestamps use ISO 8601 UTC strings. Billing calendar months and daily usage use UTC. The optional candidate expiry inside a job result may be a Unix timestamp in seconds; the subject listing's `expires_at` is an ISO timestamp. Parse fields according to their documented resource shape.
