{
  "openapi": "3.1.0",
  "info": {
    "title": "Hey Human provider and booking API",
    "version": "0.3.0-preview",
    "description": "Agent-only discovery and hiring of human services. Provider profiles, services and appointment slots are published by their owners. Credential evidence is self-reported until independently verified; unknown relevant history is null. Appointment requests generate a quote; agents explicitly accept via awards:write, then providers confirm. Requests do not reserve time. Only test-environment nonproduction server-enabled simulation permits confirmation, and actual_money_moved is always false. Live funding, identity verification, payouts, recurring series, calendar synchronization, and published connector distribution are not connected. The additive open-request API remains at /openapi-v2.yaml."
  },
  "servers": [
    {
      "url": "/"
    }
  ],
  "security": [
    {
      "AgentBearer": []
    }
  ],
  "paths": {
    "/api/v2/providers": {
      "get": {
        "operationId": "searchProviders",
        "summary": "Find published providers and service offerings",
        "x-required-scope": "tasks:read",
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 160
            }
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "plumbing",
                "electrical",
                "painting",
                "pet_care",
                "personal_care",
                "errands",
                "practical_help",
                "other"
              ]
            }
          },
          {
            "name": "city",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 2,
              "maxLength": 100
            }
          },
          {
            "name": "region",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z]{2}$"
            }
          },
          {
            "name": "booking_mode",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "appointment",
                "quote"
              ]
            }
          },
          {
            "name": "max_price_cents",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 10000000
            }
          },
          {
            "name": "required_qualifications",
            "in": "query",
            "required": false,
            "style": "form",
            "explode": false,
            "schema": {
              "default": [],
              "maxItems": 6,
              "type": "array",
              "items": {
                "type": "string",
                "enum": [
                  "license",
                  "certification",
                  "insurance",
                  "experience",
                  "training",
                  "other"
                ]
              }
            }
          },
          {
            "name": "available_after",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
            }
          },
          {
            "name": "available_before",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "default": 50,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Canonical data in {data, meta}; request/quote/acceptance is not provider confirmation. No money moves in this build.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object"
                    },
                    "meta": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "Structured {error:{code,message},meta}; invalid_request 422, unauthorized 401, insufficient_scope 403, not_found 404, stale/conflicting state 409, unavailable storage 503. Live confirmation is blocked without provider-backed funding."
          }
        }
      }
    },
    "/api/v2/providers/{id}": {
      "get": {
        "operationId": "getProvider",
        "summary": "Inspect services, cancellation terms, portfolios and qualification provenance",
        "x-required-scope": "tasks:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Canonical data in {data, meta}; request/quote/acceptance is not provider confirmation. No money moves in this build.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object"
                    },
                    "meta": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "Structured {error:{code,message},meta}; invalid_request 422, unauthorized 401, insufficient_scope 403, not_found 404, stale/conflicting state 409, unavailable storage 503. Live confirmation is blocked without provider-backed funding."
          }
        }
      }
    },
    "/api/v2/providers/{id}/availability": {
      "get": {
        "operationId": "getProviderAvailability",
        "summary": "Read future slots and exact service versions; a request does not hold a slot",
        "x-required-scope": "tasks:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 100
            }
          },
          {
            "name": "service_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Canonical data in {data, meta}; request/quote/acceptance is not provider confirmation. No money moves in this build.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object"
                    },
                    "meta": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "Structured {error:{code,message},meta}; invalid_request 422, unauthorized 401, insufficient_scope 403, not_found 404, stale/conflicting state 409, unavailable storage 503. Live confirmation is blocked without provider-backed funding."
          }
        }
      }
    },
    "/api/v2/bookings": {
      "get": {
        "operationId": "listBookings",
        "summary": "List only this organization and environment’s service bookings",
        "x-required-scope": "tasks:read",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Canonical data in {data, meta}; request/quote/acceptance is not provider confirmation. No money moves in this build.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object"
                    },
                    "meta": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "Structured {error:{code,message},meta}; invalid_request 422, unauthorized 401, insufficient_scope 403, not_found 404, stale/conflicting state 409, unavailable storage 503. Live confirmation is blocked without provider-backed funding."
          }
        }
      },
      "post": {
        "operationId": "createBooking",
        "summary": "Request a service: fixed-price appointment returns quoted; custom service returns requested",
        "x-required-scope": "tasks:write",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9._:-]{8,128}$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateBooking"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Canonical data in {data, meta}; request/quote/acceptance is not provider confirmation. No money moves in this build.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object"
                    },
                    "meta": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "Structured {error:{code,message},meta}; invalid_request 422, unauthorized 401, insufficient_scope 403, not_found 404, stale/conflicting state 409, unavailable storage 503. Live confirmation is blocked without provider-backed funding."
          }
        }
      }
    },
    "/api/v2/bookings/{id}": {
      "get": {
        "operationId": "getBooking",
        "summary": "Resume canonical agreement, status, funding and event history",
        "x-required-scope": "tasks:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Canonical data in {data, meta}; request/quote/acceptance is not provider confirmation. No money moves in this build.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object"
                    },
                    "meta": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "Structured {error:{code,message},meta}; invalid_request 422, unauthorized 401, insufficient_scope 403, not_found 404, stale/conflicting state 409, unavailable storage 503. Live confirmation is blocked without provider-backed funding."
          }
        }
      }
    },
    "/api/v2/bookings/{id}/accept": {
      "post": {
        "operationId": "acceptBookingQuote",
        "summary": "Accept this exact current quote within user authority; provider confirmation still required",
        "x-required-scope": "awards:write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 100
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9._:-]{8,128}$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AcceptBookingQuote"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Canonical data in {data, meta}; request/quote/acceptance is not provider confirmation. No money moves in this build.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object"
                    },
                    "meta": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "Structured {error:{code,message},meta}; invalid_request 422, unauthorized 401, insufficient_scope 403, not_found 404, stale/conflicting state 409, unavailable storage 503. Live confirmation is blocked without provider-backed funding."
          }
        }
      }
    },
    "/api/v2/bookings/{id}/cancellation": {
      "post": {
        "operationId": "cancelBooking",
        "summary": "Cancel an unconfirmed request; committed work requires resolution",
        "x-required-scope": "tasks:write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 100
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9._:-]{8,128}$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CancelBooking"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Canonical data in {data, meta}; request/quote/acceptance is not provider confirmation. No money moves in this build.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object"
                    },
                    "meta": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "Structured {error:{code,message},meta}; invalid_request 422, unauthorized 401, insufficient_scope 403, not_found 404, stale/conflicting state 409, unavailable storage 503. Live confirmation is blocked without provider-backed funding."
          }
        }
      }
    },
    "/api/v2/worker/provider": {
      "get": {
        "operationId": "getWorkerProvider",
        "summary": "Read the signed-in provider’s private editable profile",
        "x-required-scope": "worker identity",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Canonical data in {data, meta}; request/quote/acceptance is not provider confirmation. No money moves in this build.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object"
                    },
                    "meta": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "Structured {error:{code,message},meta}; invalid_request 422, unauthorized 401, insufficient_scope 403, not_found 404, stale/conflicting state 409, unavailable storage 503. Live confirmation is blocked without provider-backed funding."
          }
        },
        "security": [
          {
            "WorkerSession": []
          }
        ]
      },
      "put": {
        "operationId": "saveWorkerProvider",
        "summary": "Save profile, services, qualifications and slots with expected_version; no client verification claims",
        "x-required-scope": "worker identity",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProviderInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Canonical data in {data, meta}; request/quote/acceptance is not provider confirmation. No money moves in this build.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object"
                    },
                    "meta": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "Structured {error:{code,message},meta}; invalid_request 422, unauthorized 401, insufficient_scope 403, not_found 404, stale/conflicting state 409, unavailable storage 503. Live confirmation is blocked without provider-backed funding."
          }
        },
        "security": [
          {
            "WorkerSession": []
          }
        ]
      }
    },
    "/api/v2/worker/bookings": {
      "get": {
        "operationId": "listWorkerBookings",
        "summary": "Read own incoming service requests with customer spending caps and references redacted",
        "x-required-scope": "worker identity",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Canonical data in {data, meta}; request/quote/acceptance is not provider confirmation. No money moves in this build.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object"
                    },
                    "meta": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "Structured {error:{code,message},meta}; invalid_request 422, unauthorized 401, insufficient_scope 403, not_found 404, stale/conflicting state 409, unavailable storage 503. Live confirmation is blocked without provider-backed funding."
          }
        },
        "security": [
          {
            "WorkerSession": []
          }
        ]
      }
    },
    "/api/v2/worker/bookings/{id}/respond": {
      "post": {
        "operationId": "respondWorkerBooking",
        "summary": "Quote, decline, or explicitly confirm an accepted agreement; live confirmation remains blocked",
        "x-required-scope": "worker identity",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 100
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9._:-]{8,128}$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RespondBooking"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Canonical data in {data, meta}; request/quote/acceptance is not provider confirmation. No money moves in this build.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object"
                    },
                    "meta": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "Structured {error:{code,message},meta}; invalid_request 422, unauthorized 401, insufficient_scope 403, not_found 404, stale/conflicting state 409, unavailable storage 503. Live confirmation is blocked without provider-backed funding."
          }
        },
        "security": [
          {
            "WorkerSession": []
          }
        ]
      }
    }
  },
  "components": {
    "securitySchemes": {
      "AgentBearer": {
        "type": "http",
        "scheme": "bearer",
        "description": "Scoped Hey Human agent key, bound to an organization and environment."
      },
      "WorkerSession": {
        "type": "http",
        "scheme": "bearer",
        "description": "Supabase user access token, or same-origin cookie session; agent keys cannot impersonate providers."
      }
    },
    "schemas": {
      "ProviderInput": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "type": "object",
        "properties": {
          "expected_version": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991
          },
          "display_name": {
            "type": "string",
            "minLength": 2,
            "maxLength": 120
          },
          "headline": {
            "type": "string",
            "minLength": 3,
            "maxLength": 180
          },
          "bio": {
            "type": "string",
            "minLength": 20,
            "maxLength": 3000
          },
          "city": {
            "type": "string",
            "minLength": 2,
            "maxLength": 100
          },
          "region": {
            "type": "string",
            "pattern": "^[A-Za-z]{2}$"
          },
          "timezone": {
            "type": "string",
            "minLength": 3,
            "maxLength": 100
          },
          "published": {
            "type": "boolean"
          },
          "accepting_requests": {
            "type": "boolean"
          },
          "qualifications": {
            "maxItems": 30,
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 100,
                  "pattern": "^[A-Za-z0-9._:-]+$"
                },
                "kind": {
                  "type": "string",
                  "enum": [
                    "license",
                    "certification",
                    "insurance",
                    "experience",
                    "training",
                    "other"
                  ]
                },
                "title": {
                  "type": "string",
                  "minLength": 2,
                  "maxLength": 180
                },
                "issuer": {
                  "type": "string",
                  "maxLength": 180
                },
                "jurisdiction": {
                  "type": "string",
                  "maxLength": 100
                },
                "expires_at": {
                  "anyOf": [
                    {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                    },
                    {
                      "type": "null"
                    }
                  ]
                },
                "evidence_url": {
                  "anyOf": [
                    {
                      "type": "string",
                      "maxLength": 1000,
                      "format": "uri"
                    },
                    {
                      "type": "null"
                    }
                  ]
                },
                "service_categories": {
                  "default": [],
                  "maxItems": 8,
                  "type": "array",
                  "items": {
                    "type": "string",
                    "enum": [
                      "plumbing",
                      "electrical",
                      "painting",
                      "pet_care",
                      "personal_care",
                      "errands",
                      "practical_help",
                      "other"
                    ]
                  }
                }
              },
              "required": [
                "id",
                "kind",
                "title",
                "issuer",
                "jurisdiction",
                "expires_at",
                "evidence_url"
              ],
              "additionalProperties": false
            }
          },
          "portfolio": {
            "maxItems": 12,
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "title": {
                  "type": "string",
                  "minLength": 2,
                  "maxLength": 160
                },
                "url": {
                  "type": "string",
                  "maxLength": 1000,
                  "format": "uri"
                }
              },
              "required": [
                "title",
                "url"
              ],
              "additionalProperties": false
            }
          },
          "services": {
            "maxItems": 30,
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 100,
                  "pattern": "^[A-Za-z0-9._:-]+$"
                },
                "title": {
                  "type": "string",
                  "minLength": 3,
                  "maxLength": 160
                },
                "category": {
                  "type": "string",
                  "enum": [
                    "plumbing",
                    "electrical",
                    "painting",
                    "pet_care",
                    "personal_care",
                    "errands",
                    "practical_help",
                    "other"
                  ]
                },
                "description": {
                  "type": "string",
                  "minLength": 10,
                  "maxLength": 3000
                },
                "booking_mode": {
                  "type": "string",
                  "enum": [
                    "appointment",
                    "quote"
                  ]
                },
                "price_cents": {
                  "anyOf": [
                    {
                      "type": "integer",
                      "minimum": 1,
                      "maximum": 10000000
                    },
                    {
                      "type": "null"
                    }
                  ]
                },
                "duration_minutes": {
                  "type": "integer",
                  "minimum": 5,
                  "maximum": 20160
                },
                "location_type": {
                  "type": "string",
                  "enum": [
                    "customer",
                    "provider",
                    "remote"
                  ]
                },
                "location_details": {
                  "type": "string",
                  "maxLength": 500
                },
                "cancellation_policy": {
                  "type": "string",
                  "minLength": 10,
                  "maxLength": 1000
                },
                "required_qualifications": {
                  "maxItems": 6,
                  "type": "array",
                  "items": {
                    "type": "string",
                    "enum": [
                      "license",
                      "certification",
                      "insurance",
                      "experience",
                      "training",
                      "other"
                    ]
                  }
                },
                "published": {
                  "type": "boolean"
                }
              },
              "required": [
                "id",
                "title",
                "category",
                "description",
                "booking_mode",
                "price_cents",
                "duration_minutes",
                "location_type",
                "location_details",
                "cancellation_policy",
                "required_qualifications",
                "published"
              ],
              "additionalProperties": false
            }
          },
          "availability": {
            "maxItems": 100,
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 100,
                  "pattern": "^[A-Za-z0-9._:-]+$"
                },
                "service_id": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 100,
                  "pattern": "^[A-Za-z0-9._:-]+$"
                },
                "start_at": {
                  "type": "string",
                  "format": "date-time",
                  "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                },
                "end_at": {
                  "type": "string",
                  "format": "date-time",
                  "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                }
              },
              "required": [
                "id",
                "service_id",
                "start_at",
                "end_at"
              ],
              "additionalProperties": false
            }
          }
        },
        "required": [
          "expected_version",
          "display_name",
          "headline",
          "bio",
          "city",
          "region",
          "timezone",
          "published",
          "accepting_requests",
          "qualifications",
          "portfolio",
          "services",
          "availability"
        ],
        "additionalProperties": false
      },
      "ProviderSearch": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "type": "object",
        "properties": {
          "query": {
            "type": "string",
            "maxLength": 160
          },
          "category": {
            "type": "string",
            "enum": [
              "plumbing",
              "electrical",
              "painting",
              "pet_care",
              "personal_care",
              "errands",
              "practical_help",
              "other"
            ]
          },
          "city": {
            "type": "string",
            "minLength": 2,
            "maxLength": 100
          },
          "region": {
            "type": "string",
            "pattern": "^[A-Za-z]{2}$"
          },
          "booking_mode": {
            "type": "string",
            "enum": [
              "appointment",
              "quote"
            ]
          },
          "max_price_cents": {
            "type": "integer",
            "minimum": 1,
            "maximum": 10000000
          },
          "required_qualifications": {
            "default": [],
            "maxItems": 6,
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "license",
                "certification",
                "insurance",
                "experience",
                "training",
                "other"
              ]
            }
          },
          "available_after": {
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
          },
          "available_before": {
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
          },
          "limit": {
            "default": 50,
            "type": "integer",
            "minimum": 1,
            "maximum": 100
          }
        },
        "additionalProperties": false
      },
      "CreateBooking": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "type": "object",
        "properties": {
          "provider_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100,
            "pattern": "^[A-Za-z0-9._:-]+$"
          },
          "service_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100,
            "pattern": "^[A-Za-z0-9._:-]+$"
          },
          "service_version": {
            "type": "integer",
            "minimum": 1,
            "maximum": 9007199254740991
          },
          "slot_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100,
            "pattern": "^[A-Za-z0-9._:-]+$"
          },
          "scope": {
            "type": "string",
            "minLength": 10,
            "maxLength": 3000
          },
          "customer_reference": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128
          },
          "budget": {
            "type": "object",
            "properties": {
              "all_in_max_cents": {
                "type": "integer",
                "minimum": 1,
                "maximum": 10000000
              },
              "currency": {
                "type": "string",
                "const": "USD"
              }
            },
            "required": [
              "all_in_max_cents",
              "currency"
            ],
            "additionalProperties": false
          },
          "location": {
            "type": "object",
            "properties": {
              "address": {
                "type": "string",
                "minLength": 5,
                "maxLength": 500
              },
              "city": {
                "type": "string",
                "minLength": 2,
                "maxLength": 100
              },
              "region": {
                "type": "string",
                "pattern": "^[A-Za-z]{2}$"
              }
            },
            "required": [
              "address",
              "city",
              "region"
            ],
            "additionalProperties": false
          },
          "requested_start_at": {
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
          },
          "requested_end_at": {
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
          },
          "required_qualifications": {
            "default": [],
            "maxItems": 6,
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "license",
                "certification",
                "insurance",
                "experience",
                "training",
                "other"
              ]
            }
          }
        },
        "required": [
          "provider_id",
          "service_id",
          "service_version",
          "scope",
          "customer_reference",
          "budget"
        ],
        "additionalProperties": false
      },
      "RespondBooking": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "type": "object",
        "properties": {
          "action": {
            "type": "string",
            "enum": [
              "quote",
              "confirm",
              "decline"
            ]
          },
          "expected_version": {
            "type": "integer",
            "minimum": 1,
            "maximum": 9007199254740991
          },
          "quote": {
            "type": "object",
            "properties": {
              "provider_pay_cents": {
                "type": "integer",
                "minimum": 1,
                "maximum": 10000000
              },
              "start_at": {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
              },
              "end_at": {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
              },
              "scope": {
                "type": "string",
                "minLength": 10,
                "maxLength": 3000
              },
              "expires_at": {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
              }
            },
            "required": [
              "provider_pay_cents",
              "start_at",
              "end_at",
              "scope",
              "expires_at"
            ],
            "additionalProperties": false
          },
          "note": {
            "type": "string",
            "maxLength": 1000
          }
        },
        "required": [
          "action",
          "expected_version"
        ],
        "additionalProperties": false
      },
      "AcceptBookingQuote": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "type": "object",
        "properties": {
          "expected_version": {
            "type": "integer",
            "minimum": 1,
            "maximum": 9007199254740991
          },
          "quote_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100,
            "pattern": "^[A-Za-z0-9._:-]+$"
          },
          "quote_version": {
            "type": "integer",
            "minimum": 1,
            "maximum": 9007199254740991
          }
        },
        "required": [
          "expected_version",
          "quote_id",
          "quote_version"
        ],
        "additionalProperties": false
      },
      "CancelBooking": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "type": "object",
        "properties": {
          "expected_version": {
            "type": "integer",
            "minimum": 1,
            "maximum": 9007199254740991
          }
        },
        "required": [
          "expected_version"
        ],
        "additionalProperties": false
      }
    }
  }
}
