Skip to content
V2 (Legacy) API ReferenceGet started
Resources

FAQ

Frequently asked questions about the Linq API, SDKs, MCP server, and LLM-friendly docs.

Where can I access the API toolkit?

The API toolkit lives in the Linq dashboard — look for the code icon. From there you can manage API keys, browse documentation, configure webhook subscriptions, view delivery logs, and check line status.

How do I debug API issues?

Every API response includes a trace_id — include it when contacting support to speed up diagnosis.

See Debugging for a full troubleshooting guide.

Do you have read-only API keys?

Not currently — all API keys have full read/write access.

How do I rotate my API key?

Contact your Linq representative to rotate your API key.

What's the best place to monitor usage and health of my lines?

Check the analytics page in the Linq dashboard for usage, and the phone numbers section for operational status. For programmatic monitoring, subscribe to the phone_number.status_updated webhook event.

Where can I view a list of my phone lines?

To see all your phone lines, call GET /api/partner/v3/phone_numbers or browse them in the Linq dashboard.

Are there best practices for messaging with the Linq API?

Yes — see the Best Practices guide for recommended patterns around messaging flow, contact card sharing, opt-out handling, and keeping lines in good standing.

What messaging protocols does Linq support?

Linq supports iMessage, RCS, and SMS/MMS. The API automatically selects the best protocol based on recipient capabilities, or you can explicitly choose one with the preferred_service parameter.

See Protocol Selection for details.

Is there a sandbox or test environment?

Yes! Sign up for a sandbox account to get started. Sandbox accounts have a 100 messages/day limit — see Rate Limits for details. We recommend using separate API tokens for development and production.

How do I migrate from V2 to V3?

V3 introduces a redesigned resource model, multi-part messages, event-based webhooks, and a new base path (/api/partner/v3/). Contact your Linq representative for migration assistance and a V3 API token.

See the V2 to V3 Migration Guide for a full breakdown of what changed.

Can I use V2 and V3 simultaneously?

Yes. V2 and V3 operate independently with the same token but with different endpoints. You can run both during a migration period, but messages sent via one version won’t appear in the other.

What SDKs are available?

Official SDKs are available for TypeScript/Node.js, Python, and Go. All SDKs include automatic retries, type safety, pagination helpers, and idempotency support.

See Client SDKs for installation instructions.

How can I get the Share Contact Card feature enabled?

Call POST /api/partner/v3/contact_card to configure your contact card — this is a one-time setup per phone number. You can also manage this in the Linq dashboard.

Once configured, send a message to the recipient first, then share the contact card — it will only appear if an outbound message already exists in the chat.

Note:

  • Profile images must be 1:1 aspect ratio, minimum 200×200 px
  • If a number is replaced, you’ll need to set up the contact card again for the new number
How do I use Share Contact Card?

Share the contact card after your first outbound message to a recipient — at most once per day.

See Share Contact Card for details.

If a user shares their contact card with me, can I add them?

.vcf file attachments can be saved, but Apple contact card data cannot currently be read or saved via the API.

How can I share contact info with non-iPhone users?

Send a .vcf file attachment containing the contact’s name, picture, phone number, and any other details.

See Attachments for how to send files.

Does Share Contact Card work with non-iPhone users?

No — Share Contact Card is iMessage only and will not appear for Android or other non-iPhone users.

What does the Share Contact Card POST request do?

It pushes an Apple contact card via iMessage, showing a popup at the top of the recipient’s thread to add the contact.

See Share Contact Card for details.

How can I check what service my recipients are on?

Use POST /api/partner/v3/capability/check_imessage or POST /api/partner/v3/capability/check_rcs to check recipient capabilities before sending. The service used is also reported in message.sent and message.received webhook events.

What support exists for threaded replies?

Use the reply_to parameter with a message_id and an optional part_index to reply to a specific part of a multi-part message.

See Sending Messages for details.

Why am I not receiving message.read events even after a recipient responds?

Read receipts depend on the recipient’s device settings — users can disable read receipts in iMessage. Group chats do not support read receipts or delivery receipts — you’ll only receive message.sent.

Why am I not receiving message.delivered events for some numbers?

Delivery receipts are only available for iMessage and RCS direct messages. Group chats and SMS-only recipients do not emit message.delivered — you’ll receive message.sent only.

How do message reactions (tapbacks) work?

Supported reactions are: love, like, dislike, laugh, emphasize, and question. You can also send custom emoji reactions using type: custom with a custom_emoji field. Since reactions are async, you’ll receive webhook events for both inbound reactions and as confirmation when your own are added or removed.

See Reactions for details.

What's your default data retention policy?

Messages are deleted from the Linq system every 24 hours, and from iCloud every 30 days (Apple’s minimum retention period).

