Date: 2026-02-24 Status: Research complete
| Data Object | REST API Read | REST API Write | GraphQL Read | CSV Import | CSV Export | Confidence |
|---|---|---|---|---|---|---|
| Invoices | YES | YES (create, update) | YES | YES | YES | High |
| Purchase Orders | YES | YES (create, update) | YES | YES (change import) | YES | High |
| Suppliers | YES | YES (create, update, query) | YES | YES | YES (info + sites) | High |
| Contracts | YES | YES (create, update) | YES | YES | YES | High |
| Requisitions | YES | YES (create, update) | YES | YES | YES | High |
| Receipts | YES | YES | YES | YES | YES | High |
| Expense Reports | YES | YES | YES | YES (payment) | YES | High |
| Payments (CoupaPay) | YES | YES | Likely | YES | YES | High |
| Items (catalog) | YES | YES (create, update) | YES | YES | YES | High |
| Users | YES | YES (create, update) | YES | YES | YES | High |
| Accounts / CoA | YES | YES | YES | YES | N/A | High |
| Exchange Rates | YES | YES | Likely | YES | N/A | Medium |
| Approvals | YES | YES (approve/reject) | Likely | YES (chain) | N/A | High |
| ASN (Advance Ship Notices) | YES | YES | Likely | YES | YES | High |
Key finding: Coupa has a fully bidirectional API — both read and write are well-supported across all major business objects via REST. GraphQL is read-only (no mutations).
https://{instance}.coupahost.com/api/{resource}Content-Type and Accept headers to matchX-COUPA-API-KEY headeroffset parameter for pagingReference Data (~30+ endpoints):
Transactional (~40+ endpoints):
Shared: Attachments, Comments, Forms, Tags, UoM
Verdict: Full write access confirmed via REST API.
Evidence:
POST /api/invoices creates invoices, PUT /api/invoices/{id} updates themPOST /api/suppliers creates, PUT updates, GET queriesImportant nuance: GraphQL is read-only (no mutations, only client_credentials + read scopes). All writes must go through the REST API.
| Platform | Status | Notes |
|---|---|---|
| MuleSoft | Native connector | Full access to addresses, ASN, approvals, contracts, invoices, POs, suppliers, users, expenses, CoupaPay |
| Informatica | Coupa V2 Connector | Read (source) + Write (target) operations |
| Boomi | Native connector | Standard CRUD operations |
| UiPath | Native connector | Polling-based events |
| SAP Integration Suite | Coupa Receiver Adapter | For SAP-to-Coupa flows |
Coupa has extensive CSV import/export via dedicated SFTP:
./Incoming/{ObjectType}/ (e.g., ./Incoming/Invoices/)/Archive/IncomingVerdict: YES — full create/update via REST API.
Coupa models cost centers not as standalone objects but as lookup values within a dynamic Chart of Accounts. The data model works like this:
Account Type (CoA template) — must pre-exist, CANNOT be created via API
└── Lookup Values — cost centers, departments, GL codes, etc.
└── Accounts — combinations of up to 20 segments from lookup values
Lookup Values API (/api/lookup_values):
| Method | Path | Action |
|---|---|---|
POST |
/api/lookup_values |
Create a cost center / segment value |
PUT |
/api/lookup_values/:id |
Update an existing value |
GET |
/api/lookup_values |
Query values |
GET |
/api/lookup_values/:id |
Get single value |
Key fields: name (required, unique), external-ref-num (the actual code, required, unique), active (boolean), lookup (parent lookup reference), parent / parent-id (for hierarchy), description, depth.
Accounts API (/api/accounts):
| Method | Path | Action |
|---|---|---|
POST |
/api/accounts |
Create an account (code combination) |
PUT |
/api/accounts/:id |
Update account |
GET |
/api/accounts |
Query accounts |
GET |
/api/accounts/:id |
Get single account |
Key fields: segment-1 through segment-20 (the dimension values), account-type (required reference to existing CoA), name, code (auto-generated from segments), active.
Example — create a cost center:
POST /api/lookup_values
<lookup-value>
<name>Marketing Berlin (MKT-BER)</name>
<external-ref-num>MKT-BER</external-ref-num>
<active>true</active>
<lookup>
<name>COMPANY_CostCenter</name>
</lookup>
</lookup-value>
Example — create an account using that cost center as a segment:
POST /api/accounts
<account>
<active>true</active>
<name>Marketing Berlin - Travel</name>
<segment-1>MKT-BER</segment-1>
<segment-2>Travel</segment-2>
<segment-3>Expense</segment-3>
<account-type>
<name>Corporate CoA</name>
</account-type>
</account>
Constraint: Account Types (the CoA structure itself) cannot be created via API — they must already exist in the Coupa instance. This is a setup-time dependency, not a runtime issue.
Verdict: YES — approve, reject, and hold via REST API. Cannot create new approval chains programmatically.
Approvals API (/api/approvals):
| Method | Path | Action |
|---|---|---|
PUT |
/api/approvals/:id/approve |
Approve a pending approval |
PUT |
/api/approvals/:id/reject |
Reject (with optional ?reason=...) |
PUT |
/api/approvals/:id/hold |
Put on hold |
PUT |
/api/approvals/:id |
General update |
GET |
/api/approvals |
Query approvals |
GET |
/api/approvals/:id |
Get single approval |
Approvable document types: Requisitions, Purchase Orders, Invoices, Expense Reports, Contracts.
Invoice-specific approval actions (on the invoice object itself):
add_approver — manually assign an approverbypass_approvals — skip entire approval chainbypass_current_approval — skip current step onlyremove_approval — remove a manually added approverrestart_approvals — regenerate the approval chainExample — reject an invoice approval with reason:
PUT /api/approvals/12612/reject?reason=Missing%20cost%20center%20allocation
→ HTTP 200 on success
→ HTTP 400 if approval is not in Pending state
Process Automator (webhook-style, configured in Coupa admin):
What this means for Orcha: We can both push approvals (approve/reject via API) and receive approval events (via Process Automator callouts or polling).
Verdict: YES — rich status tracking via polling or event-driven.
Invoice statuses available via API:
new → draft → pending_approval → approved → processing → (paid)
Full status enum: new, draft, pending_approval, approved, ap_hold, on_hold, pending_receipt, rejected, abandoned, disputed, booking_hold, pending_action, voided, processing, invalid, payable_adjustment
Key fields for lifecycle tracking:
| Field | Type | Purpose |
|---|---|---|
status |
string | Current invoice state (see enum above) |
paid |
boolean | Whether payment has been made |
payment-date |
date | When payment occurred |
payment-method |
string | How payment was made |
payment-term |
string | Payment term code |
approvals |
nested | Associated approval records |
exported |
boolean | Whether synced to ERP |
last-exported-at |
datetime | Last ERP sync timestamp |
created-at |
datetime | When invoice entered system |
updated-at |
datetime | Last modification |
date-received |
datetime | When invoice was received |
canceled |
boolean | Cancellation flag |
Polling pattern for status updates:
GET /api/invoices?status=approved&status=pending_approval&status=on_hold&updated-at[gt]=2026-02-24T00:00:00Z
Payment status via CoupaPay:
GET /api/coupa_pay/payments?status[in]=completed_successfully,completed_with_errors&updated-at[gt]=2026-02-24
Event-driven alternative:
SFTP alternative: Delta invoice updates delivered to /Outgoing/InvoiceUpdates as CSV.
| Orcha Need | Coupa Capability | API Endpoint | Confidence |
|---|---|---|---|
| Push extracted invoice data | Full create/update | POST /api/invoices |
Confirmed |
| Attach original PDF | File attachment on objects | Attachment API on invoice | Confirmed |
| Write cost centers | Create/update lookup values | POST /api/lookup_values |
Confirmed |
| Write account codes | Create/update accounts | POST /api/accounts |
Confirmed |
| Trigger approval | Approve/reject/hold | PUT /api/approvals/:id/approve |
Confirmed |
| Manage approvers | Add/remove/bypass | Invoice approval actions | Confirmed |
| Read invoice status | Poll or webhook | GET /api/invoices?status=...&updated-at[gt]=... |
Confirmed |
| Read payment status | Poll or webhook | GET /api/coupa_pay/payments?... |
Confirmed |
| Receive status events | Process Automator callout | Coupa → Orcha webhook | Confirmed (requires Coupa admin config) |
| Sync reference data | Read accounts, suppliers, depts | GET /api/accounts, /suppliers, /departments |
Confirmed |
| Create CoA structure | NOT via API | Must be pre-configured in Coupa | Limitation |
| Approach | Cost | Complexity | Control | Best When |
|---|---|---|---|---|
| Direct REST API | Included with Coupa license | Low-Medium | Full | You need fine-grained control over reads/writes |
| SFTP/CSV | Included (standard exports) | Medium | Medium | Batch operations, ERP sync, bulk data loads |
| iPaaS (Workato/Celigo) | $$$+/yr | Low | Partial | You need rapid setup, existing iPaaS investment |
| Make.com | $/yr | Low | Limited | Only need requisition approval workflows |
| GraphQL | Included | Low | Read-only | Complex read queries needing fewer API calls |
Given Orcha's focus on document ingestion, invoice processing, and accounting automation, the integration should cover the full invoice lifecycle:
Primary: Direct REST API integration (all endpoints included with Coupa license)
Ingest phase — Sync reference data from Coupa into Orcha:
GET /api/accounts — pull chart of accounts for validationGET /api/lookup_values — pull cost centers, GL codes, departmentsGET /api/suppliers — pull supplier master data for matchingupdated-at for delta syncPush phase — Write extracted invoice data back:
POST /api/invoices (or Inbound Invoice API) — create invoice from extracted dataPOST /api/lookup_values — create new cost centers if neededPOST /api/accounts — create new account code combinations if neededApproval phase — Trigger and manage workflows:
PUT /api/approvals/:id/approve or /reject — programmatic approvalTracking phase — Monitor lifecycle:
GET /api/invoices?status=...&updated-at[gt]=... — poll for status changesGET /api/coupa_pay/payments?... — track payment statusOne known limitation: Account Types (CoA structure) cannot be created via API — they must be pre-configured in the Coupa instance by the customer's admin. This is a one-time setup dependency.
What you'd need from the Coupa customer:
{tenant}.coupahost.com)COMPANY_CostCenter)