{
  "openapi": "3.0.3",
  "info": {
    "title": "IlmFun Official Platform & Partner API",
    "version": "2.0.0",
    "description": "Complete machine-to-machine REST API specification for the IlmFun ecosystem (`https://docs.ilmfun.com`). Covers Payment Service Provider (PSP) top-ups & cashout settlements, Segregated Reserve Float accounting, Partner Shop & Storefront catalog management, HMAC-SHA256 real-time purchase webhooks, and Emerald-backed Sponsored Quests."
  },
  "servers": [
    {
      "url": "https://partner.ilmfun.com/api/v1",
      "description": "Dedicated Partner Network API Gateway (Recommended)"
    },
    {
      "url": "https://partner.ilmfun.com/api/v1/payment-provider",
      "description": "Payment Provider API Alias"
    }
  ],
  "security": [
    {
      "PartnerKey": []
    }
  ],
  "tags": [
    { "name": "Account & Metadata", "description": "Partner provider status, reserve float balances, and ISO 4217 currency minor units." },
    { "name": "Payments & Orders", "description": "Customer eligibility lookup, Emerald top-up invoicing, and atomic order state transitions." },
    { "name": "Partner Shop & Webhooks", "description": "Global & Partner Shop catalog CRUD, automated digital/webhook provisioning, and customer order fulfillment." },
    { "name": "Sponsored Quests", "description": "Emerald-backed learning quests, Telegram channel verification, timed video/web sessions, and completion logs." }
  ],
  "paths": {
    "/currencies": {
      "get": {
        "tags": ["Account & Metadata"],
        "summary": "ISO 4217 minor-unit exponent map",
        "security": [],
        "responses": {
          "200": {
            "description": "Currency minor-unit table",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CurrencyTable" }
              }
            }
          }
        }
      }
    },
    "/account": {
      "get": {
        "tags": ["Account & Metadata"],
        "summary": "Authenticated partner provider account, contract rates, limits, and reserve float",
        "responses": {
          "200": {
            "description": "Provider account summary",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ProviderAccount" }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Error" },
          "403": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/users/{username}": {
      "get": {
        "tags": ["Payments & Orders"],
        "summary": "Look up an IlmFun user by username for top-up or payout eligibility",
        "parameters": [
          {
            "name": "username",
            "in": "path",
            "required": true,
            "schema": { "type": "string", "minLength": 1, "maxLength": 80 }
          }
        ],
        "responses": {
          "200": {
            "description": "Recipient lookup result",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/UserLookup" }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Error" },
          "403": { "$ref": "#/components/responses/Error" },
          "404": { "$ref": "#/components/responses/Error" },
          "429": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/topups": {
      "post": {
        "tags": ["Payments & Orders"],
        "summary": "Create an Emerald top-up order backed by partner reserve float",
        "parameters": [
          { "$ref": "#/components/parameters/IdempotencyKey" }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/TopupRequest" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Created or idempotently replayed top-up order",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": ["order"],
                  "properties": {
                    "order": { "$ref": "#/components/schemas/PartnerOrder" }
                  }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/Error" },
          "401": { "$ref": "#/components/responses/Error" },
          "403": { "$ref": "#/components/responses/Error" },
          "409": { "$ref": "#/components/responses/Error" },
          "429": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/orders": {
      "get": {
        "tags": ["Payments & Orders"],
        "summary": "List partner payment orders",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": ["pending", "review", "authorized", "processing", "reported_paid", "completed", "failed_review", "disputed", "cancelled", "expired", "rejected", "refunded"]
            }
          },
          {
            "name": "before",
            "in": "query",
            "required": false,
            "schema": { "$ref": "#/components/schemas/Snowflake" }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 100 }
          }
        ],
        "responses": {
          "200": {
            "description": "Orders list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": ["orders"],
                  "properties": {
                    "orders": {
                      "type": "array",
                      "items": { "$ref": "#/components/schemas/PartnerOrder" }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/orders/{id}": {
      "get": {
        "tags": ["Payments & Orders"],
        "summary": "Fetch a single partner payment order",
        "parameters": [
          { "$ref": "#/components/parameters/OrderID" }
        ],
        "responses": {
          "200": {
            "description": "Order detail",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": ["order"],
                  "properties": {
                    "order": { "$ref": "#/components/schemas/PartnerOrder" },
                    "customer": { "$ref": "#/components/schemas/CustomerSnapshot" }
                  }
                }
              }
            }
          },
          "404": { "$ref": "#/components/responses/Error" }
        }
      },
      "post": {
        "tags": ["Payments & Orders"],
        "summary": "Atomically claim, complete, cancel, or fail a partner payment order",
        "parameters": [
          { "$ref": "#/components/parameters/OrderID" }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/OrderTransitionRequest" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated order",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": ["order"],
                  "properties": {
                    "order": { "$ref": "#/components/schemas/PartnerOrder" }
                  }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/Error" },
          "409": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/shop/items": {
      "get": {
        "tags": ["Partner Shop & Webhooks"],
        "summary": "List all shop items owned by your partner account",
        "responses": {
          "200": {
            "description": "Partner shop items and stats",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": { "type": "array", "items": { "$ref": "#/components/schemas/ShopItem" } },
                    "stats": { "$ref": "#/components/schemas/ShopStats" }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": ["Partner Shop & Webhooks"],
        "summary": "Create a new sellable item, voucher, course, or webhook-backed service in the Global Shop",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/ShopItemCreateRequest" }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created shop item",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "item": { "$ref": "#/components/schemas/ShopItem" }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/shop/items/{id}": {
      "put": {
        "tags": ["Partner Shop & Webhooks"],
        "summary": "Update an existing partner shop item",
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/ShopItemCreateRequest" }
            }
          }
        },
        "responses": {
          "200": { "description": "Updated shop item" }
        }
      },
      "delete": {
        "tags": ["Partner Shop & Webhooks"],
        "summary": "Delete a partner shop item",
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": { "description": "Deleted status" }
        }
      }
    },
    "/shop/items/{id}/toggle": {
      "post": {
        "tags": ["Partner Shop & Webhooks"],
        "summary": "Pause or resume a partner shop item",
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": { "description": "Toggled active status" }
        }
      }
    },
    "/shop/orders": {
      "get": {
        "tags": ["Partner Shop & Webhooks"],
        "summary": "List customer purchase orders for your partner shop items",
        "responses": {
          "200": {
            "description": "Partner shop orders",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "orders": { "type": "array", "items": { "$ref": "#/components/schemas/ShopOrder" } }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/shop/orders/{id}/fulfill": {
      "post": {
        "tags": ["Partner Shop & Webhooks"],
        "summary": "Fulfill a customer shop order, deliver a dynamic voucher/license code, or refund Emeralds",
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/ShopOrderFulfillRequest" }
            }
          }
        },
        "responses": {
          "200": { "description": "Updated shop order" }
        }
      }
    },
    "/quests": {
      "get": {
        "tags": ["Sponsored Quests"],
        "summary": "List all sponsored quests owned by your partner account",
        "responses": {
          "200": {
            "description": "Partner quests and completion stats",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "quests": { "type": "array", "items": { "$ref": "#/components/schemas/Quest" } },
                    "stats": { "$ref": "#/components/schemas/QuestStats" }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": ["Sponsored Quests"],
        "summary": "Create a new Emerald-backed sponsored quest campaign",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/QuestCreateRequest" }
            }
          }
        },
        "responses": {
          "201": { "description": "Created quest campaign" },
          "400": { "$ref": "#/components/responses/Error" },
          "409": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/quests/{id}": {
      "put": {
        "tags": ["Sponsored Quests"],
        "summary": "Update an existing partner quest campaign",
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/QuestCreateRequest" }
            }
          }
        },
        "responses": {
          "200": { "description": "Updated quest campaign" }
        }
      },
      "delete": {
        "tags": ["Sponsored Quests"],
        "summary": "Delete a partner quest campaign and refund unspent escrowed Emeralds",
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": { "description": "Deleted quest and refunded unspent budget" }
        }
      }
    },
    "/quests/{id}/toggle": {
      "post": {
        "tags": ["Sponsored Quests"],
        "summary": "Pause or resume a partner quest campaign",
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": { "description": "Toggled quest active status" }
        }
      }
    },
    "/quests/{id}/completions": {
      "get": {
        "tags": ["Sponsored Quests"],
        "summary": "Fetch verified learner completion logs for a quest",
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": { "description": "List of verified completions" }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "PartnerKey": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "ifp_<secret>",
        "description": "Server-to-server secret key (`ifp_...`) issued in the Partner Portal."
      }
    },
    "parameters": {
      "OrderID": {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": { "type": "string" }
      },
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": true,
        "schema": {
          "type": "string",
          "minLength": 8,
          "maxLength": 128,
          "pattern": "^[A-Za-z0-9_-]{8,128}$"
        }
      }
    },
    "responses": {
      "Error": {
        "description": "Structured machine-readable error",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": ["error", "code"],
              "properties": {
                "error": { "type": "string" },
                "code": { "type": "string" }
              }
            }
          }
        }
      }
    },
    "schemas": {
      "Snowflake": {
        "type": "string",
        "pattern": "^[1-9][0-9]{0,19}$",
        "description": "64-bit identifier serialized as a string."
      },
      "CurrencyTable": {
        "type": "object",
        "required": ["minor_units", "source"],
        "properties": {
          "minor_units": {
            "type": "object",
            "additionalProperties": { "type": "integer", "minimum": 0, "maximum": 4 }
          },
          "source": { "type": "string" }
        }
      },
      "ProviderAccount": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "name": { "type": "string" },
          "legal_name": { "type": "string" },
          "country": { "type": "string", "minLength": 2, "maxLength": 2 },
          "currency": { "type": "string", "minLength": 3, "maxLength": 3 },
          "currency_decimals": { "type": "integer", "minimum": 0, "maximum": 4 },
          "type": { "type": "string", "enum": ["contracted_agent", "authorized_merchant", "licensed_psp", "quest_partner", "merchant_partner"] },
          "status": { "type": "string", "enum": ["draft", "approved", "active", "suspended", "terminated"] },
          "topup": { "type": "boolean" },
          "withdraw": { "type": "boolean" },
          "refunds": { "type": "boolean" },
          "refund_days": { "type": "integer" },
          "deposit_rate": { "type": "integer" },
          "topup_rate": { "type": "integer" },
          "payout_rate": { "type": "integer" },
          "min_amount": { "type": "integer" },
          "max_amount": { "type": "integer" },
          "daily_limit": { "type": "integer" },
          "user_daily_limit": { "type": "integer" },
          "float_limit": { "type": "integer" },
          "available": { "type": "integer" },
          "customer_liability": { "type": "integer" },
          "settled_total": { "type": "integer" },
          "scopes": { "type": "string" },
          "contract_expires_at": { "type": "string", "format": "date-time" }
        }
      },
      "UserLookup": {
        "type": "object",
        "required": ["id", "username", "display_name", "payment_ready", "balance_shared"],
        "properties": {
          "id": { "$ref": "#/components/schemas/Snowflake" },
          "username": { "type": "string" },
          "display_name": { "type": "string" },
          "avatar_url": { "type": "string" },
          "payment_ready": { "type": "boolean" },
          "balance_shared": { "type": "boolean" },
          "emeralds": { "type": "integer" },
          "withdrawable_emeralds": { "type": "integer" }
        }
      },
      "TopupRequest": {
        "type": "object",
        "required": ["username", "amount", "external_reference"],
        "properties": {
          "username": { "type": "string" },
          "amount": { "type": "integer", "minimum": 1 },
          "fiat_minor": { "type": "integer", "minimum": 1 },
          "currency": { "type": "string", "minLength": 3, "maxLength": 3 },
          "external_reference": { "type": "string", "minLength": 3, "maxLength": 160 }
        }
      },
      "OrderTransitionRequest": {
        "type": "object",
        "required": ["action"],
        "properties": {
          "action": { "type": "string", "enum": ["claim", "complete", "cancel", "fail"] },
          "verification_reference": { "type": "string" },
          "reference": { "type": "string" },
          "fiat_minor": { "type": "integer", "minimum": 1 },
          "currency": { "type": "string", "minLength": 3, "maxLength": 3 },
          "reason": { "type": "string" },
          "note": { "type": "string" }
        }
      },
      "PartnerOrder": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "provider_id": { "type": "string" },
          "user_id": { "$ref": "#/components/schemas/Snowflake" },
          "username": { "type": "string" },
          "kind": { "type": "string", "enum": ["topup", "withdrawal", "refund"] },
          "amount": { "type": "integer" },
          "fiat_minor": { "type": "integer" },
          "currency": { "type": "string" },
          "currency_decimals": { "type": "integer" },
          "status": { "type": "string" },
          "external_reference": { "type": "string" },
          "verification_reference": { "type": "string" },
          "created_at": { "type": "string", "format": "date-time" },
          "updated_at": { "type": "string", "format": "date-time" }
        }
      },
      "CustomerSnapshot": {
        "type": "object",
        "properties": {
          "user_id": { "$ref": "#/components/schemas/Snowflake" },
          "legal_name": { "type": "string" },
          "country": { "type": "string" },
          "address": { "type": "string" },
          "city": { "type": "string" },
          "postal_code": { "type": "string" },
          "contact": { "type": "string" }
        }
      },
      "ShopItemCreateRequest": {
        "type": "object",
        "required": ["title", "price_emeralds"],
        "properties": {
          "category": { "type": "string", "enum": ["voucher", "course", "ebook", "kit", "merch", "service", "digital"] },
          "delivery_type": { "type": "string", "enum": ["instant", "manual", "service"] },
          "service_type": { "type": "string", "enum": ["none", "webhook_custom"] },
          "webhook_url": { "type": "string", "format": "uri" },
          "webhook_secret": { "type": "string" },
          "title": { "type": "string" },
          "description": { "type": "string" },
          "icon": { "type": "string" },
          "image_url": { "type": "string" },
          "price_emeralds": { "type": "integer", "minimum": 1 },
          "stock": { "type": "integer", "default": -1 },
          "max_per_user": { "type": "integer", "default": 1 },
          "delivery_content": { "type": "string" },
          "action_url": { "type": "string" },
          "requires_contact": { "type": "boolean" }
        }
      },
      "ShopItem": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "scope": { "type": "string" },
          "partner_account_id": { "type": "string" },
          "partner_name": { "type": "string" },
          "partner_verified": { "type": "boolean" },
          "category": { "type": "string" },
          "delivery_type": { "type": "string" },
          "service_type": { "type": "string" },
          "webhook_url": { "type": "string" },
          "title": { "type": "string" },
          "description": { "type": "string" },
          "price_emeralds": { "type": "integer" },
          "stock": { "type": "integer" },
          "sold_count": { "type": "integer" },
          "is_active": { "type": "boolean" }
        }
      },
      "ShopStats": {
        "type": "object",
        "properties": {
          "total_items": { "type": "integer" },
          "active_items": { "type": "integer" },
          "total_orders": { "type": "integer" },
          "pending_orders": { "type": "integer" },
          "emeralds_revenue": { "type": "integer" }
        }
      },
      "ShopOrder": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "item_id": { "type": "string" },
          "item_title": { "type": "string" },
          "buyer_user_id": { "type": "integer" },
          "buyer_username": { "type": "string" },
          "buyer_display_name": { "type": "string" },
          "quantity": { "type": "integer" },
          "price_emeralds": { "type": "integer" },
          "status": { "type": "string", "enum": ["pending", "processing", "fulfilled", "refunded", "cancelled"] },
          "delivery_content": { "type": "string" },
          "buyer_contact": { "type": "string" },
          "buyer_note": { "type": "string" },
          "fulfillment_note": { "type": "string" },
          "created_at": { "type": "string", "format": "date-time" }
        }
      },
      "ShopOrderFulfillRequest": {
        "type": "object",
        "required": ["status"],
        "properties": {
          "status": { "type": "string", "enum": ["processing", "fulfilled", "refunded"] },
          "delivery_content": { "type": "string" },
          "fulfillment_note": { "type": "string" }
        }
      },
      "QuestCreateRequest": {
        "type": "object",
        "required": ["title", "type", "reward_emeralds", "max_completions"],
        "properties": {
          "title": { "type": "string" },
          "description": { "type": "string" },
          "type": { "type": "string", "enum": ["telegram_join", "video_watch", "web_visit", "academy_join"] },
          "reward_emeralds": { "type": "integer", "minimum": 1, "maximum": 10000 },
          "max_completions": { "type": "integer", "minimum": 1 },
          "frequency": { "type": "string", "enum": ["once", "daily"] },
          "telegram_channel_id": { "type": "string" },
          "telegram_invite_url": { "type": "string" },
          "target_url": { "type": "string" },
          "required_seconds": { "type": "integer" },
          "academy_id": { "type": "integer" }
        }
      },
      "Quest": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "title": { "type": "string" },
          "description": { "type": "string" },
          "type": { "type": "string" },
          "reward_emeralds": { "type": "integer" },
          "max_completions": { "type": "integer" },
          "current_completions": { "type": "integer" },
          "is_active": { "type": "boolean" }
        }
      },
      "QuestStats": {
        "type": "object",
        "properties": {
          "active_quests": { "type": "integer" },
          "total_completions": { "type": "integer" },
          "emeralds_distributed": { "type": "integer" }
        }
      }
    }
  }
}
