Eliq: Authentication
Eliq APIs use OAuth 2.0 client credentials for authentication. Each integration is issued a dedicated OAuth client identity (client_id) that is set up in collaboration with your Eliq account manager and managed through the Client Admin Portal.
The access token obtained from the auth endpoint must be passed as a Bearer token in the Authorization header of all API requests. Client credentials and access tokens must never be stored insecurely or exposed to client-side applications (e.g. mobile or browser apps).
Your client_id is provided by your Eliq account manager when your integration is set up. Client secrets are generated via the Client Admin API or by your account manager.
In the Client Admin Portal you can:
Multiple secrets are supported per client, allowing you to rotate secrets without downtime. A secret is valid for 90 days by default and at most 180 days, so plan to rotate before it expires.
Use this flow for server-to-server integrations where no end-user context is needed.
POST /oauth/token
The body can be sent as JSON or as application/x-www-form-urlencoded, with the same field names.
{
"grant_type": "client_credentials",
"client_id": "utility-acme-backend",
"client_secret": "{client_secret}",
"aud": "data-management-api"
}
| Field | Type | Description |
|---|---|---|
grant_type | String | Always client_credentials |
client_id | String | Your OAuth application identity, provided by your account manager |
client_secret | String | Your client secret |
aud | String | The API you are requesting access to (e.g. data-management-api, insights-api) |
scope | String | Optional. Space-delimited scopes. Defaults to the scopes configured for your client |
Use this flow to issue a token on behalf of a specific user. Required when the target API enforces user context (e.g. when calling the Insights API for a specific end user).
POST /oauth/token
{
"grant_type": "client_credentials",
"client_id": "utility-acme-frontend",
"client_secret": "{client_secret}",
"aud": "insights-api",
"scope": "insights.read insights.write",
"sub": "{user_id}",
"sub_type": "user"
}
| Field | Type | Description |
|---|---|---|
grant_type | String | OAuth grant type. Use client_credentials for new tokens, or refresh_token to exchange a refresh token (see Refresh token) |
client_id | String | Your OAuth application identity |
client_secret | String | Your client secret |
aud | String | The API you are requesting access to |
scope | String | Optional. Space-delimited scopes |
sub | String | The ID of the user the token is issued on behalf of |
sub_type | String | Type of subject, typically user. Required when sub is set |
issue_refresh_token | Boolean | Optional. Set to true to receive a refresh token alongside the access token |
If you leave out scope, the token gets the default scopes configured for your client. Ask only for what the integration needs. The Client Admin Portal lists the scopes your client can use per API.
API (aud) | Scopes |
|---|---|
data-management-api | data.read, data.write |
insights-api | insights.read and insights.write cover the whole API. Narrower scopes limit a token to one area: insights.budgets.read, insights.budgets.write, insights.homeprofile.read, insights.homeprofile.write, insights.devices.read, insights.topup.read, insights.topup.write |
expires_in and refresh_token_expires_in are in seconds. By default access tokens last 10 minutes and refresh tokens 90 days (sliding); your account manager can change this for your organization. Always read expires_in instead of assuming a fixed lifetime.
{
"access_token": "eyJhbG...",
"token_type": "Bearer",
"expires_in": 600
}
For delegated tokens with issue_refresh_token: true, the response also includes:
{
"access_token": "eyJhbG...",
"token_type": "Bearer",
"expires_in": 600,
"refresh_token": "eliq_rt_...",
"refresh_token_expires_in": 7776000
}
Exchange a refresh token for a new access token without re-authenticating.
POST /oauth/token
{
"grant_type": "refresh_token",
"refresh_token": "{refresh_token}"
}
Refresh tokens rotate. Every refresh returns a new access token and a new refresh token. Store the new refresh token and throw the old one away: each refresh token works once.
expires_in to refresh shortly before expiry instead of waiting for a 401.Refresh tokens are revoked when the user signs out, when an administrator revokes them, or after reuse. A refresh token also stops working after refresh_token_expires_in seconds.
Eliq can limit the token endpoint to your own IP ranges, per OAuth client. Tokens can then only be requested from those addresses. Other requests are rejected with 401 and the error invalid_ip. Send your egress IP ranges to your account manager to turn this on.
Tokens are signed with asymmetric keys. The public key set is available at:
GET https://auth-api.eliq.com/.well-known/jwks.json
The full OpenID Connect discovery document is available at:
GET https://auth-api.eliq.com/.well-known/openid-configuration
| Environment | URL |
|---|---|
| Production | https://auth-api.eliq.com |
| UAT | https://auth-api-uat.eliq.com |
Full API reference: developer.eliq.com/api-reference/auth-api
AI assistants such as Claude connect to the Eliq MCP servers with their own sign-in flow. See MCP servers.
If your integration uses a numeric client_id (Utility ClientId), your existing setup continues to work without any changes. Contact your account manager to discuss migrating to the current authentication model.