The Ekso API is a REST API that lets you manage items, boards, containers, time entries, and every other resource in your tenant programmatically. This page covers the architecture — for a hands-on walkthrough, see the Quickstart.
Base URL
All API requests target your tenant’s subdomain:
https://{tenant}.ekso.app/api/
Replace {tenant} with your organization’s subdomain. Every endpoint described in the API reference is relative to this base.
Authentication
Ekso uses OAuth 2.0 with PKCE (Proof Key for Code Exchange). PKCE is the recommended flow for public clients — it protects against authorization code interception without requiring a client secret.
Discovery
Fetch the OAuth metadata from your tenant’s well-known endpoint:
curl https://{tenant}.ekso.app/.well-known/oauth-authorization-server
This returns the authorization, token, and registration endpoints you need for the flow.
Flow summary
- Generate a code verifier and challenge — create a random string (verifier) and its SHA-256 hash (challenge)
- Redirect to the authorization endpoint — include the code challenge, a redirect URI, and requested scopes
- User approves — Ekso redirects back to your app with an authorization code
- Exchange code for tokens — POST the authorization code and code verifier to the token endpoint
- Use the access token — include it in the
Authorization header of every API request
See the full OAuth 2.0 details in the API reference.
Using the token
Add the access token to every request as a Bearer token:
curl https://{tenant}.ekso.app/api/board \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
All errors follow a consistent JSON structure:
{
"kind": "Validation",
"message": "Human-readable error description",
"fields": [
{ "field": "containerId", "code": "required" }
]
}
Error kinds
| Status | Kind | Meaning |
|---|
| 400 | Validation | One or more fields failed validation — check the fields array for details |
| 403 | Permission | The authenticated user lacks the required permissions |
| 422 | Logic | A business rule was violated (e.g., closing an already-closed cycle) |
| 500 | Exception | An unexpected server error — contact support if this persists |
The fields array is only present on Validation errors. Each entry identifies the field name and a machine-readable error code.
Response conventions
- Lists return JSON arrays directly (e.g.,
GET /api/board returns [{...}, {...}])
- Single resources return a JSON object (e.g.,
GET /api/board/{id} returns {...})
- Creates and updates return the full resource after the operation
- Deletes return
204 No Content on success
- All response bodies use camelCase property names
Token lifetimes and limits
When building integrations, keep these OAuth token lifetimes and client limits in mind:
| Setting | Value |
|---|
| Access token lifetime | 15 minutes |
| Authorization code lifetime | 5 minutes |
| Refresh token lifetime | 30 days |
| PKCE code challenge method | S256 |
| Max OAuth clients per tenant | 50 |
| Client staleness threshold | 90 days (unused clients may be cleaned up) |
Access tokens expire after 15 minutes. Your integration should use the refresh token to obtain a new access token before the current one expires. Refresh tokens are valid for 30 days — if a refresh token expires, the user must re-authorize.
Next steps