PUT https://api.fire.rest/api/v1/fire/external/orders/EC-K000-KIOSK-0001
x-api-key: <your_api_key>
Content-Type: application/json
{
"expectedRevision": 1,
"idempotencyKey": "pos-loc-7f3a",
"additionalInfo": {
"orderCode": "82"
}
}
PUT https://api.fire.rest/api/v1/fire/external/orders/EC-K000-KIOSK-0001
x-api-key: <your_api_key>
Content-Type: application/json
{
"expectedRevision": 2,
"idempotencyKey": "pos-cli-9b21",
"client": {
"uid": "EnB3vmqHvrgarov6PFmfJY1bpPH2",
"name": "Comercial Andina",
"lastName": "SA",
"email": "facturas@andina.ec",
"govIdType": "RUC",
"govIdNumber": "1790012345001",
"billingInformation": {
"govIdType": "RUC",
"govIdNumber": "1790012345001",
"businessName": "Comercial Andina SA",
"email": "facturas@andina.ec",
"address": "Av. 9 de Octubre 123"
}
}
}
PUT https://api.fire.rest/api/v1/fire/external/orders/EC-K000-KIOSK-0001
x-api-key: <your_api_key>
Content-Type: application/json
{
"expectedRevision": 1,
"idempotencyKey": "pos-both-c410",
"additionalInfo": {
"orderCode": "82",
"kiosk": { "buzzer_name": "Mesa 4" }
},
"client": {
"uid": "EnB3vmqHvrgarov6PFmfJY1bpPH2",
"name": "Ana",
"lastName": "Pérez",
"govIdType": "CEDULA",
"govIdNumber": "1712345678"
}
}
{
"success": true,
"data": {
"orderId": "da670a2c-386d-4848-a51b-444738c3250b",
"orderCode": "EC-K000-KIOSK-0001",
"outcome": "applied",
"revision": 2,
"fields": ["kds"],
"changedColumns": ["metadata"],
"amendmentId": "24c523b3-a435-4cbb-b163-7a88c5b10d32",
"status": "OPEN",
"paymentStatus": "PENDING"
}
}
{
"success": true,
"data": {
"orderId": "da670a2c-386d-4848-a51b-444738c3250b",
"orderCode": "EC-K000-KIOSK-0001",
"outcome": "duplicate",
"revision": 2,
"fields": ["kds"],
"changedColumns": [],
"amendmentId": "24c523b3-a435-4cbb-b163-7a88c5b10d32",
"status": "OPEN",
"paymentStatus": "PENDING"
}
}
{
"success": true,
"data": {
"orderId": "da670a2c-386d-4848-a51b-444738c3250b",
"orderCode": "EC-K000-KIOSK-0001",
"outcome": "noop",
"revision": 2,
"fields": [],
"changedColumns": [],
"amendmentId": null,
"status": "OPEN",
"paymentStatus": "PENDING"
}
}
{
"success": false,
"error": "CONFLICT",
"code": "STALE_REVISION",
"message": "The order changed since you read it — refetch and retry",
"data": {
"orderId": "da670a2c-386d-4848-a51b-444738c3250b",
"orderCode": "EC-K000-KIOSK-0001",
"expectedRevision": 1,
"currentRevision": 2
}
}
{
"success": false,
"error": "CONFLICT",
"code": "ORDER_NOT_OPEN",
"message": "Order is closed and can no longer be updated",
"data": {
"orderId": "da670a2c-386d-4848-a51b-444738c3250b",
"orderCode": "EC-K000-KIOSK-0001",
"orderStatus": "COMPLETED"
}
}
{
"success": false,
"error": "CONFLICT",
"code": "ORDER_ALREADY_INVOICED",
"message": "Order already has a fiscal document in flight or authorized and cannot be updated",
"data": {
"orderId": "da670a2c-386d-4848-a51b-444738c3250b",
"orderCode": "EC-K000-KIOSK-0001",
"documentStatus": "authorized"
}
}
{
"success": false,
"error": "VALIDATION_ERROR",
"message": "Datos de entrada inválidos",
"details": [
{
"code": "custom",
"path": ["order"],
"message": "Products and totals cannot be updated yet — only client (fiscal data) and additionalInfo (locator) are accepted"
}
]
}
{
"success": false,
"error": "VALIDATION_ERROR",
"message": "Datos de entrada inválidos",
"details": [
{
"code": "invalid_type",
"path": ["client", "uid"],
"message": "client.uid is required — the client block replaces, it does not merge"
}
]
}
API
Update order
Corrects an open order before it is charged: the final consumer’s billing details and the locator. It does not charge, does not close the order and emits no events.
PUT
/
api
/
v1
/
fire
/
external
/
orders
/
{orderId}
PUT https://api.fire.rest/api/v1/fire/external/orders/EC-K000-KIOSK-0001
x-api-key: <your_api_key>
Content-Type: application/json
{
"expectedRevision": 1,
"idempotencyKey": "pos-loc-7f3a",
"additionalInfo": {
"orderCode": "82"
}
}
PUT https://api.fire.rest/api/v1/fire/external/orders/EC-K000-KIOSK-0001
x-api-key: <your_api_key>
Content-Type: application/json
{
"expectedRevision": 2,
"idempotencyKey": "pos-cli-9b21",
"client": {
"uid": "EnB3vmqHvrgarov6PFmfJY1bpPH2",
"name": "Comercial Andina",
"lastName": "SA",
"email": "facturas@andina.ec",
"govIdType": "RUC",
"govIdNumber": "1790012345001",
"billingInformation": {
"govIdType": "RUC",
"govIdNumber": "1790012345001",
"businessName": "Comercial Andina SA",
"email": "facturas@andina.ec",
"address": "Av. 9 de Octubre 123"
}
}
}
PUT https://api.fire.rest/api/v1/fire/external/orders/EC-K000-KIOSK-0001
x-api-key: <your_api_key>
Content-Type: application/json
{
"expectedRevision": 1,
"idempotencyKey": "pos-both-c410",
"additionalInfo": {
"orderCode": "82",
"kiosk": { "buzzer_name": "Mesa 4" }
},
"client": {
"uid": "EnB3vmqHvrgarov6PFmfJY1bpPH2",
"name": "Ana",
"lastName": "Pérez",
"govIdType": "CEDULA",
"govIdNumber": "1712345678"
}
}
{
"success": true,
"data": {
"orderId": "da670a2c-386d-4848-a51b-444738c3250b",
"orderCode": "EC-K000-KIOSK-0001",
"outcome": "applied",
"revision": 2,
"fields": ["kds"],
"changedColumns": ["metadata"],
"amendmentId": "24c523b3-a435-4cbb-b163-7a88c5b10d32",
"status": "OPEN",
"paymentStatus": "PENDING"
}
}
{
"success": true,
"data": {
"orderId": "da670a2c-386d-4848-a51b-444738c3250b",
"orderCode": "EC-K000-KIOSK-0001",
"outcome": "duplicate",
"revision": 2,
"fields": ["kds"],
"changedColumns": [],
"amendmentId": "24c523b3-a435-4cbb-b163-7a88c5b10d32",
"status": "OPEN",
"paymentStatus": "PENDING"
}
}
{
"success": true,
"data": {
"orderId": "da670a2c-386d-4848-a51b-444738c3250b",
"orderCode": "EC-K000-KIOSK-0001",
"outcome": "noop",
"revision": 2,
"fields": [],
"changedColumns": [],
"amendmentId": null,
"status": "OPEN",
"paymentStatus": "PENDING"
}
}
{
"success": false,
"error": "CONFLICT",
"code": "STALE_REVISION",
"message": "The order changed since you read it — refetch and retry",
"data": {
"orderId": "da670a2c-386d-4848-a51b-444738c3250b",
"orderCode": "EC-K000-KIOSK-0001",
"expectedRevision": 1,
"currentRevision": 2
}
}
{
"success": false,
"error": "CONFLICT",
"code": "ORDER_NOT_OPEN",
"message": "Order is closed and can no longer be updated",
"data": {
"orderId": "da670a2c-386d-4848-a51b-444738c3250b",
"orderCode": "EC-K000-KIOSK-0001",
"orderStatus": "COMPLETED"
}
}
{
"success": false,
"error": "CONFLICT",
"code": "ORDER_ALREADY_INVOICED",
"message": "Order already has a fiscal document in flight or authorized and cannot be updated",
"data": {
"orderId": "da670a2c-386d-4848-a51b-444738c3250b",
"orderCode": "EC-K000-KIOSK-0001",
"documentStatus": "authorized"
}
}
{
"success": false,
"error": "VALIDATION_ERROR",
"message": "Datos de entrada inválidos",
"details": [
{
"code": "custom",
"path": ["order"],
"message": "Products and totals cannot be updated yet — only client (fiscal data) and additionalInfo (locator) are accepted"
}
]
}
{
"success": false,
"error": "VALIDATION_ERROR",
"message": "Datos de entrada inválidos",
"details": [
{
"code": "invalid_type",
"path": ["client", "uid"],
"message": "client.uid is required — the client block replaces, it does not merge"
}
]
}
An order created at the kiosk and paid at the counter stays open until it is charged. In the
meantime the cashier may need to correct it: the customer asks for an invoice with their tax ID, or
the locator number printed on their ticket has to be entered. This endpoint corrects that data
without touching the payment.
Payment methods are not corrected here. If the body carries
No extra step is needed for the invoice to carry the corrected data. When the payment settles,
Fire builds the
Locator and kiosk —
Applied field by field: send only what changes. If you correct the locator, the buzzer name and
the invoice email stay as they were.
Final consumer —
From this block Fire recomputes the buyer printed on the receipt. You don’t need to send it
separately.
Keep the
All are
Use a new key for each different correction. Reusing a key for another change returns
Open orders only. An order that was charged, cancelled or already invoiced has already
produced its consequences and is not corrected retroactively.
Update order vs. Confirm payment
They are two separate endpoints on purpose. One corrects the order, the other charges it, and neither writes what belongs to the other.| Update order (this one) | Confirm payment | |
|---|---|---|
| Method | PUT /orders/{orderId} | POST /orders/{orderId}/confirm-payment |
| Purpose | change order data | record the money |
| What it writes | buyer and billing details, locator | payment methods, payment state |
| Changes the status? | no — the order stays OPEN | yes — becomes COMPLETED when settled |
| Emits events? | no | yes — order.completed |
| Records declines? | not applicable | yes — declined attempts are kept for your metrics |
| Idempotency | idempotencyKey | each tender’s transaction_id |
| Concurrency | expectedRevision | the charge is all-or-nothing against the total |
| How many times? | as many as needed, while it is open | once: settling closes the order |
payments.paymentMethods or a
status, the response is 400: the order status is derived from the payment and only
Confirm payment writes it. We reject it instead of ignoring it
because a silently dropped APPROVED would be money you consider collected and we don’t.
The full flow
GET /orders/{orderId} → revision: 1
PUT /orders/{orderId} expectedRevision 1 → revision: 2 (locator)
PUT /orders/{orderId} expectedRevision 2 → revision: 3 (billing details)
POST /orders/{orderId}/confirm-payment → COMPLETED + order.completed
order.completed event by reading the order at that moment, so it travels with your
latest correction.
Authentication
string
required
Your Fire API key with scope
orders:write. The key must be vendor-scoped — keys without a
vendorId are rejected with 403.Path params
string
required
Any of the order’s three public references:
It is the same set accepted by Get order and
Confirm payment.
| reference | what it is |
|---|---|
orders.id | Fire’s internal UUID |
order_external | the id you assigned when creating the order |
metadata.order_id | copy of the external id inside the order |
Body
Two control fields, always, plus one or more blocks. Whatever you don’t send is left untouched.integer
required
The order
revision you read with Get order. If the order changed
since then —another register corrected it—, the response is 409 STALE_REVISION and nothing is
written. That way two registers never overwrite each other unnoticed.string
required
A unique identifier per correction (up to 200 characters), generated by you. If the response
doesn’t reach you and you retry with the same key, you get
200 duplicate and the correction is
not applied twice.Without this key, a retry would collide with expectedRevision —which already moved— and you
couldn’t tell whether your correction went in or someone else wrote.Locator and kiosk — additionalInfo
Applied field by field: send only what changes. If you correct the locator, the buzzer name and
the invoice email stay as they were.
string
The locator: the number printed on the customer’s ticket and called out at pickup.
string
Name used to call the customer.
string
Email the invoice is sent to.
boolean
Whether the customer wants a printed invoice.
Final consumer — client
This block REPLACES the whole buyer. It is not a patch: whatever you don’t send ends up empty.
Sending
{ "uid": "…", "name": "Juan" } on an order that had a tax ID erases the tax ID.This is deliberate. Name, document and address are one piece of data: mixing a new name with
an old document produces a wrongly issued invoice, and that can only be fixed by voiding and
reissuing. Always send the complete buyer, not the difference.string
required
Customer identifier. Required precisely because the block replaces: without it the order would be
left without a customer. Use the one the order already has.
string
Document type:
CEDULA, RUC, PASAPORTE (Ecuador); CC, NIT (Colombia); CPF, CNPJ
(Brazil); or FINAL_CONSUMER.string
Document number. Dots, dashes and spaces are accepted; Fire strips them. A filler of repeated
digits (
9999999999999, 222222222222) is treated as final consumer.string
Name or company name.
string
Last name.
string
Buyer’s email.
object
The invoice recipient, and it takes precedence. Fire builds the receipt’s buyer by reading
billingInformation first (govIdType, govIdNumber, name —or businessName when name is
absent—, email, address) and
only then the client fields. It exists separately because the invoice can go to a company other
than the person.If you correct the document, put it here. Kiosk orders carry this block as final consumer:
correcting only client.govIdNumber and resending billingInformation unchanged leaves the
receipt as final consumer. If you don’t send it, it ends up empty and client is used.Products — not yet
Correcting products and totals is not enabled yet. If the body carries
order or payments,
the response is 400. It will be enabled once taxes and the total are also validated against the
lines, as they are when the order is created.Request
PUT https://api.fire.rest/api/v1/fire/external/orders/EC-K000-KIOSK-0001
x-api-key: <your_api_key>
Content-Type: application/json
{
"expectedRevision": 1,
"idempotencyKey": "pos-loc-7f3a",
"additionalInfo": {
"orderCode": "82"
}
}
PUT https://api.fire.rest/api/v1/fire/external/orders/EC-K000-KIOSK-0001
x-api-key: <your_api_key>
Content-Type: application/json
{
"expectedRevision": 2,
"idempotencyKey": "pos-cli-9b21",
"client": {
"uid": "EnB3vmqHvrgarov6PFmfJY1bpPH2",
"name": "Comercial Andina",
"lastName": "SA",
"email": "facturas@andina.ec",
"govIdType": "RUC",
"govIdNumber": "1790012345001",
"billingInformation": {
"govIdType": "RUC",
"govIdNumber": "1790012345001",
"businessName": "Comercial Andina SA",
"email": "facturas@andina.ec",
"address": "Av. 9 de Octubre 123"
}
}
}
PUT https://api.fire.rest/api/v1/fire/external/orders/EC-K000-KIOSK-0001
x-api-key: <your_api_key>
Content-Type: application/json
{
"expectedRevision": 1,
"idempotencyKey": "pos-both-c410",
"additionalInfo": {
"orderCode": "82",
"kiosk": { "buzzer_name": "Mesa 4" }
},
"client": {
"uid": "EnB3vmqHvrgarov6PFmfJY1bpPH2",
"name": "Ana",
"lastName": "Pérez",
"govIdType": "CEDULA",
"govIdNumber": "1712345678"
}
}
What Fire does with what you send
| situation | outcome | written? | revision |
|---|---|---|---|
| something changed | applied | yes | goes up by 1 |
same idempotencyKey as a previous correction | duplicate | no — returns what the original applied | the current one |
| you sent exactly what the order already had | noop | no | unchanged |
revision from the response: it is the one to send in your next correction.
When the order can’t be corrected
Each case has its own code, because each calls for a different action.| code | the order | what to do |
|---|---|---|
STALE_REVISION | changed since you read it | read it again and retry with the new revision (it comes in data.currentRevision) |
ORDER_NOT_OPEN | is no longer open | check data.orderStatus: COMPLETED = already charged with the previous data (what follows is a fiscal correction); CANCELLED or FORCE_CLOSED = nothing to correct |
ORDER_ALREADY_INVOICED | has an invoice issued or in progress | an invoice is not modified: it is voided and reissued |
409 and write nothing. The check happens at the same instant as the write, so if a
payment lands while you are correcting, one waits for the other: they never overwrite each other.
Idempotency and concurrency
Retrying is safe. If the response didn’t reach you, resend the same body with the sameidempotencyKey:
| what you send | what it is | response |
|---|---|---|
an idempotencyKey Fire already has | a retry | 200 duplicate |
a new key with the current revision | a new correction | 200 applied |
a new key with an old revision | another register wrote first | 409 STALE_REVISION |
duplicate and the new change is not applied.
Events
This endpoint emits no events. The correction stays on the order, and when it is charged, theorder.completed event carries the corrected data: locator, buyer
and billing details.
There is no
order.updated, on purpose. Event delivery is not ordered: a correction notice
arriving after order.completed would be a stale fact your system might act on by mistake.Validations
All return400 unless stated otherwise. Branch on the code, not on the text: the message may
be rewritten, the code is contract.
| rule | code |
|---|---|
expectedRevision is an integer greater than zero | 400 |
idempotencyKey present | 400 |
at least one block (client or additionalInfo) | 400 |
client.uid present if client is sent | 400 |
no order nor payments (products not yet) | 400 |
no payments.paymentMethods, status, paymentStatus, settlement, completedAt | 400 |
the body’s orderId, if sent, matches the URL’s | 400 |
| the body’s account, vendor and store, if sent, match the order | 400 |
| valid API key | 401 |
scope orders:write and vendor-scoped key | 403 |
| the order exists within your vendor | 404 |
| the reference matches more than one order | 409 AMBIGUOUS_ORDER_REFERENCE |
| the order hasn’t changed since you read it | 409 STALE_REVISION |
| the order is open (neither charged nor cancelled) | 409 ORDER_NOT_OPEN |
| the order has no invoice issued or in progress | 409 ORDER_ALREADY_INVOICED |
Responses
{
"success": true,
"data": {
"orderId": "da670a2c-386d-4848-a51b-444738c3250b",
"orderCode": "EC-K000-KIOSK-0001",
"outcome": "applied",
"revision": 2,
"fields": ["kds"],
"changedColumns": ["metadata"],
"amendmentId": "24c523b3-a435-4cbb-b163-7a88c5b10d32",
"status": "OPEN",
"paymentStatus": "PENDING"
}
}
{
"success": true,
"data": {
"orderId": "da670a2c-386d-4848-a51b-444738c3250b",
"orderCode": "EC-K000-KIOSK-0001",
"outcome": "duplicate",
"revision": 2,
"fields": ["kds"],
"changedColumns": [],
"amendmentId": "24c523b3-a435-4cbb-b163-7a88c5b10d32",
"status": "OPEN",
"paymentStatus": "PENDING"
}
}
{
"success": true,
"data": {
"orderId": "da670a2c-386d-4848-a51b-444738c3250b",
"orderCode": "EC-K000-KIOSK-0001",
"outcome": "noop",
"revision": 2,
"fields": [],
"changedColumns": [],
"amendmentId": null,
"status": "OPEN",
"paymentStatus": "PENDING"
}
}
{
"success": false,
"error": "CONFLICT",
"code": "STALE_REVISION",
"message": "The order changed since you read it — refetch and retry",
"data": {
"orderId": "da670a2c-386d-4848-a51b-444738c3250b",
"orderCode": "EC-K000-KIOSK-0001",
"expectedRevision": 1,
"currentRevision": 2
}
}
{
"success": false,
"error": "CONFLICT",
"code": "ORDER_NOT_OPEN",
"message": "Order is closed and can no longer be updated",
"data": {
"orderId": "da670a2c-386d-4848-a51b-444738c3250b",
"orderCode": "EC-K000-KIOSK-0001",
"orderStatus": "COMPLETED"
}
}
{
"success": false,
"error": "CONFLICT",
"code": "ORDER_ALREADY_INVOICED",
"message": "Order already has a fiscal document in flight or authorized and cannot be updated",
"data": {
"orderId": "da670a2c-386d-4848-a51b-444738c3250b",
"orderCode": "EC-K000-KIOSK-0001",
"documentStatus": "authorized"
}
}
{
"success": false,
"error": "VALIDATION_ERROR",
"message": "Datos de entrada inválidos",
"details": [
{
"code": "custom",
"path": ["order"],
"message": "Products and totals cannot be updated yet — only client (fiscal data) and additionalInfo (locator) are accepted"
}
]
}
{
"success": false,
"error": "VALIDATION_ERROR",
"message": "Datos de entrada inválidos",
"details": [
{
"code": "invalid_type",
"path": ["client", "uid"],
"message": "client.uid is required — the client block replaces, it does not merge"
}
]
}
Related
Get order
Read the
revision before correcting.Confirm payment
Charge the order once it is corrected.

