Skip to content

Lead and newsletter contracts

Status: Live Updated: 2026-09-30 Verified against: ecosystem cecd4003

POST https://paintaire.com/api/leads and POST https://paintaire.com/api/subscribe are the routes behind Paintaire’s public forms. Browser forms and agents reach the same rules: the Agent API validates with these bounds and submits through /api/leads. AI agents should use the Agent API, which adds a previewed, user-confirmed, idempotent step, rather than posting to /api/leads directly.

Encodings

Both routes accept JSON (Content-Type: application/json, a flat object of string values) and native form posts (application/x-www-form-urlencoded or multipart/form-data). On /api/leads file uploads are rejected: a multipart file part returns 400. /api/subscribe ignores file parts (and any other non-string value) and processes the text fields. Both routes treat a filled bot-field honeypot as success and forward nothing; leave it empty. Successful JSON requests return { "ok": true } with 200; successful native form posts return 303 to /thank-you. Upstream statuses and bodies are never passed through.

Leads: POST /api/leads

Every form needs a valid email. The form field selects the form; a missing or unrecognized value is treated as newsletter, which needs only the email and is filed as a subscriber, not a sales lead. Prefer /api/subscribe for newsletter signups.

form Required besides email Optional
homeowner_quote name, postal_code phone, project_type, timeline, message
contractor_signup name, company phone, company_size, message
contact name, subject, message phone

Every homeowner lead is routed to the one contractor currently on the platform; the caller cannot choose a recipient.

Limits

Newsletter: POST /api/subscribe

Field Rule
email Required, valid address, at most 254 characters; lower-cased
privacy Required consent: on, true, yes or 1. The consent time is recorded
contractor Optional lowercase slug of the site the person signed up through; lower-cased; anything else becomes direct

A non-string JSON value on /api/leads returns 400, while /api/subscribe ignores it; native form bodies over 8,000 bytes are refused with 413. The route has its own rate-limit bucket (five per client address per 15 minutes, separate from /api/leads). A confirmation email is sent to the subscriber. Subscribing an address already on the list returns the same success, so the route cannot be used to test membership.

Responses

Applies to both routes unless noted. JSON errors are { "error": "<message>" }; native form errors are a short HTML page.

Status Meaning
200 Accepted (JSON requests)
303 Accepted (native form posts); redirects to /thank-you
400 Invalid JSON or body, invalid email, missing required field (fields lists them), field over its bound, non-string JSON value or file upload (/api/leads only), or missing consent (subscribe)
413 Native form body or value too large
429 Rate limit exceeded; honor Retry-After
502 The upstream service could not confirm the submission
503 Submissions are not configured on this deployment

Human page: https://paintaire.com/developers/leads