One sequence, multiple channels: email, LinkedIn steps, and calls together.
Reply.io builds a single sequence that mixes email with LinkedIn steps and call tasks rather than treating each channel as a separate campaign. Your agent resolves or creates the sequence, links a sending mailbox, enrolls the contacts, then stops and waits for your approval before it starts sending.
Reply.io is activation for a multichannel cadence. Sourcing and enrichment fill the contact list before it goes near a sequence.
validate the list before it goes into a live sequence
personalisation across the email and LinkedIn steps
LinkedIn URLs feed the LinkedIn steps in the same sequence
replies land on the record automatically
Ask for the outcome and your agent composes the run itself. Or start from a skill, a whole pipeline it already knows end to end.
browse all skills →Every tool ships with a written playbook, and the agent loads it before the first call. Auth, rate limits, what each call costs, which actions need your approval, and the mistakes worth avoiding. It is the difference between an agent that knows the tool and one that guesses at it.
Read the Reply.io docs →HOW in lib/reply_io.py. Docs cached at reference/docs/reply_io/raw/endpoints.md.
https://api.reply.io (every path sits under /v3) · Auth: Authorization: Bearer <key> (env REPLY_IO_API_KEY; never hardcode). Get the key from the Reply dashboard: Settings → API Key.start_sequence(id) begins real outbound sending. add_contacts_to_sequence into a running sequence puts mail in flight. Approval-gate both: build the sequence and enroll into a paused state, pilot, confirm, then start.Contacts: list_contacts, get_contact, create_contact, update_contact, search_contacts. Contact lists: list_contact_lists, add_contacts_to_list. Sequences: list_sequences, get_sequence, create_sequence, start_sequence, pause_sequence, get_sequence_stats, list_sequence_steps. Sequence contacts: list_sequence_contacts, add_contacts_to_sequence, remove_contacts_from_sequence, set_contacts_status_in_sequence, set_contacts_replied. Email accounts: list_email_accounts, list_sequence_email_accounts, link_email_account_to_sequence. Identity: whoami. Else → generic request().
Activation layer: resolve/create a sequence → link mailboxes → create or import validated contacts → add_contacts_to_sequence → review → start_sequence. Replies feed back through get_sequence_stats and set_contacts_replied.
Field-shape note: these are vendor-native operational notes. The client returns the raw vendor JSON and uses the method names in this file — read field shapes accordingly (no normalized-wrapper /
result.data.prefix).
Activation order: resolve/create sequence -> link sending mailboxes -> create or import contacts -> enroll via add_contacts_to_sequence -> start_sequence -> monitor via get_sequence_stats. Always resolve the sequence ID before any write.
Gotchas (vendor-native):
domain:verb (e.g. contacts:read, sequences:operate). A key missing sequences:operate can read sequences but cannot enroll or start anyone — the #1 confusing 403.add_contacts_to_sequence/remove_contacts_from_sequence accept up to 10,000 contact ids; set_contacts_status_in_sequence/set_contacts_replied accept up to 100. Over the cap the adapter raises rather than trimming.top (page size, default 25, max 1000) + skip. top > 1000 is rejected, not clamped — a clamp would make a paging loop silently skip records.update_contact is PATCH: omitted fields keep their current value, unlike a PUT.get_sequence_stats takes either a dateRangePreset (lastWeek/lastMonth/lastYear/allTime) or an explicit from/to, never both.create_sequence requires a name AND at least one step — a name-only create is rejected.set_contacts_replied marks a contact replied and that finishes them in the sequence.problem+json (title, status, detail, code, errors[]); a 401 has an empty body — check WWW-Authenticate instead.Retry-After.