auth.intent

Authenticate a LinkedIn account with credentials or a session cookie.

Prerequisites

  • A Curviate API key, passed as apiKey when you construct the client. Quickstart shows how to create one.

Signature

intent(body: AuthIntentBody): Promise<AuthIntentResult>

Example

import { Curviate } from "@curviate/sdk";
 
const curviate = new Curviate({
  apiKey: "cvt_live_...",
  baseUrl: "https://api.curviate.com",
});
 
const result = await curviate.auth.intent({
  seat_id: "YOUR_SEAT_ID",
  auth_method: "credentials",
  credentials: { email: "YOUR_EMAIL", password: "YOUR_PASSWORD" },
  country: "US",
});
console.log(result.account_id);

Parameters

NameTypeRequiredDescription
seat_idstringNoThe empty seat this NEW account will occupy. Required on a new connect; omit it and the call returns 400 INVALID_REQUEST with 'seat_id is required'. Seat ids look like seat_01H..., and every seat you own is listed by GET /v1/accounts/seats (any item with occupied false is free to use) and with click-to-copy in the seat table on your dashboard. Ignored when account_id is present, because a reconnect keeps the account on its current seat.
auth_methodstringYesHow to authenticate. 'credentials' reads the nested credentials object (email + password). 'cookie' reads the nested cookie object (li_at) and also requires a top-level user_agent. Neither set of fields is accepted at the top level.
credentialsobjectNoEmail + password authentication, supplied as a NESTED object (email and password do not go at the top level). Required when auth_method=credentials.
cookieobjectNoSession-cookie authentication, supplied as a NESTED object (li_at does not go at the top level). Required when auth_method=cookie, which also requires a top-level user_agent.
account_idstringNoPresent = re-authenticate this existing account in place (reconnect); omit = connect a new account.
linkedin_premiumstringNoOptional. Which LinkedIn premium surface this connection should ask for: 'sales_navigator' or 'recruiter'. Omit it and the connection asks for every product, and LinkedIn activates whichever ones the account actually has. One LinkedIn account can hold only one of the two premium surfaces, and when both are asked for Sales Navigator takes precedence, so set this to 'recruiter' if the account holds both and you want the Recruiter surface. This applies per connection and is not remembered: state it on every connect and reconnect where Recruiter must win.
timezonestringNoOptional IANA zone name for this account's LinkedIn session, e.g. Europe/Berlin. Sent in canonical form; a UTC offset such as +02:00 is a 400.
external_idstringNoYour own id for the end user who owns this account, 1-255 chars, not unique. Treat it as opaque; avoid emails.
productsarrayNoOptional allow-list of premium products to ask for: sales_navigator, recruiter. Omit to ask for both; [] asks for none. Classic LinkedIn and company pages are always included.
countrystringNoWhere LinkedIn sees this account connecting from: a supported ISO 3166-1 alpha-2 country code (e.g. US, DE; case-insensitive). Pick the country the account owner normally signs in from. A new connect needs exactly one of country, ip or proxy. Strict by default: the connect fails rather than use another country, unless allow_country_fallback is true.
ipstringNoA public IPv4 address; its country becomes the connection location (strict by default). An alternative to country: send exactly one of country, ip or proxy on a new connect.
allow_country_fallbackbooleanNoOptional. false (the default with country or ip): only ever connect from that country; a connect fails when no connection is free there. true: a connection from another country may be used when none is free in the chosen one. Not accepted with proxy.
proxyobjectNoYour own proxy for this account's traffic. The proxy decides where LinkedIn sees the account connecting from, so country, ip and allow_country_fallback are not accepted with it.
user_agentstringNoExact browser User-Agent to pin for this account. REQUIRED for a cookie connect: send the User-Agent of the browser the li_at cookie was copied from. Optional for a credentials connect, where it helps an account that hits disconnection issues.
sync_limitobjectNoOptional caps on how much history is synced for this account.
recruiter_contract_idstringNoWhich Recruiter contract to bind this account to. Only meaningful when the LinkedIn account holds a Recruiter subscription.

Returns

Resolves to AuthIntentResult. Top-level fields: object, account_id, status, external_id, owner_user_id, team_access, connection_location, safety_warning.

