Identity API
The Identity resource is your starting point for working with the Droplet API. It answers the question "who am I, and what am I allowed to do?" by exchanging your bearer token for a client access token, along with the organization context and permission map that come with it. If you are bootstrapping a session or building a client that needs to know its own identity before doing anything else, this is the call you make first.

Issue a client access token
POST /v1/identity/client-access
Call this endpoint to exchange your API token (your identityToken) for a short-lived client access token, valid for 5 minutes. The response also hands back the organization you are operating in, its plan limits, and a granular permission map so your client knows exactly what it can see and do. There is no request body to send. Just authenticate with your bearer token and Droplet figures out the rest from the token itself.
The access token is valid for 5 minutes. Reuse it across calls until it expires, then call this endpoint again for a fresh one. A 401 on an otherwise-correct request almost always means the access token has expired, that is your cue to refresh.
Think of this as a whoami call with benefits. One request tells you your organization, your plan limits, and your permissions, so you can tailor the rest of your session without guessing.
Authentication
This endpoint is authenticated with your API token in the Authorization header:
Authorization: Bearer <token>
Request
This endpoint takes no path parameters and no request body. The identity it returns is derived entirely from the bearer token you present.
Example request
curl -X POST https://api.droplet.io/v1/identity/client-access \
-H "Authorization: Bearer <token>"
Response
A successful call returns the standard envelope with success: true and a data object containing the organization, your access token, and your permission map.
| Field | Type | Description |
|---|---|---|
data.organization | object | The organization tied to your token. Always includes an id. |
data.organization.id | string | Unique identifier for the organization. |
data.organization.name | string | Display name of the organization. |
data.organization.limits | object | Plan limits, or null if unlimited. Includes publishedForms and viewSubmissions. |
data.organization.free | boolean | Whether the organization is on a free plan. |
data.organization.directorySyncEnabled | boolean | Whether directory sync is enabled for the organization. |
data.accessToken | string | The client access token to use for subsequent requests. |
data.permissions | object | A nested map of resource to action to boolean, describing what you can do. |
Example response
{
"requestId": "req_8f3a1c92",
"success": true,
"data": {
"organization": {
"id": "org_4b21d7",
"name": "Acme Inc",
"limits": {
"publishedForms": 50,
"viewSubmissions": 10000
},
"free": false,
"directorySyncEnabled": true
},
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"permissions": {
"forms": {
"create": true,
"publish": true,
"delete": false
},
"submissions": {
"view": true,
"export": false
}
}
}
}
Errors
When something goes wrong, you get the same envelope with success: false and an error object carrying a code and a human-readable message.
{
"requestId": "req_8f3a1c92",
"success": false,
"error": {
"code": "unauthorized",
"message": "The provided token is invalid or has expired."
}
}
What you can do with it
Once you have the response in hand, you can:
- Use
data.accessTokento authenticate the rest of your client session. - Read
data.organization.limitsto show usage caps or gate features in your UI. - Check
data.permissionsbefore attempting an action, so you only surface what the user can actually do. - Branch on
data.organization.freeordirectorySyncEnabledto tailor the experience to the plan.