API Documentation

Read your AI system registry — systems, models, model versions, evaluation results, reviews and approvals, metrics, model and system cards, and AI risks — and feed it from your ML pipelines: propose systems, register model versions, record evaluation results and report metrics.

Overview

The Backsplice API gives programmatic access to your organization's AI system registry (AI systems, models, model versions, evaluation results, reviews and approvals, metrics, model and system cards, and the AI risk register), and to the governance program around it: assessments, findings, remediation, evidence metadata, vendors, incidents, policies, training, the audit log and the program score. All requests must be made over HTTPS.

Base URL https://backsplice.ai/api/v1/
Availability The REST API is included on Premium and Enterprise. It is not part of the 30-day demo, and a key from an organization that is not on a plan returns 403.
Format JSON (Content-Type: application/json)
Authentication Authorization: Bearer <api_key>
Rate limit 100 requests per minute per API key. Exceeding the limit returns 429 Too Many Requests.

Authentication

All API requests require a Bearer token. To create an API key, go to Settings → API Keys in your dashboard and click Generate new key. Store the key securely - it will only be shown once.

Include the key in every request using the Authorization header:

Authorization: Bearer bsk_••••••••••••••••••••••••••••••••••••••••••••••••

A key is bsk_ followed by 48 hexadecimal characters. Keys created before September 2026 begin ohk_ and keep working.

Scopes

Each API key is issued with one or more scopes that control which resources it can access.

Scope Access granted
findings:read Read findings
findings:write Create & update findings (write)
assessments:read Read assessments
assessments:write Create & update assessments (write)
remediation:read Read remediation tasks
remediation:write Create & update remediation tasks (write)
evidence:read Read evidence metadata
evidence:write Update evidence metadata (write)
vendors:read Read vendors & agreements
vendors:write Create & update vendors & agreements (write)
incidents:read Read incidents
incidents:write Create incidents (write)
policies:read Read policies
audit:read Read the audit log
compliance:read Read the compliance score & posture
risk_register:read Read the risk register
risk_register:write Create risks in the risk register (write)
ai_systems:read Read the AI system registry
ai_systems:write Propose AI systems (write)
models:read Read AI models, versions and evaluation results
models:write Register model versions (write)
evaluations:write Record model evaluation results (write)
cards:read Read published model and system cards
approvals:read Read AI system reviews and signed decisions
monitoring:read Read AI system monitoring metrics
monitoring:write Report AI system monitoring metrics (write)
training:read Read the training roster & assignment report
training:write Manage the training employee roster (write)
webhooks:read List webhook endpoints
webhooks:write Manage webhook endpoints (write)

Endpoints

GET /api/v1/findings.php

Returns a list of findings for your organization.

Required scope: findings:read

Query parameters

