Developers

API error codes

Every failure from the OPDC API for Sage 100 Contractor is a problem document (RFC 9457) whose type names one of these codes, which is also sent as the X-Error-Code header. Codes are append-only: a code's spelling and meaning never change once published. How errors work, and what to retry.

CodeStatusMeaning
UNAUTHORIZED401Missing, malformed or unknown API key.
FORBIDDEN403The key authenticated but may not do what was asked: on a read, the request names a field this key may not read (sensitive, personal or pay data).
SERVICE_DISABLED503The key is switched off by Twinn.
MAINTENANCE_LOCK423The operator-held maintenance lock.
LOCK_CONFLICT409An unlock attempt against a lock another user holds.
REQUEST_INVALID400Unreadable or unparseable request body.
HEADER_INVALID400A correlation header that is present but not a UUID.
CHANGE_STAMP_UNSUPPORTED501lastUpdated or createdSince named on an entity that has no such column.
UPSTREAM_TIMEOUT504No reply from the on-premise service inside the window.
SCRIPT_NOT_FOUND500A route with no script in the store: a deployment fault, never the caller's.
RESPONSE_INVALID500A reply from the on-premise service that did not fit the expected envelope.
INTERNAL_ERROR500The default.
IDEMPOTENCY_KEY_REUSED409Same Idempotency-Key, different request: a different request fingerprint, or the same body on a different route.
IDEMPOTENCY_KEY_IN_FLIGHT409A request with this Idempotency-Key is still in progress.
IDEMPOTENCY_KEY_INVALID400Idempotency-Key empty, over 128 characters, or carrying non-printable characters.
PERIOD_CLOSED422The target period is beyond the ledger's current period, or outside the postable window.
PERIOD_UNRESOLVED422A posting date that could not be resolved to a period or year at all.
LEDGER_SETUP_MISSING422The ledger setup could not be read: the ledger is not set up, or the connected schema is not the intended one.
JOURNAL_UNBALANCED422Debits do not equal credits.
JOURNAL_EMPTY422A journal with no lines.
JOURNAL_LINE_INVALID422A line missing something structural, typically an account.
DUPLICATE_TRANSACTION409A transaction number already posted with different lines.
LEDGER_ACCOUNT_UNKNOWN422An account number that does not exist in the chart of accounts.
JOURNAL_ALREADY_VOID409The journal being voided is already void.
JOURNAL_NOT_VOIDABLE422The journal cannot be voided: it has cleared the bank, its status moved no balance, or it has no lines.
SUBACCOUNT_REQUIRED422A line on an account that tracks subaccounts or departments, sent with no subaccount, or with one that does not belong to that account.
REVERSAL_NOT_ALLOWED422A journal asked to reverse in the next period that cannot be: only a journal entry (source 3) posted Open can be reversed.
SUBCONTRACT_NOT_FOUND422No subcontract has the number an AP invoice names.
SUBCONTRACT_REFUSED422An AP invoice names a subcontract whose status is Refused.
SUBCONTRACT_MISMATCH422An AP invoice names a subcontract of another vendor, or on another job.
SUBCONTRACT_LINE_REQUIRED422A line of an AP invoice that bills a subcontract names no subcontract line.
SUBCONTRACT_LINE_NOT_FOUND422A line names a subcontract line that is not on the subcontract or has no line reference, or names one with no subcontract on the invoice.
CHANGE_NUMBER_REQUIRED422No change number was sent and the job's last one is not a number Sage's NEXT can increment.
REQUESTED_PRICE_MISMATCH422A prime line's requested price disagrees with the price its estimate and markups give.
SUBCONTRACT_NOT_OPEN422A change line names a subcontract that is not for the order's job and phase and the line's vendor, or is not status 3, 4 or 5.
CHANGE_ORDER_CLOSED409An update to a change order whose status is Void or Rejected, which Sage never saves again.
CHANGE_ORDER_LOCKED409An update to a change order locked for editing that does not unlock it.
CREDIT_CARD_INVALID422A credit card receipt names a card issuer that is not a card issuer account or is inactive, or a card that is not an active card of that issuer.
RECEIPT_EXCEEDS_ORDER422A purchase-order receipt that receives more than a line has left to receive (ordered, less already received and cancelled), or that names a line that is not on the purchase order.
RECEIPT_STATUS_NOT_ALLOWED422A purchase-order receipt against an order that is Void or a Master, or whose status the order cannot be left at.
INSUFFICIENT_INVENTORY422An inventory allocation that would take more of a part out of a location than is available there.
COST_LAYERS_SHORT422A document that takes more of a part out of stock than the part's cost layers hold.
TAX_LIMIT_TYPE_UNSUPPORTED422A tax entity of the document's tax district limits its tax across the job's, location's or client's earlier invoices, which is not supported yet.
TAX_EDITION_UNSUPPORTED422The company has Canadian sales tax set up, which is not supported yet.
DOCUMENT_POSTED409An update to a document that can no longer be changed in place: a purchase order that is closed, void or a master order.
DOCUMENT_CHANGED412An update whose If-Match is not the document's current version: it was changed, through this API or in Sage, after it was read.
QUANTITY_BELOW_RECEIVED422A purchase-order update that would order less on a line than the line has already received, or remove a line that has received anything.
INVOICE_NOT_OPEN422A cash receipt applied to an invoice that is not open: it is paid or void.
RECEIPT_EXCEEDS_BALANCE422A cash receipt that pays more than an invoice's balance, or takes more discount than the invoice has available.
SERVICE_INVOICE_NOT_POSTABLE422A service invoice whose totals or status do not permit a GL post.
PAYROLL_BATCH_EMPTY422A payroll batch carrying no checks.
PAYROLL_CHECK_INVALID422A check that failed the arithmetic or rate checks.
PAYROLL_EARNING_UNSUPPORTED422An earning whose payType is outside Sage's 1-9.
PAYROLL_DEDUCTION_INVALID422A deduction with no calculation number, which would post to the GL but not the subledger.
INVOICE_STATUS_NOT_ALLOWED422A new AP invoice at a status it cannot be entered at.
RETENTION_INVALID422An AP invoice's retention is negative, more than the invoice total, or set on a credit (a negative total).
INVOICE_AMOUNT_MISMATCH422An AP invoice sent an invoiceBalance or invoiceNet that is not the value the invoice computes: the balance is the invoice total and the net is the total less retention.
EQUIPMENT_COST_INVALID422An AP invoice line names equipmentNumber but cannot be costed to it: it has no accountNumber, its account is not an equipment expense account, it has no costCode, no cost type can be found for it, or the equipment is inactive.
ATTACHMENTS_DISABLED403File attachments are not turned on for this API key, or its setting could not be checked.
ATTACHMENTS_OFF_AT_SITE403The company's on-premise service has file attachments switched off.
ATTACHMENTS_UNAVAILABLE503File attachments cannot run just now.
ATTACHMENTS_NOT_ALLOWED_BY_SAGE422Sage's own file attachment settings do not allow a copied file for the record's module.
ATTACHMENT_EXPIRED410The file was gone when the on-premise service went to fetch it: a file is kept at most 30 minutes.
ATTACHMENT_CORRUPT502The file's size or SHA-256 did not match on its way between this API and the on-premise service.
RECORD_NOT_FOUND404A referenced record does not exist.
FIELD_REQUIRED400A required input field was absent or empty.
FIELD_INVALID400A field was present but its value does not satisfy the field's rule.
NOT_IMPLEMENTED501A route that exists but is deliberately not wired up.
INVOICE_NOT_PAYABLE422A payment names an invoice that cannot be paid: another vendor's invoice, one already paid or void, or one held for review or dispute.
PAYMENT_EXCEEDS_BALANCE422A payment's amount and discount on an invoice come to more than the invoice's payable balance: its net due, or its balance including held retention when the application sets includeRetention.
BANK_ACCOUNT_NOT_CASH422A payment drawn on a ledger account that is not a cash account.
VENDOR_CERTIFICATE_EXPIRED422A payment to a vendor with a stop-pay certificate that expired on or before the payment date, vendor-wide or for the job of an invoice being paid.
INVOICE_SET_TO_PAY409A payment names an invoice that a Sage user has staged for payment in Sage, so Sage's own next check run could pay it a second time.
SECOND_PAYEE_UNSUPPORTED422A payment names an invoice with a second payee (a two-party check).
CREDIT_NOT_APPLICABLE422A payment's credit row is not an open credit of the vendor, or its credits come to more than the invoices they offset.
PERIOD_BEFORE_INVOICE422An AP payment or a cash receipt posts to a period before the period of an invoice it pays.
DAILY_PAYROLL_LINE_INVALID422A daily payroll line Sage would refuse to save.
TIMECARDS_NOT_CREATED422Create Timecards was refused before anything was written.
VALIDATION_FAILED400Report criteria that do not satisfy the report's declared parameters.
REPORT_NOT_FOUND404A report id the catalogue does not list.
REPORT_ROW_LIMIT422The report read more rows than its row ceiling.
REPORT_RESULT_TOO_LARGE422The report's result is larger than a result may be.
SERVICE_CAPABILITY_MISSING501The on-premise agent for this company does not support what was asked, such as a report or a match lookup.
JOB_NOT_FOUND404A report job id this API does not hold: never issued, another customer's, or past its retention.
JOB_NOT_DONE409The job's result was requested before the job finished.
SAGE_SCHEMA_MISMATCH422A column or table the script expected and this Sage build does not have.
SAGE_FOREIGN_KEY_VIOLATION422A referenced record does not exist in Sage, or the write would orphan a child row: SQL Server Msg 547, a foreign key or reference constraint.
SAGE_DUPLICATE_KEY409The record already exists in Sage: Msg 2627 (a PRIMARY KEY or UNIQUE constraint) or Msg 2601 (a unique index).
SAGE_NOT_NULL_VIOLATION422A column this Sage build requires received no value: Msg 515, NOT NULL.
SAGE_RULE_VIOLATION422Sage's own enforcement refused the write.
SAGE_ERROR502Any other database-side failure: a deadlock, a permission, a dropped connection.
SCRIPT_FAILED500A script that failed in a way with no more specific code.
COMPANY_LOCKED423The company is not taking requests right now, and nothing was executed.
MESSAGE_TOO_LARGE413The request or its reply is larger than this API key allows.
QUEUE_UNAVAILABLE503The request could not be queued for the on-premise agent.
HOST_UPGRADE_REQUIRED503The company's on-premise agent speaks a protocol version older than this API supports.
KEY_STORE_UNAVAILABLE503The API key could not be checked just now.
KEY_WRONG_ENVIRONMENT401The API key was issued for a different environment (production, QA or local dev) than the API it was sent to.
REQUEST_EXPIRED503A write that could not start before its start-by deadline.
OUTCOME_UNKNOWN500The write may or may not have committed, and the service cannot tell which.
REQUEST_CANCELLED409The write was cancelled before it started.
REQUEST_ALREADY_COMPLETED409A cancel for a request that already has its outcome.
REQUEST_ALREADY_STARTED409A cancel for a write that had already started.
MCP_KEY_REFUSED403The API key is not an MCP connection key.
AUTHORIZATION_UNAVAILABLE503What this MCP connection may see could not be checked just now.
RATE_LIMITED429This API key sent more requests of this kind (reads, writes, report submissions or MCP calls) than its rate limit allows.
COMPANY_READ_ONLY403The company is set up read-only: Twinn reads its data and never changes it, so every write is refused.
UPSTREAM_UNAVAILABLE503The on-premise agent cannot reach the company's Sage database just now: it is waiting for the database server to answer, or it has stopped serving the company until the database or its sign-in is fixed.