Public API Contract Pack (v1)
Status: Active
Version: v1.1.0
Last updated: 2026-03-03
Artifacts
- OpenAPI:
docs/api/openapi/rgl8r-public-api-v1.1.0.yaml - Agent integration kit:
docs/api/agent-integration-kit-v1.md - Contract tests:
apps/api/src/__tests__/contracts/api-contracts.test.tsapps/api/src/__tests__/contracts/enqueue-idempotency.contract.test.tsapps/api/src/__tests__/integration-auth.test.ts
Scope
This pack defines the public machine contract for integration-key clients and AI agents across:
- token exchange (
POST /api/auth/token/integration) - billing setup bootstrap (
POST /api/public/billing/setup-session) - async job polling (
GET /api/jobs,GET /api/jobs/:id) - SIMA screening queue + reporting (
/api/sima/*) - upload enqueue endpoints (
/api/upload,/api/catalog/upload,/api/ship/upload,/api/orders/upload,/api/carrier/agreements/upload)
Authentication Modes
Integration-key flow (public default)
- Send
x-api-key: sk_int_...toPOST /api/auth/token/integration - Receive bearer token
- Call tenant endpoints with
Authorization: Bearer <token>
Legacy API-key fallback (compatibility only)
- Header pair:
x-api-key+x-org-id - Controlled by
ALLOW_API_KEY_FALLBACK - For public launch, keep fallback disabled (
false) unless explicitly required for a migration window.
Required Scopes
Integration JWT claims carry scopes (req.permissions).
- Most tenant endpoints in this v1 pack currently do not enforce per-route scope checks.
POST /api/carrier/agreements/uploadrequiresship:upload.POST /api/public/billing/setup-sessionrequires principal typeintegration.- Admin endpoints are out of scope for this public pack.
Billing Setup Session Contract
Endpoint:
POST /api/public/billing/setup-session
Auth and tenant rules:
- requires integration bearer token (no unauthenticated access)
- tenant must be active
Request shape:
{
"billingEmail": "billing@example.com"
}billingEmail is optional.
Success response (201):
{
"tenantId": "00000000-0000-0000-0000-000000000001",
"setupIntentId": "seti_...",
"clientSecret": "seti_..._secret_...",
"stripeCustomerId": "cus_..."
}SHIP Credit Confirmation Contract (Billing-Critical)
Endpoint:
POST /api/ship/findings/:findingId/credit
Note:
- This billing-critical write contract is documented here as normative launch behavior.
- OpenAPI route-level coverage for SHIP workflow endpoints can be expanded in the next public spec revision.
Request requirements:
amountmust be a positive number.confirmationobject is required with:source(string)referenceId(string)confirmedAt(ISO timestamp)
- Optional:
confirmation.notesconfirmation.artifactUrl
Operational guardrail:
- Batch credit is disabled:
POST /api/ship/findings/batchwithaction=creditreturns400 INVALID_REQUEST- response includes remediation to use the per-finding credit endpoint above
Async Job Lifecycle
Canonical JobStatus states:
PENDING: accepted and queuedPROCESSING: worker has startedCOMPLETED: terminal successFAILED: terminal failure
Polling contract:
- Enqueue endpoints return
202withjobId - Poll
GET /api/jobs/:iduntil terminal (COMPLETEDorFAILED) - Recommended polling backoff:
- first minute: every 2-3s
- after first minute: every 5-10s with jitter
Enqueue Idempotency
The enqueue endpoints support optional idempotent replay via Idempotency-Key header:
POST /api/sima/batchPOST /api/uploadPOST /api/catalog/upload
Behavior:
- first request with a key: creates a job and returns
202 - retry with same key + same normalized payload: returns
202and originaljobId(replayed: true) - retry with same key + different payload: returns
409withACTION_NOT_ALLOWED
The idempotency scope is tenant + endpoint + key, with server-side expiry.
Canonical Error Taxonomy (v1)
These are the canonical public error codes to treat as stable:
INVALID_TOKEN(401)SCOPE_DENIED(403)INVALID_REQUEST(400)RATE_LIMITED(429)INTERNAL_ERROR(500)
Common auth-adjacent codes also used by public endpoints:
MISSING_API_KEY(400)INVALID_API_KEY(401)REVOKED_API_KEY(401)EXPIRED_API_KEY(401)
Standard envelope:
{
"code": "INVALID_REQUEST",
"message": "Invalid request payload",
"details": {
"field": "screeningAuthority"
}
}For throttled requests (429 RATE_LIMITED), details includes retry metadata:
{
"code": "RATE_LIMITED",
"message": "Rate limit exceeded",
"details": {
"bucket": "read",
"limit": 240,
"windowMs": 60000,
"retryAfterSeconds": 12,
"keyId": "ik_xxx"
}
}Quotas and Guardrails
Integration-key traffic is rate limited by endpoint family:
read: GET/HEAD/OPTIONS tenant endpointswrite: non-upload mutations and enqueue writesupload: upload endpoints (/uploadpaths)
Upload/queue guardrails:
- File size/type validation on upload endpoints
- Tenant queue-admission caps for in-flight jobs (
PENDING+PROCESSING)- total in-flight jobs
- upload-family in-flight jobs
- SIMA in-flight jobs
When queue admission caps are reached, enqueue endpoints fail with 429 RATE_LIMITED and retry metadata.
Compatibility Policy
Public API compatibility policy for v1:
- Additive changes only by default:
- adding optional request fields
- adding response fields
- adding new endpoints
- Breaking changes require a version bump (new API versioned artifact) and migration notes.
- Removals/renames require a minimum 90-day deprecation window.
- Deprecated fields/endpoints must include:
- replacement target
- cutoff date
- migration guidance
Change Management
Release-note changes to this contract must use:
docs/runbooks/api-release-notes-template.md
The release note must explicitly fill the API breaking-change guard section before merge.