Document sourceSystem / sourceSystemId pair constraint
Ondocuments, the check constraint documents_source_system_pair_nullity_chk requires both fields to be set or both to be null. Setting only sourceSystem without sourceSystemId fails with:
sourceSystemId alongside sourceSystem. If you don’t have a meaningful external id for a document, generate one (e.g. a UUID, or <your-system>_doc_<timestamp>).
Document upload: two-step presigned URL
Use the two-step presigned flow for document uploads — for carrier-invoice documents it’s the only path that runs AI classification: a combined orUNKNOWN PDF sent through an inline-base64 endpoint is filed but never classified or parsed, so nothing populates from it. The flow:
POST /api/rest/generate-upload-presigned-urlwith{ associationType, associationId, documentType, fileName, mimeType, sourceSystem, sourceSystemId }returns{ documentId, uploadUrl }.PUTthe file bytes directly touploadUrl.
Upload size limits
Inline base64 means sending the file encoded as text in the JSON request (for example,input.base64 on POST /api/rest/invoices/{invoiceId}/documents). It is a different mechanism from requesting a presigned URL and uploading raw bytes to S3.
Rate confirmations: customer vs. carrier
A customer rate confirmation and a carrier rate confirmation are two separate document types in Upwell — separatedocumentType values, separate parsers, and separate storage. Sending the correct one matters:
Type a carrier rate confirmation as
CARRIER_RATE_CONFIRMATION and a customer rate confirmation as CUSTOMER_RATE_CONFIRMATION. Each is AI-parsed on upload (through the two-step presigned flow above) by its own parser into its own storage, including the total rate. A document typed as one is never parsed, stored, or evaluated as the other.

