ERPSpan docs

Writes & batches

Create GP records via eConnect — idempotency, the write whitelist, and the unposted-batch reality.

Writes are POST /v1/{object} calls. Every write:

  • Requires an Idempotency-Key header. Retrying with the same key + body returns the stored 201 with header Idempotent-Replay: true and never re-executes.
  • Is disabled by default per connection per object. Enable it in the dashboard (Connections → Write access) or with PATCH /v1/connections/:id { "writeWhitelist": ["customers", …] }. Otherwise 403 WRITE_NOT_ENABLED. Requires the write scope; sandbox connections are read-only.
  • Requires Authorization: Bearer lb_…, X-Connection-Id, and X-Company.
  • Goes to GP only through eConnect, inside a transaction. A GP validation failure → 422 GP_VALIDATION with gpErrors[{ number, text, node, hint? }]; the whole document rolls back.
  • Sends and returns money as decimal strings (never floats).

Unposted-batch reality. Transaction writes (journal entries, AP/AR invoices, cash receipts, sales orders) land in an unposted batch — ERPSpan auto-creates a per-day batch (LBAPI-YYYYMMDD) and a human posts it in GP. Cash receipts additionally land unapplied. Master upserts (customers, vendors) are live on commit (no batch). Purchase orders land as new (no batch). Numbers that eConnect auto-assigns (journal entry, sales order, purchase order) are provisional until the batch is posted.

Master upserts (live on commit)

POST /v1/customers

{ id (req, ≤15), name (req), classId?, address?{ code, line1, line2, city, state, postalCode, country, contactPerson }, phone?, paymentTermsId?, salespersonId?, currencyId?, taxScheduleId?, inactive?, hold? }201 { id }. Bad classId422 (eConnect 305).

POST /v1/vendors

{ id (req, ≤15), name (req), checkName?, classId?, address?{ code, contactPerson, line1-3, city, state, postalCode, country }, phone?, paymentTermsId?, taxId?, status? (active|inactive|temporary) }201 { id }.

Transaction writes (unposted batch)

POST /v1/journal-entries

{ date (req, YYYY-MM-DD), reference?, lines (2..500) [{ accountNumber (req), debit?, credit?, description? }] }. Each line has exactly one of debit/credit (positive, ≤2 dp); Σdebit == Σcredit. → 201 { journalEntryNumber, batchId, status: "unposted" }. Unknown account → 422 (7).

POST /v1/ap-invoices

{ vendorId (req), vendorDocumentNumber (req), amount (req), date (req), dueDate?, purchasesAmount? (default = amount), description?, paymentTermsId? }201 { vendorDocumentNumber, batchId, status: "unposted" }. Unknown vendor → 422 (330).

POST /v1/ar-invoices

{ customerId (req), documentNumber (req), amount (req), salesAmount? (default = amount), date (req), description? }201 { documentNumber, batchId, status: "unposted" }. Unknown customer → 422 (4628).

POST /v1/cash-receipts

{ customerId (req), documentNumber (req), amount (req), date (req), checkNumber?, paymentType? (cash|check|creditCard) }201 { documentNumber, batchId, status: "unposted" } — lands unapplied. Unknown customer → 422 (4628).

POST /v1/sales-orders

{ type (order|invoice), docTypeId (req), customerId (req), date (req), customerPONumber?, siteId?, lines (≥1) [{ itemId (req), description?, quantity (req), unitPrice (req), extendedPrice? (default = quantity × unitPrice), siteId? }], subtotal? (default = Σ line extended), total? (default = subtotal) }201 { salesOrderNumber, type, batchId, status: "unposted" }. Unknown item → 422 (-101).

POST /v1/purchase-orders (a document, no batch)

{ vendorId (req), date (req), buyerId?, siteId?, lines (≥1) [{ itemId (req), quantity (req), unitCost (req), siteId?, promisedDate? }] }201 { purchaseOrderNumber, status: "new" }. Unknown item → 422 (-101); unknown vendor → 422 (330).

Reading the record back

Fetch the created record with the object's read endpoint — for example GET /v1/sales-orders/2:<salesOrderNumber> and …/lines, or GET /v1/purchase-orders/<purchaseOrderNumber> and …/lines.

On this page