API reference
Authentication, errors, limits and every partner action, written from Dium's source.
How every call works
The Dium API is JSON over HTTPS. Each area has one PHP file under https://dium.io/api/. Every call is a POST with a JSON body, and the action field picks what happens. There is no versioned path and no SDK.
curl -sS https://dium.io/api/ladder.php \
-H "Content-Type: application/json" \
-d '{"action":"get","slug":"acme-summit"}'Browsers can call the API only from origins on Dium's CORS allowlist. Allowed methods are GET, POST and OPTIONS. Allowed headers are Content-Type, Authorization, X-Api-Key and X-Requested-With.
Authentication
There are two kinds of caller.
| Caller | How it authenticates | Used for |
|---|---|---|
| Your server (partner) | X-Api-Key: <your key> header. The api_key body field still works but is legacy. | Partner actions: tokens, Flows, Waves, Pages |
| A signed-in member | Session cookie, or Authorization: Bearer <token> from the mount | Everything the Dium app does for that member |
Scopes
Each partner key carries a list of scopes named after actions, such as auth.issue_token or exhibit.create. A key with * can call every partner action. Ask for the smallest set you need.
401 or 403
No key was sent, or the key does not match any partner. Keys are compared in constant time.
The key is valid but its scopes do not include this action.
X-Api-Key from a browser, even though CORS allows the header. Anyone who can read your page source can read the key.Responses and errors
Success returns HTTP 200 and a JSON object with "success": true plus the data for that action. Failures return an error status and an error message.
{
"success": true,
"token": "<48 hex>",
"expires_in": 300
}{
"error": "..."
}| Status | Meaning |
|---|---|
200 | The action ran. |
400 | A required field is missing. Dium checks required fields before anything else. |
401 | No valid partner key, or no signed-in member for a member action. |
403 | The key lacks the scope, or the member lacks the role or profile-type permission. |
Error messages are for people, not code: they are not a stable list of error codes yet. Branch on the HTTP status. The exact data fields returned by most actions are not published yet. Where a table on this page lists returned fields, they follow Dium's database schema.
Timestamps are stored in US Eastern time (UTC-4). Convert on your side before display.
Rate limits
Limits are counted per IP address, in one-minute windows.
| Scope | Limit |
|---|---|
| Default for rate-limited endpoints | 60 requests per 60 seconds |
answer.php create | 30 per minute |
message.php send | 30 per minute |
moderation.php report | 10 per minute |
upload.php | 20 per minute |
If you hit a limit, wait and retry with exponential backoff. Spread bulk jobs, such as seeding an agenda, over time rather than sending them in one burst.
Partner endpoints
These actions accept your partner key. Fields marked from schema are named after Dium's database columns or app code; confirm them with us before you depend on them.
POST/api/auth.php action: issue_token
Mint a one-time sign-in token for a member. The token lasts 300 seconds and can be used once, at /home/autologin.php.
actionstringrequired"issue_token"
emailstringrequiredThe member's email. Must come from your own signed-in session.
namestringoptionalDisplay name, used when the account is new.
avatarstring (URL)optionalAvatar image URL, used when the account is new.
curl -sS https://dium.io/api/auth.php \
-H "Content-Type: application/json" \
-H "X-Api-Key: $DIUM_API_KEY" \
-d '{"action":"issue_token","email":"[email protected]","name":"Jane Doe"}'{
"success": true,
"token": "<48 hex characters>",
"expires_in": 300
}POST/api/ladder.php action: create
Create a Flow (a community). Pass your own external_id: it is unique, so a retry cannot create a second Flow for the same event.
actionstringrequired"create"
namestringrequiredFlow name shown to members.
slugstringoptionalURL slug, used in /asq/d/{slug}.
room_slugstringoptionalGroups sibling Flows into one Room that shares members and DMs.
external_idstring, max 64optionalYour ID for this Flow, such as an event ID. Unique.
settings_jsonobjectoptionalFlow settings: profile_types[], event_url, features and more.
curl -sS https://dium.io/api/ladder.php \
-H "Content-Type: application/json" \
-H "X-Api-Key: $DIUM_API_KEY" \
-d '{"action":"create","name":"Acme Summit 2026","slug":"acme-summit","external_id":"EVENT-123"}'{
"success": true,
...
}POST/api/ladder.php action: get
Read one Flow with its settings. This action is public.
actionstringrequired"get"
idintegeroptionalfrom schemaFlow ID. Send id or slug.
slugstringoptionalfrom schemaFlow slug.
Returned fields follow the Flow record: id, slug, room_slug, name, tagline, description, category, logo_url, banner_url, color_primary, color_accent, visibility, join_mode, external_id, settings_json.
curl -sS https://dium.io/api/ladder.php \
-H "Content-Type: application/json" \
-d '{"action":"get","slug":"acme-summit"}'{
"success": true,
...
}POST/api/ladder.php action: update
Change a Flow's name, description or settings.
actionstringrequired"update"
idintegerrequiredfrom schemaFlow ID.
namestringoptionalNew name.
descriptionstringoptionalNew description.
settings_jsonobjectoptionalReplacement settings object.
curl -sS https://dium.io/api/ladder.php \
-H "Content-Type: application/json" \
-H "X-Api-Key: $DIUM_API_KEY" \
-d '{"action":"update","id":42,"description":"Questions and sessions for Acme Summit"}'{
"success": true,
...
}POST/api/ladder.php action: list
List Flows, most recently active first.
actionstringrequired"list"
curl -sS https://dium.io/api/ladder.php \
-H "Content-Type: application/json" \
-H "X-Api-Key: $DIUM_API_KEY" \
-d '{"action":"list"}'{
"success": true,
...
}POST/api/wave.php action: create
Create a Wave (a thread) in a Flow, for example one agenda session. Profile-type limits still apply to member-created Waves.
actionstringrequired"create"
ladder_idintegerrequiredfrom schemaThe Flow to post in.
titlestring, max 500requiredWave title.
wave_typestringoptionalOne of conversation, question, broadcast, session, execution.
context_htmlstring (HTML)optionalBody text.
tagsarray of stringsoptionalTags.
privacystringoptionalpublic, limited or invite.
scheduled_atdatetimeoptionalfrom schemaStart time for a session. Stored in US Eastern time (UTC-4).
duration_minintegeroptionalSession length in minutes.
meet_linkstring (URL)optionalGoogle Meet or Zoom link for a live session.
curl -sS https://dium.io/api/wave.php \
-H "Content-Type: application/json" \
-H "X-Api-Key: $DIUM_API_KEY" \
-d '{"action":"create","ladder_id":42,"wave_type":"session","title":"Keynote Q&A","scheduled_at":"2026-10-14 10:00:00","duration_min":45}'{
"success": true,
...
}POST/api/thread.php action: check_session
Check whether a session thread already exists before you create one. Used by event partners during registration. thread.php also has create and update for session threads with a partner key.
actionstringrequired"check_session"
check_session are not published yet. Ask us for them during onboarding.curl -sS https://dium.io/api/thread.php \
-H "Content-Type: application/json" \
-d '{"action":"check_session"}'{
"success": true,
...
}POST/api/exhibit.php action: create
Create a Page (sponsor, exhibitor, speaker or partner). Safe to retry: pages are matched on Flow plus name, and on external_sponsor_id. Creating a Page also creates its discussion Wave.
actionstringrequired"create"
ladder_idintegerrequiredfrom schemaThe Flow the Page belongs to.
namestringrequiredPage name.
exhibit_typestringoptionalsponsor, exhibitor, speaker or partner.
taglinestringoptionalfrom schemaOne line under the name.
websitestring (URL)optionalfrom schemaWebsite link.
about_htmlstring (HTML)optionalfrom schemaAbout section.
logo_urlstring (URL)optionalfrom schemaLogo image.
banner_urlstring (URL)optionalfrom schemaBanner image.
social_jsonarrayoptionalfrom schema[{"platform","url","label"}]
team_jsonarrayoptionalfrom schema[{"name","initials","role","status"}]
perks_jsonarrayoptionalfrom schema[{"icon","title","desc"}]
cta_jsonobjectoptionalfrom schema{"title","desc","button","url"}
external_sponsor_idstringoptionalfrom schemaYour ID for this sponsor. Used to avoid duplicates.
curl -sS https://dium.io/api/exhibit.php \
-H "Content-Type: application/json" \
-H "X-Api-Key: $DIUM_API_KEY" \
-d '{"action":"create","ladder_id":42,"name":"Northwind Labs","exhibit_type":"sponsor","external_sponsor_id":"SP-9"}'{
"success": true,
...
}Member session endpoints
These actions run as a signed-in member, with a cookie or a Bearer token. The Dium app calls them for you when you mount it. They are listed so you know what your mounted app does. They are not a stable public contract yet.
POST/api/auth.php action: validate
Return the signed-in member, or 401. Accepts a session cookie or Authorization: Bearer. Your mount calls this after autologin.
actionstringrequired"validate"
curl -sS https://dium.io/api/auth.php \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $MEMBER_TOKEN" \
-d '{"action":"validate"}'{
"success": true,
...
}POST/api/ladder.php action: join
Join a Flow as the signed-in member. Use join_as with a profile_type_slug to join with a specific profile type.
actionstringrequired"join" or "join_as"
ladder_idintegerrequiredfrom schemaThe Flow to join.
join_codestringoptionalfrom schemaNeeded when the Flow's join mode is code.
profile_type_slugstringoptionalFor join_as: the profile type code.
curl -sS https://dium.io/api/ladder.php \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $MEMBER_TOKEN" \
-d '{"action":"join","ladder_id":42}'{
"success": true,
...
}POST/api/wave.php action: list
List Waves in a Flow. get reads one Wave by id.
actionstringrequired"list" or "get"
ladder_idintegerrequiredfrom schemaFor list: the Flow.
idintegeroptionalfrom schemaFor get: the Wave ID.
curl -sS https://dium.io/api/wave.php \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $MEMBER_TOKEN" \
-d '{"action":"list","ladder_id":42}'{
"success": true,
...
}POST/api/wave.php action: go_live
Start a live session: sets the Wave live and notifies members in real time. end_live stops it. Hosts and moderators only.
actionstringrequired"go_live" or "end_live"
idintegerrequiredfrom schemaSession Wave ID.
meet_linkstring (URL)optionalMeeting link to open.
curl -sS https://dium.io/api/wave.php \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $MEMBER_TOKEN" \
-d '{"action":"go_live","id":901,"meet_link":"https://meet.google.com/abc-defg-hij"}'{
"success": true,
...
}POST/api/exhibit.php action: get
Read one Page. list returns the Pages in a Flow.
actionstringrequired"get" or "list"
idintegeroptionalfrom schemaFor get: the Page ID.
ladder_idintegeroptionalfrom schemaFor list: the Flow.
curl -sS https://dium.io/api/exhibit.php \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $MEMBER_TOKEN" \
-d '{"action":"list","ladder_id":42}'{
"success": true,
...
}POST/api/message.php action: conversations
List the member's DM conversations, scoped to one Flow or Room.
actionstringrequired"conversations"
room_slugstringoptionalfrom schemaRoom scope.
ladder_idintegeroptionalfrom schemaFlow scope.
curl -sS https://dium.io/api/message.php \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $MEMBER_TOKEN" \
-d '{"action":"conversations","room_slug":"acme-summit-2026"}'{
"success": true,
...
}POST/api/message.php action: send
Send a direct message. Limited to 30 per minute. Text is stored as plain text.
actionstringrequired"send"
to_user_idintegerrequiredfrom schemaRecipient's user ID.
bodystringrequiredMessage text.
parent_message_idintegeroptionalfrom schemaReply inside a DM thread.
room_slugstringoptionalfrom schemaRoom the conversation belongs to.
ladder_idintegeroptionalfrom schemaFlow context.
curl -sS https://dium.io/api/message.php \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $MEMBER_TOKEN" \
-d '{"action":"send","to_user_id":17,"body":"See you at the keynote","room_slug":"acme-summit-2026"}'{
"success": true,
...
}Full action list
Every action the main API files accept. Most are used by the Dium app itself. If you need one that is not documented above, ask us before you build on it.
| File | Actions |
|---|---|
auth.php | login, validate, heartbeat, client_config, issue_token, verify_token, logout |
ladder.php | create, update, get, list, members, join, join_as, pending_members, approve_member, reject_member, remove_member, pin_announcement, event_update, rsvp_join, sponsor_login, profile type actions |
wave.php | create, update, get, list, delete, search, pin, archive, lock, go_live, end_live, join, follow, polls, breakouts, send_message, messages |
answer.php | create (30 per minute), update, delete, list, best, helpful, like, react, reply_to, toggle_pin |
exhibit.php | create, update, get, list, delete, wall chat actions, track_visit, track_event, analytics |
message.php | conversations, messages, thread_messages, send, read, create_group, add_group_member, edit_message, delete_message, pin_message, unpin_message, react, unreact |
thread.php | check_session (public), create, update |