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.
Scroll across the diagram to see all four systems.
GET contact
Request the representation using an authenticated identity.
Authorize object access
Evaluate tenant membership and the action on this contact.
Read current version
Load the record and its strong entity tag.
200 + ETag
Return the contact with ETag "v12".
PATCH + If-Match
Submit a partial change only for the version that was read.
Compare and commit
Check the entity tag atomically with the update. A changed version produces 412.
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.
| Method | Contract | Operational consequence |
|---|---|---|
| GET | Read a representation | Safe semantics; do not trigger a workflow as a side effect. |
| POST | Create or submit work | Define duplicate handling before allowing automatic retry. |
| PUT | Replace a resource representation | Clarify required fields and replacement semantics. |
| PATCH | Apply a supported partial update | Declare the patch media type and validation behavior. |
| DELETE | Remove under the resource policy | Repeatable 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.
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.
/api/v1/contacts/contact_240Expected outcome
Update committed
The caller is authorized and the current entity tag matches the submitted precondition.
{
"id": "contact_240",
"lifecycle_stage": "qualified",
"version": 13
}ETag: "v13"Decision path
- Authorize the contact
- Check the current entity tag
- Validate the requested stage
- Commit one update
Input schema 4 fields
| Field | Type | Meaning |
|---|---|---|
if_matchRequired | string | Entity tag supplied by the client. |
current_etagRequired | string | Current resource version at commit time. |
tenant_allowedRequired | boolean | Result of the object authorization check. |
lifecycle_stageRequired | string | Requested lifecycle value.Allowed: new, qualified, customer |
Standards and documentation
Explore the protocol specifications and platform guidance for this topic.
Bring the contract into your operating environment.
Discuss an implementation