Skip to main content

Expense documents

Attaches an invoice, calculation memory and other supporting documents to a fund expense, and lists, downloads or cancels the attached documents. The expense_key comes from expense retrieval. The invoice to consolidate the expense goes in the consolidation analysis: the invoice submission only considers the analysis documents.

How you attach depends on the expense origin (origin.origin_type):

OriginHow to attachWho attaches and when
Created by the manager or consultant (expense_contract, expense, reimbursement, rebate_fee)Base64 file in the body (document_b64).Only whoever created the expense (permission_type: owner), with the expense in pending_submission or pre_approved and the consolidation analysis not under review.
Calculated or registered by QI Tech (other origins)Base64 file in the body, or in two steps: the API registers the document and returns an upload URL, and you send the file directly to that URL.Only the manager, and not on a canceled expense.

The consultant attaches and cancels documents of the expenses it created. Listing and downloading the expense's documents is available only to the manager: the consultant sees the documents in documents when retrieving the expense and downloads those of the consolidation analysis.

Document types​

document_typeDescription
invoiceInvoice
calculation_memoryCalculation memory
contractContract
bank_slipBank slip
payment_receiptPayment receipt
evidenceEvidence
settlement_termSettlement term
variance_justificationJustification for an amount difference
extra_documentAdditional document

Document status​

StatusDescription
in_manual_analysisSent in Base64, awaiting QI Tech's analysis.
validAccepted on approval of the expense or the analysis.
invalidRefused by QI Tech.
canceledCanceled.
nullRegistered through the two-step upload.

Attach a document​

Available on
ProfileHostRequired permission
Managermanager-apiWrite
Consultantconsultant-apiCreate and Edit Expenses or Submit Consolidations

Base URL for each host: Environments (Hosts).

ENDPOINT
/expense/fund_class/{fund_class_key}/expense/{expense_key}/document
METHOD
POST

Path parameters​

ParameterTypeDescription
fund_class_keystringFund class key (UUID).
expense_keystringExpense key (UUID).
Request body — Base64 file
{
"name": "nfe_001234.pdf",
"document_type": "invoice",
"document_b64": "JVBERi0xLjQKJcOkw7zDtsOfCjIgMCBvYmoKPDwKL0xlbmd0aCAzIDAgUgo..."
}
Request body — two-step upload
{
"name": "nfe_001234.pdf",
"document_type": "invoice"
}

Body attributes​

FieldTypeRequiredDescription
namestringYesDocument name, up to 255 characters.
document_typestringYesDocument type. See types.
document_b64stringConditionalFile content in Base64, up to 20 MB. Required on expenses created by the manager or consultant. Without it, the API returns the URL for the two-step upload.

No other field is accepted.

Response​

STATUS
201
Response body — Base64 file
{
"name": "nfe_001234.pdf",
"document_key": "d4e5f6a7-b8c9-4123-def4-567890abcdef",
"expense_key": "b7f1c8e2-5a7d-4c7f-9a0e-2c3d4e5f6a7b",
"document_type": "invoice",
"status": "in_manual_analysis"
}
Response body — two-step upload
{
"name": "nfe_001234.pdf",
"document_key": "d4e5f6a7-b8c9-4123-def4-567890abcdef",
"expense_key": "3571e292-3a83-4011-904d-20ee963022ef",
"document_type": "invoice",
"status": null,
"upload_url": {
"url": "https://<link-temporario-de-envio>",
"fields": {
"key": "d4e5f6a7-b8c9-4123-def4-567890abcdef",
"policy": "<policy>",
"x-amz-algorithm": "AWS4-HMAC-SHA256",
"x-amz-credential": "<credential>",
"x-amz-date": "20261109T120000Z",
"x-amz-signature": "<signature>"
}
}
}
FieldTypeDescription
namestringDocument name.
document_keystringDocument key (UUID).
expense_keystringExpense key.
document_typestringDocument type.
statusstringin_manual_analysis on a Base64 upload; null on a two-step upload.
upload_url.urlstringOnly on a two-step upload: address the file must be sent to.
upload_url.fieldsobjectOnly on a two-step upload: fields that go along with the file. Send all of them, without changing names or values; the exact set may vary.

