AI-Agent Integration Kit (v1)
Status: Active
Version: v1.2.0
Last updated: 2026-04-08
This kit is the fastest path for AI agents and integrators to reach first value on the RGL8R public API using an operator-issued integration key.
New to RGL8R? Start with the 5-Minute API Quickstart first. This kit is the agent-specific layer on top of that foundation — it covers retry/backoff, polling strategy, error envelopes, and the three canonical workflows agents ship against.
Companion docs:
- OpenAPI contract (current):
docs/api/openapi/rgl8r-public-api-v1.2.0.yaml - Public API contract pack:
docs/api/public-api-contract-v1.md - Workflow companion contracts:
- TRADE feed:
docs/api/trade-feed-contract-v1.md - SHIP finding workflow:
docs/api/ship-finding-contract-v1.md - SHIP claim submission workflow:
docs/api/ship-claim-submission-contract-v1.md
- TRADE feed:
- Channel playbooks (public):
docs/api/playbooks/ai-channel-playbooks-public-v1.md
Prerequisites
Set these env vars:
# Production-first
export BASE_URL="https://api.rgl8r.com"
# Or staging as a safe sandbox
# export BASE_URL="https://rgl8r-staging-api.onrender.com"
export RGL8R_INTEGRATION_KEY="sk_int_..."Notes:
- Your RGL8R operator issues the integration key via assisted onboarding. The secret is revealed once.
POST /api/auth/token/integrationrequires headerx-api-key.- Bearer JWTs have a short TTL (typically one hour; the value is returned as
expires_in). Do not cache them indefinitely — re-exchange on the first401 INVALID_TOKEN.
Auth flow (once, shared by all three workflows)
TOKEN_JSON=$(curl -sS -X POST "$BASE_URL/api/auth/token/integration" \
-H "x-api-key: $RGL8R_INTEGRATION_KEY")
export RGL8R_BEARER_TOKEN=$(echo "$TOKEN_JSON" | python3 -c "import sys,json;print(json.load(sys.stdin)['access_token'])")Expected success shape:
{
"access_token": "<jwt>",
"token_type": "Bearer",
"expires_in": 3600,
"default_adapter": "catalog-excel"
}Optional: bootstrap a Stripe SetupIntent for billing payment-method capture:
curl -sS -X POST "$BASE_URL/api/public/billing/setup-session" \
-H "Authorization: Bearer $RGL8R_BEARER_TOKEN" \
-H "Content-Type: application/json" \
-d '{"billingEmail":"billing@example.com"}'Pick one of three canonical workflows
| Workflow | Why pick this | Minimum endpoints touched |
|---|---|---|
| A. SIMA screening (smallest) | You already have a catalog loaded and only need trade-remedy screening | sima/batch, jobs/:id, sima/results |
| B. TRADE feed | You are onboarding a product catalog from scratch and need normalize + classify-preview + apply | trade/feeds/upload, trade/feeds/:id, trade/feeds/:id/classify-preview, trade/classify/preview/:jobId/review, trade/feeds/:id/apply |
| C. SHIP audit | You have carrier invoices to audit and want findings + dispute + claim submission | ship/upload, jobs/:id, ship/findings, ship/findings/:id/dispute, ship/claims/submissions, ship/claims/submissions/:id/generate-packet, ship/claims/submissions/:id/submit |
SIMA is the smallest workflow because it does not require file upload handling. TRADE and SHIP require multipart uploads and demonstrate the full async lifecycle.
Workflow A — SIMA screening
ENQUEUE_JSON=$(curl -sS -X POST "$BASE_URL/api/sima/batch" \
-H "Authorization: Bearer $RGL8R_BEARER_TOKEN" \
-H "Content-Type: application/json" \
-d '{"skus":null,"runPolicy":"always","screeningAuthority":"US"}')
export RGL8R_JOB_ID=$(echo "$ENQUEUE_JSON" | python3 -c "import sys,json;print(json.load(sys.stdin)['jobId'])")
# Poll every 3s for up to 40 attempts (~2 min), then fetch results
for i in $(seq 1 40); do
JOB_JSON=$(curl -sS "$BASE_URL/api/jobs/$RGL8R_JOB_ID" \
-H "Authorization: Bearer $RGL8R_BEARER_TOKEN")
STATUS=$(echo "$JOB_JSON" | python3 -c "import sys,json;print(json.load(sys.stdin)['status'])")
echo "attempt=$i status=$STATUS"
[ "$STATUS" = "COMPLETED" ] || [ "$STATUS" = "FAILED" ] && break
sleep 3
done
curl -sS "$BASE_URL/api/sima/results?limit=20" \
-H "Authorization: Bearer $RGL8R_BEARER_TOKEN"Runnable versions:
- TypeScript:
docs/api/examples/rgl8r_quickstart.ts - Python:
docs/api/examples/rgl8r_quickstart.py - Postman:
RGL8R-Agent-Quickstartcollection →SIMA Workflowfolder
Workflow B — TRADE feed (upload → normalize → review → apply)
Agent sequence:
POST /api/trade/feeds/uploadwith multipartfile(bundled fixture atdocs/api/examples/fixtures/trade-feed-sample.csv). CapturesessionId.- Poll
GET /api/trade/feeds/:sessionIduntilstatusreachesREADY,PREVIEW_BLOCKED, orFAILED. Terminal-for-this-step states areREADY(happy),PREVIEW_BLOCKED(operator handoff),FAILED(inspect issues). - If
READY:POST /api/trade/feeds/:sessionId/classify-preview. CapturejobId+previewJobId. - Poll the classify-preview job via
GET /api/jobs/:iduntilCOMPLETED. PUT /api/trade/classify/preview/:jobId/reviewwith the reviewed snapshot (rows + toggles).POST /api/trade/feeds/:sessionId/apply. On success the session transitions toAPPLIED.
If the session hits PREVIEW_BLOCKED, call GET /api/trade/feeds/:sessionId/issues, surface the issues to the customer, and instruct them to contact their RGL8R operator — non-blocking issue acknowledgement is Clerk-only and is not part of the public agent surface. Full semantics in docs/api/trade-feed-contract-v1.md.
Runnable versions:
- TypeScript:
docs/api/examples/rgl8r_trade_feed_quickstart.ts - Python:
docs/api/examples/rgl8r_trade_feed_quickstart.py - Postman:
RGL8R-Agent-Quickstartcollection →Trade Feed Workflowfolder
Workflow C — SHIP audit (upload → finding → dispute → claim)
Agent sequence:
POST /api/ship/uploadwith multipartfile(bundled fixture atdocs/api/examples/fixtures/ship-invoice-sample.csv). CapturejobId.- Poll
GET /api/jobs/:iduntilCOMPLETED. GET /api/ship/findings?limit=20to list findings. Pick the ones to dispute.- For each disputed finding:
POST /api/ship/findings/:findingId/dispute. The finding transitionsOPEN → DISPUTED. - Bundle disputed findings:
POST /api/ship/claims/submissionswith{ carrier, findingIds, notes? }. Submission is created inDRAFT. POST /api/ship/claims/submissions/:submissionId/generate-packet→READY.POST /api/ship/claims/submissions/:submissionId/submit→SUBMITTED.- When carrier confirms receipt:
POST /api/ship/claims/submissions/:submissionId/acknowledge→ACKNOWLEDGED. - When carrier credits:
POST /api/ship/claims/submissions/:submissionId/confirm-credit→CREDIT_CONFIRMED, then record billing-critical per-finding credits viaPOST /api/ship/findings/:findingId/credit.
Full finding state machine in docs/api/ship-finding-contract-v1.md; full claim submission state machine in docs/api/ship-claim-submission-contract-v1.md.
Runnable versions:
- TypeScript:
docs/api/examples/rgl8r_ship_quickstart.ts - Python:
docs/api/examples/rgl8r_ship_quickstart.py - Postman:
RGL8R-Agent-Quickstartcollection →SHIP Workflowfolder
Retry + backoff contract
Recommended policy, used by all three workflows:
- Token exchange: retry up to 3 times on
429/5xxusing exponential backoff with jitter (1s,2s,4sbase). - Enqueue / workflow writes: retry once on
5xx; never blind-retry4xx. On429, honourdetails.retryAfterSeconds. - Polling (jobs and trade feed sessions): every 2-3s in the first minute, then every 5-10s with jitter.
- Terminal job states:
COMPLETED,FAILED. - Terminal feed session states:
READY(then apply),PREVIEW_BLOCKED(handoff),APPLIED(final),FAILED. - 401 INVALID_TOKEN mid-flow: re-exchange the token using the integration key and retry the current request once.
Expected terminal response shapes
GET /api/jobs/:id success
{
"id": "<uuid>",
"type": "sima_validation",
"status": "COMPLETED",
"progress": 100,
"result": {},
"reconciliation": {},
"skippedRows": {},
"warnings": null,
"outcomes": {
"atRisk": 0,
"cleared": 0,
"needsReview": 0,
"falsePositive": 0
},
"error": null,
"createdAt": "2026-04-08T00:00:00.000Z",
"updatedAt": "2026-04-08T00:00:00.000Z"
}Canonical error envelope
{
"code": "INVALID_REQUEST",
"message": "...",
"details": {}
}Troubleshooting
| Symptom | Likely cause | Action |
|---|---|---|
401 INVALID_API_KEY on token exchange | bad key | ask the operator to rotate / reissue the key |
401 INVALID_TOKEN on tenant endpoints | bearer expired / invalid | re-run token exchange and retry the request |
403 SCOPE_DENIED | missing scope (e.g. carrier upload) | ask the operator to reissue the key with required scopes |
400 INVALID_REQUEST on SIMA batch | malformed screeningAuthority or payload | validate against OpenAPI v1.2.0 |
409 ACTION_NOT_ALLOWED on trade/feeds/:id/apply | stale reviewed snapshot | re-run classify-preview + review then retry apply |
409 ACTION_NOT_ALLOWED on ship finding transition | source state does not allow the action | re-read the finding; see docs/api/ship-finding-contract-v1.md |
Trade feed stuck in PREVIEW_BLOCKED | non-blocking issues need operator acknowledgement | contact operator; do not retry without resolution |
400 INVALID_REQUEST on ship/findings/batch with action=credit | batch credit is disabled | use per-finding credit endpoint |
| polling never reaches terminal | worker backlog or failure loop | inspect /api/jobs/:id error and session status |
Postman quickstart
- Collection:
docs/postman/RGL8R-Agent-Quickstart.postman_collection.json - Environment:
docs/postman/RGL8R-Agent-Quickstart.postman_environment.json
Collection variables (cached on the collection, not the environment):
bearer_token— set automatically by the first request of each workflow folder.session_id,preview_job_id,finding_id,claim_submission_id— captured by test scripts as you run through a folder.
Environment variables you must set:
base_urlintegration_keytrade_feed_file_path(absolute local path; required for the Trade Feed folder)ship_invoice_file_path(absolute local path; required for the SHIP folder)
See the quickstart for the Postman file-path callout — relative paths do not work in Postman because the app’s working directory is not the collection’s directory.
Dry-run evidence tracker
- Public validation summary:
docs/api/playbooks/ai-channel-validation-summary-v1.md - The API/agent-first launch polish dry-run evidence will be filed at
docs/operations/api-launch-polish-dryrun.mdunder the companion ops PR.