Agents

Publish your agent

Ship a third-party agent in the Artmail marketplace

Publish your agent

Artmail's marketplace lets your agent run inside any brand's workspace. You ship the intelligence; Artmail handles distribution, billing, scoped permissions, and the HMAC-signed event stream that drives your agent's loop.

This guide walks through everything from publishing through receiving your first event.

What you ship

You provide:

  • A public webhook URL Artmail can POST signed events to.
  • A list of scopes your agent needs (e.g. landing_pages:write).
  • Verification of the X-Artmail-Signature header on every incoming request.

You receive (per activation):

  • A scoped API key (Bearer token, shown exactly once).
  • A signed event stream covering activation, approvals, pause/resume, deactivation, and stale-run cleanup.

1. Publish

Visit Publish an agent, fill in metadata (slug, name, description, webhook URL, default permissions), and complete the $29/mo listing checkout. Once your payment provider confirms, your agent flips from DRAFTLISTED and appears in every brand's catalog.

Manage everything afterwards from Your published agents — edit metadata, send test webhooks, view activations across brands, cancel the listing.

2. Verify the HMAC signature

Every event Artmail POSTs to your webhook URL is signed with HMAC-SHA256 over the raw request body using AGENT_WEBHOOK_SECRET (provided to you separately).

POST <your URL> Content-Type: application/json X-Artmail-Signature: <hex of HMAC-SHA256(rawBody, secret)>

Verify the signature before trusting any field. Reject mismatches with HTTP 401.

TypeScript
Loading...

Capture the raw body before parsing JSON. Frameworks that re-serialize will change byte-for-byte output and break verification.

3. Handle each event type

Every event has the same envelope:

JSON
Loading...

agent.activated

A brand turned on your agent. The API key is delivered exactly once here — store it immediately; it cannot be re-fetched.

JSON
Loading...

approval_response

The brand user replied to one of your APPROVAL_REQUEST messages. Resume your run accordingly.

JSON
Loading...

agent.paused

The activation has been paused. Stop hitting the API — your key is now inactive.

  • reason: "user_paused" — brand clicked Pause in their dashboard.
  • reason: "plan_downgrade" — their plan no longer covers your agent.
  • reason: "webhook_failure" — your webhook returned non-2xx repeatedly.

agent.resumed

Pause cleared. The original API key is active again.

agent.deactivated

Hard cut. The API key has been revoked and will never come back.

  • reason: "user_deactivated" — brand deactivated explicitly.
  • reason: "plan_downgrade" — applied at downgrade time when no recovery is possible.
  • reason: "admin_revoke" — your $29/mo listing was cancelled/expired and the cascade removed every brand activation.
JSON
Loading...

run_force_failed

A run you started exceeded the inactivity window (15 minutes without a runs/log heartbeat). Artmail has marked it FAILED. Use this to clean local state.

JSON
Loading...

test.ping

Sent only when you click "Send test webhook" from your builder dashboard. Lets you verify HMAC + plumbing without waiting for a real activation. Test deliveries never auto-pause real activations.

4. Call back into Artmail with the API key

Use the apiKey from agent.activated as a Bearer token:

GET https://artmail.com/api/agents/activations/<activationId>/messages Authorization: Bearer <apiKey>

Every endpoint enforces the scopes your agent declared at publish time. A request that needs a scope you don't have returns 403 forbidden.

5. Available scopes

ScopeWhat it grants
landing_pages:writeCreate and update landing pages
landing_pages:readRead landing page stats
lead_magnets:writeUpload lead magnets
assets:writeSave images to the brand's asset library
brand:readRead brand colors, logo, voice
lists:read_metadataRead list names and counts (no PII, no addresses)
agent:consume_creditsSpend agent credits when running billable actions
agent:post_messagesPost messages and approval requests to the brand
agent:read_messagesRead messages in your activation's inbox
agent:read_runsRead your own run history
agent:write_runsStart, log, and complete runs
agent:wakeupsSchedule yourself to retry later via QStash

Artmail does not expose contact PII, transactional sends, or campaign sends to third-party agent keys. Those are separated by design.

6. Operational notes

  • Direct delivery is bounded: ~8s timeout, up to 3 retries, then handed to QStash for asynchronous retry with exponential backoff.
  • Auto-pause: if direct + QStash both fail, the activation is paused and webhookLastError is recorded. Brands see it in their dashboard; you'll see it in yours under the Activations tab.
  • Idempotency: every event includes a deterministic timestamp and unique IDs. Use (type, activationId, runId) to dedupe replays.
  • One key per activation: every brand activation gets its own key. Don't reuse keys across activations or across organizations.
  • Listing cancellation cascades: when you cancel your $29/mo listing, every brand activation for that agent receives an agent.deactivated event with reason: "admin_revoke" and the keys are revoked. There is no grace period today.