Authentication
The iBinder API uses the OAuth 2.0 Client Credentials flow. Tokens are issued by the iBinder Identity Provider at signin.ibinder.com and presented as bearer tokens on every API request.
1. Obtain client credentials
An organization owner creates an API client through the iBinder UI — see Obtaining API credentials for the full walkthrough. You'll end up with three values:
tenant_id— your organization's GUID (labelled Organisations id in the iBinder UI). This is the value sent on every request asx-ibinder-tenantid.client_id— the OAuth client id, copied from the API klienter list.client_secret— the OAuth client secret, shown once at creation time.
Each client is scoped to a single organization and is granted either read or read/write access. Store these credentials securely.
2. Request an access token
Exchange the client credentials for a short-lived access token:
POST /connect/token HTTP/1.1
Host: signin.ibinder.com
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
&client_id={client_id}
&client_secret={client_secret}
&scope=ibinder_publicOr, equivalently, the JSON body form:
{
"grant_type": "client_credentials",
"client_id": "{client_id}",
"client_secret": "{client_secret}",
"scope": "ibinder_public"
}The response contains an access_token and expires_in (seconds — typically one hour). The scope is fixed at ibinder_public; there is no scope catalog to choose from.
3. Call the API
Send the token as a bearer in the Authorization header, and include the tenant header on every request:
GET /api/binders HTTP/1.1
Host: api.ibinder.com
Authorization: Bearer {access_token}
x-ibinder-tenantid: {tenant_id}Refresh the token before it expires by repeating step 2.
Access control
- Each API client is restricted to a single organization.
- Clients are assigned either read or read/write access based on the integration's requirements.
- Tokens expire after a predefined duration (typically one hour) and must be refreshed periodically. Cache the token for its lifetime instead of requesting a new one per call.
Code samples
const tokenRes = await fetch('https://signin.ibinder.com/connect/token', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
grant_type: 'client_credentials',
client_id: process.env.IBINDER_CLIENT_ID!,
client_secret: process.env.IBINDER_CLIENT_SECRET!,
scope: 'ibinder_public',
}),
})
const { access_token } = await tokenRes.json()
const binders = await fetch('https://api.ibinder.com/api/binders', {
headers: {
'Authorization': `Bearer ${access_token}`,
'x-ibinder-tenantid': process.env.IBINDER_TENANT_ID!,
},
}).then(r => r.json())using var http = new HttpClient();
var tokenResp = await http.PostAsync(
"https://signin.ibinder.com/connect/token",
new FormUrlEncodedContent(new Dictionary<string, string> {
["grant_type"] = "client_credentials",
["client_id"] = clientId,
["client_secret"] = clientSecret,
["scope"] = "ibinder_public",
}));
var token = (await tokenResp.Content.ReadFromJsonAsync<JsonElement>())
.GetProperty("access_token").GetString();
http.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", token);
http.DefaultRequestHeaders.Add("x-ibinder-tenantid", tenantId);
var binders = await http.GetFromJsonAsync<JsonElement>(
"https://api.ibinder.com/api/binders");TOKEN=$(curl -s -X POST https://signin.ibinder.com/connect/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=$IBINDER_CLIENT_ID" \
-d "client_secret=$IBINDER_CLIENT_SECRET" \
-d "scope=ibinder_public" \
| jq -r .access_token)
curl -s https://api.ibinder.com/api/binders \
-H "Authorization: Bearer $TOKEN" \
-H "x-ibinder-tenantid: $IBINDER_TENANT_ID"Security best practices
- Never embed
client_secretin client-side code (browsers, mobile apps). The client credentials flow is for server-to-server integrations. - Rotate credentials if you suspect they have been exposed.
- Cache the access token for its lifetime instead of requesting a new one on every call.

