{"openapi":"3.1.0","info":{"title":"EmailOctopus (BYOK) API","version":"0.1.0","description":"EmailOctopus (BYOK) lets an AI assistant read your own EmailOctopus data through the EmailOctopus API with a key you supply (API key). Read-only: 10 tools (list_lists, get_list, list_list_tags, list_contacts, get_contact, list_campaigns, get_campaign, get_campaign_summary_report, get_campaign_link_report, list_campaign_contact_reports). The BYOK key travels with each request, is used for that one...\n\nEvery operation is read-only or compute-only. The same tools are available over MCP (streamable HTTP) at https://byok-emailoctopus.connectorbay.com/mcp.","contact":{"name":"Unify Dynamics LLC","email":"agent@connectorbay.com","url":"https://connectorbay.com/byok-emailoctopus/docs"},"termsOfService":"https://connectorbay.com/byok-emailoctopus/terms"},"servers":[{"url":"https://byok-emailoctopus.connectorbay.com"}],"externalDocs":{"url":"https://connectorbay.com/byok-emailoctopus/docs"},"security":[{"upstreamKey":[]}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","description":"Optional. A Pro API key raises rate limits; no credentials are required."},"upstreamKey":{"type":"apiKey","in":"header","name":"X-Upstream-Key","description":"Your own key for the service this connector wraps (bring your own key). Used for that one call only; never stored, logged or cached."}},"schemas":{"Error":{"type":"object","properties":{"ok":{"const":false},"error":{"type":"object"}}}}},"paths":{"/v1/tools/list_lists":{"post":{"operationId":"list_lists","summary":"List your mailing lists with name, double opt-in setting, tags, subscriber counts (pending, subscribed, unsubscribed) an","description":"List your mailing lists with name, double opt-in setting, tags, subscriber counts (pending, subscribed, unsubscribed) and dates. Use for \"How many subscribers are on my EmailOctopus lists\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"limit":{"anyOf":[{"maximum":100,"minimum":1,"type":"integer"},{"type":"null"}],"default":100,"description":"How many results per page (1 to 100, default 100).","title":"Limit"},"starting_after":{"anyOf":[{"maxLength":300,"type":"string"},{"type":"null"}],"default":null,"description":"Paging cursor: the paging.next.starting_after value of the previous answer (leave empty for the first page).","title":"Starting After"}},"title":"list_listsArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/get_list":{"post":{"operationId":"get_list","summary":"Get one list with its name, double opt-in setting, custom fields, tags and subscriber counts. Use for \"Show my EmailOcto","description":"Get one list with its name, double opt-in setting, custom fields, tags and subscriber counts. Use for \"Show my EmailOctopus list 00000000-0000-0000-0000-000000000000\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"list_id":{"description":"EmailOctopus list ID (a UUID, from list_lists), for example '00000000-0000-0000-0000-000000000000'.","maxLength":60,"title":"List Id","type":"string"}},"required":["list_id"],"title":"get_listArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/list_list_tags":{"post":{"operationId":"list_list_tags","summary":"List the tags used on a list's contacts. Use for \"Which tags do contacts on my EmailOctopus list have\".","description":"List the tags used on a list's contacts. Use for \"Which tags do contacts on my EmailOctopus list have\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"list_id":{"description":"EmailOctopus list ID (a UUID, from list_lists), for example '00000000-0000-0000-0000-000000000000'.","maxLength":60,"title":"List Id","type":"string"},"limit":{"anyOf":[{"maximum":100,"minimum":1,"type":"integer"},{"type":"null"}],"default":100,"description":"How many results per page (1 to 100, default 100).","title":"Limit"},"starting_after":{"anyOf":[{"maxLength":300,"type":"string"},{"type":"null"}],"default":null,"description":"Paging cursor: the paging.next.starting_after value of the previous answer (leave empty for the first page).","title":"Starting After"}},"required":["list_id"],"title":"list_list_tagsArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/list_contacts":{"post":{"operationId":"list_contacts","summary":"List the contacts of a list with email address, status, tags, custom field values and dates. Filter by status, tag and c","description":"List the contacts of a list with email address, status, tags, custom field values and dates. Filter by status, tag and created or updated time. Use for \"Who is subscribed to my EmailOctopus newsletter list\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"list_id":{"description":"EmailOctopus list ID (a UUID, from list_lists), for example '00000000-0000-0000-0000-000000000000'.","maxLength":60,"title":"List Id","type":"string"},"status":{"anyOf":[{"enum":["subscribed","unsubscribed","pending"],"type":"string"},{"type":"null"}],"default":"subscribed","description":"Contact status: subscribed (default), unsubscribed or pending.","title":"Status"},"tag":{"anyOf":[{"maxLength":100,"type":"string"},{"type":"null"}],"default":null,"description":"Only contacts with this tag.","title":"Tag"},"created_at_gte":{"anyOf":[{"maxLength":30,"type":"string"},{"type":"null"}],"default":null,"description":"Only contacts created at or after this ISO 8601 time, for example 2026-01-01T00:00:00Z.","title":"Created At Gte"},"created_at_lte":{"anyOf":[{"maxLength":30,"type":"string"},{"type":"null"}],"default":null,"description":"Only contacts created at or before this ISO 8601 time.","title":"Created At Lte"},"last_updated_at_gte":{"anyOf":[{"maxLength":30,"type":"string"},{"type":"null"}],"default":null,"description":"Only contacts updated at or after this ISO 8601 time.","title":"Last Updated At Gte"},"last_updated_at_lte":{"anyOf":[{"maxLength":30,"type":"string"},{"type":"null"}],"default":null,"description":"Only contacts updated at or before this ISO 8601 time.","title":"Last Updated At Lte"},"limit":{"anyOf":[{"maximum":100,"minimum":1,"type":"integer"},{"type":"null"}],"default":100,"description":"How many results per page (1 to 100, default 100).","title":"Limit"},"starting_after":{"anyOf":[{"maxLength":300,"type":"string"},{"type":"null"}],"default":null,"description":"Paging cursor: the paging.next.starting_after value of the previous answer (leave empty for the first page).","title":"Starting After"}},"required":["list_id"],"title":"list_contactsArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/get_contact":{"post":{"operationId":"get_contact","summary":"Get one contact of a list by contact ID or by the MD5 hash of the lowercase email address. Use for \"Look up ada@example.","description":"Get one contact of a list by contact ID or by the MD5 hash of the lowercase email address. Use for \"Look up ada@example.com on my EmailOctopus list\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"list_id":{"description":"EmailOctopus list ID (a UUID, from list_lists), for example '00000000-0000-0000-0000-000000000000'.","maxLength":60,"title":"List Id","type":"string"},"contact_id":{"description":"Contact ID, or the MD5 hash of the contact's lowercase email address (32 hex characters).","maxLength":60,"title":"Contact Id","type":"string"}},"required":["list_id","contact_id"],"title":"get_contactArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/list_campaigns":{"post":{"operationId":"list_campaigns","summary":"List campaigns with name, subject, status (draft, sending, sent, error), sender and send time. The HTML body is not retu","description":"List campaigns with name, subject, status (draft, sending, sent, error), sender and send time. The HTML body is not returned. Use for \"What EmailOctopus campaigns have I sent\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"limit":{"anyOf":[{"maximum":100,"minimum":1,"type":"integer"},{"type":"null"}],"default":100,"description":"How many results per page (1 to 100, default 100).","title":"Limit"},"starting_after":{"anyOf":[{"maxLength":300,"type":"string"},{"type":"null"}],"default":null,"description":"Paging cursor: the paging.next.starting_after value of the previous answer (leave empty for the first page).","title":"Starting After"}},"title":"list_campaignsArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/get_campaign":{"post":{"operationId":"get_campaign","summary":"Get one campaign with name, subject, status, preview text, sender and dates. Use for \"Show my EmailOctopus campaign 0000","description":"Get one campaign with name, subject, status, preview text, sender and dates. Use for \"Show my EmailOctopus campaign 00000000-0000-0000-0000-000000000000\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"campaign_id":{"description":"EmailOctopus campaign ID (a UUID, from list_campaigns), for example '00000000-0000-0000-0000-000000000000'.","maxLength":60,"title":"Campaign Id","type":"string"}},"required":["campaign_id"],"title":"get_campaignArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/get_campaign_summary_report":{"post":{"operationId":"get_campaign_summary_report","summary":"Get a campaign's results: sent, bounced (hard and soft), opened, clicked (total and unique), complained and unsubscribed","description":"Get a campaign's results: sent, bounced (hard and soft), opened, clicked (total and unique), complained and unsubscribed counts. Use for \"How did my last EmailOctopus campaign perform\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"campaign_id":{"description":"EmailOctopus campaign ID (a UUID, from list_campaigns), for example '00000000-0000-0000-0000-000000000000'.","maxLength":60,"title":"Campaign Id","type":"string"}},"required":["campaign_id"],"title":"get_campaign_summary_reportArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/get_campaign_link_report":{"post":{"operationId":"get_campaign_link_report","summary":"Get which links of a campaign were clicked, with total and unique click counts per URL. Use for \"Which links in my Email","description":"Get which links of a campaign were clicked, with total and unique click counts per URL. Use for \"Which links in my EmailOctopus campaign got clicks\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"campaign_id":{"description":"EmailOctopus campaign ID (a UUID, from list_campaigns), for example '00000000-0000-0000-0000-000000000000'.","maxLength":60,"title":"Campaign Id","type":"string"}},"required":["campaign_id"],"title":"get_campaign_link_reportArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/list_campaign_contact_reports":{"post":{"operationId":"list_campaign_contact_reports","summary":"List the contacts who had a given outcome for a campaign (sent, opened, clicked, bounced, complained, unsubscribed, not-","description":"List the contacts who had a given outcome for a campaign (sent, opened, clicked, bounced, complained, unsubscribed, not-opened, not-clicked) with the time it happened. Use for \"Who opened my EmailOctopus campaign\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"campaign_id":{"description":"EmailOctopus campaign ID (a UUID, from list_campaigns), for example '00000000-0000-0000-0000-000000000000'.","maxLength":60,"title":"Campaign Id","type":"string"},"status":{"description":"Outcome to list: bounced, clicked, complained, opened, sent, unsubscribed, not-opened or not-clicked.","enum":["bounced","clicked","complained","opened","sent","unsubscribed","not-opened","not-clicked"],"title":"Status","type":"string"},"limit":{"anyOf":[{"maximum":100,"minimum":1,"type":"integer"},{"type":"null"}],"default":100,"description":"How many results per page (1 to 100, default 100).","title":"Limit"},"starting_after":{"anyOf":[{"maxLength":300,"type":"string"},{"type":"null"}],"default":null,"description":"Paging cursor: the paging.next.starting_after value of the previous answer (leave empty for the first page).","title":"Starting After"}},"required":["campaign_id","status"],"title":"list_campaign_contact_reportsArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}}}}