Skip to content

Offline Ticket API Specification

Overview

The Offline Ticket API provides endpoints for managing pre-purchased attraction tickets. It covers the full lifecycle: defining attractions, uploading ticket batches from PDF files, configuring extraction patterns, selling tickets (with Telr payment integration), downloading ticket PDFs, and reporting on inventory and sales.

Base Path: /offline

Content Types: - Request: application/json (most endpoints) or multipart/form-data (upload/analyze endpoints) - Response: application/json

Response Format

All endpoints return a TlinqApiResponse object:

{
  "apiStatus": {
    "errorCode": "OK",
    "errorMessage": "Success"
  },
  "apiData": { ... }
}

Date Format: All dates use yyyy-MM-dd format.

Binary download endpoints (ticket/download, sale/merge-download) return application/pdf on success, or a JSON error response on failure.


Endpoints

Attraction Management

POST /offline/attraction/list

Lists all offline attractions. Optionally filters to active-only.

Roles: agent, admin

Request Body:

Field Type Required Description
session string No User session token
activeOnly boolean No If true, only return active attractions

Request Example:

{
  "session": "",
  "activeOnly": true
}

Response: Array of COfflineAttraction objects.

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": [
    {
      "attractionId": 1,
      "name": "Dubai Aquarium",
      "odooProductCode": "DXBAQ-001",
      "supplier": "Emaar Entertainment",
      "categories": "Adult,Child",
      "ageGroups": "Adult,Child (3-12)",
      "hasTimeSlots": true,
      "notes": "Main entrance tickets",
      "active": true,
      "createdAt": "2026-01-15",
      "updatedAt": "2026-01-20"
    }
  ]
}

POST /offline/attraction/read

Reads a single attraction by ID.

Roles: agent, admin

Request Body:

Field Type Required Description
session string No User session token
attractionId integer Yes Attraction ID

Response: Single COfflineAttraction object.


POST /offline/attraction/write

Creates or updates an attraction. Omit attractionId to create; include it to update.

Roles: admin

Request Body:

Field Type Required Description
session string No User session token
attractionId integer No Attraction ID (omit for create)
name string Yes Attraction name
odooProductCode string Yes Odoo product code for invoicing
supplier string No Supplier name
categories string No Comma-separated ticket categories (e.g. "Adult,Child")
ageGroups string No Comma-separated age groups (e.g. "Adult,Child (3-12)")
hasTimeSlots boolean No Whether tickets have time slots
notes string No Internal notes

Request Example:

{
  "session": "",
  "name": "Dubai Aquarium",
  "odooProductCode": "DXBAQ-001",
  "supplier": "Emaar Entertainment",
  "categories": "Adult,Child",
  "ageGroups": "Adult,Child (3-12)",
  "hasTimeSlots": true
}

Response: The saved COfflineAttraction object.


POST /offline/attraction/delete

Deactivates an attraction (soft delete).

Roles: admin

Request Body:

Field Type Required Description
session string No User session token
attractionId integer Yes Attraction ID to deactivate

Response:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": "Attraction deactivated"
}

Pattern Analysis

These endpoints manage the regex-based extraction patterns used to parse ticket data from uploaded PDFs.

POST /offline/attraction/patterns/analyze

Analyzes a sample PDF to auto-detect extraction patterns for an attraction. Uses multipart/form-data.

Roles: admin

Multipart Fields:

Field Type Required Description
session string No User session token
attractionId integer Yes Attraction ID
samplePdf file Yes Sample PDF file to analyze

Response: ExtractionPatterns object with detected regex patterns.

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": {
    "serialPattern": "Ticket No[.:]?\\s*(\\S+)",
    "datePattern": "Valid Date[:]?\\s*(\\d{2}/\\d{2}/\\d{4})",
    "dateFormat": "dd/MM/yyyy",
    "dateType": "ticket_date",
    "timeSlotPattern": "Time[:]?\\s*(\\d{2}:\\d{2})",
    "categoryPattern": "Category[:]?\\s*(\\w+)",
    "barcodePattern": "\\b\\d{12,13}\\b"
  }
}

POST /offline/attraction/patterns/save

Saves extraction patterns for an attraction.

Roles: admin

Request Body:

