Your AI Connector Docs

Entry Points API

An Entry Point is a routing rule: “when this happens on this channel, hand the conversation to this Agent”. Connecting a channel gets messages into the account and creating an Agent gives you something that can reply, but neither decides who answers a stranger’s first message. Entry Points do. For the product itself, see the Entry Points guide.

All examples below show the ?apiKey= query form in cURL and the X-API-Key header in JavaScript and Python — either works on every endpoint.

In the API explorer. Every endpoint on this page is in the published OpenAPI specification, so you can browse its exact fields and run live requests in the API explorer.


The one call most integrations need

Connect a channel, create an Agent, then point the channel at the Agent:

curl -X PUT "https://api.youraiconnector.com/v1/entry-points/channel-defaults?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "channel": "whatsapp", "agent_id": "ag7HkQ2ZpLxR3mNb" }'

That is the whole setup for “this Agent answers WhatsApp”. Everything else on this page is for narrower rules (keywords, comments, new followers), several numbers on one channel, and reading back what is configured.


How routing is decided

When a message arrives, the platform walks a fixed ladder and the first step that decides wins:

  1. A human has taken over the conversation — no AI.
  2. The contact is already assigned to an Agent, manually or because a conversation with that Agent is under way — the same Agent keeps it. Entry Points never move an existing conversation; to hand a chat to a different Agent, assign it (in the app, or with the Automations action).
  3. The contact is replying to a broadcast — the broadcast’s Agent answers, or nobody if the broadcast had none.
  4. A narrow Entry Point matches. Keyword rules beat comment rules, which beat follower rules. Between two rules of the same kind, the most recently updated one wins.
  5. The channel default for the channel the message arrived on. A default scoped to the specific number the contact wrote to beats the channel-wide default.
  6. Nothing matched — the message lands in the inbox for your team and no assistant replies.

Two things soften step 6. An account with exactly one active Agent and no default configured for the channel still gets that Agent as the answerer, so a fresh account that connects WhatsApp and sends a test message does not get silence. That floor never applies to a channel that has a keyword rule (there, a message that matches no keyword is deliberately left for a human) and never overrides a channel you set to nobody (see Leave a channel with nobody answering).

Whether the ladder is live for an account is reported by GET /entry-points/routing-status. It is on for every account today; the call exists so an integration can check rather than assume.


The Entry Point object

{
  "id": "ep3KmQ8vTzXr5nWd",
  "type": "keyword",
  "channels": ["whatsapp", "instagram"],
  "agent_id": "ag7HkQ2ZpLxR3mNb",
  "enabled": true,
  "match_config": {
    "keywords": ["pricing", "quote"]
  },
  "first_response_mode": null,
  "first_response_exact_text": null,
  "public_comment_reply_exact_text": null,
  "created_at": 1700000000000,
  "last_modified_at": 1700000000000
}
Field Description
id The rule’s ID.
type One of channel_default, keyword, instagram_comment, facebook_comment, instagram_follower. See Rule types.
channels The channels the rule covers: whatsapp, whatsapp_web, instagram, instagram_private, messenger, telegram, sms, email, chat_widget, custom_channel, line, viber, tiktok, imessage, linkedin, skool. Comment rules use instagram or facebook.
agent_id The Agent the rule routes to. Empty on a channel default that is deliberately set to nobody.
enabled false for a rule that has been retired. Retired rules are history, not live settings, and both come back from the list endpoints.
match_config Type-specific settings — see Rule types. Empty for a plain channel default.
first_response_mode ai (default) lets the Agent write the first reply; exact_text sends first_response_exact_text verbatim. Honoured on comment rules today; accepted and stored on keyword rules but not yet used there.
first_response_exact_text The fixed first DM when first_response_mode is exact_text. {{first_name}} is replaced with the person’s first name, or “there” when it is unknown.
public_comment_reply_exact_text Comment rules only: the fixed public reply under the comment. Blank skips the public reply; the DM still goes out.
created_at, last_modified_at Epoch milliseconds.

Rule types

type Fires when match_config
channel_default A new, unknown contact writes in on one of the channels. phone_numbers (optional) — scope the default to one connected number instead of the whole channel. See One Agent per WhatsApp number.
keyword A new contact’s first message is one of the keywords. Matching ignores case and spaces, and a near miss (“info pls” against INFO) is still resolved by AI unless you set fuzzy_match: false — do that for promo codes and SKUs where a near miss must not count. Not applied on sms or imessage. keywords (at least one, required), fuzzy_match (default true).
instagram_comment / facebook_comment Someone comments on one of your posts. channels must include instagram or facebook respectively. keywords (empty means every comment on the watched posts counts), post_ids (empty means all posts), delay_minutes (wait before the DM goes out), reply_instructions (how the Agent should word its reply).
instagram_follower Someone new follows your Instagram account. Needs the Instagram (Personal) connection — the official Instagram DMs connection cannot see followers. reply_instructions (optional).

