MadeThis API
Business primitives — products, checkout, orders — behind an HTTP API your own coding agent can drive. Bring your own editor, your own agent, and your own hosting; MadeThis handles the money.
Base URL https://api.madethis.com/v1
1. Get a key
Create a headless business at /api-keys and mint a key. Keys are business-scoped and shown exactly once. A headless business provisions nothing — no site, no inbox, no AI co-founder — because you are supplying all three.
2. First call
curl https://api.madethis.com/v1/business \
-H "Authorization: Bearer $MADETHIS_API_KEY"
Every success returns { "data": … }, often alongside hint and next_action — one-line orientation written for agents, so a model can chain the next call without a human reading the docs.
3. Sell something
# Create a product. fileUrl is the deliverable buyers receive.
curl -X POST https://api.madethis.com/v1/products \
-H "Authorization: Bearer $MADETHIS_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"name":"My Guide","priceAmountCents":2900,"fileUrl":"https://…/guide.pdf"}'
# Turn it into a shareable checkout URL.
curl -X POST https://api.madethis.com/v1/checkout-links \
-H "Authorization: Bearer $MADETHIS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"productId":"<id from above>"}'
# Watch for sales.
curl https://api.madethis.com/v1/orders \
-H "Authorization: Bearer $MADETHIS_API_KEY"Idempotency
Send Idempotency-Key on creates. Replaying the identical request returns the original response with Idempotency-Replayed: true instead of writing twice; reusing the key with a different body returns idempotency_conflict. Retry a timed-out create byte-identically and you cannot double-charge yourself a duplicate.
Routes
Ads
| GET | /ads | Ad budget and every campaign, newest first |
| PATCH | /ads/{id}/budget | Change the daily ad budget (business-level; increases are spend-gated) |
| GET | /ads/{id}/insights | Performance for one campaign (checkpointed, lags Meta ~30m) |
| POST | /ads/{id}/pause | Pause a campaign - never gated, always available |
| POST | /ads/interests | Resolve interest names against Meta's targeting catalog |
| POST | /ads/publish | Create and launch a Meta campaign (async; spend-policy gated) |
Business
| GET | /business | Get the authenticated business |
| PATCH | /business | Set checkout return URLs and the unattended-spend policy |
Money
| POST | /checkout-links | Get a shareable checkout URL for an active product |
| GET | /orders | List orders, newest first |
| GET | /orders/{id} | Get one order |
| POST | /orders/{id}/refund | Refund an order, fully or partially (Idempotency-Key required) |
| GET | /payouts | Payout status and onboarding eligibility (Stripe Connect) |
| POST | /payouts/onboarding-link | Start Stripe Connect payout onboarding |
Auth
| POST | /cli-auth/poll | Poll a CLI login pairing for the minted key |
| POST | /cli-auth/start | Begin a CLI login pairing |
Confirmations
| GET | /confirmations | List actions waiting on your confirmation |
| GET | /confirmations/{id} | Get one confirmation, including its stored result once it has executed |
| POST | /confirmations/{id}/confirm | Confirm a parked action — executes it exactly once |
| POST | /confirmations/{id}/reject | Reject a parked action — it will never execute |
Domains
| GET | /domains | List registered domains and the DNS records still required |
| POST | /domains | Register a domain you host yourself; returns its verification record |
| DELETE | /domains/{id} | Unregister a domain (DNS is left untouched) |
| POST | /domains/{id}/verify | Check DNS now and verify ownership |
Email
| GET | /email/inbox | Inbox address and provisioning status |
| POST | /email/inbox | Provision the business inbox (idempotent; still provisioning while DNS verifies) |
| POST | /email/send | Send an email from the business inbox (per-inbox daily cap) |
| GET | /email/threads | List email threads, newest first |
| GET | /email/threads/{id} | Get one thread with its messages, oldest first |
Files
| POST | /files | Get a signed URL to upload a product deliverable |
| POST | /files/complete | Register an uploaded file and get its permanent fileUrl |
Leads
| GET | /leads | List leads, newest first |
| POST | /leads/import | Import your own lead list (per-row rejections, deduped) |
| POST | /leads/search | Search for leads matching an ICP (billed per Apollo enrichment) |
| GET | /sequences | List sequences with send/reply/booked stats and outreach readiness |
| POST | /sequences | Create a cold-email sequence (draft - sends nothing until leads are enrolled) |
| POST | /sequences/{id}/cancel | Cancel a sequence permanently (leads marked exhausted) |
| POST | /sequences/{id}/leads | Enrol leads and start sending (held for confirmation) |
| POST | /sequences/{id}/pause | Pause a sequence (mid-sequence leads keep their place) |
| POST | /sequences/{id}/resume | Resume a paused sequence (held for confirmation) |
Orders
| POST | /orders/{id}/ship | Mark a physical order shipped, with optional tracking |
Products
| GET | /products | List products |
| POST | /products | Create a product (syncs to Stripe when active) |
| GET | /products/{id} | Get one product |
| PATCH | /products/{id} | Update a product (status archived = retire) |
Social
| GET | /social/accounts | Connected social accounts with trust tier, liveness and postability |
| POST | /social/connect | Get a link the owner opens to connect an account (OAuth needs a browser) |
| GET | /social/posts | List social posts, newest first |
| POST | /social/posts | Compose and publish or schedule a social post |
| DELETE | /social/posts/{id} | Cancel a scheduled post before it publishes |
| POST | /social/posts/{id}/retry | Retry a failed or partially published post |
Usage
| GET | /usage | Credit balance and whether writes are currently allowed |
Webhooks
| GET | /webhooks | List webhook endpoints |
| POST | /webhooks | Register a webhook endpoint (secret returned once) |
| DELETE | /webhooks/{id} | Delete a webhook endpoint |
Errors
Stable machine-readable codes, each linking straight to its explanation. See the error reference.
CLI and MCP server
The MadeThis CLI includes a local stdio MCP server for approved developer accounts. It reuses the CLI's business-scoped credential, so a compatible coding agent can call this API without copying a key into its configuration. After authenticating the CLI, run madethis mcp to start the server.
For generated clients and validators, download the MadeThis OpenAPI 3.1 schema.