{
  "openapi": "3.1.0",
  "info": {
    "title": "TurboPulsa Developer API",
    "version": "1.0.0",
    "description": "Satu alur katalog → quote/inquiry → konfirmasi → status. Harga agen existing dan Saldo Rupiah. Deposit melalui website."
  },
  "servers": [
    {
      "url": "https://api.turbopulsa.com/sandbox/v1",
      "description": "Sandbox — simulasi tanpa supplier atau uang nyata"
    },
    {
      "url": "https://api.turbopulsa.com/v1",
      "description": "Produksi — mengikuti status layanan existing"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "paths": {
    "/capabilities": {
      "get": {
        "operationId": "getCapabilities",
        "summary": "Kemampuan dan batas integrasi",
        "tags": [
          "Mulai"
        ],
        "x-scope": "catalog:read",
        "responses": {
          "200": {
            "description": "Berhasil",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CapabilitiesResponse"
                },
                "example": {
                  "data": {
                    "api_version": "1",
                    "currency": "IDR",
                    "transactions_available": true,
                    "postpaid_available": true,
                    "limits": {
                      "transaction_rupiah": 100000,
                      "daily_rupiah": 1000000,
                      "requests_per_minute": 120
                    },
                    "deposit_url": "https://turbopulsa.com/member/deposit",
                    "sandbox_scenarios": [
                      "success",
                      "pending",
                      "failed",
                      "insufficient_balance",
                      "price_changed",
                      "expired",
                      "timeout",
                      "manual_review"
                    ],
                    "webhook_delivery": "at_least_once"
                  },
                  "meta": {
                    "environment": "sandbox",
                    "request_id": "10000000-0000-4000-8000-000000000001"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Key tidak berlaku",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Scope atau akun tidak diizinkan",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Periksa status, referensi atau quote",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Parameter tidak valid",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Batas akses; ikuti Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Layanan belum tersedia; jangan membuat pembelian baru",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/catalog": {
      "get": {
        "operationId": "listProducts",
        "summary": "Katalog prabayar terbit",
        "tags": [
          "Katalog"
        ],
        "x-scope": "catalog:read",
        "responses": {
          "200": {
            "description": "Berhasil",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CatalogResponse"
                },
                "example": {
                  "data": [
                    {
                      "id": 1,
                      "code": "KODE_DARI_KATALOG",
                      "slug": "pulsa",
                      "name": "Pulsa simulasi 5.000",
                      "brand": "Telkomsel",
                      "price": 5050,
                      "currency": "IDR",
                      "description": "Contoh simulasi; gunakan kode dari katalog Anda.",
                      "available": true,
                      "reason": null,
                      "logo_url": "https://turbopulsa.com/icons/brands/telkomsel.png",
                      "fields": [
                        {
                          "key": "phone",
                          "label": "Nomor HP",
                          "input_mode": "tel"
                        }
                      ]
                    }
                  ],
                  "meta": {
                    "total": 1,
                    "page": 1,
                    "last_page": 1,
                    "environment": "sandbox",
                    "request_id": "10000000-0000-4000-8000-000000000001"
                  },
                  "operator_prefixes": {
                    "Telkomsel": [
                      "0812"
                    ]
                  },
                  "categories": null
                }
              }
            }
          },
          "401": {
            "description": "Key tidak berlaku",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Scope atau akun tidak diizinkan",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Periksa status, referensi atau quote",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Parameter tidak valid",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Batas akses; ikuti Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Layanan belum tersedia; jangan membuat pembelian baru",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50
            }
          },
          {
            "name": "slug",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "brand",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/postpaid/catalog": {
      "get": {
        "operationId": "listBillers",
        "summary": "Penyedia dan wilayah pascabayar",
        "tags": [
          "Katalog"
        ],
        "x-scope": "catalog:read",
        "responses": {
          "200": {
            "description": "Berhasil",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CatalogResponse"
                },
                "example": {
                  "data": [
                    {
                      "id": 2,
                      "code": "KODE_PENYEDIA_DARI_KATALOG",
                      "category": "pln",
                      "name": "PLN Pascabayar simulasi",
                      "brand": "PLN",
                      "admin_fee": 2500,
                      "currency": "IDR",
                      "region": null,
                      "available": true,
                      "reason": null,
                      "logo_url": "https://turbopulsa.com/icons/brands/pln.ico",
                      "fields": [
                        {
                          "key": "customer_no",
                          "label": "ID pelanggan",
                          "input_mode": "numeric"
                        }
                      ]
                    }
                  ],
                  "meta": {
                    "total": 1,
                    "page": 1,
                    "last_page": 1,
                    "environment": "sandbox",
                    "request_id": "10000000-0000-4000-8000-000000000001"
                  },
                  "operator_prefixes": null,
                  "categories": {
                    "pln": "PLN Pascabayar"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Key tidak berlaku",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Scope atau akun tidak diizinkan",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Periksa status, referensi atau quote",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Parameter tidak valid",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Batas akses; ikuti Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Layanan belum tersedia; jangan membuat pembelian baru",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50
            }
          },
          {
            "name": "category",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/wallet": {
      "get": {
        "operationId": "getWallet",
        "summary": "Saldo tersedia dan dana ditahan",
        "tags": [
          "Saldo"
        ],
        "x-scope": "wallet:read",
        "responses": {
          "200": {
            "description": "Berhasil",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WalletResponse"
                },
                "example": {
                  "data": {
                    "balance": 1000000,
                    "held": 0,
                    "available": 1000000,
                    "currency": "IDR",
                    "simulated": true
                  },
                  "meta": {
                    "environment": "sandbox",
                    "request_id": "10000000-0000-4000-8000-000000000001"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Key tidak berlaku",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Scope atau akun tidak diizinkan",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Periksa status, referensi atau quote",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Parameter tidak valid",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Batas akses; ikuti Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Layanan belum tersedia; jangan membuat pembelian baru",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/quotes": {
      "post": {
        "operationId": "createQuote",
        "summary": "Buat penawaran prabayar",
        "tags": [
          "Transaksi"
        ],
        "x-scope": "quotes:write",
        "responses": {
          "201": {
            "description": "Berhasil",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderResponse"
                },
                "example": {
                  "data": {
                    "id": "20000000-0000-4000-8000-000000000001",
                    "client_reference": "ORDER-CONTOH-1001",
                    "product_code": "KODE_DARI_KATALOG",
                    "name": "Pulsa simulasi 5.000",
                    "destination": "********0000",
                    "price": 5050,
                    "charged": 0,
                    "currency": "IDR",
                    "transaction_kind": "prepaid",
                    "channel": "api",
                    "environment": "sandbox",
                    "status": "awaiting_confirmation",
                    "created_at": "2030-01-01T00:00:00Z",
                    "expires_at": "2030-01-01T00:05:00Z",
                    "confirmation_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
                    "version": 1,
                    "bill": null
                  },
                  "meta": {
                    "environment": "sandbox",
                    "request_id": "10000000-0000-4000-8000-000000000001"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Key tidak berlaku",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Scope atau akun tidak diizinkan",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Periksa status, referensi atau quote",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Parameter tidak valid",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Batas akses; ikuti Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Layanan belum tersedia; jangan membuat pembelian baru",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Pertahankan UUID yang sama untuk retry payload yang sama."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QuoteRequest"
              }
            }
          }
        }
      }
    },
    "/postpaid/inquiries": {
      "post": {
        "operationId": "createInquiry",
        "summary": "Cek tagihan pascabayar",
        "tags": [
          "Transaksi"
        ],
        "x-scope": "inquiries:write",
        "responses": {
          "201": {
            "description": "Berhasil",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderResponse"
                },
                "example": {
                  "data": {
                    "id": "20000000-0000-4000-8000-000000000001",
                    "client_reference": "BILL-CONTOH-1001",
                    "product_code": "KODE_PENYEDIA_DARI_KATALOG",
                    "name": "PLN Pascabayar simulasi",
                    "destination": "********0000",
                    "price": 52500,
                    "charged": 0,
                    "currency": "IDR",
                    "transaction_kind": "postpaid",
                    "channel": "api",
                    "environment": "sandbox",
                    "status": "awaiting_confirmation",
                    "created_at": "2030-01-01T00:00:00Z",
                    "expires_at": "2030-01-01T00:05:00Z",
                    "confirmation_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
                    "version": 1,
                    "bill": {
                      "customer_name": "PELANGGAN SIMULASI",
                      "period": "203001",
                      "admin": 2500,
                      "selling_price": 52500,
                      "details": []
                    }
                  },
                  "inquiry": {
                    "id": "30000000-0000-4000-8000-000000000001",
                    "status": "succeeded",
                    "expires_at": "2030-01-01T00:05:00Z"
                  },
                  "meta": {
                    "environment": "sandbox",
                    "request_id": "10000000-0000-4000-8000-000000000001"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Key tidak berlaku",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Scope atau akun tidak diizinkan",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Periksa status, referensi atau quote",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Parameter tidak valid",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Batas akses; ikuti Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Layanan belum tersedia; jangan membuat pembelian baru",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Pertahankan UUID yang sama untuk retry payload yang sama."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InquiryRequest"
              }
            }
          }
        }
      }
    },
    "/postpaid/inquiries/{id}": {
      "get": {
        "operationId": "getInquiry",
        "summary": "Status cek tagihan",
        "tags": [
          "Transaksi"
        ],
        "x-scope": "orders:read",
        "responses": {
          "200": {
            "description": "Berhasil",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderResponse"
                },
                "example": {
                  "data": {
                    "id": "20000000-0000-4000-8000-000000000001",
                    "client_reference": "BILL-CONTOH-1001",
                    "product_code": "KODE_PENYEDIA_DARI_KATALOG",
                    "name": "PLN Pascabayar simulasi",
                    "destination": "********0000",
                    "price": 52500,
                    "charged": 0,
                    "currency": "IDR",
                    "transaction_kind": "postpaid",
                    "channel": "api",
                    "environment": "sandbox",
                    "status": "awaiting_confirmation",
                    "created_at": "2030-01-01T00:00:00Z",
                    "expires_at": "2030-01-01T00:05:00Z",
                    "confirmation_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
                    "version": 1,
                    "bill": {
                      "customer_name": "PELANGGAN SIMULASI",
                      "period": "203001",
                      "admin": 2500,
                      "selling_price": 52500,
                      "details": []
                    }
                  },
                  "inquiry": {
                    "id": "30000000-0000-4000-8000-000000000001",
                    "status": "succeeded",
                    "expires_at": "2030-01-01T00:05:00Z"
                  },
                  "meta": {
                    "environment": "sandbox",
                    "request_id": "10000000-0000-4000-8000-000000000001"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Key tidak berlaku",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Scope atau akun tidak diizinkan",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Periksa status, referensi atau quote",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Parameter tidak valid",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Batas akses; ikuti Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Layanan belum tersedia; jangan membuat pembelian baru",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ]
      }
    },
    "/orders": {
      "get": {
        "operationId": "listOrders",
        "summary": "Riwayat integrasi",
        "tags": [
          "Transaksi"
        ],
        "x-scope": "orders:read",
        "responses": {
          "200": {
            "description": "Berhasil",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrdersResponse"
                },
                "example": {
                  "data": [
                    {
                      "id": "20000000-0000-4000-8000-000000000001",
                      "client_reference": "ORDER-CONTOH-1001",
                      "product_code": "KODE_DARI_KATALOG",
                      "name": "Pulsa simulasi 5.000",
                      "destination": "********0000",
                      "price": 5050,
                      "charged": 5050,
                      "currency": "IDR",
                      "transaction_kind": "prepaid",
                      "channel": "api",
                      "environment": "sandbox",
                      "status": "succeeded",
                      "created_at": "2030-01-01T00:00:00Z",
                      "expires_at": "2030-01-01T00:05:00Z",
                      "confirmation_token": null,
                      "version": 2,
                      "bill": null
                    }
                  ],
                  "meta": {
                    "total": 1,
                    "page": 1,
                    "last_page": 1,
                    "environment": "sandbox",
                    "request_id": "10000000-0000-4000-8000-000000000001"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Key tidak berlaku",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Scope atau akun tidak diizinkan",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Periksa status, referensi atau quote",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Parameter tidak valid",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Batas akses; ikuti Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Layanan belum tersedia; jangan membuat pembelian baru",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50
            }
          },
          {
            "name": "client_reference",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/orders/{id}": {
      "get": {
        "operationId": "getOrder",
        "summary": "Status order yang sama",
        "tags": [
          "Transaksi"
        ],
        "x-scope": "orders:read",
        "responses": {
          "200": {
            "description": "Berhasil",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderResponse"
                },
                "example": {
                  "data": {
                    "id": "20000000-0000-4000-8000-000000000001",
                    "client_reference": "ORDER-CONTOH-1001",
                    "product_code": "KODE_DARI_KATALOG",
                    "name": "Pulsa simulasi 5.000",
                    "destination": "********0000",
                    "price": 5050,
                    "charged": 5050,
                    "currency": "IDR",
                    "transaction_kind": "prepaid",
                    "channel": "api",
                    "environment": "sandbox",
                    "status": "succeeded",
                    "created_at": "2030-01-01T00:00:00Z",
                    "expires_at": "2030-01-01T00:05:00Z",
                    "confirmation_token": null,
                    "version": 2,
                    "bill": null
                  },
                  "meta": {
                    "environment": "sandbox",
                    "request_id": "10000000-0000-4000-8000-000000000001"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Key tidak berlaku",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Scope atau akun tidak diizinkan",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Periksa status, referensi atau quote",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Parameter tidak valid",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Batas akses; ikuti Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Layanan belum tersedia; jangan membuat pembelian baru",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ]
      }
    },
    "/orders/{id}/confirm": {
      "post": {
        "operationId": "confirmOrder",
        "summary": "Konfirmasi dan bayar dari Saldo Rupiah",
        "tags": [
          "Transaksi"
        ],
        "x-scope": "orders:confirm",
        "responses": {
          "200": {
            "description": "Berhasil",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderResponse"
                },
                "example": {
                  "data": {
                    "id": "20000000-0000-4000-8000-000000000001",
                    "client_reference": "ORDER-CONTOH-1001",
                    "product_code": "KODE_DARI_KATALOG",
                    "name": "Pulsa simulasi 5.000",
                    "destination": "********0000",
                    "price": 5050,
                    "charged": 5050,
                    "currency": "IDR",
                    "transaction_kind": "prepaid",
                    "channel": "api",
                    "environment": "sandbox",
                    "status": "succeeded",
                    "created_at": "2030-01-01T00:00:00Z",
                    "expires_at": "2030-01-01T00:05:00Z",
                    "confirmation_token": null,
                    "version": 2,
                    "bill": null
                  },
                  "meta": {
                    "environment": "sandbox",
                    "request_id": "10000000-0000-4000-8000-000000000001"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Key tidak berlaku",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Scope atau akun tidak diizinkan",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Periksa status, referensi atau quote",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Parameter tidak valid",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Batas akses; ikuti Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Layanan belum tersedia; jangan membuat pembelian baru",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "202": {
            "description": "Diproses/pending. Baca order yang sama.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderResponse"
                },
                "example": {
                  "data": {
                    "id": "20000000-0000-4000-8000-000000000001",
                    "client_reference": "ORDER-CONTOH-1001",
                    "product_code": "KODE_DARI_KATALOG",
                    "name": "Pulsa simulasi 5.000",
                    "destination": "********0000",
                    "price": 5050,
                    "charged": 0,
                    "currency": "IDR",
                    "transaction_kind": "prepaid",
                    "channel": "api",
                    "environment": "sandbox",
                    "status": "processing",
                    "created_at": "2030-01-01T00:00:00Z",
                    "expires_at": "2030-01-01T00:05:00Z",
                    "confirmation_token": null,
                    "version": 2,
                    "bill": null
                  },
                  "meta": {
                    "environment": "sandbox",
                    "request_id": "10000000-0000-4000-8000-000000000001"
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Pertahankan UUID yang sama untuk retry payload yang sama."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ConfirmRequest"
              }
            }
          }
        }
      }
    },
    "/orders/{id}/cancel": {
      "post": {
        "operationId": "cancelOrder",
        "summary": "Batalkan order yang belum diproses",
        "tags": [
          "Transaksi"
        ],
        "x-scope": "orders:cancel",
        "responses": {
          "200": {
            "description": "Berhasil",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderResponse"
                },
                "example": {
                  "data": {
                    "id": "20000000-0000-4000-8000-000000000001",
                    "client_reference": "ORDER-CONTOH-1001",
                    "product_code": "KODE_DARI_KATALOG",
                    "name": "Pulsa simulasi 5.000",
                    "destination": "********0000",
                    "price": 5050,
                    "charged": 0,
                    "currency": "IDR",
                    "transaction_kind": "prepaid",
                    "channel": "api",
                    "environment": "sandbox",
                    "status": "cancelled",
                    "created_at": "2030-01-01T00:00:00Z",
                    "expires_at": "2030-01-01T00:05:00Z",
                    "confirmation_token": null,
                    "version": 2,
                    "bill": null
                  },
                  "meta": {
                    "environment": "sandbox",
                    "request_id": "10000000-0000-4000-8000-000000000001"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Key tidak berlaku",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Scope atau akun tidak diizinkan",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Periksa status, referensi atau quote",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Parameter tidak valid",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Batas akses; ikuti Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Layanan belum tersedia; jangan membuat pembelian baru",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Pertahankan UUID yang sama untuk retry payload yang sama."
          }
        ]
      }
    },
    "/orders/{id}/result": {
      "get": {
        "operationId": "getResult",
        "summary": "Hasil sukses yang privat",
        "tags": [
          "Transaksi"
        ],
        "x-scope": "results:read",
        "responses": {
          "200": {
            "description": "Berhasil",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResultResponse"
                },
                "example": {
                  "data": {
                    "order": {
                      "id": "20000000-0000-4000-8000-000000000001",
                      "client_reference": "ORDER-CONTOH-1001",
                      "product_code": "KODE_DARI_KATALOG",
                      "name": "Pulsa simulasi 5.000",
                      "destination": "********0000",
                      "price": 5050,
                      "charged": 5050,
                      "currency": "IDR",
                      "transaction_kind": "prepaid",
                      "channel": "api",
                      "environment": "sandbox",
                      "status": "succeeded",
                      "created_at": "2030-01-01T00:00:00Z",
                      "expires_at": "2030-01-01T00:05:00Z",
                      "confirmation_token": null,
                      "version": 2,
                      "bill": null
                    },
                    "serial": "SIMULASI-BUKAN-TOKEN-ATAU-VOUCHER"
                  },
                  "meta": {
                    "environment": "sandbox",
                    "request_id": "10000000-0000-4000-8000-000000000001"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Key tidak berlaku",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Scope atau akun tidak diizinkan",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Periksa status, referensi atau quote",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Parameter tidak valid",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Batas akses; ikuti Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Layanan belum tersedia; jangan membuat pembelian baru",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ]
      }
    },
    "/orders/{id}/resolve": {
      "post": {
        "operationId": "resolveSimulation",
        "summary": "Selesaikan simulasi pending",
        "tags": [
          "Sandbox"
        ],
        "x-scope": "orders:confirm",
        "responses": {
          "200": {
            "description": "Berhasil",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderResponse"
                },
                "example": {
                  "data": {
                    "id": "20000000-0000-4000-8000-000000000001",
                    "client_reference": "ORDER-CONTOH-1001",
                    "product_code": "KODE_DARI_KATALOG",
                    "name": "Pulsa simulasi 5.000",
                    "destination": "********0000",
                    "price": 5050,
                    "charged": 5050,
                    "currency": "IDR",
                    "transaction_kind": "prepaid",
                    "channel": "api",
                    "environment": "sandbox",
                    "status": "succeeded",
                    "created_at": "2030-01-01T00:00:00Z",
                    "expires_at": "2030-01-01T00:05:00Z",
                    "confirmation_token": null,
                    "version": 2,
                    "bill": null
                  },
                  "meta": {
                    "environment": "sandbox",
                    "request_id": "10000000-0000-4000-8000-000000000001"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Key tidak berlaku",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Scope atau akun tidak diizinkan",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Periksa status, referensi atau quote",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Parameter tidak valid",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Batas akses; ikuti Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Layanan belum tersedia; jangan membuat pembelian baru",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Pertahankan UUID yang sama untuk retry payload yang sama."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ResolveRequest"
              }
            }
          }
        },
        "x-environments": [
          "sandbox"
        ]
      }
    },
    "/scenarios/reset": {
      "post": {
        "operationId": "resetSimulation",
        "summary": "Reset saldo simulasi setelah semua hold selesai",
        "tags": [
          "Sandbox"
        ],
        "x-scope": "orders:confirm",
        "responses": {
          "200": {
            "description": "Berhasil",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResetResponse"
                },
                "example": {
                  "data": {
                    "balance": 1000000,
                    "currency": "IDR",
                    "simulated": true
                  },
                  "meta": {
                    "environment": "sandbox",
                    "request_id": "10000000-0000-4000-8000-000000000001"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Key tidak berlaku",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Scope atau akun tidak diizinkan",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Periksa status, referensi atau quote",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Parameter tidak valid",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Batas akses; ikuti Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Layanan belum tersedia; jangan membuat pembelian baru",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Pertahankan UUID yang sama untuk retry payload yang sama."
          }
        ],
        "x-environments": [
          "sandbox"
        ]
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "tp_test_… atau tp_live_…"
      }
    },
    "schemas": {
      "Meta": {
        "type": "object",
        "required": [
          "request_id",
          "environment"
        ],
        "properties": {
          "request_id": {
            "type": "string",
            "format": "uuid"
          },
          "environment": {
            "enum": [
              "live",
              "sandbox"
            ]
          },
          "total": {
            "type": "integer"
          },
          "page": {
            "type": "integer"
          },
          "last_page": {
            "type": "integer"
          }
        }
      },
      "Destination": {
        "type": "object",
        "minProperties": 1,
        "additionalProperties": {
          "type": "string",
          "maxLength": 64
        },
        "description": "Gunakan key dari fields katalog. Nomor/ID harus string agar nol awal tidak hilang.",
        "example": {
          "phone": "081200000000"
        }
      },
      "Product": {
        "type": "object",
        "required": [
          "code",
          "name",
          "fields",
          "available"
        ],
        "properties": {
          "id": {
            "type": "integer"
          },
          "code": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "category": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "brand": {
            "type": "string"
          },
          "region": {
            "type": [
              "string",
              "null"
            ]
          },
          "price": {
            "type": "integer",
            "minimum": 0,
            "description": "Rupiah bulat (IDR), bukan Kredit AI."
          },
          "admin_fee": {
            "type": "integer",
            "minimum": 0,
            "description": "Rupiah bulat (IDR), bukan Kredit AI."
          },
          "currency": {
            "const": "IDR"
          },
          "description": {
            "type": "string"
          },
          "available": {
            "type": "boolean"
          },
          "reason": {
            "type": [
              "string",
              "null"
            ]
          },
          "logo_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "fields": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "key",
                "label"
              ],
              "properties": {
                "key": {
                  "type": "string"
                },
                "label": {
                  "type": "string"
                },
                "input_mode": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "Order": {
        "type": "object",
        "required": [
          "id",
          "client_reference",
          "status",
          "price",
          "currency",
          "environment"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "client_reference": {
            "type": "string"
          },
          "product_code": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "destination": {
            "type": "string",
            "description": "Tujuan tersamarkan; aplikasi klien mempertahankan input tujuan untuk review."
          },
          "price": {
            "type": "integer",
            "minimum": 0,
            "description": "Rupiah bulat (IDR), bukan Kredit AI."
          },
          "charged": {
            "type": "integer",
            "minimum": 0,
            "description": "Rupiah bulat (IDR), bukan Kredit AI."
          },
          "currency": {
            "const": "IDR"
          },
          "transaction_kind": {
            "enum": [
              "prepaid",
              "postpaid"
            ]
          },
          "channel": {
            "const": "api"
          },
          "environment": {
            "enum": [
              "live",
              "sandbox"
            ]
          },
          "status": {
            "enum": [
              "awaiting_confirmation",
              "requote_required",
              "processing",
              "pending",
              "succeeded",
              "failed",
              "cancelled",
              "manual_review",
              "insufficient_credit"
            ]
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "confirmation_token": {
            "type": [
              "string",
              "null"
            ],
            "description": "Rahasia sementara; jangan dicatat di log."
          },
          "version": {
            "type": "integer"
          },
          "bill": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "customer_name": {
                "type": "string"
              },
              "period": {
                "type": "string"
              },
              "admin": {
                "type": "integer",
                "minimum": 0,
                "description": "Rupiah bulat (IDR), bukan Kredit AI."
              },
              "selling_price": {
                "type": "integer",
                "minimum": 0,
                "description": "Rupiah bulat (IDR), bukan Kredit AI."
              },
              "details": {
                "type": "array",
                "items": {
                  "type": "object"
                }
              }
            }
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "message",
          "error"
        ],
        "properties": {
          "message": {
            "type": "string"
          },
          "error": {
            "type": "object",
            "required": [
              "code",
              "request_id"
            ],
            "properties": {
              "code": {
                "type": "string"
              },
              "request_id": {
                "type": "string",
                "format": "uuid"
              },
              "action": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "data": {
            "$ref": "#/components/schemas/Order"
          },
          "meta": {
            "$ref": "#/components/schemas/Meta"
          }
        }
      },
      "CatalogResponse": {
        "type": "object",
        "required": [
          "data",
          "meta"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Product"
            }
          },
          "meta": {
            "$ref": "#/components/schemas/Meta"
          },
          "operator_prefixes": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          }
        }
      },
      "OrderResponse": {
        "type": "object",
        "properties": {
          "data": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Order"
              },
              {
                "type": "null"
              }
            ]
          },
          "meta": {
            "$ref": "#/components/schemas/Meta"
          },
          "inquiry": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "status": {
                "type": "string"
              },
              "expires_at": {
                "type": "string",
                "format": "date-time"
              }
            }
          }
        }
      },
      "OrdersResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Order"
            }
          },
          "meta": {
            "$ref": "#/components/schemas/Meta"
          }
        }
      },
      "WalletResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "balance": {
                "type": "integer",
                "minimum": 0,
                "description": "Rupiah bulat (IDR), bukan Kredit AI."
              },
              "held": {
                "type": "integer",
                "minimum": 0,
                "description": "Rupiah bulat (IDR), bukan Kredit AI."
              },
              "available": {
                "type": "integer",
                "minimum": 0,
                "description": "Rupiah bulat (IDR), bukan Kredit AI."
              },
              "currency": {
                "const": "IDR"
              },
              "simulated": {
                "type": "boolean"
              }
            }
          },
          "meta": {
            "$ref": "#/components/schemas/Meta"
          }
        }
      },
      "CapabilitiesResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "api_version": {
                "type": "string"
              },
              "currency": {
                "const": "IDR"
              },
              "transactions_available": {
                "type": "boolean"
              },
              "postpaid_available": {
                "type": "boolean"
              },
              "limits": {
                "type": "object",
                "properties": {
                  "transaction_rupiah": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "Rupiah bulat (IDR), bukan Kredit AI."
                  },
                  "daily_rupiah": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "Rupiah bulat (IDR), bukan Kredit AI."
                  },
                  "requests_per_minute": {
                    "type": "integer"
                  }
                }
              },
              "deposit_url": {
                "type": "string",
                "format": "uri"
              },
              "sandbox_scenarios": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "webhook_delivery": {
                "const": "at_least_once"
              }
            }
          },
          "meta": {
            "$ref": "#/components/schemas/Meta"
          }
        }
      },
      "QuoteRequest": {
        "type": "object",
        "required": [
          "product_code",
          "client_reference",
          "destination"
        ],
        "properties": {
          "product_code": {
            "type": "string",
            "pattern": "^[a-zA-Z0-9_-]{1,64}$"
          },
          "client_reference": {
            "type": "string",
            "maxLength": 64,
            "description": "ID pembelian di aplikasi Anda; jangan gunakan nomor HP atau ID pelanggan."
          },
          "destination": {
            "$ref": "#/components/schemas/Destination"
          },
          "scenario": {
            "type": "string",
            "enum": [
              "success",
              "pending",
              "failed",
              "insufficient_balance",
              "price_changed",
              "expired",
              "timeout",
              "manual_review"
            ],
            "description": "Hanya sandbox."
          }
        },
        "example": {
          "product_code": "KODE_DARI_KATALOG",
          "client_reference": "ORDER-CONTOH-1001",
          "destination": {
            "phone": "081200000000"
          }
        }
      },
      "InquiryRequest": {
        "type": "object",
        "required": [
          "product_code",
          "client_reference",
          "customer_no"
        ],
        "properties": {
          "product_code": {
            "type": "string"
          },
          "client_reference": {
            "type": "string",
            "maxLength": 64
          },
          "customer_no": {
            "type": "string",
            "maxLength": 64
          },
          "scenario": {
            "type": "string",
            "description": "Hanya sandbox."
          }
        },
        "example": {
          "product_code": "KODE_PENYEDIA_DARI_KATALOG",
          "client_reference": "BILL-CONTOH-1001",
          "customer_no": "001234567890"
        }
      },
      "ConfirmRequest": {
        "type": "object",
        "required": [
          "confirmation_token"
        ],
        "properties": {
          "confirmation_token": {
            "type": "string",
            "minLength": 32,
            "maxLength": 32
          }
        },
        "example": {
          "confirmation_token": "{{confirmation_token}}"
        }
      },
      "WebhookEvent": {
        "type": "object",
        "required": [
          "id",
          "type",
          "created_at",
          "environment",
          "data"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "type": {
            "const": "order.status_changed"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "environment": {
            "enum": [
              "live",
              "sandbox"
            ]
          },
          "data": {
            "type": "object",
            "required": [
              "id",
              "client_reference",
              "status",
              "version"
            ],
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "client_reference": {
                "type": "string"
              },
              "status": {
                "type": "string"
              },
              "version": {
                "type": "integer"
              },
              "transaction_kind": {
                "enum": [
                  "prepaid",
                  "postpaid"
                ]
              }
            }
          }
        }
      },
      "ResultResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "order": {
                "$ref": "#/components/schemas/Order"
              },
              "serial": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Hanya pemilik melalui scope results:read; tidak ada pada webhook."
              }
            }
          },
          "meta": {
            "$ref": "#/components/schemas/Meta"
          }
        }
      },
      "ResolveRequest": {
        "type": "object",
        "required": [
          "status"
        ],
        "properties": {
          "status": {
            "enum": [
              "succeeded",
              "failed"
            ]
          }
        },
        "example": {
          "status": "succeeded"
        }
      },
      "ResetResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "balance": {
                "type": "integer",
                "minimum": 0,
                "description": "Rupiah bulat (IDR), bukan Kredit AI."
              },
              "currency": {
                "const": "IDR"
              },
              "simulated": {
                "const": true
              }
            }
          },
          "meta": {
            "$ref": "#/components/schemas/Meta"
          }
        }
      }
    }
  },
  "webhooks": {
    "orderStatus": {
      "post": {
        "summary": "Perubahan status; deduplikasi event ID dan abaikan versi lama.",
        "parameters": [
          {
            "name": "X-TurboPulsa-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "t=UNIX_TIMESTAMP,v1=HMAC_SHA256(timestamp + \".\" + rawBody). Toleransi 300 detik."
          },
          {
            "name": "X-TurboPulsa-Event-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Event diterima; proses deduplikasi sebelum tindakan bisnis."
          }
        }
      }
    }
  }
}
