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):
| Origin | How to attach | Who 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_type | Description |
|---|---|
invoice | Invoice |
calculation_memory | Calculation memory |
contract | Contract |
bank_slip | Bank slip |
payment_receipt | Payment receipt |
evidence | Evidence |
settlement_term | Settlement term |
variance_justification | Justification for an amount difference |
extra_document | Additional document |
Document status
| Status | Description |
|---|---|
in_manual_analysis | Sent in Base64, awaiting QI Tech's analysis. |
valid | Accepted on approval of the expense or the analysis. |
invalid | Refused by QI Tech. |
canceled | Canceled. |
null | Registered through the two-step upload. |
Attach a document
| Profile | Host | Required permission |
|---|---|---|
| Manager | manager-api | Write |
| Consultant | consultant-api | Create and Edit Expenses or Submit Consolidations |
Base URL for each host: Environments (Hosts).
Path parameters
| Parameter | Type | Description |
|---|---|---|
fund_class_key | string | Fund class key (UUID). |
expense_key | string | Expense key (UUID). |
{
"name": "nfe_001234.pdf",
"document_type": "invoice",
"document_b64": "JVBERi0xLjQKJcOkw7zDtsOfCjIgMCBvYmoKPDwKL0xlbmd0aCAzIDAgUgo..."
}
{
"name": "nfe_001234.pdf",
"document_type": "invoice"
}
Body attributes
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Document name, up to 255 characters. |
document_type | string | Yes | Document type. See types. |
document_b64 | string | Conditional | File 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
{
"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"
}
{
"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>"
}
}
}
| Field | Type | Description |
|---|---|---|
name | string | Document name. |
document_key | string | Document key (UUID). |
expense_key | string | Expense key. |
document_type | string | Document type. |
status | string | in_manual_analysis on a Base64 upload; null on a two-step upload. |
upload_url.url | string | Only on a two-step upload: address the file must be sent to. |
upload_url.fields | object | Only 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
filefield, 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.
| Profile | Host | Required permission |
|---|---|---|
| Manager | manager-api | Read |
Base URL for each host: Environments (Hosts).
{
"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.
| Profile | Host | Required permission |
|---|---|---|
| Manager | manager-api | Read |
Base URL for each host: Environments (Hosts).
{
"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>"
}
| Field | Type | Description |
|---|---|---|
document_url | string | Pre-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.
| Profile | Host | Required permission |
|---|---|---|
| Manager | manager-api | Write |
| Consultant | consultant-api | Create and Edit Expenses or Submit Consolidations |
Base URL for each host: Environments (Hosts).
The document with status: canceled, in the structure of the list.
Errors
| Status | code | When it happens |
|---|---|---|
| 400 | EXP000069 | The fund class does not belong to the manager. |
| 400 | EXP000072 | Attachment: the expense, created by the manager or consultant, is in neither pending_submission nor pre_approved. |
| 400 | EXP000166 | The current consolidation analysis is under review (in_manual_analysis or pending_manager_approval). |
| 400 | EXP000136 | document_b64 is not valid Base64, or was omitted on an expense created by the manager or consultant. |
| 400 | EXP000137 | The file exceeds 20 MB. |
| 400 | EXP000144 | Cancellation: the expense is in neither pending_submission nor pre_approved. |
| 400 | QIT000001 | Invalid body: name or document_type missing, document_type outside the list or unexpected field. |
| 400 | QIT000011 | The consultant tried to attach a document to an expense calculated by QI Tech. |
| 403 | EXP000124 | The consultant has no active link with the fund. Usually consultant-api rejects the request earlier, with 401 (CIT000018). |
| 403 | EXP000156 | You did not create the expense (permission_type other than owner). On cancellation, it also applies to expenses calculated by QI Tech. |
| 404 | EXP000010 | The expense_key does not exist in that fund class (attach and cancel). |
| 404 | EXP000072 | Attachment: the expense, calculated by QI Tech, is canceled. |
| 404 | EXP000071 | The document_key does not exist for that expense. |
{
"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.