Skip to content

Documentation

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

  1. 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.

  2. 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.

  3. 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.

  4. 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": [...] }).

  5. 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.

  6. 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

Analytics from a scriptbash
# 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>"
Timeseries responsejson
{
  "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.

MethodEndpointScopePurpose
GET/api/v1/requestsrequests:readList requests — supports limit (max 100) and q
POST/api/v1/requestsrequests:writeCreate a request (requestTypeId, requesterEmail, title; priority and field values optional)
GET/api/v1/requests/{id}requests:readFetch one request with comments
POST/api/v1/requests/{id}/commentsrequests:writeAdd a comment to a request
GET/api/v1/request-typesrequest-types:readList request types (use the id when creating requests)
GET/api/v1/usersusers:readList users — supports limit and q
GET/api/v1/analytics/overviewanalytics:readHeadline metrics + SLA summary — supports from/to and team/type/status/priority/assignee filters
GET/api/v1/analytics/timeseriesanalytics:readDaily 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.