/fscmRestApi/resources/11.13.18.05/ covering requisitions, draft purchase orders, suppliers, negotiations, and compliance — but receipts live in SCM Cloud, and PO creation requires the Draft PO resource, not the read-only PO resource.purchaseOrders resource is read-only (GET + actions) — to create or update POs via REST you must use draftPurchaseOrders, then submit for approval.Oracle Fusion Cloud Procurement is Oracle's SaaS procurement platform, part of the broader Oracle Fusion Cloud Applications suite. The REST API (version 11.13.18.05) provides programmatic access to procurement objects including purchase requisitions, draft purchase orders, suppliers, supplier negotiations, approved supplier lists, compliance checklists, and catalog management. The API version string remains constant across quarterly releases, but endpoint behavior changes with each release. This card covers Release 26A (January 2026). Receipts and receiving are managed by the SCM Cloud REST API, not the Procurement API. [src1]
| Property | Value |
|---|---|
| Vendor | Oracle |
| System | Oracle Fusion Cloud Procurement 26A |
| API Surface | REST (HTTPS/JSON) |
| Current API Version | 11.13.18.05 |
| Editions Covered | Enterprise (SaaS) |
| Deployment | Cloud |
| API Docs | Oracle Procurement 26A REST API |
| Status | GA |
| API Surface | Protocol | Best For | Max Records/Request | Rate Limit | Real-time? | Bulk? |
|---|---|---|---|---|---|---|
| REST API | HTTPS/JSON | Individual CRUD, requisition submission, PO lifecycle actions | Paginated (default 25, max 500) | Per-tenant throttling | Yes | No |
| SOAP Web Services | HTTPS/XML | Legacy integrations, metadata operations | Varies by service | Shared with REST | Yes | No |
| FBDI | CSV in ZIP via UCM | Data migration, bulk supplier/PO import | 100,000 per import | 5 concurrent imports | No | Yes |
| Business Events (OIC) | Async/webhook via OIC | Event-driven PO status changes | N/A (event-based) | Subscription-based | Yes | N/A |
| ERP Integration Service | SOAP/REST | Orchestrating FBDI imports with callbacks | N/A | N/A | No | Yes |
| BI Publisher / OTBI | HTTPS/SOAP | Reporting and data extraction | Report-dependent | Fair use | No | No |
| Limit Type | Value | Applies To | Notes |
|---|---|---|---|
| Default page size | 25 records | REST API GET requests | Configurable via limit query parameter |
| Max page size | 500 records | REST API GET requests | Use offset for pagination beyond 500 |
| Max FBDI ZIP file size | 250 MB | File-Based Data Import | Individual CSV files within ZIP can be up to 1 GB |
| Max records per FBDI import | 100,000 | File-Based Data Import | Split larger datasets across multiple import jobs |
| Max attachment size | 2 GB | REST API file uploads | Via LOB attribute endpoints |
| Limit Type | Value | Window | Edition Differences |
|---|---|---|---|
| REST API requests | No published hard cap | Per-tenant throttling | Adaptive throttling — excessive requests receive HTTP 429 |
| Concurrent FBDI imports | 5 | Per instance | Shared across all FBDI-enabled modules |
| Concurrent long-running REST requests | Tenant-dependent | Per instance | Not published — contact Oracle Support |
| Scheduled processes (ESS jobs) | Configurable | Per instance | Admin-configurable concurrent job limits |
| Flow | Use When | Token Lifetime | Refresh? | Notes |
|---|---|---|---|---|
| OAuth 2.0 Client Credentials (2-legged) | Server-to-server integration | Configurable (default 3600s) | New token per expiry | Recommended for automated integrations |
| OAuth 2.0 Authorization Code (3-legged) | User-context operations | Configurable, Refresh: until revoked | Yes | Requires redirect URI registration |
| JWT Bearer Token | Service-to-service with signed JWT | Per JWT expiry claim | New JWT per request | Requires certificate upload |
| Basic Auth | Development/testing only | Session-based | No | Deprecated for production |
purchaseOrders REST resource is read-only — it supports GET and action operations (cancel, close, freeze, hold) but NOT POST for creation or PATCH for updates. Use draftPurchaseOrders to create and edit POs.receivingReceiptRequests.START — User needs to integrate with Oracle Procurement Cloud
|-- What's the procurement object?
| |-- Purchase Requisitions
| | |-- Volume < 1,000 records/day?
| | | |-- YES -> REST API: purchaseRequisitions (POST + submitRequisition)
| | | +-- NO -> FBDI: Import Requisitions template via ERP Integration Service
| |-- Purchase Orders
| | |-- Creating/editing POs?
| | | |-- YES -> REST API: draftPurchaseOrders (POST/PATCH), then submit
| | | +-- NO (read-only) -> REST API: purchaseOrders (GET + actions)
| | |-- Need PO lifecycle events?
| | | |-- YES -> Business Events via OIC (PO event subscription)
| | | +-- NO -> REST API polling with lastUpdateDate filter
| | +-- Bulk PO creation?
| | +-- YES -> FBDI: Purchase Orders Import template
| |-- Suppliers
| | |-- Volume < 500 suppliers/day?
| | | |-- YES -> REST API: suppliers (POST/PATCH)
| | | +-- NO -> FBDI: Supplier Import template
| | +-- Need real-time supplier updates?
| | |-- YES -> REST API polling (no business events for suppliers)
| | +-- NO -> Scheduled FBDI export via BI Publisher
| |-- Receipts / Receiving
| | +-- Use SCM Cloud API: receivingReceiptRequests (NOT Procurement API)
| +-- Sourcing / Negotiations
| +-- REST API: supplierNegotiations, draftSupplierNegotiationResponses
|-- Which direction?
| |-- Inbound -> Use draftPurchaseOrders or FBDI
| |-- Outbound -> Use purchaseOrders or requisitionLifecycleDetails
| +-- Bidirectional -> Design conflict resolution on PO status + lastUpdateDate
+-- Error tolerance?
|-- Zero-loss -> FBDI with ERP Integration Service callbacks + retry queue
+-- Best-effort -> REST API with exponential backoff on 429/503
| Operation | Method | Endpoint | Payload | Notes |
|---|---|---|---|---|
| Create requisition | POST | /purchaseRequisitions | JSON | Creates header; add lines as child resource |
| Submit requisition | POST | /purchaseRequisitions/{id}/action/submitRequisition | JSON | Triggers approval workflow |
| Cancel requisition | POST | /purchaseRequisitions/{id}/action/cancel | JSON | Only if not yet approved |
| Get all POs | GET | /purchaseOrders | N/A | Read-only; supports query filters |
| Create draft PO | POST | /draftPurchaseOrders | JSON | Required for PO creation |
| Submit draft PO | POST | /draftPurchaseOrders/{id}/action/submitDocument | JSON | Moves to approval |
| Cancel PO | POST | /purchaseOrders/{id}/action/cancel | JSON | Only open POs |
| Close PO | POST | /purchaseOrders/{id}/action/close | JSON | Closes all lines and schedules |
| Freeze PO | POST | /purchaseOrders/{id}/action/freeze | JSON | Prevents further changes |
| Create supplier | POST | /suppliers | JSON | Creates supplier header |
| Register supplier | POST | /supplierRegistrationRequests/{key}/action/register | JSON | Self-service registration flow |
| Get supplier negotiations | GET | /supplierNegotiations | N/A | RFQ, RFI, auction details |
| Create receipt (SCM) | POST | /receivingReceiptRequests | JSON | Part of SCM API, not Procurement |
| Requisition lifecycle | GET | /requisitionLifecycleDetails | N/A | End-to-end P2P view per requisition |
| Check funds | POST | /purchaseRequisitions/{id}/action/checkFunds | JSON | Budget validation |
Configure a Confidential Application in the Fusion Applications Identity Domain and obtain an OAuth 2.0 access token using client credentials flow. [src5]
# Obtain OAuth 2.0 token from Fusion Identity Domain
curl -X POST "https://<identity-domain>.identity.oraclecloud.com/oauth2/v1/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=<CLIENT_ID>" \
-d "client_secret=<CLIENT_SECRET>" \
-d "scope=urn:opc:resource:consumer::all"
Verify: Response contains access_token field with a JWT value and expires_in (typically 3600).
Create a requisition header with at least one line. The requisition starts in "Incomplete" status until submitted. [src2]
curl -X POST "https://<fusion-host>/fscmRestApi/resources/11.13.18.05/purchaseRequisitions" \
-H "Authorization: Bearer <ACCESS_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"RequisitioningBUName": "US1 Business Unit",
"PreparerId": 300000001234567,
"Description": "Office Supplies Q2",
"lines": [{
"LineNumber": 1,
"ItemDescription": "Printer Paper A4",
"CategoryName": "Office Supplies",
"Quantity": 100,
"UnitPrice": 5.99,
"UOMCode": "EA",
"CurrencyCode": "USD"
}]
}'
Verify: Response HTTP 201 with RequisitionHeaderId in response body.
After creating lines, submit the requisition to trigger the approval workflow. [src2]
curl -X POST "https://<fusion-host>/fscmRestApi/resources/11.13.18.05/purchaseRequisitions/<ReqHeaderId>/action/submitRequisition" \
-H "Authorization: Bearer <ACCESS_TOKEN>" \
-H "Content-Type: application/json" \
-d '{}'
Verify: Response returns "result": "SUCCESS" — requisition status changes to "Pending Approval".
Retrieve POs filtered by date range, status, or supplier. [src1]
curl -X GET "https://<fusion-host>/fscmRestApi/resources/11.13.18.05/purchaseOrders?q=OrderNumber%3D1234&expand=lines&limit=25&offset=0" \
-H "Authorization: Bearer <ACCESS_TOKEN>"
Verify: Response contains items array with PO header and expanded lines child resources.
Create a new supplier record with addresses and sites as child resources. [src3]
curl -X POST "https://<fusion-host>/fscmRestApi/resources/11.13.18.05/suppliers" \
-H "Authorization: Bearer <ACCESS_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"Supplier": "Acme Corp",
"SupplierType": "Supplier",
"TaxOrganizationType": "Corporation",
"addresses": [{"AddressName": "HQ", "Country": "US", "AddressLine1": "123 Main St", "City": "New York", "State": "NY", "PostalCode": "10001"}],
"sites": [{"ProcurementBU": "US1 Business Unit", "SupplierSite": "MAIN", "PaymentCurrencyCode": "USD"}]
}'
Verify: Response HTTP 201 with SupplierId in response body.
For volumes exceeding 1,000 records, use FBDI via the ERP Integration Service. [src4]
# Upload ZIP to UCM and trigger import job
curl -X POST "https://<fusion-host>/fscmRestApi/resources/11.13.18.05/erpintegrations" \
-H "Authorization: Bearer <ACCESS_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"OperationName": "importBulkData",
"DocumentContent": "<BASE64_ENCODED_ZIP>",
"DocumentName": "PoImport.zip",
"ContentType": "zip",
"JobName": "/oracle/apps/ess/prc/po/PurchaseOrderImportEss",
"ParameterList": "US1 Business Unit,N,#NULL,#NULL,N,N"
}'
Verify: Job status returns "SUCCEEDED" — check import error report for rejected records.
# Input: OAuth token, Fusion host URL
# Output: List of all open purchase orders
import requests
def get_all_open_pos(host, token, bu_name="US1 Business Unit"):
url = f"https://{host}/fscmRestApi/resources/11.13.18.05/purchaseOrders"
headers = {"Authorization": f"Bearer {token}"}
params = {
"q": f'Status="OPEN";ProcurementBUName="{bu_name}"',
"limit": 500, "offset": 0,
"expand": "lines",
"fields": "OrderNumber,SupplierId,Supplier,Status,OrderedAmount,CurrencyCode"
}
all_pos = []
while True:
resp = requests.get(url, headers=headers, params=params)
if resp.status_code == 429:
import time
time.sleep(int(resp.headers.get("Retry-After", 30)))
continue
resp.raise_for_status()
data = resp.json()
all_pos.extend(data.get("items", []))
if not data.get("hasMore", False):
break
params["offset"] += params["limit"]
return all_pos
// Input: Fusion host, OAuth token, requisition data
// Output: Created requisition header ID
const axios = require("axios"); // v1.6+
async function createRequisition(host, token, reqData) {
const url = `https://${host}/fscmRestApi/resources/11.13.18.05/purchaseRequisitions`;
try {
const resp = await axios.post(url, reqData, {
headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
});
const reqId = resp.data.RequisitionHeaderId;
await axios.post(`${url}/${reqId}/action/submitRequisition`, {},
{ headers: { Authorization: `Bearer ${token}` } });
return reqId;
} catch (err) {
if (err.response?.status === 429) {
const retryAfter = err.response.headers["retry-after"] || 30;
await new Promise((r) => setTimeout(r, retryAfter * 1000));
return createRequisition(host, token, reqData);
}
throw err;
}
}
# Input: Valid OAuth token, Fusion host
# Output: Resource metadata
# Test authentication and list procurement resources
curl -s -X GET "https://<fusion-host>/fscmRestApi/resources/11.13.18.05" \
-H "Authorization: Bearer <ACCESS_TOKEN>" | python -m json.tool
# Describe purchaseRequisitions resource (schema/metadata)
curl -s -X GET "https://<fusion-host>/fscmRestApi/resources/11.13.18.05/purchaseRequisitions/describe" \
-H "Authorization: Bearer <ACCESS_TOKEN>" | python -m json.tool
| Source Field | Target Field | Type | Transform | Gotcha |
|---|---|---|---|---|
| External PO Number | OrderNumber | String | Direct (if auto-numbering disabled) | Auto-numbering overrides any provided value |
| Supplier Name | Supplier | String | Exact match required | Must match existing supplier record |
| Item Number | ItemNumber | String | Must exist in Item Master | Procurement does not auto-create items |
| Unit Price | UnitPrice | Number | Decimal, 2-6 places | Currency code must match PO currency |
| Delivery Date | NeedByDate | Date | ISO 8601 (YYYY-MM-DD) | Must be future date |
| Ship-To Location | ShipToLocationCode | String | Must match HR location | Location codes are HR-managed |
| Charge Account | ChargeAccountSegments | String | Segment1-Segment2-...-SegmentN | Use action/deriveChargeAccount for defaults |
| Tax Classification | TaxClassificationCode | String | Must match tax setup | Invalid codes cause silent tax calculation failures |
describe endpoint first. [src1]| Code | Meaning | Cause | Resolution |
|---|---|---|---|
| 400 | Bad Request | Malformed JSON, invalid field values, boolean as true/false | Validate payload against the describe endpoint |
| 401 | Unauthorized | Expired or invalid OAuth token | Refresh token and retry |
| 403 | Forbidden | Missing Fusion security role or data security policy | Verify integration user roles |
| 404 | Not Found | Invalid resource path or non-existent record ID | Confirm API version and resource name |
| 429 | Too Many Requests | Tenant-level throttle exceeded | Exponential backoff: Retry-After header or 30s default |
| 500 | Internal Server Error | Fusion application error, invalid business logic | Check payload against business rules; review ESS job logs |
| 503 | Service Unavailable | Fusion instance under maintenance or overload | Retry after 60s; check Oracle Cloud Status page |
Always download and parse the import error report from UCM after every FBDI job. [src4]Call action/checkFunds and validate all required fields before submission. [src1]Implement token endpoint discovery and handle 401 with a fresh token request. [src5]Query suppliers by TaxRegistrationNumber before creating. [src3]Re-test event subscriptions in a test instance after each quarterly update. [src6]# BAD — purchaseOrders is read-only, returns 405 Method Not Allowed
curl -X POST "https://host/fscmRestApi/resources/11.13.18.05/purchaseOrders" \
-H "Authorization: Bearer $TOKEN" -d '{"Supplier": "Acme"}'
# GOOD — create via draftPurchaseOrders, then submit for approval
curl -X POST "https://host/fscmRestApi/resources/11.13.18.05/draftPurchaseOrders" \
-H "Authorization: Bearer $TOKEN" \
-d '{"Supplier": "Acme", "ProcurementBUName": "US1 Business Unit"}'
# Then submit:
curl -X POST "https://host/.../draftPurchaseOrders/<id>/action/submitDocument" \
-H "Authorization: Bearer $TOKEN" -d '{}'
# BAD — retrieves ALL suppliers every poll cycle, wasting API quota
def check_supplier_updates(host, token):
resp = requests.get(f"https://{host}/.../suppliers", headers={"Authorization": f"Bearer {token}"})
return resp.json()["items"]
# GOOD — only fetches suppliers modified since last poll
def check_supplier_updates(host, token, last_poll_time):
resp = requests.get(f"https://{host}/.../suppliers",
headers={"Authorization": f"Bearer {token}"},
params={"q": f'LastUpdateDate>"{last_poll_time}"', "limit": 500})
return resp.json()["items"]
# BAD — creates suppliers one-by-one via REST, hits throttling at scale
for supplier in ten_thousand_suppliers:
requests.post(url, json=supplier, headers=headers)
# GOOD — batch via FBDI, handles 100K records per import
import base64, zipfile, io
def bulk_import_suppliers(host, token, csv_data):
buf = io.BytesIO()
with zipfile.ZipFile(buf, 'w', zipfile.ZIP_DEFLATED) as zf:
zf.writestr("SupplierImport.csv", csv_data)
payload = {"OperationName": "importBulkData",
"DocumentContent": base64.b64encode(buf.getvalue()).decode(),
"DocumentName": "SupplierImport.zip", "ContentType": "zip",
"JobName": "/oracle/apps/ess/prc/poi/SupplierImportEss"}
return requests.post(f"https://{host}/.../erpintegrations",
json=payload, headers={"Authorization": f"Bearer {token}"})
purchaseOrders resource only supports GET and action operations. Fix: Always use draftPurchaseOrders for write operations. [src1]Include lines as a nested array in the initial POST to create atomically. [src2]Always check hasMore flag and increment offset. [src1]Download and parse error report CSV from UCM after every import. [src4]Implement OAuth 2.0 client credentials flow. [src5]Use OpenID Connect discovery to dynamically resolve token endpoint. [src5]# Test authentication — should return 200 with resource list
curl -s -o /dev/null -w "%{http_code}" \
"https://<fusion-host>/fscmRestApi/resources/11.13.18.05" \
-H "Authorization: Bearer <TOKEN>"
# Describe a resource — returns field names, types, and constraints
curl -s "https://<fusion-host>/fscmRestApi/resources/11.13.18.05/purchaseRequisitions/describe" \
-H "Authorization: Bearer <TOKEN>" | python -m json.tool
# Check requisition lifecycle (end-to-end P2P status)
curl -s "https://<fusion-host>/fscmRestApi/resources/11.13.18.05/requisitionLifecycleDetails?q=RequisitionNumber=<REQ_NUM>" \
-H "Authorization: Bearer <TOKEN>"
# Check FBDI job status
curl -s "https://<fusion-host>/fscmRestApi/resources/11.13.18.05/erpintegrations?finder=ESSJobStatusRF;requestId=<JOB_ID>" \
-H "Authorization: Bearer <TOKEN>"
# List all POs for a supplier
curl -s "https://<fusion-host>/fscmRestApi/resources/11.13.18.05/purchaseOrders?q=Supplier=%22Acme%22&limit=10" \
-H "Authorization: Bearer <TOKEN>"
| API Version | Release Date | Status | Breaking Changes | Migration Notes |
|---|---|---|---|---|
| 11.13.18.05 (26A) | 2026-01 | Current | generateHighlights action added (AI) | New AI summary feature for POs |
| 11.13.18.05 (25D) | 2025-10 | Supported | Supplier Eligibility resource added | New endpoint for supplier qualification |
| 11.13.18.05 (25C) | 2025-08 | Supported | PO actions enhanced | Added duplicate, renumber actions |
| 11.13.18.05 (25B) | 2025-05 | Supported | FBDI playbook updated | New integration patterns documented |
| 11.13.18.05 (25A) | 2025-02 | Supported | None | Baseline for 2025 integrations |
| Use When | Don't Use When | Use Instead |
|---|---|---|
| Real-time requisition creation and submission (<1,000/day) | Bulk requisition migration (>10,000 records) | FBDI via ERP Integration Service |
| PO lifecycle management (freeze, close, cancel, hold) | Creating purchase orders (purchaseOrders is read-only) | draftPurchaseOrders resource |
| Supplier master data sync (<500 suppliers/day) | Bulk supplier migration (>5,000 records) | FBDI: Supplier Import template |
| Querying PO status and requisition lifecycle | Creating receipts against POs | SCM Cloud receivingReceiptRequests API |
| Event-driven PO status integration | Event-driven supplier or agreement changes | Polling with LastUpdateDate filter |
| Interactive sourcing/negotiation responses | Automated mass negotiation processing | FBDI or SOAP Web Services |