Help API

Live

Customer support behind Bolrach Help. Your own systems use a platform key on https://api.bolrach.com/v1/help: open, read, list and update your organization's tickets, and hear about every change through signed webhooks. The console itself talks to https://bolrach.com/help/api with an Authvio token, and estate apps such as DGUMS use an internal bridge; both are documented further down.

Base https://api.bolrach.com/v1/helpAuth Bearer platform key (Help module)Webhooks Bolrach-Signature, t=,v1=Spec openapi/help.json

With a platform key

Make a key under Developers, Keys and tick the Help module (scopes help:read and help:write). The key reaches the Help desk of the organization it was made in, the same tickets that organization's agents see. Pass workspace (a slug) to use another of the organization's Help workspaces. Tickets on restricted desks (HR, Finance, Security) are never reachable with a key. What each key called is under Developers, Logs.

GET /v1/help/tickets

Tickets, newest activity first. status is one of open, pending, on_hold, resolved, closed, active (the first three) or all; q searches subjects; limit (up to 100) and offset page.

curl "https://api.bolrach.com/v1/help/tickets?status=active&limit=20" \
  -H "Authorization: Bearer $BOLRACH_KEY"
POST /v1/help/tickets

Open a ticket for a customer. subject and body are required; priority is low, medium, high or urgent. Send your own id as externalRef and a retry returns the ticket already made (idempotent: true) instead of a second one.

curl -X POST "https://api.bolrach.com/v1/help/tickets" \
  -H "Authorization: Bearer $BOLRACH_KEY" \
  -H "Content-Type: application/json" \
  -d '{"subject":"Order 1042 has not arrived","body":"It was due on Monday.","customerName":"Ada","customerEmail":"ada@example.com","externalRef":"order-1042"}'
# 201 {"id":"…","number":57,"status":"open","workspace":"acme","idempotent":false,"consoleUrl":"…"}
GET /v1/help/tickets/{id}

One ticket with its customer, assignee and every message, internal notes marked internal: true.

PATCH /v1/help/tickets/{id}

Change status, priority or both. The change is recorded on the ticket against the key.

curl -X PATCH "https://api.bolrach.com/v1/help/tickets/TICKET_ID" \
  -H "Authorization: Bearer $BOLRACH_KEY" \
  -H "Content-Type: application/json" \
  -d '{"status":"resolved"}'
POST /v1/help/tickets/{id}/messages

Reply to the customer, emailed when an address is on file, or add a note only agents see with internal: true.

Webhooks

Add an endpoint under Developers, Webhooks (an owner or admin of the Help desk). It must be a public https address. You get its signing secret once. Every event is a POST of JSON:

{
  "id": "evt_…",
  "type": "ticket.created",
  "created": 1790180000,
  "workspace": "WORKSPACE_UUID",
  "data": { "ticket": { "id": "…", "number": 57, "subject": "…", "status": "open", "priority": "medium",
                       "channel": "api", "externalRef": "order-1042", "requester": { "name": "Ada", "email": "ada@example.com" } } }
}
  • ticket.created: a ticket was opened, from any channel.
  • ticket.updated: status, priority or assignee changed.
  • message.created: a reply or an internal note was added; data.message carries it.
  • conversation.started: a customer started a chat; data.conversation.
  • ticket.sla_at_risk and ticket.sla_breached: a response target is close, or missed.
  • ping: sent by Send test, so you can check your signature code first.

Each delivery carries Bolrach-Signature: t=<unix seconds>,v1=<hex>, an HMAC-SHA256 of the timestamp, a dot and the raw body with your signing secret, the same header Bolrach Pay sends. Refuse anything older than five minutes.

const [t, v1] = req.headers['bolrach-signature'].split(',').map((p) => p.split('=')[1]);
const expected = crypto.createHmac('sha256', secret).update(`${t}.${rawBody}`).digest('hex');
const ok = crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(v1)) && Math.abs(Date.now() / 1000 - Number(t)) < 300;

Answer any 2xx within eight seconds. Anything else is retried after 1 minute, 5 minutes, 30 minutes, 2 hours and 6 hours, then marked failed; you can send a failed delivery again from the Webhooks page. Switching an endpoint off also stops what is already queued for it.

One engine

Bolrach Help runs as one process. DGUMS omnichannel escalate creates tickets through /api/internal/bridge/tickets so staff work one ticket plane instead of a separate DGUMS-only ticket store.

# health (no auth)
curl "https://bolrach.com/help/api/health"
# → {"ok":true,"service":"help-api"}

Health

GET /api/health

Unauthenticated liveness. Returns service name when the API is up.

curl "https://bolrach.com/help/api/health"

Console API (agents, with an Authvio token)

