Solvey.

Reference

Endpoints

Every route under https://solvey.io/api/v1. Authentication, errors and the rate limit are on Getting started; how webhooks behave is on Webhooks.

Me

The first call to make with a new key: who it is, and what it may do.

GET/meread

The key, its scope, and the person it acts as.

curl
curl https://solvey.io/api/v1/me \
  -H "Authorization: Bearer sk_live_…"
Response
{ "data": { "tenantId": "…", "key": { "id": "…", "name": "Zapier", "prefix": "sk_live_ab12cd", "scope": "read_write" }, "actor": { "id": "…", "role": "admin" } } }

Tickets

Everything the console's queue and ticket page can do. Wherever a path says {id}, pass either the ticket's uuid or its human key such as SLV-1043.

GET/ticketsread

List tickets, newest first, with filters and paging.

Query
statusStatus slugs (see /statuses). Repeat or comma-separate for any-of.
prioritylow, normal, high, urgent. Repeat or comma-separate.
assigneeIdUser ids, and/or the word unassigned.
tagOne tag.
limit1–100, default 25.
offsetDefault 0.
curl
curl https://solvey.io/api/v1/tickets?status=open,pending&priority=high&assigneeId=unassigned&limit=25 \
  -H "Authorization: Bearer sk_live_…"
Response
{ "data": [ {
      "id": "01a0…", "key": "SLV-1043", "source": "api",
      "subject": "Printer on floor 3 jams", "status": "open", "statusLabel": "Open",
      "priority": "high", "tags": ["printer"],
      "requester": { "id": "…", "name": "Dana Ortiz", "email": "dana@example.com" },
      "assignee": null,
      "sla": { "enabled": true, "firstResponse": { "phase": "on_track", "fillPercent": 12, "…": "…" }, "resolution": { "…": "…" } },
      "createdAt": "2026-09-05T11:28:03.702Z", "updatedAt": "2026-09-05T11:28:03.702Z"
    } ], "page": { "total": 42, "limit": 25, "offset": 0 } }

A key whose creator lacks view_all_tickets sees only their own tickets, as in the console.

POST/ticketsread_write

Create a ticket. Answers 201 with the ticket; source is api.

Body
subjectRequired, up to 200 characters.
descriptionRequired, up to 20,000 characters.
prioritylow, normal (default), high, urgent.
tagsUp to 20 tags.
requesterIdWho the ticket is for; defaults to the key's creator.
assigneeIdA team member's id.
customFieldsObject of field id → value, e.g. { "<fieldId>": "value" }.
curl
curl https://solvey.io/api/v1/tickets \
  -H "Authorization: Bearer sk_live_…"
  -H "Content-Type: application/json" \
  -d '{ "subject": "Printer on floor 3 jams", "description": "Every second page.", "priority": "high", "tags": ["printer"] }'
Response
{ "data": {
  "id": "01a0…", "key": "SLV-1043", "source": "api",
  "subject": "Printer on floor 3 jams", "status": "open", "statusLabel": "Open",
  "priority": "high", "tags": ["printer"],
  "requester": { "id": "…", "name": "Dana Ortiz", "email": "dana@example.com" },
  "assignee": null,
  "sla": { "enabled": true, "firstResponse": { "phase": "on_track", "fillPercent": 12, "…": "…" }, "resolution": { "…": "…" } },
  "createdAt": "2026-09-05T11:28:03.702Z", "updatedAt": "2026-09-05T11:28:03.702Z"
} }

GET/tickets/{id}read

One ticket in full: fields, description, custom fields, comments, events, merge links.

curl
curl https://solvey.io/api/v1/tickets/SLV-1043 \
  -H "Authorization: Bearer sk_live_…"
Response
{ "data": { …ticket…, "description": "Every second page.", "customFields": [ … ], "comments": [ … ], "events": [ … ], "mergedInto": null, "mergedFrom": [] } }

PATCH/tickets/{id}read_write

Change any of subject, description, status, priority, assigneeId, tags, customFields.

Body
statusA status slug.
assigneeIdA user id, or null to unassign.
tagsThe whole list; it replaces the old one.
curl
curl https://solvey.io/api/v1/tickets/SLV-1043 \
  -H "Authorization: Bearer sk_live_…"
  -H "Content-Type: application/json" \
  -X PATCH -d '{ "status": "work_in_progress", "assigneeId": "…" }'
