ASQ API Reference
Thread-native community Q&A — REST API with configurable role-based access control
Base URL for all API requests:
https://api.asq.ai/v1
Every request scopes to a community. Most endpoints follow the pattern:
/v1/communities/{communityId}/resource
All responses return JSON. Timestamps are ISO 8601. IDs are Firestore-compatible strings. Pagination uses cursor-based startAfter + limit params.
Authentication
ASQ supports two auth modes. All requests require an Authorization header.
1. Firebase Auth Token (widget / client-side)
Authorization: Bearer {firebase_id_token}
Used by the embedded widget. The token carries the user's UID and custom claims (including role).
2. API Key + Secret (server-to-server)
Authorization: ApiKey {api_key}:{api_secret}
X-ASQ-As: {user_id}
Used for backend integrations, pre-seeding sessions, bulk imports, and admin operations. API keys are created in the community dashboard and scoped to a role.
API keys inherit the role assigned at creation. A key with moderator role cannot perform admin actions. Use X-ASQ-As to impersonate a user — requires admin role on the key.
Permission Model
ASQ uses a capability-based RBAC system. Each community defines roles, and each role is a set of capability flags. This means permissions are fully configurable — you decide exactly what each role can and cannot do.
How it works
user → community role
role.capabilities[action]
Each user has a role per community. A user can be admin in one community and viewer in another. Roles are stored in the user's community membership document.
{
"userId": "usr_abc123",
"communityId": "expo-2026",
"role": "speaker",
"customCapabilities": { // optional overrides
"session.create": true,
"thread.create": true,
"tag.manage": false
},
"joinedAt": "2026-03-28T10:00:00Z"
}
Custom overrides: The customCapabilities field lets you grant or revoke individual capabilities per user, on top of their role defaults. This is how you give one specific exhibitor tag-management powers without changing the whole exhibitor role.
Roles & Capabilities
ASQ ships with 6 default roles. All are fully configurable — rename them, change their capabilities, or create entirely new roles.
Default Roles
| Capability | admin | organizer | speaker | exhibitor | member | viewer |
|---|---|---|---|---|---|---|
| session.create | ✓ | ✓ | ✓ | ✓ | CFG | — |
| session.manage | ✓ | ✓ | — | — | — | — |
| session.join | ✓ | ✓ | ✓ | ✓ | ✓ | CFG |
| thread.create | ✓ | ✓ | ✓ | ✓ | CFG | — |
| thread.reply | ✓ | ✓ | ✓ | ✓ | ✓ | — |
| thread.read | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| room.create | ✓ | ✓ | ✓ | ✓ | CFG | — |
| room.join | ✓ | ✓ | ✓ | ✓ | ✓ | CFG |
| room.message | ✓ | ✓ | ✓ | ✓ | ✓ | — |
| tag.create | ✓ | ✓ | ✓ | CFG | CFG | — |
| tag.manage | ✓ | ✓ | — | — | — | — |
| tag.assign | ✓ | ✓ | ✓ | ✓ | CFG | — |
| member.invite | ✓ | ✓ | CFG | CFG | — | — |
| member.list | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| member.manage | ✓ | ✓ | — | — | — | — |
| knowledge.read | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| knowledge.curate | ✓ | ✓ | ✓ | — | — | — |
| community.configure | ✓ | CFG | — | — | — | — |
| analytics.view | ✓ | ✓ | CFG | CFG | — | — |
✓ = always on CFG = configurable (off by default) — = always off unless custom override
Community Configuration
Each community stores its permission config, session defaults, and feature flags in a single config document.
{
"communityId": "expo-2026",
"name": "PM Career Expo 2026",
"features": {
"sessions": true,
"rooms": true,
"knowledge": true,
"tags": true,
"meetingLinks": true,
"dm": false
},
"defaults": {
"sessionModes": ["ask-session","private-room","public-convo","ama","workshop"],
"sessionCategories": ["exhibitor","speaker","community","sponsor"],
"maxParticipantsDefault": 25,
"sessionDurationDefault": 45,
"threadVisibility": "community",
"autoSummarize": true
},
"roles": {
"admin": { "capabilities": { "session.create":true, "session.manage":true, "thread.create":true, "thread.reply":true, "thread.read":true, "room.create":true, "room.join":true, "room.message":true, "tag.create":true, "tag.manage":true, "tag.assign":true, "member.invite":true, "member.list":true, "member.manage":true, "knowledge.read":true, "knowledge.curate":true, "community.configure":true, "analytics.view":true }},
"organizer": { "capabilities": { "session.create":true, "session.manage":true, "thread.create":true, "thread.reply":true, "thread.read":true, "room.create":true, "room.join":true, "room.message":true, "tag.create":true, "tag.manage":true, "tag.assign":true, "member.invite":true, "member.list":true, "member.manage":true, "knowledge.read":true, "knowledge.curate":true, "community.configure":false, "analytics.view":true }},
"speaker": { "capabilities": { "session.create":true, "thread.create":true, "thread.reply":true, "thread.read":true, "room.create":true, "room.join":true, "room.message":true, "tag.create":true, "tag.assign":true, "member.list":true, "knowledge.read":true, "knowledge.curate":true }},
"exhibitor": { "capabilities": { "session.create":true, "thread.create":true, "thread.reply":true, "thread.read":true, "room.create":true, "room.join":true, "room.message":true, "tag.assign":true, "member.list":true, "knowledge.read":true }},
"member": { "capabilities": { "thread.reply":true, "thread.read":true, "room.join":true, "room.message":true, "member.list":true, "knowledge.read":true, "session.join":true }},
"viewer": { "capabilities": { "thread.read":true, "member.list":true, "knowledge.read":true }}
},
"registrationDefaults": {
"defaultRole": "member",
"approvalRequired": false,
"allowSelfRegister": true
}
}
Role Templates
Create custom roles for your community. Roles are just named capability bundles.
Request Body
{
"name": "panelist",
"label": "Panel Speaker",
"description": "Can create AMA sessions and threads, but not manage tags",
"capabilities": {
"session.create": true,
"session.join": true,
"thread.create": true,
"thread.reply": true,
"thread.read": true,
"room.create": true,
"room.join": true,
"room.message": true,
"tag.assign": true,
"member.list": true,
"knowledge.read": true,
"knowledge.curate": true
},
"sessionModes": ["ama", "public-convo"],
"maxSessions": 3
}
Response
{
"id": "role_panelist",
"name": "panelist",
"label": "Panel Speaker",
"capabilities": { ... },
"createdAt": "2026-03-28T10:00:00Z"
}
Requires community.configure
Returns all roles (built-in + custom) with their capability maps.
Requires community.configure or analytics.view
Request Body
{
"capabilities": {
"tag.create": true,
"member.invite": true
}
}
Merges with existing capabilities. Send false to revoke.
Requires community.configure
Capability Flags Reference
| Flag | Scope | Description |
|---|---|---|
| session.create | session | Create new sessions (Ask, AMA, Workshop, etc.) |
| session.manage | session | Edit/delete any session, change status, pin sessions |
| session.join | session | Join/reserve a spot in sessions |
| thread.create | thread | Post new question threads |
| thread.reply | thread | Add answers/replies to threads |
| thread.read | thread | View threads and answers |
| room.create | room | Spin up live rooms from threads |
| room.join | room | Enter an active room |
| room.message | room | Send messages in live rooms |
| tag.create | tag | Create new tags in the community taxonomy |
| tag.manage | tag | Edit, merge, delete, and re-parent tags |
| tag.assign | tag | Apply tags to threads/sessions |
| member.invite | member | Send invitations to join the community |
| member.list | member | View the people directory |
| member.manage | member | Change roles, ban, remove members |
| knowledge.read | knowledge | View summaries and knowledge base |
| knowledge.curate | knowledge | Edit/approve/reject auto-generated summaries |
| community.configure | admin | Change community settings, roles, features |
| analytics.view | admin | View engagement analytics and reports |
Sessions
Sessions are scheduled or live rooms — AMAs, workshops, exhibitor booths, public conversations. They can be pre-created by the API for conferences or created on-the-fly by users with the right role.
Request Body
{
"title": "Building Products That Scale",
"description": "Interactive AMA with product leaders",
"mode": "ama",
"category": "speaker",
"status": "scheduled",
"scheduledAt": "2026-04-15T14:00:00Z",
"duration": 60,
"maxParticipants": 50,
"meetLink": "https://meet.google.com/abc-defg-hij",
"visibility": "public",
"tags": ["product","leadership","scaling"],
"hosts": ["usr_sarah","usr_mike"],
"preCreatedThreads": [
{
"title": "What's the biggest mistake PMs make at Series B?",
"body": "Seed question for the AMA",
"tags": ["series-b","mistakes"],
"pinned": true
},
{
"title": "How do you prioritize when everything is P0?",
"body": "Common question — let's dig in",
"tags": ["prioritization"]
}
],
"settings": {
"allowAudienceThreads": true,
"requireApproval": false,
"autoRecord": true,
"autoSummarize": true
}
}
| Field | Type | Required | Description |
|---|---|---|---|
| title | string | required | Session title (max 120 chars) |
| mode | enum | required | ask-session private-room public-convo ama workshop |
| category | enum | optional | exhibitor speaker community sponsor or custom |
| status | enum | optional | draft scheduled live ended — defaults to draft |
| scheduledAt | ISO 8601 | optional | When the session goes live |
| duration | number | optional | Minutes. Default from community config |
| maxParticipants | number | optional | Cap. 0 = unlimited |
| meetLink | url | optional | External meeting URL (Meet, Zoom, Teams) |
| hosts | string[] | optional | User IDs of session hosts |
| preCreatedThreads | object[] | optional | Seed threads created with the session |
| tags | string[] | optional | Topic tags |
| settings | object | optional | Session-level overrides |
Requires session.create
Pre-seeding: Use preCreatedThreads to set up an AMA with starter questions, a workshop with exercise prompts, or an exhibitor booth with FAQ threads — all in a single API call.
Query Parameters
| Param | Type | Default | Description |
|---|---|---|---|
| status | enum | all | Filter: draft scheduled live ended |
| mode | enum | all | Filter by session mode |
| category | enum | all | Filter by category |
| host | string | — | Filter by host user ID |
| tag | string | — | Filter by tag |
| limit | number | 20 | Page size (max 100) |
| startAfter | string | — | Cursor for pagination |
Requires session.join or thread.read
Returns session with threads, participant count, hosts, and meeting link. Includes userPermissions block showing what the authenticated user can do in this session.
{
"id": "ses_abc123",
"title": "Building Products That Scale",
"mode": "ama",
"category": "speaker",
"status": "live",
"participantCount": 34,
"threads": [ ... ],
"userPermissions": {
"canPost": true,
"canReply": true,
"canManage": false,
"canJoinCall": true
}
}
Partial update. Only send fields to change. Hosts can update their own sessions; session.manage can update any.
{ "status": "live", "meetLink": "https://zoom.us/j/123456" }
Requires session.create (own) or session.manage (any)
Registers the authenticated user as a participant. For scheduled sessions, reserves a spot. For live sessions, joins immediately.
Requires session.join
Create up to 50 sessions in one call. Perfect for importing an entire conference schedule.
{
"sessions": [
{ "title": "...", "mode": "ama", ... },
{ "title": "...", "mode": "workshop", ... }
],
"defaults": {
"category": "exhibitor",
"visibility": "public",
"maxParticipants": 30
}
}
Requires session.manage
Threads
Threads are the core unit — a structured question that can attract answers, spawn rooms, and generate knowledge.
{
"title": "How to handle stakeholder misalignment?",
"body": "Our leadership team has conflicting priorities...",
"askType": "ask-session",
"sessionId": "ses_abc123",
"tags": ["stakeholders","alignment"],
"visibility": "community",
"meetLink": "https://meet.google.com/xyz",
"matchCriteria": {
"expertise": ["product-strategy","leadership"],
"minTrust": 70
}
}
| Field | Type | Required | Description |
|---|---|---|---|
| title | string | required | The question (max 200 chars) |
| askType | enum | optional | Matches session modes. Defaults to public-convo |
| sessionId | string | optional | Attach to an existing session |
| tags | string[] | optional | Topic tags |
| visibility | enum | optional | public community private |
| meetLink | url | optional | External call link |
| matchCriteria | object | optional | Auto-match people by expertise/trust |
Requires thread.create
Filterable by status, askType, sessionId, tag, authorId. Supports sort=recent|popular|unanswered.
Requires thread.read
{ "body": "In my experience at Stripe, we solved this by...", "parentId": null }
Nested replies use parentId. Top-level answers leave it null.
Requires thread.reply
{ "meetLink": "https://teams.microsoft.com/l/meetup/...", "maxParticipants": 8 }
Creates a live room linked to the thread. The thread pipeline: Ask → Match → Room → Summary → Knowledge.
Requires room.create
Rooms
Live conversation spaces. Always linked to a thread or session.
Returns rooms with status=active by default. Each room includes participant list with online status.
Requires room.join
{ "body": "Great point — I think the key insight is...", "type": "text" }
Requires room.message + must be a room participant
Closes the room, generates an auto-summary from the conversation, and promotes key takeaways back to the parent thread.
Requires Room host or session.manage
Members
Manage community members, their roles, and per-user capability overrides.
Query Parameters
| Param | Type | Description |
|---|---|---|
| status | enum | online in-room offline all |
| role | string | Filter by role name |
| expertise | string | Filter by expertise tag |
| search | string | Search name/bio |
Requires member.list
{
"email": "[email protected]",
"role": "speaker",
"customCapabilities": {
"tag.create": true
},
"sessionAccess": ["ses_abc123", "ses_def456"],
"sendInvite": true
}
Adds a member with a specific role. Use customCapabilities for per-user overrides. sessionAccess restricts which sessions they can see (omit for all).
Requires member.invite
{
"role": "exhibitor",
"customCapabilities": {
"session.create": true,
"tag.create": true,
"member.invite": true
}
}
Change a user's role or toggle individual capability flags. The final permission is: role.capabilities[flag] OR customCapabilities[flag].
Requires member.manage
{
"members": [
{ "email": "[email protected]", "role": "exhibitor", "name": "Acme Corp" },
{ "email": "[email protected]", "role": "speaker", "name": "Jane Doe" }
],
"defaults": { "sendInvite": true }
}
Import up to 200 members. Ideal for conference pre-registration.
Requires member.manage
Knowledge
Auto-generated summaries from resolved threads and completed rooms. The end product of ASQ's pipeline: Question → Room → Summary → Knowledge.
Query Parameters
| Param | Type | Description |
|---|---|---|
| q | string | Full-text search query |
| tag | string | Filter by tag |
| sessionId | string | Knowledge from a specific session |
| status | enum | approved pending rejected |
Requires knowledge.read
{ "status": "approved", "editedSummary": "Refined summary text..." }
Approve, reject, or edit auto-generated summaries before they become permanent knowledge.
Requires knowledge.curate
Widget Embed
Drop the ASQ widget into any website with 3 lines of code. The widget inherits the community's permission model — users see only what their role allows.
Quick Start
<!-- 1. Load ASQ -->
<script src="https://cdn.asq.ai/v1/asq.js"></script>
<link rel="stylesheet" href="https://cdn.asq.ai/v1/asq.css">
<!-- 2. Initialize -->
<script>
ASQ.init({
communityId: 'expo-2026',
firebaseConfig: { /* your config */ },
theme: 'light',
position: 'bottom-right',
features: {
sessions: true,
people: true,
knowledge: true
}
});
</script>
Configuration Options
| Option | Type | Default | Description |
|---|---|---|---|
| communityId | string | required | Your community identifier |
| firebaseConfig | object | required | Firebase project config |
| theme | string | light | light or dark |
| position | string | bottom-right | Widget position: bottom-right bottom-left |
| features | object | all on | Toggle widget features |
| locale | string | en | Language code |
| ssoToken | string | — | Pre-auth with your SSO provider |
| defaultView | string | home | Initial screen: home sessions people |
| sessionFilter | object | — | Pre-filter sessions shown (e.g. by category) |
SSO Integration
For platforms that have their own auth, pass a signed JWT to auto-login users:
ASQ.init({
communityId: 'expo-2026',
firebaseConfig: { ... },
ssoToken: 'eyJhbG...', // JWT signed with your ASQ API secret
ssoProvider: 'custom',
userMapping: {
id: 'sub', // JWT claim → ASQ user ID
name: 'name',
email: 'email',
role: 'asq_role' // optional: auto-assign role from JWT
}
});
JavaScript API
// Open/close widget programmatically
ASQ.open();
ASQ.close();
ASQ.toggle();
// Navigate to a specific session
ASQ.openSession('ses_abc123');
// Listen for events
ASQ.on('thread.created', (thread) => { ... });
ASQ.on('room.joined', (room) => { ... });
ASQ.on('session.started', (session) => { ... });
// Pre-fill a new thread
ASQ.createThread({
title: 'Question from the audience',
sessionId: 'ses_abc123',
tags: ['live-qa']
});
Webhooks
Get notified when things happen in your community. Configure webhooks in the dashboard or via API.
{
"url": "https://yoursite.com/asq-webhook",
"secret": "whsec_...",
"events": [
"session.created",
"session.started",
"session.ended",
"thread.created",
"thread.solved",
"room.started",
"room.ended",
"member.joined",
"knowledge.generated"
]
}
Requires community.configure
Webhook Payload
{
"event": "session.started",
"timestamp": "2026-04-15T14:00:00Z",
"communityId": "expo-2026",
"data": {
"sessionId": "ses_abc123",
"title": "Building Products That Scale",
"mode": "ama",
"hostIds": ["usr_sarah"],
"participantCount": 34
}
}