{"openapi":"3.1.1","info":{"title":"Paintaire marketplace API","version":"2026-09-01","description":"Shared-layer routes: agent discovery, previewed and confirmed actions, and the public lead and newsletter forms. Contractor-specific services are not described here."},"servers":[{"url":"https://paintaire.com"}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer"}}},"paths":{"/.well-known/paintaire-agent.json":{"get":{"operationId":"getAgentManifest","summary":"Agent manifest","responses":{"200":{"description":"Versioned agent manifest.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}}}}},"/api/agent/manifest":{"get":{"operationId":"getAgentManifestAlias","summary":"Agent manifest (alias of the well-known document)","responses":{"200":{"description":"Versioned agent manifest.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}}}}},"/api/agent/content":{"get":{"operationId":"getAgentContent","summary":"Resource index, or one Markdown resource","parameters":[{"name":"resource","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Resource index, or the selected resource with its Markdown content.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"404":{"description":"Unknown resource.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string"}},"additionalProperties":true}}}}}}},"/api/agent/actions/{action}/preview":{"post":{"operationId":"previewAgentAction","summary":"Preview an action","description":"Validates the fields and returns a signed preview_id, the normalized fields, the destination and the exact confirmation statement. Requires scope lead:preview.","security":[{"bearer":[]}],"parameters":[{"name":"action","in":"path","required":true,"schema":{"type":"string","enum":["homeowner_quote","contractor_signup","contact","newsletter"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"anyOf":[{"title":"homeowner_quote","type":"object","required":["name","email","postal_code"],"properties":{"name":{"type":"string","maxLength":2000},"email":{"type":"string","maxLength":2000},"postal_code":{"type":"string","maxLength":2000},"phone":{"type":"string","maxLength":2000},"project_type":{"type":"string","maxLength":2000},"timeline":{"type":"string","maxLength":2000},"message":{"type":"string","maxLength":2000}},"additionalProperties":true},{"title":"contractor_signup","type":"object","required":["name","email","company"],"properties":{"name":{"type":"string","maxLength":2000},"email":{"type":"string","maxLength":2000},"company":{"type":"string","maxLength":2000},"phone":{"type":"string","maxLength":2000},"company_size":{"type":"string","maxLength":2000},"message":{"type":"string","maxLength":2000}},"additionalProperties":true},{"title":"contact","type":"object","required":["name","email","subject","message"],"properties":{"name":{"type":"string","maxLength":2000},"email":{"type":"string","maxLength":2000},"subject":{"type":"string","maxLength":2000},"message":{"type":"string","maxLength":2000},"phone":{"type":"string","maxLength":2000}},"additionalProperties":true},{"title":"newsletter","type":"object","required":["email"],"properties":{"email":{"type":"string","maxLength":2000}},"additionalProperties":true}]}}}},"responses":{"200":{"description":"Preview created.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid JSON, field or missing required field.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string"}},"additionalProperties":true}}}},"401":{"description":"Missing or invalid bearer credential.","headers":{"WWW-Authenticate":{"description":"The Bearer challenge.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string"}},"additionalProperties":true}}}},"403":{"description":"Credential lacks the lead:preview scope.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string"}},"additionalProperties":true}}}},"404":{"description":"Unknown action.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string"}},"additionalProperties":true}}}},"429":{"description":"Rate limit exceeded.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string"}},"additionalProperties":true}}}},"503":{"description":"Agent execution or preview signing is not configured.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string"}},"additionalProperties":true}}}}}}},"/api/agent/actions/{action}/execute":{"post":{"operationId":"executeAgentAction","summary":"Execute a previewed action after user confirmation","description":"Requires scope lead:create. confirmation_text must equal exactly: I confirm that Paintaire may use these details for the selected action.","security":[{"bearer":[]}],"parameters":[{"name":"action","in":"path","required":true,"schema":{"type":"string","enum":["homeowner_quote","contractor_signup","contact","newsletter"]}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["preview_id","confirmation","confirmation_text"],"properties":{"preview_id":{"type":"string"},"confirmation":{"const":true},"confirmation_text":{"const":"I confirm that Paintaire may use these details for the selected action."}}}}}},"responses":{"200":{"description":"Submitted, or replayed from a prior identical request.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid JSON; invalid or expired preview token (a token that is not exactly `<payload>.<signature>` is invalid); missing Idempotency-Key; or action mismatch.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string"}},"additionalProperties":true}}}},"401":{"description":"Missing or invalid bearer credential.","headers":{"WWW-Authenticate":{"description":"The Bearer challenge.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string"}},"additionalProperties":true}}}},"403":{"description":"Credential lacks the lead:create scope.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string"}},"additionalProperties":true}}}},"404":{"description":"Unknown action.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string"}},"additionalProperties":true}}}},"409":{"description":"Confirmation missing or not exact; execution in progress; preview already used; or idempotency key reused with a different preview.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string"}},"additionalProperties":true}}}},"429":{"description":"Rate limit exceeded.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string"}},"additionalProperties":true}}}},"502":{"description":"Upstream failed or could not confirm the submission, including replay of a failed execution.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string"}},"additionalProperties":true}}}},"503":{"description":"Execution not configured or receipt storage unavailable.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string"}},"additionalProperties":true}}}},"4XX":{"description":"Other 4xx: the upstream rejected the submission; its status is passed through.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string"}},"additionalProperties":true}}}}}}},"/api/leads":{"post":{"operationId":"submitLead","summary":"Submit a lead form","description":"Browser-form route. AI agents should use the preview and execute routes instead. The form field selects the form; a missing or unrecognized value is treated as newsletter.","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"title":"homeowner_quote","type":"object","required":["form","name","email","postal_code"],"properties":{"form":{"const":"homeowner_quote"},"name":{"type":"string","maxLength":2000},"email":{"type":"string","maxLength":2000},"postal_code":{"type":"string","maxLength":2000},"phone":{"type":"string","maxLength":2000},"project_type":{"type":"string","maxLength":2000},"timeline":{"type":"string","maxLength":2000},"message":{"type":"string","maxLength":2000}},"additionalProperties":true},{"title":"contractor_signup","type":"object","required":["form","name","email","company"],"properties":{"form":{"const":"contractor_signup"},"name":{"type":"string","maxLength":2000},"email":{"type":"string","maxLength":2000},"company":{"type":"string","maxLength":2000},"phone":{"type":"string","maxLength":2000},"company_size":{"type":"string","maxLength":2000},"message":{"type":"string","maxLength":2000}},"additionalProperties":true},{"title":"contact","type":"object","required":["form","name","email","subject","message"],"properties":{"form":{"const":"contact"},"name":{"type":"string","maxLength":2000},"email":{"type":"string","maxLength":2000},"subject":{"type":"string","maxLength":2000},"message":{"type":"string","maxLength":2000},"phone":{"type":"string","maxLength":2000}},"additionalProperties":true},{"title":"newsletter","description":"`form` absent, `newsletter`, or any value other than the lead forms.","type":"object","required":["email"],"properties":{"form":{"not":{"enum":["homeowner_quote","contractor_signup","contact"]}},"email":{"type":"string","maxLength":2000}},"additionalProperties":true}]}},"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["email"],"properties":{"form":{"type":"string","description":"One of homeowner_quote, contractor_signup, contact or newsletter; missing or unrecognized is newsletter."},"name":{"type":"string","maxLength":2000},"email":{"type":"string","maxLength":2000},"postal_code":{"type":"string","maxLength":2000},"phone":{"type":"string","maxLength":2000},"project_type":{"type":"string","maxLength":2000},"timeline":{"type":"string","maxLength":2000},"message":{"type":"string","maxLength":2000},"company":{"type":"string","maxLength":2000},"company_size":{"type":"string","maxLength":2000},"subject":{"type":"string","maxLength":2000}}}},"multipart/form-data":{"schema":{"type":"object","required":["email"],"properties":{"form":{"type":"string","description":"One of homeowner_quote, contractor_signup, contact or newsletter; missing or unrecognized is newsletter."},"name":{"type":"string","maxLength":2000},"email":{"type":"string","maxLength":2000},"postal_code":{"type":"string","maxLength":2000},"phone":{"type":"string","maxLength":2000},"project_type":{"type":"string","maxLength":2000},"timeline":{"type":"string","maxLength":2000},"message":{"type":"string","maxLength":2000},"company":{"type":"string","maxLength":2000},"company_size":{"type":"string","maxLength":2000},"subject":{"type":"string","maxLength":2000}}}}}},"responses":{"200":{"description":"Accepted (JSON requests).","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true}}}}}},"303":{"description":"Accepted (native form posts); redirects to the thank-you page.","headers":{"Location":{"schema":{"type":"string"}}}},"400":{"description":"Invalid body, invalid email, missing or over-long field, or missing consent.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string"}},"additionalProperties":true}}}},"413":{"description":"Native form body or value too large.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string"}},"additionalProperties":true}}}},"429":{"description":"Rate limit exceeded.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string"}},"additionalProperties":true}}}},"502":{"description":"The upstream service could not confirm the submission.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string"}},"additionalProperties":true}}}},"503":{"description":"Submissions are not configured on this deployment.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string"}},"additionalProperties":true}}}}}}},"/api/subscribe":{"post":{"operationId":"subscribeNewsletter","summary":"Subscribe to the newsletter","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email","privacy"],"properties":{"email":{"type":"string","maxLength":254},"privacy":{"type":"string","description":"Consent: on, true, yes or 1."},"contractor":{"type":"string","description":"Lowercase slug of the originating site; anything else becomes direct."}},"additionalProperties":true}},"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["email","privacy"],"properties":{"email":{"type":"string","maxLength":254},"privacy":{"type":"string","description":"Consent: on, true, yes or 1."},"contractor":{"type":"string","description":"Lowercase slug of the originating site; anything else becomes direct."}}}},"multipart/form-data":{"schema":{"type":"object","required":["email","privacy"],"properties":{"email":{"type":"string","maxLength":254},"privacy":{"type":"string","description":"Consent: on, true, yes or 1."},"contractor":{"type":"string","description":"Lowercase slug of the originating site; anything else becomes direct."}}}}}},"responses":{"200":{"description":"Accepted (JSON requests).","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true}}}}}},"303":{"description":"Accepted (native form posts); redirects to the thank-you page.","headers":{"Location":{"schema":{"type":"string"}}}},"400":{"description":"Invalid body, invalid email, missing or over-long field, or missing consent.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string"}},"additionalProperties":true}}}},"413":{"description":"Native form body or value too large.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string"}},"additionalProperties":true}}}},"429":{"description":"Rate limit exceeded.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string"}},"additionalProperties":true}}}},"502":{"description":"The upstream service could not confirm the submission.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string"}},"additionalProperties":true}}}},"503":{"description":"Submissions are not configured on this deployment.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string"}},"additionalProperties":true}}}}}}}}}