← Back to blog

Oracle Fusion REST API ETag and If-Match: Fixing 412 Precondition Failed

By Mostafa Mansour 6 min read Oracle FusionREST APIETagIf-MatchConcurrency

A PATCH that worked yesterday returns 412 Precondition Failed today, with no payload change on your end. Nothing is broken — Oracle Fusion REST APIs use optimistic concurrency control, and the 412 is the API telling you the record moved since you last read it. The mechanism is ETag and If-Match, and it applies to essentially every PATCH and PUT across HCM and FSCM, yet the top search results for it are generic HTTP-status-code explainer sites with zero Oracle-specific detail. This is the practical version: where the ETag comes from, how to send it back, and how to handle the 412 when it happens.

All examples use an anonymized pod (acme.fa.us2.oraclecloud.com) and placeholder identifiers — swap in your own.

Why Oracle uses ETags at all

Two integrations updating the same worker or the same invoice at the same time is a real scenario, not an edge case — a scheduled sync job and a user editing the same record in the UI, or two integration jobs racing after a retry. Without a concurrency check, whichever PATCH lands last silently overwrites the other, and nobody gets an error. ETag-based concurrency turns that into a loud, recoverable failure instead of a quiet, unrecoverable one.

The flow, per Oracle’s REST API documentation for Common Features:

  1. GET a resource. The response includes an ETag header — an opaque version token for that exact resource state.
  2. When you PATCH or PUT the same resource, send that token back in an If-Match header.
  3. Oracle compares your If-Match value against the resource’s current ETag. If they match, the write proceeds and a fresh ETag comes back. If they don’t match — someone else changed the record since your GET — the write is rejected with 412 Precondition Failed and the response carries the current ETag.

Reading the ETag

curl -i -u integration.user \
  "https://acme.fa.us2.oraclecloud.com/hcmRestApi/resources/11.13.18.05/workers?q=PersonNumber=100001"

Response headers include something like:

ETag: "AAAAAAAAAAA="

Capture that exact string, quotes included — it’s compared byte-for-byte, not parsed.

Sending it back on PATCH

A worker location update, using the same LocationCode field from our effective dates guide:

curl -u integration.user -X PATCH \
  -H 'Content-Type: application/json' \
  -H 'If-Match: "AAAAAAAAAAA="' \
  -d '{"LocationCode": "HQ_LONDON"}' \
  "https://acme.fa.us2.oraclecloud.com/hcmRestApi/resources/11.13.18.05/workers/00020000000EACED.../child/workRelationships/.../assignments/..."

Same pattern on the FSCM side — updating a receivables credit memo header:

curl -u integration.user -X PATCH \
  -H 'Content-Type: application/json' \
  -H 'If-Match: "BBBBBBBBBBB="' \
  -d '{"TransactionDate": "2026-08-01"}' \
  "https://acme.fa.us2.oraclecloud.com/fscmRestApi/resources/11.13.18.05/receivablesCreditMemos/300000001234567"

If the ETag matches the server’s current value, the PATCH applies and the response returns a new ETag — use that one for your next write, not the one you started with.

Handling 412 Precondition Failed

When the tokens don’t match, the response is:

HTTP/1.1 412 Precondition Failed

The correct recovery is not to retry the same request — it will fail again for the same reason. Instead:

  1. GET the resource again to see the current state and the current ETag.
  2. Reconcile: is your change still valid against the new state, or did the conflicting update already do what you needed?
  3. Re-issue the PATCH with the fresh ETag in If-Match.

For automated integrations, wrap the GET → PATCH sequence in a retry loop with a small cap (2–3 attempts) rather than looping indefinitely — a 412 that keeps recurring usually means two processes are fighting over the same record on a schedule, which is a design problem, not a token problem.

Common gotchas

Where this fits with everything else

If-Match is orthogonal to the other REST mechanics we’ve covered: it doesn’t change how you build q filters or finders, and it applies regardless of the REST-Framework-Version header discussed in our Postman setup guide. It’s purely a write-path safety check — GETs never need it, and only PATCH/PUT (and some DELETE operations) are affected. For the rest of the request lifecycle — auth, pagination, expand — see the HCM REST API examples post and the full endpoint catalog.


This post is part of our complete Oracle Fusion API guide — auth, base URLs, q filters, finders, and key endpoints in one place.