Drıftstack docs
Docs

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".