A keyword rule on a channel with no channel default also works as a gate: messages that match none of the keywords get no automatic reply and simply land in your inbox, even on an account with a single Agent.


Point a channel at an Agent

PUT /entry-points/channel-defaults — makes one Agent the answerer for new contacts on a channel. Any other Agent currently set as that channel’s default is retired in the same call, so a channel always has exactly one answerer. Setting the Agent that already is the default changes nothing.

Field Required Description
channel Yes The channel, for example whatsapp, whatsapp_web, instagram, messenger, telegram, sms, email, chat_widget or custom_channel.
agent_id Yes The Agent that should answer. Must belong to your account.
phone_number No Scope the default to one of your connected numbers on this channel (E.164 with the leading +, exactly as it shows under connected numbers). Leaves the channel-wide default untouched. See One Agent per WhatsApp number.

cURL

curl -X PUT "https://api.youraiconnector.com/v1/entry-points/channel-defaults?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "channel": "instagram", "agent_id": "ag7HkQ2ZpLxR3mNb" }'

JavaScript

const res = await fetch("https://api.youraiconnector.com/v1/entry-points/channel-defaults", {
  method: "PUT",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ channel: "instagram", agent_id: "ag7HkQ2ZpLxR3mNb" }),
});
const data = await res.json();

Python

import requests

res = requests.put(
    "https://api.youraiconnector.com/v1/entry-points/channel-defaults",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"channel": "instagram", "agent_id": "ag7HkQ2ZpLxR3mNb"},
)
data = res.json()

Response

{
  "success": true,
  "entry_point_id": "ep3KmQ8vTzXr5nWd",
  "disabled_entry_point_ids": ["epPrevious1234"]
}

entry_point_id is the rule now in force; disabled_entry_point_ids lists any rules retired to make room for it (empty when there was nothing to replace). Only contacts you have never spoken to are affected — anyone already in a conversation with an Agent keeps that Agent.

A 400 means channel or agent_id is missing, the Agent belongs to another account, or phone_number is not one of your connected numbers.


See who answers each channel

GET /entry-points/channel-defaults — every channel default on the account, newest first, including retired ones (enabled: false) and a channel deliberately set to nobody (agent_id: ""). Filter on enabled yourself for the current picture.

cURL

curl "https://api.youraiconnector.com/v1/entry-points/channel-defaults?apiKey=YOUR_API_KEY"

JavaScript

