Errors and Business Rules
Errors use Problem Details JSON. Every error response includes:
typetitlestatusdetail- optional
errors
Common statuses:
| Status | Meaning |
|---|---|
401 | Missing or invalid bearer token |
403 | Credential does not have the required scope |
404 | Referenced client-owned site, project, item, or resource was not found |
409 | Duplicate resource, optimistic concurrency conflict, idempotency conflict, or invalid site-asset assignment |
413 | Uploaded file is larger than the allowed limit |
422 | Request validation failed |
429 | Request rate limit exceeded |
5xx | Service or upstream failure; inspect the problem and operation before retrying |
Problem Details examples
Rate limit response:
{
"type": "https://api.ssn.local/problems/rate-limit-exceeded",
"title": "Too Many Requests",
"status": 429,
"detail": "Request rate limit exceeded. Wait for Retry-After before retrying."
}
Validation response:
{
"type": "https://api.ssn.local/problems/validation-error",
"title": "Validation Error",
"status": 422,
"detail": "Request validation failed.",
"errors": {
"siteCode": ["Required"]
}
}
Retry guidance
A timeout or 5xx response does not prove that a write failed. Check the
operation below before repeating it. Read the Problem Details type and
detail; HTTP status alone cannot distinguish a duplicate, a request still in
progress, or an uncertain result requiring SSN help.
| Operation | Protection and safe next action |
|---|---|
Resource GET requests | Retry temporary failures with bounded backoff. Inspect persistent 404 or other failures instead of retrying indefinitely. |
POST /sites, /site-visits, /messages | Send an Idempotency-Key before the first attempt. After a timeout or temporary failure, retain the same key and unchanged body; follow the create-result rules below. The header is optional in the API, but omitting it removes this protection. |
Resource PATCH requests | Send the exact latest ETag as If-Match. This is a version precheck, not an atomic lock or retry guarantee. Serialize updates to a resource and read its current state after an uncertain result before deciding whether another update is needed. |
File-upload POST requests | No idempotency-key replay protection. Each accepted upload creates a new version. After an uncertain result, inspect the resource's file metadata/latest download or ask SSN to reconcile before uploading again. |
Webhook-subscription POST and PATCH | These handlers do not use Idempotency-Key or If-Match. List subscriptions to reconcile an uncertain create or metadata change. Secrets are never returned, so an uncertain rotation/upgrade needs coordinated reconciliation; do not blindly repeat it. |
POST /oauth/token | No idempotency-key handling. A temporary failure can be retried with bounded backoff; another successful request issues another token. Cache and reuse a valid token until it needs renewal. |
Resource create results
Persist each resource create's key, body, and result in your integration. Use a different key only for a genuinely new operation. Keys are scoped to the client tenant and resource type; use stable unique keys for distinct import rows.
- A completed request returns its saved response for 24 hours after completion,
provided the resource is still accessible to your client. This response is the
original snapshot, not a fresh read. Use
GETfor current data. 409with a type ending inidempotency-conflictmeans the key was used with a different payload. Recover the original request; do not switch keys to bypass uncertainty about its outcome.409with a type ending inidempotency-pendingmeans the request is still in progress or its outcome is unresolved. If the detail says it is in progress, back off and retry the same key/body. If it requires operator reconciliation, or remains stalled, stop automatic retries and contact SSN with the original key and request details. Never use a new key to bypass a pending result.- Pending/unresolved requests remain blocked until reconciled; they do not become safe to recreate after 24 hours. Completed keys can expire after that window, so do not treat an old key as permanent duplicate protection. Reconcile an old uncertain operation before submitting it again.
- A completed replay can return
404after access changes/deletion, or an upstream failure while checking access. Preserve the original key and reconcile; these responses are not permission to create another record.
Resource updates
If-Match is optional in the current API. Supply the quoted ETag returned by
GET; do not invent a version. A detected mismatch returns 409 with a type
ending in version-conflict. Fetch the current resource, reconcile your intended
changes, and use its new ETag only if another update is necessary.
The version check and upstream update are separate operations, so simultaneous writers can pass the same check. It also does not track every direct upstream edit. Avoid concurrent updates to the same resource. Repeating an update after a lost response can repeat upstream side effects; do not assume it is harmless.
Backoff and failures
- For
429, honorRetry-Afterwhen present, reduce concurrency, and use bounded backoff with jitter. See Rate Limits and Bulk Imports. 502,503,504, and network failures may be temporary, but can also reflect persistent problems or uncertain writes. Apply the operation-specific rules above, cap retries, and investigate repeated failures. HonorRetry-Afteron maintenance responses when present.- For
401on a protected request, obtain a fresh token once if the old one expired, then follow the operation's retry rules. Repeated401, or401from the token endpoint, requires checking credentials/configuration rather than a refresh loop. For403, request the missing scope; for422, correct the request data before retrying. - For other
409problems, inspect the type/detail: duplicate identifiers and invalid references/asset assignments require reconciliation or corrected data. Do not classify every409as either retryable or a permanent data error.
Upload failures
File upload endpoints accept form field name file.
- return labels accept PDF files
- message attachments accept PDF, PNG, and JPEG files
- uploaded files must be 10 MB or smaller
- empty uploads are rejected as validation errors
Important business rules:
siteCodemust be unique per client.clientTicketNumbershould be unique per client.projectIdmust belong to the client and be active.itemNamemust belong to the client.- every
siteAssetIdassigned to a site visit must belong to that visit's site siteAssetIds: []clears assigned site assets on patch