API
The Usetix API gives you programmatic access to your account so you can build dashboards, sync customers to your CRM, or wire ticketing data into your own systems.
The API tracks the same data and shapes the admin dashboard uses. Every endpoint is the same URL you’d visit in your browser — just request application/json instead.
Endpoints
- Authentication
- Venues
- Performers
- Events
- Tickets
- Event FAQs
- Custom checkout fields
- Orders
- Customers
- Memberships
Versioning
Usetix follows the Basecamp philosophy: clean, versionless URLs. There’s no /v1/ in the path. When a breaking change is unavoidable, the legacy endpoints move to a separate host (legacy.usetix.io) with a clearly communicated sunset window — typically 3–6 months — so you can migrate on your own schedule.
Authentication
Every request must include a Bearer token in the Authorization header. Tokens are account-scoped: a token issued for Account A only ever sees Account A’s data. Generate tokens from your admin dashboard at Settings → API Tokens.
curl -H "Authorization: Bearer your-token-here" \
-H "Accept: application/json" \
https://app.usetix.io/admin/events
See the authentication guide for token management and permission tiers.
Error responses
When a request fails, the API communicates the source of the problem through the HTTP status code.
| Status code | Description |
|---|---|
401 Unauthorized |
Token is missing, invalid, revoked, or doesn’t have permission for this method (e.g. a read token attempting a write). |
404 Not Found |
Resource doesn’t exist or doesn’t belong to your token’s account. |
422 Unprocessable Entity |
Validation failed — the response body details the failed fields. |
500 Internal Server Error |
Unexpected error on our side. If you see one, let us know. |
Money fields
Monetary values are returned as objects with a string amount (avoiding floating-point precision issues) and an ISO 4217 currency code:
{
"amount": "42.00",
"currency": "EUR"
}
Always treat amount as a decimal string — never parse it through a float — and use currency for display formatting. Symbols (€, $, £) are never returned; render them yourself if needed.
Timestamps
All timestamps are ISO 8601 in UTC, with seconds precision:
2026-04-22T12:34:56Z
Pagination
V1 endpoints return all matching records in a single response. Cursor-based pagination is on the roadmap; once introduced, responses will include a Link header with a rel="next" URL — you’ll be able to opt in by following that link, and existing single-shot consumers stay working.
Stability
The API surface is intentionally narrow today. While we don’t ship breaking changes lightly, the JSON shape tracks the admin UI’s needs — fields may be added without notice. If something breaks for you, let us know.
Write requests
POST, PATCH, and DELETE requests require a token with the Read + Write permission. Send the body as JSON with Content-Type: application/json and the resource fields directly at the top level:
curl -X POST \
-H "Authorization: Bearer your-token-here" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"title": "Spring Showcase", "venue_id": 7, "starts_at": "2026-05-01T19:00:00Z", "ends_at": "2026-05-01T23:00:00Z", "sales_ends_at": "2026-05-01T19:00:00Z"}' \
https://app.usetix.io/admin/events
Successful create returns 201 Created with a Location header pointing to the new resource. Successful update returns 200 OK. Successful delete returns 204 No Content. Validation errors return 422 Unprocessable Entity with a { "errors": { "field": ["message"] } } body.
File uploads
To attach a file (event image, performer image, etc.) over the API, use Active Storage’s two-step direct-upload flow. The bytes go straight to storage; only metadata and a signed reference travel through Usetix.
1. Create a direct upload
Send the file’s metadata to get a signed reference and a presigned upload URL:
curl -X POST \
-H "Authorization: Bearer your-token-here" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"blob": {
"filename": "cover.png",
"byte_size": 12345,
"checksum": "GQ5SqLsM7ylnji0Wgd9wNA==",
"content_type": "image/png"
}
}' \
https://app.usetix.io/rails/active_storage/direct_uploads
The checksum is a Base64-encoded MD5 of the file content.
Response:
{
"id": 42,
"key": "abc123...",
"filename": "cover.png",
"content_type": "image/png",
"byte_size": 12345,
"checksum": "GQ5SqLsM7ylnji0Wgd9wNA==",
"signed_id": "eyJfcmFpbHMi...",
"direct_upload": {
"url": "https://storage.example.com/...",
"headers": {
"Content-Type": "image/png",
"Content-MD5": "GQ5SqLsM7ylnji0Wgd9wNA=="
}
}
}
2. Upload the bytes
PUT the file content directly to the URL returned in direct_upload.url, with the headers it specifies:
curl -X PUT \
-H "Content-Type: image/png" \
-H "Content-MD5: GQ5SqLsM7ylnji0Wgd9wNA==" \
--data-binary @cover.png \
"https://storage.example.com/..."
This call goes to your storage provider (or to Usetix’s disk service in development), not to your Rails server. No Authorization header — the URL is presigned and short-lived.
3. Reference the file by signed_id
Pass the signed_id from step 1 as the value of an image / file field on any subsequent API call:
curl -X PATCH \
-H "Authorization: Bearer your-token-here" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"image": "eyJfcmFpbHMi..."}' \
https://app.usetix.io/admin/events/spring-showcase
Supported file fields:
| Resource | Fields |
|---|---|
| Event | image, background_image |
| Performer | image |