{
  "openapi": "3.1.0",
  "info": {
    "title": "UstaGeliyor Partner API",
    "version": "1.0.0",
    "description": "The API through which third-party systems (e-commerce platforms, custom software) and ustas (tradespeople) open, track and run jobs on UstaGeliyor as a **customer** or an **usta**.\n\n## Authentication\nEvery request carries `Authorization: Bearer ugp_…`. Keys are issued by the UstaGeliyor operations team on behalf of one account; the secret is shown exactly once, when it is created. A key:\n- is bound to **one account** — every call acts as that account;\n- carries **one role**: `customer` or `usta` (do not send `x-ug-role`; it is ignored);\n- carries **scopes**: `read` (every GET), `write` (state changes that move no money), `money` (opening a payment, confirming, refunds, disputes, accepting quotes and extra work, approving payouts).\n\nInvalid, revoked and expired keys all get the same answer: 401 `PARTNER_KEY_INVALID`.\n\n## Errors\nEvery non-2xx response carries `{ \"message\": \"…\", \"code\": \"…\" }`. Branch on **`code`**; messages may change. Validation failures are 400 `VALIDATION_ERROR` with an `issues` list.\n\n## Rate limits\n120 requests per minute per key (a key may carry its own quota). Every response has `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset`; beyond the quota you get 429 `RATE_LIMITED` with `Retry-After`.\n\n## Amounts\nAll amounts are **whole Turkish lira** (750 = ₺750). Prices and titles are never taken from the caller; they come from the catalog.\n\n## Card payments\nRaw card data never passes through this API. For a card, `POST /payments` returns `payment.payment_url`: send the customer there (browser or WebView); 3D Secure completes on the bank's page and the payment is held only on the bank's confirmation. For a bank transfer you get the instructions (`reference`, `amount`, `accounts`). Until the hosted page is connected to the bank, a card request in an environment with real card payments gets `503 HOSTED_PAYMENT_UNAVAILABLE` and no payment record is opened.\n\n## Retries\nThere is no `Idempotency-Key` in v1. Booking the same slot twice stops at 409 `SLOT_CONFLICT`, a second payment for the same booking at 409 `ESCROW_EXISTS`.\n\n## Tracing\nSend `X-Request-Id` and it comes back unchanged; otherwise we generate one. Quote it when you contact support.",
    "contact": {
      "name": "UstaGeliyor",
      "url": "https://ustageliyor.com"
    }
  },
  "servers": [
    {
      "url": "https://panel.ustageliyor.com/partner/v1",
      "description": "Partner API v1"
    }
  ],
  "security": [
    {
      "PartnerKey": []
    }
  ],
  "tags": [
    {
      "name": "Catalog",
      "description": "Services, prices, appointment slots, contracts and payment methods."
    },
    {
      "name": "Account",
      "description": "The key's account, notifications and file uploads."
    },
    {
      "name": "Bookings",
      "description": "Opening, tracking, cancelling and confirming jobs as a customer."
    },
    {
      "name": "Payments",
      "description": "Paying for a booking (card: hosted page, transfer: instructions), refund requests and disputes."
    },
    {
      "name": "Extra work",
      "description": "Extra charges an usta raises on site, and their negotiation."
    },
    {
      "name": "Quotes",
      "description": "An usta's quote on discovery-priced work and the customer's decision."
    },
    {
      "name": "Chat",
      "description": "Customer–usta messaging per booking; poll for new messages with `after`."
    },
    {
      "name": "Support",
      "description": "Support tickets (cancellation requests included)."
    },
    {
      "name": "Usta — Jobs",
      "description": "As an usta: the job pool, accepting, heading out, starting and completing."
    },
    {
      "name": "Usta — Shop",
      "description": "Usta profile, working hours, documents and onboarding state."
    },
    {
      "name": "Usta — Payouts",
      "description": "Weekly payout statements and the usta's approval."
    },
    {
      "name": "Meta",
      "description": "The machine-readable API description."
    }
  ],
  "x-tagGroups": [
    {
      "name": "Customer",
      "tags": [
        "Catalog",
        "Account",
        "Bookings",
        "Payments",
        "Extra work",
        "Quotes",
        "Chat",
        "Support"
      ]
    },
    {
      "name": "Usta",
      "tags": [
        "Usta — Jobs",
        "Usta — Shop",
        "Usta — Payouts"
      ]
    },
    {
      "name": "Meta",
      "tags": [
        "Meta"
      ]
    }
  ],
  "paths": {
    "/appointment-slots": {
      "get": {
        "operationId": "listAppointmentSlots",
        "tags": [
          "Catalog"
        ],
        "summary": "List appointment slots",
        "description": "A day's appointment slots and availability. `POST /bookings` takes one of these `slot` values as `appointment_slot`.\n\n**Access:** either role · scope `read`",
        "parameters": [
          {
            "name": "date",
            "in": "query",
            "required": true,
            "description": "Day, `YYYY-MM-DD`.",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "date": {
                      "type": "string"
                    },
                    "slots": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "slot": {
                            "type": "string"
                          },
                          "available": {
                            "type": "boolean"
                          },
                          "label": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "slot",
                          "available",
                          "label"
                        ],
                        "additionalProperties": {}
                      }
                    }
                  },
                  "required": [
                    "date",
                    "slots"
                  ],
                  "additionalProperties": {}
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.\n\n- `VALIDATION_ERROR` — The request failed validation; see `issues`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "VALIDATION_ERROR": {
                    "value": {
                      "message": "The request failed validation; see `issues`.",
                      "code": "VALIDATION_ERROR"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "any",
        "x-ug-scope": "read"
      }
    },
    "/bookings": {
      "get": {
        "operationId": "listBookings",
        "tags": [
          "Bookings"
        ],
        "summary": "List bookings",
        "description": "The key's account's bookings, newest first, with the assigned usta's summary and group siblings. Fixed-price drafts whose payment never started are not listed.\n\n**Access:** customer key · scope `read`",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "requests": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "reference": {
                            "description": "The booking number shown to customers and staff (`UG-102609123456`).",
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "status": {
                            "type": "string"
                          },
                          "amount": {
                            "description": "Server-computed amount, whole TRY.",
                            "anyOf": [
                              {
                                "type": "number"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "appointment_date": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "appointment_slot": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "group_id": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "status",
                          "amount",
                          "appointment_date",
                          "appointment_slot"
                        ],
                        "additionalProperties": {}
                      }
                    },
                    "role": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "requests",
                    "role"
                  ],
                  "additionalProperties": {}
                },
                "example": {
                  "requests": [],
                  "role": "customer"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_ROLE_REQUIRED` — This operation is not available to the key's role.\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_ROLE_REQUIRED": {
                    "value": {
                      "message": "This operation is not available to the key's role.",
                      "code": "PARTNER_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "customer",
        "x-ug-scope": "read"
      },
      "post": {
        "operationId": "createBooking",
        "tags": [
          "Bookings"
        ],
        "summary": "Create a booking",
        "description": "Opens a job on behalf of the key's account. Price and title come from the catalog; an uncovered province/district is 422 `SERVICE_AREA_NOT_COVERED`. A basket spanning several trades becomes one booking (leg) per trade, tied by `group_id`. A booking reaches no usta until it is paid: call `POST /payments` for it next.\n\n**Access:** customer key · scope `write`",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "items": {
                    "description": "Chosen services. Titles and prices are never taken from the caller; a basket that spans several trades is split into one booking (leg) per trade.",
                    "minItems": 1,
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "variant_id": {
                          "description": "Package (variant) id. When omitted the service's cheapest package is used.",
                          "type": "string",
                          "minLength": 1
                        },
                        "product_id": {
                          "description": "Service (product) id; required when `variant_id` is absent.",
                          "type": "string",
                          "minLength": 1
                        },
                        "quantity": {
                          "description": "Quantity, 1–99. Defaults to 1.",
                          "type": "integer",
                          "minimum": 1,
                          "maximum": 99
                        },
                        "answers": {
                          "description": "Answers to the service's questions (`ug_service_questions`). Any price difference is read from the catalog, never from the caller; a missing required answer is 400 `INVALID_SERVICE_ANSWER`.",
                          "maxItems": 20,
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "question_id": {
                                "description": "Question id.",
                                "type": "string",
                                "minLength": 1
                              },
                              "option_ids": {
                                "description": "Chosen options for select questions.",
                                "type": "array",
                                "items": {
                                  "type": "string"
                                }
                              },
                              "text": {
                                "anyOf": [
                                  {
                                    "type": "string"
                                  },
                                  {
                                    "type": "null"
                                  }
                                ]
                              },
                              "number": {
                                "anyOf": [
                                  {
                                    "type": "number"
                                  },
                                  {
                                    "type": "null"
                                  }
                                ]
                              },
                              "photos": {
                                "description": "Photo question: URLs from `POST /uploads/photo`.",
                                "type": "array",
                                "items": {
                                  "type": "string"
                                }
                              },
                              "entry_id": {
                                "description": "Catalog question (brand/model): an entry id from `GET /reference-catalogs/{key}`.",
                                "anyOf": [
                                  {
                                    "type": "string"
                                  },
                                  {
                                    "type": "null"
                                  }
                                ]
                              },
                              "entry_label": {
                                "anyOf": [
                                  {
                                    "type": "string"
                                  },
                                  {
                                    "type": "null"
                                  }
                                ]
                              }
                            },
                            "required": [
                              "question_id"
                            ]
                          }
                        }
                      }
                    }
                  },
                  "appointment_date": {
                    "description": "Appointment day, `YYYY-MM-DD`.",
                    "type": "string",
                    "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                  },
                  "appointment_slot": {
                    "description": "Appointment slot, the `slot` value from `GET /appointment-slots` (e.g. `09:00-11:00`).",
                    "type": "string",
                    "minLength": 1
                  },
                  "city": {
                    "description": "Province, e.g. `İstanbul`. Coverage and zone pricing key on it.",
                    "type": "string",
                    "minLength": 1
                  },
                  "district": {
                    "description": "District, e.g. `Kadıköy`.",
                    "type": "string",
                    "minLength": 1
                  },
                  "address_summary": {
                    "description": "The full address the usta goes to (street, number, flat).",
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 500
                  },
                  "notes": {
                    "description": "The customer's description of the job.",
                    "type": "string",
                    "maxLength": 2000
                  },
                  "photos": {
                    "description": "URLs returned by `POST /uploads/photo` (at most 5). URLs this server did not mint are dropped silently.",
                    "anyOf": [
                      {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      {
                        "type": "string"
                      }
                    ]
                  },
                  "latitude": {
                    "description": "Latitude of the address.",
                    "type": "number",
                    "minimum": -90,
                    "maximum": 90
                  },
                  "longitude": {
                    "description": "Longitude of the address.",
                    "type": "number",
                    "minimum": -180,
                    "maximum": 180
                  },
                  "billing": {
                    "type": "object",
                    "properties": {
                      "type": {
                        "description": "`corporate` means a company invoice; the other fields are read only then.",
                        "type": "string",
                        "enum": [
                          "individual",
                          "corporate"
                        ]
                      },
                      "tax_id": {
                        "description": "Tax number (10) or national id (11 digits).",
                        "type": "string"
                      },
                      "tax_office": {
                        "type": "string"
                      },
                      "company": {
                        "type": "string"
                      },
                      "e_invoice": {
                        "type": "boolean"
                      }
                    },
                    "required": [
                      "type"
                    ]
                  },
                  "legal_acceptance": {
                    "type": "object",
                    "properties": {
                      "documents": {
                        "description": "Key and version of each contract the customer read (`GET /legal`). If a newer version was published since, 409 `LEGAL_VERSION_CHANGED`.",
                        "minItems": 1,
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "key": {
                              "type": "string"
                            },
                            "version": {
                              "type": "integer",
                              "minimum": 1
                            }
                          },
                          "required": [
                            "key",
                            "version"
                          ]
                        }
                      },
                      "payment_method": {
                        "type": "string",
                        "enum": [
                          "card",
                          "bank_transfer"
                        ]
                      }
                    },
                    "required": [
                      "documents"
                    ]
                  }
                },
                "required": [
                  "items",
                  "appointment_date",
                  "appointment_slot",
                  "city",
                  "district",
                  "address_summary"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "request": {
                      "description": "The first leg (the booking itself for a single-trade basket).",
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "reference": {
                          "description": "The booking number shown to customers and staff (`UG-102609123456`).",
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "status": {
                          "type": "string"
                        },
                        "amount": {
                          "description": "Server-computed amount, whole TRY.",
                          "anyOf": [
                            {
                              "type": "number"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "appointment_date": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "appointment_slot": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "group_id": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        }
                      },
                      "required": [
                        "id",
                        "status",
                        "amount",
                        "appointment_date",
                        "appointment_slot"
                      ],
                      "additionalProperties": {}
                    },
                    "requests": {
                      "description": "Every leg; each gets its own payment.",
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "reference": {
                            "description": "The booking number shown to customers and staff (`UG-102609123456`).",
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "status": {
                            "type": "string"
                          },
                          "amount": {
                            "description": "Server-computed amount, whole TRY.",
                            "anyOf": [
                              {
                                "type": "number"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "appointment_date": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "appointment_slot": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "group_id": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "status",
                          "amount",
                          "appointment_date",
                          "appointment_slot"
                        ],
                        "additionalProperties": {}
                      }
                    },
                    "group_id": {
                      "description": "Ties the legs together when there is more than one trade; otherwise `null`.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "request",
                    "requests",
                    "group_id"
                  ],
                  "additionalProperties": {}
                },
                "example": {
                  "request": {
                    "id": "01J00000000000000000000000",
                    "reference": "UG-102610123456",
                    "customer_id": "cus_01J00000000000000000000000",
                    "product_id": "prod_01J00000000000000000000000",
                    "variant_id": "variant_01J00000000000000000000000",
                    "items": [
                      {
                        "title": "Klima Bakımı — Standart",
                        "quantity": 1,
                        "unit_price": 750,
                        "product_id": "prod_01J00000000000000000000000",
                        "variant_id": "variant_01J00000000000000000000000",
                        "base_price": 750
                      }
                    ],
                    "category_handle": "klima",
                    "group_id": null,
                    "group_order": null,
                    "title": "Klima Bakımı — Standart",
                    "notes": null,
                    "status": "pending",
                    "pricing_type": "fixed",
                    "fixed_price_checkout": true,
                    "amount": 750,
                    "currency_code": "try",
                    "appointment_date": "2026-10-06",
                    "appointment_slot": "09:00-11:00",
                    "address_summary": "Test Sok. 1 D:2",
                    "assigned_usta_id": null,
                    "cart_id": null,
                    "order_id": null,
                    "cancelled_at": null,
                    "cancel_reason": null,
                    "cancelled_by": null,
                    "metadata": {
                      "ug_fixed_price_checkout": true,
                      "ug_pricing_type": "fixed",
                      "city": "İstanbul",
                      "district": "Kadıköy"
                    },
                    "created_at": "2026-10-01T09:00:00.000Z",
                    "updated_at": "2026-10-01T09:00:00.000Z",
                    "deleted_at": null
                  },
                  "requests": [
                    {
                      "id": "01J00000000000000000000000",
                      "reference": "UG-102610123456",
                      "customer_id": "cus_01J00000000000000000000000",
                      "product_id": "prod_01J00000000000000000000000",
                      "variant_id": "variant_01J00000000000000000000000",
                      "items": [
                        {
                          "title": "Klima Bakımı — Standart",
                          "quantity": 1,
                          "unit_price": 750,
                          "product_id": "prod_01J00000000000000000000000",
                          "variant_id": "variant_01J00000000000000000000000",
                          "base_price": 750
                        }
                      ],
                      "category_handle": "klima",
                      "group_id": null,
                      "group_order": null,
                      "title": "Klima Bakımı — Standart",
                      "notes": null,
                      "status": "pending",
                      "pricing_type": "fixed",
                      "fixed_price_checkout": true,
                      "amount": 750,
                      "currency_code": "try",
                      "appointment_date": "2026-10-06",
                      "appointment_slot": "09:00-11:00",
                      "address_summary": "Test Sok. 1 D:2",
                      "assigned_usta_id": null,
                      "cart_id": null,
                      "order_id": null,
                      "cancelled_at": null,
                      "cancel_reason": null,
                      "cancelled_by": null,
                      "metadata": {
                        "ug_fixed_price_checkout": true,
                        "ug_pricing_type": "fixed",
                        "city": "İstanbul",
                        "district": "Kadıköy"
                      },
                      "created_at": "2026-10-01T09:00:00.000Z",
                      "updated_at": "2026-10-01T09:00:00.000Z",
                      "deleted_at": null
                    }
                  ],
                  "group_id": null
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.\n\n- `VALIDATION_ERROR` — The request failed validation; see `issues`.\n- `APPOINTMENT_REQUIRED` — Appointment date and slot are required.\n- `INVALID_SERVICE_ANSWER` — A service question's answer is missing or invalid; see `errors`.\n- `INVALID_SERVICE_ITEM` — A service was not found or is not published.\n- `LOCATION_REQUIRED` — Province/district is missing.\n- `ADDRESS_REQUIRED` — The job's address is required.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "VALIDATION_ERROR": {
                    "value": {
                      "message": "The request failed validation; see `issues`.",
                      "code": "VALIDATION_ERROR"
                    }
                  },
                  "APPOINTMENT_REQUIRED": {
                    "value": {
                      "message": "Appointment date and slot are required.",
                      "code": "APPOINTMENT_REQUIRED"
                    }
                  },
                  "INVALID_SERVICE_ANSWER": {
                    "value": {
                      "message": "A service question's answer is missing or invalid; see `errors`.",
                      "code": "INVALID_SERVICE_ANSWER"
                    }
                  },
                  "INVALID_SERVICE_ITEM": {
                    "value": {
                      "message": "A service was not found or is not published.",
                      "code": "INVALID_SERVICE_ITEM"
                    }
                  },
                  "LOCATION_REQUIRED": {
                    "value": {
                      "message": "Province/district is missing.",
                      "code": "LOCATION_REQUIRED"
                    }
                  },
                  "ADDRESS_REQUIRED": {
                    "value": {
                      "message": "The job's address is required.",
                      "code": "ADDRESS_REQUIRED"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_ROLE_REQUIRED` — This operation is not available to the key's role.\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_ROLE_REQUIRED": {
                    "value": {
                      "message": "This operation is not available to the key's role.",
                      "code": "PARTNER_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "The record's current state does not allow this.\n\n- `SLOT_CONFLICT` — Another booking already holds this date and slot.\n- `LEGAL_VERSION_CHANGED` — A newer contract version was published; it must be read and accepted again.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "SLOT_CONFLICT": {
                    "value": {
                      "message": "Another booking already holds this date and slot.",
                      "code": "SLOT_CONFLICT"
                    }
                  },
                  "LEGAL_VERSION_CHANGED": {
                    "value": {
                      "message": "A newer contract version was published; it must be read and accepted again.",
                      "code": "LEGAL_VERSION_CHANGED"
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable request.\n\n- `SERVICE_AREA_NOT_COVERED` — Not offered in this area; `uncovered` lists the services.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "SERVICE_AREA_NOT_COVERED": {
                    "value": {
                      "message": "Not offered in this area; `uncovered` lists the services.",
                      "code": "SERVICE_AREA_NOT_COVERED"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "customer",
        "x-ug-scope": "write",
        "x-ug-error-codes": [
          "APPOINTMENT_REQUIRED",
          "SLOT_CONFLICT",
          "INVALID_SERVICE_ANSWER",
          "INVALID_SERVICE_ITEM",
          "LOCATION_REQUIRED",
          "SERVICE_AREA_NOT_COVERED",
          "ADDRESS_REQUIRED",
          "LEGAL_VERSION_CHANGED"
        ],
        "x-ai-hint": "Show the amount with `POST /pricing/preview` first, then call this, then `POST /payments`."
      }
    },
    "/bookings/{id}": {
      "get": {
        "operationId": "getBooking",
        "tags": [
          "Bookings"
        ],
        "summary": "Get a booking",
        "description": "One booking: status, appointment, address, lines (with answers), the assigned usta (once they accepted), group siblings and the visit start code. Stages: `pending`/`assigned` searching for an usta, `accepted` usta assigned, on the way when `metadata.on_the_way_at` is set, `in_progress`, `completed` (awaiting your confirmation), `confirmed`.\n\n**Access:** customer key · scope `read`",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The record's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "request": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "reference": {
                          "description": "The booking number shown to customers and staff (`UG-102609123456`).",
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "status": {
                          "type": "string"
                        },
                        "amount": {
                          "description": "Server-computed amount, whole TRY.",
                          "anyOf": [
                            {
                              "type": "number"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "appointment_date": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "appointment_slot": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "group_id": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        }
                      },
                      "required": [
                        "id",
                        "status",
                        "amount",
                        "appointment_date",
                        "appointment_slot"
                      ],
                      "additionalProperties": {}
                    }
                  },
                  "required": [
                    "request"
                  ],
                  "additionalProperties": {}
                },
                "example": {
                  "request": {
                    "id": "01J00000000000000000000000",
                    "reference": "UG-102610123456",
                    "customer_id": "cus_01J00000000000000000000000",
                    "product_id": "prod_01J00000000000000000000000",
                    "variant_id": "variant_01J00000000000000000000000",
                    "items": [
                      {
                        "title": "Klima Bakımı — Standart",
                        "quantity": 1,
                        "base_price": 750,
                        "product_id": "prod_01J00000000000000000000000",
                        "unit_price": 750,
                        "variant_id": "variant_01J00000000000000000000000"
                      }
                    ],
                    "category_handle": "klima",
                    "group_id": null,
                    "group_order": null,
                    "title": "Klima Bakımı — Standart",
                    "notes": null,
                    "status": "pending",
                    "pricing_type": "fixed",
                    "fixed_price_checkout": true,
                    "amount": 750,
                    "currency_code": "try",
                    "appointment_date": "2026-10-06",
                    "appointment_slot": "09:00-11:00",
                    "address_summary": "Test Sok. 1 D:2",
                    "assigned_usta_id": null,
                    "cart_id": null,
                    "order_id": null,
                    "cancelled_at": null,
                    "cancel_reason": null,
                    "cancelled_by": null,
                    "metadata": {
                      "city": "İstanbul",
                      "district": "Kadıköy",
                      "offered_at": "2026-10-01T09:00:00.000Z",
                      "dispatch_note": "no_matching_usta",
                      "ug_pricing_type": "fixed",
                      "offered_usta_ids": [],
                      "ug_fixed_price_checkout": true
                    },
                    "created_at": "2026-10-01T09:00:00.000Z",
                    "updated_at": "2026-10-01T09:00:00.000Z",
                    "deleted_at": null,
                    "assigned_usta": null,
                    "customer": {
                      "id": "cus_01J00000000000000000000000",
                      "display_name": "odeme T."
                    },
                    "group_siblings": null,
                    "order": null
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_ROLE_REQUIRED` — This operation is not available to the key's role.\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_ROLE_REQUIRED": {
                    "value": {
                      "message": "This operation is not available to the key's role.",
                      "code": "PARTNER_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found.\n\n- `NOT_FOUND` — Not found, or not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "NOT_FOUND": {
                    "value": {
                      "message": "Not found, or not yours.",
                      "code": "NOT_FOUND"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "customer",
        "x-ug-scope": "read"
      }
    },
    "/bookings/{id}/cancel": {
      "post": {
        "operationId": "cancelBooking",
        "tags": [
          "Bookings"
        ],
        "summary": "Cancel a booking",
        "description": "Decides by stage: no payment → cancelled; before the usta starts → full refund request; usta on the way → refund request minus the call-out fee; job started → 409 `CANCEL_NOT_ALLOWED` (open a dispute). No money moves on cancel: the team executes the refund request.\n\n**Access:** customer key · scope `write`",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The record's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string",
                    "maxLength": 1000
                  },
                  "scope": {
                    "description": "`group`: every leg of a grouped booking.",
                    "type": "string",
                    "enum": [
                      "single",
                      "group"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "request": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "id"
                          ],
                          "additionalProperties": {}
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "legs": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {},
                        "additionalProperties": {}
                      }
                    },
                    "refund_requests": {
                      "description": "A refund request per held payment; no money moves on cancel, the team executes the refund.",
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {},
                        "additionalProperties": {}
                      }
                    }
                  },
                  "required": [
                    "request",
                    "legs",
                    "refund_requests"
                  ],
                  "additionalProperties": {}
                },
                "example": {
                  "request": {
                    "id": "01J00000000000000000000000",
                    "reference": "UG-102610123456",
                    "customer_id": "cus_01J00000000000000000000000",
                    "product_id": "prod_01J00000000000000000000000",
                    "variant_id": "variant_01J00000000000000000000000",
                    "items": [
                      {
                        "title": "Klima Bakımı — Standart",
                        "quantity": 1,
                        "base_price": 750,
                        "product_id": "prod_01J00000000000000000000000",
                        "unit_price": 750,
                        "variant_id": "variant_01J00000000000000000000000"
                      }
                    ],
                    "category_handle": "klima",
                    "group_id": null,
                    "group_order": null,
                    "title": "Klima Bakımı — Standart",
                    "notes": null,
                    "status": "cancelled",
                    "pricing_type": "fixed",
                    "fixed_price_checkout": true,
                    "amount": 750,
                    "currency_code": "try",
                    "appointment_date": "2026-10-06",
                    "appointment_slot": "09:00-11:00",
                    "address_summary": "Test Sok. 1 D:2",
                    "assigned_usta_id": null,
                    "cart_id": null,
                    "order_id": null,
                    "cancelled_at": "2026-10-01T09:00:00.000Z",
                    "cancel_reason": "Planım değişti",
                    "cancelled_by": "cus_01J00000000000000000000000",
                    "metadata": {
                      "city": "İstanbul",
                      "district": "Kadıköy",
                      "offered_at": "2026-10-01T09:00:00.000Z",
                      "dispatch_note": "no_matching_usta",
                      "ug_pricing_type": "fixed",
                      "offered_usta_ids": [],
                      "ug_fixed_price_checkout": true,
                      "cancelled_at": "2026-10-01T09:00:00.000Z",
                      "cancelled_by_role": "customer"
                    },
                    "created_at": "2026-10-01T09:00:00.000Z",
                    "updated_at": "2026-10-01T09:00:00.000Z",
                    "deleted_at": null
                  },
                  "legs": [
                    {
                      "request": {
                        "id": "01J00000000000000000000000",
                        "reference": "UG-102610123456",
                        "customer_id": "cus_01J00000000000000000000000",
                        "product_id": "prod_01J00000000000000000000000",
                        "variant_id": "variant_01J00000000000000000000000",
                        "items": [
                          {
                            "title": "Klima Bakımı — Standart",
                            "quantity": 1,
                            "base_price": 750,
                            "product_id": "prod_01J00000000000000000000000",
                            "unit_price": 750,
                            "variant_id": "variant_01J00000000000000000000000"
                          }
                        ],
                        "category_handle": "klima",
                        "group_id": null,
                        "group_order": null,
                        "title": "Klima Bakımı — Standart",
                        "notes": null,
                        "status": "cancelled",
                        "pricing_type": "fixed",
                        "fixed_price_checkout": true,
                        "amount": 750,
                        "currency_code": "try",
                        "appointment_date": "2026-10-06",
                        "appointment_slot": "09:00-11:00",
                        "address_summary": "Test Sok. 1 D:2",
                        "assigned_usta_id": null,
                        "cart_id": null,
                        "order_id": null,
                        "cancelled_at": "2026-10-01T09:00:00.000Z",
                        "cancel_reason": "Planım değişti",
                        "cancelled_by": "cus_01J00000000000000000000000",
                        "metadata": {
                          "city": "İstanbul",
                          "district": "Kadıköy",
                          "offered_at": "2026-10-01T09:00:00.000Z",
                          "dispatch_note": "no_matching_usta",
                          "ug_pricing_type": "fixed",
                          "offered_usta_ids": [],
                          "ug_fixed_price_checkout": true,
                          "cancelled_at": "2026-10-01T09:00:00.000Z",
                          "cancelled_by_role": "customer"
                        },
                        "created_at": "2026-10-01T09:00:00.000Z",
                        "updated_at": "2026-10-01T09:00:00.000Z",
                        "deleted_at": null
                      },
                      "outcome": {
                        "allowed": true,
                        "refund": "full",
                        "fee": 0,
                        "refund_amount": 750
                      },
                      "refund_requests": [
                        {
                          "escrow_id": "01J00000000000000000000000",
                          "ticket_id": "01J00000000000000000000000",
                          "amount": 750
                        }
                      ]
                    }
                  ],
                  "refund_requests": [
                    {
                      "escrow_id": "01J00000000000000000000000",
                      "ticket_id": "01J00000000000000000000000",
                      "amount": 750
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.\n\n- `VALIDATION_ERROR` — The request failed validation; see `issues`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "VALIDATION_ERROR": {
                    "value": {
                      "message": "The request failed validation; see `issues`.",
                      "code": "VALIDATION_ERROR"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_ROLE_REQUIRED` — This operation is not available to the key's role.\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_ROLE_REQUIRED": {
                    "value": {
                      "message": "This operation is not available to the key's role.",
                      "code": "PARTNER_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found.\n\n- `REQUEST_NOT_FOUND` — Booking not found.\n- `GROUP_NOT_ALLOWED` — Group not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "REQUEST_NOT_FOUND": {
                    "value": {
                      "message": "Booking not found.",
                      "code": "REQUEST_NOT_FOUND"
                    }
                  },
                  "GROUP_NOT_ALLOWED": {
                    "value": {
                      "message": "Group not found.",
                      "code": "GROUP_NOT_ALLOWED"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "The record's current state does not allow this.\n\n- `CANCEL_NOT_ALLOWED` — The job cannot be cancelled at this stage; open a dispute instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "CANCEL_NOT_ALLOWED": {
                    "value": {
                      "message": "The job cannot be cancelled at this stage; open a dispute instead.",
                      "code": "CANCEL_NOT_ALLOWED"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "customer",
        "x-ug-scope": "write",
        "x-ug-error-codes": [
          "CANCEL_NOT_ALLOWED",
          "REQUEST_NOT_FOUND",
          "GROUP_NOT_ALLOWED"
        ]
      }
    },
    "/bookings/{id}/confirm": {
      "post": {
        "operationId": "confirmBooking",
        "tags": [
          "Bookings"
        ],
        "summary": "Confirm the job",
        "description": "Confirms the completed job and releases every held payment to the usta. Irreversible. 409 while a refund request or dispute is open.\n\n**Access:** customer key · scope `money`",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The record's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "request": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id"
                      ],
                      "additionalProperties": {}
                    },
                    "escrows": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "status"
                        ],
                        "additionalProperties": {}
                      }
                    },
                    "total_payout": {
                      "type": "number"
                    }
                  },
                  "required": [
                    "request",
                    "escrows",
                    "total_payout"
                  ],
                  "additionalProperties": {}
                },
                "example": {
                  "request": {
                    "id": "01J00000000000000000000000",
                    "reference": "UG-102610123456",
                    "customer_id": "cus_01J00000000000000000000000",
                    "product_id": "prod_01J00000000000000000000000",
                    "variant_id": "variant_01J00000000000000000000000",
                    "items": [
                      {
                        "title": "Klima Bakımı — Standart",
                        "quantity": 1,
                        "base_price": 750,
                        "product_id": "prod_01J00000000000000000000000",
                        "unit_price": 750,
                        "variant_id": "variant_01J00000000000000000000000"
                      }
                    ],
                    "category_handle": "klima",
                    "group_id": null,
                    "group_order": null,
                    "title": "Klima Bakımı — Standart",
                    "notes": null,
                    "status": "completed",
                    "pricing_type": "fixed",
                    "fixed_price_checkout": true,
                    "amount": 750,
                    "currency_code": "try",
                    "appointment_date": "2026-10-06",
                    "appointment_slot": "09:00-11:00",
                    "address_summary": "Test Sok. 1 D:2",
                    "assigned_usta_id": "cus_01J00000000000000000000000",
                    "cart_id": null,
                    "order_id": null,
                    "cancelled_at": null,
                    "cancel_reason": null,
                    "cancelled_by": null,
                    "metadata": {
                      "city": "İstanbul",
                      "district": "Kadıköy",
                      "offered_at": "2026-10-01T09:00:00.000Z",
                      "start_code": "482913",
                      "started_at": "2026-10-01T09:00:00.000Z",
                      "completed_at": "2026-10-01T09:00:00.000Z",
                      "dispatch_note": null,
                      "on_the_way_at": "2026-10-01T09:00:00.000Z",
                      "start_code_at": "2026-10-01T09:00:00.000Z",
                      "completion_code": "482913",
                      "completion_note": "Klima bakımı yapıldı, filtreler temizlendi, gaz basıncı ölçüldü ve dolum tamamlandı.",
                      "ug_pricing_type": "fixed",
                      "offered_usta_ids": [
                        "cus_01J00000000000000000000000"
                      ],
                      "completion_photos": [
                        {
                          "url": "https://api.example.com/static/shared/private-1790000000000-ug-cus_01J00000000000000000000000-1790000000000.png"
                        }
                      ],
                      "completion_code_at": "2026-10-01T09:00:00.000Z",
                      "ug_fixed_price_checkout": true,
                      "confirmed_at": "2026-10-01T09:00:00.000Z"
                    },
                    "created_at": "2026-10-01T09:00:00.000Z",
                    "updated_at": "2026-10-01T09:00:00.000Z",
                    "deleted_at": null
                  },
                  "escrow": {
                    "id": "01J00000000000000000000000",
                    "order_id": null,
                    "service_request_id": "01J00000000000000000000000",
                    "customer_id": "cus_01J00000000000000000000000",
                    "usta_id": "cus_01J00000000000000000000000",
                    "kind": "primary",
                    "extra_work_id": null,
                    "amount": 750,
                    "currency_code": "try",
                    "commission_rate": 0.15,
                    "commission_amount": 112,
                    "payout_amount": 638,
                    "refunded_amount": 0,
                    "status": "released_to_technician",
                    "provider": "card-mock",
                    "payment_session_id": null,
                    "transaction_id": "MOCK-01J00000000000000000000000",
                    "released_at": "2026-10-01T09:00:00.000Z",
                    "held_at": "2026-10-01T09:00:00.000Z",
                    "disputed_at": null,
                    "dispute_reason": null,
                    "refund_requested_at": null,
                    "refunded_at": null,
                    "refund_reason": null,
                    "refund_reference": null,
                    "refund_channel": null,
                    "refund_ticket_id": null,
                    "metadata": {
                      "released_at": "2026-10-01T09:00:00.000Z",
                      "payout_provider": "stub",
                      "payout_reference": "PAYOUT-STUB-1790000000000-000000",
                      "commission_source": "services"
                    },
                    "created_at": "2026-10-01T09:00:00.000Z",
                    "updated_at": "2026-10-01T09:00:00.000Z",
                    "deleted_at": null
                  },
                  "escrows": [
                    {
                      "id": "01J00000000000000000000000",
                      "order_id": null,
                      "service_request_id": "01J00000000000000000000000",
                      "customer_id": "cus_01J00000000000000000000000",
                      "usta_id": "cus_01J00000000000000000000000",
                      "kind": "primary",
                      "extra_work_id": null,
                      "amount": 750,
                      "currency_code": "try",
                      "commission_rate": 0.15,
                      "commission_amount": 112,
                      "payout_amount": 638,
                      "refunded_amount": 0,
                      "status": "released_to_technician",
                      "provider": "card-mock",
                      "payment_session_id": null,
                      "transaction_id": "MOCK-01J00000000000000000000000",
                      "released_at": "2026-10-01T09:00:00.000Z",
                      "held_at": "2026-10-01T09:00:00.000Z",
                      "disputed_at": null,
                      "dispute_reason": null,
                      "refund_requested_at": null,
                      "refunded_at": null,
                      "refund_reason": null,
                      "refund_reference": null,
                      "refund_channel": null,
                      "refund_ticket_id": null,
                      "metadata": {
                        "released_at": "2026-10-01T09:00:00.000Z",
                        "payout_provider": "stub",
                        "payout_reference": "PAYOUT-STUB-1790000000000-000000",
                        "commission_source": "services"
                      },
                      "created_at": "2026-10-01T09:00:00.000Z",
                      "updated_at": "2026-10-01T09:00:00.000Z",
                      "deleted_at": null
                    },
                    {
                      "id": "01J00000000000000000000000",
                      "order_id": null,
                      "service_request_id": "01J00000000000000000000000",
                      "customer_id": "cus_01J00000000000000000000000",
                      "usta_id": "cus_01J00000000000000000000000",
                      "kind": "extra_work",
                      "extra_work_id": "01J00000000000000000000000",
                      "amount": 400,
                      "currency_code": "try",
                      "commission_rate": 0.15,
                      "commission_amount": 60,
                      "payout_amount": 340,
                      "refunded_amount": 0,
                      "status": "released_to_technician",
                      "provider": "card-mock",
                      "payment_session_id": null,
                      "transaction_id": "MOCK-EXTRA-01J00000000000000000000000",
                      "released_at": "2026-10-01T09:00:00.000Z",
                      "held_at": "2026-10-01T09:00:00.000Z",
                      "disputed_at": null,
                      "dispute_reason": null,
                      "refund_requested_at": null,
                      "refunded_at": null,
                      "refund_reason": null,
                      "refund_reference": null,
                      "refund_channel": null,
                      "refund_ticket_id": null,
                      "metadata": {
                        "released_at": "2026-10-01T09:00:00.000Z",
                        "payout_provider": "stub",
                        "payout_reference": "PAYOUT-STUB-1790000000000-000000",
                        "commission_source": "services"
                      },
                      "created_at": "2026-10-01T09:00:00.000Z",
                      "updated_at": "2026-10-01T09:00:00.000Z",
                      "deleted_at": null
                    }
                  ],
                  "total_payout": 978
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_ROLE_REQUIRED` — This operation is not available to the key's role.\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_ROLE_REQUIRED": {
                    "value": {
                      "message": "This operation is not available to the key's role.",
                      "code": "PARTNER_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found.\n\n- `NOT_FOUND` — Not found, or not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "NOT_FOUND": {
                    "value": {
                      "message": "Not found, or not yours.",
                      "code": "NOT_FOUND"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "The record's current state does not allow this.\n\n- `REFUND_REQUEST_PENDING` — A refund request is pending and must be settled first.\n- `ESCROW_DISPUTED` — The payment is under dispute.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "REFUND_REQUEST_PENDING": {
                    "value": {
                      "message": "A refund request is pending and must be settled first.",
                      "code": "REFUND_REQUEST_PENDING"
                    }
                  },
                  "ESCROW_DISPUTED": {
                    "value": {
                      "message": "The payment is under dispute.",
                      "code": "ESCROW_DISPUTED"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "customer",
        "x-ug-scope": "money",
        "x-ug-error-codes": [
          "REFUND_REQUEST_PENDING",
          "ESCROW_DISPUTED"
        ],
        "x-ai-hint": "Call only after the customer explicitly confirmed the work is done."
      }
    },
    "/bookings/{id}/contracts": {
      "get": {
        "operationId": "getBookingContracts",
        "tags": [
          "Bookings"
        ],
        "summary": "Get the accepted contracts",
        "description": "The server-filled copy of the contracts accepted with this booking.\n\n**Access:** customer key · scope `read`",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The record's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "acceptance": {}
                  },
                  "required": [
                    "acceptance"
                  ],
                  "additionalProperties": {}
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_ROLE_REQUIRED` — This operation is not available to the key's role.\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_ROLE_REQUIRED": {
                    "value": {
                      "message": "This operation is not available to the key's role.",
                      "code": "PARTNER_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found.\n\n- `NOT_FOUND` — Not found, or not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "NOT_FOUND": {
                    "value": {
                      "message": "Not found, or not yours.",
                      "code": "NOT_FOUND"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "customer",
        "x-ug-scope": "read"
      }
    },
    "/bookings/{id}/photos": {
      "post": {
        "operationId": "addBookingPhotos",
        "tags": [
          "Bookings"
        ],
        "summary": "Add photos",
        "description": "Sets the job's photos before an usta is assigned. After assignment: 409 `PHOTOS_LOCKED`.\n\n**Access:** customer key · scope `write`",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The record's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "photos": {
                    "description": "URLs returned by `POST /uploads/photo` (at most 5). URLs this server did not mint are dropped silently.",
                    "anyOf": [
                      {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      {
                        "type": "string"
                      }
                    ]
                  }
                },
                "required": [
                  "photos"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "request": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id"
                      ],
                      "additionalProperties": {}
                    },
                    "photos": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  },
                  "required": [
                    "request",
                    "photos"
                  ],
                  "additionalProperties": {}
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.\n\n- `VALIDATION_ERROR` — The request failed validation; see `issues`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "VALIDATION_ERROR": {
                    "value": {
                      "message": "The request failed validation; see `issues`.",
                      "code": "VALIDATION_ERROR"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_ROLE_REQUIRED` — This operation is not available to the key's role.\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_ROLE_REQUIRED": {
                    "value": {
                      "message": "This operation is not available to the key's role.",
                      "code": "PARTNER_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found.\n\n- `NOT_FOUND` — Not found, or not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "NOT_FOUND": {
                    "value": {
                      "message": "Not found, or not yours.",
                      "code": "NOT_FOUND"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "The record's current state does not allow this.\n\n- `PHOTOS_LOCKED` — Photos cannot be added once an usta is assigned.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PHOTOS_LOCKED": {
                    "value": {
                      "message": "Photos cannot be added once an usta is assigned.",
                      "code": "PHOTOS_LOCKED"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "customer",
        "x-ug-scope": "write",
        "x-ug-error-codes": [
          "PHOTOS_LOCKED"
        ]
      }
    },
    "/bookings/{id}/reschedule": {
      "post": {
        "operationId": "answerReschedule",
        "tags": [
          "Bookings"
        ],
        "summary": "Answer a reschedule proposal",
        "description": "Accepts or rejects the time the usta proposed.\n\n**Access:** customer key · scope `write`",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The record's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "accept": {
                    "description": "`true` accepts the usta's proposed time, `false` rejects it.",
                    "type": "boolean"
                  }
                },
                "required": [
                  "accept"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "request": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id"
                      ],
                      "additionalProperties": {}
                    },
                    "accepted": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "request",
                    "accepted"
                  ],
                  "additionalProperties": {}
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.\n\n- `VALIDATION_ERROR` — The request failed validation; see `issues`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "VALIDATION_ERROR": {
                    "value": {
                      "message": "The request failed validation; see `issues`.",
                      "code": "VALIDATION_ERROR"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_ROLE_REQUIRED` — This operation is not available to the key's role.\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_ROLE_REQUIRED": {
                    "value": {
                      "message": "This operation is not available to the key's role.",
                      "code": "PARTNER_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found.\n\n- `NOT_FOUND` — Not found, or not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "NOT_FOUND": {
                    "value": {
                      "message": "Not found, or not yours.",
                      "code": "NOT_FOUND"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "The record's current state does not allow this.\n\n- `NO_PENDING_RESCHEDULE` — There is no pending reschedule proposal.\n- `SLOT_CONFLICT` — Another booking already holds this date and slot.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "NO_PENDING_RESCHEDULE": {
                    "value": {
                      "message": "There is no pending reschedule proposal.",
                      "code": "NO_PENDING_RESCHEDULE"
                    }
                  },
                  "SLOT_CONFLICT": {
                    "value": {
                      "message": "Another booking already holds this date and slot.",
                      "code": "SLOT_CONFLICT"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "customer",
        "x-ug-scope": "write",
        "x-ug-error-codes": [
          "NO_PENDING_RESCHEDULE",
          "SLOT_CONFLICT"
        ]
      }
    },
    "/campaigns": {
      "get": {
        "operationId": "listCampaigns",
        "tags": [
          "Catalog"
        ],
        "summary": "List campaigns",
        "description": "Live campaigns (the app's home-screen banners) and their remaining quotas.\n\n**Access:** either role · scope `read`",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "campaigns": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id"
                        ],
                        "additionalProperties": {}
                      }
                    }
                  },
                  "required": [
                    "campaigns"
                  ],
                  "additionalProperties": {}
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "any",
        "x-ug-scope": "read"
      }
    },
    "/catalog": {
      "get": {
        "operationId": "getCatalog",
        "tags": [
          "Catalog"
        ],
        "summary": "Get the catalog",
        "description": "Every published category and service: packages (variants), starting price, zone prices and service questions. Take `variant_id`/`product_id` for a booking from here. Carries an `ETag`; answers 304 to a matching `If-None-Match`.\n\n**Access:** either role · scope `read`",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "categories": {
                      "description": "Categories in the panel's order. `ug_status` is `active` or `coming_soon` (visible, not bookable); passive ones are omitted.",
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "handle": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "handle"
                        ],
                        "additionalProperties": {}
                      }
                    },
                    "products": {
                      "description": "Published services with variants, `ug_min_price`, `ug_zone_prices` and `ug_service_questions`.",
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "handle": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "title",
                          "handle"
                        ],
                        "additionalProperties": {}
                      }
                    }
                  },
                  "required": [
                    "categories",
                    "products"
                  ],
                  "additionalProperties": {}
                },
                "example": {
                  "categories": [
                    {
                      "id": "pcat_01J00000000000000000000000",
                      "name": "Klima",
                      "handle": "klima",
                      "description": "",
                      "is_active": true,
                      "rank": 0,
                      "metadata": {},
                      "icon": "ac-unit",
                      "color": "#0066FF",
                      "backgroundColor": "#e0f2fe",
                      "image": "https://images.unsplash.com/photo-1790000000000-08b45d6a269e?q=80&w=400&auto=format&fit=crop",
                      "card_mode": null,
                      "text_color": null,
                      "ug_min_price": null,
                      "ug_max_price": null,
                      "ug_status": "active",
                      "ug_coming_soon": false,
                      "ug_product_count": 1
                    }
                  ],
                  "products": [
                    {
                      "id": "prod_01J00000000000000000000000",
                      "title": "Klima Bakımı",
                      "handle": "klima-bakimi",
                      "description": null,
                      "status": "published",
                      "metadata": {
                        "ug_pricing_type": "fixed",
                        "ug_service_areas": [
                          "istanbul"
                        ],
                        "ug_fixed_price_checkout": true
                      },
                      "thumbnail": null,
                      "categories": [
                        {
                          "id": "pcat_01J00000000000000000000000",
                          "handle": "klima",
                          "name": "Klima",
                          "metadata": {}
                        }
                      ],
                      "variants": [
                        {
                          "id": "variant_01J00000000000000000000000",
                          "title": "Standart",
                          "sku": null
                        }
                      ],
                      "ug_pricing_type": "fixed",
                      "ug_fixed_price_checkout": true,
                      "ug_min_price": null,
                      "ug_max_price": null,
                      "ug_zone_prices": {},
                      "ug_service_questions": [],
                      "ug_addons": []
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "any",
        "x-ug-scope": "read",
        "x-ai-hint": "Call once before booking and cache it; service ids come from here."
      }
    },
    "/catalog/search": {
      "get": {
        "operationId": "searchCatalog",
        "tags": [
          "Catalog"
        ],
        "summary": "Search the catalog",
        "description": "Full-text search over services, categories and content pages. At least 2 characters; returns empty lists when search is unavailable.\n\n**Access:** either role · scope `read`",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Search text, at least 2 characters.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum results, 1–50 (default 20).",
            "schema": {
              "type": "string",
              "pattern": "^\\d+$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "products": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id"
                        ],
                        "additionalProperties": {}
                      }
                    },
                    "categories": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id"
                        ],
                        "additionalProperties": {}
                      }
                    },
                    "pages": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id"
                        ],
                        "additionalProperties": {}
                      }
                    }
                  },
                  "required": [
                    "products",
                    "categories",
                    "pages"
                  ],
                  "additionalProperties": {}
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.\n\n- `VALIDATION_ERROR` — The request failed validation; see `issues`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "VALIDATION_ERROR": {
                    "value": {
                      "message": "The request failed validation; see `issues`.",
                      "code": "VALIDATION_ERROR"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "any",
        "x-ug-scope": "read"
      }
    },
    "/chat": {
      "get": {
        "operationId": "listChatThreads",
        "tags": [
          "Chat"
        ],
        "summary": "List chats",
        "description": "The account's chats with unread counts; the support chat first.\n\n**Access:** either role · scope `read`",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "threads": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "service_request_id": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "service_request_id"
                        ],
                        "additionalProperties": {}
                      }
                    }
                  },
                  "required": [
                    "threads"
                  ],
                  "additionalProperties": {}
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "any",
        "x-ug-scope": "read"
      }
    },
    "/chat/{serviceRequestId}": {
      "get": {
        "operationId": "getChat",
        "tags": [
          "Chat"
        ],
        "summary": "Get a chat",
        "description": "A job's chat (opens once an usta is assigned). With `after`, only new messages; read state is recorded.\n\n**Access:** either role · scope `read`",
        "parameters": [
          {
            "name": "serviceRequestId",
            "in": "path",
            "required": true,
            "description": "The booking's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "after",
            "in": "query",
            "required": false,
            "description": "The last message id you have; only newer messages come back (polling).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "thread": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id"
                      ],
                      "additionalProperties": {}
                    },
                    "messages": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id"
                        ],
                        "additionalProperties": {}
                      }
                    },
                    "incremental": {
                      "type": "boolean"
                    },
                    "viewer_role": {
                      "type": "string",
                      "enum": [
                        "customer",
                        "usta"
                      ]
                    }
                  },
                  "required": [
                    "thread",
                    "messages",
                    "incremental",
                    "viewer_role"
                  ],
                  "additionalProperties": {}
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.\n\n- `VALIDATION_ERROR` — The request failed validation; see `issues`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "VALIDATION_ERROR": {
                    "value": {
                      "message": "The request failed validation; see `issues`.",
                      "code": "VALIDATION_ERROR"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found.\n\n- `NOT_FOUND` — Not found, or not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "NOT_FOUND": {
                    "value": {
                      "message": "Not found, or not yours.",
                      "code": "NOT_FOUND"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "The record's current state does not allow this.\n\n- `NO_USTA_ASSIGNED` — No usta is assigned to this job.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "NO_USTA_ASSIGNED": {
                    "value": {
                      "message": "No usta is assigned to this job.",
                      "code": "NO_USTA_ASSIGNED"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "any",
        "x-ug-scope": "read",
        "x-ug-error-codes": [
          "NO_USTA_ASSIGNED"
        ]
      }
    },
    "/chat/{serviceRequestId}/messages": {
      "post": {
        "operationId": "sendChatMessage",
        "tags": [
          "Chat"
        ],
        "summary": "Send a message",
        "description": "Sends text (at most 2000 characters) or an image from `POST /uploads/photo`.\n\n**Access:** either role · scope `write`",
        "parameters": [
          {
            "name": "serviceRequestId",
            "in": "path",
            "required": true,
            "description": "The booking's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "body": {
                    "type": "string",
                    "maxLength": 2000
                  },
                  "image_url": {
                    "description": "A URL from `POST /uploads/photo`.",
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id"
                      ],
                      "additionalProperties": {}
                    },
                    "viewer_role": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "message",
                    "viewer_role"
                  ],
                  "additionalProperties": {}
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.\n\n- `VALIDATION_ERROR` — The request failed validation; see `issues`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "VALIDATION_ERROR": {
                    "value": {
                      "message": "The request failed validation; see `issues`.",
                      "code": "VALIDATION_ERROR"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found.\n\n- `NOT_FOUND` — Not found, or not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "NOT_FOUND": {
                    "value": {
                      "message": "Not found, or not yours.",
                      "code": "NOT_FOUND"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "The record's current state does not allow this.\n\n- `NO_USTA_ASSIGNED` — No usta is assigned to this job.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "NO_USTA_ASSIGNED": {
                    "value": {
                      "message": "No usta is assigned to this job.",
                      "code": "NO_USTA_ASSIGNED"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "any",
        "x-ug-scope": "write",
        "x-ug-error-codes": [
          "NO_USTA_ASSIGNED"
        ]
      }
    },
    "/extra-work": {
      "get": {
        "operationId": "listExtraWork",
        "tags": [
          "Extra work"
        ],
        "summary": "List extra work",
        "description": "The account's extra-work requests; one job's with `service_request_id`.\n\n**Access:** either role · scope `read`",
        "parameters": [
          {
            "name": "service_request_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "extra_works": {
                      "type": "array",
                      "items": {
                        "description": "An extra-work (extra charge) request.",
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "status": {
                            "description": "`pending_customer` → `approved` | `rejected` | `withdrawn`; `rejected` → counter-offer or `disputed`.",
                            "type": "string"
                          },
                          "service_request_id": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "status",
                          "service_request_id"
                        ],
                        "additionalProperties": {}
                      }
                    }
                  },
                  "required": [
                    "extra_works"
                  ],
                  "additionalProperties": {}
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.\n\n- `VALIDATION_ERROR` — The request failed validation; see `issues`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "VALIDATION_ERROR": {
                    "value": {
                      "message": "The request failed validation; see `issues`.",
                      "code": "VALIDATION_ERROR"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "any",
        "x-ug-scope": "read"
      },
      "post": {
        "operationId": "createExtraWork",
        "tags": [
          "Extra work"
        ],
        "summary": "Raise an extra charge",
        "description": "Puts extra work found on site to the customer, line by line (1–10 lines). Only on a started or completed, unconfirmed job; one open request at a time.\n\n**Access:** usta key · scope `write`",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "service_request_id": {
                    "type": "string",
                    "minLength": 1
                  },
                  "line_items": {
                    "minItems": 1,
                    "maxItems": 10,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "description": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 500
                        },
                        "amount": {
                          "description": "Line amount, positive. Whole TRY (750 = ₺750).",
                          "type": "number"
                        }
                      },
                      "required": [
                        "description",
                        "amount"
                      ]
                    }
                  },
                  "note": {
                    "type": "string",
                    "maxLength": 2000
                  },
                  "photos": {
                    "maxItems": 5,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "url": {
                          "description": "Uploaded file URL.",
                          "type": "string",
                          "minLength": 1
                        },
                        "file_name": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "mime_type": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        }
                      },
                      "required": [
                        "url"
                      ]
                    }
                  }
                },
                "required": [
                  "service_request_id",
                  "line_items"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "extra_work": {
                      "description": "An extra-work (extra charge) request.",
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "status": {
                          "description": "`pending_customer` → `approved` | `rejected` | `withdrawn`; `rejected` → counter-offer or `disputed`.",
                          "type": "string"
                        },
                        "service_request_id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "status",
                        "service_request_id"
                      ],
                      "additionalProperties": {}
                    }
                  },
                  "required": [
                    "extra_work"
                  ],
                  "additionalProperties": {}
                },
                "example": {
                  "extra_work": {
                    "id": "01J00000000000000000000000",
                    "service_request_id": "01J00000000000000000000000",
                    "usta_id": "cus_01J00000000000000000000000",
                    "customer_id": "cus_01J00000000000000000000000",
                    "line_items": [
                      {
                        "description": "Gaz dolumu",
                        "amount": 400
                      }
                    ],
                    "total": 400,
                    "currency_code": "try",
                    "note": null,
                    "photos": null,
                    "status": "pending_customer",
                    "revision": 0,
                    "history": [
                      {
                        "at": "2026-10-01T09:00:00.000Z",
                        "actor": "usta",
                        "actor_id": "cus_01J00000000000000000000000",
                        "action": "created",
                        "revision": 0,
                        "line_items": [
                          {
                            "description": "Gaz dolumu",
                            "amount": 400
                          }
                        ],
                        "total": 400,
                        "note": null
                      }
                    ],
                    "rejection_reason_code": null,
                    "rejection_reason_text": null,
                    "escrow_id": null,
                    "dispute_id": null,
                    "approved_at": null,
                    "rejected_at": null,
                    "withdrawn_at": null,
                    "disputed_at": null,
                    "resolved_at": null,
                    "metadata": null,
                    "created_at": "2026-10-01T09:00:00.000Z",
                    "updated_at": "2026-10-01T09:00:00.000Z",
                    "deleted_at": null
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.\n\n- `VALIDATION_ERROR` — The request failed validation; see `issues`.\n- `INVALID_LINE_ITEMS` — Invalid line items: 1–10 lines, each with a description and a positive amount.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "VALIDATION_ERROR": {
                    "value": {
                      "message": "The request failed validation; see `issues`.",
                      "code": "VALIDATION_ERROR"
                    }
                  },
                  "INVALID_LINE_ITEMS": {
                    "value": {
                      "message": "Invalid line items: 1–10 lines, each with a description and a positive amount.",
                      "code": "INVALID_LINE_ITEMS"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `USTA_ROLE_REQUIRED` — The usta role is required.\n- `NOT_YOUR_JOB` — This job is not assigned to you.\n- `PARTNER_ROLE_REQUIRED` — This operation is not available to the key's role.\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "USTA_ROLE_REQUIRED": {
                    "value": {
                      "message": "The usta role is required.",
                      "code": "USTA_ROLE_REQUIRED"
                    }
                  },
                  "NOT_YOUR_JOB": {
                    "value": {
                      "message": "This job is not assigned to you.",
                      "code": "NOT_YOUR_JOB"
                    }
                  },
                  "PARTNER_ROLE_REQUIRED": {
                    "value": {
                      "message": "This operation is not available to the key's role.",
                      "code": "PARTNER_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "The record's current state does not allow this.\n\n- `INVALID_JOB_STATUS` — The job's status does not allow this (started or completed jobs only).\n- `JOB_ALREADY_CONFIRMED` — The customer has already confirmed the job.\n- `EXTRA_WORK_PENDING` — An extra-work request is awaiting an answer; it is in `extra_work`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INVALID_JOB_STATUS": {
                    "value": {
                      "message": "The job's status does not allow this (started or completed jobs only).",
                      "code": "INVALID_JOB_STATUS"
                    }
                  },
                  "JOB_ALREADY_CONFIRMED": {
                    "value": {
                      "message": "The customer has already confirmed the job.",
                      "code": "JOB_ALREADY_CONFIRMED"
                    }
                  },
                  "EXTRA_WORK_PENDING": {
                    "value": {
                      "message": "An extra-work request is awaiting an answer; it is in `extra_work`.",
                      "code": "EXTRA_WORK_PENDING"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "usta",
        "x-ug-scope": "write",
        "x-ug-error-codes": [
          "USTA_ROLE_REQUIRED",
          "INVALID_LINE_ITEMS",
          "NOT_YOUR_JOB",
          "INVALID_JOB_STATUS",
          "JOB_ALREADY_CONFIRMED",
          "EXTRA_WORK_PENDING"
        ]
      }
    },
    "/extra-work/{id}": {
      "get": {
        "operationId": "getExtraWork",
        "tags": [
          "Extra work"
        ],
        "summary": "Get extra work",
        "description": "One extra-work request and which side you are on (`side`).\n\n**Access:** either role · scope `read`",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The record's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "extra_work": {
                      "description": "An extra-work (extra charge) request.",
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "status": {
                          "description": "`pending_customer` → `approved` | `rejected` | `withdrawn`; `rejected` → counter-offer or `disputed`.",
                          "type": "string"
                        },
                        "service_request_id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "status",
                        "service_request_id"
                      ],
                      "additionalProperties": {}
                    },
                    "side": {
                      "type": "string",
                      "enum": [
                        "usta",
                        "customer"
                      ]
                    }
                  },
                  "required": [
                    "extra_work",
                    "side"
                  ],
                  "additionalProperties": {}
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found.\n\n- `NOT_FOUND` — Not found, or not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "NOT_FOUND": {
                    "value": {
                      "message": "Not found, or not yours.",
                      "code": "NOT_FOUND"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "any",
        "x-ug-scope": "read"
      }
    },
    "/extra-work/{id}/approve": {
      "post": {
        "operationId": "approveExtraWork",
        "tags": [
          "Extra work"
        ],
        "summary": "Approve extra work",
        "description": "Accepts the extra charge and opens a separate payment for it (`payment`, same shape as `POST /payments`).\n\n**Access:** customer key · scope `money`",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The record's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "payment_method": {
                    "description": "`card` (default) or `bank_transfer`.",
                    "type": "string",
                    "enum": [
                      "card",
                      "bank_transfer"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "extra_work": {
                      "description": "An extra-work (extra charge) request.",
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "status": {
                          "description": "`pending_customer` → `approved` | `rejected` | `withdrawn`; `rejected` → counter-offer or `disputed`.",
                          "type": "string"
                        },
                        "service_request_id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "status",
                        "service_request_id"
                      ],
                      "additionalProperties": {}
                    },
                    "escrow": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "status"
                      ],
                      "additionalProperties": {}
                    },
                    "payment": {
                      "description": "How to complete the payment.",
                      "type": "object",
                      "properties": {
                        "mode": {
                          "description": "`gateway`: send the customer to `payment_url`; 3D Secure completes at the bank and the payment is held on the bank's confirmation. `bank_transfer`: transfer `amount` with `reference` in the description. `mock`: test environments only, already held.",
                          "type": "string",
                          "enum": [
                            "gateway",
                            "mock",
                            "bank_transfer"
                          ]
                        },
                        "payment_url": {
                          "description": "`gateway` only: the address that opens the bank's payment page (browser or WebView).",
                          "type": "string"
                        },
                        "order_number": {
                          "type": "string"
                        },
                        "reference": {
                          "description": "The booking number to put in the transfer description.",
                          "type": "string"
                        },
                        "amount": {
                          "type": "number"
                        },
                        "accounts": {
                          "description": "Accounts the transfer can go to.",
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "iban": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "iban"
                            ],
                            "additionalProperties": {}
                          }
                        }
                      },
                      "required": [
                        "mode"
                      ],
                      "additionalProperties": {}
                    }
                  },
                  "required": [
                    "extra_work",
                    "escrow",
                    "payment"
                  ],
                  "additionalProperties": {}
                },
                "example": {
                  "extra_work": {
                    "id": "01J00000000000000000000000",
                    "service_request_id": "01J00000000000000000000000",
                    "usta_id": "cus_01J00000000000000000000000",
                    "customer_id": "cus_01J00000000000000000000000",
                    "line_items": [
                      {
                        "amount": 400,
                        "description": "Gaz dolumu"
                      }
                    ],
                    "total": 400,
                    "currency_code": "try",
                    "note": null,
                    "photos": null,
                    "status": "approved",
                    "revision": 0,
                    "history": [
                      {
                        "at": "2026-10-01T09:00:00.000Z",
                        "note": null,
                        "actor": "usta",
                        "total": 400,
                        "action": "created",
                        "actor_id": "cus_01J00000000000000000000000",
                        "revision": 0,
                        "line_items": [
                          {
                            "amount": 400,
                            "description": "Gaz dolumu"
                          }
                        ]
                      },
                      {
                        "at": "2026-10-01T09:00:00.000Z",
                        "actor": "customer",
                        "actor_id": "cus_01J00000000000000000000000",
                        "action": "approved",
                        "revision": 0,
                        "total": 400
                      }
                    ],
                    "rejection_reason_code": null,
                    "rejection_reason_text": null,
                    "escrow_id": "01J00000000000000000000000",
                    "dispute_id": null,
                    "approved_at": "2026-10-01T09:00:00.000Z",
                    "rejected_at": null,
                    "withdrawn_at": null,
                    "disputed_at": null,
                    "resolved_at": null,
                    "metadata": null,
                    "created_at": "2026-10-01T09:00:00.000Z",
                    "updated_at": "2026-10-01T09:00:00.000Z",
                    "deleted_at": null
                  },
                  "escrow": {
                    "id": "01J00000000000000000000000",
                    "order_id": null,
                    "service_request_id": "01J00000000000000000000000",
                    "customer_id": "cus_01J00000000000000000000000",
                    "usta_id": "cus_01J00000000000000000000000",
                    "kind": "extra_work",
                    "extra_work_id": "01J00000000000000000000000",
                    "amount": 400,
                    "currency_code": "try",
                    "commission_rate": 0.15,
                    "commission_amount": 60,
                    "payout_amount": 340,
                    "refunded_amount": 0,
                    "status": "held",
                    "provider": "card-mock",
                    "payment_session_id": null,
                    "transaction_id": "MOCK-EXTRA-01J00000000000000000000000",
                    "released_at": null,
                    "held_at": "2026-10-01T09:00:00.000Z",
                    "disputed_at": null,
                    "dispute_reason": null,
                    "refund_requested_at": null,
                    "refunded_at": null,
                    "refund_reason": null,
                    "refund_reference": null,
                    "refund_channel": null,
                    "refund_ticket_id": null,
                    "metadata": {
                      "commission_source": "services"
                    },
                    "created_at": "2026-10-01T09:00:00.000Z",
                    "updated_at": "2026-10-01T09:00:00.000Z",
                    "deleted_at": null
                  },
                  "payment": {
                    "mode": "mock"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.\n\n- `VALIDATION_ERROR` — The request failed validation; see `issues`.\n- `PAYMENT_FAILED` — The payment could not be started.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "VALIDATION_ERROR": {
                    "value": {
                      "message": "The request failed validation; see `issues`.",
                      "code": "VALIDATION_ERROR"
                    }
                  },
                  "PAYMENT_FAILED": {
                    "value": {
                      "message": "The payment could not be started.",
                      "code": "PAYMENT_FAILED"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `NOT_YOUR_REQUEST` — This booking is not yours.\n- `PARTNER_ROLE_REQUIRED` — This operation is not available to the key's role.\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "NOT_YOUR_REQUEST": {
                    "value": {
                      "message": "This booking is not yours.",
                      "code": "NOT_YOUR_REQUEST"
                    }
                  },
                  "PARTNER_ROLE_REQUIRED": {
                    "value": {
                      "message": "This operation is not available to the key's role.",
                      "code": "PARTNER_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found.\n\n- `NOT_FOUND` — Not found, or not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "NOT_FOUND": {
                    "value": {
                      "message": "Not found, or not yours.",
                      "code": "NOT_FOUND"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "The record's current state does not allow this.\n\n- `NO_USTA_ASSIGNED` — No usta is assigned to this job.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "NO_USTA_ASSIGNED": {
                    "value": {
                      "message": "No usta is assigned to this job.",
                      "code": "NO_USTA_ASSIGNED"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "Service not configured.\n\n- `PAYMENT_GATEWAY_UNCONFIGURED` — Card payment is currently unavailable.\n- `BANK_TRANSFER_UNCONFIGURED` — Bank transfer is currently unavailable.\n- `HOSTED_PAYMENT_UNAVAILABLE` — Card payment is not yet available on this channel; use bank transfer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PAYMENT_GATEWAY_UNCONFIGURED": {
                    "value": {
                      "message": "Card payment is currently unavailable.",
                      "code": "PAYMENT_GATEWAY_UNCONFIGURED"
                    }
                  },
                  "BANK_TRANSFER_UNCONFIGURED": {
                    "value": {
                      "message": "Bank transfer is currently unavailable.",
                      "code": "BANK_TRANSFER_UNCONFIGURED"
                    }
                  },
                  "HOSTED_PAYMENT_UNAVAILABLE": {
                    "value": {
                      "message": "Card payment is not yet available on this channel; use bank transfer.",
                      "code": "HOSTED_PAYMENT_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "customer",
        "x-ug-scope": "money",
        "x-ug-error-codes": [
          "NOT_YOUR_REQUEST",
          "NO_USTA_ASSIGNED",
          "PAYMENT_GATEWAY_UNCONFIGURED",
          "BANK_TRANSFER_UNCONFIGURED",
          "PAYMENT_FAILED",
          "HOSTED_PAYMENT_UNAVAILABLE"
        ]
      }
    },
    "/extra-work/{id}/counter-offer": {
      "post": {
        "operationId": "counterExtraWork",
        "tags": [
          "Extra work"
        ],
        "summary": "Counter an extra-work rejection",
        "description": "Offers a lower amount after a rejection; at most 2 revisions.\n\n**Access:** usta key · scope `write`",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The record's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "line_items": {
                    "minItems": 1,
                    "maxItems": 10,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "description": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 500
                        },
                        "amount": {
                          "description": "Line amount, positive. Whole TRY (750 = ₺750).",
                          "type": "number"
                        }
                      },
                      "required": [
                        "description",
                        "amount"
                      ]
                    }
                  },
                  "note": {
                    "type": "string",
                    "maxLength": 2000
                  }
                },
                "required": [
                  "line_items"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "extra_work": {
                      "description": "An extra-work (extra charge) request.",
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "status": {
                          "description": "`pending_customer` → `approved` | `rejected` | `withdrawn`; `rejected` → counter-offer or `disputed`.",
                          "type": "string"
                        },
                        "service_request_id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "status",
                        "service_request_id"
                      ],
                      "additionalProperties": {}
                    }
                  },
                  "required": [
                    "extra_work"
                  ],
                  "additionalProperties": {}
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.\n\n- `VALIDATION_ERROR` — The request failed validation; see `issues`.\n- `INVALID_LINE_ITEMS` — Invalid line items: 1–10 lines, each with a description and a positive amount.\n- `AMOUNT_NOT_LOWER` — A counter-offer must be lower than the previous one (at most 2 revisions).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "VALIDATION_ERROR": {
                    "value": {
                      "message": "The request failed validation; see `issues`.",
                      "code": "VALIDATION_ERROR"
                    }
                  },
                  "INVALID_LINE_ITEMS": {
                    "value": {
                      "message": "Invalid line items: 1–10 lines, each with a description and a positive amount.",
                      "code": "INVALID_LINE_ITEMS"
                    }
                  },
                  "AMOUNT_NOT_LOWER": {
                    "value": {
                      "message": "A counter-offer must be lower than the previous one (at most 2 revisions).",
                      "code": "AMOUNT_NOT_LOWER"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_ROLE_REQUIRED` — This operation is not available to the key's role.\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_ROLE_REQUIRED": {
                    "value": {
                      "message": "This operation is not available to the key's role.",
                      "code": "PARTNER_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found.\n\n- `NOT_FOUND` — Not found, or not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "NOT_FOUND": {
                    "value": {
                      "message": "Not found, or not yours.",
                      "code": "NOT_FOUND"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "The record's current state does not allow this.\n\n- `INVALID_STATUS` — The record's status does not allow this.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INVALID_STATUS": {
                    "value": {
                      "message": "The record's status does not allow this.",
                      "code": "INVALID_STATUS"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "usta",
        "x-ug-scope": "write",
        "x-ug-error-codes": [
          "INVALID_LINE_ITEMS",
          "AMOUNT_NOT_LOWER",
          "INVALID_STATUS"
        ]
      }
    },
    "/extra-work/{id}/escalate": {
      "post": {
        "operationId": "escalateExtraWork",
        "tags": [
          "Extra work"
        ],
        "summary": "Escalate to the team",
        "description": "Asks the team to rule on a rejected extra charge. No payment is frozen; if the team rules for the usta the customer pays through the normal approval.\n\n**Access:** usta key · scope `write`",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The record's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "statement": {
                    "type": "string",
                    "minLength": 50,
                    "maxLength": 500
                  },
                  "photos": {
                    "maxItems": 5,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "url": {
                          "description": "Uploaded file URL.",
                          "type": "string",
                          "minLength": 1
                        },
                        "file_name": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "mime_type": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        }
                      },
                      "required": [
                        "url"
                      ]
                    }
                  }
                },
                "required": [
                  "statement"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "extra_work": {
                      "description": "An extra-work (extra charge) request.",
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "status": {
                          "description": "`pending_customer` → `approved` | `rejected` | `withdrawn`; `rejected` → counter-offer or `disputed`.",
                          "type": "string"
                        },
                        "service_request_id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "status",
                        "service_request_id"
                      ],
                      "additionalProperties": {}
                    },
                    "ticket": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id"
                      ],
                      "additionalProperties": {}
                    }
                  },
                  "required": [
                    "extra_work",
                    "ticket"
                  ],
                  "additionalProperties": {}
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.\n\n- `VALIDATION_ERROR` — The request failed validation; see `issues`.\n- `INVALID_STATEMENT` — The statement must be 50–500 characters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "VALIDATION_ERROR": {
                    "value": {
                      "message": "The request failed validation; see `issues`.",
                      "code": "VALIDATION_ERROR"
                    }
                  },
                  "INVALID_STATEMENT": {
                    "value": {
                      "message": "The statement must be 50–500 characters.",
                      "code": "INVALID_STATEMENT"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_ROLE_REQUIRED` — This operation is not available to the key's role.\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_ROLE_REQUIRED": {
                    "value": {
                      "message": "This operation is not available to the key's role.",
                      "code": "PARTNER_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found.\n\n- `NOT_FOUND` — Not found, or not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "NOT_FOUND": {
                    "value": {
                      "message": "Not found, or not yours.",
                      "code": "NOT_FOUND"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "usta",
        "x-ug-scope": "write",
        "x-ug-error-codes": [
          "INVALID_STATEMENT"
        ]
      }
    },
    "/extra-work/{id}/reject": {
      "post": {
        "operationId": "rejectExtraWork",
        "tags": [
          "Extra work"
        ],
        "summary": "Reject extra work",
        "description": "Rejects the extra charge with a reason; the usta may counter with a lower amount or escalate.\n\n**Access:** customer key · scope `write`",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The record's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "code": {
                    "description": "The rejection reason's code.",
                    "type": "string",
                    "enum": [
                      "price_too_high",
                      "not_needed",
                      "not_agreed",
                      "quality_concern",
                      "other"
                    ]
                  },
                  "text": {
                    "type": "string",
                    "minLength": 10,
                    "maxLength": 1000
                  }
                },
                "required": [
                  "code",
                  "text"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "extra_work": {
                      "description": "An extra-work (extra charge) request.",
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "status": {
                          "description": "`pending_customer` → `approved` | `rejected` | `withdrawn`; `rejected` → counter-offer or `disputed`.",
                          "type": "string"
                        },
                        "service_request_id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "status",
                        "service_request_id"
                      ],
                      "additionalProperties": {}
                    }
                  },
                  "required": [
                    "extra_work"
                  ],
                  "additionalProperties": {}
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.\n\n- `VALIDATION_ERROR` — The request failed validation; see `issues`.\n- `INVALID_REASON_CODE` — Invalid rejection reason code.\n- `REASON_TOO_SHORT` — The reason must be at least 10 characters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "VALIDATION_ERROR": {
                    "value": {
                      "message": "The request failed validation; see `issues`.",
                      "code": "VALIDATION_ERROR"
                    }
                  },
                  "INVALID_REASON_CODE": {
                    "value": {
                      "message": "Invalid rejection reason code.",
                      "code": "INVALID_REASON_CODE"
                    }
                  },
                  "REASON_TOO_SHORT": {
                    "value": {
                      "message": "The reason must be at least 10 characters.",
                      "code": "REASON_TOO_SHORT"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `NOT_YOUR_REQUEST` — This booking is not yours.\n- `PARTNER_ROLE_REQUIRED` — This operation is not available to the key's role.\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "NOT_YOUR_REQUEST": {
                    "value": {
                      "message": "This booking is not yours.",
                      "code": "NOT_YOUR_REQUEST"
                    }
                  },
                  "PARTNER_ROLE_REQUIRED": {
                    "value": {
                      "message": "This operation is not available to the key's role.",
                      "code": "PARTNER_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found.\n\n- `NOT_FOUND` — Not found, or not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "NOT_FOUND": {
                    "value": {
                      "message": "Not found, or not yours.",
                      "code": "NOT_FOUND"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "The record's current state does not allow this.\n\n- `INVALID_STATUS` — The record's status does not allow this.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INVALID_STATUS": {
                    "value": {
                      "message": "The record's status does not allow this.",
                      "code": "INVALID_STATUS"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "customer",
        "x-ug-scope": "write",
        "x-ug-error-codes": [
          "NOT_YOUR_REQUEST",
          "INVALID_REASON_CODE",
          "REASON_TOO_SHORT",
          "INVALID_STATUS"
        ]
      }
    },
    "/extra-work/{id}/withdraw": {
      "post": {
        "operationId": "withdrawExtraWork",
        "tags": [
          "Extra work"
        ],
        "summary": "Withdraw extra work",
        "description": "Withdraws an extra-work request awaiting an answer.\n\n**Access:** usta key · scope `write`",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The record's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "extra_work": {
                      "description": "An extra-work (extra charge) request.",
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "status": {
                          "description": "`pending_customer` → `approved` | `rejected` | `withdrawn`; `rejected` → counter-offer or `disputed`.",
                          "type": "string"
                        },
                        "service_request_id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "status",
                        "service_request_id"
                      ],
                      "additionalProperties": {}
                    }
                  },
                  "required": [
                    "extra_work"
                  ],
                  "additionalProperties": {}
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_ROLE_REQUIRED` — This operation is not available to the key's role.\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_ROLE_REQUIRED": {
                    "value": {
                      "message": "This operation is not available to the key's role.",
                      "code": "PARTNER_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found.\n\n- `NOT_FOUND` — Not found, or not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "NOT_FOUND": {
                    "value": {
                      "message": "Not found, or not yours.",
                      "code": "NOT_FOUND"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "The record's current state does not allow this.\n\n- `INVALID_STATUS` — The record's status does not allow this.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INVALID_STATUS": {
                    "value": {
                      "message": "The record's status does not allow this.",
                      "code": "INVALID_STATUS"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "usta",
        "x-ug-scope": "write",
        "x-ug-error-codes": [
          "INVALID_STATUS"
        ]
      }
    },
    "/jobs": {
      "get": {
        "operationId": "listJobs",
        "tags": [
          "Usta — Jobs"
        ],
        "summary": "List jobs",
        "description": "The usta's own jobs and the open jobs they can take (by category, province, calendar and approval). When the usta cannot get jobs the list is empty and `usta_block` says why (e.g. `PENDING_ADMIN_APPROVAL`).\n\n**Access:** usta key · scope `read`",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "requests": {
                      "description": "The usta's own jobs plus the open jobs they can take.",
                      "type": "array",
                      "items": {
                        "description": "A job as the usta sees it. Before accepting: the province and the job only; after accepting: the full address and the customer's first name and initial. The phone is never shared: talk through chat.",
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string"
                          },
                          "appointment_date": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "appointment_slot": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "status",
                          "appointment_date",
                          "appointment_slot"
                        ],
                        "additionalProperties": {}
                      }
                    },
                    "role": {
                      "type": "string"
                    },
                    "usta_block": {
                      "description": "What keeps the usta from getting jobs (e.g. `PENDING_ADMIN_APPROVAL`), or `null`.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "usta_block_message": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "requests",
                    "role",
                    "usta_block",
                    "usta_block_message"
                  ],
                  "additionalProperties": {}
                },
                "example": {
                  "requests": [
                    {
                      "id": "01J00000000000000000000000",
                      "reference": "UG-102610123456",
                      "title": "Klima Bakımı — Standart",
                      "status": "pending",
                      "category_handle": "klima",
                      "group_id": null,
                      "group_order": null,
                      "group_siblings": null,
                      "items": [
                        {
                          "title": "Klima Bakımı — Standart",
                          "quantity": 1,
                          "base_price": 750,
                          "product_id": "prod_01J00000000000000000000000",
                          "unit_price": 750,
                          "variant_id": "variant_01J00000000000000000000000"
                        }
                      ],
                      "product_id": "prod_01J00000000000000000000000",
                      "variant_id": "variant_01J00000000000000000000000",
                      "amount": 750,
                      "currency_code": "try",
                      "pricing_type": "fixed",
                      "fixed_price_checkout": true,
                      "appointment_date": "2026-10-06",
                      "appointment_slot": "09:00-11:00",
                      "notes": null,
                      "photos": [],
                      "city": "İstanbul",
                      "district": "Kadıköy",
                      "assigned_usta_id": null,
                      "created_at": "2026-10-01T09:00:00.000Z",
                      "updated_at": "2026-10-01T09:00:00.000Z",
                      "metadata": {
                        "city": "İstanbul",
                        "district": "Kadıköy",
                        "ug_pricing_type": "fixed",
                        "ug_fixed_price_checkout": true
                      }
                    }
                  ],
                  "role": "usta",
                  "usta_block": null,
                  "usta_block_message": null
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_ROLE_REQUIRED` — This operation is not available to the key's role.\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_ROLE_REQUIRED": {
                    "value": {
                      "message": "This operation is not available to the key's role.",
                      "code": "PARTNER_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "usta",
        "x-ug-scope": "read",
        "x-ai-hint": "Poll every 30–60 s, or `GET /notifications/sync`, to see new jobs."
      }
    },
    "/jobs/{id}": {
      "get": {
        "operationId": "getJob",
        "tags": [
          "Usta — Jobs"
        ],
        "summary": "Get a job",
        "description": "One job. Before accepting, the address is province-level only; the customer's name after accepting, the phone never.\n\n**Access:** usta key · scope `read`",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The record's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "request": {
                      "description": "A job as the usta sees it. Before accepting: the province and the job only; after accepting: the full address and the customer's first name and initial. The phone is never shared: talk through chat.",
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string"
                        },
                        "appointment_date": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "appointment_slot": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        }
                      },
                      "required": [
                        "id",
                        "status",
                        "appointment_date",
                        "appointment_slot"
                      ],
                      "additionalProperties": {}
                    }
                  },
                  "required": [
                    "request"
                  ],
                  "additionalProperties": {}
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `USTA_ROLE_REQUIRED` — The usta role is required.\n- `USTA_PROFILE_REQUIRED` — Create the usta profile first.\n- `SERVICE_CATEGORIES_REQUIRED` — Pick at least one service category.\n- `CATEGORY_NOT_COVERED` — The job is outside the usta's categories.\n- `CATEGORY_DOCUMENTS_REQUIRED` — Jobs in this category need an approved certificate.\n- `CITY_NOT_COVERED` — The job is outside the usta's province.\n- `OWN_REQUEST` — An usta cannot take their own booking.\n- `ALREADY_TAKEN` — Another usta has the job.\n- `PENDING_ADMIN_APPROVAL` — The account is awaiting the call center's approval.\n- `NOT_AVAILABLE_AT_SLOT` — The usta does not work that date and slot.\n- `AREA_NOT_COVERED` — The area is not covered.\n- `PARTNER_ROLE_REQUIRED` — This operation is not available to the key's role.\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "USTA_ROLE_REQUIRED": {
                    "value": {
                      "message": "The usta role is required.",
                      "code": "USTA_ROLE_REQUIRED"
                    }
                  },
                  "USTA_PROFILE_REQUIRED": {
                    "value": {
                      "message": "Create the usta profile first.",
                      "code": "USTA_PROFILE_REQUIRED"
                    }
                  },
                  "SERVICE_CATEGORIES_REQUIRED": {
                    "value": {
                      "message": "Pick at least one service category.",
                      "code": "SERVICE_CATEGORIES_REQUIRED"
                    }
                  },
                  "CATEGORY_NOT_COVERED": {
                    "value": {
                      "message": "The job is outside the usta's categories.",
                      "code": "CATEGORY_NOT_COVERED"
                    }
                  },
                  "CATEGORY_DOCUMENTS_REQUIRED": {
                    "value": {
                      "message": "Jobs in this category need an approved certificate.",
                      "code": "CATEGORY_DOCUMENTS_REQUIRED"
                    }
                  },
                  "CITY_NOT_COVERED": {
                    "value": {
                      "message": "The job is outside the usta's province.",
                      "code": "CITY_NOT_COVERED"
                    }
                  },
                  "OWN_REQUEST": {
                    "value": {
                      "message": "An usta cannot take their own booking.",
                      "code": "OWN_REQUEST"
                    }
                  },
                  "ALREADY_TAKEN": {
                    "value": {
                      "message": "Another usta has the job.",
                      "code": "ALREADY_TAKEN"
                    }
                  },
                  "PENDING_ADMIN_APPROVAL": {
                    "value": {
                      "message": "The account is awaiting the call center's approval.",
                      "code": "PENDING_ADMIN_APPROVAL"
                    }
                  },
                  "NOT_AVAILABLE_AT_SLOT": {
                    "value": {
                      "message": "The usta does not work that date and slot.",
                      "code": "NOT_AVAILABLE_AT_SLOT"
                    }
                  },
                  "AREA_NOT_COVERED": {
                    "value": {
                      "message": "The area is not covered.",
                      "code": "AREA_NOT_COVERED"
                    }
                  },
                  "PARTNER_ROLE_REQUIRED": {
                    "value": {
                      "message": "This operation is not available to the key's role.",
                      "code": "PARTNER_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found.\n\n- `NOT_FOUND` — Not found, or not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "NOT_FOUND": {
                    "value": {
                      "message": "Not found, or not yours.",
                      "code": "NOT_FOUND"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "usta",
        "x-ug-scope": "read",
        "x-ug-error-codes": [
          "USTA_ROLE_REQUIRED",
          "USTA_PROFILE_REQUIRED",
          "SERVICE_CATEGORIES_REQUIRED",
          "CATEGORY_NOT_COVERED",
          "CATEGORY_DOCUMENTS_REQUIRED",
          "CITY_NOT_COVERED",
          "OWN_REQUEST",
          "ALREADY_TAKEN",
          "PENDING_ADMIN_APPROVAL",
          "NOT_AVAILABLE_AT_SLOT",
          "AREA_NOT_COVERED"
        ]
      }
    },
    "/jobs/{id}/accept": {
      "post": {
        "operationId": "acceptJob",
        "tags": [
          "Usta — Jobs"
        ],
        "summary": "Accept a job",
        "description": "Takes the job; the first to accept wins and every other offer is withdrawn. An unpaid booking cannot be accepted.\n\n**Access:** usta key · scope `write`",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The record's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "request": {
                      "description": "A job as the usta sees it. Before accepting: the province and the job only; after accepting: the full address and the customer's first name and initial. The phone is never shared: talk through chat.",
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string"
                        },
                        "appointment_date": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "appointment_slot": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        }
                      },
                      "required": [
                        "id",
                        "status",
                        "appointment_date",
                        "appointment_slot"
                      ],
                      "additionalProperties": {}
                    }
                  },
                  "required": [
                    "request"
                  ],
                  "additionalProperties": {}
                },
                "example": {
                  "request": {
                    "id": "01J00000000000000000000000",
                    "reference": "UG-102610123456",
                    "title": "Klima Bakımı — Standart",
                    "status": "accepted",
                    "category_handle": "klima",
                    "group_id": null,
                    "group_order": null,
                    "group_siblings": null,
                    "items": [
                      {
                        "title": "Klima Bakımı — Standart",
                        "quantity": 1,
                        "base_price": 750,
                        "product_id": "prod_01J00000000000000000000000",
                        "unit_price": 750,
                        "variant_id": "variant_01J00000000000000000000000"
                      }
                    ],
                    "product_id": "prod_01J00000000000000000000000",
                    "variant_id": "variant_01J00000000000000000000000",
                    "amount": 750,
                    "currency_code": "try",
                    "pricing_type": "fixed",
                    "fixed_price_checkout": true,
                    "appointment_date": "2026-10-06",
                    "appointment_slot": "09:00-11:00",
                    "notes": null,
                    "photos": [],
                    "city": "İstanbul",
                    "district": "Kadıköy",
                    "assigned_usta_id": "cus_01J00000000000000000000000",
                    "created_at": "2026-10-01T09:00:00.000Z",
                    "updated_at": "2026-10-01T09:00:00.000Z",
                    "metadata": {
                      "city": "İstanbul",
                      "district": "Kadıköy",
                      "ug_pricing_type": "fixed",
                      "ug_fixed_price_checkout": true
                    },
                    "address_summary": "Test Sok. 1 D:2",
                    "order_id": null,
                    "customer": {
                      "id": "cus_01J00000000000000000000000",
                      "display_name": "is-akisi T."
                    },
                    "customer_id": "cus_01J00000000000000000000000"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `USTA_ROLE_REQUIRED` — The usta role is required.\n- `USTA_PROFILE_REQUIRED` — Create the usta profile first.\n- `SERVICE_CATEGORIES_REQUIRED` — Pick at least one service category.\n- `CATEGORY_NOT_COVERED` — The job is outside the usta's categories.\n- `CATEGORY_DOCUMENTS_REQUIRED` — Jobs in this category need an approved certificate.\n- `CITY_NOT_COVERED` — The job is outside the usta's province.\n- `OWN_REQUEST` — An usta cannot take their own booking.\n- `ALREADY_TAKEN` — Another usta has the job.\n- `PENDING_ADMIN_APPROVAL` — The account is awaiting the call center's approval.\n- `NOT_AVAILABLE_AT_SLOT` — The usta does not work that date and slot.\n- `AREA_NOT_COVERED` — The area is not covered.\n- `PARTNER_ROLE_REQUIRED` — This operation is not available to the key's role.\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "USTA_ROLE_REQUIRED": {
                    "value": {
                      "message": "The usta role is required.",
                      "code": "USTA_ROLE_REQUIRED"
                    }
                  },
                  "USTA_PROFILE_REQUIRED": {
                    "value": {
                      "message": "Create the usta profile first.",
                      "code": "USTA_PROFILE_REQUIRED"
                    }
                  },
                  "SERVICE_CATEGORIES_REQUIRED": {
                    "value": {
                      "message": "Pick at least one service category.",
                      "code": "SERVICE_CATEGORIES_REQUIRED"
                    }
                  },
                  "CATEGORY_NOT_COVERED": {
                    "value": {
                      "message": "The job is outside the usta's categories.",
                      "code": "CATEGORY_NOT_COVERED"
                    }
                  },
                  "CATEGORY_DOCUMENTS_REQUIRED": {
                    "value": {
                      "message": "Jobs in this category need an approved certificate.",
                      "code": "CATEGORY_DOCUMENTS_REQUIRED"
                    }
                  },
                  "CITY_NOT_COVERED": {
                    "value": {
                      "message": "The job is outside the usta's province.",
                      "code": "CITY_NOT_COVERED"
                    }
                  },
                  "OWN_REQUEST": {
                    "value": {
                      "message": "An usta cannot take their own booking.",
                      "code": "OWN_REQUEST"
                    }
                  },
                  "ALREADY_TAKEN": {
                    "value": {
                      "message": "Another usta has the job.",
                      "code": "ALREADY_TAKEN"
                    }
                  },
                  "PENDING_ADMIN_APPROVAL": {
                    "value": {
                      "message": "The account is awaiting the call center's approval.",
                      "code": "PENDING_ADMIN_APPROVAL"
                    }
                  },
                  "NOT_AVAILABLE_AT_SLOT": {
                    "value": {
                      "message": "The usta does not work that date and slot.",
                      "code": "NOT_AVAILABLE_AT_SLOT"
                    }
                  },
                  "AREA_NOT_COVERED": {
                    "value": {
                      "message": "The area is not covered.",
                      "code": "AREA_NOT_COVERED"
                    }
                  },
                  "PARTNER_ROLE_REQUIRED": {
                    "value": {
                      "message": "This operation is not available to the key's role.",
                      "code": "PARTNER_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found.\n\n- `NOT_FOUND` — Not found, or not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "NOT_FOUND": {
                    "value": {
                      "message": "Not found, or not yours.",
                      "code": "NOT_FOUND"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "The record's current state does not allow this.\n\n- `BOOKING_NOT_PAID` — An unpaid booking cannot go to an usta.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "BOOKING_NOT_PAID": {
                    "value": {
                      "message": "An unpaid booking cannot go to an usta.",
                      "code": "BOOKING_NOT_PAID"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "usta",
        "x-ug-scope": "write",
        "x-ug-error-codes": [
          "USTA_ROLE_REQUIRED",
          "USTA_PROFILE_REQUIRED",
          "SERVICE_CATEGORIES_REQUIRED",
          "CATEGORY_NOT_COVERED",
          "CATEGORY_DOCUMENTS_REQUIRED",
          "CITY_NOT_COVERED",
          "OWN_REQUEST",
          "ALREADY_TAKEN",
          "PENDING_ADMIN_APPROVAL",
          "NOT_AVAILABLE_AT_SLOT",
          "AREA_NOT_COVERED",
          "BOOKING_NOT_PAID"
        ]
      }
    },
    "/jobs/{id}/complete": {
      "post": {
        "operationId": "completeJob",
        "tags": [
          "Usta — Jobs"
        ],
        "summary": "Complete the job",
        "description": "Closes the job with the completion code, a note of at least 50 characters and 1–5 photos; the job goes to the customer for confirmation. An extra charge can be raised in the same submit.\n\n**Access:** usta key · scope `write`",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The record's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "code": {
                    "description": "The completion code sent to the customer (`POST /jobs/{id}/completion-code`).",
                    "type": "string",
                    "minLength": 4,
                    "maxLength": 12
                  },
                  "note": {
                    "description": "What was done, at least 50 characters.",
                    "type": "string",
                    "minLength": 50,
                    "maxLength": 5000
                  },
                  "photos": {
                    "description": "Evidence of the work, 1–5 photos (`POST /uploads/photo`).",
                    "minItems": 1,
                    "maxItems": 5,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "url": {
                          "description": "Uploaded file URL.",
                          "type": "string",
                          "minLength": 1
                        },
                        "file_name": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "mime_type": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        }
                      },
                      "required": [
                        "url"
                      ]
                    }
                  },
                  "extra_work": {
                    "description": "Optional: an extra charge raised in the same submit.",
                    "type": "object",
                    "properties": {
                      "line_items": {
                        "maxItems": 10,
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "description": {
                              "type": "string",
                              "minLength": 1,
                              "maxLength": 500
                            },
                            "amount": {
                              "description": "Line amount, positive. Whole TRY (750 = ₺750).",
                              "type": "number"
                            }
                          },
                          "required": [
                            "description",
                            "amount"
                          ]
                        }
                      },
                      "note": {
                        "type": "string",
                        "maxLength": 2000
                      },
                      "photos": {
                        "maxItems": 5,
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "url": {
                              "description": "Uploaded file URL.",
                              "type": "string",
                              "minLength": 1
                            },
                            "file_name": {
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "mime_type": {
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            }
                          },
                          "required": [
                            "url"
                          ]
                        }
                      }
                    }
                  }
                },
                "required": [
                  "code",
                  "note",
                  "photos"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "request": {
                      "description": "A job as the usta sees it. Before accepting: the province and the job only; after accepting: the full address and the customer's first name and initial. The phone is never shared: talk through chat.",
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string"
                        },
                        "appointment_date": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "appointment_slot": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        }
                      },
                      "required": [
                        "id",
                        "status",
                        "appointment_date",
                        "appointment_slot"
                      ],
                      "additionalProperties": {}
                    },
                    "extra_work": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "id"
                          ],
                          "additionalProperties": {}
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "request",
                    "extra_work"
                  ],
                  "additionalProperties": {}
                },
                "example": {
                  "request": {
                    "id": "01J00000000000000000000000",
                    "reference": "UG-102610123456",
                    "title": "Klima Bakımı — Standart",
                    "status": "completed",
                    "category_handle": "klima",
                    "group_id": null,
                    "group_order": null,
                    "group_siblings": null,
                    "items": [
                      {
                        "title": "Klima Bakımı — Standart",
                        "quantity": 1,
                        "base_price": 750,
                        "product_id": "prod_01J00000000000000000000000",
                        "unit_price": 750,
                        "variant_id": "variant_01J00000000000000000000000"
                      }
                    ],
                    "product_id": "prod_01J00000000000000000000000",
                    "variant_id": "variant_01J00000000000000000000000",
                    "amount": 750,
                    "currency_code": "try",
                    "pricing_type": "fixed",
                    "fixed_price_checkout": true,
                    "appointment_date": "2026-10-06",
                    "appointment_slot": "09:00-11:00",
                    "notes": null,
                    "photos": [],
                    "city": "İstanbul",
                    "district": "Kadıköy",
                    "assigned_usta_id": "cus_01J00000000000000000000000",
                    "created_at": "2026-10-01T09:00:00.000Z",
                    "updated_at": "2026-10-01T09:00:00.000Z",
                    "metadata": {
                      "city": "İstanbul",
                      "district": "Kadıköy",
                      "started_at": "2026-10-01T09:00:00.000Z",
                      "on_the_way_at": "2026-10-01T09:00:00.000Z",
                      "ug_pricing_type": "fixed",
                      "ug_fixed_price_checkout": true,
                      "completed_at": "2026-10-01T09:00:00.000Z",
                      "completion_note": "Klima bakımı yapıldı, filtreler temizlendi, gaz basıncı ölçüldü ve dolum tamamlandı.",
                      "completion_photos": [
                        {
                          "url": "https://api.example.com/static/shared/private-1790000000000-ug-cus_01J00000000000000000000000-1790000000000.png"
                        }
                      ]
                    },
                    "address_summary": "Test Sok. 1 D:2",
                    "order_id": null,
                    "customer": null,
                    "customer_id": "cus_01J00000000000000000000000"
                  },
                  "extra_work": null
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.\n\n- `VALIDATION_ERROR` — The request failed validation; see `issues`.\n- `VISIT_CODE_REQUIRED` — Enter the code the customer reads out.\n- `VISIT_CODE_INVALID` — The code is wrong.\n- `INVALID_COMPLETION` — Invalid completion: a note of at least 50 characters and 1–5 photos are required.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "VALIDATION_ERROR": {
                    "value": {
                      "message": "The request failed validation; see `issues`.",
                      "code": "VALIDATION_ERROR"
                    }
                  },
                  "VISIT_CODE_REQUIRED": {
                    "value": {
                      "message": "Enter the code the customer reads out.",
                      "code": "VISIT_CODE_REQUIRED"
                    }
                  },
                  "VISIT_CODE_INVALID": {
                    "value": {
                      "message": "The code is wrong.",
                      "code": "VISIT_CODE_INVALID"
                    }
                  },
                  "INVALID_COMPLETION": {
                    "value": {
                      "message": "Invalid completion: a note of at least 50 characters and 1–5 photos are required.",
                      "code": "INVALID_COMPLETION"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `USTA_ROLE_REQUIRED` — The usta role is required.\n- `PARTNER_ROLE_REQUIRED` — This operation is not available to the key's role.\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "USTA_ROLE_REQUIRED": {
                    "value": {
                      "message": "The usta role is required.",
                      "code": "USTA_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_REQUIRED": {
                    "value": {
                      "message": "This operation is not available to the key's role.",
                      "code": "PARTNER_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found.\n\n- `NOT_FOUND` — Not found, or not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "NOT_FOUND": {
                    "value": {
                      "message": "Not found, or not yours.",
                      "code": "NOT_FOUND"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "The record's current state does not allow this.\n\n- `VISIT_CODE_NOT_ISSUED` — No code has been issued for this step yet (head out / send the code first).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "VISIT_CODE_NOT_ISSUED": {
                    "value": {
                      "message": "No code has been issued for this step yet (head out / send the code first).",
                      "code": "VISIT_CODE_NOT_ISSUED"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "usta",
        "x-ug-scope": "write",
        "x-ug-error-codes": [
          "USTA_ROLE_REQUIRED",
          "VISIT_CODE_REQUIRED",
          "VISIT_CODE_INVALID",
          "VISIT_CODE_NOT_ISSUED",
          "NOT_FOUND",
          "INVALID_COMPLETION"
        ]
      }
    },
    "/jobs/{id}/completion-code": {
      "post": {
        "operationId": "sendCompletionCode",
        "tags": [
          "Usta — Jobs"
        ],
        "summary": "Send the completion code",
        "description": "Sends the completion code to the customer by SMS, push and notification. Safe to repeat.\n\n**Access:** usta key · scope `write`",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The record's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "sent": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "sent"
                  ],
                  "additionalProperties": {}
                },
                "example": {
                  "sent": true
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `USTA_ROLE_REQUIRED` — The usta role is required.\n- `NOT_ASSIGNED` — This job is not assigned to you.\n- `PARTNER_ROLE_REQUIRED` — This operation is not available to the key's role.\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "USTA_ROLE_REQUIRED": {
                    "value": {
                      "message": "The usta role is required.",
                      "code": "USTA_ROLE_REQUIRED"
                    }
                  },
                  "NOT_ASSIGNED": {
                    "value": {
                      "message": "This job is not assigned to you.",
                      "code": "NOT_ASSIGNED"
                    }
                  },
                  "PARTNER_ROLE_REQUIRED": {
                    "value": {
                      "message": "This operation is not available to the key's role.",
                      "code": "PARTNER_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found.\n\n- `NOT_FOUND` — Not found, or not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "NOT_FOUND": {
                    "value": {
                      "message": "Not found, or not yours.",
                      "code": "NOT_FOUND"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "usta",
        "x-ug-scope": "write",
        "x-ug-error-codes": [
          "USTA_ROLE_REQUIRED",
          "NOT_ASSIGNED"
        ]
      }
    },
    "/jobs/{id}/on-the-way": {
      "post": {
        "operationId": "markOnTheWay",
        "tags": [
          "Usta — Jobs"
        ],
        "summary": "Head out",
        "description": "Tells the customer the usta is on the way and issues the code that starts the job (the code is on the customer's screen). Safe to repeat; the same code stays live.\n\n**Access:** usta key · scope `write`",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The record's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "request": {
                      "description": "A job as the usta sees it. Before accepting: the province and the job only; after accepting: the full address and the customer's first name and initial. The phone is never shared: talk through chat.",
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string"
                        },
                        "appointment_date": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "appointment_slot": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        }
                      },
                      "required": [
                        "id",
                        "status",
                        "appointment_date",
                        "appointment_slot"
                      ],
                      "additionalProperties": {}
                    }
                  },
                  "required": [
                    "request"
                  ],
                  "additionalProperties": {}
                },
                "example": {
                  "request": {
                    "id": "01J00000000000000000000000",
                    "reference": "UG-102610123456",
                    "title": "Klima Bakımı — Standart",
                    "status": "accepted",
                    "category_handle": "klima",
                    "group_id": null,
                    "group_order": null,
                    "group_siblings": null,
                    "items": [
                      {
                        "title": "Klima Bakımı — Standart",
                        "quantity": 1,
                        "base_price": 750,
                        "product_id": "prod_01J00000000000000000000000",
                        "unit_price": 750,
                        "variant_id": "variant_01J00000000000000000000000"
                      }
                    ],
                    "product_id": "prod_01J00000000000000000000000",
                    "variant_id": "variant_01J00000000000000000000000",
                    "amount": 750,
                    "currency_code": "try",
                    "pricing_type": "fixed",
                    "fixed_price_checkout": true,
                    "appointment_date": "2026-10-06",
                    "appointment_slot": "09:00-11:00",
                    "notes": null,
                    "photos": [],
                    "city": "İstanbul",
                    "district": "Kadıköy",
                    "assigned_usta_id": "cus_01J00000000000000000000000",
                    "created_at": "2026-10-01T09:00:00.000Z",
                    "updated_at": "2026-10-01T09:00:00.000Z",
                    "metadata": {
                      "city": "İstanbul",
                      "district": "Kadıköy",
                      "ug_pricing_type": "fixed",
                      "ug_fixed_price_checkout": true,
                      "on_the_way_at": "2026-10-01T09:00:00.000Z"
                    },
                    "address_summary": "Test Sok. 1 D:2",
                    "order_id": null,
                    "customer": null,
                    "customer_id": "cus_01J00000000000000000000000"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `USTA_ROLE_REQUIRED` — The usta role is required.\n- `PARTNER_ROLE_REQUIRED` — This operation is not available to the key's role.\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "USTA_ROLE_REQUIRED": {
                    "value": {
                      "message": "The usta role is required.",
                      "code": "USTA_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_REQUIRED": {
                    "value": {
                      "message": "This operation is not available to the key's role.",
                      "code": "PARTNER_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found.\n\n- `NOT_FOUND` — Not found, or not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "NOT_FOUND": {
                    "value": {
                      "message": "Not found, or not yours.",
                      "code": "NOT_FOUND"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "usta",
        "x-ug-scope": "write",
        "x-ug-error-codes": [
          "USTA_ROLE_REQUIRED"
        ]
      }
    },
    "/jobs/{id}/reject": {
      "post": {
        "operationId": "rejectJob",
        "tags": [
          "Usta — Jobs"
        ],
        "summary": "Reject a job",
        "description": "Declines the offer you received (the job stays open to others) or gives back a job you had taken.\n\n**Access:** usta key · scope `write`",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The record's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string",
                    "maxLength": 1000
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "request": {
                      "description": "A job as the usta sees it. Before accepting: the province and the job only; after accepting: the full address and the customer's first name and initial. The phone is never shared: talk through chat.",
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string"
                        },
                        "appointment_date": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "appointment_slot": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        }
                      },
                      "required": [
                        "id",
                        "status",
                        "appointment_date",
                        "appointment_slot"
                      ],
                      "additionalProperties": {}
                    },
                    "declined": {
                      "description": "`true`: you declined your offer only; the job stays open to other ustas.",
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "request"
                  ],
                  "additionalProperties": {}
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.\n\n- `VALIDATION_ERROR` — The request failed validation; see `issues`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "VALIDATION_ERROR": {
                    "value": {
                      "message": "The request failed validation; see `issues`.",
                      "code": "VALIDATION_ERROR"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `USTA_ROLE_REQUIRED` — The usta role is required.\n- `USTA_PROFILE_REQUIRED` — Create the usta profile first.\n- `SERVICE_CATEGORIES_REQUIRED` — Pick at least one service category.\n- `CATEGORY_NOT_COVERED` — The job is outside the usta's categories.\n- `CATEGORY_DOCUMENTS_REQUIRED` — Jobs in this category need an approved certificate.\n- `CITY_NOT_COVERED` — The job is outside the usta's province.\n- `OWN_REQUEST` — An usta cannot take their own booking.\n- `ALREADY_TAKEN` — Another usta has the job.\n- `PENDING_ADMIN_APPROVAL` — The account is awaiting the call center's approval.\n- `NOT_AVAILABLE_AT_SLOT` — The usta does not work that date and slot.\n- `AREA_NOT_COVERED` — The area is not covered.\n- `PARTNER_ROLE_REQUIRED` — This operation is not available to the key's role.\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "USTA_ROLE_REQUIRED": {
                    "value": {
                      "message": "The usta role is required.",
                      "code": "USTA_ROLE_REQUIRED"
                    }
                  },
                  "USTA_PROFILE_REQUIRED": {
                    "value": {
                      "message": "Create the usta profile first.",
                      "code": "USTA_PROFILE_REQUIRED"
                    }
                  },
                  "SERVICE_CATEGORIES_REQUIRED": {
                    "value": {
                      "message": "Pick at least one service category.",
                      "code": "SERVICE_CATEGORIES_REQUIRED"
                    }
                  },
                  "CATEGORY_NOT_COVERED": {
                    "value": {
                      "message": "The job is outside the usta's categories.",
                      "code": "CATEGORY_NOT_COVERED"
                    }
                  },
                  "CATEGORY_DOCUMENTS_REQUIRED": {
                    "value": {
                      "message": "Jobs in this category need an approved certificate.",
                      "code": "CATEGORY_DOCUMENTS_REQUIRED"
                    }
                  },
                  "CITY_NOT_COVERED": {
                    "value": {
                      "message": "The job is outside the usta's province.",
                      "code": "CITY_NOT_COVERED"
                    }
                  },
                  "OWN_REQUEST": {
                    "value": {
                      "message": "An usta cannot take their own booking.",
                      "code": "OWN_REQUEST"
                    }
                  },
                  "ALREADY_TAKEN": {
                    "value": {
                      "message": "Another usta has the job.",
                      "code": "ALREADY_TAKEN"
                    }
                  },
                  "PENDING_ADMIN_APPROVAL": {
                    "value": {
                      "message": "The account is awaiting the call center's approval.",
                      "code": "PENDING_ADMIN_APPROVAL"
                    }
                  },
                  "NOT_AVAILABLE_AT_SLOT": {
                    "value": {
                      "message": "The usta does not work that date and slot.",
                      "code": "NOT_AVAILABLE_AT_SLOT"
                    }
                  },
                  "AREA_NOT_COVERED": {
                    "value": {
                      "message": "The area is not covered.",
                      "code": "AREA_NOT_COVERED"
                    }
                  },
                  "PARTNER_ROLE_REQUIRED": {
                    "value": {
                      "message": "This operation is not available to the key's role.",
                      "code": "PARTNER_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found.\n\n- `NOT_FOUND` — Not found, or not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "NOT_FOUND": {
                    "value": {
                      "message": "Not found, or not yours.",
                      "code": "NOT_FOUND"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "usta",
        "x-ug-scope": "write",
        "x-ug-error-codes": [
          "USTA_ROLE_REQUIRED",
          "USTA_PROFILE_REQUIRED",
          "SERVICE_CATEGORIES_REQUIRED",
          "CATEGORY_NOT_COVERED",
          "CATEGORY_DOCUMENTS_REQUIRED",
          "CITY_NOT_COVERED",
          "OWN_REQUEST",
          "ALREADY_TAKEN",
          "PENDING_ADMIN_APPROVAL",
          "NOT_AVAILABLE_AT_SLOT",
          "AREA_NOT_COVERED"
        ]
      }
    },
    "/jobs/{id}/start": {
      "post": {
        "operationId": "startJob",
        "tags": [
          "Usta — Jobs"
        ],
        "summary": "Start the job",
        "description": "Starts the job with the start code the customer reads out. The code is checked on the server and is never sent to the usta by the API.\n\n**Access:** usta key · scope `write`",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The record's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "code": {
                    "description": "The start code on the customer's screen (6 digits; issued when the usta heads out).",
                    "type": "string",
                    "minLength": 4,
                    "maxLength": 12
                  }
                },
                "required": [
                  "code"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "request": {
                      "description": "A job as the usta sees it. Before accepting: the province and the job only; after accepting: the full address and the customer's first name and initial. The phone is never shared: talk through chat.",
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string"
                        },
                        "appointment_date": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "appointment_slot": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        }
                      },
                      "required": [
                        "id",
                        "status",
                        "appointment_date",
                        "appointment_slot"
                      ],
                      "additionalProperties": {}
                    }
                  },
                  "required": [
                    "request"
                  ],
                  "additionalProperties": {}
                },
                "example": {
                  "request": {
                    "id": "01J00000000000000000000000",
                    "reference": "UG-102610123456",
                    "title": "Klima Bakımı — Standart",
                    "status": "in_progress",
                    "category_handle": "klima",
                    "group_id": null,
                    "group_order": null,
                    "group_siblings": null,
                    "items": [
                      {
                        "title": "Klima Bakımı — Standart",
                        "quantity": 1,
                        "base_price": 750,
                        "product_id": "prod_01J00000000000000000000000",
                        "unit_price": 750,
                        "variant_id": "variant_01J00000000000000000000000"
                      }
                    ],
                    "product_id": "prod_01J00000000000000000000000",
                    "variant_id": "variant_01J00000000000000000000000",
                    "amount": 750,
                    "currency_code": "try",
                    "pricing_type": "fixed",
                    "fixed_price_checkout": true,
                    "appointment_date": "2026-10-06",
                    "appointment_slot": "09:00-11:00",
                    "notes": null,
                    "photos": [],
                    "city": "İstanbul",
                    "district": "Kadıköy",
                    "assigned_usta_id": "cus_01J00000000000000000000000",
                    "created_at": "2026-10-01T09:00:00.000Z",
                    "updated_at": "2026-10-01T09:00:00.000Z",
                    "metadata": {
                      "city": "İstanbul",
                      "district": "Kadıköy",
                      "on_the_way_at": "2026-10-01T09:00:00.000Z",
                      "ug_pricing_type": "fixed",
                      "ug_fixed_price_checkout": true,
                      "started_at": "2026-10-01T09:00:00.000Z"
                    },
                    "address_summary": "Test Sok. 1 D:2",
                    "order_id": null,
                    "customer": null,
                    "customer_id": "cus_01J00000000000000000000000"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.\n\n- `VALIDATION_ERROR` — The request failed validation; see `issues`.\n- `VISIT_CODE_REQUIRED` — Enter the code the customer reads out.\n- `VISIT_CODE_INVALID` — The code is wrong.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "VALIDATION_ERROR": {
                    "value": {
                      "message": "The request failed validation; see `issues`.",
                      "code": "VALIDATION_ERROR"
                    }
                  },
                  "VISIT_CODE_REQUIRED": {
                    "value": {
                      "message": "Enter the code the customer reads out.",
                      "code": "VISIT_CODE_REQUIRED"
                    }
                  },
                  "VISIT_CODE_INVALID": {
                    "value": {
                      "message": "The code is wrong.",
                      "code": "VISIT_CODE_INVALID"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `USTA_ROLE_REQUIRED` — The usta role is required.\n- `PARTNER_ROLE_REQUIRED` — This operation is not available to the key's role.\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "USTA_ROLE_REQUIRED": {
                    "value": {
                      "message": "The usta role is required.",
                      "code": "USTA_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_REQUIRED": {
                    "value": {
                      "message": "This operation is not available to the key's role.",
                      "code": "PARTNER_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found.\n\n- `NOT_FOUND` — Not found, or not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "NOT_FOUND": {
                    "value": {
                      "message": "Not found, or not yours.",
                      "code": "NOT_FOUND"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "The record's current state does not allow this.\n\n- `VISIT_CODE_NOT_ISSUED` — No code has been issued for this step yet (head out / send the code first).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "VISIT_CODE_NOT_ISSUED": {
                    "value": {
                      "message": "No code has been issued for this step yet (head out / send the code first).",
                      "code": "VISIT_CODE_NOT_ISSUED"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "usta",
        "x-ug-scope": "write",
        "x-ug-error-codes": [
          "USTA_ROLE_REQUIRED",
          "VISIT_CODE_REQUIRED",
          "VISIT_CODE_INVALID",
          "VISIT_CODE_NOT_ISSUED"
        ]
      }
    },
    "/legal": {
      "get": {
        "operationId": "getLegalDocuments",
        "tags": [
          "Catalog"
        ],
        "summary": "Get the contracts",
        "description": "The published contract texts and versions. Show them to the customer before booking and pass key and version in `POST /bookings`' `legal_acceptance`; the server fills in and stores the accepted copy itself.\n\n**Access:** either role · scope `read`",
        "parameters": [
          {
            "name": "product_ids",
            "in": "query",
            "required": false,
            "description": "Comma-separated service ids: the basket's service-specific contract terms come back too.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "documents": {
                      "description": "Published contracts; `POST /bookings` takes their key and version in `legal_acceptance`.",
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "key": {
                            "type": "string"
                          },
                          "version": {
                            "type": "number"
                          }
                        },
                        "required": [
                          "key",
                          "version"
                        ],
                        "additionalProperties": {}
                      }
                    },
                    "settings": {
                      "type": "object",
                      "properties": {},
                      "additionalProperties": {}
                    }
                  },
                  "required": [
                    "documents",
                    "settings"
                  ],
                  "additionalProperties": {}
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.\n\n- `VALIDATION_ERROR` — The request failed validation; see `issues`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "VALIDATION_ERROR": {
                    "value": {
                      "message": "The request failed validation; see `issues`.",
                      "code": "VALIDATION_ERROR"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "any",
        "x-ug-scope": "read"
      }
    },
    "/me": {
      "get": {
        "operationId": "getMe",
        "tags": [
          "Account"
        ],
        "summary": "Get the account",
        "description": "The account the key acts as.\n\n**Access:** either role · scope `read`",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "customer": {
                      "description": "The key's account.",
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id"
                      ],
                      "additionalProperties": {}
                    },
                    "role": {
                      "description": "The account's primary role.",
                      "type": "string"
                    },
                    "name_locked": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "customer",
                    "role"
                  ],
                  "additionalProperties": {}
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "any",
        "x-ug-scope": "read"
      }
    },
    "/notifications": {
      "get": {
        "operationId": "listNotifications",
        "tags": [
          "Account"
        ],
        "summary": "List notifications",
        "description": "The account's in-app notification inbox, newest first.\n\n**Access:** either role · scope `read`",
        "parameters": [
          {
            "name": "unread",
            "in": "query",
            "required": false,
            "description": "`true`: unread only.",
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "notifications": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id"
                        ],
                        "additionalProperties": {}
                      }
                    },
                    "unread_count": {
                      "type": "number"
                    }
                  },
                  "required": [
                    "notifications",
                    "unread_count"
                  ],
                  "additionalProperties": {}
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.\n\n- `VALIDATION_ERROR` — The request failed validation; see `issues`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "VALIDATION_ERROR": {
                    "value": {
                      "message": "The request failed validation; see `issues`.",
                      "code": "VALIDATION_ERROR"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "any",
        "x-ug-scope": "read"
      }
    },
    "/notifications/{id}/read": {
      "post": {
        "operationId": "markNotificationRead",
        "tags": [
          "Account"
        ],
        "summary": "Mark a notification read",
        "description": "Marks one notification read.\n\n**Access:** either role · scope `write`",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The record's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "notification": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id"
                      ],
                      "additionalProperties": {}
                    }
                  },
                  "required": [
                    "notification"
                  ],
                  "additionalProperties": {}
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found.\n\n- `NOT_FOUND` — Not found, or not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "NOT_FOUND": {
                    "value": {
                      "message": "Not found, or not yours.",
                      "code": "NOT_FOUND"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "any",
        "x-ug-scope": "write"
      }
    },
    "/notifications/read-all": {
      "post": {
        "operationId": "markAllNotificationsRead",
        "tags": [
          "Account"
        ],
        "summary": "Mark all notifications read",
        "description": "Marks every notification of the account read.\n\n**Access:** either role · scope `write`",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "updated": {}
                  },
                  "required": [
                    "updated"
                  ],
                  "additionalProperties": {}
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "any",
        "x-ug-scope": "write"
      }
    },
    "/notifications/sync": {
      "get": {
        "operationId": "syncNotifications",
        "tags": [
          "Account"
        ],
        "summary": "Poll for new notifications",
        "description": "Incremental read with a cursor: call once without `after` to get a cursor, then send the previous answer's `cursor.at` and `cursor.ids` on every poll. Use this instead of webhooks.\n\n**Access:** either role · scope `read`",
        "parameters": [
          {
            "name": "after",
            "in": "query",
            "required": false,
            "description": "The previous answer's `cursor.at`. Omit it to get a starting cursor only.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "seen",
            "in": "query",
            "required": false,
            "description": "The previous answer's `cursor.ids`, comma-separated.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "notifications": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "type": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "type"
                        ],
                        "additionalProperties": {}
                      }
                    },
                    "cursor": {
                      "type": "object",
                      "properties": {
                        "at": {
                          "type": "string"
                        },
                        "ids": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        }
                      },
                      "required": [
                        "at",
                        "ids"
                      ],
                      "additionalProperties": {}
                    },
                    "has_more": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "notifications",
                    "cursor",
                    "has_more"
                  ],
                  "additionalProperties": {}
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.\n\n- `VALIDATION_ERROR` — The request failed validation; see `issues`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "VALIDATION_ERROR": {
                    "value": {
                      "message": "The request failed validation; see `issues`.",
                      "code": "VALIDATION_ERROR"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "any",
        "x-ug-scope": "read",
        "x-ai-hint": "Poll every 15–60 s to follow state changes."
      }
    },
    "/payment-methods": {
      "get": {
        "operationId": "getPaymentMethods",
        "tags": [
          "Catalog"
        ],
        "summary": "Get payment methods",
        "description": "Which payment methods are open right now, with the bank-transfer accounts. `POST /payments` makes the same decision.\n\n**Access:** either role · scope `read`",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "card": {
                      "type": "object",
                      "properties": {
                        "available": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "available"
                      ],
                      "additionalProperties": {}
                    },
                    "bank_transfer": {
                      "type": "object",
                      "properties": {
                        "available": {
                          "type": "boolean"
                        },
                        "accounts": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {},
                            "additionalProperties": {}
                          }
                        }
                      },
                      "required": [
                        "available",
                        "accounts"
                      ],
                      "additionalProperties": {}
                    }
                  },
                  "required": [
                    "card",
                    "bank_transfer"
                  ],
                  "additionalProperties": {}
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "any",
        "x-ug-scope": "read"
      }
    },
    "/payments": {
      "get": {
        "operationId": "listPayments",
        "tags": [
          "Payments"
        ],
        "summary": "List payments",
        "description": "With `service_request_id`, a booking's payments, plus the transfer instructions while a transfer is awaited.\n\n**Access:** either role · scope `read`",
        "parameters": [
          {
            "name": "service_request_id",
            "in": "query",
            "required": false,
            "description": "A booking's payments.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "escrow_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "escrows": {
                      "type": "array",
                      "items": {
                        "description": "The payment record (escrow).",
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "status": {
                            "description": "`created` (waiting) → `held` → `released_to_technician` | `refunded` | `disputed`.",
                            "type": "string"
                          },
                          "amount": {
                            "type": "number"
                          },
                          "service_request_id": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "status",
                          "amount",
                          "service_request_id"
                        ],
                        "additionalProperties": {}
                      }
                    },
                    "bank_transfer": {
                      "description": "Transfer instructions while a transfer is awaited.",
                      "type": "object",
                      "properties": {},
                      "additionalProperties": {}
                    },
                    "payment": {
                      "description": "How to complete the payment.",
                      "type": "object",
                      "properties": {
                        "mode": {
                          "description": "`gateway`: send the customer to `payment_url`; 3D Secure completes at the bank and the payment is held on the bank's confirmation. `bank_transfer`: transfer `amount` with `reference` in the description. `mock`: test environments only, already held.",
                          "type": "string",
                          "enum": [
                            "gateway",
                            "mock",
                            "bank_transfer"
                          ]
                        },
                        "payment_url": {
                          "description": "`gateway` only: the address that opens the bank's payment page (browser or WebView).",
                          "type": "string"
                        },
                        "order_number": {
                          "type": "string"
                        },
                        "reference": {
                          "description": "The booking number to put in the transfer description.",
                          "type": "string"
                        },
                        "amount": {
                          "type": "number"
                        },
                        "accounts": {
                          "description": "Accounts the transfer can go to.",
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "iban": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "iban"
                            ],
                            "additionalProperties": {}
                          }
                        }
                      },
                      "required": [
                        "mode"
                      ],
                      "additionalProperties": {}
                    }
                  },
                  "required": [
                    "escrows"
                  ],
                  "additionalProperties": {}
                },
                "example": {
                  "escrows": [
                    {
                      "id": "01J00000000000000000000000",
                      "order_id": null,
                      "service_request_id": "01J00000000000000000000000",
                      "customer_id": "cus_01J00000000000000000000000",
                      "usta_id": null,
                      "kind": "primary",
                      "extra_work_id": null,
                      "amount": 750,
                      "currency_code": "try",
                      "commission_rate": 0.15,
                      "commission_amount": 112,
                      "payout_amount": 638,
                      "refunded_amount": 0,
                      "status": "held",
                      "provider": "card-mock",
                      "payment_session_id": null,
                      "transaction_id": "MOCK-01J00000000000000000000000",
                      "released_at": null,
                      "held_at": "2026-10-01T09:00:00.000Z",
                      "disputed_at": null,
                      "dispute_reason": null,
                      "refund_requested_at": null,
                      "refunded_at": null,
                      "refund_reason": null,
                      "refund_reference": null,
                      "refund_channel": null,
                      "refund_ticket_id": null,
                      "metadata": {
                        "commission_source": "services"
                      },
                      "created_at": "2026-10-01T09:00:00.000Z",
                      "updated_at": "2026-10-01T09:00:00.000Z",
                      "deleted_at": null
                    }
                  ],
                  "role": "customer"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.\n\n- `VALIDATION_ERROR` — The request failed validation; see `issues`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "VALIDATION_ERROR": {
                    "value": {
                      "message": "The request failed validation; see `issues`.",
                      "code": "VALIDATION_ERROR"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "any",
        "x-ug-scope": "read"
      },
      "post": {
        "operationId": "createPayment",
        "tags": [
          "Payments"
        ],
        "summary": "Open a payment",
        "description": "Opens the payment of one booking (leg); the amount is the server's, never the caller's. `payment.mode`: `gateway` → send the customer to `payment_url`; `bank_transfer` → show the instructions (the payment is held once the team sees the transfer); `mock` → test environments only. Once held, the job is dispatched to ustas. For a grouped booking call it for every leg; a card charges the whole group once, through the first leg. One payment per booking: a second call is 409 `ESCROW_EXISTS` with the existing record.\n\n**Access:** customer key · scope `money`",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "service_request_id": {
                    "description": "The booking (leg) to pay for.",
                    "type": "string",
                    "minLength": 1
                  },
                  "payment_method": {
                    "description": "`card` (default) or `bank_transfer`.",
                    "type": "string",
                    "enum": [
                      "card",
                      "bank_transfer"
                    ]
                  }
                },
                "required": [
                  "service_request_id"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "escrow": {
                      "description": "The payment record (escrow).",
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "status": {
                          "description": "`created` (waiting) → `held` → `released_to_technician` | `refunded` | `disputed`.",
                          "type": "string"
                        },
                        "amount": {
                          "type": "number"
                        },
                        "service_request_id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "status",
                        "amount",
                        "service_request_id"
                      ],
                      "additionalProperties": {}
                    },
                    "payment": {
                      "description": "How to complete the payment.",
                      "type": "object",
                      "properties": {
                        "mode": {
                          "description": "`gateway`: send the customer to `payment_url`; 3D Secure completes at the bank and the payment is held on the bank's confirmation. `bank_transfer`: transfer `amount` with `reference` in the description. `mock`: test environments only, already held.",
                          "type": "string",
                          "enum": [
                            "gateway",
                            "mock",
                            "bank_transfer"
                          ]
                        },
                        "payment_url": {
                          "description": "`gateway` only: the address that opens the bank's payment page (browser or WebView).",
                          "type": "string"
                        },
                        "order_number": {
                          "type": "string"
                        },
                        "reference": {
                          "description": "The booking number to put in the transfer description.",
                          "type": "string"
                        },
                        "amount": {
                          "type": "number"
                        },
                        "accounts": {
                          "description": "Accounts the transfer can go to.",
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "iban": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "iban"
                            ],
                            "additionalProperties": {}
                          }
                        }
                      },
                      "required": [
                        "mode"
                      ],
                      "additionalProperties": {}
                    },
                    "group": {
                      "description": "For a grouped booking: every leg and the total.",
                      "type": "object",
                      "properties": {
                        "group_id": {
                          "type": "string"
                        },
                        "total": {
                          "type": "number"
                        }
                      },
                      "required": [
                        "group_id",
                        "total"
                      ],
                      "additionalProperties": {}
                    }
                  },
                  "required": [
                    "escrow",
                    "payment"
                  ],
                  "additionalProperties": {}
                },
                "example": {
                  "escrow": {
                    "id": "01J00000000000000000000000",
                    "order_id": null,
                    "service_request_id": "01J00000000000000000000000",
                    "customer_id": "cus_01J00000000000000000000000",
                    "usta_id": null,
                    "kind": "primary",
                    "extra_work_id": null,
                    "amount": 750,
                    "currency_code": "try",
                    "commission_rate": 0.15,
                    "commission_amount": 112,
                    "payout_amount": 638,
                    "refunded_amount": 0,
                    "status": "held",
                    "provider": "card-mock",
                    "payment_session_id": null,
                    "transaction_id": "MOCK-01J00000000000000000000000",
                    "released_at": null,
                    "held_at": "2026-10-01T09:00:00.000Z",
                    "disputed_at": null,
                    "dispute_reason": null,
                    "refund_requested_at": null,
                    "refunded_at": null,
                    "refund_reason": null,
                    "refund_reference": null,
                    "refund_channel": null,
                    "refund_ticket_id": null,
                    "metadata": {
                      "commission_source": "services"
                    },
                    "created_at": "2026-10-01T09:00:00.000Z",
                    "updated_at": "2026-10-01T09:00:00.000Z",
                    "deleted_at": null
                  },
                  "payment": {
                    "mode": "mock"
                  },
                  "dispatch": {
                    "dispatched": false,
                    "offer_count": 0,
                    "note": "no_matching_usta"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.\n\n- `VALIDATION_ERROR` — The request failed validation; see `issues`.\n- `AMOUNT_NOT_SET` — The booking has no amount yet (discovery work: accept a quote first).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "VALIDATION_ERROR": {
                    "value": {
                      "message": "The request failed validation; see `issues`.",
                      "code": "VALIDATION_ERROR"
                    }
                  },
                  "AMOUNT_NOT_SET": {
                    "value": {
                      "message": "The booking has no amount yet (discovery work: accept a quote first).",
                      "code": "AMOUNT_NOT_SET"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_ROLE_REQUIRED` — This operation is not available to the key's role.\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_ROLE_REQUIRED": {
                    "value": {
                      "message": "This operation is not available to the key's role.",
                      "code": "PARTNER_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "The record's current state does not allow this.\n\n- `ESCROW_EXISTS` — A payment already exists for this booking; it is in `escrow`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "ESCROW_EXISTS": {
                    "value": {
                      "message": "A payment already exists for this booking; it is in `escrow`.",
                      "code": "ESCROW_EXISTS"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "Service not configured.\n\n- `PAYMENT_GATEWAY_UNCONFIGURED` — Card payment is currently unavailable.\n- `BANK_TRANSFER_UNCONFIGURED` — Bank transfer is currently unavailable.\n- `HOSTED_PAYMENT_UNAVAILABLE` — Card payment is not yet available on this channel; use bank transfer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PAYMENT_GATEWAY_UNCONFIGURED": {
                    "value": {
                      "message": "Card payment is currently unavailable.",
                      "code": "PAYMENT_GATEWAY_UNCONFIGURED"
                    }
                  },
                  "BANK_TRANSFER_UNCONFIGURED": {
                    "value": {
                      "message": "Bank transfer is currently unavailable.",
                      "code": "BANK_TRANSFER_UNCONFIGURED"
                    }
                  },
                  "HOSTED_PAYMENT_UNAVAILABLE": {
                    "value": {
                      "message": "Card payment is not yet available on this channel; use bank transfer.",
                      "code": "HOSTED_PAYMENT_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "customer",
        "x-ug-scope": "money",
        "x-ug-error-codes": [
          "ESCROW_EXISTS",
          "AMOUNT_NOT_SET",
          "PAYMENT_GATEWAY_UNCONFIGURED",
          "BANK_TRANSFER_UNCONFIGURED",
          "HOSTED_PAYMENT_UNAVAILABLE"
        ],
        "x-ai-hint": "For a card, hand `payment_url` to the customer; card details never go through this API."
      }
    },
    "/payments/{id}/dispute": {
      "post": {
        "operationId": "disputePayment",
        "tags": [
          "Payments"
        ],
        "summary": "Open a dispute",
        "description": "Freezes a held payment and opens a dispute ticket for the team; only after the job started and before confirmation. The team's verdict releases or refunds the payment.\n\n**Access:** customer key · scope `money`",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The record's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "description": "What went wrong, 50–500 characters.",
                    "type": "string",
                    "minLength": 50,
                    "maxLength": 500
                  }
                },
                "required": [
                  "reason"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "escrow": {
                      "description": "The payment record (escrow).",
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "status": {
                          "description": "`created` (waiting) → `held` → `released_to_technician` | `refunded` | `disputed`.",
                          "type": "string"
                        },
                        "amount": {
                          "type": "number"
                        },
                        "service_request_id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "status",
                        "amount",
                        "service_request_id"
                      ],
                      "additionalProperties": {}
                    },
                    "ticket": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id"
                      ],
                      "additionalProperties": {}
                    }
                  },
                  "required": [
                    "escrow",
                    "ticket"
                  ],
                  "additionalProperties": {}
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.\n\n- `VALIDATION_ERROR` — The request failed validation; see `issues`.\n- `DISPUTE_STATEMENT_INVALID` — The dispute statement must be 50–500 characters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "VALIDATION_ERROR": {
                    "value": {
                      "message": "The request failed validation; see `issues`.",
                      "code": "VALIDATION_ERROR"
                    }
                  },
                  "DISPUTE_STATEMENT_INVALID": {
                    "value": {
                      "message": "The dispute statement must be 50–500 characters.",
                      "code": "DISPUTE_STATEMENT_INVALID"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_ROLE_REQUIRED` — This operation is not available to the key's role.\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_ROLE_REQUIRED": {
                    "value": {
                      "message": "This operation is not available to the key's role.",
                      "code": "PARTNER_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found.\n\n- `NOT_FOUND` — Not found, or not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "NOT_FOUND": {
                    "value": {
                      "message": "Not found, or not yours.",
                      "code": "NOT_FOUND"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "The record's current state does not allow this.\n\n- `DISPUTE_NOT_HELD` — No dispute can be opened on this payment.\n- `DISPUTE_REFUND_PENDING` — A refund request is pending.\n- `DISPUTE_TOO_EARLY` — A dispute cannot be opened before the job starts.\n- `DISPUTE_ALREADY_CONFIRMED` — A confirmed job cannot be disputed.\n- `DISPUTE_ALREADY_DISPUTED` — A dispute is already open.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "DISPUTE_NOT_HELD": {
                    "value": {
                      "message": "No dispute can be opened on this payment.",
                      "code": "DISPUTE_NOT_HELD"
                    }
                  },
                  "DISPUTE_REFUND_PENDING": {
                    "value": {
                      "message": "A refund request is pending.",
                      "code": "DISPUTE_REFUND_PENDING"
                    }
                  },
                  "DISPUTE_TOO_EARLY": {
                    "value": {
                      "message": "A dispute cannot be opened before the job starts.",
                      "code": "DISPUTE_TOO_EARLY"
                    }
                  },
                  "DISPUTE_ALREADY_CONFIRMED": {
                    "value": {
                      "message": "A confirmed job cannot be disputed.",
                      "code": "DISPUTE_ALREADY_CONFIRMED"
                    }
                  },
                  "DISPUTE_ALREADY_DISPUTED": {
                    "value": {
                      "message": "A dispute is already open.",
                      "code": "DISPUTE_ALREADY_DISPUTED"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "customer",
        "x-ug-scope": "money",
        "x-ug-error-codes": [
          "DISPUTE_STATEMENT_INVALID",
          "DISPUTE_NOT_HELD",
          "DISPUTE_REFUND_PENDING",
          "DISPUTE_TOO_EARLY",
          "DISPUTE_ALREADY_CONFIRMED",
          "DISPUTE_ALREADY_DISPUTED"
        ]
      }
    },
    "/payments/{id}/refund": {
      "post": {
        "operationId": "requestRefund",
        "tags": [
          "Payments"
        ],
        "summary": "Request a refund",
        "description": "Files a refund request (202); the team executes the refund. The job cannot be confirmed while it is open.\n\n**Access:** customer key · scope `money`",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The record's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "description": "Why a refund is requested.",
                    "type": "string",
                    "minLength": 1
                  },
                  "amount": {
                    "description": "Optional partial amount; defaults to everything refundable. Whole TRY (750 = ₺750).",
                    "type": "number"
                  }
                },
                "required": [
                  "reason"
                ]
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ticket": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id"
                      ],
                      "additionalProperties": {}
                    },
                    "escrow": {
                      "description": "The payment record (escrow).",
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "status": {
                          "description": "`created` (waiting) → `held` → `released_to_technician` | `refunded` | `disputed`.",
                          "type": "string"
                        },
                        "amount": {
                          "type": "number"
                        },
                        "service_request_id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "status",
                        "amount",
                        "service_request_id"
                      ],
                      "additionalProperties": {}
                    },
                    "requested_amount": {
                      "type": "number"
                    }
                  },
                  "required": [
                    "ticket",
                    "escrow",
                    "requested_amount"
                  ],
                  "additionalProperties": {}
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.\n\n- `VALIDATION_ERROR` — The request failed validation; see `issues`.\n- `REFUND_REASON_REQUIRED` — A refund reason is required.\n- `REFUND_AMOUNT_INVALID` — The refund amount is invalid or exceeds what is refundable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "VALIDATION_ERROR": {
                    "value": {
                      "message": "The request failed validation; see `issues`.",
                      "code": "VALIDATION_ERROR"
                    }
                  },
                  "REFUND_REASON_REQUIRED": {
                    "value": {
                      "message": "A refund reason is required.",
                      "code": "REFUND_REASON_REQUIRED"
                    }
                  },
                  "REFUND_AMOUNT_INVALID": {
                    "value": {
                      "message": "The refund amount is invalid or exceeds what is refundable.",
                      "code": "REFUND_AMOUNT_INVALID"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_ROLE_REQUIRED` — This operation is not available to the key's role.\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_ROLE_REQUIRED": {
                    "value": {
                      "message": "This operation is not available to the key's role.",
                      "code": "PARTNER_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found.\n\n- `NOT_FOUND` — Not found, or not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "NOT_FOUND": {
                    "value": {
                      "message": "Not found, or not yours.",
                      "code": "NOT_FOUND"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "The record's current state does not allow this.\n\n- `ESCROW_DISPUTED` — The payment is under dispute.\n- `ESCROW_NOT_REFUNDABLE` — This payment is not refundable.\n- `REFUND_ALREADY_REQUESTED` — A refund was already requested for this payment.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "ESCROW_DISPUTED": {
                    "value": {
                      "message": "The payment is under dispute.",
                      "code": "ESCROW_DISPUTED"
                    }
                  },
                  "ESCROW_NOT_REFUNDABLE": {
                    "value": {
                      "message": "This payment is not refundable.",
                      "code": "ESCROW_NOT_REFUNDABLE"
                    }
                  },
                  "REFUND_ALREADY_REQUESTED": {
                    "value": {
                      "message": "A refund was already requested for this payment.",
                      "code": "REFUND_ALREADY_REQUESTED"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "customer",
        "x-ug-scope": "money",
        "x-ug-error-codes": [
          "REFUND_REASON_REQUIRED",
          "REFUND_AMOUNT_INVALID",
          "ESCROW_DISPUTED",
          "ESCROW_NOT_REFUNDABLE",
          "REFUND_ALREADY_REQUESTED"
        ]
      }
    },
    "/payouts": {
      "get": {
        "operationId": "listPayouts",
        "tags": [
          "Usta — Payouts"
        ],
        "summary": "List payouts",
        "description": "Weekly payout statements, newest first.\n\n**Access:** usta key · scope `read`",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "payouts": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "status": {
                            "description": "`pending_approval` → `approved` (the usta's approval) → `paid` (the team made the transfer).",
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "status"
                        ],
                        "additionalProperties": {}
                      }
                    }
                  },
                  "required": [
                    "payouts"
                  ],
                  "additionalProperties": {}
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_ROLE_REQUIRED` — This operation is not available to the key's role.\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_ROLE_REQUIRED": {
                    "value": {
                      "message": "This operation is not available to the key's role.",
                      "code": "PARTNER_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "usta",
        "x-ug-scope": "read"
      }
    },
    "/payouts/{id}": {
      "get": {
        "operationId": "getPayout",
        "tags": [
          "Usta — Payouts"
        ],
        "summary": "Get a payout",
        "description": "One payout and its items.\n\n**Access:** usta key · scope `read`",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The record's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "payout": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "status": {
                          "description": "`pending_approval` → `approved` (the usta's approval) → `paid` (the team made the transfer).",
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "status"
                      ],
                      "additionalProperties": {}
                    },
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {},
                        "additionalProperties": {}
                      }
                    },
                    "payment_delay_days": {
                      "type": "number"
                    }
                  },
                  "required": [
                    "payout",
                    "items",
                    "payment_delay_days"
                  ],
                  "additionalProperties": {}
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_ROLE_REQUIRED` — This operation is not available to the key's role.\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_ROLE_REQUIRED": {
                    "value": {
                      "message": "This operation is not available to the key's role.",
                      "code": "PARTNER_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found.\n\n- `NOT_FOUND` — Not found, or not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "NOT_FOUND": {
                    "value": {
                      "message": "Not found, or not yours.",
                      "code": "NOT_FOUND"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "usta",
        "x-ug-scope": "read"
      }
    },
    "/payouts/{id}/approve": {
      "post": {
        "operationId": "approvePayout",
        "tags": [
          "Usta — Payouts"
        ],
        "summary": "Approve a payout",
        "description": "Approves the statement; the team pays it on the due date. A valid IBAN is required.\n\n**Access:** usta key · scope `money`",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The record's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "payout": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "status": {
                          "description": "`pending_approval` → `approved` (the usta's approval) → `paid` (the team made the transfer).",
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "status"
                      ],
                      "additionalProperties": {}
                    }
                  },
                  "required": [
                    "payout"
                  ],
                  "additionalProperties": {}
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_ROLE_REQUIRED` — This operation is not available to the key's role.\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_ROLE_REQUIRED": {
                    "value": {
                      "message": "This operation is not available to the key's role.",
                      "code": "PARTNER_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found.\n\n- `NOT_FOUND` — Not found, or not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "NOT_FOUND": {
                    "value": {
                      "message": "Not found, or not yours.",
                      "code": "NOT_FOUND"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "The record's current state does not allow this.\n\n- `PAYOUT_DETAILS_REQUIRED` — A valid IBAN is required for payouts.\n- `INVALID_STATUS` — The record's status does not allow this.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PAYOUT_DETAILS_REQUIRED": {
                    "value": {
                      "message": "A valid IBAN is required for payouts.",
                      "code": "PAYOUT_DETAILS_REQUIRED"
                    }
                  },
                  "INVALID_STATUS": {
                    "value": {
                      "message": "The record's status does not allow this.",
                      "code": "INVALID_STATUS"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "usta",
        "x-ug-scope": "money",
        "x-ug-error-codes": [
          "PAYOUT_DETAILS_REQUIRED",
          "INVALID_STATUS"
        ]
      }
    },
    "/pricing/preview": {
      "post": {
        "operationId": "previewPricing",
        "tags": [
          "Catalog"
        ],
        "summary": "Price a basket",
        "description": "Prices a basket with the booking routes' own code without creating anything: zone prices, answer surcharges and the total. This is the amount to show the customer; `POST /bookings` computes the same.\n\n**Access:** either role · scope `read`",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "items": {
                    "description": "Services to price (1–50).",
                    "minItems": 1,
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "variant_id": {
                          "description": "Package (variant) id. When omitted the service's cheapest package is used.",
                          "type": "string",
                          "minLength": 1
                        },
                        "product_id": {
                          "description": "Service (product) id; required when `variant_id` is absent.",
                          "type": "string",
                          "minLength": 1
                        },
                        "quantity": {
                          "description": "Quantity, 1–99. Defaults to 1.",
                          "type": "integer",
                          "minimum": 1,
                          "maximum": 99
                        },
                        "answers": {
                          "description": "Answers to the service's questions (`ug_service_questions`). Any price difference is read from the catalog, never from the caller; a missing required answer is 400 `INVALID_SERVICE_ANSWER`.",
                          "maxItems": 20,
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "question_id": {
                                "description": "Question id.",
                                "type": "string",
                                "minLength": 1
                              },
                              "option_ids": {
                                "description": "Chosen options for select questions.",
                                "type": "array",
                                "items": {
                                  "type": "string"
                                }
                              },
                              "text": {
                                "anyOf": [
                                  {
                                    "type": "string"
                                  },
                                  {
                                    "type": "null"
                                  }
                                ]
                              },
                              "number": {
                                "anyOf": [
                                  {
                                    "type": "number"
                                  },
                                  {
                                    "type": "null"
                                  }
                                ]
                              },
                              "photos": {
                                "description": "Photo question: URLs from `POST /uploads/photo`.",
                                "type": "array",
                                "items": {
                                  "type": "string"
                                }
                              },
                              "entry_id": {
                                "description": "Catalog question (brand/model): an entry id from `GET /reference-catalogs/{key}`.",
                                "anyOf": [
                                  {
                                    "type": "string"
                                  },
                                  {
                                    "type": "null"
                                  }
                                ]
                              },
                              "entry_label": {
                                "anyOf": [
                                  {
                                    "type": "string"
                                  },
                                  {
                                    "type": "null"
                                  }
                                ]
                              }
                            },
                            "required": [
                              "question_id"
                            ]
                          }
                        }
                      }
                    }
                  },
                  "city": {
                    "description": "Province (e.g. `İstanbul`). Zone pricing is applied per province/district.",
                    "type": "string"
                  },
                  "district": {
                    "description": "District (e.g. `Kadıköy`).",
                    "type": "string"
                  }
                },
                "required": [
                  "items"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "title": {
                            "type": "string"
                          },
                          "unit_price": {
                            "type": "number"
                          },
                          "quantity": {
                            "type": "number"
                          }
                        },
                        "required": [
                          "title",
                          "unit_price",
                          "quantity"
                        ],
                        "additionalProperties": {}
                      }
                    },
                    "total": {
                      "description": "Total in whole TRY.",
                      "type": "number"
                    },
                    "currency_code": {
                      "type": "string",
                      "const": "try"
                    },
                    "priced_by_zone": {
                      "description": "`true` when at least one line was priced by zone.",
                      "type": "boolean"
                    },
                    "location": {
                      "type": "object",
                      "properties": {},
                      "additionalProperties": {}
                    }
                  },
                  "required": [
                    "items",
                    "total",
                    "currency_code",
                    "priced_by_zone",
                    "location"
                  ],
                  "additionalProperties": {}
                },
                "example": {
                  "items": [
                    {
                      "title": "Klima Bakımı — Standart",
                      "quantity": 1,
                      "unit_price": 750,
                      "product_id": "prod_01J00000000000000000000000",
                      "variant_id": "variant_01J00000000000000000000000",
                      "base_price": 750
                    }
                  ],
                  "total": 750,
                  "currency_code": "try",
                  "location": {
                    "city": "İstanbul",
                    "district": "Kadıköy",
                    "zone_key": "istanbul/kadikoy"
                  },
                  "priced_by_zone": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.\n\n- `VALIDATION_ERROR` — The request failed validation; see `issues`.\n- `EMPTY_ITEMS` — No services to price.\n- `INVALID_SERVICE_ANSWER` — A service question's answer is missing or invalid; see `errors`.\n- `INVALID_SERVICE_ITEM` — A service was not found or is not published.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "VALIDATION_ERROR": {
                    "value": {
                      "message": "The request failed validation; see `issues`.",
                      "code": "VALIDATION_ERROR"
                    }
                  },
                  "EMPTY_ITEMS": {
                    "value": {
                      "message": "No services to price.",
                      "code": "EMPTY_ITEMS"
                    }
                  },
                  "INVALID_SERVICE_ANSWER": {
                    "value": {
                      "message": "A service question's answer is missing or invalid; see `errors`.",
                      "code": "INVALID_SERVICE_ANSWER"
                    }
                  },
                  "INVALID_SERVICE_ITEM": {
                    "value": {
                      "message": "A service was not found or is not published.",
                      "code": "INVALID_SERVICE_ITEM"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "any",
        "x-ug-scope": "read",
        "x-ug-error-codes": [
          "EMPTY_ITEMS",
          "INVALID_SERVICE_ANSWER",
          "INVALID_SERVICE_ITEM"
        ]
      }
    },
    "/quotes": {
      "get": {
        "operationId": "listQuotes",
        "tags": [
          "Quotes"
        ],
        "summary": "List quotes",
        "description": "Quotes on discovery-priced jobs; customers never see drafts.\n\n**Access:** either role · scope `read`",
        "parameters": [
          {
            "name": "service_request_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "quotes": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string"
                          },
                          "amount": {
                            "type": "number"
                          }
                        },
                        "required": [
                          "id",
                          "status",
                          "amount"
                        ],
                        "additionalProperties": {}
                      }
                    },
                    "role": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "quotes",
                    "role"
                  ],
                  "additionalProperties": {}
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.\n\n- `VALIDATION_ERROR` — The request failed validation; see `issues`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "VALIDATION_ERROR": {
                    "value": {
                      "message": "The request failed validation; see `issues`.",
                      "code": "VALIDATION_ERROR"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "any",
        "x-ug-scope": "read"
      },
      "post": {
        "operationId": "createQuote",
        "tags": [
          "Quotes"
        ],
        "summary": "Create a quote",
        "description": "Quotes a price on a discovery-priced job; the amount must be within the service's range. Sent right away by default.\n\n**Access:** usta key · scope `write`",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "service_request_id": {
                    "type": "string",
                    "minLength": 1
                  },
                  "amount": {
                    "description": "Quote amount, within the service's price range. Whole TRY (750 = ₺750).",
                    "type": "number"
                  },
                  "notes": {
                    "type": "string",
                    "maxLength": 2000
                  },
                  "send": {
                    "description": "`false`: save as a draft (default: send right away).",
                    "type": "boolean"
                  }
                },
                "required": [
                  "service_request_id",
                  "amount"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "quote": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string"
                        },
                        "amount": {
                          "type": "number"
                        }
                      },
                      "required": [
                        "id",
                        "status",
                        "amount"
                      ],
                      "additionalProperties": {}
                    }
                  },
                  "required": [
                    "quote"
                  ],
                  "additionalProperties": {}
                },
                "example": {
                  "quote": {
                    "id": "01J00000000000000000000000",
                    "service_request_id": "01J00000000000000000000000",
                    "usta_id": "cus_01J00000000000000000000000",
                    "customer_id": "cus_01J00000000000000000000000",
                    "amount": 1500,
                    "currency_code": "try",
                    "notes": "Keşif",
                    "status": "sent",
                    "metadata": {
                      "ug_min_price": null,
                      "ug_max_price": null
                    },
                    "created_at": "2026-10-01T09:00:00.000Z",
                    "updated_at": "2026-10-01T09:00:00.000Z",
                    "deleted_at": null
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.\n\n- `VALIDATION_ERROR` — The request failed validation; see `issues`.\n- `FIXED_PRICE_PATH` — Fixed-price jobs take no quotes.\n- `QUOTE_CREATE_FAILED` — The quote could not be created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "VALIDATION_ERROR": {
                    "value": {
                      "message": "The request failed validation; see `issues`.",
                      "code": "VALIDATION_ERROR"
                    }
                  },
                  "FIXED_PRICE_PATH": {
                    "value": {
                      "message": "Fixed-price jobs take no quotes.",
                      "code": "FIXED_PRICE_PATH"
                    }
                  },
                  "QUOTE_CREATE_FAILED": {
                    "value": {
                      "message": "The quote could not be created.",
                      "code": "QUOTE_CREATE_FAILED"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_ROLE_REQUIRED` — This operation is not available to the key's role.\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_ROLE_REQUIRED": {
                    "value": {
                      "message": "This operation is not available to the key's role.",
                      "code": "PARTNER_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable request.\n\n- `PRICE_OUT_OF_RANGE` — The quote is outside the service's price range (`min_price`, `max_price`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PRICE_OUT_OF_RANGE": {
                    "value": {
                      "message": "The quote is outside the service's price range (`min_price`, `max_price`).",
                      "code": "PRICE_OUT_OF_RANGE"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "usta",
        "x-ug-scope": "write",
        "x-ug-error-codes": [
          "FIXED_PRICE_PATH",
          "PRICE_OUT_OF_RANGE",
          "QUOTE_CREATE_FAILED"
        ]
      }
    },
    "/quotes/{id}/accept": {
      "post": {
        "operationId": "acceptQuote",
        "tags": [
          "Quotes"
        ],
        "summary": "Accept a quote",
        "description": "Accepts the quote; its amount becomes the booking's amount. Then call `POST /payments`.\n\n**Access:** customer key · scope `money`",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The record's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "quote": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string"
                        },
                        "amount": {
                          "type": "number"
                        }
                      },
                      "required": [
                        "id",
                        "status",
                        "amount"
                      ],
                      "additionalProperties": {}
                    }
                  },
                  "required": [
                    "quote"
                  ],
                  "additionalProperties": {}
                },
                "example": {
                  "quote": {
                    "id": "01J00000000000000000000000",
                    "service_request_id": "01J00000000000000000000000",
                    "usta_id": "cus_01J00000000000000000000000",
                    "customer_id": "cus_01J00000000000000000000000",
                    "amount": 1500,
                    "currency_code": "try",
                    "notes": "Keşif",
                    "status": "accepted",
                    "metadata": {
                      "ug_max_price": null,
                      "ug_min_price": null
                    },
                    "created_at": "2026-10-01T09:00:00.000Z",
                    "updated_at": "2026-10-01T09:00:00.000Z",
                    "deleted_at": null
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_ROLE_REQUIRED` — This operation is not available to the key's role.\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_ROLE_REQUIRED": {
                    "value": {
                      "message": "This operation is not available to the key's role.",
                      "code": "PARTNER_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found.\n\n- `NOT_FOUND` — Not found, or not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "NOT_FOUND": {
                    "value": {
                      "message": "Not found, or not yours.",
                      "code": "NOT_FOUND"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "customer",
        "x-ug-scope": "money"
      }
    },
    "/quotes/{id}/reject": {
      "post": {
        "operationId": "rejectQuote",
        "tags": [
          "Quotes"
        ],
        "summary": "Reject a quote",
        "description": "Rejects the quote.\n\n**Access:** customer key · scope `write`",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The record's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string",
                    "maxLength": 1000
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "quote": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string"
                        },
                        "amount": {
                          "type": "number"
                        }
                      },
                      "required": [
                        "id",
                        "status",
                        "amount"
                      ],
                      "additionalProperties": {}
                    }
                  },
                  "required": [
                    "quote"
                  ],
                  "additionalProperties": {}
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.\n\n- `VALIDATION_ERROR` — The request failed validation; see `issues`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "VALIDATION_ERROR": {
                    "value": {
                      "message": "The request failed validation; see `issues`.",
                      "code": "VALIDATION_ERROR"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_ROLE_REQUIRED` — This operation is not available to the key's role.\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_ROLE_REQUIRED": {
                    "value": {
                      "message": "This operation is not available to the key's role.",
                      "code": "PARTNER_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found.\n\n- `NOT_FOUND` — Not found, or not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "NOT_FOUND": {
                    "value": {
                      "message": "Not found, or not yours.",
                      "code": "NOT_FOUND"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "customer",
        "x-ug-scope": "write"
      }
    },
    "/quotes/{id}/send": {
      "post": {
        "operationId": "sendQuote",
        "tags": [
          "Quotes"
        ],
        "summary": "Send a draft quote",
        "description": "Sends a quote saved as a draft to the customer.\n\n**Access:** usta key · scope `write`",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The record's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "quote": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string"
                        },
                        "amount": {
                          "type": "number"
                        }
                      },
                      "required": [
                        "id",
                        "status",
                        "amount"
                      ],
                      "additionalProperties": {}
                    }
                  },
                  "required": [
                    "quote"
                  ],
                  "additionalProperties": {}
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_ROLE_REQUIRED` — This operation is not available to the key's role.\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_ROLE_REQUIRED": {
                    "value": {
                      "message": "This operation is not available to the key's role.",
                      "code": "PARTNER_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found.\n\n- `NOT_FOUND` — Not found, or not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "NOT_FOUND": {
                    "value": {
                      "message": "Not found, or not yours.",
                      "code": "NOT_FOUND"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "usta",
        "x-ug-scope": "write"
      }
    },
    "/ratings": {
      "get": {
        "operationId": "listRatings",
        "tags": [
          "Bookings"
        ],
        "summary": "Get ratings",
        "description": "With `service_request_id`, a job's rating; with `usta_id`, an usta's public ratings and average.\n\n**Access:** either role · scope `read`",
        "parameters": [
          {
            "name": "service_request_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "usta_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "rating": {},
                    "ratings": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {},
                        "additionalProperties": {}
                      }
                    },
                    "summary": {}
                  },
                  "additionalProperties": {}
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.\n\n- `VALIDATION_ERROR` — The request failed validation; see `issues`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "VALIDATION_ERROR": {
                    "value": {
                      "message": "The request failed validation; see `issues`.",
                      "code": "VALIDATION_ERROR"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "any",
        "x-ug-scope": "read"
      },
      "post": {
        "operationId": "rateBooking",
        "tags": [
          "Bookings"
        ],
        "summary": "Rate a job",
        "description": "Once per job: the usta score (feeds the usta's ranking) and a separate app score.\n\n**Access:** customer key · scope `write`",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "service_request_id": {
                    "type": "string",
                    "minLength": 1
                  },
                  "rating": {
                    "description": "Usta score, 1–5.",
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 5
                  },
                  "comment": {
                    "type": "string",
                    "maxLength": 2000
                  },
                  "app_rating": {
                    "description": "App score, 1–5 (never affects the usta's ranking).",
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 5
                  },
                  "app_comment": {
                    "type": "string",
                    "maxLength": 2000
                  },
                  "would_rebook": {
                    "type": "boolean"
                  },
                  "would_recommend": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "service_request_id",
                  "rating"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "rating": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id"
                      ],
                      "additionalProperties": {}
                    }
                  },
                  "required": [
                    "rating"
                  ],
                  "additionalProperties": {}
                },
                "example": {
                  "rating": {
                    "id": "01J00000000000000000000000",
                    "order_id": null,
                    "service_request_id": "01J00000000000000000000000",
                    "customer_id": "cus_01J00000000000000000000000",
                    "usta_id": "cus_01J00000000000000000000000",
                    "rating": 5,
                    "comment": null,
                    "app_rating": 4,
                    "app_comment": null,
                    "would_rebook": null,
                    "would_recommend": null,
                    "metadata": null,
                    "created_at": "2026-10-01T09:00:00.000Z",
                    "updated_at": "2026-10-01T09:00:00.000Z",
                    "deleted_at": null
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.\n\n- `VALIDATION_ERROR` — The request failed validation; see `issues`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "VALIDATION_ERROR": {
                    "value": {
                      "message": "The request failed validation; see `issues`.",
                      "code": "VALIDATION_ERROR"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_ROLE_REQUIRED` — This operation is not available to the key's role.\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_ROLE_REQUIRED": {
                    "value": {
                      "message": "This operation is not available to the key's role.",
                      "code": "PARTNER_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "customer",
        "x-ug-scope": "write"
      }
    },
    "/reference-catalogs/{key}": {
      "get": {
        "operationId": "getReferenceCatalog",
        "tags": [
          "Catalog"
        ],
        "summary": "Get a reference catalog",
        "description": "The option list behind catalog questions (e.g. air-conditioner brand and model). `entries` is a tree: `parent_id` ties a model to its brand. Use the id as `entry_id` in an answer.\n\n**Access:** either role · scope `read`",
        "parameters": [
          {
            "name": "key",
            "in": "path",
            "required": true,
            "description": "The record's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "catalog": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "key": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "key",
                        "name"
                      ],
                      "additionalProperties": {}
                    },
                    "entries": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id"
                        ],
                        "additionalProperties": {}
                      }
                    }
                  },
                  "required": [
                    "catalog",
                    "entries"
                  ],
                  "additionalProperties": {}
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found.\n\n- `NOT_FOUND` — Not found, or not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "NOT_FOUND": {
                    "value": {
                      "message": "Not found, or not yours.",
                      "code": "NOT_FOUND"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "any",
        "x-ug-scope": "read",
        "x-ug-error-codes": [
          "NOT_FOUND"
        ]
      }
    },
    "/shop": {
      "get": {
        "operationId": "getShop",
        "tags": [
          "Usta — Shop"
        ],
        "summary": "Get the shop",
        "description": "The usta's shop (profile) record.\n\n**Access:** usta key · scope `read`",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "shops": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "is_active": {
                            "description": "`true` once the call center approved; only approved ustas get jobs.",
                            "type": "boolean"
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "is_active"
                        ],
                        "additionalProperties": {}
                      }
                    }
                  },
                  "required": [
                    "shops"
                  ],
                  "additionalProperties": {}
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_ROLE_REQUIRED` — This operation is not available to the key's role.\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_ROLE_REQUIRED": {
                    "value": {
                      "message": "This operation is not available to the key's role.",
                      "code": "PARTNER_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "usta",
        "x-ug-scope": "read"
      },
      "post": {
        "operationId": "saveShop",
        "tags": [
          "Usta — Shop"
        ],
        "summary": "Save the shop",
        "description": "Creates or updates the shop. A new shop gets no jobs until the call center approves it. Name, photo and description changes go to the team for review.\n\n**Access:** usta key · scope `write`",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "description": "Business name.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 2000
                  },
                  "city": {
                    "type": "string"
                  },
                  "district": {
                    "type": "string"
                  },
                  "service_handles": {
                    "description": "The `handle`s of the categories served (`GET /catalog`).",
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "service_districts": {
                    "maxItems": 200,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 120
                    }
                  },
                  "service_product_ids": {
                    "maxItems": 200,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 120
                    }
                  },
                  "business_profile": {
                    "type": "object",
                    "properties": {
                      "team_size": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 500
                      },
                      "can_issue_invoice": {
                        "type": "boolean"
                      },
                      "has_mastery_certificate": {
                        "type": "boolean"
                      },
                      "employees_insured": {
                        "description": "Required only when `team_size > 0`.",
                        "type": "boolean"
                      }
                    },
                    "required": [
                      "team_size",
                      "can_issue_invoice",
                      "has_mastery_certificate"
                    ]
                  },
                  "iban": {
                    "description": "TR IBAN; the holder must be the usta or the business.",
                    "type": "string"
                  },
                  "iban_holder": {
                    "type": "string"
                  },
                  "tax_number": {
                    "type": "string"
                  },
                  "avatar_url": {
                    "type": "string"
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "shop": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        },
                        "is_active": {
                          "description": "`true` once the call center approved; only approved ustas get jobs.",
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "id",
                        "name",
                        "is_active"
                      ],
                      "additionalProperties": {}
                    },
                    "pending_review": {
                      "description": "Fields queued for the team's review (name, photo, description); customers see the old value until approved.",
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  },
                  "required": [
                    "shop"
                  ],
                  "additionalProperties": {}
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.\n\n- `VALIDATION_ERROR` — The request failed validation; see `issues`.\n- `INVALID_BUSINESS_PROFILE` — The business profile is incomplete or invalid.\n- `INVALID_IBAN` — Invalid IBAN.\n- `IBAN_HOLDER_REQUIRED` — The account holder's name is required.\n- `IBAN_HOLDER_MISMATCH` — The account holder must be the usta or the business.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "VALIDATION_ERROR": {
                    "value": {
                      "message": "The request failed validation; see `issues`.",
                      "code": "VALIDATION_ERROR"
                    }
                  },
                  "INVALID_BUSINESS_PROFILE": {
                    "value": {
                      "message": "The business profile is incomplete or invalid.",
                      "code": "INVALID_BUSINESS_PROFILE"
                    }
                  },
                  "INVALID_IBAN": {
                    "value": {
                      "message": "Invalid IBAN.",
                      "code": "INVALID_IBAN"
                    }
                  },
                  "IBAN_HOLDER_REQUIRED": {
                    "value": {
                      "message": "The account holder's name is required.",
                      "code": "IBAN_HOLDER_REQUIRED"
                    }
                  },
                  "IBAN_HOLDER_MISMATCH": {
                    "value": {
                      "message": "The account holder must be the usta or the business.",
                      "code": "IBAN_HOLDER_MISMATCH"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `USTA_ROLE_REQUIRED` — The usta role is required.\n- `PARTNER_ROLE_REQUIRED` — This operation is not available to the key's role.\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "USTA_ROLE_REQUIRED": {
                    "value": {
                      "message": "The usta role is required.",
                      "code": "USTA_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_REQUIRED": {
                    "value": {
                      "message": "This operation is not available to the key's role.",
                      "code": "PARTNER_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "usta",
        "x-ug-scope": "write",
        "x-ug-error-codes": [
          "USTA_ROLE_REQUIRED",
          "INVALID_BUSINESS_PROFILE",
          "INVALID_IBAN",
          "IBAN_HOLDER_REQUIRED",
          "IBAN_HOLDER_MISMATCH"
        ]
      }
    },
    "/shop/availability": {
      "get": {
        "operationId": "getAvailability",
        "tags": [
          "Usta — Shop"
        ],
        "summary": "Get working hours",
        "description": "Weekly working slots and date-specific exceptions.\n\n**Access:** usta key · scope `read`",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "availability": {
                      "type": "object",
                      "properties": {
                        "configured": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "configured"
                      ],
                      "additionalProperties": {}
                    }
                  },
                  "required": [
                    "availability"
                  ],
                  "additionalProperties": {}
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_ROLE_REQUIRED` — This operation is not available to the key's role.\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_ROLE_REQUIRED": {
                    "value": {
                      "message": "This operation is not available to the key's role.",
                      "code": "PARTNER_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found.\n\n- `NOT_FOUND` — Not found, or not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "NOT_FOUND": {
                    "value": {
                      "message": "Not found, or not yours.",
                      "code": "NOT_FOUND"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "usta",
        "x-ug-scope": "read",
        "x-ug-error-codes": [
          "NOT_FOUND"
        ]
      },
      "put": {
        "operationId": "setAvailability",
        "tags": [
          "Usta — Shop"
        ],
        "summary": "Set working hours",
        "description": "Writes the weekly slots and exceptions; invalid entries are dropped. Job matching follows this calendar.\n\n**Access:** usta key · scope `write`",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "weekly": {
                    "description": "Weekday (`0` Sunday … `6` Saturday) → slots worked.",
                    "type": "object",
                    "propertyNames": {
                      "type": "string",
                      "pattern": "^[0-6]$"
                    },
                    "additionalProperties": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  },
                  "overrides": {
                    "description": "Date-specific exceptions.",
                    "type": "object",
                    "propertyNames": {
                      "type": "string",
                      "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                    },
                    "additionalProperties": {
                      "type": "object",
                      "properties": {
                        "off": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "extra": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "full_day_off": {
                          "type": "boolean"
                        }
                      }
                    }
                  },
                  "preset": {
                    "type": "string",
                    "enum": [
                      "every_day",
                      "weekdays",
                      "weekends",
                      "custom"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "availability": {
                      "type": "object",
                      "properties": {
                        "configured": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "configured"
                      ],
                      "additionalProperties": {}
                    }
                  },
                  "required": [
                    "availability"
                  ],
                  "additionalProperties": {}
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.\n\n- `VALIDATION_ERROR` — The request failed validation; see `issues`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "VALIDATION_ERROR": {
                    "value": {
                      "message": "The request failed validation; see `issues`.",
                      "code": "VALIDATION_ERROR"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_ROLE_REQUIRED` — This operation is not available to the key's role.\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_ROLE_REQUIRED": {
                    "value": {
                      "message": "This operation is not available to the key's role.",
                      "code": "PARTNER_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found.\n\n- `NOT_FOUND` — Not found, or not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "NOT_FOUND": {
                    "value": {
                      "message": "Not found, or not yours.",
                      "code": "NOT_FOUND"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "usta",
        "x-ug-scope": "write",
        "x-ug-error-codes": [
          "NOT_FOUND"
        ]
      }
    },
    "/shop/documents": {
      "get": {
        "operationId": "listDocuments",
        "tags": [
          "Usta — Shop"
        ],
        "summary": "List documents",
        "description": "Uploaded documents and the team's decisions.\n\n**Access:** usta key · scope `read`",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "documents": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id"
                        ],
                        "additionalProperties": {}
                      }
                    }
                  },
                  "required": [
                    "documents"
                  ],
                  "additionalProperties": {}
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_ROLE_REQUIRED` — This operation is not available to the key's role.\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_ROLE_REQUIRED": {
                    "value": {
                      "message": "This operation is not available to the key's role.",
                      "code": "PARTNER_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "usta",
        "x-ug-scope": "read"
      },
      "post": {
        "operationId": "createDocument",
        "tags": [
          "Usta — Shop"
        ],
        "summary": "Add a document record",
        "description": "Files a previously uploaded private file as a document.\n\n**Access:** usta key · scope `write`",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "doc_type": {
                    "type": "string",
                    "enum": [
                      "myk",
                      "craft_cert",
                      "other"
                    ]
                  },
                  "file_url": {
                    "description": "A private-tier file this account uploaded. `POST /shop/documents/upload` is simpler in most cases.",
                    "type": "string",
                    "minLength": 1
                  },
                  "file_name": {
                    "type": "string"
                  },
                  "mime_type": {
                    "type": "string"
                  }
                },
                "required": [
                  "doc_type",
                  "file_url"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "document": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id"
                      ],
                      "additionalProperties": {}
                    }
                  },
                  "required": [
                    "document"
                  ],
                  "additionalProperties": {}
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.\n\n- `VALIDATION_ERROR` — The request failed validation; see `issues`.\n- `UNSUPPORTED_FILE_URL` — The file URL is not an upload of this account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "VALIDATION_ERROR": {
                    "value": {
                      "message": "The request failed validation; see `issues`.",
                      "code": "VALIDATION_ERROR"
                    }
                  },
                  "UNSUPPORTED_FILE_URL": {
                    "value": {
                      "message": "The file URL is not an upload of this account.",
                      "code": "UNSUPPORTED_FILE_URL"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_ROLE_REQUIRED` — This operation is not available to the key's role.\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_ROLE_REQUIRED": {
                    "value": {
                      "message": "This operation is not available to the key's role.",
                      "code": "PARTNER_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found.\n\n- `SHOP_NOT_FOUND` — The usta shop was not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "SHOP_NOT_FOUND": {
                    "value": {
                      "message": "The usta shop was not found.",
                      "code": "SHOP_NOT_FOUND"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "usta",
        "x-ug-scope": "write",
        "x-ug-error-codes": [
          "SHOP_NOT_FOUND",
          "UNSUPPORTED_FILE_URL"
        ]
      }
    },
    "/shop/documents/upload": {
      "post": {
        "operationId": "uploadDocument",
        "tags": [
          "Usta — Shop"
        ],
        "summary": "Upload a document",
        "description": "Uploads a vocational or mastery certificate; some categories' jobs require an approved one.\n\n**Access:** usta key · scope `write`",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "doc_type": {
                    "description": "`myk` (vocational certificate), `craft_cert` (mastery certificate), `other`.",
                    "type": "string",
                    "enum": [
                      "myk",
                      "craft_cert",
                      "other"
                    ]
                  },
                  "content": {
                    "description": "Base64 file, at most 8 MB.",
                    "type": "string",
                    "minLength": 1
                  },
                  "mime_type": {
                    "type": "string",
                    "enum": [
                      "image/jpeg",
                      "image/png",
                      "image/heic",
                      "image/webp",
                      "application/pdf"
                    ]
                  },
                  "file_name": {
                    "type": "string"
                  },
                  "category_handle": {
                    "description": "The category `handle` when the certificate belongs to a trade.",
                    "type": "string"
                  }
                },
                "required": [
                  "doc_type",
                  "content"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "document": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id"
                      ],
                      "additionalProperties": {}
                    }
                  },
                  "required": [
                    "document"
                  ],
                  "additionalProperties": {}
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.\n\n- `VALIDATION_ERROR` — The request failed validation; see `issues`.\n- `INVALID_DOC_TYPE` — Invalid document type (`myk`, `craft_cert`, `other`).\n- `UNSUPPORTED_MIME` — Unsupported file type.\n- `FILE_TOO_LARGE` — Files are limited to 8 MB.\n- `INVALID_DOCUMENT_CATEGORY` — A document can only be filed under one of the usta's categories.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "VALIDATION_ERROR": {
                    "value": {
                      "message": "The request failed validation; see `issues`.",
                      "code": "VALIDATION_ERROR"
                    }
                  },
                  "INVALID_DOC_TYPE": {
                    "value": {
                      "message": "Invalid document type (`myk`, `craft_cert`, `other`).",
                      "code": "INVALID_DOC_TYPE"
                    }
                  },
                  "UNSUPPORTED_MIME": {
                    "value": {
                      "message": "Unsupported file type.",
                      "code": "UNSUPPORTED_MIME"
                    }
                  },
                  "FILE_TOO_LARGE": {
                    "value": {
                      "message": "Files are limited to 8 MB.",
                      "code": "FILE_TOO_LARGE"
                    }
                  },
                  "INVALID_DOCUMENT_CATEGORY": {
                    "value": {
                      "message": "A document can only be filed under one of the usta's categories.",
                      "code": "INVALID_DOCUMENT_CATEGORY"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_ROLE_REQUIRED` — This operation is not available to the key's role.\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_ROLE_REQUIRED": {
                    "value": {
                      "message": "This operation is not available to the key's role.",
                      "code": "PARTNER_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found.\n\n- `SHOP_NOT_FOUND` — The usta shop was not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "SHOP_NOT_FOUND": {
                    "value": {
                      "message": "The usta shop was not found.",
                      "code": "SHOP_NOT_FOUND"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "usta",
        "x-ug-scope": "write",
        "x-ug-error-codes": [
          "INVALID_DOC_TYPE",
          "UNSUPPORTED_MIME",
          "FILE_TOO_LARGE",
          "SHOP_NOT_FOUND",
          "INVALID_DOCUMENT_CATEGORY"
        ]
      }
    },
    "/shop/onboarding": {
      "get": {
        "operationId": "getOnboarding",
        "tags": [
          "Usta — Shop"
        ],
        "summary": "Get the onboarding checklist",
        "description": "What the profile still lacks and what each item holds back.\n\n**Access:** usta key · scope `read`",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "checklist": {
                      "description": "The profile checklist: each item says what it holds back (getting jobs, a category, payouts)."
                    },
                    "onboarding": {}
                  },
                  "required": [
                    "checklist",
                    "onboarding"
                  ],
                  "additionalProperties": {}
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_ROLE_REQUIRED` — This operation is not available to the key's role.\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_ROLE_REQUIRED": {
                    "value": {
                      "message": "This operation is not available to the key's role.",
                      "code": "PARTNER_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "usta",
        "x-ug-scope": "read"
      }
    },
    "/shop/onboarding/accept-contract": {
      "post": {
        "operationId": "acceptUstaContract",
        "tags": [
          "Usta — Shop"
        ],
        "summary": "Accept the usta contract",
        "description": "Records the acceptance of the service-provider contract.\n\n**Access:** usta key · scope `write`",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "shop": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        },
                        "is_active": {
                          "description": "`true` once the call center approved; only approved ustas get jobs.",
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "id",
                        "name",
                        "is_active"
                      ],
                      "additionalProperties": {}
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "shop",
                    "message"
                  ],
                  "additionalProperties": {}
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_ROLE_REQUIRED` — This operation is not available to the key's role.\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_ROLE_REQUIRED": {
                    "value": {
                      "message": "This operation is not available to the key's role.",
                      "code": "PARTNER_ROLE_REQUIRED"
                    }
                  },
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found.\n\n- `NOT_FOUND` — Not found, or not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "NOT_FOUND": {
                    "value": {
                      "message": "Not found, or not yours.",
                      "code": "NOT_FOUND"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "usta",
        "x-ug-scope": "write",
        "x-ug-error-codes": [
          "NOT_FOUND"
        ]
      }
    },
    "/tickets": {
      "get": {
        "operationId": "listTickets",
        "tags": [
          "Support"
        ],
        "summary": "List support tickets",
        "description": "The account's support tickets.\n\n**Access:** either role · scope `read`",
        "parameters": [
          {
            "name": "service_request_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tickets": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id"
                        ],
                        "additionalProperties": {}
                      }
                    }
                  },
                  "required": [
                    "tickets"
                  ],
                  "additionalProperties": {}
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.\n\n- `VALIDATION_ERROR` — The request failed validation; see `issues`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "VALIDATION_ERROR": {
                    "value": {
                      "message": "The request failed validation; see `issues`.",
                      "code": "VALIDATION_ERROR"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "any",
        "x-ug-scope": "read"
      },
      "post": {
        "operationId": "createTicket",
        "tags": [
          "Support"
        ],
        "summary": "Open a support ticket",
        "description": "Opens a ticket for the team. To ask for a cancellation use `category: cancel_request` with `service_request_id`.\n\n**Access:** either role · scope `write`",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "subject": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "description": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 5000
                  },
                  "category": {
                    "description": "`cancel_request` asks for a booking's cancellation; the team settles it under the same rules.",
                    "type": "string",
                    "enum": [
                      "dispute",
                      "refund",
                      "quality",
                      "billing",
                      "cancel_request",
                      "general"
                    ]
                  },
                  "service_request_id": {
                    "type": "string"
                  },
                  "photos": {
                    "description": "URLs returned by `POST /uploads/photo` (at most 5). URLs this server did not mint are dropped silently.",
                    "anyOf": [
                      {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      {
                        "type": "string"
                      }
                    ]
                  }
                },
                "required": [
                  "subject",
                  "description"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ticket": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id"
                      ],
                      "additionalProperties": {}
                    }
                  },
                  "required": [
                    "ticket"
                  ],
                  "additionalProperties": {}
                },
                "example": {
                  "ticket": {
                    "id": "01J00000000000000000000000",
                    "ticket_number": "TICK-00000000-0000",
                    "customer_id": "cus_01J00000000000000000000000",
                    "usta_id": null,
                    "order_id": null,
                    "service_request_id": "01J00000000000000000000000",
                    "escrow_id": null,
                    "extra_work_id": null,
                    "verdict": null,
                    "category": "cancel_request",
                    "status": "open",
                    "priority": "medium",
                    "subject": "Randevu",
                    "description": "Saati değiştirmek istiyorum.",
                    "resolution": null,
                    "assigned_to": null,
                    "sla_due_at": "2026-10-01T09:00:00.000Z",
                    "resolved_at": null,
                    "metadata": null,
                    "created_at": "2026-10-01T09:00:00.000Z",
                    "updated_at": "2026-10-01T09:00:00.000Z",
                    "deleted_at": null
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.\n\n- `VALIDATION_ERROR` — The request failed validation; see `issues`.\n- `INVALID_CATEGORY` — Invalid support category.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "VALIDATION_ERROR": {
                    "value": {
                      "message": "The request failed validation; see `issues`.",
                      "code": "VALIDATION_ERROR"
                    }
                  },
                  "INVALID_CATEGORY": {
                    "value": {
                      "message": "Invalid support category.",
                      "code": "INVALID_CATEGORY"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "any",
        "x-ug-scope": "write",
        "x-ug-error-codes": [
          "INVALID_CATEGORY"
        ]
      }
    },
    "/tickets/{id}": {
      "get": {
        "operationId": "getTicket",
        "tags": [
          "Support"
        ],
        "summary": "Get a support ticket",
        "description": "One support ticket.\n\n**Access:** either role · scope `read`",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The record's id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ticket": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id"
                      ],
                      "additionalProperties": {}
                    }
                  },
                  "required": [
                    "ticket"
                  ],
                  "additionalProperties": {}
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found.\n\n- `NOT_FOUND` — Not found, or not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "NOT_FOUND": {
                    "value": {
                      "message": "Not found, or not yours.",
                      "code": "NOT_FOUND"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "any",
        "x-ug-scope": "read"
      }
    },
    "/uploads/photo": {
      "post": {
        "operationId": "uploadPhoto",
        "tags": [
          "Account"
        ],
        "summary": "Upload a photo",
        "description": "Uploads a base64 photo and returns its URL. Booking photos, question answers, chat images and completion evidence accept only URLs returned here. At most 8 MB; uploads are rate-limited.\n\n**Access:** either role · scope `write`",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "content": {
                    "description": "Base64 file content (a `data:…;base64,` prefix is allowed), at most 8 MB.",
                    "type": "string",
                    "minLength": 1
                  },
                  "file_name": {
                    "type": "string"
                  },
                  "mime_type": {
                    "description": "Defaults to `image/jpeg`.",
                    "type": "string",
                    "enum": [
                      "image/jpeg",
                      "image/png",
                      "image/heic",
                      "image/webp"
                    ]
                  }
                },
                "required": [
                  "content"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "file": {
                      "type": "object",
                      "properties": {
                        "url": {
                          "description": "The URL to use in booking, answer, chat and completion photos.",
                          "type": "string"
                        },
                        "file_name": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "mime_type": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "url",
                        "file_name",
                        "mime_type"
                      ],
                      "additionalProperties": {}
                    }
                  },
                  "required": [
                    "file"
                  ],
                  "additionalProperties": {}
                },
                "example": {
                  "file": {
                    "url": "https://api.example.com/static/shared/private-1790000000000-ug-cus_01J00000000000000000000000-1790000000000.png",
                    "file_name": null,
                    "mime_type": "image/png"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.\n\n- `VALIDATION_ERROR` — The request failed validation; see `issues`.\n- `UNSUPPORTED_MIME` — Unsupported file type.\n- `FILE_TOO_LARGE` — Files are limited to 8 MB.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "VALIDATION_ERROR": {
                    "value": {
                      "message": "The request failed validation; see `issues`.",
                      "code": "VALIDATION_ERROR"
                    }
                  },
                  "UNSUPPORTED_MIME": {
                    "value": {
                      "message": "Unsupported file type.",
                      "code": "UNSUPPORTED_MIME"
                    }
                  },
                  "FILE_TOO_LARGE": {
                    "value": {
                      "message": "Files are limited to 8 MB.",
                      "code": "FILE_TOO_LARGE"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or expired key.\n\n- `PARTNER_KEY_INVALID` — The API key is invalid, revoked or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_KEY_INVALID": {
                    "value": {
                      "message": "The API key is invalid, revoked or expired.",
                      "code": "PARTNER_KEY_INVALID"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key's role or scope does not allow this operation.\n\n- `PARTNER_SCOPE_REQUIRED` — The key lacks the scope this operation needs.\n- `PARTNER_ROLE_UNAVAILABLE` — The account no longer holds the key's role.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "PARTNER_SCOPE_REQUIRED": {
                    "value": {
                      "message": "The key lacks the scope this operation needs.",
                      "code": "PARTNER_SCOPE_REQUIRED"
                    }
                  },
                  "PARTNER_ROLE_UNAVAILABLE": {
                    "value": {
                      "message": "The account no longer holds the key's role.",
                      "code": "PARTNER_ROLE_UNAVAILABLE"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.\n\n- `RATE_LIMITED` — Rate limit reached; wait for `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "RATE_LIMITED": {
                    "value": {
                      "message": "Rate limit reached; wait for `Retry-After`.",
                      "code": "RATE_LIMITED"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected error.\n\n- `INTERNAL_ERROR` — An unexpected error occurred.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "INTERNAL_ERROR": {
                    "value": {
                      "message": "An unexpected error occurred.",
                      "code": "INTERNAL_ERROR"
                    }
                  }
                }
              }
            }
          }
        },
        "x-ug-role": "any",
        "x-ug-scope": "write",
        "x-ug-error-codes": [
          "UNSUPPORTED_MIME",
          "FILE_TOO_LARGE"
        ]
      }
    },
    "/openapi.json": {
      "get": {
        "operationId": "getOpenApi",
        "tags": [
          "Meta"
        ],
        "summary": "Get the API description",
        "description": "This document itself (OpenAPI 3.1). `lang=tr|en` picks the language of the descriptions. No key required.\n\n**Access:** public, no key required.",
        "parameters": [
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "Description language.",
            "schema": {
              "type": "string",
              "enum": [
                "tr",
                "en"
              ],
              "default": "tr"
            }
          }
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "OpenAPI document.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        },
        "x-ug-role": "any",
        "x-ug-scope": null
      }
    }
  },
  "components": {
    "securitySchemes": {
      "PartnerKey": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "ugp_<64 hex>",
        "description": "A partner key issued by the operations team: `Authorization: Bearer ugp_…`."
      }
    },
    "schemas": {
      "ErrorResponse": {
        "description": "The body of every non-2xx response.",
        "type": "object",
        "properties": {
          "message": {
            "description": "Human-readable text. Store handler messages are Turkish; the partner layer's own messages follow `Accept-Language: en`.",
            "type": "string"
          },
          "code": {
            "description": "Stable, machine-readable error code. Branch on this, never on the message.",
            "type": "string"
          },
          "issues": {
            "description": "VALIDATION_ERROR only: which field failed and why.",
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "path": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                },
                "code": {
                  "type": "string"
                }
              },
              "required": [
                "path",
                "message",
                "code"
              ],
              "additionalProperties": false
            }
          }
        },
        "required": [
          "message",
          "code"
        ],
        "additionalProperties": {}
      },
      "ErrorCode": {
        "type": "string",
        "description": "Every error code this API can return.",
        "enum": [
          "ADDRESS_REQUIRED",
          "ALREADY_TAKEN",
          "AMOUNT_NOT_LOWER",
          "AMOUNT_NOT_SET",
          "APPOINTMENT_REQUIRED",
          "AREA_NOT_COVERED",
          "AUTH_METHOD_DISABLED",
          "BAD_REQUEST",
          "BANK_TRANSFER_UNCONFIGURED",
          "BOOKING_NOT_PAID",
          "CANCEL_NOT_ALLOWED",
          "CARD_INVALID",
          "CATEGORY_DOCUMENTS_REQUIRED",
          "CATEGORY_NOT_COVERED",
          "CITY_NOT_COVERED",
          "CODE_EXPIRED",
          "CODE_INVALID",
          "CONFLICT",
          "CUSTOMER_METADATA_NOT_WRITABLE",
          "DATE_AND_SLOT",
          "DISPUTE_ALREADY_CONFIRMED",
          "DISPUTE_ALREADY_DISPUTED",
          "DISPUTE_NOT_HELD",
          "DISPUTE_REFUND_PENDING",
          "DISPUTE_STATEMENT_INVALID",
          "DISPUTE_TOO_EARLY",
          "DUPLICATE",
          "EMAIL_ALREADY_IN_USE",
          "EMAIL_CODE_COOLDOWN",
          "EMAIL_SEND_FAILED",
          "EMPTY_CART",
          "EMPTY_ITEMS",
          "ESCROW_DISPUTED",
          "ESCROW_EXISTS",
          "ESCROW_NOT_PAYABLE",
          "ESCROW_NOT_REFUNDABLE",
          "ESCROW_RELEASE_REQUIRES_REQUEST_CONFIRMATION",
          "EXTRA_WORK_PENDING",
          "FILE_TOO_LARGE",
          "FIXED_PRICE_PATH",
          "FORBIDDEN",
          "GROUP_NOT_ALLOWED",
          "GROUP_PAYMENT_CARRIER_ONLY",
          "GUEST_LIMIT",
          "HANDOFF_INVALID",
          "HOSTED_PAYMENT_UNAVAILABLE",
          "IBAN_HOLDER_MISMATCH",
          "IBAN_HOLDER_REQUIRED",
          "INTERNAL_ERROR",
          "INVALID_BIRTH_DATE",
          "INVALID_BUSINESS_PROFILE",
          "INVALID_CATEGORY",
          "INVALID_COMPLETION",
          "INVALID_COORDINATES",
          "INVALID_DATA",
          "INVALID_DATE",
          "INVALID_DOCUMENT_CATEGORY",
          "INVALID_DOC_TYPE",
          "INVALID_EMAIL",
          "INVALID_IBAN",
          "INVALID_JOB_STATUS",
          "INVALID_LINE_ITEMS",
          "INVALID_PHONE",
          "INVALID_REASON_CODE",
          "INVALID_SERVICE_ANSWER",
          "INVALID_SERVICE_ITEM",
          "INVALID_STATEMENT",
          "INVALID_STATUS",
          "INVALID_TC",
          "IN_PROGRESS",
          "JOB_ALREADY_CONFIRMED",
          "LEGAL_VERSION_CHANGED",
          "LOCATION_NOT_FOUND",
          "LOCATION_REQUIRED",
          "METHOD_NOT_ALLOWED",
          "MISSING_FIELDS",
          "MISSING_PERMISSION",
          "NAME_CHANGE_NOT_ALLOWED",
          "NOTHING_TO_UPDATE",
          "NOT_ALLOWED",
          "NOT_ASSIGNED",
          "NOT_AVAILABLE_AT_SLOT",
          "NOT_FOUND",
          "NOT_LIVE",
          "NOT_YOUR_JOB",
          "NOT_YOUR_REQUEST",
          "NO_PENDING_EMAIL",
          "NO_PENDING_RESCHEDULE",
          "NO_REGION",
          "NO_USTA_ASSIGNED",
          "OUTSIDE_SERVICE_AREA",
          "OWN_REQUEST",
          "PARTNER_KEY_INVALID",
          "PARTNER_ROLE_REQUIRED",
          "PARTNER_ROLE_UNAVAILABLE",
          "PARTNER_SCOPE_REQUIRED",
          "PAYLOAD_TOO_LARGE",
          "PAYMENT_AUTHORIZATION_ERROR",
          "PAYMENT_DECLINED",
          "PAYMENT_FAILED",
          "PAYMENT_GATEWAY_UNCONFIGURED",
          "PAYMENT_GATEWAY_UNREACHABLE",
          "PAYOUT_DETAILS_REQUIRED",
          "PENDING_ADMIN_APPROVAL",
          "PHONE_CHANGE_NOT_ALLOWED",
          "PHOTOS_LOCKED",
          "PRICE_OUT_OF_RANGE",
          "PRODUCT_NOT_FOUND",
          "QUOTE_CREATE_FAILED",
          "RATE_LIMITED",
          "REASON_TOO_SHORT",
          "REFUND_ALREADY_REQUESTED",
          "REFUND_AMOUNT_INVALID",
          "REFUND_BANK_REJECTED",
          "REFUND_BANK_UNREACHABLE",
          "REFUND_BANK_UNSUPPORTED",
          "REFUND_GATEWAY_UNAVAILABLE",
          "REFUND_GATEWAY_UNCONFIGURED",
          "REFUND_IN_PROGRESS",
          "REFUND_NO_PENDING_REQUEST",
          "REFUND_REASON_REQUIRED",
          "REFUND_REFERENCE_REQUIRED",
          "REFUND_REQUEST_PENDING",
          "REQUEST_NOT_FOUND",
          "REVERSE_GEOCODE_UNAVAILABLE",
          "REVERSE_GEOCODE_UNCONFIGURED",
          "SERVICE_AREA_NOT_COVERED",
          "SERVICE_CATEGORIES_REQUIRED",
          "SERVICE_UNAVAILABLE",
          "SESSION_EXPIRED",
          "SESSION_REVOKED",
          "SHOP_NOT_FOUND",
          "SLOT_CONFLICT",
          "STORE_METADATA_NOT_WRITABLE",
          "TOO_MANY_ATTEMPTS",
          "TOO_MANY_PAYMENT_ATTEMPTS",
          "TOO_MANY_REQUESTS",
          "UNAUTHORIZED",
          "UNEXPECTED_STATE",
          "UNPROCESSABLE",
          "UNSUPPORTED_FILE_URL",
          "UNSUPPORTED_MIME",
          "UPSTREAM_ERROR",
          "USTA_NOT_ACTIVE",
          "USTA_NOT_APPROVED",
          "USTA_PROFILE_REQUIRED",
          "USTA_ROLE_REQUIRED",
          "VALIDATION_ERROR",
          "VISIT_CODE_INVALID",
          "VISIT_CODE_NOT_ISSUED",
          "VISIT_CODE_REQUIRED",
          "WELCOME_PACKAGE_NOT_EARNED"
        ]
      }
    }
  }
}
