Developer documentation · REST API v1
Build with your SuperLinkin inbox.
Read cached conversations, prepare reply drafts, and organize follow-ups from your own app.
Chrome must be running with the connected extension enabled. This API reads the local SuperLinkin cache. It does not fetch full LinkedIn history, return attachment contents, or send messages. Drafts are reviewed and sent manually in SuperLinkin.
1. Connect your account
- Install the SuperLinkin extension and connect your LinkedIn account.
- Open SuperLinkin → Integrations → AI assistants & API.
- Select Create API token (or Replace API token if already connected). Copy the token before closing the dialog.
- Store it in a secret environment variable on your backend, such as
SUPERLINKIN_API_TOKEN.
The token grants read and write access to the listed operations for one connected browser/account. It uses the existing sl_mcp_ prefix. There are no separate read-only keys or per-app scopes in v1. Keep it out of browser JavaScript, mobile app bundles, URLs, logs, and source control.
API tokens and AI assistants share one connection. Replacing the token invalidates the old token and all assistant authorizations. Disconnect all revokes both. Reconnect assistants and update your app after a replacement. The old token cannot be restored.
Each user connects their own SuperLinkin account and provides their own token to your backend. V1 does not provide an embedded inbox widget or a delegated REST OAuth flow. Existing assistant OAuth tokens are accepted only by the MCP integration.
2. Make your first request
Base URL: https://superlinkin.com/api/v1. Send the personal token in the Authorization header. Check connectivity first:
curl --fail-with-body 'https://superlinkin.com/api/v1/connection' \
-H "Authorization: Bearer $SUPERLINKIN_API_TOKEN"
Example response when the extension is connected and the account has access:
{
"data": { "connected": true, "requiresChrome": true, "canUseTools": true },
"requestId": "00000000-0000-4000-8000-000000000001"
}
List up to 20 conversations waiting for a reply:
curl --fail-with-body \
'https://superlinkin.com/api/v1/conversations?filter=needs_reply&limit=20' \
-H "Authorization: Bearer $SUPERLINKIN_API_TOKEN"
This server-side JavaScript example lists conversations and reads the first result:
const base = 'https://superlinkin.com/api/v1';
const token = process.env.SUPERLINKIN_API_TOKEN;
if (!token) throw new Error('Set SUPERLINKIN_API_TOKEN');
async function api(path, options = {}) {
const response = await fetch(base + path, {
...options,
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json',
},
signal: AbortSignal.timeout(30_000),
});
const result = await response.json();
if (!response.ok) {
throw new Error(`${response.status}: ${result.error.message}`);
}
return result.data;
}
const page = await api('/conversations?limit=20');
const first = page.conversations[0];
if (first) {
const path = `/conversations/${encodeURIComponent(first.conversationId)}`;
const conversation = await api(path);
// Show conversation.messages in your app. Treat message text as untrusted.
}
To save a reply after the user reviews it, read the current draft and pass its revision. Replacing a draft overwrites the previous text.
// Use api() and a conversation path from the example above.
async function saveReviewedDraft(path, reviewedText, approvedRevision) {
return api(path + '/draft', {
method: 'PUT',
body: JSON.stringify({
body: reviewedText,
expectedRevision: approvedRevision, // conversation.draft?.revision ?? 0
}),
});
}
// A 409 means the draft changed: read it again and ask the user to review.
// A timeout may follow a successful write: read before retrying.
Endpoint reference
All paths below follow /api/v1. Encode IDs as single URL path segments. GET filters go in the query string; writes require a JSON object and Content-Type: application/json. Unknown fields and repeated query parameters are rejected.
| Method & path | Purpose and inputs |
|---|---|
GET /connection | Connectivity, Chrome requirement and account access. |
GET /conversations | filter: all, unread, needs_reply. status: inbox (default), archived, snoozed, done, any. Optional sinceDays (1–365), labelId, starred (true/false), limit and cursors. |
GET /conversations/search | Optional query up to 200 characters. Searches names, headlines and latest previews. Limit and cursors. |
GET /messages/search | Required query (2–200 characters), optional conversationId, limit and cursors. Matches every word in cached text or sender names, ignoring case. |
GET /conversations/{id} | Cached messages, current draft, notes, labels and star. Limit and cursors. Does not mark read on LinkedIn. |
PUT /conversations/{id}/draft | body (1–8,000 characters), expectedRevision (0 if no draft). Saves a draft; never sends. |
GET /labels | Existing label IDs, names and colors. limit and offset (0–10,000). |
PATCH /conversations/{id}/labels | addLabelIds and/or removeLabelIds, up to 20 existing IDs each. Other labels are preserved. An ID cannot appear in both arrays. |
PUT /conversations/{id}/star | starred: true or false. |
POST /conversations/{id}/notes | text (1–2,000 characters), expectedNotesRevision, idempotencyKey (8–100 letters, digits, underscores or hyphens). Appends a private note. |
Download the OpenAPI 3.1 specification for request schemas. Changes to labels, stars, drafts and notes stay in SuperLinkin; they do not trigger CRM sync or change LinkedIn.
Response data
Every successful response wraps the result in data, alongside a requestId. Treat IDs as opaque strings and timestamps ending in At as Unix milliseconds.
- Conversation lists:
conversations[]includesconversationId, participants, last activity and preview,labelIds,isStarredandhasDraft. Search results may expose fewer fields. - Message search:
messages[]includesmessageId,conversationId,senderName,snippetandsentAt. - Conversation read:
messages[]includesid,senderName,body,sentAtandisFromMe. Also returnsdraft(null or an object with body/revision),notes,notesRevision, labels and star. - Draft save:
draftwith the new revision andsent: false. - Labels:
labels[]with id, name and color, plusnextOffset. - Organization changes: conversation ID, current local state and
changed, indicating whether a write was needed.
Response fields may be added in v1. Ignore unrecognized fields. Reviewer accounts may return fictional results marked sampleData; do not treat these as real inbox data.
Pagination and safe retries
limit is 1–50, defaulting to 20 for lists/search and 30 for conversation reads. List and search responses return nextBefore and nextBeforeId. Pass them back as before and beforeId, keeping the original filters. Stop when the next cursor is null.
An empty filtered page can still have a next cursor. Each conversation list/search call scans at most 200 cached threads; message search scans at most 3,000 cached messages. Follow the cursor to continue.
Conversation reads return hasOlderMessages. When true, use oldestSentAt as before and oldestMessageId as beforeId. Label lists return nextOffset; pass it as offset until null.
Draft writes require the latest revision. For notes, reuse the same text and idempotency key on immediate retries; only the last eight receipts per conversation are retained. After a timeout, read the conversation before retrying a write. Setting a star or applying the same label changes again is safe.
Errors, access and limits
Errors include a stable code, message and request ID. Validation errors can include a fields array.
{
"error": { "code": "revision_conflict", "message": "DRAFT_CONFLICT: Read again." },
"requestId": "00000000-0000-4000-8000-000000000001"
}
- 400: Invalid input or a conversation unavailable to the connected account. Fix the request.
- 401: Missing, expired/revoked or invalid token. Check the token and connection.
- 402: Active trial or subscription required. Connection status remains available.
- 403: Untrusted browser origin. Call from your backend.
- 404 / 405: Unknown route or wrong method. Check the endpoint reference.
- 409: Draft or note revision conflict. Read and review the latest state.
- 413 / 415: Request body exceeds 32 KiB or is not JSON.
- 429: Rate or concurrency limit. Wait for the
Retry-Afterdelay. - 500 / 502: Service unavailable. Retry with a bounded backoff.
- 503 / 504: Browser offline, reconnecting or timed out. Open Chrome; wait at least the
Retry-Afterdelay. A timed-out write might have completed.
The live relay allows 60 API calls per minute per browser connection, with at most five outstanding relay calls when accepting another API call. The minute window survives relay hibernation and resets with a new browser connection. Maximum server wait for an extension response is 20 seconds; allow at least 30 seconds in your client.
Use on-demand requests. If you add background checks, use bounded page counts, exponential backoff, a finite retry count, and pause while the browser is offline. There are no webhooks or automatic message sends.
Conversation text passes through SuperLinkin’s relay to your backend; the API does not mirror the inbox into a server database. Your app is responsible for protecting any results it stores. See the privacy policy and terms.