Authentication & Accounts
This article walks through the two things you need before your first API call: obtaining your Curviate API key and connecting a LinkedIn account.
Step 1 — Obtain your API key
Your Curviate workspace API key is ready as soon as you sign up. It lives in the key chip at the top-right of the dashboard top bar. The chip shows the key prefix (for example cvt_live_…); click the copy icon on the chip to copy the full key to your clipboard. The key is a tenant-scoped secret that works across the REST API, CLI, and MCP server, and you only need one. If you have revoked your key, the chip shows a Generate API key control to mint a replacement; that full key is revealed once, so copy it right away.
Step 2 — Understand the key format and keep it safe
| Property | Value |
|---|---|
| Live format | cvt_live_… (24-character suffix) |
| Test format | cvt_test_… (24-character suffix) |
| Scope | Tenant workspace — all accounts and resources |
| TTL | Non-expiring until rotated |
| Rotation | Key chip → ⋮ menu → Refresh token |
| Storage | Server-side environment variable only |
Security
- Store the key in an environment variable (
CURVIATE_API_KEY). Never put it in client-side code or version control. - Rotate immediately on suspected exposure via the key chip's ⋮ menu → Refresh token (the replacement is shown once). To disable a key entirely, use ⋮ → Revoke key.
Step 3 — Connect a LinkedIn account
Before your API calls can act on LinkedIn, you need to connect a LinkedIn account in the Curviate dashboard.
- In the dashboard, navigate to Accounts (
/accounts). - Click Connect account. If you have no seats, the modal prompts you to purchase a seat first.
- The connect modal offers two authentication methods:
- Credentials (recommended) — enter your LinkedIn email and password. Credentials are encrypted at rest and never logged.
- Cookie — paste the
li_atvalue from your browser's LinkedIn cookies. The modal includes an inline "How to find my cookies?" guide.
- Select your preferred method, fill in the form, and click Connect.
- If LinkedIn issues a verification challenge, the dashboard walks you through it — entering a one-time code (from email, SMS, an authenticator app, or WhatsApp), choosing between a code and an in-app approval, approving the sign-in in the LinkedIn mobile app, or picking a Recruiter / Sales Navigator seat. A mobile-app approval is time-limited (a few minutes); if it expires before you approve, the dashboard explains how to retry.
- If that LinkedIn identity is already connected to your workspace, the dashboard offers to reconnect the existing account rather than creating a duplicate — one LinkedIn account maps to one connection per workspace.
- On success, your account appears in the Accounts list with status
activeand a copy-ableacc_…account ID.
Account ID — The
account_id(formatacc_…) identifies your connected LinkedIn account in every API call, CLI command, and SDK method. You can copy it from the Accounts table at any time.
Connecting accounts programmatically
You can connect accounts from the API instead of the dashboard — for example, to onboard your own customers. POST /v1/auth/intent is the single connect path: you supply the LinkedIn credentials or cookie, and the same endpoint handles both a brand-new connection and re-authenticating an existing one in place. LinkedIn often responds with a verification challenge, so the flow can take more than one call:
-
POST /v1/auth/intentwith eitherauth_method: "credentials"(email+password) orauth_method: "cookie"(li_at). Cookie auth also requires a top-leveluser_agent— the exact browser User-Agent the cookie was captured with. Omitaccount_idto connect a new account into the givenseat_id; includeaccount_idin the body to re-authenticate an existing account in place — the same endpoint handles both. -
A
201(new) or200(reconnect) means the account connected immediately. A202means a challenge is required — the body carries anaccount_id, achallenge_type, and anexpires_at:{ "object": "checkpoint", "status": "checkpoint_required", "account_id": "acc_...", "challenge_type": "two_factor_app", "expires_at": "2026-06-08T10:10:00Z" } -
Resolve the challenge on the same account. For a code-based challenge, submit the code to
POST /v1/auth/checkpoint/solvewith{ "account_id": "acc_...", "code": "123456" }; re-request the notification withPOST /v1/auth/checkpoint/request(same body shape) if the user never received it. For amobile_app_approvalchallenge, the user approves the sign-in in the LinkedIn app — pollPOST /v1/auth/checkpoint/pollwith{ "account_id": "acc_..." }until it returns the connected account, or untilexpires_atpasses and it reportsstatus: "expired". You can also read the connect's current status at any time withGET /v1/auth/sessions/{session_id}, passing the connect'saccount_id(theacc_…id) assession_id. -
A resolved challenge returns the connected account. If it turns out to re-adopt an identity your workspace already holds, the account is returned with
"recovered": true.
If the identity is already connected, POST /v1/auth/intent (new-connect branch) returns 409 ACCOUNT_ALREADY_LINKED — pass that identity's account_id in the body on a follow-up POST /v1/auth/intent call to re-authenticate it in place instead of creating a duplicate. When your workspace already owns that account, the error names your own account_id so you can reconnect it directly.
Every step above has a CLI equivalent under curviate account — see the CLI account reference. For the full request and response shapes, see the API reference.
Next: API Quick Start