Authentication
The External API uses OAuth2 client credentials to authenticate partner systems. Every call must be accompanied by a valid bearer token and an x-e1-client-id header that matches the client_id used to obtain that token.
Obtaining a bearer token
Exchange your client_id and client_secret for an access token at the OAuth2 token endpoint (see Environments).
POST https://auth.api.estimateone.com/oauth2/tokenContent-Type: application/x-www-form-urlencoded
grant_type=client_credentials&client_id=<client_id>&client_secret=<client_secret>&scope=speci-finder/readResponse:
{ "access_token": "eyJhbGc...", "token_type": "Bearer", "expires_in": 3600}expires_in is expressed in seconds. Tokens are valid for 1 hour from issuance.
Required request headers
Every authenticated request must carry both of the following:
| Header | Value | Purpose |
|---|---|---|
Authorization | Bearer <access_token> | Proves your identity to the API gateway. |
x-e1-client-id | your client_id | Defence-in-depth check that the caller owns the token. The API compares this header to the client_id claim inside the token. |
If you omit x-e1-client-id, you’ll receive 400 Bad Request with error code CLIENT_ID_HEADER_MISSING. If the header doesn’t match the token, you’ll receive 401 Unauthorised with error code CLIENT_ID_HEADER_MISMATCH. See Errors for the full catalogue.
Token lifecycle
- Lifetime: 3600 seconds (1 hour).
- Refresh: there is no refresh-token flow — this is the client credentials grant. When a token is close to expiry (or when a call fails with 401), request a new token using your
client_idandclient_secret. - Caching: cache tokens in-memory until just before their
expires_inwindow ends. Do not persist tokens to disk. - Concurrency: a single token can be used from multiple processes simultaneously. You don’t need one token per worker.
A common pattern is to wrap your HTTP client in a small helper that:
- Holds the current token and its expiry time.
- Fetches a new token lazily on first use, and when the cached token is within ~60 seconds of expiry.
- Retries a single time on
401by discarding the cached token and fetching a fresh one.
Handling the client_secret
The client_secret is a long-lived shared secret. Treat it like a password.
- Do not commit it to source control. Use environment variables or a secret manager.
- Do not share it across integrations. If you operate multiple products, request a separate credential per product.
- Rotate on suspected compromise. Contact E1 support to issue a new credential; once confirmed, revoke the old one. See Security for the disclosure channel.
- Rotate on staff changes. If a staff member with access to the secret leaves, rotate it.
Secret rotation
E1 can issue a new client_secret on request. The rotation flow is:
- You request a rotation via the support channel.
- E1 issues a new credential (new
client_idandclient_secret). - You deploy the new credential to your systems and confirm it’s working.
- E1 revokes the old credential on your go-ahead.
Old and new credentials can coexist during the changeover, so there is no downtime if you deploy in this order.
Scopes at token-request time
The scope parameter in the token request is optional — if omitted, the token carries all scopes your application is permitted to use. You can narrow the token’s scope by passing a space-separated list (currently only speci-finder/read is defined for supplier partners).
At request time, the API intersects the token’s scopes with the permission’s scopes, and rejects the call if the intersection doesn’t include any of the route’s required scopes. See Authorization for detail.