{
  "openapi": "3.1.0",
  "info": {
    "title": "TJP Cloud API",
    "version": "1.0.0",
    "description": "Trade and read MetaTrader 5 accounts hosted on TJP Cloud.\n\n**Authentication**: `Authorization: Bearer tjpc_live_…` (create keys in TradeJournal Pro → TJP Cloud API). Read-only keys never trade.\n\n**Writes are idempotent**: every write (POST/PUT/PATCH/DELETE) needs a unique `Idempotency-Key` (8–200 characters). Retrying with the same key returns the first answer (`Idempotent-Replayed: true`) and never trades twice. A `503` with `uncertain: true` means the broker may have executed the request: check positions, or retry with the SAME key.\n\n**Live stream**: connect a WebSocket to `/v1/stream` (header `Authorization: Bearer …`, or `?token=` in browsers), then send `{\"type\":\"subscribe\",\"accountId\":\"…\",\"channels\":[\"ticks\",\"trades\",\"account\",\"status\"],\"symbols\":[\"EURUSD\"]}`. Messages: `tick`, `trade` (deal), `position`, `order`, `account`, `broker`, `status`. The key is checked again every 30 s: a revoked key's stream closes with code 4401, and an account the key can no longer use is dropped with `{\"type\":\"unsubscribed\",\"reason\":\"ACCOUNT_NOT_FOUND\"}`.\n\n**Webhooks**: events are POSTed to your endpoint with `X-TJP-Signature: t=<unix>,v1=<hex>`, where v1 = HMAC-SHA256(secret, `<t>.<raw body>`).\n\n**Limits**: per key, bursts of 100 reads (30/s sustained) and 20 writes (5/s sustained); `429` responses carry `Retry-After`."
  },
  "servers": [
    {
      "url": "https://api.tradejournalpro.net"
    }
  ],
  "security": [
    {
      "bearer": []
    }
  ],
  "tags": [
    {
      "name": "Accounts"
    },
    {
      "name": "Trading"
    },
    {
      "name": "Market data"
    },
    {
      "name": "History"
    },
    {
      "name": "Service"
    }
  ],
  "paths": {
    "/v1/health": {
      "get": {
        "tags": [
          "Service"
        ],
        "security": [],
        "summary": "Liveness",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "const": true
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/status": {
      "get": {
        "tags": [
          "Service"
        ],
        "security": [],
        "summary": "Public service summary",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServiceStatus"
                }
              }
            }
          }
        }
      }
    },
    "/v1/openapi.json": {
      "get": {
        "tags": [
          "Service"
        ],
        "security": [],
        "summary": "This document",
        "responses": {
          "200": {
            "description": "OpenAPI document"
          }
        }
      }
    },
    "/v1/accounts": {
      "get": {
        "tags": [
          "Accounts"
        ],
        "summary": "Accounts this key can use",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "accounts": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Account"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/accounts/{accountId}": {
      "get": {
        "tags": [
          "Accounts"
        ],
        "summary": "Account, terminal connection and live balance",
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "account": {
                      "allOf": [
                        {
                          "$ref": "#/components/schemas/Account"
                        },
                        {
                          "type": "object",
                          "properties": {
                            "info": {
                              "oneOf": [
                                {
                                  "$ref": "#/components/schemas/AccountInfo"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            }
                          }
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/accounts/{accountId}/positions": {
      "get": {
        "tags": [
          "Trading"
        ],
        "summary": "Open positions",
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "positions": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Position"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Offline"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "delete": {
        "tags": [
          "Trading"
        ],
        "summary": "Close every matching position",
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "name": "symbol",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "side",
            "in": "query",
            "schema": {
              "enum": [
                "buy",
                "sell"
              ]
            }
          }
        ],
        "responses": {
          "207": {
            "description": "One result per position",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "results": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "ticket": {
                            "type": "string"
                          },
                          "status": {
                            "type": "integer"
                          },
                          "body": {}
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/ReadOnlyKey"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Offline"
          },
          "422": {
            "$ref": "#/components/responses/BrokerRejected"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Uncertain"
          }
        }
      }
    },
    "/v1/accounts/{accountId}/positions/{ticket}": {
      "patch": {
        "tags": [
          "Trading"
        ],
        "summary": "Change stop loss / take profit",
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "ticket",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[1-9][0-9]{0,19}$"
            },
            "description": "Broker ticket (string: MT tickets exceed JavaScript's safe integers)."
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProtectionChange"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TradeResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/ReadOnlyKey"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Offline"
          },
          "422": {
            "$ref": "#/components/responses/BrokerRejected"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Uncertain"
          }
        }
      },
      "delete": {
        "tags": [
          "Trading"
        ],
        "summary": "Close (or partially close) a position",
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "ticket",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[1-9][0-9]{0,19}$"
            },
            "description": "Broker ticket (string: MT tickets exceed JavaScript's safe integers)."
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "volume": {
                    "type": "number",
                    "exclusiveMinimum": 0,
                    "description": "Lots to close; omit to close all."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TradeResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/ReadOnlyKey"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Offline"
          },
          "422": {
            "$ref": "#/components/responses/BrokerRejected"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Uncertain"
          }
        }
      }
    },
    "/v1/accounts/{accountId}/rules": {
      "get": {
        "tags": [
          "Trading"
        ],
        "summary": "Protection rules running in the terminal (MT5)",
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "rules": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ProtectionRules"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Offline"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "501": {
            "$ref": "#/components/responses/NotOnPlatform"
          }
        }
      }
    },
    "/v1/accounts/{accountId}/positions/{ticket}/rules": {
      "put": {
        "tags": [
          "Trading"
        ],
        "summary": "Set breakeven, trailing stop and partial take-profits for a position (run by the terminal)",
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "ticket",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[1-9][0-9]{0,19}$"
            },
            "description": "Broker ticket (string: MT tickets exceed JavaScript's safe integers)."
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProtectionRulesRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "$ref": "#/components/schemas/ProtectionRules"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/ReadOnlyKey"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Offline"
          },
          "422": {
            "$ref": "#/components/responses/BrokerRejected"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "501": {
            "$ref": "#/components/responses/NotOnPlatform"
          },
          "503": {
            "$ref": "#/components/responses/Uncertain"
          }
        }
      },
      "delete": {
        "tags": [
          "Trading"
        ],
        "summary": "Remove a position's protection rules",
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "ticket",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[1-9][0-9]{0,19}$"
            },
            "description": "Broker ticket (string: MT tickets exceed JavaScript's safe integers)."
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "result": {
                      "type": "object",
                      "properties": {
                        "ticket": {
                          "type": "string"
                        },
                        "cleared": {
                          "type": "boolean"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/ReadOnlyKey"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Offline"
          },
          "422": {
            "$ref": "#/components/responses/BrokerRejected"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Uncertain"
          }
        }
      }
    },
    "/v1/accounts/{accountId}/orders": {
      "get": {
        "tags": [
          "Trading"
        ],
        "summary": "Pending orders",
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "orders": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Order"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Offline"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "tags": [
          "Trading"
        ],
        "summary": "Place a market or pending order",
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrderRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Accepted by the broker",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TradeResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/ReadOnlyKey"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Offline"
          },
          "422": {
            "$ref": "#/components/responses/BrokerRejected"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Uncertain"
          }
        }
      }
    },
    "/v1/accounts/{accountId}/orders/{ticket}": {
      "patch": {
        "tags": [
          "Trading"
        ],
        "summary": "Move a pending order",
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "ticket",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[1-9][0-9]{0,19}$"
            },
            "description": "Broker ticket (string: MT tickets exceed JavaScript's safe integers)."
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PendingChange"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TradeResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/ReadOnlyKey"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Offline"
          },
          "422": {
            "$ref": "#/components/responses/BrokerRejected"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Uncertain"
          }
        }
      },
      "delete": {
        "tags": [
          "Trading"
        ],
        "summary": "Cancel a pending order",
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "ticket",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[1-9][0-9]{0,19}$"
            },
            "description": "Broker ticket (string: MT tickets exceed JavaScript's safe integers)."
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TradeResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/ReadOnlyKey"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Offline"
          },
          "422": {
            "$ref": "#/components/responses/BrokerRejected"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Uncertain"
          }
        }
      }
    },
    "/v1/bulk/orders": {
      "post": {
        "tags": [
          "Trading"
        ],
        "summary": "Place one order on up to 50 accounts",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "accountIds",
                  "order"
                ],
                "properties": {
                  "accountIds": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 50,
                    "items": {
                      "type": "string",
                      "format": "uuid"
                    }
                  },
                  "order": {
                    "$ref": "#/components/schemas/OrderRequest"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "207": {
            "description": "One result per account",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "results": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "accountId": {
                            "type": "string"
                          },
                          "status": {
                            "type": "integer"
                          },
                          "body": {}
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/ReadOnlyKey"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/accounts/{accountId}/symbols": {
      "get": {
        "tags": [
          "Market data"
        ],
        "summary": "All symbols of the broker",
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "symbols": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Offline"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/accounts/{accountId}/symbols/{symbol}": {
      "get": {
        "tags": [
          "Market data"
        ],
        "summary": "Symbol specification (tick size and value, volume limits)",
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "symbol",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "symbol": {
                      "$ref": "#/components/schemas/SymbolSpec"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Offline"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/accounts/{accountId}/quotes/{symbol}": {
      "get": {
        "tags": [
          "Market data"
        ],
        "summary": "Current bid/ask",
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "symbol",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "quote": {
                      "$ref": "#/components/schemas/Quote"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Offline"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/accounts/{accountId}/candles": {
      "get": {
        "tags": [
          "Market data"
        ],
        "summary": "Price history (bars)",
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "symbol",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "timeframe",
            "in": "query",
            "schema": {
              "enum": [
                "M1",
                "M5",
                "M15",
                "M30",
                "H1",
                "H4",
                "D1",
                "W1",
                "MN1"
              ],
              "default": "H1"
            }
          },
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "count",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 5000
            },
            "description": "Bars ending at `to` (when `from` is not given)."
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "candles": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Candle"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Offline"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/accounts/{accountId}/deals": {
      "get": {
        "tags": [
          "History"
        ],
        "summary": "Deals (fills, deposits, charges)",
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Default: 7 days before `to`."
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Default: now. At most 93 days after `from`."
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "deals": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Deal"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Offline"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/accounts/{accountId}/history-orders": {
      "get": {
        "tags": [
          "History"
        ],
        "summary": "Finished orders",
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Default: 7 days before `to`."
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Default: now. At most 93 days after `from`."
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "orders": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/HistoryOrder"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Offline"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearer": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "tjpc_live_<id>_<secret>"
      }
    },
    "parameters": {
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": true,
        "schema": {
          "type": "string",
          "pattern": "^[A-Za-z0-9_.:-]{8,200}$"
        },
        "description": "Unique per intended action. A retry with the same key never repeats the action."
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Invalid request; nothing was sent",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Missing, invalid or revoked key",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotFound": {
        "description": "Unknown account, ticket or symbol (accounts the key may not use look missing)",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Offline": {
        "description": "The account's terminal is not connected (nothing was sent), or the same Idempotency-Key is still running",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "RateLimited": {
        "description": "Too many requests; see Retry-After",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "ReadOnlyKey": {
        "description": "This key cannot trade (READ_ONLY_KEY), or, during the beta, the account is not a demo account (LIVE_TRADING_DISABLED: new orders only)",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "BrokerRejected": {
        "description": "The broker refused the request (see retcode), or the Idempotency-Key was used for a different request",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Uncertain": {
        "description": "The outcome is not confirmed (uncertain: true). Check positions; retry only with the same Idempotency-Key",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotOnPlatform": {
        "description": "Not available on this account's platform (protection rules are MT5 only)",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              },
              "retcode": {
                "type": "integer",
                "description": "MetaTrader trade server return code"
              }
            }
          },
          "uncertain": {
            "type": "boolean"
          }
        }
      },
      "ServiceStatus": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "terminalsOnline": {
            "type": "integer"
          },
          "hosts": {
            "type": "integer"
          },
          "hostsReachable": {
            "type": "integer"
          },
          "lastPassAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "checkedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Account": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "label": {
            "type": "string"
          },
          "platform": {
            "enum": [
              "mt4",
              "mt5"
            ]
          },
          "server": {
            "type": "string"
          },
          "login": {
            "type": "string",
            "description": "Last digits only"
          },
          "state": {
            "enum": [
              "pending",
              "starting",
              "running",
              "broker_offline",
              "auth_failed",
              "stopped",
              "sleeping",
              "error",
              "no_capacity",
              "unknown"
            ]
          },
          "lastError": {
            "type": [
              "string",
              "null"
            ]
          },
          "connection": {
            "type": "object",
            "properties": {
              "online": {
                "type": "boolean"
              },
              "brokerConnected": {
                "type": "boolean"
              },
              "connectedAt": {
                "type": "string",
                "format": "date-time"
              },
              "lastSeenAt": {
                "type": "string",
                "format": "date-time"
              },
              "server": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          }
        }
      },
      "AccountInfo": {
        "type": "object",
        "properties": {
          "login": {
            "type": "integer"
          },
          "server": {
            "type": "string"
          },
          "company": {
            "type": "string"
          },
          "currency": {
            "type": "string"
          },
          "balance": {
            "type": "number"
          },
          "equity": {
            "type": "number"
          },
          "margin": {
            "type": "number"
          },
          "freeMargin": {
            "type": "number"
          },
          "marginLevel": {
            "type": "number"
          },
          "leverage": {
            "type": "integer"
          },
          "marginMode": {
            "enum": [
              "hedging",
              "netting",
              "exchange"
            ]
          },
          "accountType": {
            "enum": [
              "demo",
              "real",
              "contest"
            ]
          },
          "tradeAllowed": {
            "type": "boolean"
          }
        }
      },
      "Position": {
        "type": "object",
        "properties": {
          "ticket": {
            "type": "string"
          },
          "symbol": {
            "type": "string"
          },
          "side": {
            "enum": [
              "buy",
              "sell"
            ]
          },
          "volume": {
            "type": "number"
          },
          "openPrice": {
            "type": "number"
          },
          "stopLoss": {
            "type": [
              "number",
              "null"
            ]
          },
          "takeProfit": {
            "type": [
              "number",
              "null"
            ]
          },
          "profit": {
            "type": "number"
          },
          "swap": {
            "type": "number"
          },
          "comment": {
            "type": "string"
          },
          "magic": {
            "type": "integer"
          },
          "openTime": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Order": {
        "type": "object",
        "properties": {
          "ticket": {
            "type": "string"
          },
          "symbol": {
            "type": "string"
          },
          "type": {
            "enum": [
              "buy_limit",
              "sell_limit",
              "buy_stop",
              "sell_stop",
              "buy_stop_limit",
              "sell_stop_limit"
            ]
          },
          "volume": {
            "type": "number"
          },
          "price": {
            "type": "number"
          },
          "stopLoss": {
            "type": [
              "number",
              "null"
            ]
          },
          "takeProfit": {
            "type": [
              "number",
              "null"
            ]
          },
          "expiresAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "comment": {
            "type": "string"
          },
          "setupTime": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "OrderRequest": {
        "type": "object",
        "required": [
          "side",
          "symbol",
          "volume"
        ],
        "properties": {
          "side": {
            "enum": [
              "buy",
              "sell"
            ]
          },
          "type": {
            "enum": [
              "market",
              "limit",
              "stop"
            ],
            "default": "market"
          },
          "symbol": {
            "type": "string"
          },
          "volume": {
            "type": "number",
            "exclusiveMinimum": 0
          },
          "price": {
            "type": "number",
            "exclusiveMinimum": 0,
            "description": "Required for limit and stop orders"
          },
          "stopLoss": {
            "type": "number",
            "exclusiveMinimum": 0
          },
          "takeProfit": {
            "type": "number",
            "exclusiveMinimum": 0
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "Pending orders only"
          },
          "clientOrderId": {
            "type": "string",
            "pattern": "^[A-Za-z0-9_.:-]{1,31}$",
            "description": "Stored as the order comment"
          }
        }
      },
      "ProtectionChange": {
        "type": "object",
        "properties": {
          "stopLoss": {
            "type": [
              "number",
              "null"
            ],
            "exclusiveMinimum": 0,
            "description": "Stop loss price; null removes it, omit to keep it."
          },
          "takeProfit": {
            "type": [
              "number",
              "null"
            ],
            "exclusiveMinimum": 0,
            "description": "Take profit price; null removes it, omit to keep it."
          }
        }
      },
      "PendingChange": {
        "type": "object",
        "properties": {
          "price": {
            "type": "number",
            "exclusiveMinimum": 0
          },
          "stopLoss": {
            "type": [
              "number",
              "null"
            ],
            "exclusiveMinimum": 0,
            "description": "Stop loss price; null removes it, omit to keep it."
          },
          "takeProfit": {
            "type": [
              "number",
              "null"
            ],
            "exclusiveMinimum": 0,
            "description": "Take profit price; null removes it, omit to keep it."
          },
          "expiresAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "null = good till cancelled"
          }
        }
      },
      "TradeResult": {
        "type": "object",
        "properties": {
          "result": {
            "type": "object",
            "properties": {
              "retcode": {
                "type": "integer"
              },
              "order": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "deal": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "position": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "price": {
                "type": "number"
              },
              "volume": {
                "type": "number"
              },
              "closedVolume": {
                "type": "number"
              },
              "remainingVolume": {
                "type": "number"
              }
            }
          }
        }
      },
      "ProtectionRulesRequest": {
        "type": "object",
        "description": "Rules the terminal itself applies on every price change, even while our servers are unreachable. Points are the symbol's point size.",
        "properties": {
          "breakeven": {
            "type": "object",
            "required": [
              "triggerPoints"
            ],
            "properties": {
              "triggerPoints": {
                "type": "number",
                "minimum": 1,
                "description": "Profit (points) that moves the stop to entry"
              },
              "offsetPoints": {
                "type": "number",
                "minimum": 0,
                "description": "Points beyond entry to lock in"
              }
            }
          },
          "trailing": {
            "type": "object",
            "required": [
              "distancePoints"
            ],
            "properties": {
              "startPoints": {
                "type": "number",
                "minimum": 0,
                "description": "Profit (points) that starts trailing"
              },
              "distancePoints": {
                "type": "number",
                "minimum": 1
              },
              "stepPoints": {
                "type": "number",
                "minimum": 1,
                "default": 1
              }
            }
          },
          "takeProfits": {
            "type": "array",
            "maxItems": 5,
            "items": {
              "type": "object",
              "required": [
                "price"
              ],
              "properties": {
                "price": {
                  "type": "number",
                  "exclusiveMinimum": 0
                },
                "volume": {
                  "type": "number",
                  "exclusiveMinimum": 0,
                  "description": "Lots to close; omit to close the rest"
                }
              }
            }
          }
        }
      },
      "ProtectionRules": {
        "type": "object",
        "properties": {
          "ticket": {
            "type": "string"
          },
          "breakeven": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "triggerPoints": {
                "type": "number"
              },
              "offsetPoints": {
                "type": "number"
              },
              "done": {
                "type": "boolean"
              }
            }
          },
          "trailing": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "startPoints": {
                "type": "number"
              },
              "distancePoints": {
                "type": "number"
              },
              "stepPoints": {
                "type": "number"
              }
            }
          },
          "takeProfits": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "price": {
                  "type": "number"
                },
                "volume": {
                  "type": "number"
                },
                "done": {
                  "type": "boolean"
                }
              }
            }
          }
        }
      },
      "SymbolSpec": {
        "type": "object",
        "properties": {
          "symbol": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "digits": {
            "type": "integer"
          },
          "point": {
            "type": "number"
          },
          "tickSize": {
            "type": "number"
          },
          "tickValue": {
            "type": "number"
          },
          "contractSize": {
            "type": "number"
          },
          "volumeMin": {
            "type": "number"
          },
          "volumeMax": {
            "type": "number"
          },
          "volumeStep": {
            "type": "number"
          },
          "tradeMode": {
            "enum": [
              "full",
              "long_only",
              "short_only",
              "close_only",
              "disabled"
            ]
          },
          "stopsLevel": {
            "type": "integer"
          },
          "currencyBase": {
            "type": "string"
          },
          "currencyProfit": {
            "type": "string"
          },
          "currencyMargin": {
            "type": "string"
          }
        }
      },
      "Quote": {
        "type": "object",
        "properties": {
          "symbol": {
            "type": "string"
          },
          "bid": {
            "type": "number"
          },
          "ask": {
            "type": "number"
          },
          "time": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Candle": {
        "type": "object",
        "properties": {
          "time": {
            "type": "string",
            "format": "date-time"
          },
          "open": {
            "type": "number"
          },
          "high": {
            "type": "number"
          },
          "low": {
            "type": "number"
          },
          "close": {
            "type": "number"
          },
          "tickVolume": {
            "type": "integer"
          },
          "spread": {
            "type": "integer"
          }
        }
      },
      "Deal": {
        "type": "object",
        "properties": {
          "ticket": {
            "type": "string"
          },
          "order": {
            "type": [
              "string",
              "null"
            ]
          },
          "position": {
            "type": [
              "string",
              "null"
            ]
          },
          "symbol": {
            "type": "string"
          },
          "type": {
            "enum": [
              "buy",
              "sell",
              "balance",
              "credit",
              "bonus",
              "commission",
              "other"
            ]
          },
          "entry": {
            "enum": [
              "in",
              "out",
              "inout",
              "out_by",
              "other"
            ]
          },
          "volume": {
            "type": "number"
          },
          "price": {
            "type": "number"
          },
          "profit": {
            "type": "number"
          },
          "commission": {
            "type": "number"
          },
          "swap": {
            "type": "number"
          },
          "fee": {
            "type": "number"
          },
          "magic": {
            "type": "integer"
          },
          "comment": {
            "type": "string"
          },
          "time": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "HistoryOrder": {
        "type": "object",
        "properties": {
          "ticket": {
            "type": "string"
          },
          "position": {
            "type": [
              "string",
              "null"
            ]
          },
          "symbol": {
            "type": "string"
          },
          "type": {
            "type": "string"
          },
          "state": {
            "enum": [
              "filled",
              "cancelled",
              "rejected",
              "expired",
              "partial",
              "placed",
              "started",
              "other"
            ]
          },
          "volume": {
            "type": "number"
          },
          "price": {
            "type": "number"
          },
          "comment": {
            "type": "string"
          },
          "setupTime": {
            "type": "string",
            "format": "date-time"
          },
          "doneTime": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      }
    }
  }
}
