Docs sections
Keys and requests
How to pass the key, how a test key differs from a live one, and the shape of the data the API takes and returns.
API key
Every request carries the organization's key in a header:
http
Authorization: Bearer bt_live_…| Prefix | Mode | What the key sees |
|---|---|---|
bt_test_ | test | test events, orders, tickets and devices only |
bt_live_ | live | live ones only |
The organization owner creates and revokes keys in the dashboard under интеграция → ключи API (Integration → API keys). A key works in the mode the dashboard was in when the key was created. You see the full key once. We store only its hash, so a lost key can't be recovered: revoke it and create a new one.
- A revoked key stops working within 5 seconds.
- A suspended organization's key doesn't work.
- With no key, a wrong key or a revoked key the response is
401 unauthorized.
The key opens every event and ticket of the organization in its mode. Keep it on your server. It has no place in page code, a mobile app or a public repository.
Base URL
The API base URL is https://api.budu.events/v1. Requests are accepted over HTTPS only.
Organization and mode
The key sets the organization and the mode. The org_id and livemode fields in a request body have no effect. Another organization's event, order or ticket, and an object from the other mode, look as if they don't exist: 404 not_found.
What a key can do
| Section | What it does |
|---|---|
| Events | create, update, publish, availability, cover |
| Assigned seating | upload the seat map, list seats |
| Orders | an order after payment, a reservation during payment |
| Tickets | find, cancel, reissue, resend the email, export |
| Issue without payment | issue tickets by hand, upload a guest list |
| Door staff | pair a door staff phone, check-in report |
API keys, branding, test recipients, the activity log and an event's live numbers are dashboard-only. A key gets 403 forbidden with details.reason: "session_only" on those requests.
Data format
- The request body is JSON in UTF-8, up to 1 MB. Files (seats, guest list, cover) go as the request body as they are, with their own
Content-Type. - Field names are
snake_case. An unknown field in a request body gives400 invalid_request, so a typo in a field name never slips through unnoticed. The exception is devices (POST /v1/devices/invites,PATCH /v1/devices/{id}), which ignore extra fields. - A response has every field of the object, even empty ones: string
"", number0, list[], nested objectnull. - IDs are UUID strings:
"0193e0b2-4a7c-7d10-9e3f-2c5a8b1d4e60". - Times are RFC 3339 strings. Responses are always in UTC:
"2026-12-12T16:00:00Z". In requests you can give an offset:"2026-12-12T19:00:00+03:00". *_msfields are Unix milliseconds."0"means "never":"checked_in_at_ms": "0"on a ticket that hasn't checked in.- 64-bit numbers (
price_minorand every*_ms) come back as strings:"price_minor": "250000". That's how protobuf writes them to JSON. In requests a number or a string both work. - Money is in the currency's minor units:
250000kopecks means 2,500 ₽. The currency is a three-letter code,RUBby default.
Headers
| Header | Where | Why |
|---|---|---|
Authorization | request | Bearer and the API key |
Idempotency-Key | request, POST and DELETE | safe retries, see idempotency |
Content-Type | request with a body | application/json for JSON, text/csv for seats and guests, image/jpeg, image/png or image/webp for the cover |
X-Request-Id | response | the request's number in our logs. Quote it when you write to us about a problem |
Idempotent-Replayed | response | true when this is the stored response to a retry |
Retry-After | 429 response | how many seconds to wait before retrying |