Prerequisites
Before you start, you need:
- A Disqua account — sign up free
- A workspace (created during onboarding)
curlor any HTTP client (Postman, Insomnia, etc.)
All API calls require HTTPS. HTTP requests will be redirected with a 301 to the HTTPS equivalent.
Step 1 — Get a token
Disqua uses Bearer token authentication. Pick the credential that fits what you are building:
- A quick script acting as you — log in and use the returned JWT
access_token(valid 15 minutes; renew it with therefresh_token). - An AI agent or long-running automation — in the console open Profile → AI access, create a master token (
dq_usr_…), then exchange it for a session key (dq_ai_…) scoped to one workspace withPOST /v1/ai/request-session-key. The master token is shown once. - An app other people connect to their Disqua — use OAuth 2.1 (see below). Access tokens start with
dq_oat_. - Just posting into a channel from another system — you need no token at all: create an incoming webhook.
curl -X POST https://api.disqua.com/v1/auth/login \
-H "Content-Type: application/json" \
-d '{ "email": "jane@example.com", "password": "YOUR_PASSWORD" }'
# → { "ok": true, "data": { "user": { … }, "access_token": "eyJ…", "refresh_token": "…" } }
# Accounts with 2FA get { "requires_2fa": true, "temp_token": "…" } —
# finish with POST /v1/auth/2fa/challenge { "temp_token": "…", "code": "123456" }.
Treat every token like a password. Never commit it to version control. Use environment variables or a secrets manager.
Step 2 — Make your first request
Verify your token by fetching your own profile:
curl https://api.disqua.com/v1/users/me \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
{
"ok": true,
"data": {
"user": {
"id": "7f9e…",
"username": "janedoe",
"display_name": "Jane Doe",
"email": "jane@example.com",
"avatar_url": null,
"status": "online"
},
"preferences": { … }
}
}
List channels in a workspace
Every resource lives under a workspace. Get your workspace_id from GET /v1/workspaces (add ?slug=your-slug to match one exactly), then:
curl "https://api.disqua.com/v1/workspaces/WORKSPACE_ID/channels" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
# → { "ok": true, "data": { "channels": [ { "id": "7a0c…", "name": "general", "type": "public", … } ] } }
Send a message
curl -X POST "https://api.disqua.com/v1/workspaces/WORKSPACE_ID/channels/CHANNEL_ID/messages" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{ "content": "Hello from the Disqua API!" }'
# 201 → { "ok": true, "data": { "message": { "id": "8b1d…", "content": "Hello from the Disqua API!",
# "content_html": "<p>Hello from the Disqua API!</p>", … } } }
OAuth 2.1 for third-party apps
Standard authorization code flow with PKCE (S256). Endpoints are published at https://api.disqua.com/.well-known/oauth-authorization-server; public clients can register themselves through dynamic client registration (POST /v1/oauth/register). Supported scopes: workspaces:read, channels:read, messages:read, messages:write, helpdesk:read, helpdesk:write, reminders:write, search:read.
GET https://console.disqua.com/oauth/authorize
?client_id=YOUR_CLIENT_ID
&redirect_uri=https://yourapp.com/callback
&response_type=code
&scope=channels:read+messages:read
&state=random_csrf_string
&code_challenge=BASE64URL(SHA256(code_verifier))
&code_challenge_method=S256
POST https://api.disqua.com/v1/oauth/token
Content-Type: application/x-www-form-urlencoded (JSON is accepted too)
grant_type=authorization_code
&code=AUTH_CODE_FROM_REDIRECT
&redirect_uri=https://yourapp.com/callback
&client_id=YOUR_CLIENT_ID
&code_verifier=YOUR_CODE_VERIFIER
# → { "access_token": "dq_oat_…", "token_type": "Bearer", "expires_in": …,
# "refresh_token": "…", "scope": "channels:read messages:read" }
Users see and revoke connected apps in the console under Profile → Apps.
Errors
All errors use the same envelope:
{
"ok": false,
"error": {
"code": "E_AUTHZ_NOT_MEMBER",
"message": "You are not a member of this workspace.",
"status": 403
}
}
| HTTP | Typical code | Meaning |
|---|---|---|
| 400 / 422 | E_VALIDATION_FAILED, E_VALIDATION_BAD_REQUEST | Body or parameters failed validation |
| 401 | E_AUTH_MISSING, E_AUTH_TOKEN_INVALID, E_AUTH_TOKEN_EXPIRED | No token, a bad one, or an expired one — refresh it |
| 402 | E_PLAN_FEATURE_NOT_AVAILABLE | The workspace plan does not include this feature or limit |
| 403 | E_AUTHZ_NOT_MEMBER, E_AUTHZ_INSUFFICIENT_ROLE, E_AUTHZ_FORBIDDEN | Not a member, wrong role, or the token's scope does not allow it |
| 404 | E_NOT_FOUND, E_CHANNEL_NOT_FOUND, … | Does not exist or is not visible to you |
| 429 | — | Rate limited (default 600 requests/min per user) — back off and retry |
| 500 | E_INTERNAL | Unexpected server error — contact support with the X-Request-ID response header |