{"openapi":"3.1.0","info":{"title":"Bloombilt Local — Service Request API","version":"1.0.0","description":"Submit a local service request on behalf of a person, and read its status. One qualified request is offered to exactly one merchant; it is never distributed to multiple competing providers.","contact":{"name":"Bloombilt LLC","email":"support@bloombilt.com"}},"servers":[{"url":"https://local.bloombilt.com/api/v1"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"A per-channel API key issued by Bloombilt. The key that creates a request is the only key that can read its status."}},"schemas":{"Fulfillment":{"oneOf":[{"type":"object","required":["mode","address","postal_code"],"properties":{"mode":{"const":"onsite"},"address":{"type":"string"},"postal_code":{"type":"string","pattern":"^\\d{5}$"}}},{"type":"object","required":["mode","customer_origin_postal_code"],"properties":{"mode":{"const":"at_merchant"},"customer_origin_postal_code":{"type":"string","pattern":"^\\d{5}$"}}},{"type":"object","required":["mode","customer_timezone"],"properties":{"mode":{"const":"remote"},"customer_timezone":{"type":"string"}}}]},"SubmitRequest":{"type":"object","required":["need","capability_id","fulfillment","needed_by","customer","consent"],"properties":{"need":{"type":"string","description":"What the person wants, in their words."},"capability_id":{"type":"string","description":"From GET /capabilities."},"fulfillment":{"$ref":"#/components/schemas/Fulfillment"},"needed_by":{"type":"string","format":"date-time"},"customer":{"type":"object","required":["name","phone"],"properties":{"name":{"type":"string"},"phone":{"type":"string"},"email":{"type":["string","null"]}}},"consent":{"type":"object","required":["purpose_text","granted_at"],"description":"The exact sentence the person was shown, and when they agreed. Not a boolean: a caller that cannot supply this has not collected consent.","properties":{"purpose_text":{"type":"string"},"granted_at":{"type":"string","format":"date-time"}}},"test":{"type":"boolean","description":"Marks a demo. Can never produce a charge."},"source_ref":{"type":["string","null"]}}},"StatusResponse":{"type":"object","properties":{"request_id":{"type":"string"},"status":{"type":"string","enum":["searching","accepted","unfulfilled","rejected","cancelled"]},"accepted_by":{"type":["object","null"],"properties":{"merchant_name":{"type":"string"},"next_step":{"type":"string"}}},"rejection_reason":{"type":["string","null"]},"explanation":{"type":"string"}}},"Error":{"type":"object","properties":{"error":{"type":"string","description":"Stable machine-readable code."},"message":{"type":"string"},"field":{"type":["string","null"]}}}}},"paths":{"/capabilities":{"get":{"summary":"List the service categories that can be requested","security":[],"responses":{"200":{"description":"The controlled vocabulary.","content":{"application/json":{"schema":{"type":"object","properties":{"capabilities":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string"}}}}}}}}}}}},"/requests":{"post":{"summary":"Submit a service request","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmitRequest"}}}},"responses":{"201":{"description":"Accepted for qualification.","content":{"application/json":{"schema":{"type":"object","properties":{"request_id":{"type":"string"},"status":{"type":"string"},"possible_duplicate_of":{"type":["string","null"]}}}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The request cannot be qualified. `error` is the machine-readable reason, e.g. prohibited_category, insufficient_detail, missing_contact.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/requests/{id}":{"get":{"summary":"Read a request status","description":"Returns customer-safe states only. A merchant that declined is never named.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Current status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusResponse"}}}},"404":{"description":"No such request for this API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}