Issues and feature requests
Sonora reads your customers’ support tickets, emails, calls and chats and distills them into issues (problems a customer raised) and feature requests (capabilities a customer asked for). Each one belongs to a customer and lists the sources it was found in. Reading issues needs a key with the issues:read scope; reading feature requests needs feature-requests:read. Resolving and reopening issues needs issues:write. Every field is in the API reference; this page covers how to use them.
The two resources work the same way, so everything below about issues holds for feature requests too, at /feature-requests in place of /issues.
List issues
Section titled “List issues”curl "https://api.usesonora.com/v1/issues?status=open&limit=50" \ -H "Authorization: Bearer sonora_sk_…"{ "data": [ { "id": "7e1a…", "customer": { "id": "c1d2…", "name": "Acme" }, "title": "Login loops back to the sign-in page", "summary": "Users on SSO are redirected to the sign-in page after authenticating; …", "category": "Authentication", "status": "Open", "priority": "High", "occurredAt": "2026-09-28T09:14:00.000Z", "lastActivityAt": "2026-10-13T17:40:22.000Z", "sourceCount": 2, "sources": [ { "type": "zendesk_support_tickets", "externalId": "48213" }, { "type": "gong_calls", "externalId": "7782910034" } ], "createdAt": "2026-09-28T09:20:41.118Z", "updatedAt": "2026-10-13T17:41:02.553Z", "links": { "self": "https://api.usesonora.com/v1/issues/7e1a…" } } ], "nextCursor": "MjAyNi0wOS0yOFQw…"}Issues come newest first. Narrow the list with:
| Parameter | |
|---|---|
customerId |
One customer’s issues, by Sonora id. |
status, priority |
Comma-separated, matched without regard to case (status=open,pending). |
includeArchived |
true to list archived customers’ issues too. |
createdAfter, updatedAfter |
ISO 8601 instants with an offset. |
status and priority are what the source system said, so their values are your tools’ own: Zendesk’s solved, a Salesforce case’s Closed - Duplicate, and so on; status is null when the source gave none. A feature request’s status is always set; open, pending and in_review mean it is still waiting on an answer.
occurredAt is when the issue was first raised, in its earliest source’s own system; lastActivityAt is the latest update among its sources. Either is null when no source carried a date. createdAt is when Sonora recorded the issue — for an import of old tickets, much later than occurredAt. createdAfter and the default order read createdAt.
Sources
Section titled “Sources”sources lists every ticket, email, call or conversation the issue was found in, oldest link first. type names the system and kind of record (zendesk_support_tickets, salesforce_support_cases, intercom_tickets, gmail, gong_calls, slack_conversations, aha_ideas, …), and externalId is the record’s id there, so you can link back to it. externalId is null where Sonora keeps no single id — a feature request found in a meeting, say. New types appear as Sonora reads new systems, so treat type as an open set.
Feature requests
Section titled “Feature requests”A feature request carries the same fields plus requestedAt, requestedBy and estimatedValue. requestedBy names the person who asked when the source does (an Aha! idea’s author, a Pylon request’s requester); for a request Sonora found in a call or a Slack thread it names the analysis instead (Meeting Transcript Analysis). estimatedValue is a number in your workspace’s currency, or null.
One customer’s issues
Section titled “One customer’s issues”GET /customers/{customerId}/issues lists a single customer’s issues, with the same filters and order. It names the customer the way GET /customers/{customerId} does — Sonora’s id, or your own system’s with idType:
curl "https://api.usesonora.com/v1/customers/001Ab00000XyZ12/issues?idType=salesforce" \ -H "Authorization: Bearer sonora_sk_…"Because the path names the customer, its issues are listed even when it is archived. An id that matches no customer is 404 customer_not_found.
Get one issue
Section titled “Get one issue”GET /issues/{issueId} returns one issue, archived customer or not. No issue with that id in your workspace is 404 issue_not_found (feature_request_not_found for GET /feature-requests/{featureRequestId}).
Resolve or reopen an issue
Section titled “Resolve or reopen an issue”PATCH /issues/{issueId} marks an issue resolved, or reopens it, as Mark resolved and Reopen on the issue’s panel in Sonora do. It needs the issues:write scope, with issues:read:
curl -X PATCH "https://api.usesonora.com/v1/issues/7e1a…" \ -H "Authorization: Bearer sonora_sk_…" \ -H "Content-Type: application/json" \ -d '{ "status": "resolved" }'The answer is the issue, with "status": "resolved" and a new updatedAt. Send { "status": "open" } to reopen it.
- Only
openandresolved. Those are the statuses a person can set in Sonora. Anything else — another status, another field — is400 invalid_request. - Only issues no support ticket backs. When a Zendesk ticket, a Salesforce case or another support ticket is among an issue’s
sources, the ticket’s own status is copied onto the issue every time Sonora syncs it, so a change here wouldn’t last and Sonora would disagree with your support tool. Those answer409 status_managed_by_source: close the ticket there instead. Issues found only in emails, calls and chats are yours to resolve. - Safe to repeat. Setting the status an issue already has changes nothing, and
updatedAtdoesn’t move. A status spelled another way is a change: resolving an issue whosestatusisClosedsets it toresolved. - A resolved issue can come back. If a customer raises it again in a new email, call or chat, Sonora reopens it on its own, as it does after a person resolves it in Sonora.
Feature requests have no status a person sets in Sonora, so the API doesn’t change them either.
Quotes
Section titled “Quotes”Add include=quotes to any of these calls and each issue carries quotes, the customer’s own words behind it:
"quotes": [ { "text": "We get bounced back to the login page every single time.", "personName": "Pat Buyer", "personTitle": "IT Lead", "personEmail": "pat@acme.com" }]Quotes are opt-in because they name people at your customers, with their email addresses where Sonora knows them. Ask for them only where you need them, and handle them as the personal data they are. Without include=quotes the field is left out, not empty. A feature request’s quotes come from the calls and Slack threads it was found in, so personTitle is always null there.
Keep another system in step
Section titled “Keep another system in step”Syncing issues works like syncing customers:
- First run:
GET /issues?sort=updatedAt&includeArchived=true, followingnextCursorto the last page. Remember the largestupdatedAtyou saw. - Each later run:
GET /issues?sort=updatedAt&includeArchived=true&updatedAfter=<that updatedAt minus 5 minutes>.
Upsert by id, so the overlap costs nothing. An issue’s updatedAt moves whenever it changes, including when Sonora links a new source to it. A feature request’s updatedAt moves when the request itself changes, but linking another source may not move it — so a sync can miss a new source on an otherwise unchanged request until something else about it changes. Read a request again with GET /feature-requests/{featureRequestId} when you need its sources current.
A cursor belongs to the order it came from: one from sort=updatedAt is refused under the default order, and the reverse.