Can I delete messages?

Yes — call DELETE /v3/messages/{messageId} to remove a message from Linq’s records. Note: this does not unsend the message — recipients will still see it.

Can I edit messages?

Yes, you can edit messages using PATCH /v3/messages/{messageId}, which will amend the contents of the message on your and the recipient’s end. A message can be edited up to 5 times within 15 minutes from when it was originally sent. You’ll receive a message.edited webhook as confirmation. Only supported in webhook version v2026-02-03 and later.

How can I prevent duplicate messages?

Use the idempotency_key parameter when sending a message. If you send the same request twice with the same key, the API returns the original message instead of creating a duplicate.

See Idempotency for details.

Do you support sending App Clips?

Yes, simply send the App Clip link on its own and it will display normally for the recipient.

Can I send OTP codes through my Linq line?

Linq numbers are P2P iMessage numbers, and are not explicitly designed to deliver that category of messaging. To ensure consistent delivery of OTP codes, we recommend you utilize a traditional SMS provider to handle that function.

How do I send a voice memo?

Call POST /api/partner/v3/chats/{chatId}/voicememo with the audio file. Supported formats: MP3, M4A, AAC, CAF, WAV, AIFF, AMR. Max size: 10MB. Send it alone — voice memos cannot be combined with other message parts.

See Voice Memos for details.

How can I make URLs unfurl into rich previews?

