{
  "description": "Motorical Agent Hub machine twin. Generated from docs-site/data/journeys.yaml plus the live scope catalog — do not hand-edit. Human-readable version: https://docs.motorical.com/agents",
  "coreDefinition": "The email API for developers with multiple projects: one isolated sending stream (a Motor Block) per project.",
  "motorBlock": {
    "canonicalTerm": "Motor Block",
    "definition": "A Motor Block is Motorical's SMTP sending block: one isolated sending stream per project, with its own domain, credentials, limits, logs, webhooks and analytics.",
    "aliases": [
      "SMTP sending block",
      "sending stream",
      "per-project sending stream",
      "email sending project"
    ],
    "nearestEquivalentsAtOtherProviders": [
      "Postmark Servers",
      "SendGrid subusers",
      "Mailgun subaccounts"
    ]
  },
  "scopes": {
    "send:transactional": {
      "resource": "transactional",
      "level": "manage",
      "agentDescription": "Send transactional email through the caller's Motor Block(s)."
    },
    "read:analytics": {
      "resource": "analytics",
      "level": "read",
      "agentDescription": "Read delivery logs, analytics, and usage for the caller's Motor Block(s). Never includes unmasked recipient PII (logs.pii) regardless of what is requested."
    },
    "manage:domains": {
      "resource": "domains",
      "level": "manage",
      "agentDescription": "Add, verify, and read sending domains and their DNS health. Includes everything read:domains grants."
    },
    "manage:motor-blocks": {
      "resource": "motor-blocks",
      "level": "manage",
      "agentDescription": "List and manage the ordinary lifecycle of production Motor Blocks: create, rename, change type, assign domain, deactivate, reactivate, and delete. Includes no credential values and cannot change the active auth method."
    },
    "manage:sandbox": {
      "resource": "sandbox",
      "level": "manage",
      "agentDescription": "Check, provision, and convert the developer sandbox. Sandbox allowlist requests/confirmations additionally require a dashboard session — this scope alone does not make them callable over OAuth."
    },
    "manage:webhooks": {
      "resource": "webhooks",
      "level": "manage",
      "agentDescription": "Create, update, delete, and test webhook endpoints on the caller's Motor Block(s). Includes everything read:webhooks grants."
    },
    "read:webhooks": {
      "resource": "webhooks",
      "level": "read",
      "agentDescription": "List webhook endpoints and read their delivery history and stats, without creating, updating, deleting, or testing any."
    },
    "read:domains": {
      "resource": "domains",
      "level": "read",
      "agentDescription": "List and read sending domains, without adding or verifying any."
    }
  },
  "journeys": [
    {
      "key": "A",
      "audience": "Coding assistant adding email to an app",
      "status": "real",
      "route": "Local server (API keys) or the HTTP API directly",
      "steps": [
        {
          "id": "A1",
          "description": "Get a Motor Block API key (mk_live_...) from the dashboard, or use the developer sandbox for a zero-credential start (see Journey C).",
          "humanRequired": true,
          "sayToHuman": "I need a Motor Block API key from your Motorical dashboard (or we can start with the free sandbox — no account needed yet)."
        },
        {
          "id": "A2",
          "description": "Dry-run the send payload before sending anything real.",
          "tool": "motorical_send_email",
          "endpoint": "POST /v1/send (dryRun: true)",
          "humanRequired": false
        },
        {
          "id": "A3",
          "description": "Remove dryRun (or set it false) to send for real.",
          "tool": "motorical_send_email",
          "endpoint": "POST /v1/send",
          "humanRequired": false
        },
        {
          "id": "A4",
          "description": "Check delivery status/events for a sent message, or wait for a terminal outcome rather than treating a 202 as delivered.",
          "tools": [
            "motorical_get_send_status",
            "motorical_get_message",
            "motorical_get_message_events",
            "motorical_wait_for_outcome"
          ],
          "humanRequired": false
        },
        {
          "id": "A5",
          "description": "Optional: register a webhook so the app learns about deliveries, bounces, and complaints without polling.",
          "tool": "motorical_webhook_create",
          "humanRequired": false,
          "note": "Available on both the local server and hosted OAuth's dedicated webhooks server (read:webhooks/manage:webhooks scopes) — not local-only."
        }
      ]
    },
    {
      "key": "B",
      "audience": "Operator agent running a customer's account over MCP",
      "status": "real",
      "route": "Hosted MCP over OAuth (a person present for consent)",
      "steps": [
        {
          "id": "B1",
          "description": "Connect to the hosted MCP server (main, for a full setup on one consent, or a narrow scoped server for least privilege).",
          "humanRequired": true,
          "sayToHuman": "I'll connect to Motorical over OAuth — you'll see a browser consent screen asking which scopes to grant."
        },
        {
          "id": "B2",
          "description": "Read live account state before acting.",
          "tools": [
            "motorical_get_onboarding_state",
            "motorical_list_motor_blocks"
          ],
          "humanRequired": false
        },
        {
          "id": "B3",
          "description": "Operate within the granted scope — send email, read analytics, manage domains, manage Motor Blocks, or manage webhooks, depending on which scopes were granted.",
          "tools": [
            "motorical_send_email",
            "motorical_get_overview",
            "motorical_get_deliverability",
            "motorical_motor_block_list",
            "motorical_motor_block_create"
          ],
          "humanRequired": false
        },
        {
          "id": "B4",
          "description": "A consequential operation (type change, domain assignment, deactivate, delete) asks for confirmation bound to the exact arguments shown — never assume consent carries to different arguments.",
          "tools": [
            "motorical_motor_block_change_type",
            "motorical_motor_block_assign_domain",
            "motorical_motor_block_deactivate",
            "motorical_motor_block_delete"
          ],
          "humanRequired": true,
          "sayToHuman": "This is a consequential change (e.g. permanently deleting a Motor Block) — confirming means exactly this action, nothing broader.",
          "stopCondition": "Deactivate is reversible; delete is not. Never treat them as interchangeable, and never skip the confirmation step."
        }
      ]
    },
    {
      "key": "C",
      "audience": "Agent whose human has no account",
      "status": "real",
      "route": "signup server, then Journey B",
      "steps": [
        {
          "id": "C1",
          "description": "Call the unauthenticated signup server's one tool — no Motorical account or credential needed yet.",
          "tool": "motorical_signup_handoff",
          "humanRequired": false
        },
        {
          "id": "C2",
          "description": "Hand the returned one-time URL to the human — it runs signup and OAuth consent in the same browser visit. No credential of any kind is ever returned to the agent.",
          "humanRequired": true,
          "sayToHuman": "Open this link to create your Motorical account and grant access — I never see or hold your credentials."
        },
        {
          "id": "C3",
          "description": "Continue as Journey B — the OAuth grant from consent is usable immediately, no separate step needed. The account starts on the unpaid developer sandbox (outbound-locked to an allowlist).",
          "humanRequired": false
        },
        {
          "id": "C4",
          "description": "To send in production, convert the sandbox Motor Block onto a domain the human owns. motorical_sandbox_convert requires an active Motorical plan — it throws subscription_required with err.data.upgradeUrl if none exists yet; retry the same call once the human has subscribed.",
          "tool": "motorical_sandbox_convert",
          "humanRequired": true,
          "sayToHuman": "To move off the sandbox onto your own domain, you'll need an active Motorical plan — here's the link to subscribe.",
          "stopCondition": "motorical_sandbox_convert fails closed with subscription_required until the human subscribes; there is no agent-side workaround."
        },
        {
          "id": "C5",
          "description": "Add the domain and complete DNS verification before any production send is possible.",
          "tools": [
            "motorical_domain_add",
            "motorical_domain_verify",
            "motorical_domain_check_dns"
          ],
          "humanRequired": true,
          "sayToHuman": "Add these DNS records at your domain registrar, then let me know once they're live so I can verify them.",
          "stopCondition": "A domain is not sendReady until DKIM and SPF are both configured — the human must publish the DNS records before send works."
        }
      ]
    }
  ]
}