Response
{ "data": { …ticket… } }

Every change appends to the ticket's event log; the answer is the ticket after the change.

GET/tickets/{id}/commentsread

The thread the key's creator may see.

curl
curl https://solvey.io/api/v1/tickets/SLV-1043/comments \
  -H "Authorization: Bearer sk_live_…"
Response
{ "data": [ { "id": "…", "kind": "public", "body": "Fixed tomorrow.", "author": { … }, "createdAt": "…" } ] }

POST/tickets/{id}/commentsread_write

Post a public reply or an internal note. Answers 201 with the ticket.

Body
bodyRequired.
kindpublic — the requester sees it; internal — never leaves the organization.
curl
curl https://solvey.io/api/v1/tickets/SLV-1043/comments \
  -H "Authorization: Bearer sk_live_…"
  -H "Content-Type: application/json" \
  -d '{ "body": "Fixed tomorrow.", "kind": "public" }'
Response
{ "data": { …ticket with the new comment… } }

POST/tickets/{id}/mergeread_write

Mark {id} as a duplicate of another ticket. Link-only: both histories stay.

Body
targetThe survivor, as uuid or human key. targetId is accepted too.
curl
curl https://solvey.io/api/v1/tickets/SLV-1043/merge \
  -H "Authorization: Bearer sk_live_…"
  -H "Content-Type: application/json" \
  -d '{ "target": "SLV-1042" }'
Response
{ "data": { …the duplicate, with mergedInto set… } }

Users, tags, statuses

The vocabulary around tickets. Read-only: people join through invitations in the console, tags are created by using them, statuses are defined by admins.

GET/usersread

Everyone in the organization with their role.

curl
curl https://solvey.io/api/v1/users \
  -H "Authorization: Bearer sk_live_…"
Response
{ "data": [ { "id": "…", "name": "Sam Lee", "email": "sam@example.com", "role": "agent", "joinedAt": "…" } ] }

GET/tagsread

Tags in use, sorted.

curl
curl https://solvey.io/api/v1/tags \
  -H "Authorization: Bearer sk_live_…"
Response
{ "data": ["printer", "vpn"] }

GET/statusesread

The organization's statuses — the slugs status accepts.

curl
curl https://solvey.io/api/v1/statuses \
  -H "Authorization: Bearer sk_live_…"
Response
{ "data": [ { "slug": "open", "label": "Open", "isTerminal": false, "slaClockRunning": true, "sortOrder": 0 } ] }

Add-ons

Optional features, on or off per organization — the requester portal, ticket merge, webhooks, and the assistant's doors as they ship. Everything listed is included in the plan.

GET/addonsread

Every add-on with its state.

curl
curl https://solvey.io/api/v1/addons \
  -H "Authorization: Bearer sk_live_…"
Response
{ "data": [ { "id": "webhooks", "label": "Webhooks", "category": "Integrations", "description": "…", "status": "available", "price": "Included", "enabled": true }, { "id": "assistant.triage", "status": "coming_soon", "enabled": false, "…": "…" } ] }

A feature whose add-on is off answers 403 addon_disabled on the routes that need it.

PATCH/addons/{id}read_write

Turn an add-on on or off (admin). Add-ons marked coming_soon cannot be turned on yet.

curl
curl https://solvey.io/api/v1/addons/SLV-1043 \
  -H "Authorization: Bearer sk_live_…"
  -H "Content-Type: application/json" \
  -X PATCH -d '{ "enabled": false }'
Response
{ "data": { "id": "webhooks", "enabled": false } }

Billing

