Browse documentation

REST resource contracts

Design resource identity, conditional updates and predictable HTTP responses for customer operations.

On this page
Before you start
  • A resource ownership map
  • A tenant boundary
  • A defined update policy

A conditional contact update

The current resource version travels back with the read and becomes a precondition on the write.

A conditional contact updateStep 1: Client to API boundary. GET contact. Step 2: API boundary to Policy service. Authorize object access. Step 3: API boundary to Resource store. Read current version. Step 4: API boundary to Client. 200 + ETag. Step 5: Client to API boundary. PATCH + If-Match. Step 6: API boundary to Resource store. Compare and commit.ClientAPI boundaryPolicy serviceResource storeGET contact1Authorize object access2Read current version3200 + ETag4PATCH + If-Match5Compare and commit6

Scroll across the diagram to see all four systems.

Inspect each exchange

GET contact

Request the representation using an authenticated identity.

Start with the resource boundary

A contact, account, consent record and workflow execution have different lifecycles. Give each a stable identifier and define which system owns its writable fields. A contact identifier should remain stable when an email address changes. Place relationships in explicit fields or subresources rather than encoding business state into the URL.

Use collection resources for discovery and item resources for direct operations. The path communicates identity; authorization determines whether the caller may act on that identity. An opaque identifier reduces accidental exposure but does not replace an access check.

MethodContractOperational consequence
GETRead a representationSafe semantics; do not trigger a workflow as a side effect.
POSTCreate or submit workDefine duplicate handling before allowing automatic retry.
PUTReplace a resource representationClarify required fields and replacement semantics.
PATCHApply a supported partial updateDeclare the patch media type and validation behavior.
DELETERemove under the resource policyRepeatable intended effect does not require identical response bodies.

Prevent a stale screen from overwriting newer work

Return an ETag for a representation and accept If-Match on changes that require a current version. Evaluate the precondition in the same transaction as the write. If the version changed, return 412 Precondition Failed and let the client fetch the current state before proposing a new edit.

Do not silently merge fields whose ownership or order matters. A marketing stage correction and an active sales qualification can be individually valid but mutually inconsistent. Keep the original request and explain the changed precondition.

Conditional updatehttp
PATCH /api/v1/contacts/contact_240 HTTP/1.1
Host: api.example.test
Authorization: Bearer <access_token>
Content-Type: application/merge-patch+json
If-Match: "v12"

{
  "lifecycle_stage": "qualified"
}

Make lists stable enough to traverse

Specify sort order, page size bounds and the meaning of a cursor. An opaque cursor can carry a stable ordering key and snapshot context without exposing database details. A cursor is not an access token: the API must authorize every page again.

Decide how inserts, deletes and permission changes affect a traversal. Reporting exports may need a consistent snapshot, while an operational list may accept a changing view. Document that distinction so a client does not mistake a paginated listing for a complete historical export.

Choose status by the result of this request

Return 201 for a completed creation and identify the new resource with Location. Use 202 only when processing has been accepted and is not complete; expose a separate operation resource to inspect completion. A 204 response has no content body.

Keep business conflicts, missing permissions and invalid representations distinct. Generic network clients understand HTTP status even when they do not understand your JSON error structure. The problem details status member must match the actual HTTP response status.

Verify the contract at the boundary

Test stale entity tags, repeated deletion, concurrent creation, empty pages, expired cursors and an object outside the tenant. Confirm that validation cannot partly commit a resource unless partial success is a documented feature.

A contract review should include the cache policy, maximum payload, content negotiation, date format, timezone, error vocabulary and request correlation. These decisions are part of the interface and should survive a change of framework.

Evaluate a conditional write

Change the entity tag or tenant context and inspect the resulting contract. Evaluation runs in this page.

PATCH/api/v1/contacts/contact_240

Contract inputs

Includes request values and the server validation context defined below.

Expected outcome

HTTP 200

Update committed

The caller is authorized and the current entity tag matches the submitted precondition.

{
  "id": "contact_240",
  "lifecycle_stage": "qualified",
  "version": 13
}

Decision path

  1. Authorize the contact
  2. Check the current entity tag
  3. Validate the requested stage
  4. Commit one update
Input schema 4 fields
FieldTypeMeaning
if_matchRequiredstringEntity tag supplied by the client.
current_etagRequiredstringCurrent resource version at commit time.
tenant_allowedRequiredbooleanResult of the object authorization check.
lifecycle_stageRequiredstringRequested lifecycle value.Allowed: new, qualified, customer
Download JSON Schema

Standards and documentation

Explore the protocol specifications and platform guidance for this topic.

Bring the contract into your operating environment.

Discuss an implementation

Image preview