ERP charge sync LIVE
Pull consolidated charges out of OpenIRIS and post them into SAP, Oracle Fusion, NetSuite or Workday as journal entries — with a dedup fence, because your ERP probably doesn't have one.
Scope required: billing:read (covers reading charges and
recording exports).
The loop
- Pull new/changed charges since your last run.
- Transform each charge into your ERP's journal-entry shape (mapping below).
- Post it to the ERP.
- Acknowledge the export back to OpenIRIS with the ERP document number —
this is your dedup fence and flips the charge's status to
exported.
1. Pull — delta sync
GET /v1/charges?filter[created_at][gte]=2026-08-01T00:00:00Z&sort=created_at&limit=200
Page with links.next; persist the newest created_at you've seen
as the next run's watermark. To pull only what's not yet posted, add
filter[status]=invoiced (or unbilled, depending on where your
institution draws the "ready" line).
filter[updated_at][gte] exists,
but historical rows are still being backfilled — until the changelog announces completion,
updated_at-based delta sync under-reports. created_at is reliably
populated on every row.
A charge
{
"id": 98888864,
"source": "booking",
"source_id": 24722216,
"booking_id": 3416659,
"provider_id": 1300,
"user_id": 20117,
"group_id": 512,
"currency": "EUR",
"total": 215.0511,
"is_waived": false,
"invoice_id": 33,
"status": "invoiced",
"period_start": "2026-06-30T07:00:00Z",
"period_end": "2026-06-30T09:00:00Z",
"created_at": "2026-06-30T09:12:44.153Z",
"links": { "self": "…/v1/charges/98888864" }
}
idis a synthetic integer, stable and unique across charge sources — treat it as opaque.source+source_idcarry the domain identity (bookingorrequest).statuslifecycle:unbilled→invoiced→exported;waivedcharges are zeroed by the facility and should not be posted.currencyis ISO 4217. Amounts keep source precision — do not re-round before your ERP requires it.GET /v1/charges/{id}/line-itemsgives the per-usage breakdown when your posting is line-level.
2. Transform — SAP Journal Entry mapping
Target Journal Entry Post (API_JOURNALENTRYITEMBASIC) — OpenIRIS
charges are internal cost recovery, not supplier invoices. Oracle GL
Journal Batch / NetSuite Journal Entry / Workday Manual Journal follow the same shape.
| SAP field | Source | Notes |
|---|---|---|
CompanyCode | your config | Map provider → company code on your side |
PostingDate / DocumentDate | period_end or invoice_date | Watch fiscal-period cutoffs (below) |
DocumentReferenceID | charge id | ≤35 chars; your dedup key inside SAP |
GLAccount | your mapping table | Typically resource/provider → GL on your side |
CostCenter | cost_center.provider_code* | ≤10 alphanumeric — matches SAP's limit |
Amount + currency | total + currency | Debit user cost center, credit facility revenue GL |
* the collapsed cost_center object is part of the proposed contract — until it
ships, resolve codes via the cost-centers surface.
Fiscal periods: SAP posting periods close monthly. A delayed export can land in a closed period — decide whether late charges post to the original period date or the run date, and be consistent.
3–4. Post, then acknowledge
After the ERP accepts the entry, record the acknowledgement (note the
Idempotency-Key — required on all writes):
POST /v1/charges/98888864/exports
Idempotency-Key: 7f3a1c…
Content-Type: application/json
{ "external_system": "SAP", "external_id": "4900001234", "notes": "FY26 P06" }
201— recorded; the charge'sstatusbecomesexported.200— this (system, external id) pair was already recorded: your retry hit the fence, nothing double-posted. Carry on.409— the charge is waived; it should not have been posted.
GET /v1/charges/{id}/exports returns the full history — the audit answer to
"where did this charge land, and when?". On your next pull,
filter[status]=invoiced naturally excludes everything already exported.
Crash-safe ordering
Post to the ERP before acknowledging. If your job dies between the two, the next
run re-posts the charge — and SAP-side dedup on DocumentReferenceID (the charge
id you set in step 2) catches it. If you acknowledge first and die, the charge silently never
reaches the ERP. Post → acknowledge, always in that order.