--- title: Authentication | Vitable Docs description: How to authenticate with Vitable's API using API keys and bound access tokens. --- Vitable uses two types of credentials depending on your integration: - **API keys** — for server-to-server requests (creating employers, managing employees, etc.) - **Bound access tokens** — short-lived, employee-scoped tokens for the [Employee Dashboard Widget](/drops/employee-dashboard/index.md) ## Getting an API Key To get an API key, please [reach out to our team](mailto:felippe@vitablehealth.com). We’ll provide you with the credentials to access the Vitable API. Your API key grants full access to your organization’s data. Keep it server-side only. Never expose your API key in frontend code, public repositories, or client-side requests. Treat it like a password. ## Server-Side Authentication Include your API key as a Bearer token in the `Authorization` header: Terminal window ``` curl -X GET https://api.vitablehealth.com/v1/employers \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" ``` ``` import requests response = requests.get( "https://api.vitablehealth.com/v1/employers", headers={ "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json", }, ) data = response.json() ``` ``` const response = await fetch("https://api.vitablehealth.com/v1/employers", { headers: { Authorization: "Bearer YOUR_API_KEY", "Content-Type": "application/json", }, }) const data = await response.json() ``` A successful request returns `200` with a JSON body. If authentication fails, you’ll receive: ``` { "error": { "code": "unauthorized", "message": "Invalid or missing API key" } } ``` All timestamps in API requests and responses are in **UTC**, formatted as ISO 8601 (e.g., `2026-01-23T14:30:00+00:00`). ## Bound Access Tokens The [Employee Dashboard Widget](/drops/employee-dashboard/index.md) requires a **bound access token** instead of your API key. A bound token is a short-lived session token scoped to a single employee — it can only access that employee’s data, providing row-level security in the browser. Your server creates bound tokens by calling the [Issue Access Token](/api/resources/auth/methods/issue_access_token/index.md) endpoint with your API key: Terminal window ``` curl -X POST https://api.vitablehealth.com/v1/auth/access-tokens \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "grant_type": "client_credentials", "bound_entity": { "type": "employee", "id": "empl_abc123" } }' ``` The response includes the token and its lifetime: ``` { "access_token": "vit_at_...", "expires_in": 3600 } ``` Your frontend uses this token to initialize the widget. The `@vitable/connect` SDK handles token refresh automatically — see the [Employee Dashboard Widget](/drops/employee-dashboard/index.md) guide for the full integration flow. | Field | Description | | ------------------- | ---------------------------------------------- | | `grant_type` | Always `"client_credentials"` | | `bound_entity.type` | Always `"employee"` | | `bound_entity.id` | The Vitable employee ID the token is scoped to | | `access_token` | The bound token to pass to the widget | | `expires_in` | Token lifetime in seconds |