Error codes

CodeWhat it means, and what to do
UNAUTHORIZEDThe API key is missing, malformed, or revoked. Check the key you passed to the client.
INVALID_REQUESTA parameter failed validation. The message names the offending field; fix the request rather than retrying it.
RATE_LIMIT_ACCOUNTThis account's own quota is exhausted. Wait for the window in the Retry-After header, then retry.
RATE_LIMIT_TENANTThe tenant-wide quota is exhausted across all accounts. Slow the whole workload, not just this call.
PLATFORM_RATE_LIMITLinkedIn is throttling this account. Back off well beyond the hinted delay; sustained pressure risks the account.
PLATFORM_ERRORAn upstream failure, usually transient: retry once with backoff before treating it as a real error. Check the response first, though. When it carries retry_likely_to_succeed: false and retry_hint: {kind: "never"}, retrying cannot help and backing off only delays the real answer.
ACCOUNT_ALREADY_LINKEDThat LinkedIn account is already connected. Reconnect or adopt the existing account instead of linking it again.
CHECKPOINT_ALREADY_RESOLVEDThe challenge is already solved. Poll for the account's status instead.
CHECKPOINT_EXPIREDThe challenge timed out. Request a fresh one and solve it promptly.
CHECKPOINT_INVALID_CODEThe code was wrong. Ask the account owner for the current one and resubmit.
CHECKPOINT_MAX_ATTEMPTSToo many wrong codes. Restart the connect flow from the beginning.
CHECKPOINT_NOT_FOUNDNo challenge is pending for that account. Start the connect flow again.
CHECKPOINT_UNSUPPORTEDThis challenge type cannot be solved through the API. Sign in on LinkedIn directly first.
CONNECTION_IN_PROGRESSA connection attempt for this LinkedIn account is already open. Wait for it to finish or expire before starting another.
CONNECTION_LOCATION_REQUIREDNo connection location was named. Send exactly one of country, ip or your own proxy (on PATCH, proxy: null needs a country).
CONNECTION_LOCATION_UNAVAILABLENo connection is free in that country right now, or the change landed elsewhere. Try a nearby country or allow fallback; read connectionLocation for where the account connects from now.
INTERNALAn unexpected server error. Retry once; if it persists, it is ours, not yours.
LINKEDIN_AUTH_FAILEDLinkedIn rejected the credentials. Confirm them with the account owner.
LINKEDIN_COOKIE_INVALIDThe session cookie is expired or invalid. Supply a fresh one, or connect with credentials.
LINKEDIN_RATE_LIMITEDLinkedIn is rate limiting the sign-in itself. Wait substantially longer before retrying.
LINKEDIN_SERVICE_UNAVAILABLELinkedIn is unavailable, or the resource is still being prepared upstream. Retry with backoff.
NO_ACTIVE_SEATThe targeted account is not on an active seat. Buy or attach a seat in Billing, then retry.
PAYLOAD_TOO_LARGEThree limits can trigger this. The platform's own ceiling on total request size is the lowest and the one you are most likely to hit: it starts rejecting at roughly 1 MB, so a handful of photo-sized images is refused even though it clears everything below. Above that, this API caps one attachment at 5 MiB of file content and the whole request body at 9 MiB. Attachments travel base64-encoded, which inflates them by about a third, so a 5 MiB file costs roughly 6.7 MiB of the body budget. Send fewer or smaller attachments; retrying unchanged will not help.
PAYMENT_REQUIREDThe workspace has no active subscription, or its subscription is past due. Subscribe, or update the payment method, then retry.
REAUTH_REQUIREDA cookie replay cannot change an account's scope. Re-authenticate with credentials instead.

Every code above is a stable CurviateError.code you can branch on. The full list, the response envelope, and retry semantics are in the Error codes reference.

Next steps

  • Quickstart: connect a LinkedIn account. An empty account list means the key works and nothing is connected yet.
  • auth.getSession: Poll a credential connect session by its account id, a pure status read that makes no external call and does not itself complete the connection.
  • auth.pollCheckpoint: Poll for mobile-app approval of a pending checkpoint challenge until it leaves pending.
  • SDK Quick Start: installation, the client, account scoping, and pagination.