Where the organization stands: seats bought and in use, the monthly quote, trial and period dates. Subscribing happens in the console (Paddle's checkout); changing seats, cancelling and resuming are here too.

GET/billingread

The billing summary.

curl
curl https://solvey.io/api/v1/billing \
  -H "Authorization: Bearer sk_live_…"
Response
{ "data": { "phase": "active", "status": "active", "writable": true, "seatsInUse": 4, "seatsPurchased": 6, "seatsUnused": 2, "overSeats": false, "quote": { "totalCents": 5800, "breakdown": [ … ] }, "trialEndsAt": "…", "currentPeriodEnd": "…", "cancelAt": null, "hasSubscription": true } }

phase is one of trial, trial_expired, active, past_due, canceled. When writable is false the organization can read and export but not change anything — every write answers 402 billing_locked.

Admins, agents and assistants hold seats; requesters are free. While subscribed, team invitations and promotions stop at seatsPurchased and answer 409 seats_exhausted. The trial has no cap.

POST/billing/seatsread_write

Change the purchased seats. Up is charged now, pro rata; down is credited now. Never below the people holding a seat.

Body
seatsA whole number, at least the people holding a seat today.
curl
curl https://solvey.io/api/v1/billing/seats \
  -H "Authorization: Bearer sk_live_…"
  -H "Content-Type: application/json" \
  -d '{ "seats": 8 }'

POST/billing/cancelread_write

Cancel at the end of the paid period. The team keeps what it paid for; cancelAt says when.

curl
curl https://solvey.io/api/v1/billing/cancel \
  -H "Authorization: Bearer sk_live_…"
  -X POST

POST/billing/resumeread_write

Undo a scheduled cancellation.

curl
curl https://solvey.io/api/v1/billing/resume \
  -H "Authorization: Bearer sk_live_…"
  -X POST

POST/billing/portalread_write

A short-lived link to Paddle's customer portal: card, invoices, receipts.

curl
curl https://solvey.io/api/v1/billing/portal \
  -H "Authorization: Bearer sk_live_…"
  -X POST
Response
{ "data": { "url": "https://customer-portal.paddle.com/…" } }

Webhooks

Manage subscriptions and read the delivery log. The how-it-works — events, signatures, retries — is on the Webhooks page.

GET/webhooksread

Subscriptions.

curl
curl https://solvey.io/api/v1/webhooks \
  -H "Authorization: Bearer sk_live_…"

POST/webhooksread_write

Subscribe a URL to events. The signing secret is in this answer and nowhere else.

Body
urlhttp:// or https://.
eventsOne or more event types.
descriptionOptional.
curl
curl https://solvey.io/api/v1/webhooks \
  -H "Authorization: Bearer sk_live_…"
  -H "Content-Type: application/json" \
  -d '{ "url": "https://example.com/hooks/solvey", "events": ["ticket.created", "ticket.replied"] }'
Response
{ "data": { "id": "…", "url": "…", "events": [ … ], "active": true, … }, "secret": "whsec_…" }

GET/webhooks/{id}read

One subscription.

curl
curl https://solvey.io/api/v1/webhooks/SLV-1043 \
  -H "Authorization: Bearer sk_live_…"

PATCH/webhooks/{id}read_write

Change url, description, events, or active (pause with false).

curl
curl https://solvey.io/api/v1/webhooks/SLV-1043 \
  -H "Authorization: Bearer sk_live_…"
  -H "Content-Type: application/json" \
  -X PATCH -d '{ "active": false }'

DELETE/webhooks/{id}read_write

Delete the subscription and its delivery log. Answers 204.

curl
curl https://solvey.io/api/v1/webhooks/SLV-1043 \
  -H "Authorization: Bearer sk_live_…"
  -X DELETE

GET/webhooks/{id}/deliveriesread

The delivery log, newest first.

Query
limitDefault 50, up to 200.
curl
curl https://solvey.io/api/v1/webhooks/SLV-1043/deliveries \
  -H "Authorization: Bearer sk_live_…"
Response
{ "data": [ { "id": "…", "eventType": "ticket.created", "status": "succeeded", "attemptCount": 1, "lastStatusCode": 200, "lastError": null, "completedAt": "…", "createdAt": "…" } ] }

GET/webhooks/deliveries/{deliveryId}read

One delivery with its payload and every attempt.

curl
curl https://solvey.io/api/v1/webhooks/deliveries/01a0… \
  -H "Authorization: Bearer sk_live_…"

POST/webhooks/deliveries/{deliveryId}/redeliverread_write

Queue the same payload again. Answers 202.

curl
curl https://solvey.io/api/v1/webhooks/deliveries/01a0…/redeliver \
  -H "Authorization: Bearer sk_live_…"
  -X POST