const res = await fetch("https://api.youraiconnector.com/v1/entry-points/channel-defaults", {
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();

Python

import requests

res = requests.get(
    "https://api.youraiconnector.com/v1/entry-points/channel-defaults",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()

Response

{
  "success": true,
  "entry_points": [
    {
      "id": "ep3KmQ8vTzXr5nWd",
      "type": "channel_default",
      "channels": ["whatsapp"],
      "agent_id": "ag7HkQ2ZpLxR3mNb",
      "enabled": true,
      "match_config": {},
      "created_at": 1700000000000,
      "last_modified_at": 1700000000000
    },
    {
      "id": "epAEnhHoozpoGVze",
      "type": "channel_default",
      "channels": ["whatsapp"],
      "agent_id": "agRotterdamBranch",
      "enabled": true,
      "match_config": { "phone_numbers": ["+31685101091"] },
      "created_at": 1700000000000,
      "last_modified_at": 1700000000000
    }
  ]
}

This is the account-wide read. Listing one Agent’s rules with GET /agents/{agentId}/entry-points cannot show a channel set to nobody, because that rule belongs to no Agent.


Leave a channel with nobody answering

DELETE /entry-points/channel-defaults?channel=instagram — retires the channel-wide default for one channel. The channel is named as a query parameter, not in a body. Add &phone_number=%2B31685101091 to clear only that number’s default and let the number go back to whoever answers the channel.

cURL

curl -X DELETE "https://api.youraiconnector.com/v1/entry-points/channel-defaults?channel=instagram&apiKey=YOUR_API_KEY"

JavaScript

const res = await fetch(
  "https://api.youraiconnector.com/v1/entry-points/channel-defaults?channel=instagram",
  { method: "DELETE", headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const data = await res.json();

Python

import requests

res = requests.delete(
    "https://api.youraiconnector.com/v1/entry-points/channel-defaults",
    params={"channel": "instagram"},
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()

Response

{ "success": true, "disabled_entry_point_ids": ["ep3KmQ8vTzXr5nWd"] }

Safe to repeat: clearing a channel that has no default is a 200 with an empty list. Clearing means unset, not silence — on an account with exactly one active Agent, an unconfigured channel still falls back to that Agent. To keep the AI off a channel entirely, pick No one’s answering for it in the app’s Who Answers New Conversations panel (that writes an explicit “nobody” default which the fallback never overrides), or pause the Agent with PATCH /agents/{agentId}/active.


One Agent per WhatsApp number

Routing is per channel by default: all your WhatsApp numbers share one answerer. With two or more numbers connected on WhatsApp Business or WhatsApp Web, a default can be scoped to a single number, so a business with a number per branch or brand can give each its own Agent inside one account.

Send phone_number with the set call:

curl -X PUT "https://api.youraiconnector.com/v1/entry-points/channel-defaults?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "channel": "whatsapp_web",
    "agent_id": "agRotterdamBranch",
    "phone_number": "+31685101091"
  }'
  • The number must be one of your connected numbers on that channel, written as it shows under connected numbers (E.164 with the +); anything else is a 400.
  • The rule is stored as a channel default with match_config.phone_numbers: ["+31685101091"]. A message that arrives on that number goes to its Agent; every other number keeps following the channel-wide default.
  • Setting or clearing the channel-wide default leaves number-scoped rules alone, and vice versa. Clear a number’s own rule with DELETE /entry-points/channel-defaults?channel=whatsapp_web&phone_number=%2B31685101091.
  • Replies always go out from the number the contact wrote to, so the contact keeps talking to the same number and the same Agent.

Add a narrower rule

POST /agents/{agentId}/entry-points — creates a keyword, comment or follower rule (or a channel default, though PUT /entry-points/channel-defaults is the better call for that because it retires the previous answerer for you). The Agent in the path always wins: a rule can never be created for a different Agent than the one in the URL.

Field Required Description
type Yes keyword, instagram_comment, facebook_comment, instagram_follower or channel_default.
channels Yes A non-empty list of the channels the rule covers. A comment rule must list its own channel (instagram or facebook).
match_config Depends on type See Rule types. A keyword rule needs at least one entry in keywords.
enabled No Defaults to true.
first_response_mode, first_response_exact_text, public_comment_reply_exact_text No The first-response settings described in The Entry Point object.

cURL

curl -X POST "https://api.youraiconnector.com/v1/agents/ag7HkQ2ZpLxR3mNb/entry-points?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "keyword",
    "channels": ["whatsapp", "instagram"],
    "match_config": { "keywords": ["pricing", "quote"] }
  }'

JavaScript

const res = await fetch(
  "https://api.youraiconnector.com/v1/agents/ag7HkQ2ZpLxR3mNb/entry-points",
  {
    method: "POST",
    headers: {
      "X-API-Key": "YOUR_API_KEY",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      type: "keyword",
      channels: ["whatsapp", "instagram"],
      match_config: { keywords: ["pricing", "quote"] },
    }),
  }
);
const data = await res.json();

Python

import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/agents/ag7HkQ2ZpLxR3mNb/entry-points",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "type": "keyword",
        "channels": ["whatsapp", "instagram"],
        "match_config": {"keywords": ["pricing", "quote"]},
    },
)
data = res.json()

Response (201)

{ "success": true, "entry_point_id": "ep3KmQ8vTzXr5nWd" }

A comment-to-DM rule that only reacts to comments saying “LINK” on two specific posts, waits two minutes, and sends a fixed first message:

{
  "type": "instagram_comment",
  "channels": ["instagram"],
  "match_config": {
    "keywords": ["LINK"],
    "post_ids": ["17895695668004550", "17841400008460056"],
    "delay_minutes": 2
  },
  "first_response_mode": "exact_text",
  "first_response_exact_text": "Hi {{first_name}}, here is the link you asked for: https://example.com/guide",
  "public_comment_reply_exact_text": "Sent you a DM!"
}

Leave keywords empty to DM everyone who comments on the watched posts, and post_ids empty to watch every post. A 400 names what is wrong: an unknown type, an empty channels, a keyword rule without keywords, or a comment rule that does not list its own channel.


List an Agent’s rules

GET /agents/{agentId}/entry-points — the rules that send conversations to this Agent, newest first: its channel defaults, keyword rules, comment rules and follower rules. Retired rules come back too, with enabled: false.

cURL

curl "https://api.youraiconnector.com/v1/agents/ag7HkQ2ZpLxR3mNb/entry-points?apiKey=YOUR_API_KEY"

JavaScript

const res = await fetch(
  "https://api.youraiconnector.com/v1/agents/ag7HkQ2ZpLxR3mNb/entry-points",
  { headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const data = await res.json();

Python

import requests

res = requests.get(
    "https://api.youraiconnector.com/v1/agents/ag7HkQ2ZpLxR3mNb/entry-points",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()

Response

{
  "success": true,
  "entry_points": [
    {
      "id": "ep3KmQ8vTzXr5nWd",
      "type": "keyword",
      "channels": ["whatsapp", "instagram"],
      "agent_id": "ag7HkQ2ZpLxR3mNb",
      "enabled": true,
      "match_config": { "keywords": ["pricing", "quote"] },
      "created_at": 1700000000000,
      "last_modified_at": 1700000000000
    }
  ]
}

Change a rule

PUT /entry-points/{entryPointId} — changes one rule. Send only the fields you are changing; nested settings can be addressed leaf by leaf with a dotted key such as "match_config.keywords". Whenever the change touches type, channels or match_config, the whole rule is re-checked, so a partial edit can never leave an unusable rule behind (switching type to keyword without supplying keywords is rejected). Sending agent_id hands the rule to another of your Agents; a blank one is rejected. Ownership and identity fields are ignored.

cURL

curl -X PUT "https://api.youraiconnector.com/v1/entry-points/ep3KmQ8vTzXr5nWd?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "match_config": { "keywords": ["pricing", "quote", "demo"] } }'

JavaScript

const res = await fetch("https://api.youraiconnector.com/v1/entry-points/ep3KmQ8vTzXr5nWd", {
  method: "PUT",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ match_config: { keywords: ["pricing", "quote", "demo"] } }),
});
const data = await res.json();

Python

import requests

res = requests.put(
    "https://api.youraiconnector.com/v1/entry-points/ep3KmQ8vTzXr5nWd",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"match_config": {"keywords": ["pricing", "quote", "demo"]}},
)
data = res.json()

Response

{ "success": true, "entry_point_id": "ep3KmQ8vTzXr5nWd" }

Other common edits: { "enabled": false } retires a rule without deleting it, and { "agent_id": "agOtherAgent" } moves it to a different Agent. An empty body returns 400 with "No fields to update".


Delete a rule

DELETE /entry-points/{entryPointId} — removes the rule permanently. Nothing else refers to an Entry Point, so there is nothing to detach first.

cURL

curl -X DELETE "https://api.youraiconnector.com/v1/entry-points/ep3KmQ8vTzXr5nWd?apiKey=YOUR_API_KEY"

JavaScript

const res = await fetch("https://api.youraiconnector.com/v1/entry-points/ep3KmQ8vTzXr5nWd", {
  method: "DELETE",
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();

Python

import requests

res = requests.delete(
    "https://api.youraiconnector.com/v1/entry-points/ep3KmQ8vTzXr5nWd",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()

Response

{ "success": true, "entry_point_id": "ep3KmQ8vTzXr5nWd" }

To stop a rule from firing but keep it around, set enabled to false instead. Channel defaults in particular are normally retired rather than deleted, which is what DELETE /entry-points/channel-defaults does.


Check that routing is live

GET /entry-points/routing-status — returns whether the Entry Points ladder decides who answers on this account. Readable with view access, so a teammate sees the same answer the owner does.

curl "https://api.youraiconnector.com/v1/entry-points/routing-status?apiKey=YOUR_API_KEY"
{ "success": true, "cutover_enabled": true }

It is true on every account today. The call is kept so an integration can verify before telling someone their routing change is live rather than assume it.


The older, campaign-shaped calls

Two endpoints from before Agents still work for accounts organised around campaigns. New integrations should use the channel-defaults calls above instead.

  • PUT /channel-routing/{channel} with { "campaignId": "cp5NbV8xQrT2wYzA" } — names a campaign, and that campaign’s Agent becomes the channel’s answerer. { "campaignId": null } clears the channel. An outgoing-only campaign is rejected because it has no inbound behaviour to offer.
  • POST /channel-routing/clear with { "channels": ["whatsapp", "instagram"] } — frees several channels from whichever Agent answers them in one call, typically before pointing them somewhere else. The response lists released_channels, the ones that actually had an answerer.

Both unset rather than silence: on an account with exactly one active Agent, a freed channel still falls back to that Agent.


Entry Points API errors

Entry Point endpoints return the standard error envelope:

{
  "success": false,
  "error": "Entry point not found"
}
Status When it happens on an Entry Point endpoint
400 A field is missing or the rule would be unusable: no channel or agent_id on a set call, an unknown type, an empty channels, a keyword rule without keywords, a comment rule that does not list its own channel, a blank agent_id on an update, an empty update body, or a phone_number that is not one of your connected numbers.
403 The key or team member may not edit routing. Writes need edit rights on campaigns; the list and status reads need view rights.
404 The Entry Point or Agent was not found — either it does not exist or it belongs to another account.

The shared codes every endpoint can return — 401, 403 (your plan does not include API access), 429 (rate limit) and 500 — are listed with retry guidance in Errors & Pagination.


Next steps