Authentication

Every call to the Woven API needs two things: a subscription key that identifies you to the gateway, and an access token that identifies the Woven user you are acting as. This page covers how to get both.

Your portal account is not your Woven account

The account you created here signs you in to this documentation site and issues your subscription key. It is not a Woven login. The Username and Password you send to /tokens/v2 are the credentials for a user inside the Woven application itself. If you do not have one, ask your Woven administrator to create a user for your integration.

Environments

Production and development are entirely separate. Accounts, subscription keys and data do not cross between them, so a key issued on one will be rejected by the other.

                Base URL                                Portal
Production https://gateway-api.woven.team/api api-docs.woven.team
Development https://gateway-api-dev.woven.team/api api-dev-docs.woven.team

Headers on every request

Header             Value                        When
----------------- --------------------------- ---------------------------------------
Subscription-Key your key from Profile Every request, including the login call
AccessToken token from /tokens/v2 Every request except /tokens/v2
ApiVersion 1.0 Every request
Content-Type application/json POST and PUT

The subscription key is required on the login call too. This catches most people out. /tokens/v2 needs no AccessToken, because it is the call that issues one, but it still needs Subscription-Key like everything else. Without it you get a 401 Access Denied that looks exactly like a bad password.

Step 1 - get an access token

Send your Woven credentials. Leave CompanyID out of the body entirely.

curl -X POST "https://gateway-api-dev.woven.team/api/tokens/v2" \
-H "Subscription-Key: <your subscription key>" \
-H "ApiVersion: 1.0" \
-H "Content-Type: application/json" \
-d '{
"Username": "you@example.com",
"Password": "your-woven-password",
"Platform": 1
}'

The Platform parameter identifies the calling client: 1 API, 2 Web, 3 iOS, 4 Android. Integrations send 1.

Check the body, not the status code. A rejected login returns 200, not 401. Confirm AccessToken is non-null and FailedLoginAttempt is false before you use the token.

A successful response carries the token and the company you are now acting as:

{
"AccessToken": "eyJhbGciOiJIUzI1NiIs...",
"TokenExpirationDate": "2026-09-02T18:17:40.943Z",
"FailedLoginAttempt": false,
"AccountStatus": 1,
"CompanyID": "e60c07a1-6f13-44f2-82a7-9607dc9d653f",
"HasMultipleCompanyAccess": false,
"CompanyLoginOptions": []
}

Keeping your token current

The access token is a JWT valid for 7 days from the moment it is issued. TokenExpirationDate on the response is the authoritative expiry. Store it alongside the token and work from it rather than assuming a schedule.

Logging in again does not extend your token. If you call /tokens/v2 while your current token is still valid, Woven returns the same token with its original expiry rather than issuing a new one. Once the token has expired, the next login mints a fresh one with a full 7 days.

The response also carries RefreshToken and RefreshTokenExpirationDate. Those belong to a refresh flow reserved for the Woven mobile apps and are not used by this API. To renew, call /tokens/v2 again with your credentials.

For a scheduled integration that means: cache the token and its expiry, reuse it across runs until the expiry passes, then log in again. If a call fails with 401 mid-run, log in once and retry that call rather than re-authenticating before every request.

If you have access to more than one company

Most integration users belong to a single company. If yours does, HasMultipleCompanyAccess is false, your CompanyID is already filled in on the response, and you are done. There is nothing else to do and no second call to make.

If HasMultipleCompanyAccess is true, the token you were issued is not yet scoped to a company. CompanyLoginOptions lists the companies available to you. Pick the one you want, then call /tokens/v2 again with its CompanyID included in the body, and use the token from that second response.

Step 2 - call an endpoint

curl "https://gateway-api-dev.woven.team/api/locations" \
-H "Subscription-Key: <your subscription key>" \
-H "ApiVersion: 1.0" \
-H "AccessToken: <token from step 1>"

The token goes in its own AccessToken header. It is not a Bearer token and does not go in Authorization.