For the complete documentation index, see llms.txt. This page is also available as Markdown.

Audit Partner Integration

Reference for auditors integrating with Sprinto's Audit Partner API — core concepts, authentication, endpoints, and sync guidance.

Sprinto's Audit Partner API lets your integration pull the audits your client has shared with you, review controls, request missing information, and keep your own systems in sync — without a human logging into Sprinto for every step.

This page is for engineers integrating against Sprinto on behalf of an auditor user. It covers the concepts you need before reading the OpenAPI spec, what your API key can and can't do, and the operational details (pagination, sync, errors) you'll hit in practice.

Core concepts

Sprinto's audit workflow is built from a small number of entities. Skim this before your first call — the field and endpoint names below all map directly onto these.

  • Auditor user — the individual auditor identity added to an audit. Your API key resolves to one auditor user, and access grants always target that specific identity. If a colleague also needs access, the client adds them as their own separate auditor user.

  • Audit — one audit engagement (e.g. "SOC 2 Type II — FY2026"). Your key only ever sees audits your auditor user has been explicitly shared on.

  • Control — the underlying compliance requirement being assessed (e.g. "MFA enforced on production access").

  • Audit Item — a control as it's being reviewed within a specific audit. This is what you actually work with day to day — one row per control under review in that audit, each carrying its own review status. auditItemPk is the ID you'll use across evidence-review and conversation calls.

  • Evidence Request — an ask, raised against a control, for the client to supply a specific piece of supporting material by a due date.

  • Evidence — the supporting material itself, of two kinds:

    • Manual evidence — a file a person on the client side uploaded.

    • Automated (system) evidence — a snapshot automatically captured by one of Sprinto's monitors (e.g. a passing/failing check result). This is what "control check evidence" refers to in the API.

  • Conversation — a message thread attached to a control (or a control's evidence request), for back-and-forth between you and the client without leaving an audit trail gap.

  • Access grant — each audit you can see is an explicit grant to your auditor user. Access is revocable at any time by the client, per audit; a revoked audit stops appearing (and returns "not found," not a permission error — see Errors) on your very next call. Revoking your last remaining audit deactivates your API key entirely — it stops authenticating, not just that audit disappearing.

Status and lifecycle

  • Audit status: SCHEDULEDEVIDENCE_COLLECTIONEVIDENCE_REVIEWDUE_FOR_AUDITAUDIT_IN_PROGRESSCOMPLETED (or ARCHIVED).

  • Audit Item (control) review status: COLLECTING_EVIDENCEINTERNAL_REVIEWREADY_FOR_REVIEWINFO_REQUESTEDACCEPTED.

    • READY_FOR_REVIEW is your queue — controls the client considers done and waiting on you.

    • INFO_REQUESTED is a control you've flagged as needing more from the client.

    • ACCEPTED is a control you've formally signed off on. Setting ACCEPTED requires a finding determination — pass evidenceReviewFindingType (e.g. NO_FINDINGS) or findings text with the status, else it's rejected as "No update required."

  • Evidence Request status: UPLOAD_PENDINGREVIEW_PENDINGREUPLOAD_PENDINGUPLOADED.

Authentication

Every request carries a per-integration API token in the api-key header — there's no Authorization: Bearer scheme:

Your token resolves to a dedicated Sprinto user scoped to the AUDITOR or INTERNAL_AUDITOR role. Every endpoint below checks that role, and separately checks that the specific audit/control/conversation you're asking about is one your key has been granted. The two checks are independent — a valid key with the right role still gets nothing back for an audit it hasn't been granted.

What you can do

Read: audits and controls

Operation
Type
What it returns

listAuditsForAuditor

Query

Every audit your key has been granted access to. Supports updatedSince for incremental sync.

getAuditForAuditor

Query

Details of one shared audit.

listAuditItemsForAuditor

Query

The controls under review within a shared audit, with an optional status filter (see the spec for the exact field) and updatedSince support.

An auditPk for an audit that exists but wasn't shared with you returns the same response as one that doesn't exist at all — see Errors.

Review controls

Operation
Type
What it does

UPDATE_EVIDENCE_REVIEW_STATUS

Action

Moves a single control to a new review status — optionally posting a conversation message in the same call, so a status change and the reason for it land together.

BULK_UPDATE_EVIDENCE_REVIEW_STATUS

Action

Moves a batch of controls to a new review status in one call (e.g. bulk-accepting everything that's clearly satisfied).

Both accept evidenceReviewStatus: "ACCEPTED" — remember, include evidenceReviewFindingType when accepting; on the bulk action, items already ACCEPTED are skipped and returned in skippedAuditItemPks.

Conversations

Operation
Type
What it does

getConversationMessages

Query

Reads a thread's message history, including attachments as ready-to-use signed URLs. Supports updatedSince.

SEND_CONVERSATION_MESSAGE

Action

Posts a message to a control's thread — starts one automatically if it doesn't exist yet.

You can only read/post on a conversation whose parent control is on an audit shared with you — not any conversation in the org.

Evidence

Operation
Type
What it returns

listManualEvidences

Query

Uploaded evidence files.

listControlCheckEvidences

Query

Automated check evidence behind passing/failing controls.

Both of these are org-wide, not scoped to just your shared audits — as long as you have at least one active grant in the org, you can read every piece of evidence in it. This matches what auditors can already see in Sprinto's own UI; it isn't a narrower or wider carve-out specific to the API. If your only audit in an org gets revoked, this access goes with it.

If you need something from the client that isn't on hand, flag the control (INFO_REQUESTED) and message them via the conversation thread — the client sees it in their normal queue.

Evidence requests

Operation
Type
What it does

CREATE_ORG_EVIDENCE_REQUEST

Action

Raises a new evidence request (title, assignee, due date) — the client sees it in their normal task queue.

Creating a request only succeeds when the client org has enabled auditor collaboration with the "can request evidence" capability for you — the same setting that governs this in Sprinto's UI. Without it, the call returns 200 with a permission error in errors[]. If that's not enabled for your engagement, flag the control (INFO_REQUESTED) and message the client via the conversation thread instead. Editing, archiving, and bulk-creating requests stay admin-only.

Incremental sync

Every list-shaped operation above accepts updatedSince — a full ISO 8601 datetime string:

Only records with updatedAt >= updatedSince come back. Record a timestamp before each sync run and pass it on the next one — a bare date like "2026-06-25" is not rejected with 400 — it's silently interpreted as midnight UTC. Always send a full ISO 8601 datetime.

On paginated endpoints (getConversationMessages), passing updatedSince switches result ordering to oldest-first instead of the newest-first default, so a row that changes mid-pagination can't slip behind your cursor and get skipped.

Pagination: first is capped at 100 server-side — ask for more and it's silently clamped, not rejected. listAuditItemsForAuditor returns a plain array, not a paginated connection.

Errors

HTTP
Shape
When

403

{ "isSuccess": false, "error": "Insufficient permissions..." }

During query, your key's role doesn't match this operation's requirements

403

{ "success": false, "error": "Insufficient area access for this action" }

During action, your key's role doesn't match this operation's requirements

401

{ "success": false, "error": "User login required!" }

No valid user resolved from your api-key

400

{ "isSuccess": false, "error": "Invalid request. Please check your query arguments." }

Covers bad arguments and an audit/item/conversation that either doesn't exist or wasn't shared with you — these look identical on purpose, so you can't probe what else is on the platform by comparing error messages

200 with a business error

{ "isSuccess": true, "data": { "errors": [...], "data": ... } }

"No update required", or a missing required field) — always check the response errors, not just the HTTP status. The evidence-review

actions return { data, errors } with no top-level success; only the request/conversation actions carry data.success.

Internal error detail (stack traces, database errors) is never included in a response — check the generic message bucket you landed in above rather than trying to pattern-match on specific wording.

Best practices

  • Use the filtered spec (?tags=audit) so your integration only builds against operations you'll actually call.

  • Check the action response body, not just the HTTP status — an action can return 200 and still have rejected your input. The evidence-review actions signal this via an empty/populated errors array (no top-level success field); the evidence-request and conversation actions carry data.success. Check errors in both cases

  • Poll with updatedSince, not full re-pulls — every list endpoint here supports it, and it's how your integration should pick up changes.

  • Keep request bodies under 500kb. This applies across every endpoint, including bulk actions like BULK_UPDATE_EVIDENCE_REVIEW_STATUS — batch large jobs into multiple calls rather than one large payload.

  • Pace your integration, especially on sync jobs. Use updatedSince to fetch only what changed instead of re-pulling everything, and space out bulk operations rather than firing large bursts of concurrent requests. Traffic that looks abusive can result in your key being revoked.

  • Implement exponential backoff on 429 (respect Retry-After).

FAQ

Can I see every audit in my client's org? No — only audits explicitly shared with your specific auditor user. If a colleague needs access, the client adds them as their own auditor user and grants it separately.

What happens if the client revokes my access mid-sync? The audit stops appearing in listAuditsForAuditor and any direct call for it returns the same "not found" response as an audit that never existed. This takes effect on your very next request — there's no caching delay. If the revoked audit was your last grant, your key is deactivated too — a sudden 401 means "all access revoked," not a transient error.

How do I flag a control that needs more information from the client? Set its evidenceReviewStatus to INFO_REQUESTED via UPDATE_EVIDENCE_REVIEW_STATUS and include a conversationMessage in the same call — the client sees both the status change and your note together, in their normal queue.

Last updated