← Back to blog

Oracle Fusion REST API Bulk Operations: The Parts Payload Batch Pattern

By Mostafa Mansour 7 min read Oracle FusionREST APIBatch OperationsBulkParts Payload

Looping POST /workers or PATCH /invoices/{id} one record at a time works, but it’s slow, it burns through rate limits fast, and each call is a separate network round trip. Oracle Fusion’s REST layer has a generic answer to this that most integration guides either skip entirely or only describe from inside Oracle Integration Cloud’s mapper UI: a batch media type that lets you send a mixed list of create, update, delete, and even read operations in a single HTTP request. This post covers it the way a direct REST client — not OIC — actually calls it, with real payload shapes.

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

The batch media type

A batch request is a normal POST, but instead of the usual application/vnd.oracle.adf.resourceitem+json content type, you send application/vnd.oracle.adf.batch+json against the resources root:

POST /hcmRestApi/resources/latest
Content-Type: application/vnd.oracle.adf.batch+json

The body is a parts array. Each part is one independent operation with its own id, path, operation, and (for writes) payload:

{
  "parts": [
    {
      "id": "part1",
      "path": "/workers/300000012345678",
      "operation": "get"
    },
    {
      "id": "part2",
      "path": "/workers/300000012345678",
      "operation": "update",
      "payload": {
        "emails": [
          { "EmailType": "W1", "EmailAddress": "[email protected]" }
        ]
      }
    }
  ]
}

Mixing operation types in one batch — a get to check current state alongside a update that depends on it — is the main thing this pattern buys you over N separate calls.

Bulk create: multiple new records in one request

create parts each carry their own payload, built the same way a standalone POST body would be. Using the real Workers endpoint child structure covered in the workers guide:

{
  "parts": [
    {
      "id": "hire1",
      "path": "/workers",
      "operation": "create",
      "payload": {
        "names": [
          { "LegislationCode": "GLOBAL", "FirstName": "Test", "LastName": "EmployeeOne" }
        ],
        "workRelationships": [
          {
            "LegalEmployerName": "Acme Corp",
            "WorkerType": "E",
            "PrimaryFlag": true,
            "assignments": [
              { "ActionCode": "HIRE", "BusinessUnitName": "Acme US BU", "PrimaryFlag": true }
            ]
          }
        ]
      }
    },
    {
      "id": "hire2",
      "path": "/workers",
      "operation": "create",
      "payload": {
        "names": [
          { "LegislationCode": "GLOBAL", "FirstName": "Test", "LastName": "EmployeeTwo" }
        ],
        "workRelationships": [
          {
            "LegalEmployerName": "Acme Corp",
            "WorkerType": "E",
            "PrimaryFlag": true,
            "assignments": [
              { "ActionCode": "HIRE", "BusinessUnitName": "Acme US BU", "PrimaryFlag": true }
            ]
          }
        ]
      }
    }
  ]
}

Every rule that applies to a standalone POST /workers — required child resources, Effective-Of for the hire date, WorkerType values — still applies per-part; batching doesn’t relax field-level validation, it just avoids the extra round trips.

Bulk update and delete

update parts send only the changed fields, same as a standalone PATCH. delete parts need no payload at all:

{
  "parts": [
    {
      "id": "close1",
      "path": "/invoices/300000098765432",
      "operation": "update",
      "payload": { "PaymentTerms": "Immediate" }
    },
    {
      "id": "remove1",
      "path": "/invoices/300000098765433",
      "operation": "delete"
    }
  ]
}

For resources with ETag/If-Match protection, the same If-Match requirement applies to update and delete parts — you can’t batch around optimistic locking, you just move the header logic into building each part.

How partial failure works

This is the detail most third-party writeups skip, and it’s the one that actually determines whether batching is safe for your use case. By default, Oracle processes each part independently — one part failing doesn’t roll back the others, and the response tells you which parts succeeded and which didn’t, part-by-part, matched by the id you assigned. If you need all-or-nothing semantics instead, that’s a request-level setting, not something you get for free just by using the batch media type — check the current behavior against a real response before relying on it in production, since it’s easy to assume atomicity that isn’t actually there.

Practical implication: always check every part’s individual result, never just the outer HTTP status code. A batch request can return 200 OK at the top level while three of ten parts inside it failed — the same trap as ignoring o:errorDetails on a 400 response, just multiplied across a whole batch.

Practical batch size

Oracle’s own guidance is to keep batches modest — around 50 operations per request is the commonly cited practical ceiling, not a hard-documented maximum baked into every resource. Treat it the same way you’d treat the 500-row page-size cap: don’t assume you can push an arbitrarily large batch through and get a clean response back. For a true bulk-load scenario — thousands of rows, not dozens — HDL or FBDI is still the right tool; the batch media type is for combining a handful of related REST operations into one round trip, not for replacing bulk data-load pipelines.

Not the same thing as a resource’s own “Bulk” action

A few Supply Chain resources (buyerPlanningSupplies, collaborationCustomerDemands, and similar) additionally expose their own dedicated bulk-style POST action that accepts an array of records directly in a single resource-specific payload shape — a different mechanism from the generic parts batch media type described above, scoped to that one resource. If you’re integrating with one of those specific SCM resources, check its own REST API reference for whether it has this dedicated action before reaching for the generic batch pattern; the two aren’t interchangeable and use different payload shapes.

Common mistakes

Checking a resource’s real fields before you batch

The batch mechanism is generic, but the payload inside each create/update part still has to match that specific resource’s real schema — the same q-fields, finders, and child resources documented per endpoint. OPAL bundles the Oracle Fusion Cloud OpenAPI specification offline, so you can look up an endpoint’s exact fields and required child resources in the endpoint catalog before building a batch part, without burning API calls on trial and error against a live pod.


This post is part of our complete Oracle Fusion API guide — base URLs, authentication, q filters, finders, and common errors in one place.

Explore Oracle Fusion APIs offline

OPAL bundles 59,000+ Oracle Fusion REST endpoints, fully searchable offline, with a visual Q Builder and Finder Builder that only offer fields the endpoint actually accepts — so your filter can't 400.

Free, no account required. Pro adds live requests and multi-step Flows.