{"openapi":"3.1.0","info":{"title":"Treatyway","version":"0.2.0","description":"Search unclaimed Bay Area businesses. A request is recorded. No live email is sent. English. REST phone is E.164, for example +14155550100. phone_display is the local format, such as (415) 555-0100. MCP phone still uses the display format. Request status:\n\n| Status | Meaning |\n| --- | --- |\n| sandbox_queued | Demo listing, or a test listing with no connected channel. Nothing is emailed. A buyer follow-up on that path stays sandbox_queued. |\n| dry_run | Real listing with a contact email, and outbound email is off. The request is recorded and nothing is sent. |\n| not_deliverable_by_email | Real listing with no contact email. Nothing is sent. |\n| invalid_recipient | The contact address is not a usable email. Nothing is sent. |\n| opted_out | The address has opted out. Nothing is sent. |\n| recorded | The channel is OpenAPI or MCP, which Treatyway does not call, or a test webhook that is not the sandbox echo. Nothing is emailed. |\n| delivered | The signed webhook POST was accepted (HTTP 2xx). |\n| failed | The signed webhook POST failed after the retries. |\n| pending_send | Outbound email is on and the message is queued. |\n| daily_cap | Outbound email is on and the daily sending cap is reached. Nothing is sent. |\n| not_configured | Outbound email is on and no email provider is configured. Nothing is sent. |\n| sent | Treatyway sent the email. |\n| provider_error | The email provider did not accept the message. |\n| cancelled | The requester cancelled the request. |\n| replied | The business replied, by the business-key reply, a sandbox supplier reply, or an inbound email. This replaces the previous status, including delivered and failed. A later buyer follow-up is still delivered when a webhook is connected, and the status stays replied. |"},"servers":[{"url":"https://treatyway.com"}],"paths":{"/health":{"get":{"summary":"Health","responses":{"200":{"description":"ok"}}}},"/api/businesses":{"get":{"summary":"Search businesses","parameters":[{"name":"q","in":"query","schema":{"type":"string","maxLength":300}},{"name":"category","in":"query","schema":{"type":"string"},"description":"Label or slug, any case."},{"name":"city","in":"query","schema":{"type":"string"}},{"name":"county","in":"query","schema":{"type":"string"}},{"name":"near","in":"query","schema":{"type":"string"},"description":"City center. Distance uses the recorded city."},{"name":"contactable","in":"query","schema":{"type":"boolean"}},{"name":"channel","in":"query","schema":{"type":"string"},"description":"email or information. inquiry means email."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":20}},{"name":"offset","in":"query","schema":{"type":"integer","minimum":0,"maximum":10000}},{"name":"cursor","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"A page of listings","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchPage"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The directory is busy with an update. The body is {detail}. Wait and retry the same call.","headers":{"Retry-After":{"schema":{"type":"string","example":"5"},"description":"Seconds to wait."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/businesses/{business_id}":{"get":{"summary":"One business","parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string"},"description":"Full id or a unique ba- prefix."}],"responses":{"200":{"description":"record"},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"410":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The directory is busy with an update. The body is {detail}. Wait and retry the same call.","headers":{"Retry-After":{"schema":{"type":"string","example":"5"},"description":"Seconds to wait."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/businesses/{business_id}/documents/{document_id}":{"get":{"summary":"One document","parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string"}},{"name":"document_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"document"},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/workspaces":{"post":{"summary":"Create a workspace key. The key is in the JSON body only. This route does not set a cookie.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceInput"}}}},"responses":{"201":{"description":"Key, shown once. No Set-Cookie."},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/workspace":{"get":{"summary":"Current workspace, including trust tier","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"workspace"},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"summary":"Delete this workspace and its requests","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"deleted"},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/workspace/upgrade":{"post":{"summary":"Raise the trust tier without a new key","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceInput"}}}},"responses":{"200":{"description":"workspace"},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/requests":{"post":{"summary":"Record a request. A connected webhook is signed and delivered. Otherwise nothing is emailed. idempotency_key is 8 to 100 characters.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["business_id","category","subject","message","idempotency_key","authorized"],"properties":{"business_id":{"type":"string"},"category":{"type":"string","enum":["information","quotation"]},"subject":{"type":"string"},"message":{"type":"string"},"idempotency_key":{"type":"string","minLength":8,"maxLength":100,"description":"8 to 100 characters."},"authorized":{"type":"boolean"},"quantity":{"type":["integer","null"]},"destination":{"type":"string"}}}}}},"responses":{"201":{"description":"recorded"},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The directory is busy with an update. The body is {detail}. Wait and retry the same call.","headers":{"Retry-After":{"schema":{"type":"string","example":"5"},"description":"Seconds to wait."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"summary":"List requests for this workspace","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"requests"},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/requests/{request_id}":{"get":{"summary":"One request","security":[{"bearerAuth":[]}],"parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"request"},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/requests/{request_id}/messages":{"post":{"summary":"Add a message","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"recorded"},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/requests/{request_id}/cancel":{"post":{"summary":"Cancel a request. History is kept.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"cancelled"},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/mcp":{"post":{"summary":"MCP Streamable HTTP. A missing or rejected key is a JSON-RPC tool error (isError) with HTTP 200, not an HTTP 401. Send the key only as Authorization: Bearer.","responses":{"200":{"description":"JSON-RPC"},"503":{"description":"The directory is busy with an update. The body is {detail}. Wait and retry the same call.","headers":{"Retry-After":{"schema":{"type":"string","example":"5"},"description":"Seconds to wait."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"options":{"summary":"CORS preflight","responses":{"204":{"description":"CORS"}}}},"/api/businesses/{business_id}/claim":{"post":{"summary":"Store one claim token and return it. A new token revokes earlier unused tokens. It expires in 24 hours. Does not email, call, or text the business. 8 per hour per client IP and 48 per hour per business. ba-treatyway-0000 is not exempt.","security":[],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"201":{"description":"The token, shown once. ba-treatyway-0000 also sends X-RateLimit-Limit and X-RateLimit-Remaining for the IP bucket (8/hour) and X-RateLimit-Limit-Business and X-RateLimit-Remaining-Business for the business bucket (48/hour). Other listings omit those headers. The listing is not exempt from the limit.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"IP bucket limit. Present only for ba-treatyway-0000."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"IP bucket remaining this hour. Present only for ba-treatyway-0000."},"X-RateLimit-Limit-Business":{"schema":{"type":"integer"},"description":"Business bucket limit. Present only for ba-treatyway-0000."},"X-RateLimit-Remaining-Business":{"schema":{"type":"integer"},"description":"Business bucket remaining this hour. Present only for ba-treatyway-0000."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClaimToken"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The directory is busy with an update. The body is {detail}. Wait and retry the same call.","headers":{"Retry-After":{"schema":{"type":"string","example":"5"},"description":"Seconds to wait."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/businesses/{business_id}/claim/verify":{"post":{"summary":"Check a DNS TXT record or a well-known file, then show a business key once. method is dns or well_known. key_reissued is false on the first key. Proving the domain again while a key is active issues a new key, revokes the old one, and sets key_reissued to true. verification_audits.evidence records key_reissued.","security":[],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClaimVerifyRequest"}}}},"responses":{"200":{"description":"Verified. business_key and signing_secret are shown once. key_reissued is false unless a prior active key was revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClaimVerifyResult"}}}},"401":{"description":"Unknown claim token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"detail":"Unknown claim token."}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Empty body, a token shorter than 16 characters, a bad method, an expired or replaced token, or the domain check did not find the token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The directory is busy with an update. The body is {detail}. Wait and retry the same call.","headers":{"Retry-After":{"schema":{"type":"string","example":"5"},"description":"Seconds to wait."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/businesses/{business_id}/channel":{"put":{"summary":"Connect a webhook, OpenAPI, or MCP channel on the verified domain. Authorization: Bearer business key.","security":[{"bearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelInput"}}}},"responses":{"200":{"description":"Connected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelResult"}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The directory is busy with an update. The body is {detail}. Wait and retry the same call.","headers":{"Retry-After":{"schema":{"type":"string","example":"5"},"description":"Seconds to wait."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/businesses/{business_id}/channel/disable":{"post":{"summary":"Turn the connected channel off. Authorization: Bearer business key. Body is an empty object.","security":[{"bearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmptyObject"}}}},"responses":{"200":{"description":"Disabled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelDisabled"}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The directory is busy with an update. The body is {detail}. Wait and retry the same call.","headers":{"Retry-After":{"schema":{"type":"string","example":"5"},"description":"Seconds to wait."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/businesses/{business_id}/unclaim":{"post":{"summary":"Unclaim the listing. Authorization: Bearer business key. Body is an empty object.","security":[{"bearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmptyObject"}}}},"responses":{"200":{"description":"Unclaimed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Unclaimed"}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The directory is busy with an update. The body is {detail}. Wait and retry the same call.","headers":{"Retry-After":{"schema":{"type":"string","example":"5"},"description":"Seconds to wait."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/businesses/{business_id}/rotate-key":{"post":{"summary":"Rotate the business key. Authorization: Bearer business key. Body is an empty object.","security":[{"bearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmptyObject"}}}},"responses":{"200":{"description":"The new key and signing secret, shown once.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RotatedKey"}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The directory is busy with an update. The body is {detail}. Wait and retry the same call.","headers":{"Retry-After":{"schema":{"type":"string","example":"5"},"description":"Seconds to wait."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/businesses/{business_id}/requests/{request_id}/reply":{"post":{"summary":"Reply to a request as the business. Authorization: Bearer business key. idempotency_key is required and is 8 to 100 characters. The request status becomes replied.","security":[{"bearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string"}},{"name":"request_id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessReply"}}}},"responses":{"200":{"description":"The request, including the verified reply."},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The directory is busy with an update. The body is {detail}. Wait and retry the same call.","headers":{"Retry-After":{"schema":{"type":"string","example":"5"},"description":"Seconds to wait."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/sandbox/echo":{"get":{"summary":"Last signed delivery for the active ba-treatyway-0000 claim. Authorization: Bearer with that claim's current business key, or the workspace key that sent the stored request. Unclaim clears it. A cookie is not accepted.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"headers, raw body, and signature_valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxEcho"}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"summary":"Accept one signed webhook for ba-treatyway-0000. Treatyway-Signature is required. A Bearer key is not required. The body is the webhook payload.","parameters":[{"name":"Treatyway-Signature","in":"header","required":true,"schema":{"type":"string"},"description":"t=<unix send time>,v1=<hex HMAC-SHA256 of <timestamp>.<raw body>>. t is when Treatyway signed. Receivers must reject a timestamp more than 300 seconds from their own clock."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookPayload"}}}},"responses":{"200":{"description":"Stored.","content":{"application/json":{"schema":{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/llms.txt":{"get":{"summary":"Short agent instructions","responses":{"200":{"description":"text"}}}},"/agents.md":{"get":{"summary":"Agent guide","responses":{"200":{"description":"markdown"}}}},"/stats.json":{"get":{"summary":"MCP call counts for 7 days","responses":{"200":{"description":"aggregates"}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Workspace key for /api/requests, /api/workspace, and GET /api/sandbox/echo. Business key for the channel, reply, disable, rotate, unclaim, and GET /api/sandbox/echo routes. Send Authorization: Bearer. A key in the URL or a cookie is not accepted. POST /api/workspaces does not set a cookie."}},"schemas":{"EmptyObject":{"type":"object","additionalProperties":false},"ClaimToken":{"type":"object","required":["token","domain","expires_at","dns_name","well_known_url"],"properties":{"token":{"type":"string","description":"Shown once. Publish this value. It expires in 24 hours. A newer token revokes it."},"domain":{"type":"string"},"expires_at":{"type":"string","description":"ISO-8601."},"dns_name":{"type":"string","description":"DNS TXT name. The record value is the token."},"well_known_url":{"type":"string","description":"HTTPS file whose body is the token."}}},"ClaimVerifyRequest":{"type":"object","additionalProperties":false,"required":["token","method"],"properties":{"token":{"type":"string","minLength":16,"maxLength":200},"method":{"type":"string","enum":["dns","well_known"],"description":"dns checks a TXT record. well_known checks the HTTPS file. This is not the workspace prove value dns_txt."}}},"ClaimVerifyResult":{"type":"object","required":["domain","method","verified_at","business_key","signing_secret","key_reissued"],"properties":{"domain":{"type":"string"},"method":{"type":"string","enum":["dns","well_known"]},"verified_at":{"type":"string"},"business_key":{"type":["string","null"],"description":"Shown once on every successful check. A later proof while a key is active returns a new key and revokes the previous one."},"signing_secret":{"type":["string","null"],"description":"Shown once on every successful check. Replaced together with the business key."},"key_reissued":{"type":"boolean","description":"False on the first key. True only when this check revoked a prior active key. verification_audits.evidence records the same value."}}},"ChannelInput":{"type":"object","additionalProperties":false,"required":["type","url"],"properties":{"type":{"type":"string","enum":["webhook","openapi","mcp"]},"url":{"type":"string","description":"https on the verified domain."},"description":{"type":"string","description":"Required for openapi and mcp. Optional for webhook."},"contact_email":{"type":"string","description":"Optional. Must be on the verified domain."}}},"ChannelResult":{"type":"object","required":["channel_type","domain"],"properties":{"channel_type":{"type":"string","enum":["webhook","openapi","mcp"]},"channel_url":{"type":"string","description":"Omitted for a webhook."},"domain":{"type":"string"}}},"ChannelDisabled":{"type":"object","required":["channel_type","disabled"],"properties":{"channel_type":{"type":"null"},"disabled":{"type":"boolean"}}},"Unclaimed":{"type":"object","required":["unclaimed"],"properties":{"unclaimed":{"type":"boolean"}}},"RotatedKey":{"type":"object","required":["business_key","signing_secret"],"properties":{"business_key":{"type":"string"},"signing_secret":{"type":"string"}}},"BusinessReply":{"type":"object","additionalProperties":false,"required":["message","idempotency_key"],"properties":{"message":{"type":"string","minLength":1,"maxLength":5000},"idempotency_key":{"type":"string","minLength":8,"maxLength":100,"description":"Required. 8 to 100 characters. The same key and the same message return the same reply."}}},"Error":{"type":"object","properties":{"detail":{"type":"string"}},"required":["detail"]},"RequestStatus":{"type":"string","enum":["sandbox_queued","dry_run","not_deliverable_by_email","invalid_recipient","opted_out","recorded","delivered","failed","pending_send","daily_cap","not_configured","sent","provider_error","cancelled","replied"],"description":"sandbox_queued: Demo listing, or a test listing with no connected channel. Nothing is emailed. A buyer follow-up on that path stays sandbox_queued. dry_run: Real listing with a contact email, and outbound email is off. The request is recorded and nothing is sent. not_deliverable_by_email: Real listing with no contact email. Nothing is sent. invalid_recipient: The contact address is not a usable email. Nothing is sent. opted_out: The address has opted out. Nothing is sent. recorded: The channel is OpenAPI or MCP, which Treatyway does not call, or a test webhook that is not the sandbox echo. Nothing is emailed. delivered: The signed webhook POST was accepted (HTTP 2xx). failed: The signed webhook POST failed after the retries. pending_send: Outbound email is on and the message is queued. daily_cap: Outbound email is on and the daily sending cap is reached. Nothing is sent. not_configured: Outbound email is on and no email provider is configured. Nothing is sent. sent: Treatyway sent the email. provider_error: The email provider did not accept the message. cancelled: The requester cancelled the request. replied: The business replied, by the business-key reply, a sandbox supplier reply, or an inbound email. This replaces the previous status, including delivered and failed. A later buyer follow-up is still delivered when a webhook is connected, and the status stays replied."},"WebhookPayload":{"type":"object","description":"Signed webhook body. Header Treatyway-Signature is t=<unix send time>,v1=<hex HMAC-SHA256 of <timestamp>.<raw body>> with the signing secret. t is the send time. Receivers must reject a timestamp more than 300 seconds from their own clock. Use the raw body. signature_valid on the sandbox echo checks the HMAC only and does not apply that window.","required":["type","id","request_id","business_id","category","subject","message","quantity","destination","created_at","business_sees","from"],"properties":{"type":{"type":"string","enum":["request","message"]},"id":{"type":"string","description":"The inquiry id when type is request. The follow-up message id when type is message."},"request_id":{"type":"string","description":"The inquiry id. Present on request and message events."},"message_id":{"type":"string","description":"Present when type is message. Distinct from request_id."},"business_id":{"type":"string"},"category":{"type":"string"},"subject":{"type":"string"},"message":{"type":"string"},"quantity":{"type":["integer","null"]},"destination":{"type":"string"},"created_at":{"type":"string"},"business_sees":{"type":"string"},"from":{"type":"object","required":["organization","agent_name","identity","business_sees"],"properties":{"organization":{"type":"string"},"agent_name":{"type":"string"},"identity":{"type":"string","description":"self-declared"},"business_sees":{"type":"string"}}}}},"SandboxEcho":{"type":"object","required":["headers","body","signature_valid","request_id","created_at"],"properties":{"headers":{"type":"object","description":"content-type, user-agent, and Treatyway-Signature from the delivery.","additionalProperties":{"type":"string"}},"body":{"type":"string","description":"Raw webhook body."},"signature_valid":{"type":"boolean","description":"True when the HMAC in Treatyway-Signature matches the current signing secret and the raw body. This is the signature only. It does not apply the 300-second window. t is the send time, and receivers must enforce that window themselves. A reissued key makes an older delivery false."},"request_id":{"type":"string"},"created_at":{"type":"string"}}},"WorkspaceInput":{"type":"object","description":"No fields are required. An empty object is Anonymous. organization is the company. operator_name is the person. website is an https URL. agent_name is optional and defaults to Business assistant.","properties":{"organization":{"type":"string"},"operator_name":{"type":"string"},"website":{"type":"string"},"agent_name":{"type":"string"}}},"SearchHit":{"type":"object","properties":{"claimed":{"type":"boolean"},"channel_type":{"type":["string","null"]},"id":{"type":"string"},"name":{"type":"string"},"category":{"type":"string"},"city":{"type":"string"},"location":{"type":"string"},"phone":{"type":["string","null"],"description":"REST phone is E.164, for example +14155550100. phone_display is the local format, such as (415) 555-0100. MCP phone still uses the display format."},"phone_display":{"type":["string","null"],"description":"Local format for the same number, such as (415) 555-0100. phone is E.164."},"website":{"type":["string","null"]},"capabilities":{"type":"array","items":{"type":"object"}},"capabilities_text":{"type":"string"},"has_contact_email":{"type":"boolean"},"domain_verified":{"type":"boolean"},"domain_verification_method":{"type":["string","null"]},"domain_verified_at":{"type":["string","null"]},"registered_business":{"type":"boolean"},"registry_method":{"type":["string","null"]},"registry_verified_at":{"type":["string","null"]},"why_matched":{"type":"string"},"match_reason":{"type":"string"}},"required":["id","name","claimed","channel_type","domain_verified","registered_business"]},"SearchPage":{"type":"object","properties":{"businesses":{"type":"array","items":{"$ref":"#/components/schemas/SearchHit"}},"total":{"type":"integer"},"next_cursor":{"type":["string","null"]},"coverage_note":{"type":"string"},"provenance":{"type":"object","properties":{"source":{"type":"string"},"check":{"type":"string"}}}},"required":["businesses","total"]}}}}