Skip to content

API Keys

In the app, go to Account → Integrations and create a key. You’ll be asked for a name and the scopes it should carry (defaults to discovery if you don’t pick any — see Scopes).

Only an org owner or admin can create or revoke keys — the account scope this requires is role-gated server-side, not just hidden in the UI. If you’re on a team without that role, ask your org owner.

A key looks like:

cf_live_QSoVINQ4nCJQryOAQcEMBAX8hpEnKAPJ

There is a single cf_live_ prefix for all environments — dev and prod keys are indistinguishable by format, so keep track of which one you’re pasting where.

A cf_live_ key is not a bearer token. Every request must first exchange it:

Terminal window
curl -X POST https://api.infiniteaudience.ai/v1/auth/token \
-H "Content-Type: application/json" \
-d '{"api_key": "cf_live_QSoVINQ4nCJQryOAQcEMBAX8hpEnKAPJ"}'
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600
}

Use access_token as a bearer token on every subsequent call:

Terminal window
curl https://api.infiniteaudience.ai/v1/catalog/fields \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."

There is no refresh token — re-exchange instead

Section titled “There is no refresh token — re-exchange instead”

expires_in is always 3600 and the response carries nothing to refresh. When a token is close to expiring (or a request 401s), call POST /v1/auth/token again with the same key. A minimal client that owns this for you:

class InfiniteAudienceAuth {
private token: string | null = null;
private expiresAt = 0;
constructor(private apiKey: string, private baseUrl = 'https://api.infiniteaudience.ai') {}
async getToken(): Promise<string> {
// Refresh 60s early so a request in flight doesn't land right as it expires.
if (this.token && Date.now() < this.expiresAt - 60_000) return this.token;
const res = await fetch(`${this.baseUrl}/v1/auth/token`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ api_key: this.apiKey }),
});
if (!res.ok) throw new Error(`Token exchange failed: ${res.status}`);
const body = await res.json();
this.token = body.access_token;
this.expiresAt = Date.now() + body.expires_in * 1000;
return this.token!;
}
}

Delete it from Account → Integrations, or DELETE /v1/settings/api-keys/{id}. Revoked keys still appear in GET /v1/settings/api-keys (with active: false) so you can see your history — they aren’t deleted, just deactivated. Any access token already issued from a revoked key keeps working until it naturally expires (up to 1 hour) — revoking doesn’t invalidate tokens already in flight.