API Reference

Complete reference for the TicketForge REST API (v1).

Authentication

All API endpoints require a Bearer token in the Authorization header. API keys are prefixed with tf_ and scoped to a single project.

Authorization: Bearer tf_your_api_key

Base URL & Versioning

/v1/
Current version: v1 Content-Type: application/json

All request and response bodies use JSON. The API is versioned via URL path — breaking changes will ship as v2.

POST

/v1/tickets

Create a new support ticket. Returns immediately — AI triage runs asynchronously.

Request Body

FieldTypeRequiredDescription
subjectstringRequiredTicket subject line
bodystringRequiredFull description (Markdown supported)
sender_emailstringOptionalSubmitter's email address
sender_namestringOptionalSubmitter's display name
prioritystringOptionalp1_critical, p2_high, p3_medium, p4_low
sourcestringOptionalapi, widget, email, form — defaults to api
tagsstring[]OptionalArray of tag names to apply
metadataobjectOptionalArbitrary JSON metadata

Example

curl -X POST /v1/tickets \
  -H "Authorization: Bearer tf_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "subject": "Cannot access billing portal",
    "body": "Getting a 403 error when clicking Manage Subscription.",
    "sender_email": "jane@acme.com",
    "priority": "p2_high"
  }'

Response

202 Accepted
{
  "ticket_id": "550e8400-e29b-41d4-a716-446655440000",
  "ticket_number": 42
}

Async side effects:

  • AI triage — category, priority, sentiment analysis
  • Sentry issue auto-linking (if configured)
  • Duplicate ticket detection
  • Webhook dispatch (ticket_created)
GET

/v1/tickets/:id

Retrieve ticket details including conversation messages.

URL Parameters

FieldTypeRequiredDescription
iduuidRequiredTicket ID

Query Parameters

FieldTypeRequiredDescription
contact_emailstringOptionalScope results to this contact (validates ownership)

Example

curl /v1/tickets/550e8400-...?contact_email=jane@acme.com \
  -H "Authorization: Bearer tf_your_api_key"

Response

200 OK
{
  "ticket_id": "550e8400-e29b-41d4-a716-446655440000",
  "ticket_number": 42,
  "subject": "Cannot access billing portal",
  "status": "open",
  "priority": "p2_high",
  "category": "billing",
  "created_at": "2026-03-18T14:32:00Z",
  "updated_at": "2026-03-18T15:10:00Z",
  "messages": [
    {
      "id": "660e8400-...",
      "author_type": "contact",
      "body": "Getting a 403 error...",
      "created_at": "2026-03-18T14:32:00Z"
    }
  ]
}

Only non-internal messages are returned. Messages are ordered by created_at ascending.

POST

/v1/tickets/:id/messages

Add a message to an existing ticket. Reopens resolved tickets automatically.

Request Body

FieldTypeRequiredDescription
bodystringRequiredMessage text content
contact_emailstringOptionalAssociate message with a contact

Example

curl -X POST /v1/tickets/550e8400-.../messages \
  -H "Authorization: Bearer tf_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "body": "We have deployed a fix. Please try again.",
    "contact_email": "jane@acme.com"
  }'

Response

201 Created
{
  "message_id": "770e8400-e29b-41d4-a716-446655440001"
}

Behavior:

  • Creates a contact author-type message
  • If ticket was resolved/closed, reopens to open
  • Triggers automation rules for ticket_replied event
  • Notifies assigned agent
GET

/v1/articles/search

Full-text search across published knowledge base articles.

Query Parameters

FieldTypeRequiredDescription
qstringRequiredSearch query string
limitintegerOptionalMax results (default: 10, max: 50)

Example

curl "/v1/articles/search?q=billing+portal&limit=5" \
  -H "Authorization: Bearer tf_your_api_key"

Response

200 OK
{
  "articles": [
    {
      "id": "880e8400-...",
      "title": "Managing Your Subscription",
      "slug": "managing-subscription",
      "excerpt": "Learn how to access and manage your billing portal...",
      "category": "Billing",
      "relevance": 0.95
    }
  ],
  "total": 1
}
GET

/health

Health check — no authentication required.

Example

curl /health

Response

200 OK
{
  "status": "ok",
  "service": "ticketforge-ingestion",
  "version": "0.1.0"
}

Error Codes

All errors return a consistent JSON envelope.

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Subject is required"
  }
}
StatusCodeDescription
400VALIDATION_ERRORMissing or invalid request fields
401UNAUTHORIZEDInvalid or missing API key
404NOT_FOUNDResource does not exist or is outside project scope
409CONFLICTDuplicate or conflicting operation
429RATE_LIMITEDRate limit exceeded (100 req/min per key)
500INTERNAL_ERRORUnexpected server error

Rate Limiting

100

requests per minute

per key

scoped to API key

429

returned when exceeded

The TypeScript SDK handles retries automatically with exponential backoff and jitter. If calling the API directly, wait and retry with increasing delays.

Webhook Events

Outbound HTTP callbacks. Signed with HMAC-SHA256, with automatic retries (1m, 5m, 30m).

EventDescription
ticket_createdA new ticket was created
ticket_repliedA message was added to a ticket
ticket_resolvedA ticket was marked as resolved
ticket_status_changedTicket status changed (open, in_progress, waiting, etc.)
ticket_assignedA ticket was assigned to an agent

Example Payload

{
  "event": "ticket_created",
  "timestamp": "2026-03-18T12:00:00Z",
  "data": {
    "id": "550e8400-...",
    "subject": "Cannot access billing portal",
    "status": "open",
    "priority": "p2_high",
    "sender_email": "jane@acme.com",
    "project_id": "proj_xyz"
  }
}

Headers

Content-Type: application/json

X-TicketForge-Event: ticket_created

X-TicketForge-Signature: sha256=<hmac>

X-TicketForge-Delivery: <uuid>

For signature verification code and webhook configuration, see the Webhooks guide.