# Provider API reference

Contract version: **1.0.0**. This page is generated from `packages/contracts/src/provider-protocol.ts`. Do not edit examples independently.

Implement ZAYUNO_TO_PROVIDER routes on **your provider backend**. The webhook entry is PROVIDER_TO_ZAYUNO. Core management routes live in the separate [Zayuno Core API guide](https://partners.zayuno.uz/docs/api-reference.md).

- [OpenAPI 3.1 JSON](https://partners.zayuno.uz/openapi.json) — schemas, required fields and request/response examples.
- [Postman collection](https://partners.zayuno.uz/postman.json) — requests with environment placeholders.
- [Capabilities](https://partners.zayuno.uz/docs/capabilities.md) — read-only vs transactional; physical fulfillment also requires active locations.
- [Authentication](https://partners.zayuno.uz/docs/auth.md) — outbound auth and inbound webhook signing are separate.

Provider-to-Zayuno status events use `POST https://api.zayuno.uz/api/v1/webhooks/{providerSlug}`.
Never send production status updates to your own backend URL.

## Request parameters {#contract-parameters}

Use the IDs and field names from the request schema. Base URLs, path parameters and query parameters are not interchangeable. Encode path IDs, send JSON bodies for POST requests, and use the authentication mode selected in the portal.

## GET /provider-info {#contract-metadata}

Provider metadata, advertised capabilities, geography and supported verticals

| Property | Value |
| --- | --- |
| Capability | `METADATA` |
| Direction | `ZAYUNO_TO_PROVIDER` |
| Profiles | DISCOVERY_READONLY, TRANSACTIONAL |
| Requirement | Required in the listed profiles |
| Request schema | No JSON request body |
| Response schema | ProviderInfo |

### Request

`GET /provider-info` — no JSON body.

### Response example

```json
{
  "id": "provider_shopla",
  "slug": "shopla",
  "name": "Shopla Online Mart",
  "status": "ACTIVE",
  "type": "RETAIL",
  "environment": "LIVE",
  "category": "RETAIL",
  "subcategory": "online_marketplace",
  "geography": [
    "UZ"
  ],
  "adapterType": "remote-http",
  "authMethod": "API_KEY",
  "capabilities": [
    "METADATA",
    "HEALTH",
    "LOCATIONS",
    "CATALOG",
    "SEARCH",
    "QUOTE",
    "ACTION_CREATE",
    "ACTION_STATUS",
    "PAYMENT_OPTIONS",
    "ACTION_CANCEL",
    "WEBHOOK"
  ],
  "supportContact": {
    "email": "support@shopla.uz",
    "phone": "+998712000000",
    "telegram": "@shoplasupport"
  },
  "metadata": {}
}
```

Required response fields: `id`, `slug`, `name`, `status`, `type`, `capabilities`.

## GET /health {#contract-health}

Deterministic health check protocol with latency and system status

| Property | Value |
| --- | --- |
| Capability | `HEALTH` |
| Direction | `ZAYUNO_TO_PROVIDER` |
| Profiles | DISCOVERY_READONLY, TRANSACTIONAL |
| Requirement | Required in the listed profiles |
| Request schema | No JSON request body |
| Response schema | HealthCheckResult |

### Request

`GET /health` — no JSON body.

### Response example

```json
{
  "status": "HEALTHY",
  "latencyMs": 18,
  "timestamp": "2026-08-24T10:00:00.000Z",
  "details": {
    "uptimeSeconds": 86400
  }
}
```

Required response fields: `status`, `latencyMs`, `timestamp`.

## GET /locations {#contract-locations}

Physical branches, warehouses, pickup locations, or fulfillment centers

| Property | Value |
| --- | --- |
| Capability | `LOCATIONS` |
| Direction | `ZAYUNO_TO_PROVIDER` |
| Profiles | DISCOVERY_READONLY, TRANSACTIONAL |
| Requirement | When declared; see fulfillment/location requirements |
| Request schema | No JSON request body |
| Response schema | Location[] |

### Request

`GET /locations` — no JSON body.

### Response example

```json
[
  {
    "id": "loc_main",
    "providerId": "provider_shopla",
    "providerLocationId": "branch_1",
    "name": "Main Branch",
    "address": "Tashkent, Amir Temur 1",
    "latitude": 41.311081,
    "longitude": 69.240562,
    "serviceRadiusKm": 10,
    "isActive": true,
    "metadata": {}
  }
]
```

Required response fields: `id`, `providerId`, `providerLocationId`, `name`, `address`.

## GET /catalog {#contract-catalog}

Full catalog hierarchy with categories, offerings, variants, and option groups

| Property | Value |
| --- | --- |
| Capability | `CATALOG` |
| Direction | `ZAYUNO_TO_PROVIDER` |
| Profiles | DISCOVERY_READONLY, TRANSACTIONAL |
| Requirement | Required in the listed profiles |
| Request schema | No JSON request body |
| Response schema | Catalog |

### Request

`GET /catalog` — no JSON body.

### Response example

```json
{
  "providerSlug": "shopla",
  "categories": [
    {
      "id": "cat_drinks",
      "slug": "drinks",
      "title": "Ichimliklar",
      "description": "Issiq va sovuq ichimliklar",
      "displayOrder": 1,
      "offeringsCount": 1
    }
  ],
  "offerings": [
    {
      "id": "item_coffee_latte",
      "providerId": "provider_shopla",
      "offeringCode": "COFFEE-LATTE",
      "title": "Latte",
      "description": "Freshly brewed espresso with velvety steamed milk",
      "categorySlug": "drinks",
      "categoryTitle": "Ichimliklar",
      "basePrice": 30000,
      "currency": "UZS",
      "isAvailable": true,
      "variants": [
        {
          "id": "var_standard",
          "name": "Standard (300ml)",
          "basePrice": 30000,
          "isAvailable": true,
          "metadata": {}
        },
        {
          "id": "var_large",
          "name": "Large (450ml)",
          "basePrice": 38000,
          "isAvailable": true,
          "metadata": {}
        }
      ],
      "optionGroups": [
        {
          "id": "grp_milk",
          "name": "Sut turi",
          "isRequired": false,
          "minSelections": 0,
          "maxSelections": 1,
          "options": [
            {
              "id": "opt_whole",
              "name": "Oddiy sut",
              "priceDelta": 0,
              "isDefault": true,
              "isAvailable": true,
              "metadata": {}
            },
            {
              "id": "opt_oat",
              "name": "Suli suti (Oat milk)",
              "priceDelta": 6000,
              "isDefault": false,
              "isAvailable": true,
              "metadata": {}
            }
          ]
        }
      ],
      "tags": [
        "coffee",
        "hot-drinks"
      ],
      "metadata": {}
    }
  ],
  "version": "2026.1",
  "updatedAt": "2026-08-24T10:00:00.000Z"
}
```

Required response fields: `providerSlug`, `categories`, `offerings`.

## GET /offerings/:id {#contract-offering}

Single offering deep lookup by offering ID or offeringCode with option groups

| Property | Value |
| --- | --- |
| Capability | `CATALOG` |
| Direction | `ZAYUNO_TO_PROVIDER` |
| Profiles | DISCOVERY_READONLY, TRANSACTIONAL |
| Requirement | Required in the listed profiles |
| Request schema | No JSON request body |
| Response schema | Offering |

### Request

`GET /offerings/:id` — no JSON body.

### Response example

```json
{
  "id": "item_coffee_latte",
  "providerId": "provider_shopla",
  "offeringCode": "COFFEE-LATTE",
  "title": "Latte",
  "description": "Freshly brewed espresso with velvety steamed milk",
  "categorySlug": "drinks",
  "categoryTitle": "Ichimliklar",
  "basePrice": 30000,
  "currency": "UZS",
  "isAvailable": true,
  "variants": [
    {
      "id": "var_standard",
      "name": "Standard (300ml)",
      "basePrice": 30000,
      "isAvailable": true,
      "metadata": {}
    },
    {
      "id": "var_large",
      "name": "Large (450ml)",
      "basePrice": 38000,
      "isAvailable": true,
      "metadata": {}
    }
  ],
  "optionGroups": [
    {
      "id": "grp_milk",
      "name": "Sut turi",
      "isRequired": false,
      "minSelections": 0,
      "maxSelections": 1,
      "options": [
        {
          "id": "opt_whole",
          "name": "Oddiy sut",
          "priceDelta": 0,
          "isDefault": true,
          "isAvailable": true,
          "metadata": {}
        },
        {
          "id": "opt_oat",
          "name": "Suli suti (Oat milk)",
          "priceDelta": 6000,
          "isDefault": false,
          "isAvailable": true,
          "metadata": {}
        }
      ]
    }
  ],
  "tags": [
    "coffee",
    "hot-drinks"
  ],
  "metadata": {}
}
```

Required response fields: `id`, `providerId`, `offeringCode`, `title`, `basePrice`.

## GET /search {#contract-search}

Real-time keyword and parameter search over provider catalog items

| Property | Value |
| --- | --- |
| Capability | `SEARCH` |
| Direction | `ZAYUNO_TO_PROVIDER` |
| Profiles | DISCOVERY_READONLY, TRANSACTIONAL |
| Requirement | When declared; see fulfillment/location requirements |
| Request schema | No JSON request body |
| Response schema | Offering[] |

### Request

`GET /search` — no JSON body.

### Response example

```json
[
  {
    "id": "item_coffee_latte",
    "providerId": "provider_shopla",
    "offeringCode": "COFFEE-LATTE",
    "title": "Latte",
    "description": "Freshly brewed espresso with velvety steamed milk",
    "categorySlug": "drinks",
    "categoryTitle": "Ichimliklar",
    "basePrice": 30000,
    "currency": "UZS",
    "isAvailable": true,
    "variants": [
      {
        "id": "var_standard",
        "name": "Standard (300ml)",
        "basePrice": 30000,
        "isAvailable": true,
        "metadata": {}
      },
      {
        "id": "var_large",
        "name": "Large (450ml)",
        "basePrice": 38000,
        "isAvailable": true,
        "metadata": {}
      }
    ],
    "optionGroups": [
      {
        "id": "grp_milk",
        "name": "Sut turi",
        "isRequired": false,
        "minSelections": 0,
        "maxSelections": 1,
        "options": [
          {
            "id": "opt_whole",
            "name": "Oddiy sut",
            "priceDelta": 0,
            "isDefault": true,
            "isAvailable": true,
            "metadata": {}
          },
          {
            "id": "opt_oat",
            "name": "Suli suti (Oat milk)",
            "priceDelta": 6000,
            "isDefault": false,
            "isAvailable": true,
            "metadata": {}
          }
        ]
      }
    ],
    "tags": [
      "coffee",
      "hot-drinks"
    ],
    "metadata": {}
  }
]
```

Required response fields: `id`, `providerId`, `offeringCode`, `title`, `basePrice`.

## POST /quote {#contract-quote}

Itemized price calculation with binding total, subtotal, fees and expiration

| Property | Value |
| --- | --- |
| Capability | `QUOTE` |
| Direction | `ZAYUNO_TO_PROVIDER` |
| Profiles | TRANSACTIONAL |
| Requirement | Required in the listed profiles |
| Request schema | RequestQuoteInput |
| Response schema | NormalizedQuote |

### Request

```json
{
  "providerSlug": "shopla",
  "locationId": "loc_main",
  "items": [
    {
      "offeringId": "item_coffee_latte",
      "variantId": "var_standard",
      "quantity": 2,
      "selectedOptions": [
        {
          "groupId": "grp_milk",
          "optionId": "opt_whole",
          "quantity": 1
        }
      ]
    }
  ]
}
```

### Response example

```json
{
  "id": "quote_123",
  "providerSlug": "shopla",
  "locationId": "loc_main",
  "currency": "UZS",
  "subtotal": 60000,
  "totalFees": 10000,
  "totalDiscount": 0,
  "total": 70000,
  "lines": [
    {
      "offeringId": "item_coffee_latte",
      "offeringTitle": "Latte",
      "variantId": "var_standard",
      "quantity": 2,
      "unitPrice": 30000,
      "optionsTotal": 0,
      "lineTotal": 60000,
      "selectedOptions": [
        {
          "groupId": "grp_milk",
          "optionId": "opt_whole",
          "name": "Oddiy sut",
          "priceDelta": 0
        }
      ]
    }
  ],
  "fees": [
    {
      "name": "Yetkazib berish xizmati",
      "amount": 10000
    }
  ],
  "discounts": [],
  "expiresAt": "2026-08-24T10:15:00.000Z",
  "metadata": {}
}
```

Required response fields: `id`, `providerSlug`, `lines`, `subtotal`, `total`, `expiresAt`.

## POST /actions {#contract-actions}

Order/booking creation with idempotency and provider payment checkout handoff

| Property | Value |
| --- | --- |
| Capability | `ACTION_CREATE` |
| Direction | `ZAYUNO_TO_PROVIDER` |
| Profiles | TRANSACTIONAL |
| Requirement | Required in the listed profiles |
| Request schema | CreateActionInput |
| Response schema | NormalizedAction |

### Request

```json
{
  "idempotencyKey": "idemp_unique_98765",
  "providerSlug": "shopla",
  "quoteId": "quote_123",
  "customer": {
    "name": "Ali Valiyev",
    "phone": "+998901234567"
  },
  "destination": {
    "raw": "Tashkent, Amir Temur 1"
  },
  "items": [
    {
      "offeringId": "item_coffee_latte",
      "quantity": 2
    }
  ],
  "userConfirmed": true
}
```

### Response example

```json
{
  "id": "act_12345",
  "publicId": "ZY-SHOPLA-12345",
  "externalActionId": "ord_provider_999",
  "providerSlug": "shopla",
  "quoteId": "quote_123",
  "status": "AWAITING_PAYMENT",
  "paymentStatus": "PENDING",
  "subtotal": 60000,
  "fees": 10000,
  "discount": 0,
  "total": 70000,
  "currency": "UZS",
  "customer": {
    "name": "Ali Valiyev",
    "phone": "+998901234567"
  },
  "lines": [
    {
      "offeringId": "item_coffee_latte",
      "offeringTitle": "Latte",
      "quantity": 2,
      "unitPrice": 30000,
      "optionsTotal": 0,
      "lineTotal": 60000
    }
  ],
  "nextAction": {
    "type": "OPEN_URL",
    "url": "https://checkout.shopla.uz/pay/act_12345",
    "label": "Shopla xavfsiz to‘lov sahifasiga o‘tish"
  },
  "fulfillmentType": "STANDARD",
  "createdAt": "2026-08-24T10:00:00.000Z",
  "updatedAt": "2026-08-24T10:00:00.000Z",
  "metadata": {}
}
```

Required response fields: `providerSlug`, `quoteId`, `userConfirmed`.

## GET /actions/:id {#contract-action-status}

Polling and real-time status inquiry for created action/order

| Property | Value |
| --- | --- |
| Capability | `ACTION_STATUS` |
| Direction | `ZAYUNO_TO_PROVIDER` |
| Profiles | TRANSACTIONAL |
| Requirement | Required in the listed profiles |
| Request schema | No JSON request body |
| Response schema | NormalizedAction |

### Request

`GET /actions/:id` — no JSON body.

### Response example

```json
{
  "id": "act_12345",
  "publicId": "ZY-SHOPLA-12345",
  "externalActionId": "ord_provider_999",
  "providerSlug": "shopla",
  "quoteId": "quote_123",
  "status": "PROCESSING",
  "paymentStatus": "PAID",
  "subtotal": 60000,
  "fees": 10000,
  "discount": 0,
  "total": 70000,
  "currency": "UZS",
  "customer": {
    "name": "Ali Valiyev",
    "phone": "+998901234567"
  },
  "lines": [
    {
      "offeringId": "item_coffee_latte",
      "offeringTitle": "Latte",
      "quantity": 2,
      "unitPrice": 30000,
      "optionsTotal": 0,
      "lineTotal": 60000
    }
  ],
  "fulfillmentType": "STANDARD",
  "createdAt": "2026-08-24T10:00:00.000Z",
  "updatedAt": "2026-08-24T10:05:00.000Z",
  "metadata": {}
}
```

Required response fields: `id`, `publicId`, `providerSlug`, `status`, `lines`, `subtotal`, `total`, `createdAt`, `updatedAt`.

## GET /actions/:id/payment-options {#contract-payment-options}

Available payment methods discovery for a pending action

| Property | Value |
| --- | --- |
| Capability | `PAYMENT_OPTIONS` |
| Direction | `ZAYUNO_TO_PROVIDER` |
| Profiles | TRANSACTIONAL |
| Requirement | When declared; see fulfillment/location requirements |
| Request schema | No JSON request body |
| Response schema | PaymentOption[] |

### Request

`GET /actions/:id/payment-options` — no JSON body.

### Response example

```json
[
  {
    "id": "pay_click",
    "name": "Click",
    "type": "CLICK",
    "checkoutUrl": "https://checkout.shopla.uz/pay/act_12345?method=click",
    "isAvailable": true
  },
  {
    "id": "pay_payme",
    "name": "Payme",
    "type": "PAYME",
    "checkoutUrl": "https://checkout.shopla.uz/pay/act_12345?method=payme",
    "isAvailable": true
  }
]
```

Required response fields: `id`, `name`, `type`.

## POST /actions/:id/cancel {#contract-cancellation}

Action/order cancellation lifecycle with reason description

| Property | Value |
| --- | --- |
| Capability | `ACTION_CANCEL` |
| Direction | `ZAYUNO_TO_PROVIDER` |
| Profiles | TRANSACTIONAL |
| Requirement | When declared; see fulfillment/location requirements |
| Request schema | CancelActionInput |
| Response schema | CancelActionResult |

### Request

```json
{
  "reason": "Foydalanuvchi buyurtmani bekor qildi"
}
```

### Response example

```json
{
  "success": true,
  "actionId": "act_12345",
  "previousStatus": "AWAITING_PAYMENT",
  "newStatus": "CANCELLED",
  "message": "Foydalanuvchi buyurtmani bekor qildi",
  "refundInitiated": false
}
```

Required response fields: `success`, `actionId`, `previousStatus`, `newStatus`, `message`.

## POST /api/v1/webhooks/:providerSlug {#contract-webhooks}

Provider status update delivery to Zayuno signed with HMAC-SHA256

| Property | Value |
| --- | --- |
| Capability | `WEBHOOK` |
| Direction | `PROVIDER_TO_ZAYUNO` |
| Profiles | TRANSACTIONAL |
| Requirement | Required in the listed profiles |
| Request schema | NormalizedWebhookEvent |
| Response schema | WebhookIngestionResponse |

### Request

```json
{
  "eventId": "evt_123",
  "eventType": "action.status_updated",
  "providerSlug": "shopla",
  "actionId": "act_12345",
  "newStatus": "COMPLETED",
  "timestamp": "2026-08-24T10:00:00.000Z"
}
```

### Response example

```json
{
  "success": true
}
```

Required event request fields: `eventId`, `eventType`, `providerSlug`, `timestamp`.

