WWaesta Enterprises U Ltd +256750081491 [email protected]
Base address for every call: https://waestaos.waestaltd.com

Support tickets API

Lets a connected system (Benofy, Webook, EduMaster...) raise support tickets on behalf of its own users, follow them, pass on the user's rating, and be told by webhook when we reply, resolve or close a ticket. New here? Read API.md first (keys, errors, rate limits, retries). Machine-readable: openapi.json.

Key: wcp_... · Base: https://waestaos.waestaltd.com/api/v1/support

Every ticket records the system it came from, so the case log, response times, satisfaction ratings and upgrade history stay in one professional record.

How it works

  1. Your system raises a ticket when a user reports a problem (POST /tickets), with your own external_ref.
  2. Our team replies and resolves it in *Customer care*. You can read it any time, and you are called on your webhook.
  3. When resolved, the user gets an email from [email protected] with what we did and a link to rate it. You can also collect the rating in your own screens and send it to us.
  4. A poor rating (1 or 2) re-opens the ticket and alerts our team. A good rating (3 to 5), or a week of silence, closes it.

Ticket status: open → in_progress / awaiting_client → resolved → closed. First-reply targets: urgent 2h · high 8h · normal 24h · low 72h.

Get connected

  1. Staff: *Customer care → Systems → the system → Connect this system (API)*.
  2. Choose the client account the tickets belong to (usually the client that owns or runs the system) and, optionally, a webhook address (https).
  3. Copy the API key and the webhook signing secret at once. They are shown once; only a hash of the key is stored.
  4. Put both in the connected system's settings, on its server.

A key sees only tickets of its own client account and system.

Raise a ticket

POST /api/v1/support/tickets

curl -X POST https://waestaos.waestaltd.com/api/v1/support/tickets \
  -H "Authorization: Bearer wcp_YOUR_KEY" -H "Content-Type: application/json" \
  -d '{
    "subject": "Report will not export",
    "message": "Clicking Export on the fees report does nothing. Started this morning.",
    "kind": "issue", "priority": "high", "external_ref": "BEN-4471",
    "reporter": { "name": "Grace Auma", "email": "[email protected]", "phone": "+256772000111" }
  }'

201 (or 200 with "replayed": true when the same external_ref was already used):

{
  "ok": true, "replayed": false,
  "ticket": {
    "id": 12, "ticket_no": "TICKET-2026-00012", "external_ref": "BEN-4471", "subject": "Report will not export",
    "status": "open", "kind": "issue", "priority": "high", "system": "Benofy",
    "opened_at": "2026-09-28T08:00:00+00:00", "first_response_at": null, "resolved_at": null,
    "first_reply_due": "2026-09-28 16:00:00 UTC",
    "resolution_type": null, "resolution": null, "feedback_link": null, "feedback": null
  }
}

Store ticket_no next to your own record: it is what you use in every other call.

Read tickets

  • GET /api/v1/support/tickets/{ticket_no}: the ticket plus its replies:
{ "ok": true, "ticket": { "ticket_no": "TICKET-2026-00012", "status": "resolved", "resolution_type": "fixed",
    "resolution": "We renewed the expired certificate.", "feedback_link": "https://waestaos.waestaltd.com/feedback/3f9c...", "feedback": null,
    "replies": [
      { "from": "customer", "message": "Clicking Export does nothing...", "at": "2026-09-28T08:00:00+00:00" },
      { "from": "support", "message": "We are checking.", "at": "2026-09-28T08:40:00+00:00" } ] } }
  • GET /api/v1/support/tickets?status=open&external_ref=BEN-4471&limit=25: list (newest first, up to 100). status is one of open, in_progress, awaiting_client, resolved, closed.

Internal notes, the internal root cause and staff names are never included. Once resolved, resolution_type (fixed, workaround, advice, upgrade, no_fault, duplicate, wont_fix) and resolution are filled in, and feedback_link is a page where the user can rate the help.

Add a message

POST /api/v1/support/tickets/{ticket_no}/replies { "message": "It is still failing" }

A reply on a resolved or closed ticket re-opens it. Returns the updated ticket.

Pass on a rating

POST /api/v1/support/tickets/{ticket_no}/feedback { "rating": 5, "comment": "Fast and polite" }

rating is 1 to 5. It works once per resolution and only after the ticket is resolved. (422 otherwise.) 1 or 2 re-opens the ticket; 3 to 5 closes it.

Errors

Webhooks

The same webhook address also receives **licence.changed** events about the client's subscription (see SYSTEMS_API.md). Check the event field and ignore events you do not handle.

If the key has a webhook address we POST JSON there:

{ "event": "ticket.resolved", "sent_at": "2026-09-28T09:15:00+00:00",
  "ticket": { "ticket_no": "TICKET-2026-00012", "external_ref": "BEN-4471", "status": "resolved", "resolution": "We renewed the expired certificate.",
              "feedback_link": "https://waestaos.waestaltd.com/feedback/3f9c..." } }

Headers on every call:

Answer with any 2xx, quickly. Otherwise we retry after 1 minute, 5 minutes, 30 minutes, 2 hours and 12 hours, then mark it failed (staff see failed webhooks on the system's page). The address must be https and public; private and internal addresses are refused. Webhooks are sent within minutes because the scheduler delivers them (run it every 5 minutes).

// PHP receiver
$body = file_get_contents('php://input');
$expected = 'sha256=' . hash_hmac('sha256', $body, $webhookSecret);
if (!hash_equals($expected, $_SERVER['HTTP_X_WAESTA_SIGNATURE'] ?? '')) { http_response_code(401); exit; }
$event = json_decode($body, true);
// find your record by $event['ticket']['external_ref'], update its status, show $event['ticket']['resolution']
http_response_code(204);

(A Node.js receiver is in API.md.)

Good practice

  • Always send external_ref and reporter: it makes retries safe and lets us answer the person directly.
  • Write the message for someone who cannot see your screen: what the user did, what they expected, what happened, when it started, any error text.
  • Use kind: "complaint" when a customer is unhappy: it gets high priority and management is alerted.
  • Show resolution and feedback_link inside your own product when a ticket is resolved, so users can rate help without leaving.
  • Treat the webhook as a nudge: if one is missed, GET /tickets/{ticket_no} always tells the truth.