Creating Documents¶
This guide walks through the process of creating sales and purchase documents via the API.
Overview¶
The following endpoints support document creation:
| Endpoint | Document Type |
|---|---|
POST /invoices |
Sales invoices |
POST /orders |
Sales orders |
POST /receipts |
Receipts / payment confirmations |
POST /purchases |
Purchase / supplier invoices |
POST /purchase_orders |
Purchase orders |
POST /transfer_orders |
Stock transfer orders |
All document creation endpoints:
- Require a session token (
Authorization: Bearer <xa-token>) - Require a nonce query parameter
- Accept a JSON request body
- Return
201 Createdon success with adocumentCreatedresponse - Optionally return a PDF when
print=1is passed
Step-by-step: Creating an Invoice¶
1. Prepare the request body¶
A customerDocument object. Required fields: document_set, seq_number, date, currency, total_amount.
{
"document_set": "FT",
"seq_number": "FT2024/1002",
"date": "2024-11-15",
"currency": "EUR",
"net_amount": 1000.00,
"vat": 230.00,
"total_amount": 1230.00,
"payment_type": "Transferência Bancária",
"customer": {
"name": "Acme Corp",
"vat_id": "PT123456789",
"billing_address": {
"postal_address": "Rua da Liberdade 1",
"city": "Lisboa",
"zip_code": "1250-001",
"country": "PT"
}
},
"items": [
{
"item_code": "CONSULT",
"description": "Consulting Services — November 2024",
"qty": 2,
"unit_price": 500.00,
"vat": 23.0
}
]
}
2. Send the request¶
POST /api/03101176/v4.0.0/invoices?nonce=1700000000001
Authorization: Bearer <xa-token>
Content-Type: application/json
{ ... document body ... }
3. Handle the response¶
On 201 Created:
{
"id": 1002,
"documentSeries": "FT",
"documentNumber": "FT2024/1002",
"url": "https://gestix.pt/..."
}
On 400 Bad Request — check the apiError for the specific field causing the issue.
On 409 Conflict — a document with this document_set + seq_number already exists.
Getting a PDF¶
Pass print=1 to receive the PDF of the created document directly in the response body:
POST /api/03101176/v4.0.0/invoices?nonce=1700000000002&print=1
Authorization: Bearer <xa-token>
Content-Type: application/json
The response will have Content-Type: application/pdf and contain the PDF binary.
response = requests.post(url, params={"nonce": nonce, "print": 1}, ...)
if response.headers["Content-Type"] == "application/pdf":
with open("invoice.pdf", "wb") as f:
f.write(response.content)
Document Lines (items)¶
Each line item in the items array is a documentLine:
{
"item_code": "WIDGET-A",
"description": "Widget Type A",
"qty": 10,
"unit_price": 25.00,
"discount": 5.0,
"vat": 23.0,
"vat_included": false
}
descriptionis requireditem_codeis optional but links the line to a product in/articles- When
vat_includedistrue,unit_priceis treated as a gross (VAT-inclusive) price
Notes on Required Fields¶
| Field | Notes |
|---|---|
document_set |
Must match a document set configured in Gestix |
seq_number |
Must be unique within its document_set |
date |
Format: YYYY-MM-DD |
currency |
Must be a valid currency code (e.g., EUR) |
total_amount |
Must match the sum of line totals (server may validate) |
Creating Supplier Documents¶
The process is identical for POST /purchases and POST /purchase_orders, but the request body uses a supplierDocument schema — note the slight field name differences (related_doc vs related_document, source_warehouse instead of warehouse).
Example in Python¶
import requests
import time
BASE_URL = "https://gestix.pt:443/api/03101176/v4.0.0"
TOKEN = "your-session-token"
document = {
"document_set": "FT",
"seq_number": "FT2024/1003",
"date": "2024-11-15",
"currency": "EUR",
"total_amount": 246.00,
"customer": {"name": "Test Customer"},
"items": [
{
"description": "Test Item",
"qty": 1,
"unit_price": 200.00,
"vat": 23.0
}
]
}
nonce = int(time.time() * 1000)
response = requests.post(
f"{BASE_URL}/invoices",
params={"nonce": nonce},
headers={
"Authorization": f"Bearer {TOKEN}",
"Content-Type": "application/json"
},
json=document
)
if response.status_code == 201:
result = response.json()
print(f"Invoice created: {result['documentNumber']} (id={result['id']})")
else:
error = response.json()
print(f"Error: {error['code']} — {error['message']}")