Sign-in and sessions
Passwordless sign-in, sign-up, sessions, second factors, step-up and device login.
/v1/auth/profileThe person's profile and preferences#
- Credential
- A dashboard session only (API keys are refused)
- Roles
- Any role
Response
200Profile
idstringemailstringphonestring | nullnamestring | nullavatarstring | nulllanguagestring | nulltime_zonestring | nullcalendarstring | nulldate_formatstring | nullthemestring | nullupdated_atstring (date-time) | nulldefaultsobject
Errors
| Status | Description |
|---|---|
| 401 | unauthorized: missing, invalid, expired or revoked credential |
| 403 | Forbidden: session_only |
| 500 | internal: an unexpected failure |
Example
curl "https://api.ibel.ai/v1/auth/profile" \
-H "Authorization: Bearer $SESSION"/v1/auth/profileChange the person's profile and preferences#
Any of name, avatar, language, time_zone, calendar, date_format, theme; null puts a field back on its default. Needs a dashboard session.
- Credential
- A dashboard session only (API keys are refused)
- Roles
- Any role
Request bodyapplication/json
namestring | nullavatarstring | nulla png, jpeg or webp image as a data URL, under 40 KB
languagestring | nullone of
fa,en,nulltime_zonestring | nullan IANA time zone, for example Asia/Tehran
calendarstring | nullone of
jalali,gregorian,nulldate_formatstring | nullone of
medium,short,long,nullthemestring | nullone of
system,light,dark,null
Response
200Profile
idstringemailstringphonestring | nullnamestring | nullavatarstring | nulllanguagestring | nulltime_zonestring | nullcalendarstring | nulldate_formatstring | nullthemestring | nullupdated_atstring (date-time) | nulldefaultsobject
Errors
| Status | Description |
|---|---|
| 400 | Bad request: bad_name, bad_avatar, bad_language, bad_time_zone, bad_calendar, bad_date_format, bad_theme, empty |
| 401 | unauthorized: missing, invalid, expired or revoked credential |
| 403 | Forbidden: session_only |
| 500 | internal: an unexpected failure |
Example
curl -X PATCH "https://api.ibel.ai/v1/auth/profile" \
-H "Authorization: Bearer $SESSION" \
-d '{"name":"my-api","avatar":"…","language":"fa","time_zone":"…","calendar":"jalali","date_format":"medium","theme":"system"}'/v1/auth/contact/startBegin changing the email address or mobile number#
Sends a code to the new address or number; nothing changes until it is confirmed. Needs a session and a fresh second factor (step_up_required).
- Credential
- A dashboard session only (API keys are refused)
- Roles
- Any role
- Step-up
- With a dashboard session, a second factor confirmed in the last 10 minutes; API keys pass.
Request bodyapplication/json
channelstringrequiredone of
email,phonevaluestringrequired
Response
200object
challengestringchannelstringexpires_ininteger
Errors
| Status | Description |
|---|---|
| 400 | Bad request: bad_channel, bad_email, bad_phone |
| 401 | unauthorized: missing, invalid, expired or revoked credential |
| 403 | Forbidden: step_up_required, session_only |
| 429 | Too many requests: rate_limited, resend_wait |
| 500 | internal: an unexpected failure |
Example
curl -X POST "https://api.ibel.ai/v1/auth/contact/start" \
-H "Authorization: Bearer $SESSION" \
-d '{"channel":"email","value":"s3cr3t"}'/v1/auth/contact/confirmFinish changing the email address or mobile number#
With the code sent to the new one. Needs a session and a fresh second factor.
- Credential
- A dashboard session only (API keys are refused)
- Roles
- Any role
- Step-up
- With a dashboard session, a second factor confirmed in the last 10 minutes; API keys pass.
Request bodyapplication/json
challengestringrequiredcodestringrequiredpattern
^\d{6}$
Response
200Profile
idstringemailstringphonestring | nullnamestring | nullavatarstring | nulllanguagestring | nulltime_zonestring | nullcalendarstring | nulldate_formatstring | nullthemestring | nullupdated_atstring (date-time) | nulldefaultsobject
Errors
| Status | Description |
|---|---|
| 400 | Bad request: bad_code |
| 401 | unauthorized: missing, invalid, expired or revoked credential |
| 403 | Forbidden: step_up_required, session_only |
| 409 | Conflict: taken |
| 500 | internal: an unexpected failure |
Example
curl -X POST "https://api.ibel.ai/v1/auth/contact/confirm" \
-H "Authorization: Bearer $SESSION" \
-d '{"challenge":"…","code":"123456"}'- Credential
- None
Request bodyapplication/json
identifierstringrequiredan email or an Iranian mobile
browserstringrequireda random value of 16+ characters the client keeps
at least 16 characters
Response
200Challenge
challengestring (uuid)requiredchannelstringrequiredone of
email,smsexpires_inintegerseconds
resend_afterintegerseconds
Errors
| Status | Description |
|---|---|
| 400 | Bad request: bad_browser, bad_identifier, bad_json |
| 429 | Too many requests: resend_wait, rate_limited |
| 500 | internal: an unexpected failure |
Example
curl -X POST "https://api.ibel.ai/v1/auth/signin" \
-d '{"identifier":"you@example.com","browser":"b3f1c9a27d4e4c0e9a1f"}'/v1/auth/verifyExchange a sign-in code for a session#
- Credential
- None
Request bodyapplication/json
challengestring (uuid)requiredcodestringrequiredpattern
^\d{6}$
Response
200Session
sessionstringrequiredchs_ bearer token
expires_atstring (date-time)required
Errors
| Status | Description |
|---|---|
| 400 | Bad request: bad_code, bad_json |
| 403 | Not allowed: no_team |
| 429 | Too many requests: rate_limited |
| 500 | internal: an unexpected failure |
Example
curl -X POST "https://api.ibel.ai/v1/auth/verify" \
-d '{"challenge":"8c1e0c55-1f2a-4d3b-9e8f-0a1b2c3d4e5f","code":"123456"}'/v1/auth/linkSign in with a magic link#
- Credential
- None
Request bodyapplication/json
challengestring (uuid)requiredtokenstringrequiredbrowserstringrequireda random value of 16+ characters the client keeps
at least 16 characters
Response
200Session
sessionstringrequiredchs_ bearer token
expires_atstring (date-time)required
Errors
| Status | Description |
|---|---|
| 400 | Bad request: expired, bad_json |
| 409 | Conflict: other_browser |
| 500 | internal: an unexpected failure |
Example
curl -X POST "https://api.ibel.ai/v1/auth/link" \
-d '{"challenge":"8c1e0c55-1f2a-4d3b-9e8f-0a1b2c3d4e5f","token":"…","browser":"b3f1c9a27d4e4c0e9a1f"}'/v1/auth/registrationWhether sign-up is open#
CORS for the marketing site's origins (CH_SITE_ORIGINS), with the OPTIONS preflight.
- Credential
- None
Response
200object
registrationstringrequiredone of
open,invite,closed
Errors
| Status | Description |
|---|---|
| 500 | internal: an unexpected failure |
Example
curl "https://api.ibel.ai/v1/auth/registration"/v1/auth/signupStart a sign-up#
- Credential
- None
Request bodyapplication/json
emailstringrequiredphonestringrequiredIranian mobile
browserstringrequireda random value of 16+ characters the client keeps
at least 16 characters
invitestringteam_invitestring
Response
200object
email_challengestring (uuid)requiredphone_challengestring (uuid)requiredexpires_inintegerboth codes work this long (300)
email_expires_ininteger600
phone_expires_ininteger300
resend_afterinteger
Errors
| Status | Description |
|---|---|
| 400 | Bad request: bad_email, bad_phone, bad_browser, bad_json |
| 403 | Not allowed: registration_closed, bad_invite |
| 429 | Too many requests: resend_wait, rate_limited |
| 500 | internal: an unexpected failure |
Example
curl -X POST "https://api.ibel.ai/v1/auth/signup" \
-d '{"email":"you@example.com","phone":"09121234567","browser":"b3f1c9a27d4e4c0e9a1f"}'/v1/auth/signup/verifyFinish a sign-up#
Creates the person, their personal team and a session that is already stepped up.
- Credential
- None
Request bodyapplication/json
email_challengestring (uuid)requiredemail_codestringrequiredphone_challengestring (uuid)requiredphone_codestringrequiredinvitestringteam_invitestring
Response
200Session
sessionstringrequiredchs_ bearer token
expires_atstring (date-time)required
Errors
| Status | Description |
|---|---|
| 400 | Bad request: bad_code, bad_invite, bad_json |
| 403 | Not allowed: bad_invite, registration_closed |
| 409 | Conflict: exists |
| 429 | Too many requests: rate_limited |
| 500 | internal: an unexpected failure |
Example
curl -X POST "https://api.ibel.ai/v1/auth/signup/verify" \
-d '{"email_challenge":"8c1e0c55-1f2a-4d3b-9e8f-0a1b2c3d4e5f","email_code":"…","phone_challenge":"8c1e0c55-1f2a-4d3b-9e8f-0a1b2c3d4e5f","phone_code":"…"}'/v1/auth/waitlistJoin the waitlist#
CORS for the marketing site's origins (CH_SITE_ORIGINS), with the OPTIONS preflight.
- Credential
- None
Request bodyapplication/json
contactstringrequiredan email or an Iranian mobile
Response
200Ok
okbooleanrequired
Errors
| Status | Description |
|---|---|
| 400 | Bad request: bad_contact, bad_json |
| 429 | Too many requests: rate_limited |
| 500 | internal: an unexpected failure |
Example
curl -X POST "https://api.ibel.ai/v1/auth/waitlist" \
-d '{"contact":"you@example.com"}'/v1/auth/sessionsThe person's sessions#
- Credential
- A dashboard session only (API keys are refused)
- Roles
- Any role
Response
200object
sessionsSessionInfo[]requiredidstringrequiredcreated_atstring (date-time)last_seen_atstring (date-time)expires_atstring (date-time)ipstring | nulluser_agentstring | nullcurrentbooleanrequired
Errors
| Status | Description |
|---|---|
| 401 | unauthorized: missing, invalid, expired or revoked credential |
| 403 | Not allowed: session_only |
| 500 | internal: an unexpected failure |
Example
curl "https://api.ibel.ai/v1/auth/sessions" \
-H "Authorization: Bearer $SESSION"/v1/auth/sessions/{id}End a session#
- Credential
- A dashboard session only (API keys are refused)
- Roles
- Any role
Parameters
idstringpathrequiredsession id
pattern
^[0-9a-f]{16}$
Response
200object
revokedstring
Errors
| Status | Description |
|---|---|
| 401 | unauthorized: missing, invalid, expired or revoked credential |
| 403 | Not allowed: session_only |
| 404 | Not found: not_found |
| 500 | internal: an unexpected failure |
Example
curl -X DELETE "https://api.ibel.ai/v1/auth/sessions/88e2fe1d-6d75-4de5-8c8f-27380ec66903" \
-H "Authorization: Bearer $SESSION"/v1/auth/signoutEnd this session#
- Credential
- A dashboard session only (API keys are refused)
- Roles
- Any role
Response
200Ok
okbooleanrequired
Errors
| Status | Description |
|---|---|
| 401 | unauthorized: missing, invalid, expired or revoked credential |
| 403 | Not allowed: session_only |
| 500 | internal: an unexpected failure |
Example
curl -X POST "https://api.ibel.ai/v1/auth/signout" \
-H "Authorization: Bearer $SESSION"/v1/auth/signout-everywhereEnd every session of the person#
- Credential
- A dashboard session only (API keys are refused)
- Roles
- Any role
Response
200object
revokedinteger
Errors
| Status | Description |
|---|---|
| 401 | unauthorized: missing, invalid, expired or revoked credential |
| 403 | Not allowed: session_only |
| 500 | internal: an unexpected failure |
Example
curl -X POST "https://api.ibel.ai/v1/auth/signout-everywhere" \
-H "Authorization: Bearer $SESSION"/v1/auth/factorsFactors and step-up methods#
- Credential
- A dashboard session only (API keys are refused)
- Roles
- Any role
Response
200Factors
signed_in_withstringtotpbooleanpasskeysintegeremailstringphonestring | nullmasked
step_up_methodsstring[]single_factorbooleanstepped_up_untilstring (date-time) | null
Errors
| Status | Description |
|---|---|
| 401 | unauthorized: missing, invalid, expired or revoked credential |
| 403 | Not allowed: session_only |
| 500 | internal: an unexpected failure |
Example
curl "https://api.ibel.ai/v1/auth/factors" \
-H "Authorization: Bearer $SESSION"/v1/auth/step-up/startSend a step-up code#
- Credential
- A dashboard session only (API keys are refused)
- Roles
- Any role
Request bodyapplication/json
methodstringrequiredone of
email,sms
Response
200Challenge
challengestring (uuid)requiredchannelstringrequiredone of
email,smsexpires_inintegerseconds
resend_afterintegerseconds
Errors
| Status | Description |
|---|---|
| 400 | Bad request: bad_method, bad_json |
| 401 | unauthorized: missing, invalid, expired or revoked credential |
| 403 | Not allowed: session_only |
| 429 | Too many requests: resend_wait, rate_limited |
| 500 | internal: an unexpected failure |
Example
curl -X POST "https://api.ibel.ai/v1/auth/step-up/start" \
-H "Authorization: Bearer $SESSION" \
-d '{"method":"email"}'/v1/auth/step-up/verifyConfirm the second factor#
Sensitive actions are then allowed for 10 minutes.
- Credential
- A dashboard session only (API keys are refused)
- Roles
- Any role
Request bodyapplication/json
methodstringone of
totpchallengestring (uuid)codestringrequired
Response
200object
stepped_up_untilstring (date-time)
Errors
| Status | Description |
|---|---|
| 400 | Bad request: bad_code, bad_json |
| 401 | unauthorized: missing, invalid, expired or revoked credential |
| 403 | Not allowed: session_only |
| 429 | Too many requests: rate_limited |
| 500 | internal: an unexpected failure |
Example
curl -X POST "https://api.ibel.ai/v1/auth/step-up/verify" \
-H "Authorization: Bearer $SESSION" \
-d '{"code":"123456"}'/v1/auth/passkeysList your passkeys#
- Credential
- A dashboard session only (API keys are refused)
- Roles
- Any role
Response
200object
passkeysPasskey[]idstring (uuid)namestringcreated_atstring (date-time)last_used_atstring (date-time) | nullsyncedbooleansyncs across devices (phone, password manager)
transportsstring[]
availablebooleanrp_idstring
Errors
| Status | Description |
|---|---|
| 401 | unauthorized: missing, invalid, expired or revoked credential |
| 403 | Not allowed: session_only |
| 500 | internal: an unexpected failure |
Example
curl "https://api.ibel.ai/v1/auth/passkeys" \
-H "Authorization: Bearer $SESSION"- Credential
- A dashboard session only (API keys are refused)
- Roles
- Any role
Response
200object
challenge_idstring (uuid)optionsobjectthe browser's credential options, binary values in base64url
Errors
| Status | Description |
|---|---|
| 401 | unauthorized: missing, invalid, expired or revoked credential |
| 403 | Not allowed: session_only, step_up_required |
| 409 | Conflict: passkey_limit |
| 500 | internal: an unexpected failure |
| 503 | Not offered on this site: passkeys_unavailable |
Example
curl -X POST "https://api.ibel.ai/v1/auth/passkeys/register/options" \
-H "Authorization: Bearer $SESSION"- Credential
- A dashboard session only (API keys are refused)
- Roles
- Any role
Request bodyapplication/json
challenge_idstring (uuid)requiredcredentialobjectrequiredwhat PublicKeyCredential.toJSON() returns: id, rawId, type, response
namestringup to 60 characters
Response
201PasskeyCreated
idstring (uuid)namestringcreated_atstring (date-time)last_used_atstring (date-time) | nullsyncedbooleansyncs across devices (phone, password manager)
transportsstring[]
Errors
| Status | Description |
|---|---|
| 400 | Bad request: passkey_refused, passkey_expired, bad_json |
| 401 | unauthorized: missing, invalid, expired or revoked credential |
| 403 | Not allowed: session_only, step_up_required |
| 409 | Conflict: passkey_exists, passkey_limit |
| 500 | internal: an unexpected failure |
| 503 | Not offered on this site: passkeys_unavailable |
Example
curl -X POST "https://api.ibel.ai/v1/auth/passkeys/register/verify" \
-H "Authorization: Bearer $SESSION" \
-d '{"challenge_id":"8c1e0c55-1f2a-4d3b-9e8f-0a1b2c3d4e5f","credential":{}}'- Credential
- A dashboard session only (API keys are refused)
- Roles
- Any role
Parameters
idstring (uuid)pathrequired
Response
200object
removedstring (uuid)
Errors
| Status | Description |
|---|---|
| 401 | unauthorized: missing, invalid, expired or revoked credential |
| 403 | Not allowed: session_only, step_up_required |
| 404 | Not found: not_found |
| 500 | internal: an unexpected failure |
Example
curl -X DELETE "https://api.ibel.ai/v1/auth/passkeys/88e2fe1d-6d75-4de5-8c8f-27380ec66903" \
-H "Authorization: Bearer $SESSION"/v1/auth/passkeys/{id}Rename a passkey#
- Credential
- A dashboard session only (API keys are refused)
- Roles
- Any role
Parameters
idstring (uuid)pathrequired
Request bodyapplication/json
namestringrequired1–60 characters
Response
200Passkey
idstring (uuid)namestringcreated_atstring (date-time)last_used_atstring (date-time) | nullsyncedbooleansyncs across devices (phone, password manager)
transportsstring[]
Errors
| Status | Description |
|---|---|
| 400 | Bad request: bad_name, bad_json |
| 401 | unauthorized: missing, invalid, expired or revoked credential |
| 403 | Not allowed: session_only |
| 404 | Not found: not_found |
| 500 | internal: an unexpected failure |
Example
curl -X PATCH "https://api.ibel.ai/v1/auth/passkeys/88e2fe1d-6d75-4de5-8c8f-27380ec66903" \
-H "Authorization: Bearer $SESSION" \
-d '{"name":"my-api"}'/v1/auth/passkeys/signin/optionsStart a passkey sign-in#
- Credential
- None
Response
200object
challenge_idstring (uuid)optionsobjectthe browser's credential options, binary values in base64url
Errors
| Status | Description |
|---|---|
| 429 | Too many requests: rate_limited |
| 500 | internal: an unexpected failure |
| 503 | Not offered on this site: passkeys_unavailable |
Example
curl -X POST "https://api.ibel.ai/v1/auth/passkeys/signin/options"/v1/auth/passkeys/signin/verifySign in with a passkey#
The session starts stepped up (a passkey is user-verified).
- Credential
- None
Request bodyapplication/json
challenge_idstring (uuid)requiredcredentialobjectrequiredwhat PublicKeyCredential.toJSON() returns: id, rawId, type, response
teamstring (uuid)
Response
200Session
sessionstringrequiredchs_ bearer token
expires_atstring (date-time)requiredpasskeyobjectidstring (uuid)namestring
Errors
| Status | Description |
|---|---|
| 400 | Bad request: passkey_refused, passkey_expired, passkey_unknown, bad_json |
| 403 | Not allowed: no_team |
| 429 | Too many requests: rate_limited |
| 500 | internal: an unexpected failure |
| 503 | Not offered on this site: passkeys_unavailable |
Example
curl -X POST "https://api.ibel.ai/v1/auth/passkeys/signin/verify" \
-d '{"challenge_id":"8c1e0c55-1f2a-4d3b-9e8f-0a1b2c3d4e5f","credential":{}}'/v1/auth/step-up/passkey/optionsStart a step-up with a passkey#
- Credential
- A dashboard session only (API keys are refused)
- Roles
- Any role
Response
200object
challenge_idstring (uuid)optionsobjectthe browser's credential options, binary values in base64url
Errors
| Status | Description |
|---|---|
| 400 | Bad request: bad_method |
| 401 | unauthorized: missing, invalid, expired or revoked credential |
| 403 | Not allowed: session_only |
| 500 | internal: an unexpected failure |
| 503 | Not offered on this site: passkeys_unavailable |
Example
curl -X POST "https://api.ibel.ai/v1/auth/step-up/passkey/options" \
-H "Authorization: Bearer $SESSION"/v1/auth/step-up/passkey/verifyConfirm a step-up with a passkey#
- Credential
- A dashboard session only (API keys are refused)
- Roles
- Any role
Request bodyapplication/json
challenge_idstring (uuid)requiredcredentialobjectrequiredwhat PublicKeyCredential.toJSON() returns: id, rawId, type, response
Response
200object
stepped_up_untilstring (date-time)
Errors
| Status | Description |
|---|---|
| 400 | Bad request: passkey_refused, passkey_expired, passkey_unknown, bad_json |
| 401 | unauthorized: missing, invalid, expired or revoked credential |
| 403 | Not allowed: session_only |
| 429 | Too many requests: rate_limited |
| 500 | internal: an unexpected failure |
| 503 | Not offered on this site: passkeys_unavailable |
Example
curl -X POST "https://api.ibel.ai/v1/auth/step-up/passkey/verify" \
-H "Authorization: Bearer $SESSION" \
-d '{"challenge_id":"8c1e0c55-1f2a-4d3b-9e8f-0a1b2c3d4e5f","credential":{}}'/v1/auth/totp/setupStart adding an authenticator app#
- Credential
- A dashboard session only (API keys are refused)
- Roles
- Any role
- Step-up
- With a dashboard session, a second factor confirmed in the last 10 minutes; API keys pass.
Response
200object
secretstringrequiredotpauth_uristringrequiredconfirmstring
Errors
| Status | Description |
|---|---|
| 401 | unauthorized: missing, invalid, expired or revoked credential |
| 403 | Not allowed: step_up_required, session_only |
| 500 | internal: an unexpected failure |
Example
curl -X POST "https://api.ibel.ai/v1/auth/totp/setup" \
-H "Authorization: Bearer $SESSION"/v1/auth/totp/confirmTurn the authenticator app on#
- Credential
- A dashboard session only (API keys are refused)
- Roles
- Any role
Request bodyapplication/json
codestringrequiredpattern
^\d{6}$
Response
200object
enabledboolean
Errors
| Status | Description |
|---|---|
| 400 | Bad request: bad_code, bad_json |
| 401 | unauthorized: missing, invalid, expired or revoked credential |
| 403 | Not allowed: session_only |
| 429 | Too many requests: rate_limited |
| 500 | internal: an unexpected failure |
Example
curl -X POST "https://api.ibel.ai/v1/auth/totp/confirm" \
-H "Authorization: Bearer $SESSION" \
-d '{"code":"123456"}'/v1/auth/totpRemove the authenticator app#
- Credential
- A dashboard session only (API keys are refused)
- Roles
- Any role
- Step-up
- With a dashboard session, a second factor confirmed in the last 10 minutes; API keys pass.
Response
200object
removedboolean
Errors
| Status | Description |
|---|---|
| 401 | unauthorized: missing, invalid, expired or revoked credential |
| 403 | Not allowed: step_up_required, session_only |
| 500 | internal: an unexpected failure |
Example
curl -X DELETE "https://api.ibel.ai/v1/auth/totp" \
-H "Authorization: Bearer $SESSION"/v1/auth/deviceStart a device login (CLI)#
- Credential
- None
Request bodyapplication/json
namestringup to 80 characters
Response
200DeviceStart
device_codestringrequireduser_codestringrequiredpattern
^[A-Z0-9]{4}-[A-Z0-9]{4}$verification_urlstringrequiredverification_url_completestringintervalintegerrequiredexpires_inintegerrequired
Errors
| Status | Description |
|---|---|
| 400 | Bad request: bad_json |
| 429 | Too many requests: rate_limited |
| 500 | internal: an unexpected failure |
Example
curl -X POST "https://api.ibel.ai/v1/auth/device" \
-d '{"name":"my-api"}'- Credential
- A dashboard session only (API keys are refused)
- Roles
- Any role
- Step-up
- With a dashboard session, a second factor confirmed in the last 10 minutes; API keys pass.
Request bodyapplication/json
user_codestringrequireddenyboolean
Response
200object
approvedbooleannamestring
Errors
| Status | Description |
|---|---|
| 400 | Bad request: bad_json |
| 401 | unauthorized: missing, invalid, expired or revoked credential |
| 403 | Not allowed: step_up_required, session_only |
| 404 | Not found: bad_code |
| 500 | internal: an unexpected failure |
Example
curl -X POST "https://api.ibel.ai/v1/auth/device/approve" \
-H "Authorization: Bearer $SESSION" \
-d '{"user_code":"WDJB-MJHT"}'/v1/auth/device/tokenPoll for the device's API key#
RFC 8628: every polling error is a 400, authorization_pending included.
- Credential
- None
Request bodyapplication/json
device_codestringrequired
Response
200DeviceToken
api_keystringrequiredkey_idstringrequiredexpires_in_daysinteger
Errors
| Status | Description |
|---|---|
| 400 | Bad request: authorization_pending, access_denied, expired_token, bad_json |
| 500 | internal: an unexpected failure |
Example
curl -X POST "https://api.ibel.ai/v1/auth/device/token" \
-d '{"device_code":"…"}'