Agent routes need an Authvio bearer token for audience empire:support:web and the workspace UUID in x-workspace-id.

GET /api/tickets

List tickets. Optional query: status, priority, query, page.

curl "https://bolrach.com/help/api/tickets?status=open" \
  -H "Authorization: Bearer $AUTHVIO_ID_TOKEN" \
  -H "x-workspace-id: WORKSPACE_UUID"
POST /api/tickets

Create a ticket with subject, body, optional priority and customer.

curl -X POST "https://bolrach.com/help/api/tickets" \
  -H "Authorization: Bearer $AUTHVIO_ID_TOKEN" \
  -H "x-workspace-id: WORKSPACE_UUID" \
  -H "Content-Type: application/json" \
  -d '{"subject":"Billing question","body":"Invoice looks wrong","priority":"medium","customer":{"name":"Ada","email":"ada@example.com"}}'
GET /api/tickets/{id}

Ticket detail with messages, customer, and events.

curl "https://bolrach.com/help/api/tickets/TICKET_UUID" \
  -H "Authorization: Bearer $AUTHVIO_ID_TOKEN" \
  -H "x-workspace-id: WORKSPACE_UUID"
POST /api/tickets/{id}/reply

Agent reply or internal note. Set internal: true for notes that stay off the customer channel.

curl -X POST "https://bolrach.com/help/api/tickets/TICKET_UUID/reply" \
  -H "Authorization: Bearer $AUTHVIO_ID_TOKEN" \
  -H "x-workspace-id: WORKSPACE_UUID" \
  -H "Content-Type: application/json" \
  -d '{"body":"We are looking into this.","internal":false}'

Conversations

GET /api/conversations

Inbox conversations. Filter with channel (email, chat, web, api, voice).

curl "https://bolrach.com/help/api/conversations?channel=chat" \
  -H "Authorization: Bearer $AUTHVIO_ID_TOKEN" \
  -H "x-workspace-id: WORKSPACE_UUID"

Public intake (no agent JWT)

POST /api/public/chat/{workspaceSlug}/start

Start a public widget chat for a workspace slug.

curl -X POST "https://bolrach.com/help/api/public/chat/my-workspace/start" \
  -H "Content-Type: application/json" \
  -d '{"name":"Visitor","message":"Hi, I need help"}'
POST /api/public/intake/{workspaceSlug}/ticket

Public contact form intake into a ticket.

curl -X POST "https://bolrach.com/help/api/public/intake/my-workspace/ticket" \
  -H "Content-Type: application/json" \
  -d '{"subject":"Website form","body":"Need a callback","email":"visitor@example.com"}'

Estate bridge (DGUMS and internal services)

Service-to-service only, over the private network: the bridge is not reachable from the internet, so the examples use $HELP_INTERNAL_URL for the service address. Each caller sends its own Authvio workload token as Authorization: Bearer, minted for the audience https://bolrach.help/api/internal. Help checks the issuer, the exact audience and the subject, and each subject may use only the route groups it was granted: reading tickets needs help-bridge:tickets.read, creating, patching and replying need help-bridge:tickets.write, and the bulk import needs help-bridge:import. A new caller gets its own subject from the Authvio workload provisioner. Tokens last ten minutes and never leave the server.

GET /api/internal/bridge/health

Bridge liveness for estate monitors.

curl "$HELP_INTERNAL_URL/api/internal/bridge/health" \
  -H "Authorization: Bearer $AUTHVIO_WORKLOAD_TOKEN"
GET /api/internal/bridge/tickets

List tickets for a logical workspace key (default dgums).

curl "$HELP_INTERNAL_URL/api/internal/bridge/tickets?workspace=dgums&status=open" \
  -H "Authorization: Bearer $AUTHVIO_WORKLOAD_TOKEN"
POST /api/internal/bridge/tickets

Create a ticket from an estate app. DGUMS omnichannel escalate uses this path so new tickets land in the one Bolrach Help ticket plane.

curl -X POST "$HELP_INTERNAL_URL/api/internal/bridge/tickets" \
  -H "Authorization: Bearer $AUTHVIO_WORKLOAD_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"workspace":"dgums","subject":"WA escalate #42","body":"Customer needs billing help","priority":"high","channel":"chat","source":"dgums-omni","customerName":"Chioma","customerPhone":"+2348012345678","tags":["omni","whatsapp"],"externalRef":"omni:conv-uuid"}'

Related products

Notes

Machine-readable OpenAPI: /openapi/help.json. The platform catalogue (Help, Geo, AI, WhatsApp, …) is at api.bolrach.com/v1. Human mail on the estate stays on Stalwart; this API is the ticket / conversation engine, not the staff mailbox MTA.