Field Type Required Description
session string No User session token
attractionId integer Yes Attraction ID
serialPattern string No Regex for ticket serial number
datePattern string No Regex for date extraction
dateFormat string No Date format string (e.g. "dd/MM/yyyy")
dateType string No Date semantics: "ticket_date" or "valid_until"
timeSlotPattern string No Regex for time slot extraction
categoryPattern string No Regex for ticket category
barcodePattern string No Regex for barcode extraction

Response:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": "Patterns saved successfully"
}

POST /offline/attraction/patterns/test

Tests extraction patterns against sample text without saving.

Roles: admin

Request Body:

Field Type Required Description
session string No User session token
sampleText string Yes Raw text to test patterns against
serialPattern string No Regex for ticket serial number
datePattern string No Regex for date extraction
dateFormat string No Date format string
dateType string No Date semantics
timeSlotPattern string No Regex for time slot extraction
categoryPattern string No Regex for ticket category
barcodePattern string No Regex for barcode extraction

Response: ExtractionResult object with matched values.


Campaign Management

POST /offline/campaign/list

Lists all ticket campaigns.

Roles: agent, admin

Request Body:

Field Type Required Description
session string No User session token

Response: Array of CTicketCampaign objects.


POST /offline/campaign/read

Reads a single campaign by ID.

Roles: agent, admin

Request Body:

Field Type Required Description
session string No User session token
campaignId integer Yes Campaign ID

Response: Single CTicketCampaign object.


POST /offline/campaign/write

Creates or updates a campaign. Omit campaignId to create.

Roles: admin

Request Body:

Field Type Required Description
session string No User session token
campaignId integer No Campaign ID (omit for create)
name string Yes Campaign name
startDate string No Start date (yyyy-MM-dd)
endDate string No End date (yyyy-MM-dd)
description string No Campaign description

Response: The saved CTicketCampaign object.


Batch Management

POST /offline/batch/list

Lists ticket batches, optionally filtered by attraction.

Roles: agent, admin

Request Body:

Field Type Required Description
session string No User session token
attractionId integer No Filter by attraction ID

Response: Array of CTicketBatch objects.


POST /offline/batch/read

Reads a single batch by ID.

Roles: agent, admin

Request Body:

Field Type Required Description
session string No User session token
batchId integer Yes Batch ID

Response: Single CTicketBatch object.


POST /offline/batch/upload

Uploads a PDF file containing tickets and creates a new batch. The PDF is split into individual ticket pages and ticket data is extracted using the attraction's configured patterns. Uses multipart/form-data.

Roles: admin

Multipart Fields:

Field Type Required Description
session string No User session token
attractionId integer Yes Attraction the tickets belong to
campaignId integer No Campaign to associate with
pdfFile file Yes PDF file containing tickets
supplierReference string No Supplier invoice/reference number
purchasePriceTotal decimal No Total purchase price
purchasePricePerTicket decimal No Per-ticket purchase price
purchaseCurrency string No Purchase currency (ISO 4217)
defaultSellingPrice decimal No Default selling price per ticket
sellingCurrency string No Selling currency (ISO 4217)
notes string No Internal notes

Response:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": {
    "batch": {
      "batchId": 10,
      "attractionId": 1,
      "totalTickets": 25,
      "supplierReference": "INV-2026-0042",
      "purchasePriceTotal": 5000.00,
      "purchasePricePerTicket": 200.00,
      "purchaseCurrency": "AED",
      "defaultSellingPrice": 350.00,
      "sellingCurrency": "AED",
      "createdAt": "2026-03-01"
    },
    "tickets": [ ... ],
    "ticketCount": 25
  }
}

POST /offline/batch/tickets

Lists all tickets in a batch.

Roles: agent, admin

Request Body:

Field Type Required Description
session string No User session token
batchId integer Yes Batch ID

Response: Array of COfflineTicket objects.


POST /offline/batch/tickets/save

Bulk-saves edited ticket data for a batch (e.g. after manual corrections to extracted fields).

Roles: admin

Request Body:

Field Type Required Description
session string No User session token
tickets array Yes Array of ticket objects with fields to update

Each ticket object in the array should include ticketId and any fields to update (e.g. ticketSerial, barcode, category, ageGroup, ticketDate, timeSlot, validUntil, sellingPrice, sellingCurrency).

Response: Array of updated COfflineTicket objects.


POST /offline/batch/delete

Deletes a batch and all its tickets. Only batches with no sold tickets can be deleted.

