Every error response follows the same envelope:
"type" : " https://docs.ampout.dev/errors/<code> " ,
code is the only thing your client should branch on — message is human-readable and may change. The HTTP status is determined by the code; both are documented below.
Code Status Fires when unauthorized401 Missing, malformed, or revoked API key. not_found404 Generic fallback for resources without a dedicated code. validation_failed422 Model validation failed. message carries the validator’s full message. unprocessable422 Request was syntactically valid but couldn’t be processed (e.g., business-rule violation). bad_request400 Malformed request. rate_limited429 Exceeded the per-key (60/min) or per-IP signup throttle. Includes Retry-After.
These all return 404 . They’re semantically equivalent to not_found but emit distinct codes so your client can branch precisely.
Code Resource campaign_not_foundCampaign contact_not_foundContact contact_import_not_foundContactImport outreach_not_foundOutreach smtp_credential_not_foundSmtpCredential api_key_not_foundApiKey webhook_not_foundWebhook plan_not_foundPlan
Code Status Fires when no_pending_enrollments422 POST /campaigns/:id/dispatch and there’s nothing to dispatch.campaign_not_active422 POST /campaigns/:id/pause on a non-active campaign.campaign_not_paused422 POST /campaigns/:id/resume on a non-paused campaign.contact_already_enrolled422 POST /campaigns/:id/enroll_contact and the contact already has an enrollment.no_emails_provided422 POST /campaigns/:id/test_send without any emails.no_contacts_provided422 POST /contact_imports without any contacts.
Code Status Fires when plan_limit_reached402 Account has reached its plan’s monthly send limit. details includes current_period_sends, monthly_limit, plan_slug. plan_required402 (Reserved for paid-only features in the future.) feature_not_in_plan402 (Reserved for paid-only features in the future.) plan_not_purchasable422 POST /billing/checkout for a free or private plan.no_stripe_customer422 POST /billing/portal or /checkout and the account has no Stripe customer (signed up before Stripe was wired).
Code Status Fires when cannot_revoke_last_key422 DELETE /api_keys/:id would leave the account with zero active keys.
Code Status Fires when invalid_signature401 POST /webhooks/stripe HMAC signature verification fails. (Inbound only — your outbound webhook receiver is responsible for its own signature checks.)
Code Status Fires when idempotency_conflict409 Same Idempotency-Key reused with a different request body.
Content-Type : application/json
"code" : " campaign_not_found " ,
"type" : " https://docs.ampout.dev/errors/campaign_not_found " ,
"message" : " Campaign not found "
HTTP / 1.1 422 Unprocessable Content
Content-Type : application/json
"code" : " validation_failed " ,
"type" : " https://docs.ampout.dev/errors/validation_failed " ,
"message" : " Name can't be blank, Min wait seconds must be greater than or equal to 0 "
HTTP / 1.1 402 Payment Required
Content-Type : application/json
"code" : " plan_limit_reached " ,
"type" : " https://docs.ampout.dev/errors/plan_limit_reached " ,
"message" : " Plan send limit reached for the current period " ,
"current_period_sends" : 5000 ,
HTTP / 1.1 429 Too Many Requests
Content-Type : application/json
"type" : " https://docs.ampout.dev/errors/rate_limited " ,
"message" : " Too many requests. Slow down and retry after the period resets. " ,
"details" : { "limit" : 60 , "period" : 60 }