Two-step file upload​

Make a multipart/form-data POST to upload_url.url with:

  • all the fields from upload_url.fields;
  • the file in the file field, the last one in the form.

The URL expires in 10 minutes and accepts files of up to 50 MB. This call goes straight to storage, without QI Tech's authentication headers.

import requests

upload = response_body["upload_url"]

with open("nfe_001234.pdf", "rb") as arquivo:
resposta = requests.post(
upload["url"],
data=upload["fields"],
files={"file": arquivo},
)

resposta.raise_for_status()

A 204 response indicates the upload is complete. If the URL expires before the upload, attach the document again to get another one.

List documents​

Returns all of the expense's documents, in any status, without a download URL and without pagination. An expense_key that does not exist in the fund class returns an empty data, without an error.

Available on
ProfileHostRequired permission
Managermanager-apiRead

Base URL for each host: Environments (Hosts).

ENDPOINT
/expense/fund_class/{fund_class_key}/expense/{expense_key}/documents
METHOD
GET
Response body
{
"data": [
{
"name": "nfe_001234.pdf",
"document_key": "d4e5f6a7-b8c9-4123-def4-567890abcdef",
"expense_key": "b7f1c8e2-5a7d-4c7f-9a0e-2c3d4e5f6a7b",
"document_type": "invoice",
"status": "in_manual_analysis"
}
]
}

Retrieve a document by key​

Returns the document with a temporary link to download the file.

Available on
ProfileHostRequired permission
Managermanager-apiRead

Base URL for each host: Environments (Hosts).

ENDPOINT
/expense/fund_class/{fund_class_key}/expense/{expense_key}/document/{document_key}
METHOD
GET
Response body
{
"name": "nfe_001234.pdf",
"document_key": "d4e5f6a7-b8c9-4123-def4-567890abcdef",
"expense_key": "b7f1c8e2-5a7d-4c7f-9a0e-2c3d4e5f6a7b",
"document_type": "invoice",
"status": "valid",
"document_url": "https://<link-temporario-de-download>"
}
FieldTypeDescription
document_urlstringPre-signed URL to download the file, valid for 24 hours. The file is served as application/pdf, whatever the format sent. Retrieve it again to get another URL.

Cancel a document​

Marks as canceled a document of an expense you created, as manager or consultant (permission_type: owner). Allowed with the expense in pending_submission or pre_approved and the consolidation analysis not under review.

Available on
ProfileHostRequired permission
Managermanager-apiWrite
Consultantconsultant-apiCreate and Edit Expenses or Submit Consolidations

Base URL for each host: Environments (Hosts).

ENDPOINT
/expense/fund_class/{fund_class_key}/expense/{expense_key}/document/{document_key}
METHOD
DELETE
STATUS
200

The document with status: canceled, in the structure of the list.

Errors​

StatuscodeWhen it happens
400EXP000069The fund class does not belong to the manager.
400EXP000072Attachment: the expense, created by the manager or consultant, is in neither pending_submission nor pre_approved.
400EXP000166The current consolidation analysis is under review (in_manual_analysis or pending_manager_approval).
400EXP000136document_b64 is not valid Base64, or was omitted on an expense created by the manager or consultant.
400EXP000137The file exceeds 20 MB.
400EXP000144Cancellation: the expense is in neither pending_submission nor pre_approved.
400QIT000001Invalid body: name or document_type missing, document_type outside the list or unexpected field.
400QIT000011The consultant tried to attach a document to an expense calculated by QI Tech.
403EXP000124The consultant has no active link with the fund. Usually consultant-api rejects the request earlier, with 401 (CIT000018).
403EXP000156You did not create the expense (permission_type other than owner). On cancellation, it also applies to expenses calculated by QI Tech.
404EXP000010The expense_key does not exist in that fund class (attach and cancel).
404EXP000072Attachment: the expense, calculated by QI Tech, is canceled.
404EXP000071The document_key does not exist for that expense.
Example
{
"title": "Invalid Status For Expense Document",
"description": "Cannot create an expense document on an expense in status in_provision.",
"translation": "Nao e possivel criar um documento em uma despesa no status in_provision.",
"code": "EXP000072"
}

Authentication, permission and host errors: see API Errors.