Roles: admin

Request Body:

Field Type Required Description
session string No User session token
batchId integer Yes Batch ID to delete

Response:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": "Batch deleted successfully"
}

Ticket Operations

POST /offline/ticket/search

Searches tickets with optional filters.

Roles: agent, admin

Request Body:

Field Type Required Description
session string No User session token
batchId integer No Filter by batch ID
attractionId integer No Filter by attraction ID
status string No Filter by ticket status (AVAILABLE, RESERVED, SOLD, EXPIRED)
category string No Filter by category
ageGroup string No Filter by age group
dateFrom string No Filter by ticket date from (yyyy-MM-dd)
dateTo string No Filter by ticket date to (yyyy-MM-dd)
campaignId integer No Filter by campaign ID

Response: Array of COfflineTicket objects.


POST /offline/ticket/read

Reads a single ticket by ID.

Roles: agent, admin

Request Body:

Field Type Required Description
session string No User session token
ticketId integer Yes Ticket ID

Response: Single COfflineTicket object.


POST /offline/ticket/download

Downloads a ticket's PDF page. This is a public endpoint protected by a unique download code (not session authentication).

Roles: guest, agent, admin

Request Body:

Field Type Required Description
ticketId integer Yes Ticket ID
code string Yes Unique download code

Response: Binary application/pdf file on success, or JSON error response on failure.

Note: This endpoint returns binary data. Use fetch() with appropriate headers, not tlinq(). See hotel-list.js for a reference binary download pattern.


POST /offline/ticket/extend-validity

Extends the validity date for one or more tickets.

Roles: admin

Request Body:

Field Type Required Description
session string No User session token
ticketIds array[integer] Yes List of ticket IDs to extend
newValidUntil string Yes New validity date (yyyy-MM-dd)

Response: Array of updated COfflineTicket objects.


Sales Workflow

POST /offline/sale/list

Lists sales with optional filters.

Roles: agent, admin

Request Body:

Field Type Required Description
session string No User session token
cartReference string No Filter by cart reference
ticketId integer No Filter by ticket ID
status string No Filter by sale status

Response: Array of CTicketSale objects.


POST /offline/sale/read

Reads a sale by cart reference, including associated tickets and payment link.

Roles: agent, admin

Request Body:

Field Type Required Description
session string No User session token
cartReference string Yes Cart reference

Response:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": {
    "cartReference": "OT-20260301-ABC12",
    "paymentLink": "https://secure.telr.com/gateway/order.json?...",
    "odooQuoteNumber": "S00142",
    "sales": [ ... ],
    "tickets": [ ... ]
  }
}

POST /offline/sale/reserve

Reserves one or more tickets for a customer. Creates sale records, an Odoo quotation, and optionally a Telr payment link.

Roles: agent, admin

Request Body:

Field Type Required Description
session string No User session token
ticketIds array[integer] Yes List of ticket IDs to reserve
customerName string Yes Customer full name
customerEmail string Yes Customer email address
customerPhone string No Customer phone number
agentUserId string No Agent user ID making the sale
notes string No Sale notes
customerId integer No Existing Odoo customer ID
skipPaymentLink boolean No If true, skip Telr payment link generation

Response:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": {
    "cartReference": "OT-20260301-ABC12",
    "paymentLink": "https://secure.telr.com/gateway/order.json?...",
    "sales": [ ... ],
    "tickets": [ ... ]
  }
}

POST /offline/sale/assign-group

Assigns tickets to a group trip service instead of an individual sale. Tickets are marked as sold with status GROUP_ASSIGNED.

Roles: agent, admin

Request Body:

Field Type Required Description
session string No User session token
ticketIds array[integer] Yes List of ticket IDs to assign
tripServiceId integer Yes Group trip service ID
agentUserId string No Agent user ID

Response:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": {
    "cartReference": "OT-20260301-XYZ99",
    "sales": [ ... ],
    "tickets": [ ... ]
  }
}

POST /offline/sale/confirm-payment

Manually confirms payment for a reservation (admin override, bypasses Telr callback).

Roles: admin

Request Body:

Field Type Required Description
session string No User session token
cartReference string Yes Cart reference to confirm

Response: Array of updated CTicketSale objects.


POST /offline/sale/cancel

Cancels a reservation and releases the tickets back to available inventory.

