A2A agent
Reach SendSets from another agent over the Agent2Agent (A2A) protocol v1.0.
SendSets publishes an A2A v1.0 agent. Another agent discovers it from the Agent Card, then calls the same service-layer tools the MCP server exposes, with the same credentials and the same send policy.
| URL | |
|---|---|
| Agent Card | https://api.sendsetsapi.com/.well-known/agent-card.json |
| Endpoint | https://api.sendsetsapi.com/v1/a2a (JSON-RPC 2.0, protocolVersion 1.0) |
A self-hosted instance serves both on its own API host (API_PUBLIC_URL), so
its card always points at its own endpoint.
Authentication
Send a SendSets API key (ssk_...) or an OAuth 2.1 access token as
Authorization: Bearer <credential>. The card declares this as its bearer
security scheme and never carries a credential. A missing or invalid credential
gets 401 with WWW-Authenticate: Bearer. The credential's
API permissions decide which tools it may call, tool by
tool, exactly as over MCP.
Sending a message
Each SendMessage runs one tool. Put the call in a data part:
curl https://api.sendsetsapi.com/v1/a2a \
-H "Authorization: Bearer $SENDSETS_API_KEY" \
-H "Content-Type: application/json" \
-H "A2A-Version: 1.0" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "SendMessage",
"params": {
"message": {
"messageId": "5f1c2b1e-0000-4000-8000-000000000001",
"role": "ROLE_USER",
"parts": [{ "data": { "tool": "list_campaigns", "arguments": {} } }]
}
}
}'The call runs synchronously and returns a completed task whose artifact holds the tool's result:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"task": {
"id": "…",
"contextId": "…",
"status": { "state": "TASK_STATE_COMPLETED", "timestamp": "2026-09-27T12:00:00.000Z" },
"artifacts": [{
"artifactId": "…",
"name": "list_campaigns",
"parts": [{ "data": { "campaigns": [] }, "mediaType": "application/json" }]
}],
"history": [ … ]
}
}
}A text part holding the same JSON object, or a bare tool name such as
list_campaigns, works too. Any other text gets back a message (not a task)
listing the tools this credential may call, with each tool's description and
input schema. The agent does not interpret prose: it runs exactly the tool you
name.
A tool that fails returns a task in TASK_STATE_FAILED with the reason in
status.message. Set configuration.acceptedOutputModes to ["text/plain"] to
receive the result as text instead of a data part.
Skills
The card groups the tools into seven skills. A tool outside this list is refused
with -32602, even when the credential could call it over MCP.
| Skill | Tools |
|---|---|
create-outbound-campaign | create_campaign_draft, add_campaign_step, update_campaign_step, list_campaign_steps, set_campaign_senders |
manage-outbound-campaign | list_campaigns, get_campaign, update_campaign, start_campaign, stop_campaign, delete_campaign, delete_campaign_step, list_campaign_senders, set_lead_hold, list_ab_variants, create_ab_variant, update_ab_variant, delete_ab_variant |
add-prospects | add_contact, search_contacts, lead_database_search, lead_database_companies, audience_coverage, get_contact, update_contact_fields, bulk_edit_contacts, add_tag, remove_tag, list_segment_fields, preview_segment, create_segment, update_segment, set_segment_members, list_segments, get_segment, set_campaign_segments, add_segment_to_campaign, list_campaign_segments, list_categories, create_category, update_category, delete_category, log_meeting, delete_meeting, sql_bulk_contacts |
manage-sending-accounts | list_mailboxes, get_mailbox, update_mailbox, set_mailbox_warmup, set_mailbox_tracking_domain, get_warmup_ban_status, disconnect_mailbox |
send-email | compose_email, send_reply, draft_reply, list_scheduled_sends, cancel_scheduled_send |
get-campaign-results | get_campaign_stats, get_campaign_logs, list_campaign_leads, get_dashboard_analytics, outbound_metrics, outbound_breakdown, mailbox_scorecard, list_threads, get_thread, get_contact_sent_emails |
query-workspace-data | sql_schema, sql_examples, sql_estimate, sql_query |
measure-acquisition | events_schema, event_test, goals_list, goal_create, goal_preview, prospects_search, prospect_timeline, acquisition_summary, acquisition_breakdown, attribution_summary, attribution_breakdown, attribution_explain, event_trends, event_funnel, record_event, goal_update, goal_archive, delete_person, correct_attribution, restore_attribution, set_campaign_spend, delete_campaign_spend |
Connecting a new mailbox needs its credentials and is not an A2A skill; do it in the dashboard or with the CLI.
Sends and approvals
start_campaign, compose_email and send_reply go through the credential's
send policy. The task still completes, and its artifact
carries result: executed, awaiting_approval or blocked. For the last
two, status.message says so in text, including the approval link, so a client
never reads a completed task as mail that went out.
What is not supported
Tasks finish inside SendMessage and are not retained. The endpoint answers:
| Method | Response |
|---|---|
GetTask, CancelTask, or a message with taskId | -32001 task not found |
ListTasks | an empty list |
SendStreamingMessage, SubscribeToTask | -32004 unsupported operation |
| Push notification config methods | -32003 push notifications not supported |
GetExtendedAgentCard | -32007 no extended card |
The card declares streaming, pushNotifications and extendedAgentCard as
false. Only A2A 1.0 is served: an A2A-Version other than 1.x, or a 0.3
method name such as message/send, gets -32009. A request without the header
is served as 1.0. A credential that lacks a tool's permission gets -32000 with
reason PERMISSION_DENIED.
SendMessage accepts Idempotency-Key, which replays the first response for a
retried request.
