Skip to content

Ticket Company Sales API

Related documentation: Promoters Integration · Finance API

Version: 1.0.0 (2026-07-13) Audience: external ticket companies, partners, internal developers Status: live

This is the doc you hand to a ticket company so they can push daily ticket sales into Kisum automatically. Sales land in Promoters (real-time event view) and flow daily to Finance, the source of truth for real income.


1. Authentication — one key per ticket company

Section titled “1. Authentication — one key per ticket company”

Every request carries an API key in the x-api-key header:

x-api-key: tkv_<64 hex characters>
  • Keys are per ticket vendor, per promoter company. A key only sees the tickets assigned to that vendor inside that promoter’s company — never another tenant’s data.
  • Keys are generated by the promoter in Promoters: Event → Tickets → vendor card → Sales API access → Generate key. The key is shown once; only its sha256 hash is stored (ticket_vendor_api_keys collection).
  • Rotating generates a new key and revokes the old one immediately. Revoking cuts access without affecting other ticket companies.
  • This is NOT the platform INTERNAL_API_KEY — the internal key is never shared with external partners.

Backend: middleware/ticket-vendor-key.middleware.js (authenticateTicketVendorKey) in Backend-Kisum-Promoters.

Base URL: the Promoters backend base URL + /api.

Lists the events and tickets assigned to the authenticated vendor, so the ticket company can map their internal products to Kisum ticketIds.

{
"data": {
"vendorId": "",
"events": [
{
"eventId": "", "eventTitle": "", "eventDate": "", "eventStatus": "confirmed",
"tickets": [
{ "ticketId": "", "title": "GA", "price": 50, "currency": "usd", "allocation": 1000, "comps": 50 }
]
}
]
}
}

Push daily sales totals. Body:

{
"sales": [
{ "ticketId": "", "date": "2026-07-12", "quantity": 120, "comps": 4, "discount": 0 }
]
}

Rules:

  • date is YYYY-MM-DD (UTC day). quantity = paid tickets sold that day (integer ≥ 0). comps optional. discount optional, decimal 0–1 applied to that day’s paid quantity.
  • Day-set semantics (idempotent): a push REPLACES that ticket+date’s previous API rows. Re-sending the same day (e.g. corrected totals) never double-counts. Manual rows entered in the Promoters UI are never touched.
  • Max 200 rows per request. Per-row results — one bad row doesn’t reject the rest:
{ "data": { "processed": 2, "accepted": 1, "rejected": 1,
"results": [ { "index": 0, "status": "ACCEPTED" }, { "index": 1, "status": "REJECTED", "error": "Ticket not found for this vendor" } ] } }
  • Standard capacity validation applies (cannot sell beyond the ticket’s saleable allocation; comps beyond the comp allocation are rejected).
  1. Rows are written to event_ticket_sold_history with source: 'api' (manual rows are source: 'manual'); vendor payment terms update exactly like manual entry (addTicketSale validation chain).
  2. Promoters shows sales in real time on the event’s Tickets tab. If someone opens the manual add-sales form for a ticket that receives API sales, the form shows a duplicate-entry warning.
  3. Income reaches Finance via the daily cron push (/cron/finance-income-daily-push) or the per-event “Sync to Finance” button. In Finance the ticket income is LIVE (accruing, counts everywhere) until the promoter settles it after the event — after settlement Finance ignores further sync for that income (SETTLED_SKIPPED).

4. Key management endpoints (internal users)

Section titled “4. Key management endpoints (internal users)”

Tenant-scoped (session auth + x-org), permission promoter.event.sales.edit / commercial edit:

MethodPathPurpose
POST/api/vendors/tickets/{vendorId}/api-keyGenerate / rotate — returns the raw key ONCE
GET/api/vendors/tickets/{vendorId}/api-keyStatus: key prefix, created, last used (never the key)
DELETE/api/vendors/tickets/{vendorId}/api-keyRevoke

Backend: integrations/commands/ticket-api.command.js, routes in integrations/integrations.route.js.