Skip to Content
DocsAPIPublic API Contract Pack (v1)

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.ts
    • apps/api/src/__tests__/contracts/enqueue-idempotency.contract.test.ts
    • apps/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)

  1. Send x-api-key: sk_int_... to POST /api/auth/token/integration
  2. Receive bearer token
  3. 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/upload requires ship:upload.
  • POST /api/public/billing/setup-session requires principal type integration.
  • 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:

  • amount must be a positive number.
  • confirmation object is required with:
    • source (string)
    • referenceId (string)
    • confirmedAt (ISO timestamp)
  • Optional:
    • confirmation.notes
    • confirmation.artifactUrl

Operational guardrail:

  • Batch credit is disabled:
    • POST /api/ship/findings/batch with action=credit returns 400 INVALID_REQUEST
    • response includes remediation to use the per-finding credit endpoint above

Async Job Lifecycle

Canonical JobStatus states:

  • PENDING: accepted and queued
  • PROCESSING: worker has started
  • COMPLETED: terminal success
  • FAILED: terminal failure

Polling contract:

  • Enqueue endpoints return 202 with jobId
  • Poll GET /api/jobs/:id until terminal (COMPLETED or FAILED)
  • 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/batch
  • POST /api/upload
  • POST /api/catalog/upload

Behavior:

  • first request with a key: creates a job and returns 202
  • retry with same key + same normalized payload: returns 202 and original jobId (replayed: true)
  • retry with same key + different payload: returns 409 with ACTION_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 endpoints
  • write: non-upload mutations and enqueue writes
  • upload: upload endpoints (/upload paths)

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.