Roles: admin

Request Body:

Field Type Required Description
session string No User session token
cartReference string Yes Cart reference to cancel
reason string No Cancellation reason

Response: Array of updated CTicketSale objects.


POST /offline/sale/regenerate-link

Regenerates the Telr payment link for a pending reservation.

Roles: agent, admin

Request Body:

Field Type Required Description
session string No User session token
cartReference string Yes Cart reference

Response:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": {
    "cartReference": "OT-20260301-ABC12",
    "paymentLink": "https://secure.telr.com/gateway/order.json?..."
  }
}

POST /offline/sale/email-tickets

Sends ticket download links to the customer via email.

Roles: agent, admin

Request Body:

Field Type Required Description
session string No User session token
cartReference string Yes Cart reference
baseUrl string Yes Base URL for download links (e.g. "https://app.example.com")

Response:

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": "Download links sent successfully"
}

POST /offline/sale/merge-download

Downloads all ticket PDFs for a sale merged into a single PDF file.

Roles: agent, admin

Request Body:

Field Type Required Description
session string No User session token
cartReference string Yes Cart reference

Response: Binary application/pdf file on success, or JSON error response on failure.

Note: This endpoint returns binary data. Use fetch() with getAuthHeaders(), not tlinq().


Reports

POST /offline/report/inventory-summary

Returns an overall inventory summary across all attractions, including per-attraction breakdowns with revenue.

Roles: admin

Request Body:

Field Type Required Description
session string No User session token

Response: Summary object with global counts and a per-attraction array including revenue.

{
  "apiStatus": { "errorCode": "OK", "errorMessage": "Success" },
  "apiData": {
    "totalAttractions": 3,
    "totalTickets": 150,
    "available": 80,
    "reserved": 10,
    "sold": 50,
    "expired": 10,
    "totalRevenue": 17500.00,
    "attractions": [
      {
        "attractionId": 1,
        "attractionName": "Dubai Aquarium",
        "supplier": "Emaar",
        "available": 30,
        "reserved": 5,
        "sold": 20,
        "expired": 5,
        "totalTickets": 60,
        "totalRevenue": 7000.00
      }
    ]
  }
}

POST /offline/report/attraction-summary

Returns inventory and sales summary for a specific attraction.

Roles: agent, admin

Request Body:

Field Type Required Description
session string No User session token
attractionId integer Yes Attraction ID

Response: Summary object with attraction-specific counts and values.


POST /offline/report/expiring-tickets

Lists tickets that are expiring within a given number of days.

Roles: agent, admin

Request Body:

Field Type Required Description
session string No User session token
withinDays integer No Number of days to look ahead (default: 7)

Response: Array of COfflineTicket objects expiring within the specified window.


POST /offline/report/sales

Lists sales with optional status and date filters.

Roles: agent, admin

Request Body:

Field Type Required Description
session string No User session token
status string No Filter by sale status
dateFrom string No Start date filter (yyyy-MM-dd)
dateTo string No End date filter (yyyy-MM-dd)
attractionId integer No Filter by attraction ID
agentUserId string No Filter by agent user ID

Response: Array of CTicketSale objects.


POST /offline/report/inventory-csv

Exports the current inventory as a CSV file, applying the same filters as ticket search.

Roles: agent, admin

Request Body:

Field Type Required Description
session string No User session token
batchId integer No Filter by batch ID
attractionId integer No Filter by attraction ID
status string No Filter by ticket status
category string No Filter by category
ageGroup string No Filter by age group
dateFrom string No Filter by ticket date from (yyyy-MM-dd)
dateTo string No Filter by ticket date to (yyyy-MM-dd)
campaignId integer No Filter by campaign ID

Response: Binary text/csv file download.

Note: This endpoint returns CSV data, not JSON. Use fetch() with appropriate headers, not tlinq().


Data Models

COfflineAttraction

Field Type Description
attractionId integer Unique attraction identifier
name string Attraction name
odooProductCode string Odoo product code for invoicing
supplier string Supplier name
categories string Comma-separated ticket categories
ageGroups string Comma-separated age groups
hasTimeSlots boolean Whether tickets have time slots
extractionPatterns string JSON-encoded extraction patterns
notes string Internal notes
active boolean Whether the attraction is active
createdAt date Creation timestamp
updatedAt date Last update timestamp

