Business API
The Business REST API gives you programmatic access to websites, feedback threads, and comments.
Outbound webhooks let your systems react to feedback events in real time.
Both features are available on the Business plan and use secret credentials that must never be exposed in client-side code.
Business plan
Base URL: https://suggestra.dev/api/v1
Send your secret key on every request:
http
Authorization: Bearer sk_your_secret_key
- Keys start with
sk_ and belong to your subscription, not an individual website.
- Embed keys (
mk_…) are not accepted on Business API routes.
- Generate or rotate keys from Dashboard → API after upgrading.
These query parameters apply to GET /threads and GET /export:
| Parameter |
Description |
website or website_id |
Numeric website ID. Must belong to your account. |
status |
One of open, resolved, reopened, closed. |
from |
Earliest thread creation date (ISO 8601 or YYYY-MM-DD). |
to |
Latest thread creation date. Date-only values include the full day. |
GET
/api/v1/websites
List all websites on your account, including embed keys and widget settings.
Response
json
{
"websites": [
{
"id": 1,
"name": "Acme Marketing",
"domain": "acme.com",
"widgetPosition": "right",
"embedApiKey": "mk_…"
}
]
}
Example
bash
curl -s -H "Authorization: Bearer sk_…" \
"https://suggestra.dev/api/v1/websites"
GET
/api/v1/threads
List feedback threads with nested comments. Supports filter query parameters.
Response
json
{
"threads": [ { "id": 42, "status": "open", "comments": [ … ], … } ],
"meta": {
"count": 12,
"filters": { "websiteId": 1, "status": "open", "from": null, "to": null }
}
}
Example
bash
curl -s -H "Authorization: Bearer sk_…" \
"https://suggestra.dev/api/v1/threads?website=1&status=open&from=2026-01-01"
PATCH
/api/v1/threads/{id}
Update a thread status. Same transition rules as the dashboard.
Request body
json
{ "status": "resolved" }
Response
json
{ "thread": { "id": 42, "status": "resolved", … } }
DELETE
/api/v1/threads/{id}
Permanently delete a thread, its comments, and any attached screenshot. Returns 204 No Content.
GET
/api/v1/export
Export feedback as JSON or CSV. CSV returns one row per comment; threads without comments still appear as a single row.
Query parameters
-
format
optional — json (default) or csv
-
website, status, from, to
optional — Same filters as GET /threads
Example
bash
curl -s -H "Authorization: Bearer sk_…" \
"https://suggestra.dev/api/v1/export?format=csv&from=2026-01-01" \
-o suggestra-feedback.csv
Business plan accounts can register an HTTPS endpoint to receive real-time notifications when feedback changes.
Configure your endpoint URL and subscribed events from Dashboard → Webhooks.
- Enter your server URL (must accept
POST with a JSON body).
- Select which events to receive — you can enable any combination.
- Suggestra generates a signing secret (
whsec_…). Use it to verify the X-Suggestra-Signature header on every delivery.
- Use Send test webhook in the dashboard to confirm your endpoint is reachable.
Each delivery is an HTTP POST with a JSON body and these headers:
| Header |
Description |
X-Suggestra-Event |
Event type (same as the event field in the body). |
X-Suggestra-Delivery |
Unique delivery ID for deduplication. |
X-Suggestra-Signature |
sha256=<hmac> — HMAC-SHA256 of the raw JSON body using your signing secret. |
json
{
"id": "evt_abc123…",
"event": "thread.created",
"createdAt": "2026-06-17T14:30:00+00:00",
"data": {
"thread": { "id": 42, "status": "open", "comments": [ … ], … }
}
}
Return any 2xx status to acknowledge delivery. Non-success responses are logged but not retried automatically.
| Event |
When it fires |
data payload |
thread.created |
A visitor or reviewer pins new feedback on a website. |
thread — full thread object with nested comments. |
comment.created |
A reply is added to an existing thread (embed, dashboard, or API). |
thread, comment |
thread.status_changed |
Thread status is updated (open → resolved, etc.). |
thread, previousStatus |
thread.deleted |
A thread is permanently deleted. |
thread — snapshot before deletion. |
webhook.test |
Sent manually from the dashboard test button. |
message |
Thread and comment objects match the shapes returned by the REST API
(GET /api/v1/threads). See the endpoint reference above for field definitions.
Compute HMAC-SHA256 over the raw request body (before JSON parsing) and compare to the signature header:
php
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_SUGGESTRA_SIGNATURE'] ?? '';
$expected = 'sha256=' . hash_hmac('sha256', $payload, $signingSecret);
if (!hash_equals($expected, $signature)) {
http_response_code(401);
exit('Invalid signature');
}
Thread status can be open, resolved, reopened, or closed. Valid transitions:
| From |
Allowed next statuses |
open, reopened |
resolved, closed |
resolved |
reopened, closed |
closed |
reopened |
Threads cannot transition back to open — use reopened instead. Invalid transitions return 400 Bad Request.
Errors use standard HTTP status codes with a JSON body when applicable:
| Status |
Meaning |
401 Unauthorized |
Missing or invalid API key. |
403 Forbidden |
Valid key but account lacks Business API access. |
404 Not Found |
Thread ID not found on your account. |
400 Bad Request |
Invalid JSON, filter values, or status transition. |
json
{
"type": "https://tools.ietf.org/html/rfc2616#section-10",
"title": "Bad Request",
"status": 400,
"detail": "Cannot change thread status from \"resolved\" to \"open\"."
}