Skip to main content
An offline office (taquilla offline) is a physical point-of-sale that operates without a persistent internet connection. Tickets are pre-assigned to the office from the central platform, sold locally using the office’s own device, and then synchronised back when connectivity is restored.

Offline Ticket Lifecycle

1

Assign tickets to the offline office

Call offline_office_tickets with the list of ticket IDs, the office_id, and the event_id. The platform marks each ticket with status_offline = true and inserts records into the tickets_offline table, locking them from online sale.
2

Sell tickets locally

The office device uses offline_office_tickets_list_sales to display available inventory. Sales are recorded locally on the device.
3

Synchronise completed sales

Call offline_office_tickets_synchronization with the array of sold tickets. For each sold ticket, an order is created via the order_created callable function, replicating the sale in the central platform.
4

Return unsold tickets (optional)

Call offline_office_tickets_unassign to return unsold tickets to online availability. This clears status_offline, removes rows from tickets_offline, and appends an unassign entry to each ticket’s ledger.
Tickets assigned to an offline office are invisible to the virtual (online) sales office. The status_offline flag and the tickets_offline JOIN in sales queries enforce this separation.

Assign Tickets to Offline Office

offline_office_tickets transfers a set of available tickets to a specific offline office.
POST /offline_office_tickets
Content-Type: application/json
{
  "data": {
    "tickets_offline": [
      "JAOTIiQrtU1fMWZZY2IZ-nGxHQ00YzCg9PphEwlYb",
      "JAOTIiQrtU1fMWZZY2IZ-LqQTJHAGEkdwzrbcScWe"
    ],
    "office_id": "office_taquilla_norte",
    "event_id": "JAOTIiQrtU1fMWZZY2IZ"
  }
}
data.tickets_offline
array
required
Array of composite ticket IDs to assign. All tickets must be available (status = true) and not already assigned offline (status_offline = false). Any ticket failing either check causes the entire request to be rejected.
data.office_id
string
required
The identifier of the offline office receiving the tickets. Stored in tickets_offline.office_id.
data.event_id
string
required
The event these tickets belong to. Stored in tickets_offline.event_id.

What this does

  1. Validates that no ticket in the list is already sold or blocked.
  2. Writes status_offline = true and appends an offline ledger entry to each ticket in both Firestore and PostgreSQL.
  3. Inserts a row per ticket into tickets_offline with ticket_id, date_created, event_id, and office_id.
Success (200)
{
  "message": "Tickets Tranferido offline",
  "status": 200,
  "data": {
    "valido": true,
    "tickets": [
      "JAOTIiQrtU1fMWZZY2IZ-nGxHQ00YzCg9PphEwlYb",
      "JAOTIiQrtU1fMWZZY2IZ-LqQTJHAGEkdwzrbcScWe"
    ]
  }
}
Tickets unavailable (400)
{
  "message": "Tickets no disponibles",
  "status": 400,
  "data": {
    "valido": false,
    "nodisponible": ["JAOTIiQrtU1fMWZZY2IZ-nGxHQ00YzCg9PphEwlYb"]
  }
}

List Office Inventory

offline_office_tickets_list_sales returns the tickets assigned to a specific office for a specific event, with computed availability status.
POST /offline_office_tickets_list_sales
Content-Type: application/json
{
  "data": {
    "event_id": "JAOTIiQrtU1fMWZZY2IZ",
    "office_id": "office_taquilla_norte"
  }
}
data.event_id
string
required
The event to list inventory for.
data.office_id
string
required
The offline office to list inventory for. Uses an INNER JOIN on tickets_offline — only tickets explicitly assigned to this office are returned.

Response Fields

data.response
array
Array of ticket rows for this office. The query JOINs tickets with tickets_offline on t.id = tt.ticket_id.
data.response[].status
boolean
Computed: false if status_sold is set, true if raw status is true, otherwise false.
data.response[].ticket_id
string
The composite ticket ID.
data.response[].seat_id
string
The seat reference.
data.response[].zone
string
Zone name.
data.response[].color
string
Zone hex color.
Success (200)
{
  "message": "Tickets Encontrado para la Taquilla Offline",
  "status": 200,
  "data": {
    "valido": true,
    "response": [
      {
        "ticket_id": "JAOTIiQrtU1fMWZZY2IZ-nGxHQ00YzCg9PphEwlYb",
        "seat_id": "GEN5",
        "zone": "General",
        "color": "#4A90D9",
        "status": true,
        "event_id": "JAOTIiQrtU1fMWZZY2IZ"
      }
    ]
  }
}

