A2A Agent Card · Live Direct Marketing

LDM.delivery

Email delivery API for AI agents. Pay only for delivered inbox messages.

Near-conformant. Correctly shaped against the A2A 1.0.0 AgentCard object, but omits optional fields an agent may expect.
Legacy discovery path. This card is served at /.well-known/agent.json, the pre-0.3 location, rather than the current /.well-known/agent-card.json. Clients written against A2A 1.0.0 will not find it.
Provider: Live Direct Marketing Conformance: Near-Conformant Protocol: 0.3.0 Transport: Version: 0.1.0 Host: api.live-direct-marketing.online Skills: 237
Discovery

An A2A client finds this agent by fetching the well-known path on the provider's own host. That is what makes an agent card different from every other agent artifact in this catalog: it is provider-published by construction — it cannot be derived, generated, or reconstructed on a provider's behalf.

https://api.live-direct-marketing.online/.well-known/agent.json
Skills (237)

List notifications for the current user notifications.list

List notifications for the current user — GET /api/notifications (scope notifications:read)

notificationsnotifications

Create an agent self-note notification notifications.self-note

Create an agent self-note notification — POST /api/notifications/self-note (scope notifications:write)

notificationsnotifications

List tenant API keys (raw key value hidden) keys.list

List tenant API keys (raw key value hidden) — GET /api/api-keys (scope keys:read)

keyskeys

Create a new tenant API key. Pass `actAsCurrentUser: true` to bind the key to the calling user (required for compose/reply/forward and other user-context endpoints; sets `ownerUserId`). Optional `scopes` array gates which surfaces the key can hit; default `["*"]`. keys.create

Create a new tenant API key. Pass `actAsCurrentUser: true` to bind the key to the calling user (required for compose/reply/forward and other user-context endpoints; sets `ownerUserId`). Optional `scopes` array gates which surfaces the key can hit; default `["*"]`. — POST /api/api-keys (scope keys:write)

keyskeys

