{"components":{"schemas":{"ApiKeyEnvironment":{"enum":["LIVE","SANDBOX"],"type":"string"},"ApiKeyScope":{"enum":["orders:read","orders:pii","logistics:write","webhooks:manage","payments:read"],"type":"string"},"CreateDeveloperKeyDto":{"properties":{"environment":{"allOf":[{"$ref":"#/components/schemas/ApiKeyEnvironment"}]},"name":{"example":"Production integration","maxLength":60,"minLength":2,"type":"string"},"scopes":{"description":"At least one scope; `orders:pii` unlocks the customer block on partner orders.","example":["orders:read","logistics:write"],"items":{"$ref":"#/components/schemas/ApiKeyScope"},"type":"array"}},"required":["name","environment","scopes"],"type":"object"},"CreateDeveloperWebhookDto":{"properties":{"apiKeyId":{"description":"The API key this webhook belongs to","format":"uuid","type":"string"},"events":{"example":["order.status_changed"],"items":{"$ref":"#/components/schemas/WebhookEvent"},"type":"array"},"url":{"description":"HTTPS only (http:// is accepted for localhost outside production).","example":"https://partner.example.az/esadarak/events","type":"string"}},"required":["apiKeyId","url","events"],"type":"object"},"CreatePartnerOrderEventDto":{"properties":{"at":{"description":"When it happened at the partner. Informational — the event row is stamped now.","format":"date-time","type":"string"},"codCollectedQepik":{"description":"Cash collected at the door in qəpik (DELIVERED, COD orders). Never above the order COD amount.","maximum":100000000,"minimum":0,"type":"integer"},"failReason":{"allOf":[{"$ref":"#/components/schemas/DeliveryFailReason"}]},"note":{"maxLength":500,"type":"string"},"type":{"allOf":[{"$ref":"#/components/schemas/PartnerEventType"}],"description":"PICKED_UP (goods collected from the hub) · EN_ROUTE · DELIVERED · FAILED. Each maps to an OrderStateMachine transition with the PARTNER actor."}},"required":["type"],"type":"object"},"DeliveryFailReason":{"enum":["NOT_HOME","REFUSED","WRONG_ADDRESS","UNREACHABLE","OTHER"],"type":"string"},"DeveloperDelivery":{"properties":{"attempts":{"example":1,"type":"number"},"createdAt":{"format":"date-time","type":"string"},"deliveredAt":{"format":"date-time","nullable":true,"type":"string"},"event":{"example":"order.delivered","type":"string"},"id":{"format":"uuid","type":"string"},"lastError":{"example":"HTTP 503","nullable":true,"type":"string"},"nextAttemptAt":{"format":"date-time","nullable":true,"type":"string"},"status":{"allOf":[{"$ref":"#/components/schemas/WebhookDeliveryStatus"}]},"statusCode":{"example":200,"nullable":true,"type":"number"},"webhookId":{"format":"uuid","type":"string"}},"required":["id","webhookId","event","status","attempts","statusCode","lastError","createdAt","deliveredAt","nextAttemptAt"],"type":"object"},"DeveloperKey":{"properties":{"createdAt":{"format":"date-time","type":"string"},"environment":{"allOf":[{"$ref":"#/components/schemas/ApiKeyEnvironment"}]},"id":{"format":"uuid","type":"string"},"isActive":{"example":true,"type":"boolean"},"lastUsedAt":{"format":"date-time","nullable":true,"type":"string"},"name":{"example":"Production integration","type":"string"},"prefix":{"description":"The only part of the key that is stored","example":"esk_live_ab12","type":"string"},"rateLimit":{"description":"Requests per minute","example":600,"type":"number"},"receivesAllOrders":{"example":false,"type":"boolean"},"revokedAt":{"description":"When the key stops working — a rotation sets it 24 h out, a revoke sets it now","format":"date-time","nullable":true,"type":"string"},"scopes":{"example":["orders:read","logistics:write"],"items":{"$ref":"#/components/schemas/ApiKeyScope"},"type":"array"}},"required":["id","name","prefix","environment","scopes","rateLimit","receivesAllOrders","isActive","lastUsedAt","revokedAt","createdAt"],"type":"object"},"DeveloperKeyCreated":{"properties":{"createdAt":{"format":"date-time","type":"string"},"environment":{"allOf":[{"$ref":"#/components/schemas/ApiKeyEnvironment"}]},"id":{"format":"uuid","type":"string"},"isActive":{"example":true,"type":"boolean"},"key":{"description":"THE ONLY TIME the key is shown. Store it now — only its sha256 hash is kept.","example":"esk_live_9f2c1a7be40d5836a1c9e0b47d3f6a21","type":"string"},"lastUsedAt":{"format":"date-time","nullable":true,"type":"string"},"name":{"example":"Production integration","type":"string"},"prefix":{"description":"The only part of the key that is stored","example":"esk_live_ab12","type":"string"},"rateLimit":{"description":"Requests per minute","example":600,"type":"number"},"receivesAllOrders":{"example":false,"type":"boolean"},"revokedAt":{"description":"When the key stops working — a rotation sets it 24 h out, a revoke sets it now","format":"date-time","nullable":true,"type":"string"},"scopes":{"example":["orders:read","logistics:write"],"items":{"$ref":"#/components/schemas/ApiKeyScope"},"type":"array"}},"required":["id","name","prefix","environment","scopes","rateLimit","receivesAllOrders","isActive","lastUsedAt","revokedAt","createdAt","key"],"type":"object"},"DeveloperKeyRotated":{"properties":{"createdAt":{"format":"date-time","type":"string"},"environment":{"allOf":[{"$ref":"#/components/schemas/ApiKeyEnvironment"}]},"id":{"format":"uuid","type":"string"},"isActive":{"example":true,"type":"boolean"},"key":{"description":"THE ONLY TIME the key is shown. Store it now — only its sha256 hash is kept.","example":"esk_live_9f2c1a7be40d5836a1c9e0b47d3f6a21","type":"string"},"lastUsedAt":{"format":"date-time","nullable":true,"type":"string"},"movedOrders":{"description":"Orders that were assigned to the old key and now belong to the new one — rotation carries the identity, not just the secret","example":3,"type":"number"},"movedWebhooks":{"description":"Webhooks moved from the old key to the new one","example":1,"type":"number"},"name":{"example":"Production integration","type":"string"},"prefix":{"description":"The only part of the key that is stored","example":"esk_live_ab12","type":"string"},"previousKeyId":{"description":"The key that was rotated out","format":"uuid","type":"string"},"previousKeyRevokedAt":{"description":"The old key keeps working until this instant (24 h grace)","format":"date-time","type":"string"},"rateLimit":{"description":"Requests per minute","example":600,"type":"number"},"receivesAllOrders":{"example":false,"type":"boolean"},"revokedAt":{"description":"When the key stops working — a rotation sets it 24 h out, a revoke sets it now","format":"date-time","nullable":true,"type":"string"},"scopes":{"example":["orders:read","logistics:write"],"items":{"$ref":"#/components/schemas/ApiKeyScope"},"type":"array"}},"required":["id","name","prefix","environment","scopes","rateLimit","receivesAllOrders","isActive","lastUsedAt","revokedAt","createdAt","key","previousKeyId","previousKeyRevokedAt","movedOrders","movedWebhooks"],"type":"object"},"DeveloperKeyUsage":{"properties":{"clientErrors":{"example":3,"type":"number"},"day":{"example":"2026-08-27","type":"string"},"requests":{"example":1284,"type":"number"},"serverErrors":{"example":0,"type":"number"}},"required":["day","requests","clientErrors","serverErrors"],"type":"object"},"DeveloperKeyUsageSeries":{"properties":{"apiKeyId":{"format":"uuid","type":"string"},"days":{"example":7,"type":"number"},"items":{"description":"Oldest first","items":{"$ref":"#/components/schemas/DeveloperKeyUsage"},"type":"array"},"totalRequests":{"example":8901,"type":"number"}},"required":["apiKeyId","days","items","totalRequests"],"type":"object"},"DeveloperKeys":{"properties":{"items":{"items":{"$ref":"#/components/schemas/DeveloperKey"},"type":"array"}},"required":["items"],"type":"object"},"DeveloperWebhook":{"properties":{"apiKeyId":{"format":"uuid","type":"string"},"consecutiveFailures":{"example":0,"type":"number"},"createdAt":{"format":"date-time","type":"string"},"events":{"example":["order.delivered"],"items":{"$ref":"#/components/schemas/WebhookEvent"},"type":"array"},"id":{"format":"uuid","type":"string"},"isActive":{"description":"Auto-disabled after 50 consecutive dead deliveries","example":true,"type":"boolean"},"url":{"example":"https://partner.example.az/esadarak/events","type":"string"}},"required":["id","apiKeyId","url","events","isActive","consecutiveFailures","createdAt"],"type":"object"},"DeveloperWebhookCreated":{"properties":{"apiKeyId":{"format":"uuid","type":"string"},"consecutiveFailures":{"example":0,"type":"number"},"createdAt":{"format":"date-time","type":"string"},"events":{"example":["order.delivered"],"items":{"$ref":"#/components/schemas/WebhookEvent"},"type":"array"},"id":{"format":"uuid","type":"string"},"isActive":{"description":"Auto-disabled after 50 consecutive dead deliveries","example":true,"type":"boolean"},"secret":{"description":"THE ONLY TIME the signing secret is shown. Verify `X-Esadarak-Signature: t=<unix>,v1=<hex>` as HMAC-SHA256 of `\"<t>.<rawBody>\"` with it.","example":"whsec_4f1c8a2e9b7d3056a1c9e0b47d3f6a21","type":"string"},"url":{"example":"https://partner.example.az/esadarak/events","type":"string"}},"required":["id","apiKeyId","url","events","isActive","consecutiveFailures","createdAt","secret"],"type":"object"},"DeveloperWebhooks":{"properties":{"items":{"items":{"$ref":"#/components/schemas/DeveloperWebhook"},"type":"array"}},"required":["items"],"type":"object"},"ErrorCode":{"description":"Machine-readable error code. Clients map it to a localised string.","enum":["ERR_VALIDATION","ERR_BAD_REQUEST","ERR_UNAUTHORIZED","ERR_FORBIDDEN","ERR_NOT_FOUND","ERR_CONFLICT","ERR_RATE_LIMITED","ERR_INTERNAL","ERR_DEPENDENCY_UNAVAILABLE","ERR_OTP_INVALID","ERR_OTP_EXPIRED","ERR_OTP_RATE_LIMITED","ERR_OTP_TOO_MANY_ATTEMPTS","ERR_NO_DEFAULT_ADDRESS","ERR_OUT_OF_STOCK","ERR_PRODUCT_UNAVAILABLE","ERR_OUT_OF_ZONE","ERR_PAYMENT_METHOD_UNAVAILABLE","ERR_ORDER_NOT_CANCELLABLE","ERR_ORDER_NOT_RATABLE","ERR_ALREADY_RATED","ERR_INVALID_TRANSITION","ERR_IDEMPOTENCY_KEY_REQUIRED","ERR_IDEMPOTENCY_CONFLICT","ERR_VENDOR_NOT_FOUND","ERR_ORDER_NOT_ACCEPTABLE","ERR_ITEMS_ALREADY_DECIDED","ERR_PRODUCT_NOT_OWNED","ERR_CATEGORY_INVALID","ERR_SKU_CONFLICT","ERR_MEDIA_UNAVAILABLE","ERR_MEDIA_INVALID","ERR_ORDER_ALREADY_CLAIMED","ERR_ORDER_NOT_CLAIMED","ERR_PICKUP_INCOMPLETE","ERR_ITEM_NOT_PICKABLE","ERR_DRIVER_NOT_FOUND","ERR_DRIVER_OFFLINE","ERR_DRIVER_BUSY","ERR_BATCH_NOT_OFFERED","ERR_OFFER_EXPIRED","ERR_BATCH_NOT_ASSIGNED","ERR_SCAN_INCOMPLETE","ERR_SCAN_WRONG_BATCH","ERR_STOP_ALREADY_RESOLVED","ERR_BATCH_INCOMPLETE","ERR_COD_VARIANCE_NOTE_REQUIRED","ERR_BATCH_INVALID_TRANSITION","ERR_ROUTE_UNAVAILABLE","ERR_DELIVERY_RETRY_LIMIT","ERR_USER_BLOCKED","ERR_CATEGORY_NOT_EMPTY","ERR_CATEGORY_CYCLE","ERR_ZONE_INVALID_POLYGON","ERR_SETTLEMENT_EXISTS","ERR_SETTLEMENT_INVALID_STATE","ERR_SETTLEMENT_PERIOD_OPEN","ERR_STAFF_PHONE_EXISTS","ERR_SETTING_UNKNOWN","ERR_SETTING_INVALID","ERR_TICKET_CLOSED","ERR_TICKET_NOT_ASSIGNABLE","ERR_CSAT_NOT_ALLOWED","ERR_CSAT_ALREADY_GIVEN","ERR_REFUND_AMOUNT_EXCEEDS","ERR_REFUND_INVALID_STATE","ERR_REFUND_ORDER_NOT_ELIGIBLE","ERR_RETURN_NOT_ELIGIBLE","ERR_PAYMENT_PROVIDER_UNAVAILABLE","ERR_PAYMENT_INTENT_INVALID_STATE","ERR_PAYMENT_SIGNATURE_INVALID","ERR_PAYMENT_ALREADY_PAID","ERR_API_KEY_INVALID","ERR_API_KEY_REVOKED","ERR_API_KEY_SCOPE","ERR_API_KEY_ENVIRONMENT","ERR_API_KEY_LIMIT","ERR_WEBHOOK_URL_INVALID","ERR_WEBHOOK_LIMIT","ERR_WEBHOOK_DISABLED","ERR_PARTNER_ORDER_NOT_ASSIGNED","ERR_PHONE_REQUIRED","ERR_CONTACT_TAKEN","ERR_CHANNEL_DISABLED","ERR_ITEM_NOT_EXPECTED","ERR_INTAKE_INCOMPLETE","ERR_PARCEL_NOT_IN_BATCH","ERR_ORDER_NOT_PACKABLE","ERR_WRONG_STOP_PARCEL","ERR_PARCEL_NOT_LOADED","ERR_OUTSIDE_GEOFENCE","ERR_DELIVERY_SCAN_INCOMPLETE","ERR_LOCATION_REQUIRED","ERR_COUPON_INVALID","ERR_COUPON_CODE_TAKEN","ERR_LOYALTY_INSUFFICIENT"],"type":"string"},"ErrorResponseDto":{"properties":{"code":{"allOf":[{"$ref":"#/components/schemas/ErrorCode"}],"description":"Machine-readable error code. Clients map it to a localised string.","example":"ERR_VALIDATION"},"details":{"description":"Extra context: an object (e.g. { retryAfterSec } for ERR_OTP_RATE_LIMITED) or an array (e.g. [{ field, messages[] }] for ERR_VALIDATION). Shape depends on `code`.","example":[{"field":"phone","messages":["phone must be an Azerbaijani number"]}],"oneOf":[{"additionalProperties":true,"type":"object"},{"items":{},"type":"array"}]},"message":{"description":"Developer-facing English message. Never show it to end users.","example":"Validation failed","type":"string"},"statusCode":{"description":"HTTP status code (duplicated in the body)","example":400,"type":"number"}},"required":["statusCode","code","message"],"type":"object"},"LocalizedText":{"properties":{"az":{"example":"Kişi köynəyi — Qara","type":"string"},"en":{"example":"Men's shirt — Black","type":"string"},"ru":{"example":"Мужская рубашка — Чёрный","type":"string"}},"required":["az","ru","en"],"type":"object"},"OrderPaymentStatus":{"description":"A COD order stays UNPAID; a CARD order is PAID once its intent is captured","enum":["UNPAID","PAID","REFUNDED","PARTIALLY_REFUNDED"],"type":"string"},"OrderStatus":{"enum":["PLACED","VENDOR_ACCEPTED","RUNNER_PICKUP","AT_HUB","PACKED","SCANNED_TO_VAN","EN_ROUTE","DELIVERED","FAILED","RETURNED","CANCELLED"],"type":"string"},"PageOfDeveloperDelivery":{"properties":{"items":{"items":{"$ref":"#/components/schemas/DeveloperDelivery"},"type":"array"},"page":{"example":1,"maximum":10000,"minimum":1,"type":"number"},"pageSize":{"example":20,"maximum":50,"minimum":1,"type":"number"},"total":{"description":"Total matching rows","example":137,"type":"number"}},"required":["page","pageSize","total","items"],"type":"object"},"PageOfPartnerOrder":{"properties":{"items":{"items":{"$ref":"#/components/schemas/PartnerOrder"},"type":"array"},"page":{"example":1,"maximum":10000,"minimum":1,"type":"number"},"pageSize":{"example":20,"maximum":50,"minimum":1,"type":"number"},"total":{"description":"Total matching rows","example":137,"type":"number"}},"required":["page","pageSize","total","items"],"type":"object"},"PartnerBatchRef":{"properties":{"code":{"example":"B-2081","type":"string"},"status":{"example":"EN_ROUTE","type":"string"}},"required":["code","status"],"type":"object"},"PartnerCustomer":{"properties":{"address":{"$ref":"#/components/schemas/PartnerCustomerAddress"},"name":{"example":"Aysel Məmmədova","nullable":true,"type":"string"},"phone":{"description":"phone ?? contactPhone — null when the account has neither","example":"+994501234567","nullable":true,"type":"string"}},"required":["name","phone","address"],"type":"object"},"PartnerCustomerAddress":{"properties":{"details":{"example":"mənzil 34, 3-cü mərtəbə","nullable":true,"type":"string"},"lat":{"example":40.3789,"nullable":true,"type":"number"},"lng":{"example":49.8506,"nullable":true,"type":"number"},"street":{"example":"Nizami küç. 12","type":"string"}},"required":["street","details","lat","lng"],"type":"object"},"PartnerEnvironment":{"enum":["live","sandbox"],"type":"string"},"PartnerEventType":{"description":"PICKED_UP (goods collected from the hub) · EN_ROUTE · DELIVERED · FAILED. Each maps to an OrderStateMachine transition with the PARTNER actor.","enum":["PICKED_UP","EN_ROUTE","DELIVERED","FAILED"],"type":"string"},"PartnerMe":{"properties":{"environment":{"allOf":[{"$ref":"#/components/schemas/PartnerEnvironment"}]},"keyName":{"example":"Production integration","type":"string"},"partnerName":{"example":"Kargo Express","type":"string"},"rateLimit":{"description":"Requests per minute for this key","example":600,"type":"number"},"receivesAllOrders":{"description":"Admin flag: this key sees every order, not only its own","example":false,"type":"boolean"},"scopes":{"example":["orders:read","logistics:write"],"items":{"$ref":"#/components/schemas/ApiKeyScope"},"type":"array"},"usage7d":{"description":"Daily counters, oldest first (7 days)","items":{"$ref":"#/components/schemas/PartnerUsage"},"type":"array"}},"required":["partnerName","keyName","environment","scopes","rateLimit","receivesAllOrders","usage7d"],"type":"object"},"PartnerOrder":{"properties":{"area":{"example":"20 Yanvar","nullable":true,"type":"string"},"batch":{"allOf":[{"$ref":"#/components/schemas/PartnerBatchRef"}],"description":"The Turanyol van batch the order is on, when it is ours to deliver","nullable":true,"type":"object"},"codAmountQepik":{"description":"Cash to collect at the door, qəpik (0 for CARD)","example":24560,"type":"number"},"code":{"example":"ES-1042","type":"string"},"customer":{"allOf":[{"$ref":"#/components/schemas/PartnerCustomer"}],"description":"Present only for a key with the `orders:pii` scope — null otherwise","nullable":true,"type":"object"},"items":{"items":{"$ref":"#/components/schemas/PartnerOrderItem"},"type":"array"},"partnerAssignedAt":{"format":"date-time","nullable":true,"type":"string"},"paymentMethod":{"allOf":[{"$ref":"#/components/schemas/PaymentMethod"}]},"paymentStatus":{"allOf":[{"$ref":"#/components/schemas/OrderPaymentStatus"}]},"status":{"allOf":[{"$ref":"#/components/schemas/OrderStatus"}]},"timeWindowEnd":{"format":"date-time","nullable":true,"type":"string"},"timeWindowStart":{"format":"date-time","nullable":true,"type":"string"},"timeline":{"description":"Status timeline, oldest first","items":{"$ref":"#/components/schemas/PartnerOrderEvent"},"type":"array"},"totalQepik":{"description":"Order total in qəpik","example":24560,"type":"number"},"updatedAt":{"format":"date-time","type":"string"},"zone":{"allOf":[{"$ref":"#/components/schemas/PartnerZoneRef"}],"nullable":true,"type":"object"}},"required":["code","status","paymentMethod","paymentStatus","totalQepik","codAmountQepik","area","zone","timeWindowStart","timeWindowEnd","items","timeline","customer","batch","partnerAssignedAt","updatedAt"],"type":"object"},"PartnerOrderEvent":{"properties":{"at":{"format":"date-time","type":"string"},"status":{"allOf":[{"$ref":"#/components/schemas/OrderStatus"}]}},"required":["status","at"],"type":"object"},"PartnerOrderItem":{"properties":{"name":{"$ref":"#/components/schemas/LocalizedText"},"qty":{"example":2,"type":"number"},"unitPriceQepik":{"description":"Unit price in qəpik","example":1880,"type":"number"}},"required":["name","qty","unitPriceQepik"],"type":"object"},"PartnerUsage":{"properties":{"clientErrors":{"description":"4xx answers","example":3,"type":"number"},"day":{"description":"UTC calendar day","example":"2026-08-27","type":"string"},"requests":{"example":1284,"type":"number"},"serverErrors":{"description":"5xx answers","example":0,"type":"number"}},"required":["day","requests","clientErrors","serverErrors"],"type":"object"},"PartnerZoneRef":{"properties":{"id":{"format":"uuid","type":"string"},"name":{"$ref":"#/components/schemas/LocalizedText"}},"required":["id","name"],"type":"object"},"PaymentMethod":{"enum":["COD","CARD"],"type":"string"},"UpdateDeveloperWebhookDto":{"properties":{"events":{"items":{"enum":["order.placed","order.status_changed","order.delivered","order.cancelled","batch.completed","order.assigned_to_partner"],"type":"string"},"type":"array"},"isActive":{"description":"Re-enabling a webhook that was auto-disabled also clears its failure streak.","type":"boolean"},"url":{"example":"https://partner.example.az/esadarak/events","type":"string"}},"type":"object"},"WebhookDeliveryStatus":{"enum":["PENDING","DELIVERED","FAILED","DEAD"],"type":"string"},"WebhookEvent":{"enum":["order.placed","order.status_changed","order.delivered","order.cancelled","batch.completed","order.assigned_to_partner"],"type":"string"}},"securitySchemes":{"bearer":{"bearerFormat":"JWT","description":"Access token from /v1/auth/otp/verify or /v1/auth/refresh","scheme":"bearer","type":"http"}}},"info":{"contact":{},"description":"Marketplace + logistics platform for Sadarak Trade Center, Baku.\n\n- All money fields are **integers in qəpik** and end in `Qepik` (1 ₼ = 100 qəpik).\n- Every error is `{ statusCode, code, message, details? }` — switch on `code` (`ERR_*`); `message` is developer-only English.\n- Phones are E.164 (`+994XXXXXXXXX`).\n- Realtime: Socket.IO namespace `/realtime`, handshake `auth: { token: <accessToken> }`.","title":"Turanyol API","version":"0.1.0"},"openapi":"3.0.0","paths":{"/v1/developer/deliveries/{id}/redeliver":{"post":{"description":"Resets the attempt counter, so the redelivery gets the full backoff schedule.","operationId":"redeliverDeveloperDelivery","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeveloperDelivery"}}},"description":""},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_UNAUTHORIZED"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_FORBIDDEN — PARTNER accounts only · ERR_API_KEY_SCOPE — the key is missing `webhooks:manage`"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_NOT_FOUND"}},"security":[{"bearer":[]}],"summary":"Queue a failed or dead delivery again","tags":["developer"]}},"/v1/developer/keys":{"get":{"description":"Prefix only — the raw key was shown once, at creation or rotation.","operationId":"listDeveloperKeys","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeveloperKeys"}}},"description":""},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_UNAUTHORIZED"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_FORBIDDEN — PARTNER accounts only"}},"security":[{"bearer":[]}],"summary":"The API keys of this partner account","tags":["developer"]},"post":{"description":"The response is the ONLY time the key is shown (`esk_live_<32>` / `esk_sandbox_<32>`); only its sha256 hash is stored. A LIVE key works against the live API, a SANDBOX key against the sandbox one — the other environment answers ERR_API_KEY_ENVIRONMENT. Maximum 10 active keys per partner.","operationId":"createDeveloperKey","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDeveloperKeyDto"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeveloperKeyCreated"}}},"description":""},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_VALIDATION"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_UNAUTHORIZED"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_FORBIDDEN — PARTNER accounts only"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_API_KEY_LIMIT"}},"security":[{"bearer":[]}],"summary":"Mint a new API key","tags":["developer"]}},"/v1/developer/keys/{id}":{"delete":{"description":"No grace: the next request with it answers ERR_API_KEY_REVOKED.","operationId":"revokeDeveloperKey","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeveloperKey"}}},"description":""},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_UNAUTHORIZED"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_FORBIDDEN — PARTNER accounts only"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_NOT_FOUND"}},"security":[{"bearer":[]}],"summary":"Revoke a key immediately","tags":["developer"]}},"/v1/developer/keys/{id}/rotate":{"post":{"description":"Mints a key with the same name, environment and scopes and sets `revokedAt = now + 24 h` on the old one, so both work while the new key is deployed. After the grace the old key answers ERR_API_KEY_REVOKED.","operationId":"rotateDeveloperKey","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeveloperKeyRotated"}}},"description":""},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_API_KEY_REVOKED"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_FORBIDDEN — PARTNER accounts only"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_NOT_FOUND"}},"security":[{"bearer":[]}],"summary":"Replace a key, old one valid for another 24 h","tags":["developer"]}},"/v1/developer/keys/{id}/usage":{"get":{"description":"Requests, 4xx and 5xx per UTC day, oldest first. Counters are kept 35 days.","operationId":"getDeveloperKeyUsage","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}},{"in":"query","name":"days","required":false,"schema":{"default":7,"maximum":35,"minimum":1,"type":"number"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeveloperKeyUsageSeries"}}},"description":""},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_UNAUTHORIZED"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_FORBIDDEN — PARTNER accounts only"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_NOT_FOUND"}},"security":[{"bearer":[]}],"summary":"Daily request counters of one key","tags":["developer"]}},"/v1/developer/openapi.json":{"get":{"description":"The full Turanyol spec reduced to the `partner` and `developer` operations plus every schema they reach (the error schema always included). Public — the developer portal renders it without a session.","operationId":"getDeveloperOpenApi","parameters":[],"responses":{"200":{"description":"An OpenAPI 3 document"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_UNAUTHORIZED"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_FORBIDDEN — PARTNER accounts only"}},"security":[{"bearer":[]}],"summary":"The partner-facing OpenAPI document","tags":["developer"]}},"/v1/developer/webhooks":{"get":{"operationId":"listDeveloperWebhooks","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeveloperWebhooks"}}},"description":""},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_UNAUTHORIZED"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_FORBIDDEN — PARTNER accounts only"}},"security":[{"bearer":[]}],"summary":"The webhooks of this partner account","tags":["developer"]},"post":{"description":"HTTPS only (http:// is accepted for localhost outside production) — the payload can carry customer data. The signing secret is returned ONCE. Maximum 5 webhooks per key. The API key named in `apiKeyId` must carry the `webhooks:manage` scope (ERR_API_KEY_SCOPE otherwise), and so must the key behind every other /v1/developer/webhooks route.","operationId":"createDeveloperWebhook","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDeveloperWebhookDto"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeveloperWebhookCreated"}}},"description":""},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_VALIDATION · ERR_WEBHOOK_URL_INVALID"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_UNAUTHORIZED"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_FORBIDDEN — PARTNER accounts only · ERR_API_KEY_SCOPE — the key is missing `webhooks:manage`"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_NOT_FOUND"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_WEBHOOK_LIMIT"}},"security":[{"bearer":[]}],"summary":"Register a webhook on one API key","tags":["developer"]}},"/v1/developer/webhooks/{id}":{"delete":{"operationId":"deleteDeveloperWebhook","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Deleted"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_UNAUTHORIZED"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_FORBIDDEN — PARTNER accounts only · ERR_API_KEY_SCOPE — the key is missing `webhooks:manage`"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_NOT_FOUND"}},"security":[{"bearer":[]}],"summary":"Delete a webhook and its delivery history","tags":["developer"]},"patch":{"operationId":"updateDeveloperWebhook","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDeveloperWebhookDto"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeveloperWebhook"}}},"description":""},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_VALIDATION · ERR_WEBHOOK_URL_INVALID"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_UNAUTHORIZED"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_FORBIDDEN — PARTNER accounts only · ERR_API_KEY_SCOPE — the key is missing `webhooks:manage`"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_NOT_FOUND"}},"security":[{"bearer":[]}],"summary":"Change a webhook URL, its events, or switch it on again","tags":["developer"]}},"/v1/developer/webhooks/{id}/deliveries":{"get":{"description":"PENDING (queued) · DELIVERED (2xx) · FAILED (a retry is scheduled at `nextAttemptAt`) · DEAD (the 1 min / 5 min / 30 min / 2 h / 12 h schedule is exhausted).","operationId":"listDeveloperDeliveries","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}},{"in":"query","name":"status","required":false,"schema":{"$ref":"#/components/schemas/WebhookDeliveryStatus"}},{"in":"query","name":"page","required":false,"schema":{"default":1,"maximum":10000,"minimum":1,"type":"number"}},{"in":"query","name":"pageSize","required":false,"schema":{"default":20,"maximum":50,"minimum":1,"type":"number"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PageOfDeveloperDelivery"}}},"description":""},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_VALIDATION"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_UNAUTHORIZED"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_FORBIDDEN — PARTNER accounts only · ERR_API_KEY_SCOPE — the key is missing `webhooks:manage`"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_NOT_FOUND"}},"security":[{"bearer":[]}],"summary":"Delivery log of one webhook, newest first","tags":["developer"]}},"/v1/developer/webhooks/{id}/test":{"post":{"description":"Queues a real delivery with a real `X-Esadarak-Signature`, so an integration can verify its signature check before going live. Poll the deliveries list for the outcome. A DISABLED webhook is refused up front — the worker would abandon the delivery immediately.","operationId":"testDeveloperWebhook","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeveloperDelivery"}}},"description":""},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_UNAUTHORIZED"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_FORBIDDEN — PARTNER accounts only · ERR_API_KEY_SCOPE — the key is missing `webhooks:manage`"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_NOT_FOUND"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_WEBHOOK_DISABLED — the webhook is switched off; re-enable it first"}},"security":[{"bearer":[]}],"summary":"Send a signed `ping` through the real delivery path","tags":["developer"]}},"/v1/partner/me":{"get":{"description":"Partner name, environment, scopes, per-minute rate limit and the last 7 days of usage.","operationId":"getPartnerMe","parameters":[{"description":"Partner API key: `esk_live_<32>` on the live API, `esk_sandbox_<32>` on the sandbox one.","in":"header","name":"X-Api-Key","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerMe"}}},"description":""},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_API_KEY_INVALID · ERR_API_KEY_REVOKED"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_API_KEY_ENVIRONMENT · ERR_API_KEY_SCOPE"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_RATE_LIMITED — see the `Retry-After` header"}},"summary":"The key behind this request","tags":["partner"]}},"/v1/partner/orders":{"get":{"description":"Orders assigned to this partner (`Order.partnerApiKeyId`), or every order when an admin flagged the key `receivesAllOrders`. Newest first. `customer` is present only with the `orders:pii` scope. `updatedSince` is the incremental-sync filter.","operationId":"listPartnerOrders","parameters":[{"description":"Partner API key: `esk_live_<32>` on the live API, `esk_sandbox_<32>` on the sandbox one.","in":"header","name":"X-Api-Key","required":true,"schema":{"type":"string"}},{"in":"query","name":"status","required":false,"schema":{"$ref":"#/components/schemas/OrderStatus"}},{"description":"createdAt ≥ from","in":"query","name":"from","required":false,"schema":{"format":"date-time","type":"string"}},{"description":"createdAt < to","in":"query","name":"to","required":false,"schema":{"format":"date-time","type":"string"}},{"description":"updatedAt ≥ updatedSince — the incremental-sync filter","in":"query","name":"updatedSince","required":false,"schema":{"format":"date-time","type":"string"}},{"in":"query","name":"page","required":false,"schema":{"default":1,"maximum":10000,"minimum":1,"type":"number"}},{"in":"query","name":"pageSize","required":false,"schema":{"default":20,"maximum":50,"minimum":1,"type":"number"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PageOfPartnerOrder"}}},"description":""},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_VALIDATION"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_API_KEY_INVALID · ERR_API_KEY_REVOKED"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_API_KEY_ENVIRONMENT · ERR_API_KEY_SCOPE"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_RATE_LIMITED — see the `Retry-After` header"}},"summary":"List the orders visible to this API key","tags":["partner"]}},"/v1/partner/orders/{code}":{"get":{"description":"Same visibility rule as the list; an order this key may not see is 404.","operationId":"getPartnerOrder","parameters":[{"description":"Partner API key: `esk_live_<32>` on the live API, `esk_sandbox_<32>` on the sandbox one.","in":"header","name":"X-Api-Key","required":true,"schema":{"type":"string"}},{"in":"path","name":"code","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerOrder"}}},"description":""},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_API_KEY_INVALID · ERR_API_KEY_REVOKED"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_API_KEY_ENVIRONMENT · ERR_API_KEY_SCOPE"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_NOT_FOUND"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_RATE_LIMITED — see the `Retry-After` header"}},"summary":"One order by its code (ES-1042)","tags":["partner"]}},"/v1/partner/orders/{code}/events":{"post":{"description":"PICKED_UP → SCANNED_TO_VAN · EN_ROUTE → EN_ROUTE (also straight from PACKED, the partner-only edge for regionally fulfilled orders — Phase 8 moved it off AT_HUB because the hub now packs partner orders too) · DELIVERED · FAILED. Every event goes through OrderStateMachine with the PARTNER actor and appends an OrderEvent noted `partner:<partnerName>`. Only orders assigned to THIS key: `receivesAllOrders` grants read access, never write.","operationId":"createPartnerOrderEvent","parameters":[{"description":"Partner API key: `esk_live_<32>` on the live API, `esk_sandbox_<32>` on the sandbox one.","in":"header","name":"X-Api-Key","required":true,"schema":{"type":"string"}},{"in":"path","name":"code","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePartnerOrderEventDto"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerOrder"}}},"description":""},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_VALIDATION · ERR_BAD_REQUEST"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_API_KEY_INVALID · ERR_API_KEY_REVOKED"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_PARTNER_ORDER_NOT_ASSIGNED · ERR_API_KEY_SCOPE · ERR_API_KEY_ENVIRONMENT"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_INVALID_TRANSITION"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponseDto"}}},"description":"ERR_RATE_LIMITED — see the `Retry-After` header"}},"summary":"Report logistics progress on an assigned order","tags":["partner"]}}},"servers":[{"url":"http://localhost:3000","description":"Live"}],"tags":[{"name":"partner"},{"name":"developer"}]}