Select base URL
When running locally, API is on the same origin as the interface. Production should be placed behind a TLS reverse proxy.
export JSONAPI_URL="http://localhost:8080"
Authenticate with JWT or API key
Use JWT for user sessions. Use API key with minimum scope for service and automation.
API secret key is only displayed once. Do not include tokens in URL, logs or source control.
curl -X POST "$JSONAPI_URL/api/v1/keys" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "release-service",
"scope": "FULL"
}'
Create resources
A resource accepts any valid JSON object. The private property controls public read access.
curl -X POST "$JSONAPI_URL/api/v1/resources" \
-H "X-API-Key: $JSONAPI_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "release-config",
"private": true,
"data": {
"region": "ap-southeast-1",
"features": ["audit", "webhook"]
}
}'
Keep the id and version from the response. The version prevents concurrent changes from being overwritten.
Read and update controlled
Projection reduces payload when only a few fields are needed. Update requires current version.
curl "$JSONAPI_URL/api/v1/resources/$RESOURCE_ID?fields=id,name,data,version" \
-H "X-API-Key: $JSONAPI_KEY"
curl -X PUT "$JSONAPI_URL/api/v1/resources/$RESOURCE_ID" \
-H "X-API-Key: $JSONAPI_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "release-config",
"private": true,
"version": 0,
"data": {"ready": true}
}'
Define the schema, then search
Collection attaches the JSON Schema contract to the resource. Search supports full-text, filter, projection and sorting with limited cost.
curl --get "$JSONAPI_URL/api/v1/resources/search" \
-H "X-API-Key: $JSONAPI_KEY" \
--data-urlencode 'q=release' \
--data-urlencode 'filter={"data.ready":{"$eq":true}}' \
--data-urlencode 'fields=id,name,data.ready,updatedAt' \
--data-urlencode 'sort=updatedAt' \
--data-urlencode 'direction=desc'
Put large tasks into queue
Small batches can be completed immediately. Import, export and large batches return the job ID to the client to poll the status.
Webhook receives signed event after commit. When the endpoint fails, the system retries according to the backoff and allows replay delivery.
Trace errors using request ID
All errors use a stable envelope. Server errors do not contain a stack trace, database name or runtime details.
{
"code": "VALIDATION_FAILED",
"message": "Request validation failed",
"status": 400,
"requestId": "req-client-42",
"timestamp": "2026-07-24T08:00:00Z",
"details": []
}
- 400
- Fix the request body, parameter, or validation details.
- 401 / 403
- Check credential, scope and workspace role.
- 409
- Read the latest version before recording.
- 429
- Wait according to the
Retry-After. - 5xx
- Record
X-Request-Idand retry with backoff.
Bring to production
Run at least three application instances behind the load balancer. Use PostgreSQL, Redis, RabbitMQ and shared object storage.