Check that the current Bearer credentials (API key or JWT) are valid, and learn where this key is connected before hitting a wall. No scope required — any authenticated caller passes. Used by the MCP gateway to reject bad keys before building an MCP session, instead of after the first tool call. Beyond the original `{ ok, tenantId, scopes, authMode }`, also returns `baseUrl` (scheme+host the request actually arrived on, honoring x-forwarded-proto/x-forwarded-host behind the nginx edge), `apiPrefix` (the mandatory path prefix, taken from the same constant main.ts uses for setGlobalPrefix), and `closedCapabilityClasses` (LEGACY_CAPABILITIES id-prefix groups where NOT ONE operation is reachable with this key's granted scopes). me

Check that the current Bearer credentials (API key or JWT) are valid, and learn where this key is connected before hitting a wall. No scope required — any authenticated caller passes. Used by the MCP gateway to reject bad keys before building an MCP session, instead of after the first tool call. Beyond the original `{ ok, tenantId, scopes, authMode }`, also returns `baseUrl` (scheme+host the request actually arrived on, honoring x-forwarded-proto/x-forwarded-host behind the nginx edge), `apiPrefix` (the mandatory path prefix, taken from the same constant main.ts uses for setGlobalPrefix), and `closedCapabilityClasses` (LEGACY_CAPABILITIES id-prefix groups where NOT ONE operation is reachable with this key's granted scopes). — GET /api/api-keys/whoami

me

Permanently delete a tenant API key keys.revoke

Permanently delete a tenant API key — DELETE /api/api-keys/{id} (scope keys:write)

keyskeys

List webhook endpoints webhooks.list

List webhook endpoints — GET /api/webhooks (scope webhooks:read)

webhookswebhooks

Create a webhook endpoint webhooks.create

Create a webhook endpoint — POST /api/webhooks (scope webhooks:write)

webhookswebhooks

List delivery history for a webhook endpoint webhooks.deliveries

List delivery history for a webhook endpoint — GET /api/webhooks/{id}/deliveries (scope webhooks:read)

webhookswebhooks

Retry a single webhook delivery webhooks.retry

Retry a single webhook delivery — POST /api/webhooks/deliveries/{id}/retry (scope webhooks:write)

webhookswebhooks

List users (SUPER/MANAGER) users.list

List users (SUPER/MANAGER) — GET /api/users (scope users:read)

usersusers

Create a user (SUPER only) users.create

Create a user (SUPER only) — POST /api/users (scope users:write)

usersusers

List companies with pagination, search, and filters companies.list

List companies with pagination, search, and filters — GET /api/companies (scope crm:read)

companiescrm

Create a new company. Note: `email` is NOT a Company field — emails live on linked contacts as Channels. Use POST /api/contacts to create the contact, then POST /api/contacts/:id/channels { type: "EMAIL", value } to attach an email channel. Passing `email` in this body returns 400. companies.create

Create a new company. Note: `email` is NOT a Company field — emails live on linked contacts as Channels. Use POST /api/contacts to create the contact, then POST /api/contacts/:id/channels { type: "EMAIL", value } to attach an email channel. Passing `email` in this body returns 400. — POST /api/companies (scope crm:write)

companiescrm

Soft-delete a company companies.delete

Soft-delete a company — DELETE /api/companies/{id} (scope companies:write)

companiescompanies

Restore a soft-deleted company companies.restore

Restore a soft-deleted company — POST /api/companies/{id}/restore (scope companies:write)

companiescompanies

Roll back a company import batch by ID companies.import_rollback

Roll back a company import batch by ID — DELETE /api/companies/import/rollback/{batchId} (scope companies:write)

companiescompanies

List suppressed emails suppression.list

List suppressed emails — GET /api/suppression (scope suppression:read)

suppressionsuppression

Add an email to the suppression list suppression.add

Add an email to the suppression list — POST /api/suppression (scope suppression:write)

suppressionsuppression

Check a batch of emails against the suppression list suppression.check

Check a batch of emails against the suppression list — POST /api/suppression/check (scope suppression:read)

suppressionsuppression

Remove an email from the suppression list suppression.remove

Remove an email from the suppression list — DELETE /api/suppression/{email} (scope suppression:write)

suppressionsuppression

List stop list entries (user scope) stoplist.list

List stop list entries (user scope) — GET /api/stop-lists (scope stoplist:read)

stopliststoplist

Add a stop list entry (user scope) stoplist.add

Add a stop list entry (user scope) — POST /api/stop-lists (scope stoplist:write)

stopliststoplist

Remove a stop list entry (user scope) stoplist.remove

Remove a stop list entry (user scope) — DELETE /api/stop-lists/{id} (scope stoplist:write)

stopliststoplist

Check a batch of emails against the stop list stoplist.check

Check a batch of emails against the stop list — POST /api/stop-lists/check (scope stoplist:read)

stopliststoplist

List tenant reports (paginated) + storage quota reports.list

List tenant reports (paginated) + storage quota — GET /api/reports (scope reports:read)

reportsreports

Create a report from base64 content (agent/MCP path) reports.create

Create a report from base64 content (agent/MCP path) — POST /api/reports (scope reports:write)

reportsreports

Register a completed export job as a report (idempotent) reports.from_export

Register a completed export job as a report (idempotent) — POST /api/reports/from-export/{exportJobId} (scope reports:write)

reportsreports

Publish: open a direct public download link (no auth!) reports.publish

Publish: open a direct public download link (no auth!) — POST /api/reports/{id}/publish (scope reports:write)

reportsreports

Unpublish: close the public link (token kept — re-publish restores the same url) reports.unpublish

Unpublish: close the public link (token kept — re-publish restores the same url) — POST /api/reports/{id}/unpublish (scope reports:write)

reportsreports

Download the report file (authorized) reports.download

Download the report file (authorized) — GET /api/reports/{id}/download (scope reports:read)

reportsreports

Get the mail agent connection status and stats agent.status

Get the mail agent connection status and stats — GET /api/mail-agent/status (scope agent:read)

agentagent

Get current mail agent settings agent.settings.get

Get current mail agent settings — GET /api/mail-agent/settings (scope agent:read)

agentagent

Toggle the mail agent enabled flag agent.settings.toggle

Toggle the mail agent enabled flag — POST /api/mail-agent/settings (scope agent:write)

agentagent

Regenerate the mail agent auth token agent.token.regenerate

Regenerate the mail agent auth token — POST /api/mail-agent/token/regenerate (scope agent:write)

agentagent

Disconnect the mail agent session agent.disconnect

Disconnect the mail agent session — POST /api/mail-agent/disconnect (scope agent:write)

agentagent

Generate AI completion via configured provider ai.generate

Generate AI completion via configured provider — POST /api/ai/generate (scope ai:write)

aiai

List available AI providers with status ai.providers

List available AI providers with status — GET /api/ai/providers (scope ai:read)

aiai

Verify a batch of email addresses synchronously email-verification.verify-batch

Verify a batch of email addresses synchronously — POST /api/verify/batch (scope email:send)

email-verificationemail

List custom field definitions, optionally filtered by entity customfields.list

List custom field definitions, optionally filtered by entity — GET /api/custom-fields (scope customfields:read)

customfieldscustomfields

Create a custom field definition customfields.create

Create a custom field definition — POST /api/custom-fields (scope customfields:write)

customfieldscustomfields

List contacts with pagination, search, and filters contacts.list

List contacts with pagination, search, and filters — GET /api/contacts (scope crm:read)

contactscrm

Create a new contact. Note: `email`/`phone` are NOT direct Contact fields — they live as Channels. After creating the contact, attach the email/phone via POST /api/contacts/:id/channels { type: "EMAIL" | "PHONE", value }. Passing `email`/`phone` in this body returns 400. contacts.create

Create a new contact. Note: `email`/`phone` are NOT direct Contact fields — they live as Channels. After creating the contact, attach the email/phone via POST /api/contacts/:id/channels { type: "EMAIL" | "PHONE", value }. Passing `email`/`phone` in this body returns 400. — POST /api/contacts (scope crm:write)

contactscrm

Soft-delete a contact contacts.delete

Soft-delete a contact — DELETE /api/contacts/{id} (scope contacts:write)

contactscontacts

Restore a soft-deleted contact contacts.restore

Restore a soft-deleted contact — POST /api/contacts/{id}/restore (scope contacts:write)

contactscontacts

Roll back a contact import batch by ID contacts.import_rollback

Roll back a contact import batch by ID — DELETE /api/contacts/import/rollback/{batchId} (scope contacts:write)

contactscontacts

List all pipelines pipelines.list

List all pipelines — GET /api/pipelines (scope pipelines:read)

pipelinespipelines

Create a new pipeline pipelines.create

Create a new pipeline — POST /api/pipelines (scope pipelines:write)

pipelinespipelines

List leads with pagination, search, and pipeline/stage filters leads.list

List leads with pagination, search, and pipeline/stage filters — GET /api/leads (scope leads:read)

leadsleads

Create a new lead leads.create

Create a new lead — POST /api/leads (scope leads:write)

leadsleads

Get lead statistics, optionally scoped to a pipeline leads.stats

Get lead statistics, optionally scoped to a pipeline — GET /api/leads/stats (scope leads:read)

leadsleads

Get the kanban board for a pipeline leads.kanban

Get the kanban board for a pipeline — GET /api/leads/kanban/{pipelineId} (scope leads:read)

leadsleads

Update an existing lead leads.update

Update an existing lead — PATCH /api/leads/{id} (scope leads:write)

leadsleads

Move a lead to a different stage (and optionally pipeline) leads.move

Move a lead to a different stage (and optionally pipeline) — POST /api/leads/{id}/move (scope leads:write)

leadsleads

Export leads to a downloadable file leads.export

Export leads to a downloadable file — POST /api/leads/export (scope leads:write)

leadsleads

Start a leads import job leads.import

Start a leads import job — POST /api/leads/import/start (scope leads:write)

leadsleads

List all tags in the workspace tags.list

List all tags in the workspace — GET /api/tags (scope tags:read)

tagstags

Create a new tag tags.create

Create a new tag — POST /api/tags (scope tags:write)

tagstags

List all contact lists for the tenant contact-lists.list

List all contact lists for the tenant — GET /api/contact-lists (scope crm:read)

contact-listscrm

List all company lists for the tenant company-lists.list

List all company lists for the tenant — GET /api/company-lists (scope crm:read)

company-listscrm

Get the full workspace settings document settings.get

Get the full workspace settings document — GET /api/settings (scope settings:read)

settingssettings

Update workspace metadata (name, currency, language) settings.update

Update workspace metadata (name, currency, language) — PATCH /api/settings/workspace (scope settings:write)

settingssettings

Get bo.nalog.gov.ru integration state: enabled, our rate limit, requests today, last error integrations.bo_nalog_get

Get bo.nalog.gov.ru integration state: enabled, our rate limit, requests today, last error — GET /api/settings/integrations/bo-nalog (scope settings:read)

integrationssettings

Update bo.nalog.gov.ru integration: enable/disable, requests-per-minute cap integrations.bo_nalog_update

Update bo.nalog.gov.ru integration: enable/disable, requests-per-minute cap — PATCH /api/settings/integrations/bo-nalog (scope settings:write)

integrationssettings

Get DaData integration configuration integrations.dadata_get

Get DaData integration configuration — GET /api/settings/integrations/dadata (scope settings:read)

integrationssettings

Update DaData integration configuration integrations.dadata_update

Update DaData integration configuration — PATCH /api/settings/integrations/dadata (scope settings:write)

integrationssettings

Reset the DaData daily request counter integrations.dadata_reset_counter

Reset the DaData daily request counter — POST /api/settings/integrations/dadata/reset-counter (scope settings:write)

integrationssettings

Get Inbox Check integration configuration integrations.inbox_check_get

Get Inbox Check integration configuration — GET /api/settings/integrations/inbox-check (scope settings:read)

integrationssettings

Update Inbox Check integration configuration integrations.inbox_check_update

Update Inbox Check integration configuration — PATCH /api/settings/integrations/inbox-check (scope settings:write)

integrationssettings

Test the Inbox Check connection integrations.inbox_check_test

Test the Inbox Check connection — POST /api/settings/integrations/inbox-check/test (scope settings:write)

integrationssettings

Get Smartlead integration configuration integrations.smartlead_get

Get Smartlead integration configuration — GET /api/settings/integrations/smartlead (scope settings:read)

integrationssettings

Update Smartlead integration configuration integrations.smartlead_update

Update Smartlead integration configuration — PATCH /api/settings/integrations/smartlead (scope settings:write)

integrationssettings

Test the Smartlead connection integrations.smartlead_test

Test the Smartlead connection — POST /api/settings/integrations/smartlead/test (scope settings:write)

integrationssettings

Smartlead placement matrix — mailbox × provider (#1040) integrations.smartlead_placement_matrix

Smartlead placement matrix — mailbox × provider (#1040) — GET /api/settings/integrations/smartlead/placement-matrix (scope settings:read)

integrationssettings

Smartlead placement history for one mailbox × provider cell (#1040) integrations.smartlead_placement_history

Smartlead placement history for one mailbox × provider cell (#1040) — GET /api/settings/integrations/smartlead/placement-history (scope settings:read)

integrationssettings

List dialogs with filters (channel, status, folder, etc.) dialogs.list

List dialogs with filters (channel, status, folder, etc.) — GET /api/dialogs (scope dialogs:read)

dialogsdialogs

Read safe, paginated history for one durable outbox task dialogs.outbox_history

Read safe, paginated history for one durable outbox task — GET /api/dialogs/outbox/{id}/history (scope dialogs:read)

dialogsdialogs

Get a single dialog by ID messages.get

Get a single dialog by ID — GET /api/dialogs/{id} (scope dialogs:read)

messagesdialogs

Reply to a dialog (optionally send via SMTP with attachments). Attachments can be passed inline as `attachmentsJson: [{ filename, contentBase64, contentType }]` (base64-encoded, JSON body) or as multipart files. (#175 — parity with /compose) dialogs.reply

Reply to a dialog (optionally send via SMTP with attachments). Attachments can be passed inline as `attachmentsJson: [{ filename, contentBase64, contentType }]` (base64-encoded, JSON body) or as multipart files. (#175 — parity with /compose) — POST /api/dialogs/{id}/reply (scope dialogs:write)

dialogsdialogs

Compose and send a new outbound email. Provide exactly one sender binding: `accountId` (a fixed relay) OR `accountListId` (a virtual-relay pool — the live relay is chosen from the pool at dispatch time, #40). Attachments are inline only: `attachmentsJson: [{ filename, contentBase64, contentType }]` (base64-encoded). No multipart upload on this endpoint — use `:id/reply` or `:id/forward` for that. (#3 Block 3 — inline attachments) dialogs.compose

Compose and send a new outbound email. Provide exactly one sender binding: `accountId` (a fixed relay) OR `accountListId` (a virtual-relay pool — the live relay is chosen from the pool at dispatch time, #40). Attachments are inline only: `attachmentsJson: [{ filename, contentBase64, contentType }]` (base64-encoded). No multipart upload on this endpoint — use `:id/reply` or `:id/forward` for that. (#3 Block 3 — inline attachments) — POST /api/dialogs/compose (scope dialogs:write)

dialogsdialogs

Get current user settings user-settings.get

Get current user settings — GET /api/user-settings (scope settings:read)

user-settingssettings

Get a global overview of all mailing campaigns (admin dashboard) — merges legacy mailing tasks AND the campaign conveyor (#539); each row is tagged source: legacy | campaign mailing.overview

Get a global overview of all mailing campaigns (admin dashboard) — merges legacy mailing tasks AND the campaign conveyor (#539); each row is tagged source: legacy | campaign — GET /api/mailing/overview (scope mailing:read)

mailingmailing

List campaigns awaiting admin approval (cross-tenant for SUPER) mailing.pending

List campaigns awaiting admin approval (cross-tenant for SUPER) — GET /api/mailing/pending-approvals (scope mailing:read)

mailingmailing

Approve a pending mailing campaign (admin) mailing.approve

Approve a pending mailing campaign (admin) — POST /api/mailing/{taskId}/approve (scope mailing:write)

mailingmailing

Get browser queue stats and fair-share view admin.browser-queue

Get browser queue stats and fair-share view — GET /api/admin/browser-queue (scope admin:read)

adminadmin

Pause the browser queue admin.browser-queue.pause

Pause the browser queue — POST /api/admin/browser-queue/pause (scope admin:write)

adminadmin

Import images from a source attachment into tenant storage files.images.import

Import images from a source attachment into tenant storage — POST /api/files/images/import (scope files:write)

filesfiles

Upload an image for creatives (max 5 MB) files.upload

Upload an image for creatives (max 5 MB) — POST /api/files/upload (scope files:write)

filesfiles

List uploaded creative images for the tenant files.images

List uploaded creative images for the tenant — GET /api/files/images (scope files:read)

filesfiles

Delete a tenant-scoped creative image files.delete_image

Delete a tenant-scoped creative image — DELETE /api/files/images/{filename} (scope files:write)

filesfiles

List tenant assets files.assets

List tenant assets — GET /api/files/assets (scope files:read)

filesfiles

Delete a tenant asset files.delete_asset

Delete a tenant asset — DELETE /api/files/assets/{filename} (scope files:write)

filesfiles

List file attachments for a contact, company or lead files.list

List file attachments for a contact, company or lead — GET /api/files (scope files:read)

filesfiles

Delete a file attachment record files.delete

Delete a file attachment record — DELETE /api/files/{id} (scope files:write)

filesfiles

List tasks with pagination and status/method filters tasks.list

List tasks with pagination and status/method filters — GET /api/tasks (scope tasks:read)

taskstasks

Create a task. SITE SCORING (lead gen): methodId=22 + methodName="scoring" + companyListId (items are populated from the company list on start) → POST /tasks/:id/steps (SITE_AVAILABILITY, then AI_CONTENT) → POST /tasks/:id/start. Other methodId values: 11=email validation, 14=ICP review, 15=DIG, 12=mailing (legacy — prefer /campaigns). tasks.create

Create a task. SITE SCORING (lead gen): methodId=22 + methodName="scoring" + companyListId (items are populated from the company list on start) → POST /tasks/:id/steps (SITE_AVAILABILITY, then AI_CONTENT) → POST /tasks/:id/start. Other methodId values: 11=email validation, 14=ICP review, 15=DIG, 12=mailing (legacy — prefer /campaigns). — POST /api/tasks (scope tasks:write)

taskstasks

Delete a task tasks.delete

Delete a task — DELETE /api/tasks/{id} (scope tasks:write)

taskstasks

List errors encountered during a task run tasks.errors

List errors encountered during a task run — GET /api/tasks/{id}/errors (scope tasks:read)

taskstasks

Start (or resume) a task. If items are empty, they are populated from the task's contactListId/companyListId. Progress: GET /tasks/:id (processedItems/totalItems); for scoring: GET /tasks/:id/scoring-stats and /tasks/:id/scoring-results?status=ACTIVE (score, companyType, contacts found on the site). tasks.start

Start (or resume) a task. If items are empty, they are populated from the task's contactListId/companyListId. Progress: GET /tasks/:id (processedItems/totalItems); for scoring: GET /tasks/:id/scoring-stats and /tasks/:id/scoring-results?status=ACTIVE (score, companyType, contacts found on the site). — POST /api/tasks/{id}/start (scope tasks:write)

taskstasks

List pipeline steps configured on a task tasks.steps.list

List pipeline steps configured on a task — GET /api/tasks/{id}/steps (scope tasks:read)

taskstasks

Add a pipeline step to a task. Types: SITE_AVAILABILITY, AI_CONTENT, KEYWORDS, EMAIL_EXTRACT, PHONE_EXTRACT, SOCIAL_LINKS, TECH_DETECT, GEO_FILTER, NALOG_LOOKUP, AI_CARD_FIELD, and others. For AI_CONTENT: config.messages=[{role:system,...},{role:user,...}] with placeholders {-Variable.page_text-}/{-Variable.domain-}, config.min_score (success when score>=min_score). For AI_CARD_FIELD (#1035, requires item.contactId; or item.companyId when config.targetEntity=COMPANY — a company with no single contact is covered too): config.promptTemplate with the resolver's canonical variables ({{firstName}}, {company.name}, ccf_...), config.targetEntity=CONTACT|COMPANY|LEAD (LEAD requires item.contactId — TaskItem does not store leadId, the target becomes that contact's single lead; 0 leads → no_lead, more than one → ambiguous_lead, the step does not guess), config.targetFieldId=id of an existing CustomFieldDefinition, config.fallback — writes the result to that custom field WITHOUT hitting the site; a repeat on an already-computed entity×field pair does not invoke AI again (dedup by non-empty field value). Routing: onSuccess/onFail/onError = CONTINUE|STOP|MOVE_TO_LIST (+onSuccessTarget=list id)|DELETE. Typical scoring: step 1 SITE_AVAILABILITY (onFail=STOP), step 2 AI_CONTENT (onSuccess=MOVE_TO_LIST into the target list). tasks.steps.add

Add a pipeline step to a task. Types: SITE_AVAILABILITY, AI_CONTENT, KEYWORDS, EMAIL_EXTRACT, PHONE_EXTRACT, SOCIAL_LINKS, TECH_DETECT, GEO_FILTER, NALOG_LOOKUP, AI_CARD_FIELD, and others. For AI_CONTENT: config.messages=[{role:system,...},{role:user,...}] with placeholders {-Variable.page_text-}/{-Variable.domain-}, config.min_score (success when score>=min_score). For AI_CARD_FIELD (#1035, requires item.contactId; or item.companyId when config.targetEntity=COMPANY — a company with no single contact is covered too): config.promptTemplate with the resolver's canonical variables ({{firstName}}, {company.name}, ccf_...), config.targetEntity=CONTACT|COMPANY|LEAD (LEAD requires item.contactId — TaskItem does not store leadId, the target becomes that contact's single lead; 0 leads → no_lead, more than one → ambiguous_lead, the step does not guess), config.targetFieldId=id of an existing CustomFieldDefinition, config.fallback — writes the result to that custom field WITHOUT hitting the site; a repeat on an already-computed entity×field pair does not invoke AI again (dedup by non-empty field value). Routing: onSuccess/onFail/onError = CONTINUE|STOP|MOVE_TO_LIST (+onSuccessTarget=list id)|DELETE. Typical scoring: step 1 SITE_AVAILABILITY (onFail=STOP), step 2 AI_CONTENT (onSuccess=MOVE_TO_LIST into the target list). — POST /api/tasks/{id}/steps (scope tasks:write)

taskstasks

Reorder pipeline steps in a task tasks.steps.reorder

Reorder pipeline steps in a task — PUT /api/tasks/{id}/steps/reorder (scope tasks:write)

taskstasks

Update a single pipeline step tasks.steps.update

Update a single pipeline step — PATCH /api/tasks/{id}/steps/{stepId} (scope tasks:write)

taskstasks

Delete a pipeline step from a task tasks.steps.remove

Delete a pipeline step from a task — DELETE /api/tasks/{id}/steps/{stepId} (scope tasks:write)

taskstasks

List scoring results for a task with pagination. contradictory=true narrows to results whose stepResults carry a contradiction flag (data.contradictoryFields non-empty on any step) — same detection as POST :id/scoring-results/retry contradictoryOnly (#1113). tasks.scoring-results

List scoring results for a task with pagination. contradictory=true narrows to results whose stepResults carry a contradiction flag (data.contradictoryFields non-empty on any step) — same detection as POST :id/scoring-results/retry contradictoryOnly (#1113). — GET /api/tasks/{id}/scoring-results (scope tasks:read)

taskstasks

Get aggregate scoring statistics for a task tasks.scoring-stats

Get aggregate scoring statistics for a task — GET /api/tasks/{id}/scoring-stats (scope tasks:read)

taskstasks

#975: paginated step journal for a single scoring card (requested/success/fail/error/interrupted/resumed_after_restart, seq by time) tasks.scoring-step-events

#975: paginated step journal for a single scoring card (requested/success/fail/error/interrupted/resumed_after_restart, seq by time) — GET /api/tasks/{id}/scoring-results/{resultId}/events (scope tasks:read)

taskstasks

Get the cron scheduling settings for a task tasks.cron.get

Get the cron scheduling settings for a task — GET /api/tasks/{id}/cron (scope tasks:read)

taskstasks

Update the cron scheduling settings for a task tasks.cron.update

Update the cron scheduling settings for a task — PATCH /api/tasks/{id}/cron (scope tasks:write)

taskstasks

Manually trigger a task cron run tasks.cron.trigger

Manually trigger a task cron run — POST /api/tasks/{id}/cron/trigger (scope tasks:write)

taskstasks

List creatives with pagination and search creatives.list

List creatives with pagination and search — GET /api/creatives (scope creatives:read)

creativescreatives

Create a new creative creatives.create

Create a new creative — POST /api/creatives (scope creatives:write)

creativescreatives

Get the PDF generation queue status creatives.pdf-status

Get the PDF generation queue status — GET /api/creatives/pdf-status (scope creatives:read)

creativescreatives

List available template variables creatives.variables.available

List available template variables — GET /api/creatives/variables/available (scope creatives:read)

creativescreatives

Get a single creative by ID creatives.get

Get a single creative by ID — GET /api/creatives/{id} (scope creatives:read)

creativescreatives

Update a creative creatives.update

Update a creative — PATCH /api/creatives/{id} (scope creatives:write)

creativescreatives

Canonical brief intake email and localized help for customer materials linked to this creative creatives.brief-intake

Canonical brief intake email and localized help for customer materials linked to this creative — GET /api/creatives/{id}/brief-intake (scope creatives:read)

creativescreatives

Render a preview of a creative for a sample contact creatives.preview

Render a preview of a creative for a sample contact — POST /api/creatives/{id}/preview (scope creatives:write)

creativescreatives

Get template variables used in a creative creatives.variables

Get template variables used in a creative — GET /api/creatives/{id}/variables (scope creatives:read)

creativescreatives

List test sends of a creative creatives.test-sends

List test sends of a creative — GET /api/creatives/{id}/test-sends (scope creatives:read)

creativescreatives

Send a test copy of this creative. sender="account" (default, unchanged behaviour) needs a connected email account: pass accountId AND toEmail. sender="platform" needs NO connected account and NO toEmail at all — omit toEmail and it sends from the LDM platform mailbox (same transport as signup email) straight to the address the TENANT OWNER registered with; this is the intended zero-config call. If you DO pass toEmail with sender="platform" it must equal that same registration address exactly or the call is refused (not an open relay, #801) — passing any other address never sends anywhere else, it just fails closed. Use "platform" the moment a creative exists, before any mailbox is connected, to see the rendered email + attachment land for real. Rate-limited to 5 platform sends/hour per tenant. The response carries a disclaimer: placement via the platform mailbox says NOTHING about the client's own sending domain reputation — it only proves the creative renders and the attachment attaches; re-test with sender="account" before trusting placement for a real campaign. Zero connected accounts AND no sender given → the 400 body lists BOTH ways forward (connect one, or use sender="platform" with no toEmail). creatives.test-send

Send a test copy of this creative. sender="account" (default, unchanged behaviour) needs a connected email account: pass accountId AND toEmail. sender="platform" needs NO connected account and NO toEmail at all — omit toEmail and it sends from the LDM platform mailbox (same transport as signup email) straight to the address the TENANT OWNER registered with; this is the intended zero-config call. If you DO pass toEmail with sender="platform" it must equal that same registration address exactly or the call is refused (not an open relay, #801) — passing any other address never sends anywhere else, it just fails closed. Use "platform" the moment a creative exists, before any mailbox is connected, to see the rendered email + attachment land for real. Rate-limited to 5 platform sends/hour per tenant. The response carries a disclaimer: placement via the platform mailbox says NOTHING about the client's own sending domain reputation — it only proves the creative renders and the attachment attaches; re-test with sender="account" before trusting placement for a real campaign. Zero connected accounts AND no sender given → the 400 body lists BOTH ways forward (connect one, or use sender="platform" with no toEmail). — POST /api/creatives/{id}/test-send (scope creatives:write)

creativescreatives

Get the status of an asynchronous PDF generation creatives.pdf-generations.get

Get the status of an asynchronous PDF generation — GET /api/creatives/{id}/pdf-generations/{generationId} (scope creatives:read)

creativescreatives

Generate a PDF from a creative creatives.generate-pdf

Generate a PDF from a creative — POST /api/creatives/{id}/generate-pdf (scope creatives:write)

creativescreatives

Existing Brief intake address by briefId/briefUrl; omit both only before a Brief exists for workspace unassigned intake (#755) briefs.intake

Existing Brief intake address by briefId/briefUrl; omit both only before a Brief exists for workspace unassigned intake (#755) — GET /api/briefs/intake (scope briefs:read)

briefsbriefs

List system intake messages for MCP/UI (#750) briefs.intake.items.list

List system intake messages for MCP/UI (#750) — GET /api/briefs/intake/items (scope briefs:read)

briefsbriefs

Read one lossless system intake item with provenance, attachments and work log (#750) briefs.intake.items.get

Read one lossless system intake item with provenance, attachments and work log (#750) — GET /api/briefs/intake/items/{itemId} (scope briefs:read)

briefsbriefs

Transition an intake item to IN_REVIEW, IGNORED or REJECTED with an audited reason (#750) briefs.intake.items.transition

Transition an intake item to IN_REVIEW, IGNORED or REJECTED with an audited reason (#750) — PATCH /api/briefs/intake/items/{itemId}/status (scope briefs:write)

briefsbriefs

Link an intake item/files to a Brief idempotently (#750) briefs.intake.items.link

Link an intake item/files to a Brief idempotently (#750) — POST /api/briefs/intake/items/{itemId}/link (scope briefs:write)

briefsbriefs

Append an agent work-log event with intake provenance (#750) briefs.intake.items.log

Append an agent work-log event with intake provenance (#750) — POST /api/briefs/intake/items/{itemId}/log (scope briefs:write)

briefsbriefs

List briefs with pagination, search and active/deleted filters briefs.list

List briefs with pagination, search and active/deleted filters — GET /api/briefs (scope briefs:read)

briefsbriefs

Create a new brief briefs.create

Create a new brief — POST /api/briefs (scope briefs:write)

briefsbriefs

Read one Brief attachment as bounded source-backed text/structure/image pages; imageRef yields a real MCP image block (#768) briefs.attachment.content

Read one Brief attachment as bounded source-backed text/structure/image pages; imageRef yields a real MCP image block (#768) — GET /api/briefs/{id}/attachments/content (scope briefs:read)

briefsbriefs

Update brief content body (JSON-merge patch). personas[]/examples[] merge by item id when every item has a stable id -- give a NEW item a UUID id and keep reusing it, or the whole array is replaced (legacy behavior, unsafe under concurrent edits, #782); customFields[] has no id yet and always replaces whole briefs.update-content

Update brief content body (JSON-merge patch). personas[]/examples[] merge by item id when every item has a stable id -- give a NEW item a UUID id and keep reusing it, or the whole array is replaced (legacy behavior, unsafe under concurrent edits, #782); customFields[] has no id yet and always replaces whole — PATCH /api/briefs/{id}/content (scope briefs:write)

briefsbriefs

Operation-level SDR expert flow: intake provenance → live schema → gaps → recommendations → save/validate briefs.expert

Operation-level SDR expert flow: intake provenance → live schema → gaps → recommendations → save/validate — GET /api/briefs/{id}/expert (scope briefs:read)

briefsbriefs

Decline a Russian full name (FIO) by grammatical case names.decline

Decline a Russian full name (FIO) by grammatical case — POST /api/names/decline (scope utils:read)

namesutils

List email accounts with filters and pagination accounts.list

List email accounts with filters and pagination — GET /api/email-accounts (scope accounts:read)

accountsaccounts

Create a new email account. Lookup is advisory and client-invoked: POST does not auto-detect transport. Call GET /email-accounts/lookup first for the email address, then pass the returned SMTP/IMAP/service fields explicitly. Override host/port/credentials for custom domains. The legacy `provider` field is normalized to the `service` enum (no separate column). accounts.create

Create a new email account. Lookup is advisory and client-invoked: POST does not auto-detect transport. Call GET /email-accounts/lookup first for the email address, then pass the returned SMTP/IMAP/service fields explicitly. Override host/port/credentials for custom domains. The legacy `provider` field is normalized to the `service` enum (no separate column). — POST /api/email-accounts (scope accounts:write)

accountsaccounts

Get IMAP orchestrator dashboard stats imap.stats

Get IMAP orchestrator dashboard stats — GET /api/imap-orchestrator/stats (scope imap:read)

imapimap

Get lossless mail sync cursor, staging and quarantine health imap.sync-health

Get lossless mail sync cursor, staging and quarantine health — GET /api/imap-orchestrator/sync-health (scope imap:read)

imapimap

Retry a failed durable inbound message, or force a re-fetch of an exhausted quarantine row imap.retry-staged

Retry a failed durable inbound message, or force a re-fetch of an exhausted quarantine row — POST /api/imap-orchestrator/sync-health/{id}/retry (scope imap:write)

imapimap

Auto-heal stuck GAS accounts and IMAP locks for the current tenant imap.heal

Auto-heal stuck GAS accounts and IMAP locks for the current tenant — POST /api/imap-orchestrator/heal (scope imap:write)

imapimap

Trigger an IMAP fetch for every active account in the tenant imap.fetch-all

Trigger an IMAP fetch for every active account in the tenant — POST /api/imap-orchestrator/fetch-all (scope imap:write)

imapimap

Get the latest N IMAP job log entries for monitoring imap.tech-log

Get the latest N IMAP job log entries for monitoring — GET /api/imap-orchestrator/tech-log (scope imap:read)

imapimap

List all inbound rules inbound-rules.list

List all inbound rules — GET /api/inbound-rules (scope rules:read)

inbound-rulesrules

Create a new inbound rule inbound-rules.create

Create a new inbound rule — POST /api/inbound-rules (scope rules:write)

inbound-rulesrules

Manually re-run linker for a specific dialog linker.relink

Manually re-run linker for a specific dialog — POST /api/dialog-linker/relink/{dialogId} (scope linker:write)

linkerlinker

Get linker statistics by status linker.stats

Get linker statistics by status — GET /api/dialog-linker/stats (scope linker:read)

linkerlinker

Get all linker logs (admin tech log) linker.logs

Get all linker logs (admin tech log) — GET /api/dialog-linker/logs (scope linker:read)

linkerlinker

List saved views for an entity for the current user views.list

List saved views for an entity for the current user — GET /api/saved-views (scope views:read)

viewsviews

Create a saved view views.create

Create a saved view — POST /api/saved-views (scope views:write)

viewsviews

List activities filtered by lead/contact/company/type activities.list

List activities filtered by lead/contact/company/type — GET /api/activities (scope activities:read)

activitiesactivities

Create an activity (call/task/note) linked to a lead/contact/company activities.create

Create an activity (call/task/note) linked to a lead/contact/company — POST /api/activities (scope activities:write)

activitiesactivities

Get stats for all BullMQ queues admin.queues

Get stats for all BullMQ queues — GET /api/admin/queues (scope admin:read)

adminadmin

Pause a BullMQ queue admin.queue.pause

Pause a BullMQ queue — POST /api/admin/queues/{name}/pause (scope admin:write)

adminadmin

List all tenants with metadata admin.tenants

List all tenants with metadata — GET /api/admin/tenants (scope admin:read)

adminadmin

Toggle LDM AI for a tenant admin.tenant.ldm-ai

Toggle LDM AI for a tenant — PATCH /api/admin/tenants/{dbName}/ldm-ai (scope admin:write)

adminadmin

Update mail transport config for a tenant admin.tenant.transport

Update mail transport config for a tenant — PATCH /api/admin/tenants/{dbName}/transport (scope admin:write)

adminadmin

Get i18n translations bundle admin.i18n

Get i18n translations bundle — GET /api/admin/i18n (scope admin:read)

adminadmin

List memory files admin.memory.list

List memory files — GET /api/admin/memory (scope admin:read)

adminadmin

Get security overview dashboard admin.security.overview

Get security overview dashboard — GET /api/admin/security/overview (scope admin:read)

adminadmin

campaigns test task create campaigns.test_task.create

POST /api/campaigns/{id}/test-task (scope campaigns:write)

campaignscampaigns

campaigns test task status campaigns.test_task.status

GET /api/campaigns/{id}/test-task/{taskId} (scope campaigns:read)

campaignscampaigns

Single source of truth for "what is happening with this campaign right now". Returns lifecycleStatus (DRAFT|ACTIVE|PAUSED|DONE|ERROR|AUDIT_BLOCKED) SEPARATELY from operationalState (RUNNING|WAITING|DEGRADED|BLOCKED|COMPLETED): an ACTIVE campaign that sends nothing is the exact defect this endpoint exists for, so never report "active" without the operational qualifier. primaryBlocker is picked by a documented priority table and carries code, since, retryAt, recoverable, suggestedAction and docsKey; `legitimateWait` marks a normal wait (closed send window, future schedule) rather than a stop. `lastProgressAt` is the last REAL hand-off to transport, not the last campaign event. `nextActions[]` lists machine-readable moves — the endpoint never promises to fix anything by itself. UI, notifications and MCP all read this same computation; send-readiness returns the same state plus the full gate dump. campaigns.operational_status

Single source of truth for "what is happening with this campaign right now". Returns lifecycleStatus (DRAFT|ACTIVE|PAUSED|DONE|ERROR|AUDIT_BLOCKED) SEPARATELY from operationalState (RUNNING|WAITING|DEGRADED|BLOCKED|COMPLETED): an ACTIVE campaign that sends nothing is the exact defect this endpoint exists for, so never report "active" without the operational qualifier. primaryBlocker is picked by a documented priority table and carries code, since, retryAt, recoverable, suggestedAction and docsKey; `legitimateWait` marks a normal wait (closed send window, future schedule) rather than a stop. `lastProgressAt` is the last REAL hand-off to transport, not the last campaign event. `nextActions[]` lists machine-readable moves — the endpoint never promises to fix anything by itself. UI, notifications and MCP all read this same computation; send-readiness returns the same state plus the full gate dump. — GET /api/campaigns/{id}/operational-status (scope campaigns:read)

campaignscampaigns

Paginated durable delivery-task history for a campaign campaigns.task_history

Paginated durable delivery-task history for a campaign — GET /api/campaigns/{id}/task-history (scope campaigns:read)

campaignscampaigns

Submit self-rendered (BYOC) email content for SCREENED recipients: [{recipientId, subject, bodyHtml, bodyText?}], batch <=100, bodyHtml <=256KB. Submission is free; the content goes through a mandatory paid audit (audit/audit_failed operations), rejection reasons are coarse categories in auditCategories. Limit of 5 audit iterations per recipient; the campaign is blocked (AUDIT_BLOCKED) on systematic rejections. campaigns.submit_rendered_emails

Submit self-rendered (BYOC) email content for SCREENED recipients: [{recipientId, subject, bodyHtml, bodyText?}], batch <=100, bodyHtml <=256KB. Submission is free; the content goes through a mandatory paid audit (audit/audit_failed operations), rejection reasons are coarse categories in auditCategories. Limit of 5 audit iterations per recipient; the campaign is blocked (AUDIT_BLOCKED) on systematic rejections. — POST /api/campaigns/{id}/recipients/content (scope campaigns:write)

campaignscampaigns

Start or join a durable bounded preparation operation (no sending). Poll statusUrl; accepted means queued, not completed. Preferred over synchronous prepare for AI and personal PDFs. campaigns.preparations.start

Start or join a durable bounded preparation operation (no sending). Poll statusUrl; accepted means queued, not completed. Preferred over synchronous prepare for AI and personal PDFs. — POST /api/campaigns/{id}/preparations (scope campaigns:write)

campaignscampaigns

Read a tenant-bound preparation operation. Completed result has the same fields as prepare; failed contains a safe error code/message. This endpoint never sends. campaigns.preparations.status

Read a tenant-bound preparation operation. Completed result has the same fields as prepare; failed contains a safe error code/message. This endpoint never sends. — GET /api/campaigns/{id}/preparations/{generationId} (scope campaigns:read)

campaignscampaigns

Resolve recommended send time without scheduling; AI fallback uses normal usage logging and billing best-send-time.calc

Resolve recommended send time without scheduling; AI fallback uses normal usage logging and billing — POST /api/best-send-time (scope mailing:read)

best-send-timemailing

Resume snapshot (read-only): tenant context core, own recent notifications and self-notes, plus an honest next_step resume

Resume snapshot (read-only): tenant context core, own recent notifications and self-notes, plus an honest next_step — GET /api/v1/agent-guide/resume (scope agent:read)

resumeagent

#968 detect forms on a page from HTML: hasForm — whether any form is present at all; hasContactForm — a CONTACT-US form (excluding search/login/subscribe/catalog filter); forms[] — submit address (absolute if pageUrl is supplied), method, kind (contact|search|login|subscribe|catalog_filter|other), confidence (0..1), and reasons[] — a human-readable basis for the decision. site-enrichment.detect-forms

#968 detect forms on a page from HTML: hasForm — whether any form is present at all; hasContactForm — a CONTACT-US form (excluding search/login/subscribe/catalog filter); forms[] — submit address (absolute if pageUrl is supplied), method, kind (contact|search|login|subscribe|catalog_filter|other), confidence (0..1), and reasons[] — a human-readable basis for the decision. — POST /api/site-enrichment/detect-forms (scope site-enrichment:read)

site-enrichmentsite-enrichment

#903/#889 enqueue the canonical site-crawl task (durable, DB is the source of truth) site-enrichment.tasks.create

#903/#889 enqueue the canonical site-crawl task (durable, DB is the source of truth) — POST /api/site-enrichment/tasks (scope site-enrichment:write)

site-enrichmentsite-enrichment

#953 list of site-crawl tasks: both linked to a scoring task (scoringTaskId) and unlinked (owned=false — e.g. launched via MCP without a task) site-enrichment.tasks.list

#953 list of site-crawl tasks: both linked to a scoring task (scoringTaskId) and unlinked (owned=false — e.g. launched via MCP without a task) — GET /api/site-enrichment/tasks (scope site-enrichment:read)

site-enrichmentsite-enrichment

#955 preview list coverage WITHOUT starting a crawl: how many cards are in the list, how many have the domain field filled, how many unique domains among them — plus coverage of ALL eligible fields at once (website/domain/URL custom fields) site-enrichment.tasks.preview

#955 preview list coverage WITHOUT starting a crawl: how many cards are in the list, how many have the domain field filled, how many unique domains among them — plus coverage of ALL eligible fields at once (website/domain/URL custom fields) — GET /api/site-enrichment/tasks/preview (scope site-enrichment:read)

site-enrichmentsite-enrichment

Status/counters of a site-crawl task site-enrichment.tasks.get

Status/counters of a site-crawl task — GET /api/site-enrichment/tasks/{id} (scope site-enrichment:read)

site-enrichmentsite-enrichment

#903 task transition log, read from the DB, cursor=last received seq site-enrichment.tasks.events

#903 task transition log, read from the DB, cursor=last received seq — GET /api/site-enrichment/tasks/{id}/events (scope site-enrichment:read)

site-enrichmentsite-enrichment

#1144 atom B: an agent note into the task journal (kind=agent_note, author taken from the request key/JWT, NOT from the body). Written through the SINGLE existing journal writer (SiteEnrichmentService.appendEvent) — there is no second one. Does NOT touch the task's updatedAt/status/processed/counters and does not count towards MAX_RESUME_ATTEMPTS: an observer note must not affect the observed thing (otherwise it would delay the watchdog's staleness pickup). The body is ONLY {text}; the system kind cannot be supplied from outside (forbidNonWhitelisted → 400 before the controller, see CreateAgentNoteDto). site-enrichment.tasks.events.add

#1144 atom B: an agent note into the task journal (kind=agent_note, author taken from the request key/JWT, NOT from the body). Written through the SINGLE existing journal writer (SiteEnrichmentService.appendEvent) — there is no second one. Does NOT touch the task's updatedAt/status/processed/counters and does not count towards MAX_RESUME_ATTEMPTS: an observer note must not affect the observed thing (otherwise it would delay the watchdog's staleness pickup). The body is ONLY {text}; the system kind cannot be supplied from outside (forbidNonWhitelisted → 400 before the controller, see CreateAgentNoteDto). — POST /api/site-enrichment/tasks/{id}/events (scope site-enrichment:write)

site-enrichmentsite-enrichment

#949 summary of failure reasons (for a clickable filter above the journal) site-enrichment.tasks.reason-summary

#949 summary of failure reasons (for a clickable filter above the journal) — GET /api/site-enrichment/tasks/{id}/reason-summary (scope site-enrichment:read)

site-enrichmentsite-enrichment

#957/#969 unified task statistics read from durable rows: funnel (cards AND domains counted separately, including sourceTotal/visitsSaved from dedup), collected data (substrate-writer receipt — emails/phones/socials/text/native fields, per-map and total), acquisition method, pace/forecast state by domain (plus elapsedSeconds/cardsPerHour/etaAt), breakdown by reason (byReason), breakdown by outcome (byStatus: OK/DOWN/NO_SITE/EMPTY/CAPTCHA) and actual homepage HTTP codes (byHttpStatus, httpStatus:null — no response), launch (launch parameters echoed back — listId/listName/domainField/visitPages/timeoutMs/maxAttempts/mode/surface/startedBy), and links (direct URLs to the scoring-task card and this task's journal) — WITHOUT the full result list (use tasks/:id/items for paginated inspection). The same method serves the legacy alias GET /icp-tasks/companies/scrape/:taskId (stats key) — the only route that actually reaches MCP. site-enrichment.tasks.stats

#957/#969 unified task statistics read from durable rows: funnel (cards AND domains counted separately, including sourceTotal/visitsSaved from dedup), collected data (substrate-writer receipt — emails/phones/socials/text/native fields, per-map and total), acquisition method, pace/forecast state by domain (plus elapsedSeconds/cardsPerHour/etaAt), breakdown by reason (byReason), breakdown by outcome (byStatus: OK/DOWN/NO_SITE/EMPTY/CAPTCHA) and actual homepage HTTP codes (byHttpStatus, httpStatus:null — no response), launch (launch parameters echoed back — listId/listName/domainField/visitPages/timeoutMs/maxAttempts/mode/surface/startedBy), and links (direct URLs to the scoring-task card and this task's journal) — WITHOUT the full result list (use tasks/:id/items for paginated inspection). The same method serves the legacy alias GET /icp-tasks/companies/scrape/:taskId (stats key) — the only route that actually reaches MCP. — GET /api/site-enrichment/tasks/{id}/stats (scope site-enrichment:read)

site-enrichmentsite-enrichment

#952/#969 crawl task items: paginated, with a filter by outcome (status=OK|DOWN|NO_SITE|EMPTY|CAPTCHA) and/or reason code (reasonCode) site-enrichment.tasks.items

#952/#969 crawl task items: paginated, with a filter by outcome (status=OK|DOWN|NO_SITE|EMPTY|CAPTCHA) and/or reason code (reasonCode) — GET /api/site-enrichment/tasks/{id}/items (scope site-enrichment:read)

site-enrichmentsite-enrichment

#965 diagnostic snapshot of the RAW visited page text(s) for ONE company (homepage + "Contacts", BEFORE contact extraction) — TTL 12h, only while diagnostic mode is on; an empty data is legitimate, not an error site-enrichment.tasks.raw

#965 diagnostic snapshot of the RAW visited page text(s) for ONE company (homepage + "Contacts", BEFORE contact extraction) — TTL 12h, only while diagnostic mode is on; an empty data is legitimate, not an error — GET /api/site-enrichment/tasks/{id}/raw (scope site-enrichment:read)

site-enrichmentsite-enrichment

Cancel a site-crawl task (durable — status in the DB, visible to any process) site-enrichment.tasks.cancel

Cancel a site-crawl task (durable — status in the DB, visible to any process) — POST /api/site-enrichment/tasks/{id}/cancel (scope site-enrichment:write)

site-enrichmentsite-enrichment

#952 pause a crawl task (durable, non-terminal — resumed via .../resume) site-enrichment.tasks.pause

#952 pause a crawl task (durable, non-terminal — resumed via .../resume) — POST /api/site-enrichment/tasks/{id}/pause (scope site-enrichment:write)

site-enrichmentsite-enrichment

#952 resume a paused crawl task site-enrichment.tasks.resume

#952 resume a paused crawl task — POST /api/site-enrichment/tasks/{id}/resume (scope site-enrichment:write)

site-enrichmentsite-enrichment

Retry still-not-OK companies of a terminal task (FAILED/PARTIAL/CANCELLED) site-enrichment.tasks.retry

Retry still-not-OK companies of a terminal task (FAILED/PARTIAL/CANCELLED) — POST /api/site-enrichment/tasks/{id}/retry (scope site-enrichment:write)

site-enrichmentsite-enrichment

#969 backfill: count and ids of tenant cards where customFields.site_status='ok' but a real crawl HTTP code was never recorded (customFields.site_status_http is empty). The condition is live (the same as the migration itself), NOT the write-once flag site_needs_recrawl_969 — a card that has already actually been recrawled drops out of the list by itself, with no separate cleanup step. Not retroactive code guessing. site-enrichment.backlog.list

#969 backfill: count and ids of tenant cards where customFields.site_status='ok' but a real crawl HTTP code was never recorded (customFields.site_status_http is empty). The condition is live (the same as the migration itself), NOT the write-once flag site_needs_recrawl_969 — a card that has already actually been recrawled drops out of the list by itself, with no separate cleanup step. Not retroactive code guessing. — GET /api/site-enrichment/backlog/stale-http-status (scope site-enrichment:read)

site-enrichmentsite-enrichment

#969 backfill: a controlled BATCH re-crawl of flagged cards (batchSize, defaults to 50, cap 200) — via the same create()/run() as a normal task enqueue; not a separate crawl engine. site-enrichment.backlog.requeue

#969 backfill: a controlled BATCH re-crawl of flagged cards (batchSize, defaults to 50, cap 200) — via the same create()/run() as a normal task enqueue; not a separate crawl engine. — POST /api/site-enrichment/backlog/stale-http-status/requeue (scope site-enrichment:write)

site-enrichmentsite-enrichment

#1126: count and ids of tenant cards where customFields.site_status='down' AND customFields.site_last_reason is one of a NARROW list of transient failures of OUR OWN infrastructure (currently only 'wait_timeout'), AND customFields.site_status_http is empty (navigation never reached a response). NOT cards with dns_error/tls_error/conn_refused — those are responses FROM THE WORLD about the site, not a failure of our attempt, and are deliberately excluded (see SiteEnrichmentService.TRANSIENT_DOWN_REASONS). The condition is live — a card that has already actually been recrawled drops out of the list by itself. site-enrichment.backlog-down.list

#1126: count and ids of tenant cards where customFields.site_status='down' AND customFields.site_last_reason is one of a NARROW list of transient failures of OUR OWN infrastructure (currently only 'wait_timeout'), AND customFields.site_status_http is empty (navigation never reached a response). NOT cards with dns_error/tls_error/conn_refused — those are responses FROM THE WORLD about the site, not a failure of our attempt, and are deliberately excluded (see SiteEnrichmentService.TRANSIENT_DOWN_REASONS). The condition is live — a card that has already actually been recrawled drops out of the list by itself. — GET /api/site-enrichment/backlog/down-wait-timeout (scope site-enrichment:read)

site-enrichmentsite-enrichment

#1126: a controlled BATCH re-crawl of cards from backlog/down-wait-timeout (batchSize, defaults to 50, cap 200) — via the same create()/run() as a normal task enqueue; not a separate crawl engine, only a real crawl changes a card's status. site-enrichment.backlog-down.requeue

#1126: a controlled BATCH re-crawl of cards from backlog/down-wait-timeout (batchSize, defaults to 50, cap 200) — via the same create()/run() as a normal task enqueue; not a separate crawl engine, only a real crawl changes a card's status. — POST /api/site-enrichment/backlog/down-wait-timeout/requeue (scope site-enrichment:write)

site-enrichmentsite-enrichment

List all marking patterns marking.patterns.list

List all marking patterns — GET /api/marking/patterns (scope marking:read)

markingmarking

Create a new marking pattern marking.patterns.create

Create a new marking pattern — POST /api/marking/patterns (scope marking:write)

markingmarking

Classify a message against the marking patterns marking.classify

Classify a message against the marking patterns — POST /api/marking/classify (scope marking:read)

markingmarking

List all email provider configurations provider-configs.list

List all email provider configurations — GET /api/provider-configs (scope settings:read)

provider-configssettings

Update the terms of service text (SUPER only) legal.update

Update the terms of service text (SUPER only) — PUT /api/legal/terms (scope legal:write)

legallegal

List all legal documents (SUPER only) legal.list

List all legal documents (SUPER only) — GET /api/legal (scope legal:read)

legallegal

Tilda form webhook (disabled — requires authorization, see #193) connectors.tilda.webhook

Tilda form webhook (disabled — requires authorization, see #193) — POST /api/connectors/tilda/webhook (scope connectors:write)

connectorsconnectors

Normalize Russian full name via DaData API connectors.dadata

Normalize Russian full name via DaData API — GET /api/connectors/dadata/name (scope connectors:read)

connectorsconnectors

Account balance (USD) + operation prices (platform_render/audit/audit_failed/send) + topUpUrl. Top-up is only via the personal account; every paid response contains a _billing { operation, cost, balance_after } block. billing.get_balance

Account balance (USD) + operation prices (platform_render/audit/audit_failed/send) + topUpUrl. Top-up is only via the personal account; every paid response contains a _billing { operation, cost, balance_after } block. — GET /api/billing/balance (scope billing:read)

billingbilling

Balance movement journal (billing_ledger): entryType (CHARGE|CREDIT|ADJUSTMENT|REFUND), operation, cost, balance_after, campaignId/recipientId. Also shows background cron-pipeline charges that are absent from HTTP responses. Filters: campaignId, entryType. billing.list_charges

Balance movement journal (billing_ledger): entryType (CHARGE|CREDIT|ADJUSTMENT|REFUND), operation, cost, balance_after, campaignId/recipientId. Also shows background cron-pipeline charges that are absent from HTTP responses. Filters: campaignId, entryType. — GET /api/billing/ledger (scope billing:read)

billingbilling

Create a share link for an entity share.create

Create a share link for an entity — POST /api/share-links (scope share:write)

shareshare

List share links for an entity share.list

List share links for an entity — GET /api/share-links (scope share:read)

shareshare

List exportable columns and groups for an entity exports.columns

List exportable columns and groups for an entity — GET /api/exports/columns (scope exports:read)

exportsexports

Create an export job exports.create

Create an export job — POST /api/exports (scope exports:write)

exportsexports

List my export jobs exports.list

List my export jobs — GET /api/exports (scope exports:read)

exportsexports

Download a completed export file exports.download

Download a completed export file — GET /api/exports/{id}/download (scope exports:read)

exportsexports

Read your own API/MCP call journal — time, MCP tool name, method, path, HTTP status, duration, error, resourceId (object a create call produced), costUsd (mirrors _billing.cost) and correlationId. Scoped to your own tenant; foreign tenantId cannot be requested. #1212: the SDK's own /api-keys/whoami preflight before every tool call is hidden by default — pass includeInternal=true to see it. me.calls

Read your own API/MCP call journal — time, MCP tool name, method, path, HTTP status, duration, error, resourceId (object a create call produced), costUsd (mirrors _billing.cost) and correlationId. Scoped to your own tenant; foreign tenantId cannot be requested. #1212: the SDK's own /api-keys/whoami preflight before every tool call is hidden by default — pass includeInternal=true to see it. — GET /api/me/api-monitor/calls (scope agent:read)

meagent

List ICP tasks with pagination and status filter icp.tasks.list

List ICP tasks with pagination and status filter — GET /api/icp-tasks (scope icp:read)

icpicp

Create a new ICP task icp.tasks.create

Create a new ICP task — POST /api/icp-tasks (scope icp:write)

icpicp

#955 preview list coverage WITHOUT starting a crawl: how many cards, how many have the domain field filled, how many unique domains among them (alias of .../preview on the canonical site-enrichment) icp.scrape.preview

#955 preview list coverage WITHOUT starting a crawl: how many cards, how many have the domain field filled, how many unique domains among them (alias of .../preview on the canonical site-enrichment) — GET /api/icp-tasks/companies/scrape/preview (scope icp:read)

icpicp

#835 status and progress of a site-crawl task. #957 (fix): includeResults=false removes the results field from the response — on large tasks (thousands of cards) the full result list stops fitting in the response and gets in the way of working with the task via MCP; by default results is returned (the old contract), an explicit includeResults=false returns only aggregates (total/processed/ok/down/noSite). To page through the results themselves — GET .../companies/scrape/:taskId/items or the canonical .../site-enrichment/tasks/:id/items. #957 (continued): the response NOW carries a stats key — the same enriched statistics byte-for-byte as the canonical GET .../site-enrichment/tasks/:id/stats (cards AND domains funnel counted separately, breakdown of collected data by field, pace/forecast, launch parameters echoed back — listId/listName/domainField/visitPages/timeoutMs/maxAttempts/mode/surface/startedBy, direct links to the scoring-task card and this same task's journal); this is a legacy route (ldm_icp_scrape_status) that remains available. The canonical ldm_site_enrichment_tasks_* tools exist in the client catalog but may return 403 insufficient_scope. The legacy alias stays available for clients that lack scope for the new tools. icp.scrape.status

#835 status and progress of a site-crawl task. #957 (fix): includeResults=false removes the results field from the response — on large tasks (thousands of cards) the full result list stops fitting in the response and gets in the way of working with the task via MCP; by default results is returned (the old contract), an explicit includeResults=false returns only aggregates (total/processed/ok/down/noSite). To page through the results themselves — GET .../companies/scrape/:taskId/items or the canonical .../site-enrichment/tasks/:id/items. #957 (continued): the response NOW carries a stats key — the same enriched statistics byte-for-byte as the canonical GET .../site-enrichment/tasks/:id/stats (cards AND domains funnel counted separately, breakdown of collected data by field, pace/forecast, launch parameters echoed back — listId/listName/domainField/visitPages/timeoutMs/maxAttempts/mode/surface/startedBy, direct links to the scoring-task card and this same task's journal); this is a legacy route (ldm_icp_scrape_status) that remains available. The canonical ldm_site_enrichment_tasks_* tools exist in the client catalog but may return 403 insufficient_scope. The legacy alias stays available for clients that lack scope for the new tools. — GET /api/icp-tasks/companies/scrape/{taskId} (scope icp:read)

icpicp

#835 cancel a site-crawl task icp.scrape.cancel

#835 cancel a site-crawl task — POST /api/icp-tasks/companies/scrape/{taskId}/cancel (scope icp:write)

icpicp

Get an ICP task by id icp.tasks.get

Get an ICP task by id — GET /api/icp-tasks/{id} (scope icp:read)

icpicp

Update an ICP task icp.tasks.update

Update an ICP task — PATCH /api/icp-tasks/{id} (scope icp:write)

icpicp

Preview the ACTUAL scoring prompt for this task (brief-driven / custom / default) icp.tasks.scoring-prompt

Preview the ACTUAL scoring prompt for this task (brief-driven / custom / default) — GET /api/icp-tasks/{id}/scoring-prompt (scope icp:read)

icpicp

#298/#835 server-side crawl fetcher: enqueued in the background, the response is a taskId immediately. Input is companyIds OR listId (#955, the whole list with no 500-item cap on the request body — SiteEnrichmentService resolves it in full); with an explicit limit, the first limit are taken into work (defaults to 50 for companyIds input), how many were actually enqueued is visible in the queued field. icp.scrape.start

#298/#835 server-side crawl fetcher: enqueued in the background, the response is a taskId immediately. Input is companyIds OR listId (#955, the whole list with no 500-item cap on the request body — SiteEnrichmentService resolves it in full); with an explicit limit, the first limit are taken into work (defaults to 50 for companyIds input), how many were actually enqueued is visible in the queued field. — POST /api/icp-tasks/companies/scrape (scope icp:write)

icpicp

#952 pause a crawl task (alias of .../pause on the canonical site-enrichment) icp.scrape.pause

#952 pause a crawl task (alias of .../pause on the canonical site-enrichment) — POST /api/icp-tasks/companies/scrape/{taskId}/pause (scope icp:write)

icpicp

#952 resume a paused crawl task (alias of .../resume on the canonical site-enrichment) icp.scrape.resume

#952 resume a paused crawl task (alias of .../resume on the canonical site-enrichment) — POST /api/icp-tasks/companies/scrape/{taskId}/resume (scope icp:write)

icpicp

#952 crawl task items with a filter by outcome/reason code (alias of .../items on the canonical site-enrichment) icp.scrape.items

#952 crawl task items with a filter by outcome/reason code (alias of .../items on the canonical site-enrichment) — GET /api/icp-tasks/companies/scrape/{taskId}/items (scope icp:read)

icpicp

Get statistics for an ICP task icp.tasks.stats

Get statistics for an ICP task — GET /api/icp-tasks/{id}/statistics (scope icp:read)

icpicp

List items belonging to an ICP task icp.tasks.items

List items belonging to an ICP task — GET /api/icp-tasks/{id}/items (scope icp:read)

icpicp

LinkedIn integration status (toggle, defaults) linkedin.integration

LinkedIn integration status (toggle, defaults) — GET /api/linkedin/integration (scope linkedin:read)

linkedinlinkedin

Enable/disable the module, kill-switch, defaults linkedin.integration.update

Enable/disable the module, kill-switch, defaults — PATCH /api/linkedin/integration (scope linkedin:write)

linkedinlinkedin

List of LinkedIn accounts (without cookies) linkedin.accounts

List of LinkedIn accounts (without cookies) — GET /api/linkedin/accounts (scope linkedin:read)

linkedinlinkedin

Revoke session (erase cookies) linkedin.account.disconnect

Revoke session (erase cookies) — POST /api/linkedin/accounts/{id}/disconnect (scope linkedin:write)

linkedinlinkedin

List of campaigns linkedin.campaigns

List of campaigns — GET /api/linkedin/campaigns (scope linkedin:read)

linkedinlinkedin

Create a campaign linkedin.campaign.create

Create a campaign — POST /api/linkedin/campaigns (scope linkedin:write)

linkedinlinkedin

Pour leads into a campaign linkedin.campaign.leads

Pour leads into a campaign — POST /api/linkedin/campaigns/{id}/leads (scope linkedin:write)

linkedinlinkedin

List of scenarios linkedin.scenarios

List of scenarios — GET /api/linkedin/scenarios (scope linkedin:read)

linkedinlinkedin

Dashboard: funnel + acceptance/reply-rate linkedin.stats

Dashboard: funnel + acceptance/reply-rate — GET /api/linkedin/stats (scope linkedin:read)

linkedinlinkedin

List all Phantom browser profiles admin.phantom.profiles

List all Phantom browser profiles — GET /api/phantom-browser/profiles (scope admin:read)

adminadmin

Launch a profile on the user's Phantom desktop client admin.phantom.launch

Launch a profile on the user's Phantom desktop client — POST /api/phantom-browser/profiles/{id}/launch (scope admin:write)

adminadmin

List available import templates import.templates

List available import templates — GET /api/import/templates (scope import:read)

importimport

Create a new import task import.tasks.create

Create a new import task — POST /api/import/tasks (scope import:write)

importimport

Import a list from a link (Google Sheets or a direct .csv/.xlsx URL) — the "link -> file" link, does not start the import itself (#805). Response includes suggestedMapping/unmapped (#1058): a proposed column -> field mapping (from the detected template when one matched, or a header-name heuristic otherwise) with a sample value per column, plus the columns nobody could confidently guess. import.from_url

Import a list from a link (Google Sheets or a direct .csv/.xlsx URL) — the "link -> file" link, does not start the import itself (#805). Response includes suggestedMapping/unmapped (#1058): a proposed column -> field mapping (from the detected template when one matched, or a header-name heuristic otherwise) with a sample value per column, plus the columns nobody could confidently guess. — POST /api/import/from-url (scope import:write)

importimport

Get an import task by id import.tasks.get

Get an import task by id — GET /api/import/tasks/{id} (scope import:read)

importimport

Cancel an in-progress import task import.tasks.cancel

Cancel an in-progress import task — POST /api/import/tasks/{id}/cancel (scope import:write)

importimport

List IANA timezones with cities, country, offset utils.timezones

List IANA timezones with cities, country, offset — GET /api/utils/timezones (scope utils:read)

utilsutils

Look up timezone by city or country utils.tz-lookup

Look up timezone by city or country — POST /api/utils/timezone-lookup (scope utils:read)

utilsutils
Documentation
Evidence. Fetched 2026-09-19 from https://api.live-direct-marketing.online/.well-known/agent.json, HTTP 200. The body was saved verbatim and is the sole source for everything on this page — no field is inferred. View the captured card. Providers change what they serve; if this card has moved or changed shape, the provider profile carries the current state as of the last build.

Work with this as data

Every agent card here is available over the APIs.io API and to AI agents over MCP. A2A Agent Cards is not yet its own endpoint on the v1 API. Reach it through catalog search and the tag graph, or the MCP server.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for a2a agent cards

3 MCP tools reach this
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
Search the catalog
curl "https://apis.io/api/v1/search?q=live-direct-marketing-online&limit=10"
Everything under a tag
curl "https://apis.io/api/v1/tags/live-direct-marketing-online"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.