Integration Abstraction Layer · HTTP API
The IAL exposes one uniform interface for every external action CredTek triggers — whether the underlying work is an HTTP API call, a browser agent, or a human credentialing specialist. You call integrations.submit(), you get back an IntegrationJobwith a stable ID, status, and ETA. You poll or subscribe. You don't care which tier the integration falls into.
Base URL: https://www.cred-tek.com/api. All requests and responses are JSON. Every endpoint requires an authenticated CredTek session and is tenant-scoped. The job store behind them is still in-memory pending the Supabase migration.
Authentication
Production: Authorization: Bearer <jwt> header. JWTs are issued by Supabase Auth. Every request is tenant-scoped via the JWT claims; cross-tenant access returns 404 (not 403, to avoid resource-existence leaks).
Today: a signed-in CredTek session (cookie-based) is required — unauthenticated requests return 401. A tenant_idpassed in the query string or body is ignored; the tenant is always taken from the session, so a request cannot reach another customer's jobs.
Integration tiers
Every external system CredTek interacts with falls into one of four tiers. From the API's perspective they look identical — same shape in, same shape out. The tier governs the lifecycle behavior under the hood.
- tier_1_api — direct REST/GraphQL APIs (NPPES, OIG, SAM.gov, Checkr, Twilio, Resend). Synchronous or webhook-based.
- tier_2_partner — gated APIs we access via an NCQA-certified CVO partner (CAQH ProView Credentialing API, NPDB queries).
- tier_3_browser — web portals with no API. Completed by our credentialing team on the platform. Always requires a human approval gate before submission.
- tier_4_human— work that can't be automated in v1. Creates an Operations Queue ticket with an SLA-based ETA.
Lifecycle states
An IntegrationJob moves through a deterministic state machine (IAL §4). Transitions are the only place status changes; production enforces this with a database trigger.
draftedCreated, not yet submitted. Editable by the coordinator.awaiting_approvalTier 3 only — agent has prepared submission, waiting on coordinator click.submittedSent to external system or queued for ops specialist.in_progressExternal system or specialist is actively working it.awaiting_infoBlocked, waiting on provider or coordinator to supply additional info.completedSuccessfully completed with structured result. Terminal.failedPermanent failure, manual review required. Terminal.cancelledCancelled by coordinator or admin. Terminal./api/integrations/submitCreate an IntegrationJob
Creates a new job in `drafted` state. Tier 3 jobs are auto-routed to `awaiting_approval` (human-in-the-loop gate per IAL §4). Tier 1/4 jobs can opt into immediate submission with `auto_submit: true`.
{
"tenant_id": "mindscape",
"integration_type": "optum_enrollment",
"tier": "tier_3_browser",
"provider_id": "james-mitchell",
"payload": {
"providerName": "James Mitchell",
"credential": "LCSW",
"state": "CA",
"npi": "2109834567"
},
"auto_submit": false
}{
"job": {
"id": "job_01HZX7000000041F",
"tenant_id": "mindscape",
"integration_type": "optum_enrollment",
"tier": "tier_3_browser",
"provider_id": "james-mitchell",
"status": "awaiting_approval",
"payload": { ... },
"result": null,
"eta": "2026-05-12T15:30:00.000Z",
"submitted_at": null,
"completed_at": null,
"created_by": "api_demo_user",
"cost_cents": 0,
"metadata": { "attempts": 0 },
"audit_log_id": "audit_01HZX700000000",
"created_at": "2026-04-29T15:30:00.000Z",
"updated_at": "2026-04-29T15:30:00.000Z"
}
}201 | Created |
400 | missing_fields / invalid_tier / invalid_json |
/api/integrations/listList IntegrationJobs
Returns jobs filtered by query params. Newest first.
| Name | Type | Description |
|---|---|---|
tenant_id | string | Filter by customer org |
provider_id | string | Filter by provider slug |
status | IntegrationStatus | drafted | awaiting_approval | submitted | in_progress | awaiting_info | completed | failed | cancelled |
limit | number | Max rows. Default 50, capped 200. |
{
"total": 5,
"returned": 5,
"limit": 50,
"jobs": [
{ "id": "job_01HZX700000000A5", "status": "awaiting_info", ... },
...
]
}200 | OK |
400 | invalid_status |
/api/integrations/[id]Fetch a single IntegrationJob
Returns the full job by ID.
{
"job": { "id": "job_01HZX700000000A1", "status": "drafted", ... }
}200 | OK |
404 | not_found |
/api/integrations/[id]Apply a state transition
Drives the IAL state machine (§4). Validates the transition is legal for the current state and the actor type. Optional `patch` lets you update `result`, `eta`, `cost_cents`, or merge into `metadata` in the same call.
{
"to_status": "submitted",
"actor_type": "user",
"patch": {
"metadata": { "external_reference": "OPT-2026-04-CR-99812" }
}
}{
"job": { "id": "...", "status": "submitted", "submitted_at": "2026-04-29T15:31:00.000Z", ... }
}200 | OK |
400 | missing_field / invalid_to_status / invalid_actor_type |
404 | job not found |
409 | job is in terminal state |
422 | transition_rejected (state machine refused) |
Error response shape
All errors return a structured JSON body:
{
"error": "transition_rejected",
"reason": "no rule allows submitted → drafted",
"message": "(optional human-readable hint)"
}The error field is a stable machine-readable code; the reason / message are for humans and may change copy without breaking compatibility.
Ready to wire CredTek into your stack?
The same API your engineers see here is what runs in production. Tenant isolation via Supabase RLS, audit logging via the IAL §9 hash chain, and human-in-the-loop gates on every Tier 3 submission.
Book a 20-min demo →