Help
The same conversations you see under Help in the desktop app and the
dashboard, reachable from your program. A message you send lands with
Driftstack support already linked to your account. Email support on every
plan, the trial too. Replies appear here, and a
copy is sent to your account’s email address, always from
[email protected]. Conversations
started by email continue by email and are not listed here.
A conversation belongs to the account that wrote it. In a shared workspace a
teammate’s conversations are theirs, and the workspace is context only; the
X-Driftstack-Account header is ignored on these routes.
Routes
| Route | Scope | What it does |
|---|---|---|
GET /v1/support/conversations |
read |
Your conversations, newest first, with unread_count and open_count. |
POST /v1/support/conversations |
write |
A new conversation with its first message. Honours Idempotency-Key. |
GET /v1/support/conversations/{id} |
read |
One conversation with its messages. |
POST /v1/support/conversations/{id}/messages |
write |
A follow-up. Reopens a closed conversation and marks it read. |
POST /v1/support/conversations/{id}/read |
write |
Marks it read (explicit, so a GET has no side effect). |
POST /v1/support/conversations/{id}/close |
write |
You resolved it. Either side writing again reopens it. |
Starting a conversation
curl -X POST https://api.driftstack.dev/v1/support/conversations \
-H "Authorization: Bearer $DRIFTSTACK_API_KEY" \
-H "Idempotency-Key: 6f1c0d9e-help-1" \
-H "Content-Type: application/json" \
-d '{
"subject": "Session stops with proxy refused its sign-in",
"body": "Every session on my NL profile stops after about five seconds.",
"topic_hint": "session",
"context": {
"app_version": "0.1.73",
"platform": "macOS",
"deployment": "cloud",
"session_id": "<agt_ id of the session>",
"last_error": ["proxy_auth_failed"]
}
}'
const { conversation } = await client.support.create({
subject: 'Session stops with proxy refused its sign-in',
body: 'Every session on my NL profile stops after about five seconds.',
topic_hint: 'session',
});
The response is 201 with the conversation and your message. Retrying with
the same Idempotency-Key returns the original conversation with 200
instead of opening a second one; see Idempotency keys.
topic_hint is one of question, session, billing, account, other.
It is a hint for sorting; it does not change who reads the message.
What context may contain
Every field is optional and bounded; unknown fields are refused with 400.
| Field | Bound | Kept when |
|---|---|---|
app_version |
32 characters | always |
platform |
256 characters | always |
deployment |
cloud / self-hosted |
always |
workspace_account_id |
an acc_… id |
you are a member of that workspace (any role); otherwise dropped |
profile_id |
a prof_… id |
it is yours, or belongs to a workspace you are a member of |
session_id |
an agt_… id |
it is yours, or belongs to a workspace you are a member of |
last_error |
5 lines × 400 chars | always; URLs on hosts other than Driftstack’s own (driftstack.io, api.driftstack.dev) become [url removed] |
A user name or password in a web address, and a value Driftstack recognises as
a credential by its name or its format (such as a Driftstack or Anthropic API
key, or a bearer token), are removed from the subject, the body and every
last_error line before storage; a credential written in any other form, such
as a proxy password typed out in full, is stored as written. The whole
context object is capped at 4 KiB. Never send cookies, page content or proxy
credentials; nothing here needs them.
Reading
const page = await client.support.list();
const detail = await client.support.get(page.data[0].id);
for (const m of detail.messages) console.log(m.author, m.body);
A conversation’s status is waiting_for_driftstack, waiting_for_you or
closed. A message’s author is you or driftstack; via is app,
dashboard or email. A staff reply appears once it is delivered, about a
minute after it was approved.
Limits
At most 3 open conversations per account, 5 new conversations an
hour, 30 messages a day, and one new conversation every 10 seconds.
Past any of these the route answers 429 with reason: "support_limit_reached" and retry_after_seconds; the messages you already
sent are safe. Every route also draws on the account’s global rate-limit
bucket.
Creating a conversation requires a verified email address, because the reply
copy goes there; an unverified account gets 403.
Errors
| Status | When |
|---|---|
400 |
The body fails validation, or Idempotency-Key is malformed. |
403 |
The account’s email address is not verified. |
404 |
The conversation does not exist or belongs to another account. |
429 |
A ceiling above, reason: "support_limit_reached". |