ParameterTypeDescription
statusstringFilter by status: open, in_progress, resolved, accepted_risk, false_positive, or all_open for every finding still open (open and in_progress, the set the dashboard's Open Findings figure counts). open alone is the literal status.
risk_levelstringFilter by risk: critical, high, medium, low, informational
GET /api/v1/assessments.php

Returns a list of assessments for your organization.

Required scope: assessments:read

Query parameters

ParameterTypeDescription
statusstringFilter by status: draft, in_progress, review, completed, archived. An unrecognized value returns 400.
limitintegerPage size, clamped to 1–100. Default 100.
offsetintegerRows to skip. Default 0.
GET /api/v1/remediation.php

Returns a list of remediation tasks linked to your organization's findings.

Required scope: remediation:read

Query parameters

ParameterTypeDescription
statusstringFilter by status: open, in_progress, completed, deferred
prioritystringFilter by priority: critical, high, medium, low
GET PATCH /api/v1/evidence.php

Read and update evidence metadata (filename, type, size, description, review/expiry dates, version). File contents are never served or writable via the API.

  • GET — list evidence metadata (evidence:read).
  • PATCH — update metadata by id (evidence:write). Writable: description, review_date, expires_at only.

Query parameters (GET)

ParameterTypeDescription
limitintPage size, 1–100 (default 100)
offsetintRow offset for pagination
GET POST PATCH /api/v1/vendors.php

Read and manage vendors, including the AI each supplies (ai_involvement), whether it trains on your data (customer_data_training), agreement status (has_agreement, agreement_signed_at, agreement_expires_at) and review dates. Pass ?id= to GET a single vendor.

  • GET — list or fetch vendors (vendors:read).
  • POST — create a vendor (vendors:write). Body: name (required), plus optional contact_name, contact_email, website, services_provided, data_access, risk_level, status, has_agreement, agreement_signed_at, agreement_expires_at, ai_involvement, customer_data_training, next_review_date, notes. Returns HTTP 201.
  • PATCH — update a vendor by id (vendors:write).

Query parameters (GET)

ParameterTypeDescription
idstringReturn a single vendor by id
statusstringFilter by status: active, under_review, terminated
risk_levelstringFilter by risk: low, medium, high, critical
ai_involvementstringFilter by the AI the vendor supplies: none, embedded, ai_product, model_provider
customer_data_trainingstringFilter by whether the vendor trains on your data: unknown, no, opt_out, yes
An unrecognized filter value is refused with HTTP 400, naming the allowed values.
GET POST /api/v1/ai-systems.php

The AI system registry. GET lists systems (filters stage, risk_tier, generative, q) or fetches one with ?id=, adding its intended use, oversight design and models (ai_systems:read). POST proposes a system (ai_systems:write): it is created in proposed, unclassified, and counts toward your system cap. The API never decides: a request carrying risk_tier, eu_ai_act_class, is_gpai, lifecycle_stage or next_review_date is refused. A person sets those on the system's page, and the lifecycle moves only through a review.

Filters take the listed values only; any other value is refused with HTTP 400, naming the allowed values.

GET /api/v1/models.php

AI models (models:read). ?id= returns one model with its recorded versions, the systems it backs and how many evaluation results exist.

POST /api/v1/model-versions.php

Register a new version of a model from a CI or ML pipeline (models:write). Body: model_id, version (required), optional released_on, evaluation_summary, notes. It changes no system's approval; a system that pins a version keeps its pin.

GET POST /api/v1/evaluations.php

Model evaluation results, one metric per result. GET ?model_id= (optional version_id) lists them newest first, paged with limit (at most 200) and offset (models:read). POST records one (evaluations:write, not granted by default): model_id, version_id, metric, value, optional threshold, passed, dataset, notes, measured_at. Results are append-only, and passed is recorded as sent, never worked out from the threshold.

GET /api/v1/model-cards.php

Published model and system card versions (cards:read). Pass version_id, or system_id / model_id for that subject's latest published card with its content. Drafts are never returned.

GET /api/v1/approvals.php

AI system reviews and the decisions approvers signed (approvals:read). Filter by system_id or status; ?id= returns one review with its approvers and decisions. Read-only: a decision is signed in the dashboard with a password and a second factor, never through a key.

Filters take the listed values only; any other value is refused with HTTP 400, naming the allowed values.

GET POST /api/v1/risks.php

The AI risk register. GET lists risks (filters status, category, treatment, ai_system_id) or fetches one with its treating controls (risk_register:read). POST creates a risk (risk_register:write, org admins only) under the same rules as the form: the trustworthy characteristic is required, a NIST AI 600-1 category needs a generative system or model, and the residual pair is both or neither. Unrated residual values are null, never zero.

Filters take the listed values only; any other value is refused with HTTP 400, naming the allowed values.

GET POST PATCH DELETE /api/v1/training-employees.php

Manage the delivered-training employee roster — built for HR-system sync. Employees are keyed by email (unique per organization), so re-posting a person updates them and never duplicates. Course assignment and invite emails stay in the dashboard.

  • GET — list the roster, ?id= for one employee, ?active=1 for active only (training:read).
  • POST — upsert by email (training:write). Body: full_name (required), email (required), optional department and ai_roles, a list drawn from builder, reviewer (approvers) and executive (leadership); everyone takes AI literacy and each role adds its own course. Returns HTTP 201 when created, 200 when an existing email was updated.
  • PATCH — update by id: full_name, department, is_active (training:write). Deactivation excludes the employee from bulk assignment while preserving history.
  • DELETE — remove by ?id= (training:write). Employees with completed training cannot be deleted (HTTP 409) — completions are compliance evidence; deactivate instead.
GET /api/v1/training-assignments.php

Read-only delivered-training report (training:read): every assignment with its effective status (expired once a pass is older than the 12-month validity window), score, attempts, duration, valid-through date, reminder count, invite-failure flag, and certificate id, plus an org-level stats block. Filters: course_key, status, employee_id; paginate with limit/offset. Assigning, resending, and revoking are dashboard-only actions (they send email).

GET /api/v1/training-transcript.php

The complete merged training transcript (training:read) — both delivered employee training and legacy manually-logged completions, the same dataset as the dashboard transcript export. One call gives an auditor or HR system the organization's full training record. Filters: q (person name/email), source (delivered|logged), status; paginate with limit (max 200) / offset. Every pull is recorded in the audit log.

GET POST PATCH DELETE /api/v1/webhooks.php

Manage your organization's outbound webhook endpoints.

  • GET — list endpoints (webhooks:read). Append ?catalog=1 for the list of subscribable event names. Signing secrets are never returned on read.
  • POST — create an endpoint (webhooks:write). Body: url, events (array), optional description. The signing secret is returned once in the response.
  • PATCH — update url / events / description / is_active by id (webhooks:write).
  • DELETE — remove an endpoint by id (webhooks:write).

Webhook URLs are validated against an SSRF guard. Use the X-HTTP-Method-Override header if your client can't send PATCH/DELETE.

GET /api/v1/incidents.php

Returns AI incidents for your organization: type, severity, the AI system and model involved, whether personal data was involved, people affected (null when not yet known), and whether the incident is serious and when an authority was notified. Pass ?id= for a single incident. POST creates one (incidents:write) with title, discovery_date and optional incident_type, severity, ai_system_id, ai_model_id, description, personal_data_involved, people_affected, serious_incident. A new incident starts open; move it on in the dashboard once it has been triaged.

Required scope: incidents:read

Query parameters

ParameterTypeDescription
idstringReturn a single incident by id
statusstringFilter: open, under_review, resolved, reported
incident_typestringFilter: harmful_output, inaccurate_output, biased_outcome, performance_degradation, misuse_or_attack, data_exposure, safety_harm, rights_impact, unapproved_use, outage, other
severitystringFilter: low, medium, high, critical
ai_system_idstringFilter to incidents involving one AI system
personal_data_involvedbooleanFilter to incidents where personal data was involved
serious_incidentbooleanFilter to incidents your organization marked serious
GET /api/v1/policies.php

Returns policies with status, version, owner, and review dates. Pass ?id= for a single policy.

Required scope: policies:read

Query parameters

ParameterTypeDescription
idstringReturn a single policy by id
statusstringFilter: draft, active, under_review, retired
policy_typestringFilter by type (e.g. governance, acceptable_use, transparency)
overdue_reviewbooleanOnly policies past their review date
GET /api/v1/audit-log.php

Returns your organization's tamper-evident audit log, newest first — the same event stream that drives webhooks and SIEM export. Ideal for pulling activity into your own SIEM/GRC tooling.

Required scope: audit:read

Query parameters

ParameterTypeDescription
eventstringPrefix match on the event name (e.g. incident matches incident.created, incident.closed)
event_exactstringMatch one full event name exactly
entity_typestringFilter by entity type (e.g. finding, policy)
from / tostringBound created_at (inclusive), YYYY-MM-DD or YYYY-MM-DD HH:MM[:SS]; a date alone as to includes that whole day. Anything else, including a relative date such as yesterday, returns 400.
GET /api/v1/compliance-score.php

Returns your organization's current compliance score (0–100), letter grade, and the per-dimension breakdown (Findings, Policies & Docs, Training, Incident Response), plus the date of the last daily snapshot.

Required scope: compliance:read

Write operations

Each requires the matching *:write scope. Send a JSON body; use the X-HTTP-Method-Override header for PATCH if your client can't send it directly.

  • PATCH /api/v1/findings.php — update a finding by id. Editable: status (open, in_progress, resolved, accepted_risk, false_positive), risk_level, title, notes, description, category, recommendation, due_date.
  • POST /api/v1/remediation.php — create a task. Body: title (required), description, status (not completed), priority, assigned_to (the email of an active member of your organization; invite anyone else from the dashboard), due_date (YYYY-MM-DD), finding_id. Returns HTTP 201 with the created task.
  • PATCH /api/v1/remediation.php — update a task by id. Editable: title, description, status, priority, assigned_to, due_date. Completing a task that needs approval (or an AI approval condition) sends it to the approvers instead, answering pending_approval: true; the other fields are still saved.
  • PATCH /api/v1/assessments.php — update an assessment's name, status, or due_date by id. Changing the status needs an organization admin's key, as in the dashboard: in_progress, review, completed or archived (never draft). Completing does what Mark Complete does, raising the findings and recording the score. An archived assessment cannot be changed, and a completed one cannot be renamed.
  • POST / PATCH /api/v1/vendors.php — create (201) or update a vendor by id (vendors:write).
  • PATCH /api/v1/evidence.php — update evidence metadata (description, review_date, expires_at) by id (evidence:write).
  • POST / PATCH / DELETE /api/v1/training-employees.php — upsert (by email), update, or remove training-roster employees (training:write); employees with completions can only be deactivated. POST accepts auto_assign: true to also assign every due built-in course and email the invites (HR-sync onboarding in one call).

Response format

List (GET) responses return HTTP 200 with a data array, the count in this page, and the limit / offset used. Findings and remediation also include a total (the full match count); assessments omit total. A successful create (POST /api/v1/remediation.php) returns HTTP 201 with the created record.

{
  "data": [
    { "id": "abc123", "title": "...", "status": "open", ... }
  ],
  "count": 1,
  "total": 1,
  "limit": 100,
  "offset": 0
}

Paginate with ?limit= (1–100, default 100) and ?offset=.

Error responses

Errors return a non-2xx HTTP status with a JSON body carrying a single error key:

{
  "error": "Invalid or expired API key."
}
HTTP statusMeaning
400Malformed request — an unrecognized filter value, or invalid JSON in the body
401Missing or invalid API key
403Valid key, but insufficient scope, insufficient role, a disabled org module, or no accepted Data Processing Agreement
404No such record, or it belongs to another organization
405Method not supported on this endpoint
409Conflicts with the current state of the record
415Request body was not application/json
422Well-formed request that fails a validation rule
429Rate limit exceeded. See the Retry-After and X-RateLimit-* headers
500Internal server error

Rate limit headers

Every response carries the current window state, so a client can back off before it is throttled rather than after:

HeaderMeaning
X-RateLimit-LimitRequests permitted in the current window
X-RateLimit-RemainingRequests left in it
X-RateLimit-ResetUnix timestamp when the window resets
Retry-AfterSeconds to wait. Sent with a 429.

Example

Fetch all open critical findings using curl:

curl -s \
  -H "Authorization: Bearer bsk_••••••••••••••••••••••••••••••••••••••••••••••••" \
  -H "Accept: application/json" \
  "https://backsplice.ai/api/v1/findings.php?status=open&risk_level=critical"

Example response:

{
  "data": [
    {
      "id": "fnd_01j9kx4",
      "title": "No documented human oversight for an automated decision system",
      "risk_level": "critical",
      "status": "open",
      "created_at": "2026-01-15T09:32:00Z"
    }
  ],
  "count": 1
}