Set the part type to link and send the link alone with no other parts. The URL must include a scheme (http://, https://, or ftp://).

See Rich Link Previews for details.

What types of files can I send?

You can send images, videos, audio, documents, contacts, and calendar events — either via URL or by pre-uploading via POST /api/partner/v3/chats/{chatId}/messages. Make sure to add cdn.linqapp.com to any domain allowlists.

See supported file types for details.

Can I leave a group chat?

Yes — call POST /api/partner/v3/chats/{chatId}/leave. The group must have at least 3 participants remaining after you leave. Once you leave, you can no longer access the chat unless an active participant adds you back. Recreating a chat with the same set of participants will create a new, separate chat.

See Group Chats for details.

Can I add or remove participants?

Yes — add participants via POST /api/partner/v3/chats/{chatId}/participants. The chat must already have 3+ participants, and the new participant must support the same messaging service. Remove participants via DELETE — at least 3 participants must remain.

You cannot remove yourself from the group chat — use POST /leave instead. See Group Chats for details.

Why does a removed participant still appear in the chat handles?

When a participant is removed, they remain in the chat’s handles list with status: removed and a left_at timestamp, but can no longer send or receive messages in the chat.

Is adding a user to a group chat considered outbound first communication?

Yes — adding a user to a group chat counts as outbound activity regardless of who sends the first message.

What happens to the Chat ID if a participant is added or removed?

The Chat ID always stays the same when participants are added or removed — it is stable for the lifetime of the chat.

Do typing indicators work in group chats?

No — typing indicators are not currently supported in group chats.

Why isn't my typing indicator showing despite a 204 response?

Typing indicators are best-effort — a 204 means the request was accepted, not that it was delivered. The chat must have had activity within the last 5 minutes, and group chats are not supported.

See Typing Indicators for details.

How can I make outbound calls?

There is no native outbound calling support. You can use a voice-capable service with number masking and set your Linq number as the masked caller ID.

How can I receive inbound voice calls?

You cannot pick up calls to your Linq number directly. You can forward inbound calls via PUT /api/partner/v2/phone_number/{id} (V2 API).

Where can I set up webhook subscriptions?

Create and manage webhook subscriptions via POST /api/partner/v3/webhooks, or through the Linq dashboard.

How do I verify webhook signatures?

All webhooks are signed with HMAC-SHA256 using your webhook signing secret. The signature is computed over {timestamp}.{payload} and sent in the X-Webhook-Signature header.

See Signature Verification for step-by-step instructions and SDK examples.

What events can I subscribe to?

Linq delivers events across messages, reactions, chats, participants, and phone numbers. You choose which events to subscribe to when creating a webhook subscription. You can also call GET /api/partner/v3/webhook_events to fetch all available event types programmatically.

See Webhook Event Types for the full list and a representative payload per event.

Can webhooks be configured on a per-number basis?

Yes — when creating a subscription, pass an optional phone_numbers filter to limit delivery to specific numbers. By default, a subscription fires for all numbers in your environment.

See Filtering by phone number for details.

What is your webhook retry policy?

Linq retries failed webhook deliveries up to 10 times over approximately 25 minutes per endpoint. Retries are triggered by HTTP 5xx responses, HTTP 429, connection timeouts over 10 seconds, or connection refused / network errors.

See Delivery Guarantees for details.

How should I handle duplicate webhooks?

Use the event_id field to deduplicate events. The same event may arrive multiple times during retries, so your webhook handler should be idempotent — processing the same event twice should have no side effects. We recommend:

  • Store processed event_id values (e.g., in Redis or your database)
  • Check if an incoming event_id has already been processed
  • Skip processing if it’s a duplicate
Will Linq send multiple webhooks quickly without waiting for a 200 response?

Yes — Linq sends webhook events regardless of whether your server has responded to previous deliveries. Log and process events asynchronously to avoid timeouts.

If I miss webhooks due to an outage, how can I retrieve missing data?

Call GET /api/partner/v3/chats/{chatId} to pull missed data for a specific chat, or contact your Linq representative to request a manual event replay.

What does not trigger a webhook retry?

HTTP 4xx responses (except 429), DNS failures, and invalid hostnames are treated as permanent failures and will not be retried. Check your delivery logs in the Linq dashboard to diagnose issues.

Why am I not receiving webhooks?

Common causes:

  1. Endpoint not reachable — Ensure your URL is publicly accessible over HTTPS
  2. Timeout — Your endpoint must respond with a 2xx status within 10 seconds
  3. Wrong events — Verify you subscribed to the correct event types
  4. Firewall rules — Allow inbound requests from Linq’s IP ranges

See Debugging for webhook troubleshooting tools.

How can team members access the dashboard?

You can either have your account set up with a shared team email, or invite users from the Users section of the dashboard.

What's the best way to separate lines for testing, staging, and production?

Although you can control which lines are used for what purposes on your end, to prevent accidental deployment of test features into production, we recommend segmenting lines into separate environments entirely.

To have this done, please reach out to your Linq representative and request your desired setup. We will separate your numbers for you. Each environment will have its own dashboard and API key, which you can access via the admin login(s) we provide for each environment.

What are the rate limits?

The API enforces a per-phone-pair limit of 30 messages in any 60-second window between the same sender and recipient, plus a 100 messages/day cap on sandbox accounts. There is no hard daily cap on production accounts — we recommend staying under 7,000 inbound + outbound messages per line per day for best performance. Exceeding a limit returns HTTP 429 with error code 1007 and a Retry-After header.

See Rate Limits for details.

What is Linq doing to help prevent flagging?

As responsible stewards of the iMessage ecosystem, we’re committed to providing you with the necessary tools and alerts to not only ensure your lines stay operational, but to help you deliver your end users the best possible experience.

In the near future, we’ll be rolling out new reporting within the API that’ll aim to give you insights into what may be potentially risky behavior, which you can act on to optimize your service availability.

What counts as a reply from a message reciprocity standpoint?

Both messages back and tapback reactions count as responses and boost your reciprocity score.

How much engagement should I aim for to keep lines in good standing?

You should aim to elicit 3+ responses from a new user as soon as possible in order to keep conversations healthy. You should also aim for a message reciprocity ratio of 1:2 (inbound:outbound) for optimal results.

How can I reduce the incidence of flagging?

The following are best practices to reduce flagging risk:

Inbound flow: Have users message your number first. This removes their ability to mark your message as spam, since they initiated the conversation.

Load balance: Have users onboard evenly across multiple lines and over-provision by 10–20% to account for peak times and virality. We recommend onboarding users via deeplink from your webpage so you can rotate numbers with each signup.

Ramp up usage gradually: Onboard users evenly and gradually to avoid large volume spikes.

Ensure your AI isn’t aggressive: AI that aggressively follows up (especially unsolicitedly) can cause users to block your number and signal to Apple that recipients are receiving spam.

Have clear opt-out detection: Honor opt-out language from your users (e.g. stop, unsubscribe, or negative sentiment generally).

Subscribe to compliance events to detect and act on compliance signals programmatically.

Use multiple lines: We recommend sharding across multiple numbers so that if one were to become unavailable, your service will still remain operational. You can also put multiple fallback Linq Blue numbers on .vcf files you share with users at onboarding to ensure they can continue to receive communications in their existing threads should the primary number become flagged.

If my line is flagged, will I still receive inbound messages?

It is possible that you might receive inbound messages for a short while, but it’s expected that all activity to and from the line will fail at some point. The expected behavior is that iMessages will fail first, followed by RCS/SMS.

If my line gets flagged, how long will it be down?

Flagged lines typically see downtime of around 24 hours, but may be longer depending on severity. You will be able to check the recovery status in the API toolkit section of the dashboard, and will receive a phone_number.status_updated webhook event notifying you when the number is active again if you’ve subscribed to it.

What typically causes individual lines to become disabled?

“Flagged” is one of the most common reasons why your line may become non-operational. Flagging is when Apple disables a phone line due to a high amount of spam reports from recipients or low message reciprocity. Apple may also flag your number due to sudden volume spikes (which are interpreted as automated, spammy behavior).

You can monitor the status of your lines in the API toolkit in the dashboard. We also encourage you to subscribe to the phone_number.status_updated webhook to detect flagged lines programmatically. You can also enable Slack notifications to be alerted in your linked partner channel whenever a line’s status changes — see below.

How do I know when a phone number's status changes?

Subscribe to the phone_number.status_updated webhook event to receive a real-time payload whenever a number transitions between ACTIVE and FLAGGED. You can also enable Flagged-number Slack notifications in the API Tooling settings to get a message in your linked partner channel whenever a number’s status changes.

See Phone Numbers for details.

One of my lines is disabled — how do I migrate users?

If users need to be migrated to a new line, we recommend setting up a dedicated broadcast number to announce issues/outages, and to direct users to working lines.

The best tool for this would be an A2P registered SMS line reserved for this purpose. Email and push notifications (if you have an app) are also recommended.

It’s preferred that migrations to different numbers take place by prompting users to inbound to the new number rather than outbounding to users from that new number, unless you know for certain that the user is actively engaging with your service.

How can I mitigate line-specific downtime risk?

We highly recommend using backup numbers to ensure service is available should any one of your lines become inoperable. To implement this, add one or more backup numbers to a .vcf file along with your primary number and share it with users upon onboarding (ideally via web download at signup) for them to add to their contact list. If your service were to fall back to any of the backup numbers, users would still see messages come through in their existing thread, preserving continuity.

What should I expect for systemic downtime?

Scheduled maintenance will be communicated to you in advance. In the event of a platform outage, you can monitor live as well as subscribe to updates via our status page.

How do volume limits translate to concurrent users?

The approach to determining the number of concurrent users each of your lines can support is nuanced, given factors including how your AI agent behaves (does it send many or few messages) and how your users behave (do they converse with your AI, or simply make requests of it). We recommend utilizing a pilot line, onboarding users onto that line, and calculating the average number of inbound/outbound messages per user. You can then use the resulting amount to determine how many users can onboard onto your line before you hit the 7,000 messages/line/day guideline.

How many messages can I send per line?

We recommend limiting message volume to a combined total of up to 7,000 inbound and outbound messages per day per line. There are no hard daily caps on production accounts — this recommendation is meant to optimize line performance.

See Rate Limits for details.

What is the Linq MCP server?

The Linq MCP server is an auto-generated Model Context Protocol server that lets AI tools like Claude Desktop, Cursor, Windsurf, and Claude Code interact with the Linq API directly. It’s built by Stainless from our OpenAPI specification.

How do I install the MCP server?

npx (no install required):

Terminal window
npx -y linq-api-mcp@latest

Claude Code:

Terminal window
claude mcp add linq-api-mcp -- npx -y linq-api-mcp@latest

Claude Desktop / Cursor / Windsurf (mcpServers.json):

{
"mcpServers": {
"linq-api": {
"command": "npx",
"args": ["-y", "linq-api-mcp@latest"],
"env": {
"LINQ_API_V3_API_KEY": "your-api-key"
}
}
}
}
What can the MCP server do?

The MCP server exposes two tools to LLMs:

  1. Code execution — Run TypeScript code against the Linq SDK in a sandboxed environment
  2. Documentation search — Query Linq API documentation in Markdown format, optimized for LLM consumption

This means an AI assistant can search the docs, construct API calls, and execute them — all within a single conversation.

What are LLM-friendly docs?

Stainless automatically generates machine-readable versions of the Linq API documentation, optimized for use by large language models. These follow the llms.txt standard and provide structured Markdown that LLMs can consume directly.

How do I access the LLM-friendly docs?

The following endpoints are available on the docs site:

EndpointDescription
/llms.txtIndex of available documentation pages in a concise format
/llms-full.txtComplete API documentation in a single file, optimized for LLM context windows

These files are automatically kept in sync with the latest API documentation.

When should I use LLM-friendly docs vs. the MCP server?
  • Use llms.txt / llms-full.txt when you want to feed Linq API docs into a custom LLM pipeline, RAG system, or prompt context
  • Use the MCP server when you want an AI assistant (Claude, Cursor, etc.) to interactively search docs and execute API calls on your behalf
Can I use these with my own AI agents?

Yes. The llms-full.txt file is ideal for embedding Linq API knowledge into your own AI agents. Fetch it at build time or runtime and include it in your system prompt or retrieval pipeline. Combined with the Linq API itself, this lets you build AI agents that understand and use the Linq API without manual documentation parsing.