Connector API
Build customer integrations with scoped connections, resource mappings, external context, and signed event delivery.
The Connector API lets your applications read approved Solarius context, publish external service records, and receive events across connected products. Each request stays within the service account's role, bindings, key scopes, and active connection grants.
Choose an integration workflow
Start with a task, then use the corresponding resource reference:
| Goal | Task | Reference |
|---|---|---|
| Connect a customer application | Register a custom integration | Custom integration API |
| Approve information exchange | Add a project to a connection | Connection API and Grant API |
| Build a service catalog | Synchronize a service catalog | Resource API and Mapping API |
| Add deployment or ticket context | Publish external context | External record API |
| Receive changes | Receive Connector events | Subscription API and Event API |
| Recover interrupted delivery | Replay a failed delivery | Delivery API and Operation API |
Download the OpenAPI 3.1 contract as a JSON file to import the endpoints and schemas into your API tooling. The example server origin in the contract is a placeholder.
Base URL and authentication
In Console, open Organization → Connector → Developer settings → API endpoint.
Use that origin followed by /api/v1/connector. A self-hosted deployment uses
its configured API origin. Endpoint cards include the complete path after the origin.
Send Authorization: Bearer CONNECTOR_API_KEY and Accept: application/json.
JSON requests also require Content-Type: application/json. Replace
CONNECTOR_API_KEY with a Connector service-account key.
Infra keys, Guard keys, browser sessions, and webhook secrets are not Connector API keys.
Native resource mutations use their product APIs. Reading an Infra resource through Connector does not authorize restarting it. Publishing an external ticket does not close a Guard finding.
Response envelopes
Single-resource responses contain data and request_id. Collections contain
a data array, pagination.next_cursor, and request_id. A null cursor ends
the collection; an empty page with a non-null cursor does not.
Asynchronous changes return 202 with operation.id. Follow
Read an operation until a terminal result.
reconciling means the result remains unknown; preserve the original operation
reference instead of issuing a replacement change.
Resource schemas are defined in API data types. API states use lowercase identifiers; Console presents labels such as Connected.
Pagination and snapshots
Collection reads accept limit from 1 to 200, inclusive, with a default of 50.
cursor is opaque and binds the original filters and authorization. Unknown
filters or invalid limits return 422; a cursor for another selection is rejected.
Shared-resource pagination fixes a consistent snapshot. Every page returns the
same snapshot_id and grant_revision. Its cursor expires after 600 seconds.
A grant change rejects continuation with 409 scope_changed. Publish your local
catalog only after the final page; restart the entire read after expiry or scope change.
Revisions and conditional writes
Protected mutations require If-Match with the ETag from a current resource
read. Missing preconditions return 428; stale preconditions return 412.
Re-read the resource and review the concurrent change before submitting an update.
External record creation uses If-None-Match: *. Replacement and deletion use
If-Match with the record ETag. PUT replaces the record summary; PATCH preserves
omitted fields. Null is rejected unless the schema explicitly permits it.
Idempotency and retries
POST and PUT require an Idempotency-Key of 1 to 128 characters. Connector
retains the key for 24 hours within the organization. The key binds the method,
path, and canonical request content. Reusing it for different work returns
409 idempotency_conflict.
After a timeout, retry the same request with the same key and body. A retry rechecks current authorization. Preserve the original conditional headers. A completed matching request returns its stored result before evaluating the revision precondition again. Successful retries identify the original result; they do not repeat one-time signing secrets. If a creation response containing a secret is lost, rotate that secret rather than expecting to retrieve it.
After the retention window, read the resource or operation before choosing a
replacement key. Retry 429 after the whole seconds in Retry-After. For a
transport error or 5xx, use bounded exponential backoff with jitter and retain
the request identity. Validation and permission failures require correction.
Validation and errors
Requests reject unknown fields and invalid types. Request bodies cannot exceed 1 MiB. Timestamps use RFC 3339 UTC, durations use seconds, and IDs are opaque.
The following errors share an error object and request_id:
| Status | Condition | Recovery |
|---|---|---|
401 | Missing, expired, revoked, or wrong-audience key | Replace the Connector key |
403 | Missing role, scope, binding, or product approval | Review effective access and active grants |
404 | Missing or inaccessible resource | Check its ID and organization scope |
409 | Conflicting state, dependency, approval, or retry identity | Read the resource and the operation-specific code |
410 | Expired cursor or journal event | Restart the snapshot or refresh present state |
412 | Stale ETag or failed creation precondition | Read the current resource before writing |
413 | Request body exceeds 1 MiB | Reduce the payload |
422 | Invalid selection, field, type, or value | Correct the named input |
428 | Missing revision precondition | Supply the required conditional header |
429 | Request allowance exhausted | Wait for Retry-After seconds |
A rejected request returns an envelope similar to the following:
{
"error": {
"code": "scope_changed",
"message": "The active grant changed. Restart the resource snapshot."
},
"request_id": "req_catalog_01"
}Use request_id when collecting a support record. Rate allowances come from
the deployment's configured policy; the API does not define one universal
requests-per-second rate.