{"openapi":"3.0.3","info":{"title":"Playfood Partner API","version":"1.0.0","description":"Taxi and courier rides from point A to point B for partner developers: price, booking, tracking, cancellation. Paid in cash to the driver at the usual tariff. Human-readable guide: /partner/docs"},"servers":[{"url":"https://api.playfood.pro/partner/v1"}],"security":[{"bearer":[]},{"apiKey":[]}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","description":"Authorization: Bearer pf_live_..."},"apiKey":{"type":"apiKey","in":"header","name":"X-Api-Key"}},"schemas":{"Point":{"type":"object","required":["lat","lng"],"properties":{"lat":{"type":"number","example":42.517},"lng":{"type":"number","example":69.786},"address":{"type":"string","example":"ул. Толе би, 12"}}},"Error":{"type":"object","properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","example":"invalid_route"},"message":{"type":"string"},"fields":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}}}},"Order":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"number":{"type":"string","example":"97574"},"external_id":{"type":"string","nullable":true},"service":{"type":"string","enum":["taxi","courier"]},"status":{"type":"string","enum":["searching","driver_assigned","driver_arrived","in_progress","completed","cancelled"]},"tariff":{"type":"object","nullable":true,"properties":{"id":{"type":"integer"},"name":{"type":"string"}}},"price":{"type":"object","properties":{"amount":{"type":"integer","example":800},"currency":{"type":"string","example":"KZT"},"final":{"type":"boolean"},"payment_method":{"type":"string","enum":["cash"]}}},"route":{"type":"array","items":{"$ref":"#/components/schemas/Point"}},"distance_km":{"type":"number","nullable":true},"duration_min":{"type":"integer","nullable":true},"contact":{"type":"object","properties":{"name":{"type":"string"},"phone":{"type":"string"}}},"recipient":{"type":"object","nullable":true,"properties":{"name":{"type":"string"},"phone":{"type":"string"}}},"performer":{"type":"object","nullable":true,"properties":{"name":{"type":"string"},"phone":{"type":"string"},"rating":{"type":"number","nullable":true},"photo_url":{"type":"string","nullable":true},"car":{"type":"object","properties":{"brand":{"type":"string"},"model":{"type":"string"},"color":{"type":"string"},"plate":{"type":"string"}}}}},"location":{"type":"object","nullable":true,"properties":{"lat":{"type":"number"},"lng":{"type":"number"},"heading":{"type":"number","nullable":true},"updated_at":{"type":"string","format":"date-time"}}},"eta_minutes":{"type":"integer","nullable":true,"description":"Minutes to point A while the driver is on the way; to point B during the ride."},"can_cancel":{"type":"boolean"},"cancellation":{"type":"object","nullable":true,"properties":{"by":{"type":"string","enum":["partner","client","driver","operator","system"]},"reason":{"type":"string","nullable":true}}},"created_at":{"type":"string","format":"date-time"},"arrived_at":{"type":"string","format":"date-time","nullable":true},"started_at":{"type":"string","format":"date-time","nullable":true},"completed_at":{"type":"string","format":"date-time","nullable":true},"cancelled_at":{"type":"string","format":"date-time","nullable":true},"updated_at":{"type":"string","format":"date-time"}}},"Offer":{"type":"object","properties":{"offer_id":{"type":"string","format":"uuid"},"tariff":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"}}},"price":{"type":"integer","example":800},"currency":{"type":"string","example":"KZT"},"distance_km":{"type":"number"},"duration_min":{"type":"integer"},"surge":{"type":"number","example":1},"expires_at":{"type":"string","format":"date-time"}}}},"responses":{"Unauthorized":{"description":"Missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Invalid":{"description":"Validation failed or the request cannot be served","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Too many requests; see Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"No such order for your API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/tariffs":{"get":{"summary":"Tariffs of a service bookable at a point","operationId":"listTariffs","parameters":[{"name":"service","in":"query","required":true,"schema":{"type":"string","enum":["taxi","courier"]}},{"name":"lat","in":"query","required":true,"schema":{"type":"number"}},{"name":"lng","in":"query","required":true,"schema":{"type":"number"}}],"responses":{"200":{"description":"Tariffs","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"service":{"type":"string","enum":["taxi","courier"]},"currency":{"type":"string"},"pickup_fee":{"type":"number"},"price_per_km":{"type":"number"},"min_fare":{"type":"number"},"is_night":{"type":"boolean"}}}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"422":{"$ref":"#/components/responses/Invalid"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/price":{"post":{"summary":"Price of a ride A → B","operationId":"getPrice","description":"Returns one offer per tariff (or only tariff_id). Pass offer_id to POST /orders within 10 minutes to book at that price.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["service","route"],"properties":{"service":{"type":"string","enum":["taxi","courier"]},"tariff_id":{"type":"integer"},"route":{"type":"array","minItems":2,"maxItems":2,"description":"Exactly two points: A (pickup) and B (drop-off).","items":{"$ref":"#/components/schemas/Point"}}}}}}},"responses":{"200":{"description":"Offers","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Offer"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"422":{"$ref":"#/components/responses/Invalid"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/orders":{"get":{"summary":"Your latest orders","operationId":"listOrders","parameters":[{"name":"external_id","in":"query","schema":{"type":"string"}},{"name":"status","in":"query","schema":{"type":"string","enum":["active","completed","cancelled"]}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}}],"responses":{"200":{"description":"Orders","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Order"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"422":{"$ref":"#/components/responses/Invalid"},"429":{"$ref":"#/components/responses/RateLimited"}}},"post":{"summary":"Book a ride A → B","operationId":"createOrder","parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","maxLength":64},"description":"Unique per new order. Repeating it returns the same order (200, Idempotent-Replayed: true)."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["service","route","contact"],"properties":{"service":{"type":"string","enum":["taxi","courier"]},"tariff_id":{"type":"integer","description":"Default: the first tariff of the service at point A."},"offer_id":{"type":"string","description":"From POST /price; books at the quoted price."},"route":{"type":"array","minItems":2,"maxItems":2,"description":"Exactly two points: A (pickup) and B (drop-off).","items":{"$ref":"#/components/schemas/Point"}},"contact":{"type":"object","required":["phone"],"description":"The passenger (taxi) or the sender at point A (courier). The driver calls this number.","properties":{"name":{"type":"string"},"phone":{"type":"string","example":"+77001234567"}}},"recipient":{"type":"object","description":"Courier: who receives at point B.","properties":{"name":{"type":"string"},"phone":{"type":"string"}}},"comment":{"type":"string","maxLength":500},"external_id":{"type":"string","maxLength":100,"description":"Your own order id."}}}}}},"responses":{"201":{"description":"Booked","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Order"}}}}}},"200":{"description":"Already booked with this Idempotency-Key","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Order"}}}}}},"403":{"description":"The service is not enabled for your key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Too many cancellations for this phone","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"422":{"$ref":"#/components/responses/Invalid"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/orders/{id}":{"get":{"summary":"Order status, performer, car, location, ETA","operationId":"getOrder","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Order","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Order"}}}}}},"404":{"$ref":"#/components/responses/NotFound"},"401":{"$ref":"#/components/responses/Unauthorized"},"422":{"$ref":"#/components/responses/Invalid"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/orders/{id}/cancel":{"post":{"summary":"Cancel before the ride starts","operationId":"cancelOrder","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string","maxLength":200}}}}}},"responses":{"200":{"description":"Cancelled","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Order"}}}}}},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"The ride has started or finished","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"422":{"$ref":"#/components/responses/Invalid"},"429":{"$ref":"#/components/responses/RateLimited"}}}}}}