Skip to main content

Contract document

The contract PDF is uploaded in two steps:

  1. Get the upload URL from the API.
  2. Upload the file straight to that URL.

Document rules:

  • Upload a PDF without a password, as the automated reading requires.
  • With signature_method: external, upload the contract already signed.
  • While the contract is in pending_submission, a new upload replaces the previous one.
  • On submission for review, the document is frozen and can no longer be replaced.

Get upload URL​

Available on
ProfileHostRequired permission
Managermanager-apiWrite
Consultantconsultant-apiCreate Expense Contracts

Base URL for each host: Environments (Hosts).

ENDPOINT
/expense_contract/fund_class/{fund_class_key}/contract/{contract_key}/document/upload_url
METHOD
GET

Path parameters​

ParameterTypeDescription
fund_class_keystringFund class key (UUID).
contract_keystringContract key (UUID).

Response​

STATUS
200

The contract, in the structure described in contract attributes, with the additional field upload_url.

Response excerpt
{
"contract_key": "3f2b8c1e-7d4a-4e9b-9a61-0c5d2e8f4b17",
"status": "pending_submission",
"upload_url": {
"url": "https://<link-temporario-de-envio>",
"fields": {
"key": "3f2b8c1e-7d4a-4e9b-9a61-0c5d2e8f4b17_draft",
"x-amz-algorithm": "AWS4-HMAC-SHA256",
"x-amz-credential": "<credential>",
"x-amz-date": "20261109T141000Z",
"x-amz-security-token": "<token>",
"policy": "<policy>",
"x-amz-signature": "<signature>"
}
}
}
FieldTypeDescription
upload_url.urlstringAddress the file must be sent to.
upload_url.fieldsobjectFields that go along with the file. Send all of them, without changing names or values. Do not hard-code the list of fields: the exact set may vary.

Upload the file​

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

  • Include all the fields from upload_url.fields.
  • Put the file in the file field, the last one in the form.
  • Do not send the QI Tech authentication headers: this call goes straight to storage.

The URL expires in 3 minutes and accepts files up to 50 MB.

import requests

upload = response_body["upload_url"]

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

resposta.raise_for_status()

A 204 response means the upload is complete. There is no confirmation call: the API only checks the document on submission for review. If the URL expires, request another one.

To check the uploaded file, download it through download_url in the contract retrieval.

Errors​

StatuscodeWhen it happens
404ECT000005The fund class does not exist or you do not have access to it.
404ECT000009The contract does not exist in this fund class.
409ECT000017The contract is not in pending_submission: the document has already been frozen and cannot be replaced.
409ECT000046The contract was created by QI Tech during fund structuring and does not accept this call.

Authentication, permission and host errors: see API Errors.

Next step​

Submission for review: submit the contract for QI Tech review.