Synchronise Completed Sales

offline_office_tickets_synchronization pushes locally-recorded sales from the offline device to the central platform. For each sold ticket in the payload, it invokes the order_created callable function to create a full order record.
POST /offline_office_tickets_synchronization
Content-Type: application/json
{
  "data": {
    "ticket_sold": [
      {
        "ticket": "JAOTIiQrtU1fMWZZY2IZ-nGxHQ00YzCg9PphEwlYb",
        "transactions": [ { "method": "cash", "amount": 25.00 } ],
        "amount": 25.00,
        "event_id": "JAOTIiQrtU1fMWZZY2IZ",
        "event_name": "Festival de Verano 2024",
        "office_id": "office_taquilla_norte",
        "office_name": "Taquilla Norte",
        "status": "completed",
        "tickets": ["JAOTIiQrtU1fMWZZY2IZ-nGxHQ00YzCg9PphEwlYb"],
        "client_id": "client_001",
        "client_name": "Carlos Martínez"
      }
    ]
  }
}
data.ticket_sold
array
required
Array of completed sale objects recorded locally by the offline device.
data.ticket_sold[].ticket
string
required
The composite ticket ID that was sold.
data.ticket_sold[].transactions
array
required
Array of transaction objects as recorded by the offline device (forwarded as-is to order_created).
data.ticket_sold[].amount
number
required
Total amount collected for this ticket.
data.ticket_sold[].event_id
string
required
The event ID.
data.ticket_sold[].event_name
string
required
The event display name.
data.ticket_sold[].office_id
string
required
The offline office that made the sale.
data.ticket_sold[].office_name
string
required
Display name of the offline office.
data.ticket_sold[].status
string
required
Order status string passed to order_created (e.g. "completed").
data.ticket_sold[].tickets
array
required
Array of ticket IDs included in this order (same as ticket for single-ticket orders).
data.ticket_sold[].client_id
string
required
The customer ID recorded by the offline device.
data.ticket_sold[].client_name
string
required
The customer name recorded by the offline device.
Success (200)
{
  "message": "Sincronizado",
  "status": 200,
  "data": { "valido": true }
}
Synchronisation calls order_created as a Firebase callable function via the Firebase client SDK. The response from order_created is not awaited per-item — the endpoint returns Sincronizado as soon as the iteration is dispatched.

Unassign (Return) Tickets

offline_office_tickets_unassign returns tickets from an offline office back to the online pool. Tickets not sold during the event can be released so they become available to other sales channels.
POST /offline_office_tickets_unassign
Content-Type: application/json
{
  "data": {
    "tickets_offline": [
      "JAOTIiQrtU1fMWZZY2IZ-LqQTJHAGEkdwzrbcScWe"
    ],
    "office_id": "office_taquilla_norte",
    "event_id": "JAOTIiQrtU1fMWZZY2IZ"
  }
}
data.tickets_offline
array
required
Array of composite ticket IDs to return to online availability.
data.office_id
string
required
The offline office releasing the tickets.
data.event_id
string
required
The event these tickets belong to.

What this does

  1. Sets status_offline = false on each ticket in both Firestore and PostgreSQL.
  2. Appends an unassign ledger entry to each ticket.
  3. Deletes the corresponding rows from tickets_offline.
Success (200)
{
  "message": "Tickets Tranferido online",
  "status": 200,
  "data": {
    "valido": true,
    "tickets": [
      "JAOTIiQrtU1fMWZZY2IZ-LqQTJHAGEkdwzrbcScWe"
    ]
  }
}

Full Event Sales View (Offline Context)

offline_tickets_list_event_sales returns all tickets for an event with computed availability status, including offline assignment state. This is the same query shape as the virtual office sales view and is used to give operators a complete picture of event inventory.
POST /offline_tickets_list_event_sales
Content-Type: application/json
{
  "data": {
    "event_id": "JAOTIiQrtU1fMWZZY2IZ"
  }
}
data.event_id
string
required
The event to query.

Response Fields

data.response[].status
boolean
Computed: false if blocked (status_d) or sold. true if neither condition holds.
data.response[].status_offline
boolean
true when the ticket is currently held by an offline office.
data.response[].status_real
boolean
Raw status value from tickets before block/offline evaluation.

Build docs developers (and LLMs) love