Overview
36Blocks User API
36Blocks is an authentication-as-a-service product. It is a hosted authentication, user and company management service: you set up a Block in the dashboard, drop in widgets, and 36Blocks handles sign-up and login, sessions, companies, members, roles and permissions.
These APIs cover what your end users and your own backend call at runtime: sign-in sessions, companies and members, roles and permissions, OAuth 2.0, OTP, subscriptions and billing.
Base URL: https://routes.msg91.com/api
Widgets: the entry point
Widgets are how you integrate 36Blocks. Each widget is a small snippet you paste into a page of your app. 36Blocks renders the UI and runs the logic behind it, so you do not build login screens, profile pages or member management yourself. The APIs in this documentation are what your backend calls once a user is signed in through a widget.
| Widget | type |
Use it for |
|---|---|---|
| Authentication | authorization |
Login and sign-up page. Needs your Block's referenceId. |
| Profile | user-profile |
Account settings and "my profile", including the companies a user belongs to. |
| Management | user-management |
Team management: list members, invite, change roles, remove. |
| Organization | organization-details |
Organization or workspace settings for the current company. |
The Authentication widget is where every integration starts:
<div id="YOUR_BLOCK_REFERENCE_ID"></div>
<script type="text/javascript">
var configuration = {
referenceId: 'YOUR_BLOCK_REFERENCE_ID',
type: 'authorization',
success: (data) => {
console.log('success response', data);
},
failure: (error) => {
console.log('failure reason', error);
},
};
</script>
<script
type="text/javascript"
onload="initVerification(configuration)"
src="https://36blocks.com/assets/proxy-auth/proxy-auth.js"
></script>
After a successful login, 36Blocks redirects the browser to your Block's redirect URL with a proxy_auth_token in the query string. That token authenticates every signed-in API call, and it is what the Profile, Management and Organization widgets take as authToken.
The Widgets page has the snippets for all four, the options for the login widget, and which widget to use for which page.
Snippets and options for all four widgets.
Start here
The end-to-end flow for adding 36Blocks to an app, written for developers and AI coding agents: login widget, redirect, session storage, user data, logout.
Create a Block, choose login methods, set your branding, and get the embed code for the Authentication widget.
Guides and reference
| Section | Use it to |
|---|---|
| Widgets | Embed login, profile, member management and organization settings. |
| Sessions | Handle proxy_auth_token, JWTs, refresh tokens and post-login redirects. |
| Companies & Users | Read the signed-in user's profile and companies, switch or create companies, and manage members. |
| API Keys, Roles & Permissions | Manage a company's API keys, custom roles and permission assignments. |
| Security & Access | Restrict which origins can trigger OTPs, and block new sign-ups. |
| Webhooks | Get notified when users and companies change. |
| Blocks | Create and configure Blocks, client secrets, OAuth clients, custom scopes and hidden permissions. |
| Server-to-Server (Auth Key) | Manage your Block's users, companies, roles and permissions from your backend, using an auth key. |
| OAuth 2.0 | Let third-party apps connect to your users' accounts with your own authorization server. |
| Analytics | Read usage analytics for your Block. |
| Billing | Plans, subscriptions, usage and payment methods. |
Terms
- Client: your account on 36Blocks.
- Block (feature configuration): one auth setup inside a client, for one app. It has its own login methods, branding, session settings and a reference ID. Its
reference_idis theref_id/featureIdin many paths. - c_user: an end user of your app.
- c_company: a tenant or organisation that c_users belong to. A c_user can belong to several and has a role in each one.
proxy_auth_token: the session token returned after a successful login.- Widget: an embeddable 36Blocks UI snippet (
authorization,user-profile,user-management,organization-details).
Credentials
| Credential | Where | Used by |
|---|---|---|
proxy_auth_token |
HTTP header | Calls made as a signed-in end user (/c/*, /oauth/userinfo, subscription user APIs) |
authkey |
HTTP header | Server-to-server calls from your backend (client users, roles, permissions, OTP v1, usage). Never put an auth key in a browser or mobile app |
Authorization |
HTTP header | Calls made as a signed-in dashboard user (/v1/billing/*). Send the raw JWT, without a Bearer prefix |
proxy_state |
Request body or query | Sign-in and registration widget calls. It is an encrypted value generated by the 36Blocks widget |
Where the authkey comes from
The authkey is provided by 36Blocks to the owner of the 36Blocks account. It is not created by any API endpoint or widget, so code and AI agents cannot fetch, generate or look it up. When a task needs it, the value comes from the user, who has it from 36Blocks.
Only the Server-to-Server (Auth Key) module uses it. Widget-based integrations and the signed-in calls need only the proxy_auth_token.
Backend endpoints that authenticate with the authkey.
Response format
Most endpoints return:
{ "data": {}, "status": "success", "hasError": false, "errors": [], "proxy_duration": 37 }
Errors use "status": "error" and "hasError": true, with the message in data.message. Validation errors return HTTP 422 with { "message": "...", "errors": { "field": ["..."] } }.
Things to know:
- Authentication and permission failures usually return 401, not 403.
- An unexpected server error returns 418.
- A few business errors return HTTP 200 with
hasError: true. Always checkhasError. - OAuth
/token,/userinfoand error responses use plain OAuth-style JSON, not the envelope above.