Menu

curl & MCP

Raw HTTP + MCP stdio configuration for Claude Code, Cursor, and Codex. Create endpoints at https://api.gopigeon.dev/new — no auth required.

One-liner

# 1. Create an endpoint (no auth)
curl -X POST https://api.gopigeon.dev/new -d '[email protected]'
# → {"endpoint_url":"https://api.gopigeon.dev/f/f_abc123def456xyz0","form_id":"f_abc123def456xyz0","unclaimed":true,"claim_note":"..."}

# 2. Submit to that endpoint
curl -X POST https://api.gopigeon.dev/f/f_abc123def456xyz0 \
  -d 'name=Jane&[email protected]&message=hello'
# → {"ok":true,"submission_id":"sub_..."}

How it works

The first curl creates an endpoint and returns a JSON payload with the live endpoint_url. The second curl submits to that URL. No auth required; the recipient email passed at creation time is where the claim link lands once a real submission arrives.

Every response is a plain JSON body (no wrapper envelope). 201 on creation, 200 on submission, 303 when a redirect_url is configured. Errors return a JSON body with an error key plus the HTTP status — see the Errors page for the full list.

Dry-run mode

Dry-run is a routing preview, not a sandbox. Append ?dry_run=1 to any submission URL and the handler runs the full request path — CORS check, honeypot, rate limit, quota read — but emits zero side effects: no submission row, no claim email, no funnel event, no quota counter increment, no AMQP publish. The response is a 200 with a JSON preview showing where the submission would have gone. Sends nothing. Use it to verify wiring before publishing your form to real users.

Contrast with sandbox mode (Mailgun-style): gopigeon has no sandbox tier. There is no test-mode inbox. Dry-run runs the live request path against the live form record and returns a preview; it does not deliver anywhere.

curl -X POST "https://api.gopigeon.dev/f/${FORM_ID}?dry_run=1" \
  -H "Content-Type: application/json" \
  -d '{"name":"Ada","email":"[email protected]","message":"hi"}'

Returns 200 with this shape:

{
  "dry_run": true,
  "would_route_to": [
    {"kind": "email", "target_hint": "u***@example.com"}
  ],
  "claim_status": {
    "claimed": false,
    "claim_email_recipient_hint": "u***@example.com"
  },
  "validations_passed": ["honeypot", "rate_limit", "cors"],
  "would_have_counted": {
    "quota_used": 12,
    "quota_remaining": 488,
    "period_resets_at": "2026-06-01T00:00:00.000Z"
  }
}

would_route_to is an array because forms can fan out to multiple destinations after claiming. target_hint is a redacted preview (e.g. u***@example.com) — never the full address. would_have_counted shows the quota state your submission would have moved to; the live quota counter is unchanged.

The same flag works on queue publish: POST /q/${QUEUE_ID}/publish?dry_run=1 returns a preview without enqueuing an envelope.

Claim-status probe

Before sending your first real submission, verify the endpoint exists and check claim state without burning the one-shot claim event:

curl "https://api.gopigeon.dev/f/${FORM_ID}/status"

Returns 200 with no PII:

{"exists": true, "claimed": false, "active": true}

Returns 404 if the form doesn’t exist. The same /status suffix works for queues: GET /q/${QUEUE_ID}/status. No auth required. No submission counts. No recipient email. Use this to chain create_endpoint → probe → dry-run → real submission from an agent loop.

Dry-run and probe are free for all tiers and never count toward the 50/mo form quota or the 100/mo queue quota. Hammer them in CI without worry — there's a separate 60/min/IP rate limit so a flood test doesn't exhaust your real-submission rate-limit bucket.

Claude Code install

# Anonymous mode — exposes create_endpoint only
claude mcp add --transport stdio gopigeon -- npx -y @gopigeon/mcp@^0.1.0

# With API key for get_submissions + list_endpoints
claude mcp add --transport stdio --env GOPIGEON_API_KEY=YOUR_KEY gopigeon -- npx -y @gopigeon/mcp@^0.1.0

Cursor / generic JSON config

{
  "mcpServers": {
    "gopigeon": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@gopigeon/mcp@^0.1.0"],
      "env": { "GOPIGEON_API_KEY": "${GOPIGEON_API_KEY}" }
    }
  }
}

Owned mode

Set GOPIGEON_API_KEY (generate one in the dashboard) and create_endpoint routes to OWNED mode automatically — no claim email, no trial TTL, no 30-day expiry. The owned path calls POST /api/forms with Bearer auth and skips the anonymous claim handshake entirely.

For multi-destination endpoints, supply a destinations array at creation time:

{
  "name": "My endpoint",
  "destinations": [
    {"type": "managed-email", "to": "[email protected]"},
    {"type": "webhook", "url": "https://example.com/hook"}
  ]
}

Once created, manage the endpoint with the sibling MCP tools: update_endpoint (name / redirect URL / allowed origins / active flag), add_destination, list_destinations, remove_destination. See /docs/destinations for destination type options.

The email you passed as recipient above gets a one-click claim link on the first real submission — that is how you become the authenticated owner. See the claim flow for the full sequence.

Useful flags

  • redirect_url — after claiming, set this in the dashboard to send submitters to a thank-you page (HTTP 303). Without it, the response body is raw JSON.
  • _gotcha — reserved honeypot field name. Drop <input name="_gotcha" tabindex="-1" style="position:absolute;left:-9999px" aria-hidden="true"> in your form. Any submission where _gotcha is non-empty is silently dropped as spam.
  • allowed_origins — defaults to *. After claiming, lock down to a comma-separated list of HTTPS origins on the endpoint’s dashboard page.

Not what you're looking for? See the full surface at /llms.txt.