{
  "openapi": "3.0.3",
  "info": {
    "title": "TRONENS API",
    "version": "3.0.0",
    "description": "TRONENS public API v1 for TRON Energy pricing, estimation, single and bulk order creation, status, balance and webhooks."
  },
  "servers": [
    {
      "url": "https://tronens.com"
    }
  ],
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "TRONENS API key"
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "success",
          "error"
        ],
        "properties": {
          "success": {
            "type": "boolean",
            "example": false
          },
          "error": {
            "type": "string",
            "example": "INVALID_TRON_ADDRESS"
          }
        }
      },
      "QuoteData": {
        "type": "object",
        "required": [
          "type",
          "energy_amount",
          "duration_minutes",
          "base_price_trx",
          "discount_percent",
          "discount_trx",
          "price_trx"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "package",
              "custom"
            ],
            "description": "Quote type."
          },
          "package_id": {
            "type": "integer",
            "nullable": true,
            "description": "Package ID for package quotes."
          },
          "name": {
            "type": "string",
            "nullable": true,
            "description": "Package name for package quotes."
          },
          "energy_amount": {
            "type": "integer",
            "example": 65000
          },
          "duration_minutes": {
            "type": "integer",
            "example": 60
          },
          "base_price_trx": {
            "type": "number",
            "format": "double",
            "description": "Price before account discount.",
            "example": 1.961
          },
          "discount_percent": {
            "type": "number",
            "format": "double",
            "example": 0
          },
          "discount_trx": {
            "type": "number",
            "format": "double",
            "example": 0
          },
          "price_trx": {
            "type": "number",
            "format": "double",
            "description": "Final amount charged to the customer.",
            "example": 2.05
          }
        }
      },
      "QuoteResponse": {
        "type": "object",
        "required": [
          "success",
          "data"
        ],
        "properties": {
          "success": {
            "type": "boolean",
            "example": true
          },
          "data": {
            "$ref": "#/components/schemas/QuoteData"
          }
        }
      },
      "RecommendedPackage": {
        "type": "object",
        "required": [
          "id",
          "name",
          "energy_amount",
          "duration_minutes"
        ],
        "properties": {
          "id": {
            "type": "integer",
            "example": 1
          },
          "name": {
            "type": "string",
            "example": "65 000 Energy"
          },
          "energy_amount": {
            "type": "integer",
            "example": 65000
          },
          "duration_minutes": {
            "type": "integer",
            "example": 15
          }
        }
      },
      "EstimateRequest": {
        "type": "object",
        "required": [
          "recipient_address"
        ],
        "properties": {
          "recipient_address": {
            "type": "string",
            "example": "T..."
          },
          "has_usdt": {
            "type": "boolean",
            "nullable": true,
            "description": "Optional hint whether a USDT TRC20 operation is planned."
          }
        }
      },
      "EstimateData": {
        "type": "object",
        "required": [
          "estimated_energy",
          "recommended_package"
        ],
        "properties": {
          "estimated_energy": {
            "type": "integer",
            "example": 65000
          },
          "recommended_package": {
            "allOf": [
              {
                "$ref": "#/components/schemas/RecommendedPackage"
              }
            ],
            "nullable": true
          }
        }
      },
      "EstimateResponse": {
        "type": "object",
        "required": [
          "success",
          "data"
        ],
        "properties": {
          "success": {
            "type": "boolean",
            "example": true
          },
          "data": {
            "$ref": "#/components/schemas/EstimateData"
          }
        }
      },
      "OrderCreate": {
        "type": "object",
        "required": [
          "address"
        ],
        "properties": {
          "external_id": {
            "type": "string",
            "maxLength": 128,
            "pattern": "^[A-Za-z0-9._:\\-]+$",
            "description": "Customer-side idempotency key."
          },
          "package_id": {
            "type": "integer",
            "description": "Use package_id OR energy_amount."
          },
          "energy_amount": {
            "type": "integer",
            "description": "Use energy_amount OR package_id."
          },
          "duration_minutes": {
            "type": "integer"
          },
          "address": {
            "type": "string",
            "description": "Recipient TRON address."
          }
        },
        "oneOf": [
          {
            "required": [
              "package_id"
            ]
          },
          {
            "required": [
              "energy_amount"
            ]
          }
        ]
      },
      "OrderCreateData": {
        "type": "object",
        "required": [
          "order_id",
          "external_id",
          "status",
          "idempotent"
        ],
        "properties": {
          "order_id": {
            "type": "integer",
            "example": 123
          },
          "external_id": {
            "type": "string",
            "nullable": true,
            "example": "merchant_93481"
          },
          "status": {
            "type": "string",
            "example": "processing"
          },
          "idempotent": {
            "type": "boolean",
            "description": "True when the existing order for this external_id was returned.",
            "example": false
          }
        }
      },
      "OrderCreateResponse": {
        "type": "object",
        "required": [
          "success",
          "data"
        ],
        "properties": {
          "success": {
            "type": "boolean",
            "example": true
          },
          "data": {
            "$ref": "#/components/schemas/OrderCreateData"
          }
        }
      },
      "OrderStatusData": {
        "type": "object",
        "required": [
          "id",
          "external_id",
          "address",
          "energy_amount",
          "duration_minutes",
          "price_trx",
          "status",
          "txid",
          "refunded",
          "error_code",
          "created_at",
          "delivered_at",
          "completed_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "integer",
            "example": 123
          },
          "external_id": {
            "type": "string",
            "nullable": true,
            "example": "merchant_93481"
          },
          "address": {
            "type": "string",
            "example": "T..."
          },
          "energy_amount": {
            "type": "integer",
            "example": 65000
          },
          "duration_minutes": {
            "type": "integer",
            "example": 15
          },
          "price_trx": {
            "type": "number",
            "format": "double",
            "example": 1.14
          },
          "status": {
            "type": "string",
            "enum": [
              "processing",
              "delegating",
              "delegated",
              "undelegating",
              "completed",
              "review",
              "failed"
            ]
          },
          "txid": {
            "type": "string",
            "nullable": true,
            "description": "Delegation transaction id when available."
          },
          "refunded": {
            "type": "boolean",
            "example": false
          },
          "error_code": {
            "type": "string",
            "nullable": true,
            "description": "ORDER_REVIEW, ORDER_FAILED or null."
          },
          "created_at": {
            "type": "string",
            "example": "2026-10-03 18:01:00"
          },
          "delivered_at": {
            "type": "string",
            "nullable": true,
            "example": "2026-10-03 18:01:12"
          },
          "completed_at": {
            "type": "string",
            "nullable": true
          },
          "updated_at": {
            "type": "string",
            "example": "2026-10-03 18:01:12"
          }
        }
      },
      "OrderStatusResponse": {
        "type": "object",
        "required": [
          "success",
          "data"
        ],
        "properties": {
          "success": {
            "type": "boolean",
            "example": true
          },
          "data": {
            "$ref": "#/components/schemas/OrderStatusData"
          }
        }
      },
      "BalanceData": {
        "type": "object",
        "required": [
          "balance_trx"
        ],
        "properties": {
          "balance_trx": {
            "type": "number",
            "format": "double",
            "example": 125.5
          }
        }
      },
      "BalanceResponse": {
        "type": "object",
        "required": [
          "success",
          "data"
        ],
        "properties": {
          "success": {
            "type": "boolean",
            "example": true
          },
          "data": {
            "$ref": "#/components/schemas/BalanceData"
          }
        }
      },
      "WebhookOrderData": {
        "type": "object",
        "required": [
          "order_id",
          "external_id",
          "address",
          "energy_amount",
          "duration_minutes",
          "price_trx",
          "status",
          "txid",
          "refunded",
          "error_code",
          "created_at",
          "delivered_at",
          "completed_at",
          "updated_at"
        ],
        "properties": {
          "order_id": {
            "type": "integer",
            "example": 123
          },
          "external_id": {
            "type": "string",
            "nullable": true,
            "example": "merchant_93481"
          },
          "address": {
            "type": "string",
            "example": "T..."
          },
          "energy_amount": {
            "type": "integer",
            "example": 65000
          },
          "duration_minutes": {
            "type": "integer",
            "example": 15
          },
          "price_trx": {
            "type": "number",
            "format": "double",
            "example": 1.14
          },
          "status": {
            "type": "string",
            "enum": [
              "processing",
              "delegating",
              "delegated",
              "undelegating",
              "completed",
              "review",
              "failed"
            ]
          },
          "txid": {
            "type": "string",
            "nullable": true
          },
          "refunded": {
            "type": "boolean",
            "example": false
          },
          "error_code": {
            "type": "string",
            "nullable": true,
            "description": "ORDER_REVIEW, ORDER_FAILED or null."
          },
          "created_at": {
            "type": "string"
          },
          "delivered_at": {
            "type": "string",
            "nullable": true
          },
          "completed_at": {
            "type": "string",
            "nullable": true
          },
          "updated_at": {
            "type": "string"
          }
        }
      },
      "WebhookPayload": {
        "type": "object",
        "required": [
          "event",
          "event_id",
          "created_at",
          "data"
        ],
        "properties": {
          "event": {
            "type": "string",
            "enum": [
              "order.processing",
              "order.delegating",
              "order.delegated",
              "order.undelegating",
              "order.completed",
              "order.review",
              "order.failed"
            ]
          },
          "event_id": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "data": {
            "$ref": "#/components/schemas/WebhookOrderData"
          }
        }
      }
    }
  },
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "paths": {
    "/api/v1/quote/": {
      "get": {
        "summary": "Get customer quote",
        "description": "Returns the customer price for the selected Energy amount and duration.",
        "parameters": [
          {
            "in": "query",
            "name": "package_id",
            "schema": {
              "type": "integer"
            },
            "description": "Package ID. Use package_id or energy_amount."
          },
          {
            "in": "query",
            "name": "energy_amount",
            "schema": {
              "type": "integer"
            },
            "description": "Custom Energy amount. Use energy_amount or package_id."
          },
          {
            "in": "query",
            "name": "duration_minutes",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Quote",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuoteResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Package not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "Method not allowed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Temporarily unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/estimate/": {
      "post": {
        "summary": "Estimate Energy requirement",
        "description": "Returns estimated Energy and an optional recommended package.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EstimateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Energy estimate",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EstimateResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "Method not allowed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Request too large",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid TRON address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Temporarily unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/order/": {
      "post": {
        "summary": "Create idempotent Energy order",
        "description": "Creates a real order. Use external_id for safe retries.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrderCreate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Existing idempotent order returned",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderCreateResponse"
                }
              }
            }
          },
          "202": {
            "description": "New order accepted for asynchronous processing",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderCreateResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Insufficient balance",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Package not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "Method not allowed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Request too large",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/status/": {
      "get": {
        "summary": "Get sanitized public order status",
        "parameters": [
          {
            "in": "query",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "TRONENS order ID. Use id or external_id."
          },
          {
            "in": "query",
            "name": "external_id",
            "schema": {
              "type": "string",
              "maxLength": 128
            },
            "description": "Customer order ID. Use external_id or id."
          }
        ],
        "responses": {
          "200": {
            "description": "Order status",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderStatusResponse"
                }
              }
            }
          },
          "400": {
            "description": "id or external_id required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "Method not allowed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid external_id",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Temporarily unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/balance/": {
      "get": {
        "summary": "Get TRX balance",
        "responses": {
          "200": {
            "description": "Balance",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BalanceResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "Method not allowed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Temporarily unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/orders/bulk/": {
      "post": {
        "summary": "Create up to 50 Energy orders",
        "description": "Creates 1–50 orders. Each item is processed independently and should include external_id for idempotency. Requires orders:create.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "orders"
                ],
                "properties": {
                  "orders": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 50,
                    "items": {
                      "type": "object",
                      "required": [
                        "external_id",
                        "address"
                      ],
                      "properties": {
                        "external_id": {
                          "type": "string",
                          "maxLength": 120,
                          "description": "Idempotency key unique per account."
                        },
                        "address": {
                          "type": "string",
                          "example": "T..."
                        },
                        "package_id": {
                          "type": "integer",
                          "minimum": 1
                        },
                        "energy_amount": {
                          "type": "integer",
                          "minimum": 1
                        },
                        "duration_minutes": {
                          "type": "integer",
                          "enum": [
                            5,
                            10,
                            15,
                            60
                          ],
                          "default": 15
                        }
                      },
                      "description": "Provide package_id or energy_amount."
                    }
                  }
                }
              },
              "example": {
                "orders": [
                  {
                    "external_id": "bulk-001",
                    "package_id": 1,
                    "duration_minutes": 15,
                    "address": "T..."
                  },
                  {
                    "external_id": "bulk-002",
                    "energy_amount": 65000,
                    "duration_minutes": 60,
                    "address": "T..."
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "All valid items accepted"
          },
          "207": {
            "description": "Partial success; inspect each result"
          },
          "400": {
            "description": "Invalid request body"
          },
          "401": {
            "description": "Invalid or missing API key"
          },
          "403": {
            "description": "Missing orders:create permission or IP not allowed"
          },
          "422": {
            "description": "No item could be accepted"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        }
      }
    }
  },
  "x-webhooks": {
    "order-events": {
      "description": "Configured per account. POST JSON signed with X-Webhook-Signature: sha256=HMAC_SHA256(raw_json_body, webhook_secret). HTTP 2xx acknowledges delivery. Temporary failures are retried up to 8 times.",
      "schema": {
        "$ref": "#/components/schemas/WebhookPayload"
      }
    }
  }
}
