REST API
A REST surface for requests, comments, users, request types, and analytics. API-key authenticated, org-scoped, and rate-limited.
- Where:
- Settings → API keys
- Permission:
- MANAGE_INTEGRATIONS
- Updated:
- July 2026
Overview
- Authentication: Authorization: Bearer eventier_… (an x-api-key header with the same value also works).
- Scopes: each key carries a set of resource:action scopes chosen at creation. Calling an endpoint the key isn't scoped for returns HTTP 403 naming the missing scope.
- Rate limit: 120 requests per minute per organization, shared across all of its keys — minting more keys does not raise the ceiling. Exceeding it returns HTTP 429. Self-hosted deployments can adjust it with the API_RATE_LIMIT_PER_MINUTE env var.
- Errors return JSON with an `error` message and the appropriate HTTP status.
- Keys are org-scoped. Every API call writes an audit row, so you can attribute production traffic by key.
Step by step
- 01
Mint an API key
Settings → API keys → New. Pick a label and the scopes the integration needs — a reporting script only needs analytics:read; a ticket-creating integration needs requests:write plus request-types:read. Scopes are fixed at creation (revoke and re-mint to change them). The key (prefixed eventier_) is shown once — store it immediately in your secrets manager.
- 02
Choose the key's identity
A personal key acts as you: API actions are attributed to you in the audit log, and the key stops working if your account is deactivated. A service account key belongs to a named machine identity (e.g. "Reporting Bot") — actions attribute to it, it can never log in, it isn't billed as a seat, and its keys keep working through staff changes. Use service accounts for anything running in production.
- 03
Make your first call
curl -H "Authorization: Bearer eventier_…" https://<your-app-host>/api/v1/requests?limit=10 — returns the latest requests for the org the key belongs to.
- 04
List and filter
List endpoints accept a `limit` query param (max 100) and a `q` search param. They return a JSON array (e.g. { "requests": [...] }).
- 05
Create a request
POST /api/v1/requests with requestTypeId, requesterEmail, and title (priority and field values optional). The owning team is derived from the request type.
- 06
Pull analytics into your own tooling
GET /api/v1/analytics/overview returns the same headline numbers as the Analytics dashboard (volume, SLA compliance, resolution percentiles, breakdowns by status/team/type/priority). GET /api/v1/analytics/timeseries returns a daily series for one metric — created, resolved, or sla_compliance. Both accept from/to (YYYY-MM-DD) plus teamId, requestTypeId, status, priority, and assigneeId filters.
Examples
# June's SLA compliance, straight into a spreadsheet or alert
curl -s -H "Authorization: Bearer eventier_…" \
"https://<your-app-host>/api/v1/analytics/overview?from=2026-06-01&to=2026-06-30" \
| jq .overview.slaCompliancePercent
# Daily created-ticket counts for one team (zero-filled across the range)
curl -s -H "Authorization: Bearer eventier_…" \
"https://<your-app-host>/api/v1/analytics/timeseries?metric=created&from=2026-06-01&to=2026-06-30&teamId=<id>"{
"metric": "created",
"interval": "day",
"filters": { "from": "2026-06-01", "to": "2026-06-04" },
"points": [
{ "date": "2026-06-01", "value": 0 },
{ "date": "2026-06-02", "value": 14 },
{ "date": "2026-06-03", "value": 9 },
{ "date": "2026-06-04", "value": 11 }
]
}Endpoints
All endpoints require an API key carrying the listed scope and are scoped to the key's organization. Keys minted before scoping existed were grandfathered with every scope.
| Method | Endpoint | Scope | Purpose |
|---|---|---|---|
| GET | /api/v1/requests | requests:read | List requests — supports limit (max 100) and q |
| POST | /api/v1/requests | requests:write | Create a request (requestTypeId, requesterEmail, title; priority and field values optional) |
| GET | /api/v1/requests/{id} | requests:read | Fetch one request with comments |
| POST | /api/v1/requests/{id}/comments | requests:write | Add a comment to a request |
| GET | /api/v1/request-types | request-types:read | List request types (use the id when creating requests) |
| GET | /api/v1/users | users:read | List users — supports limit and q |
| GET | /api/v1/analytics/overview | analytics:read | Headline metrics + SLA summary — supports from/to and team/type/status/priority/assignee filters |
| GET | /api/v1/analytics/timeseries | analytics:read | Daily series for one metric — metric=created | resolved | sla_compliance, same filters as overview |
Good to know
- Scope keys to least privilege: a Grafana or spreadsheet integration needs only analytics:read, so a leaked key can't read or write tickets.
- Every API call writes an audit row visible in Settings → Audit — filter by API key to attribute production traffic. Scope denials land in the security audit log as api_key.scope_denied.
- Mint a separate key per integration, each under its own service account, so you can revoke one without disrupting the others and offboarding a teammate never breaks production.
- Keys minted before identities existed are org-wide (legacy): they keep working and attribute to an arbitrary admin. Re-mint them under a service account to get clean attribution.
- Analytics endpoints compute from the same data as the in-app Analytics dashboard — run the same filters in the UI to spot-check a script.
- Invalid analytics filter values return HTTP 400 with the offending parameter named; sla_compliance series only include days that had at least one resolution.