CTicketCampaign

Field Type Description
campaignId integer Unique campaign identifier
name string Campaign name
startDate date Campaign start date
endDate date Campaign end date
description string Campaign description
createdAt date Creation timestamp

CTicketBatch

Field Type Description
batchId integer Unique batch identifier
attractionId integer Parent attraction ID
campaignId integer Associated campaign ID
uploadDate date Batch upload date
supplierReference string Supplier invoice/reference number
purchasePriceTotal decimal Total purchase price
purchasePricePerTicket decimal Per-ticket purchase price
purchaseCurrency string Purchase currency (ISO 4217)
defaultSellingPrice decimal Default selling price per ticket
sellingCurrency string Selling currency (ISO 4217)
originalPdfPath string Path to original uploaded PDF
totalTickets integer Total number of tickets in batch
notes string Internal notes
createdAt date Creation timestamp

COfflineTicket

Field Type Description
ticketId integer Unique ticket identifier
batchId integer Parent batch ID
internalSerial integer Internal sequential number within batch
ticketSerial string Ticket serial extracted from PDF
barcode string Barcode value extracted from PDF
category string Ticket category (e.g. "Adult", "Child")
ageGroup string Age group
ticketDate date Ticket date
timeSlot string Time slot (e.g. "14:00")
validUntil date Ticket expiration date
promoCode string Promo code if applicable
limitations string Usage limitations
status string Ticket status (see Ticket Status Values)
sellingPrice decimal Selling price
sellingCurrency string Selling currency (ISO 4217)
pdfPageNumber integer Page number in original PDF
pdfFilePath string Path to individual ticket PDF
downloadCode string Unique code for public download
cartReference string Cart reference if sold/reserved
odooQuoteId integer Linked Odoo quotation ID
downloadCount integer Number of times downloaded
downloadExpiresAt date Download link expiration
tripServiceId integer Group trip service ID (if group-assigned)
reservedAt date Reservation timestamp
soldAt date Sale confirmation timestamp
createdAt date Creation timestamp
updatedAt date Last update timestamp

CTicketSale

Field Type Description
saleId integer Unique sale record identifier
ticketId integer Associated ticket ID
cartReference string Cart reference grouping the sale
odooQuoteId integer Linked Odoo quotation ID
odooCustomerId integer Linked Odoo customer ID
customerName string Customer full name
customerPhone string Customer phone number
customerEmail string Customer email address
saleDate date Sale date
salePrice decimal Sale price
saleCurrency string Sale currency (ISO 4217)
telrPaymentLink string Telr payment gateway link
telrTransactionId string Telr transaction ID
agentUserId string Agent who made the sale
status string Sale status (see Sale Status Values)
paymentStatus string Payment status (see Payment Status Values)
downloadCodeSentAt date When download link was emailed
notes string Sale notes
createdAt date Creation timestamp
updatedAt date Last update timestamp

CTicketAudit

Field Type Description
auditId integer Unique audit record identifier
entityType string Entity type: "TICKET" or "SALE"
entityId integer The ticket or sale ID
action string Action performed (RESERVE, CONFIRM_PAYMENT, CANCEL, ASSIGN_GROUP, EXTEND_VALIDITY, PAYMENT_STATUS_UPDATE)
oldStatus string Previous status before the transition
newStatus string New status after the transition
cartReference string Associated cart reference
userId string User who performed the action
details string Additional context (free text)
createdAt datetime Timestamp of the audit entry

Status Values

Ticket Status

Value Description
AVAILABLE Ticket is in inventory and available for sale
RESERVED Ticket is reserved pending payment
SOLD Ticket has been sold and paid for
EXPIRED Ticket has passed its validity date

Sale Status

Value Description
PENDING_PAYMENT Reservation created, awaiting payment
COMPLETED Payment confirmed, sale finalized
CANCELLED Reservation cancelled
GROUP_ASSIGNED Ticket assigned to a group trip service

Payment Status (Telr Callback)

Value Description
PAID Payment received successfully
DECLINED Payment was declined by gateway
CANCELLED_PAYMENT Customer cancelled the payment

Error Codes

Code Description
OK Operation successful
GENERAL General server error
MISSING_PARAMETER Required parameter not provided
INVALID_PARAMETER Parameter value is invalid (e.g. non-PDF file, invalid date)
NOTFOUND Resource not found