Quickstart
This walkthrough takes you from zero to downloading a file in under five minutes, assuming an organization owner has already created an API client and given you three values:
IBINDER_ORG_ID— the Organisations id (x-ibinder-tenantid)IBINDER_CLIENT_ID— the API client's idIBINDER_CLIENT_SECRET— the API client's secret
The flow is:
- Exchange the client credentials for an access token.
- List the binders you have access to.
- Search a binder for documents.
- Resolve a document version to a download URL and fetch the bytes.
Full end-to-end example
ts
const API = 'https://api.ibinder.com/api'
const AUTH = 'https://signin.ibinder.com/connect/token'
const orgId = process.env.IBINDER_ORG_ID!
// 1. Token
const tokenRes = await fetch(AUTH, {
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 headers = {
Authorization: `Bearer ${access_token}`,
'x-ibinder-tenantid': orgId,
'Content-Type': 'application/json',
}
// 2. List binders
const binders = await fetch(`${API}/binders`, { headers }).then(r => r.json())
const binderId = binders.items[0].id
// 3. Search documents in that binder
const search = await fetch(`${API}/documents?pageSize=10&pageNumber=1`, {
method: 'POST',
headers,
body: JSON.stringify({
MetadataFilters: [
{ metadataElementId: 'GLOBAL_BinderId', valueId: binderId },
],
}),
}).then(r => r.json())
const doc = search.items[0]
const versionId = doc.latestVersionId
// 4. Get a download URL and fetch the bytes (no Authorization header on the storage URL)
const { url } = await fetch(
`${API}/documents/${doc.id}/versions/${versionId}/downloadlink`,
{ headers },
).then(r => r.json())
const fileBytes = await fetch(url).then(r => r.arrayBuffer())
console.log(`Downloaded ${fileBytes.byteLength} bytes`)csharp
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text.Json;
const string Api = "https://api.ibinder.com/api";
const string Auth = "https://signin.ibinder.com/connect/token";
var orgId = Environment.GetEnvironmentVariable("IBINDER_ORG_ID")!;
var clientId = Environment.GetEnvironmentVariable("IBINDER_CLIENT_ID")!;
var clientSecret = Environment.GetEnvironmentVariable("IBINDER_CLIENT_SECRET")!;
using var http = new HttpClient();
// 1. Token
var tokenResp = await http.PostAsync(Auth, 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", orgId);
// 2. List binders
var binders = await http.GetFromJsonAsync<JsonElement>($"{Api}/binders");
var binderId = binders.GetProperty("items")[0].GetProperty("id").GetString();
// 3. Search documents in that binder
var search = await http.PostAsJsonAsync(
$"{Api}/documents?pageSize=10&pageNumber=1",
new
{
MetadataFilters = new[]
{
new { metadataElementId = "GLOBAL_BinderId", valueId = binderId },
},
});
var hits = await search.Content.ReadFromJsonAsync<JsonElement>();
var doc = hits.GetProperty("items")[0];
var docId = doc.GetProperty("id").GetString();
var versionId = doc.GetProperty("latestVersionId").GetString();
// 4. Resolve download URL and fetch
var link = await http.GetFromJsonAsync<JsonElement>(
$"{Api}/documents/{docId}/versions/{versionId}/downloadlink");
var url = link.GetProperty("url").GetString();
// Storage URL — do NOT send the bearer token here
using var bare = new HttpClient();
var bytes = await bare.GetByteArrayAsync(url);
Console.WriteLine($"Downloaded {bytes.Length} bytes");bash
API=https://api.ibinder.com/api
AUTH=https://signin.ibinder.com/connect/token
# 1. Token
TOKEN=$(curl -s -X POST "$AUTH" \
-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)
H_AUTH="Authorization: Bearer $TOKEN"
H_TEN="x-ibinder-tenantid: $IBINDER_ORG_ID"
# 2. List binders
BINDER_ID=$(curl -s "$API/binders" -H "$H_AUTH" -H "$H_TEN" \
| jq -r '.items[0].id')
# 3. Search documents in that binder
SEARCH=$(curl -s -X POST "$API/documents?pageSize=10&pageNumber=1" \
-H "$H_AUTH" -H "$H_TEN" -H "Content-Type: application/json" \
-d "{\"MetadataFilters\":[{\"metadataElementId\":\"GLOBAL_BinderId\",\"valueId\":\"$BINDER_ID\"}]}")
DOC_ID=$(echo "$SEARCH" | jq -r '.items[0].id')
VERSION_ID=$(echo "$SEARCH" | jq -r '.items[0].latestVersionId')
# 4. Resolve download URL and fetch
URL=$(curl -s "$API/documents/$DOC_ID/versions/$VERSION_ID/downloadlink" \
-H "$H_AUTH" -H "$H_TEN" | jq -r .url)
# Note: no auth header on the storage URL
curl -s "$URL" -o downloaded.bin
ls -lh downloaded.binWhat to read next
- Pagination & filtering — narrow searches with metadata filters and sort.
- Documents reference — the full set of document, version, and upload endpoints.
- API behavior & guidelines — status codes, retries, audit logging.
Token caching
Don't request a new token on every call. Cache the access_token for its expires_in lifetime (minus a small safety margin) and refresh on demand.

