Invoicing Flow
Summary
This page shows the invoicing leg of the Vertex API flow: how a client submits an invoice and
gets back a compliant e-invoice, once tax amounts are already known. Applies across Vertex's LatAm coverage:
The endpoints, call types, and webhook contract are the same regardless of country; only the
payload fields and the local tax authority differ.
Key things to know before reading the diagram:
- Invoices are issued one by one, not in bulk. Each
POST /invoicescall submits exactly
one invoice. There is no batch-submission endpoint — if you need to issue 500 invoices, that's
500 separate calls. - Your systems always initiate the request. Vertex only calls you back once, via webhook, to
confirm the outcome. - The webhook — not the sync response to
POST /invoices— is what tells you whether the
invoice actually succeeded. The sync response only confirms the request was well-formed. - You can implement a polling fallback. If by any change you don't receive the webhook, poll GET /invoices/{invoice_id} until the invoice reaches a final status. See If the webhook doesn't arrive.
Call sequence
sequenceDiagram
autonumber
participant Client
participant Vertex
participant Auth as Tax Authority
Client->>Vertex: POST /invoices
Vertex-->>Client: 201 status "received" / 400-500 schema error
rect rgba(168,118,15,0.08)
Note over Vertex,Auth: async backend — no client-facing call
Vertex->>Auth: transmit invoice to the local tax authority
Auth-->>Vertex: accept / reject
end
rect rgba(46,125,82,0.09)
Note over Client,Vertex: Scenario: created invoice
Vertex--)Client: webhook — status: created
Client->>Vertex: GET /invoices/{invoice_id}
Vertex-->>Client: invoice_key, documents, country fields
end
rect rgba(178,58,58,0.09)
Note over Client,Vertex: Scenario: failed invoice
Vertex--)Client: webhook — status: failed
end
Every call above the shaded amber band is client-initiated and synchronous. Inside that band,
Vertex talks to the local tax authority with no client visibility. The webhook is the only call
Vertex initiates, and it always carries one of exactly two outcomes — created or failed —
shown above as two mutually exclusive scenarios. created ends after the GET in step 5;
failed ends at the webhook itself.
If the webhook doesn't arrive
The webhook is the primary way to learn an invoice's outcome, but your integration should not
depend on it alone. If the webhook hasn't arrived after the expected time, implement a
short-polling fallback: call GET /invoices/{invoice_id} on an interval until the invoice
reaches a final status.
How it works
- Store the
idreturned in the201response ofPOST /invoices(or use your own
invoice_external_idwith?use_external_id=true). - Wait for the webhook. If it arrives, stop: no polling needed.
- If it hasn't arrived after the initial wait for that country, call
GET /invoices/{invoice_id}and checkstatus:
status | Meaning | What to do |
|---|---|---|
received | Still being processed by the tax authority. | Not final. Wait and poll again. |
created | Accepted by the tax authority. | Final. Use invoice_key, pdf_url / xml_url and country fields from this same response. Stop polling. |
failed | Rejected by the tax authority. | Final. Read the errors, fix the payload, and submit a new invoice. Stop polling. |
- Keep polling with increasing intervals (backoff) until you get
createdorfailed, or
until you reach your maximum wait time. If the invoice is stillreceivedafter that,
contact Vertex support with theinvoice_id.
Best practices
- Don't resubmit while
received. Sending the same invoice again withPOST /invoices
can create a duplicate document at the tax authority. Only submit a new invoice after afailedstatus. - Polling is a fallback, not a replacement. Keep the webhook as your main signal; poll
only for invoices whose webhook hasn't arrived in time.
Example
curl --request GET \
--url https://api.brinta.com/invoices/36bc8191-3011-41ec-8e0b-2c00462ad955 \
--header 'Authorization: Bearer <token>'Still processing:
{
"id": "36bc8191-3011-41ec-8e0b-2c00462ad955",
"invoice_external_id": "53987482cdvjb48h",
"status": "received",
"status_description": "The invoice request has been received."
"..."
}Final (accepted):
{
"id": "36bc8191-3011-41ec-8e0b-2c00462ad955",
"invoice_external_id": "53987482cdvjb48h",
"status": "created",
"status_description": "The invoice is created.",
"invoice_key": "75452644088340",
"pdf_url": "https://...",
"..."
}Step reference
endpoints as called against api.brinta.com
| # | Endpoint | Direction | Type | Notes |
|---|---|---|---|---|
| 1 | POST /invoices | Client → Vertex | SYNC | Submit invoice. Sync response is a schema check only: valid → status: received (201); invalid → 400/500. |
| 2 | — | Vertex → Tax Authority | ASYNC | Vertex transmits the invoice to the local tax authority. |
| 3 | — | Tax Authority → Vertex | ASYNC | Authority accepts or rejects. |
| 4 | Webhook | Vertex → Client | WEBHOOK | The only call Vertex initiates. Payload: invoice_id, invoice_external_id, status. 2 possible outcomes: created (tax authority accepted) or failed (rejected). For rejected invoices, errors will be sent in the webhook body |
| 5 | GET /invoices/{invoice_id} | Client → Vertex | SYNC | Only when step 4's status is created — a failed webhook is terminal, there's nothing to fetch. Works with invoice_id, or with invoice_external_id by adding ?use_external_id=true (docs). Returns invoice_key, documents (PDF/XML or country equivalent), and country-specific fields.If invoice_external_id is used, then use param array=true to return an array of every invoice with that invoice_external_id (maximum 20) instead of one invoice. |
Vertex API · api.brinta.com — request examples: Postman collection
Updated 10 days ago
