The Speak AI API exposes 2 authentication endpoints under the base URL https://api.speakai.co/v1. Every request needs your API key in the x-speakai-key header, as described in Authentication. No access token is needed.
Send your API key on every request, in the x-speakai-key header. The API authenticates the request from the key alone, so you do not need an access token.
curl 'https://api.speakai.co/v1/media' \
-H 'x-speakai-key: YOUR_API_KEY'You can send the same key as Authorization: Bearer YOUR_API_KEY instead. The API treats it exactly like x-speakai-key, which helps when your client cannot set custom headers.
A missing or invalid API key returns 401.
Access tokens for older integrations
Integrations built on the earlier token flow keep working, and you do not need to change them. New integrations can skip this section. In that flow you exchange your API key for a token pair and send the access token in x-access-token alongside x-speakai-key.
-
Get an access token: Call
POST /v1/auth/accessTokenwith yourx-speakai-keyandContent-Type: application/jsonheaders and an empty JSON body,{}. The response returns youraccessTokenandrefreshTokeninside thedataobject. -
Use the access token: Send the access token in the
x-access-tokenheader alongside yourx-speakai-key. When a request carriesx-access-token, the API also checks that token, so an expired token returns401even with a valid key. -
Refresh the token: When the access token expires, call
POST /v1/auth/refreshTokenwith bothx-speakai-keyandx-access-tokenheaders (include the expired access token), and pass{"refreshToken": "..."}in the request body. You get a newaccessTokenandrefreshTokenpair.
Example Response
{
"data": {
"email": "you@example.com",
"accessToken": "eyJhbG...",
"refreshToken": "eyJhbG..."
}
}Token Expiry
| Token | Expiry | Action on Expiry |
|---|---|---|
| Access Token | 80 minutes | Call Refresh Token endpoint |
| Refresh Token | 24 hours | Re-authenticate via Get Access Token |
Rate Limits
Both /v1/auth/accessToken and /v1/auth/refreshToken are limited to 5 requests per 60 seconds. Exceeding this returns 429 Too Many Requests.
Error Handling
- Expired Access Token: Returns
401 Unauthorized. Use the Refresh Token endpoint to get a new token pair, or stop sendingx-access-tokenand authenticate with the API key alone. - Expired Refresh Token: Returns an error response. Get a new pair from the Get Access Token endpoint.
- Rate Limited: Returns
429. Wait and retry, with exponential backoff for automated clients.
What can you do with the authentication endpoints?
Speak AI groups these 2 endpoints under the authentication resource. Each entry below links to the full reference for that endpoint further down this page.
Get Access Token
/auth/accessTokenOptional, for older integrations. You do not need this endpoint to call the API: send your API key in x-speakai-key (or Authorization: Bearer) on every request instead. Integrations built on the earlier token flow use it to exchange the API key for an access token and refresh token.
Upon successful authentication, the server responds with a status of “success” and returns your email, access token, and refresh token in the response data.
Request rules. The request body is entirely optional: you can post an empty JSON object. Authentication comes from your API key in the x-speakai-key request header, not from the body, and a missing or invalid key returns 401. A deactivated account returns 200 with a deactivated status rather than tokens. This endpoint is rate limited to 5 requests per minute per IP address.
Request body
Fields marked required are the ones the server rejects the request without. Anything conditional, where a field becomes required only alongside another, is described under Request rules above rather than marked here.
| Field | Type | Description |
|---|---|---|
deviceType |
string | Labels the kind of client requesting the token so the resulting session is identified correctly in your login history. Leave it out and the session is labeled as an API session. Send zapier when you want a plain token pair with no session recorded; in that case the refresh token you get back cannot be exchanged later, so request a new access token instead of refreshing. Any value outside the accepted list is rejected when the session is saved, and you still get a working access token but no session record and no usable refresh token. Optional string. Defaults to api when you omit it or send an empty value. Only web, android, ios, zapier, api and desktop are stored successfully. One of: web, android, ios, zapier, api, desktop . |
curl -X POST 'https://api.speakai.co/v1/auth/accessToken' \
-H 'x-speakai-key: sk_test_speak_0000000000000000' \
-H 'Content-Type: application/json' \
-d '{}'200 OK
Response body, application/json.
| Field | Type |
|---|---|
status |
string |
data |
object |
data.email |
string |
data.accessToken |
string |
data.refreshToken |
string |
Example response (Get Access Token), application/json.
{
"status": "success",
"data": {
"email": "your_email_id",
"accessToken": "access_token",
"refreshToken": "refresh_token"
}
}404 Not Found
Response body, application/json.
| Field | Type |
|---|---|
status |
string |
requestId |
string |
code |
integer |
message |
string |
hints |
string[] |
Example response (Get Access Token - Failure (No value found for Speak AI Key)), application/json.
{
"status": "failed",
"requestId": "ca665625-645e-438a-867d-366a6e3f133a",
"code": 401,
"message": "The authorization api key provided for the request is invalid.",
"hints": [
"The authorization api key provided for the request is invalid."
]
}Example response (Get Access Token - Failure - Invalid API Key), application/json.
{
"status": "failed",
"requestId": "358bc130-e798-41c2-9864-2cd2ce9b766d",
"code": 401,
"message": "The authorization api key provided for the request is invalid.",
"hints": [
"The authorization api key provided for the request is invalid."
]
}Refresh Token
/auth/refreshTokenOptional, for older integrations that use access tokens. If you authenticate with your API key alone you never need to refresh anything.
This endpoint refreshes the access token by providing the refresh token in the request body.
The refreshToken expires in 24 hour.
Request Body
- refreshToken (string, required): The refresh token used to obtain a new access token.
Response
- status (string): Indicates the status of the request, where “success” means the request was successful.
- data (object): Contains the new access token and refresh token.
- accessToken (string): The new access token.
- refreshToken (string): The new refresh token.
Request rules. You must send refreshToken in the body unless the request already carries Speak’s refresh token session cookie, which only browser clients signed in through Speak’s own web apps have. The server reads the body value first and falls back to that cookie, so an API integration that omits the field always gets a 404. This endpoint is rate limited to 5 requests per minute per IP address.
Request body
Fields marked required are the ones the server rejects the request without. Anything conditional, where a field becomes required only alongside another, is described under Request rules above rather than marked here.
| Field | Type | Description |
|---|---|---|
refreshToken |
string | The refresh token you received the last time you signed in or requested a token. Send it here to get back a new access token and a new refresh token. Refresh tokens are single use: once you exchange one, the old value stops working, so store the new one from the response and use that next time. Replaying an already used refresh token ends the whole session and forces a fresh sign in. A missing token, or one that does not match an active session, returns 404. A token that is expired, tampered with, or otherwise not valid returns 401. Must be a string. An empty value or a value that is not a string is treated as missing and returns 404. Sending a non-string value also cancels the cookie fallback, so send either a real token string or no field at all. Required for API callers, since the only alternative the server accepts is a browser session cookie. |
curl -X POST 'https://api.speakai.co/v1/auth/refreshToken' \
-H 'x-speakai-key: sk_test_speak_0000000000000000' \
-H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000' \
-H 'Content-Type: application/json' \
-d '{}'200 OK
Response body, application/json.
| Field | Type |
|---|---|
status |
string |
data |
object |
data.accessToken |
string |
data.refreshToken |
string |
Example response (Refresh Token), application/json.
{
"status": "success",
"data": {
"accessToken": "new_access_token",
"refreshToken": "new_refresh_token"
}
}404 Not Found
Response body, application/json.
| Field | Type |
|---|---|
status |
string |
requestId |
string |
code |
integer |
message |
string |
Example response (Refresh Token - Failure - Invalid / Expired Token), application/json.
{
"status": "failed",
"requestId": "3fcf7e0c-a977-4c37-bae5-a72485206cd0",
"code": 404,
"message": "We were unable to find a valid token. Your token may have expired or invalid. Please contact development team."
}Related pages
- API reference for the base URL, authentication, and the error format.
- Upload audio and video to Speak AI and read insights
- Create and update live transcription sessions
- Analyze text notes with the Speak AI text endpoints
- Export Speak AI transcripts and insights to a file
Get an API key on the Speak AI developer page.