v1 conventions
This page covers the patterns shared by every endpoint in the v1 surface. Read it once before drilling into the per-resource references.
Base URL
All v1 endpoints live under:
https://api.novantra.io/api/v1/...For Sovereign customers, the API is served from your install’s workspace URL with the same /api/v1/... path prefix. Your account team provides the exact base URL for your tenant when you provision a service account.
Every request is scoped to a single organization. The organization is identified by the credentials presented; there is no ?orgId= parameter and no way to act across organizations in a single call.
Request shape
All write endpoints accept JSON. Set Content-Type: application/json and provide a JSON body.
All endpoints accept and return JSON. Set Accept: application/json.
Response shape
Successful responses return a JSON object with a single top-level key naming the resource:
{
"control": { "id": "ctrl_01H...", ... }
}List endpoints return a top-level key naming the collection plus pagination metadata:
{
"controls": [ { ... }, { ... } ],
"pagination": {
"nextCursor": "<cursor>"
}
}When nextCursor is omitted or null, you have reached the end of the collection.
ID format
Every record has a string id with a short stable resource prefix and a ULID-style suffix. Examples:
ctrl_01H...- a controlrisk_01H...- a riskevreq_01H...- an evidence requirementevclm_01H...- an evidence claimfind_01H...- a findingexcp_01H...- an exception
The prefixes are stable across all of v1 and used by every endpoint. Treat them as opaque strings; do not parse the suffix or assume monotonic ordering from it.
The reason field on writes
Every mutation endpoint requires a reason field in the request body. The reason is free text between 10 and 1000 characters explaining why this action is being taken. It is captured into the workspace audit log alongside the action.
{
"controlKey": "supplier-due-diligence",
"title": "Supplier due-diligence requirement",
"reason": "Created from upstream GRC export 2026-Q2 batch."
}This is not optional. Requests without a reason are rejected with a validation error. Plan to construct meaningful reasons in your integration code, not placeholder strings; the reason ends up in compliance audit trails that may be reviewed by regulators.
Idempotency keys for writes
Write endpoints accept an optional Idempotency-Key header. When present, repeated requests with the same key within a retention window return the original response without re-executing the action.
POST /api/v1/governance/findings
Idempotency-Key: my-scanner-batch-2026-05-21-item-3947Use idempotency keys whenever your integration cannot guarantee at-most-once delivery (most real-world scenarios). See Errors for details on the retention window and conflict semantics.
Subject attachments
Several v1 resources (findings, evidence claims, exceptions, applicability decisions) optionally attach to another resource in your workspace through three fields:
| Field | Meaning |
|---|---|
subjectModuleKey | The module the subject lives in, for example "controls", "risks", "assets". |
subjectResourceType | The resource type within that module, for example "control", "risk", "asset". |
subjectResourceId | The ID of the specific record. |
For example, attaching a finding to a specific control:
{
"title": "Annual control review overdue",
"severity": "medium",
"subjectModuleKey": "controls",
"subjectResourceType": "control",
"subjectResourceId": "ctrl_01HXY...",
"reason": "Q1-2026 review pass surfaced this gap."
}You can omit all three for free-standing records.
Encrypted fields
Several resources include fields that are encrypted at rest in the Novantra database (descriptions, source snapshots, justifications). These are transparently decrypted in API responses for callers whose tokens have the right scopes. You do not encrypt anything yourself when writing; just send plaintext values.
Responses may include sensitive customer data. Do not log entire response bodies to systems with weaker access controls than your Novantra workspace.
Common headers
Headers used across the v1 surface:
| Header | Direction | Purpose |
|---|---|---|
Authorization: Bearer <access-token> | request | Service-account access token. See Authentication. |
Idempotency-Key | request (writes) | Make a write retry-safe. See above. |
X-Request-Id | response (always) | Unique ID for the request. Include when filing support tickets. |
X-RateLimit-Remaining | response (always) | Calls remaining in the current rate-limit window. See Rate limits. |
Retry-After | response (429, 503) | Seconds to wait before retrying. |
What’s deliberately not in v1
A short list so you don’t go hunting:
- GraphQL or aggregated queries - REST only in v1.
- Synchronous bulk operations - submit batches via repeated calls with idempotency keys or a supported import workflow.
- Personal user tokens for API calls - service accounts only. See Authentication.
- Admin-shaped operations - license, billing, key management, backup/restore, member or role mutation, cross-org administration.
- Destructive bulk writes - mass-delete or mass-archive operations.
If one of these boundaries blocks your integration, check with your account team for the supported enterprise integration path.
Next
- Authentication - get a service account and a scoped token.
- Governance reference - per-resource endpoint reference.