{
  "openapi": "3.1.0",
  "info": {
    "title": "Loopscale API",
    "version": "0.1.0"
  },
  "servers": [
    {
      "url": "https://tars.loopscale.com/v1",
      "description": "Loopscale Production Server"
    }
  ],
  "paths": {
    "/markets/strategy/create": {
      "post": {
        "tags": [
          "strategy"
        ],
        "operationId": "query_create_strategy",
        "parameters": [
          {
            "name": "Idempotent-Key",
            "in": "header",
            "description": "Optional idempotency key; a retried write with the same key replays the original response",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TxnCreateStrategyParams"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "One or more serialized transactions needed to create and fund the strategy.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/VersionedTransactionReturn"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Idempotency-Key reused with a different request body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "summary": "Create strategy",
        "description": "Creates a new lending strategy, deposits the initial principal amount, and may return multiple transactions when lookup-table setup or external yield account initialization is required."
      }
    },
    "/markets/strategy/deposit": {
      "post": {
        "tags": [
          "strategy"
        ],
        "operationId": "query_deposit_strategy",
        "parameters": [
          {
            "name": "Idempotent-Key",
            "in": "header",
            "description": "Optional idempotency key; a retried write with the same key replays the original response",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TxnDepositStrategyParams"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Serialized transaction for the strategy deposit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VersionedTransactionReturn"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Idempotency-Key reused with a different request body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "summary": "Deposit into strategy",
        "description": "Deposits additional principal into an existing lending strategy."
      }
    },
    "/markets/strategy/withdraw": {
      "post": {
        "tags": [
          "strategy"
        ],
        "operationId": "query_withdraw_strategy",
        "parameters": [
          {
            "name": "Idempotent-Key",
            "in": "header",
            "description": "Optional idempotency key; a retried write with the same key replays the original response",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TxnWithdrawStrategyParams"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Serialized transaction for the strategy withdrawal.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VersionedTransactionReturn"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Idempotency-Key reused with a different request body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "summary": "Withdraw from strategy",
        "description": "Withdraws principal from an existing lending strategy, optionally closing out the full position."
      }
    },
    "/markets/strategy/update": {
      "post": {
        "tags": [
          "strategy"
        ],
        "operationId": "query_update_strategy",
        "parameters": [
          {
            "name": "Idempotent-Key",
            "in": "header",
            "description": "Optional idempotency key; a retried write with the same key replays the original response",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateStrategyQueryParams"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "One or more serialized transactions needed to apply the strategy update.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/VersionedTransactionReturn"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Idempotency-Key reused with a different request body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "summary": "Update strategy",
        "description": "Updates strategy settings and collateral terms. Large collateral-term updates may be split across multiple returned transactions."
      }
    },
    "/markets/strategy/close/{strategy}": {
      "post": {
        "tags": [
          "strategy"
        ],
        "operationId": "route_close_strategy",
        "parameters": [
          {
            "name": "strategy",
            "in": "path",
            "description": "Strategy account address to close",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotent-Key",
            "in": "header",
            "description": "Optional idempotency key; a retried write with the same key replays the original response",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Serialized transaction for closing the strategy.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VersionedTransactionReturn"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Idempotency-Key reused with a different request body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "summary": "Close strategy",
        "description": "Closes an existing lending strategy and returns the serialized transaction required to do so."
      }
    }
  },
  "components": {
    "schemas": {
      "AddCollateralArgs": {
        "type": "object",
        "required": [
          "durationsAndApys"
        ],
        "properties": {
          "durationsAndApys": {
            "type": "object",
            "description": "Request map of serialized-duration → apy, both as strings.",
            "additionalProperties": {
              "type": "string"
            },
            "propertyNames": {
              "type": "string"
            }
          },
          "externalMarketInformationAddress": {
            "type": [
              "string",
              "null"
            ]
          },
          "marketInformation": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/ParsedUpdateAssetDataParams",
                "description": "Parsed asset-data params (ignored for base vaults / custom strategy)."
              }
            ]
          }
        }
      },
      "CollateralAllocationUpdateArgs": {
        "type": "object",
        "required": [
          "assetIdentifier",
          "maxAllocationPct"
        ],
        "properties": {
          "assetIdentifier": {
            "type": "string"
          },
          "maxAllocationPct": {
            "type": "string"
          }
        }
      },
      "CollateralParamsUpdateArgs": {
        "type": "object",
        "properties": {
          "apyUpdate": {
            "type": [
              "object",
              "null"
            ],
            "description": "Request map of serialized-duration → apy, both as strings.",
            "additionalProperties": {
              "type": "string"
            },
            "propertyNames": {
              "type": "string"
            }
          },
          "ltvUpdate": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/ParsedUpdateAssetDataParams",
                "description": "Parsed asset-data params."
              }
            ]
          }
        }
      },
      "CollateralTermsIndicesSchema": {
        "type": "object",
        "description": "A single (collateral, duration) slot the strategy offers terms for.",
        "required": [
          "collateralIndex",
          "durationIndex"
        ],
        "properties": {
          "collateralIndex": {
            "type": "integer",
            "format": "int32",
            "description": "Index into the market's collateral map.",
            "minimum": 0
          },
          "durationIndex": {
            "type": "integer",
            "format": "int32",
            "description": "Index into the strategy's offered durations.",
            "minimum": 0
          }
        }
      },
      "EditStrategySettingsArgs": {
        "type": "object",
        "properties": {
          "externalYieldSource": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/ExternalYieldSourceParams"
              }
            ]
          },
          "interestFee": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "minimum": 0
          },
          "liquidityBuffer": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "minimum": 0
          },
          "originationCap": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "minimum": 0
          },
          "originationFee": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "minimum": 0
          },
          "originationsEnabled": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "principalFee": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "minimum": 0
          }
        }
      },
      "ErrorDetails": {
        "type": "object",
        "description": "Inner detail of the [`ErrorResponse`] envelope.",
        "required": [
          "code",
          "message"
        ],
        "properties": {
          "code": {
            "type": "integer",
            "format": "int32",
            "description": "HTTP status code, mirrored in the response status line",
            "example": 400,
            "minimum": 0
          },
          "message": {
            "type": "string",
            "description": "human-readable, client-safe message (sensitive data redacted)",
            "example": "Request could not be processed."
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "description": "Canonical error envelope for every endpoint. The `x-request-id` response\nheader carries the correlation id for the failing request.",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "$ref": "#/components/schemas/ErrorDetails",
            "description": "error detail"
          }
        }
      },
      "ExternalYieldSourceParams": {
        "type": "object",
        "required": [
          "newExternalYieldSource"
        ],
        "properties": {
          "newExternalYieldSource": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          }
        }
      },
      "MultiCollateralTermsUpdateParamsSchema": {
        "type": "object",
        "description": "One APY applied across a set of (collateral, duration) slots\n(`update_multi_collateral_terms`).",
        "required": [
          "apy",
          "indices"
        ],
        "properties": {
          "apy": {
            "type": "integer",
            "format": "int64",
            "description": "APY in basis points of a hundredth (cbps).",
            "minimum": 0
          },
          "indices": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CollateralTermsIndicesSchema"
            },
            "description": "(collateral, duration) slots this APY applies to."
          }
        }
      },
      "ParsedUpdateAssetDataParams": {
        "type": "object",
        "description": "Parsed per-collateral asset-data / oracle config update (LTV, liquidation\nthreshold, oracle account/type, allocation cap).",
        "required": [
          "assetIdentifier"
        ],
        "properties": {
          "assetIdentifier": {
            "type": "string"
          },
          "liquidationThreshold": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "minimum": 0
          },
          "ltv": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "minimum": 0
          },
          "maxAge": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "minimum": 0
          },
          "maxCollateralAllocationPct": {
            "type": [
              "string",
              "null"
            ]
          },
          "maxUncertainty": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "minimum": 0
          },
          "oracleAccount": {
            "type": [
              "string",
              "null"
            ]
          },
          "oracleType": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "minimum": 0
          },
          "quoteMint": {
            "type": [
              "string",
              "null"
            ]
          },
          "removeCollateral": {
            "type": [
              "boolean",
              "null"
            ]
          }
        }
      },
      "RemoveCollateralArgs": {
        "type": "object",
        "required": [
          "durations",
          "removeFromMarketInformation"
        ],
        "properties": {
          "durations": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/StrategyDuration"
            }
          },
          "removeFromMarketInformation": {
            "type": "boolean"
          }
        }
      },
      "StrategyCollateralUpdates": {
        "type": "object",
        "properties": {
          "addCollateral": {
            "type": "object",
            "additionalProperties": {
              "$ref": "#/components/schemas/AddCollateralArgs"
            },
            "propertyNames": {
              "type": "string"
            }
          },
          "removeCollateral": {
            "type": "object",
            "additionalProperties": {
              "$ref": "#/components/schemas/RemoveCollateralArgs"
            },
            "propertyNames": {
              "type": "string"
            }
          },
          "updateAssetAllocation": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CollateralAllocationUpdateArgs"
            }
          },
          "updateCollateral": {
            "type": "object",
            "additionalProperties": {
              "$ref": "#/components/schemas/CollateralParamsUpdateArgs"
            },
            "propertyNames": {
              "type": "string"
            }
          }
        }
      },
      "StrategyDuration": {
        "type": "object",
        "required": [
          "duration",
          "durationType"
        ],
        "properties": {
          "duration": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          },
          "durationType": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          }
        }
      },
      "TxnCreateStrategyParams": {
        "type": "object",
        "required": [
          "principalMint",
          "lender",
          "amount"
        ],
        "properties": {
          "amount": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          },
          "collateralTerms": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MultiCollateralTermsUpdateParamsSchema"
            }
          },
          "externalYieldSourceArgs": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/TxnExternalYieldSourceArgs"
              }
            ]
          },
          "interestFee": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          },
          "lender": {
            "type": "string"
          },
          "liquidityBuffer": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          },
          "marketInformation": {
            "type": [
              "string",
              "null"
            ]
          },
          "originationCap": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          },
          "originationFee": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          },
          "originationsEnabled": {
            "type": "boolean"
          },
          "principalMint": {
            "type": "string"
          }
        }
      },
      "TxnDepositStrategyParams": {
        "type": "object",
        "required": [
          "strategy",
          "amount"
        ],
        "properties": {
          "amount": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          },
          "strategy": {
            "type": "string"
          }
        }
      },
      "TxnExternalYieldSourceArgs": {
        "type": "object",
        "required": [
          "newExternalYieldSource",
          "createExternalYieldAccount"
        ],
        "properties": {
          "createExternalYieldAccount": {
            "type": "boolean"
          },
          "newExternalYieldSource": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          }
        }
      },
      "TxnWithdrawStrategyParams": {
        "type": "object",
        "required": [
          "strategy",
          "amount",
          "withdrawAll"
        ],
        "properties": {
          "amount": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          },
          "strategy": {
            "type": "string"
          },
          "withdrawAll": {
            "type": "boolean"
          }
        }
      },
      "UpdateStrategyQueryParams": {
        "type": "object",
        "required": [
          "strategy"
        ],
        "properties": {
          "collateralTerms": {
            "$ref": "#/components/schemas/StrategyCollateralUpdates"
          },
          "strategy": {
            "type": "string"
          },
          "updateParams": {
            "$ref": "#/components/schemas/EditStrategySettingsArgs"
          }
        }
      },
      "VersionedTransactionReturn": {
        "type": "object",
        "description": "versioned txn return",
        "required": [
          "message",
          "signatures"
        ],
        "properties": {
          "message": {
            "type": "string",
            "description": "serialized message"
          },
          "signatures": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/VersionedTransactionSignature"
            },
            "description": "serialized signatures"
          }
        }
      },
      "VersionedTransactionSignature": {
        "type": "object",
        "description": "versioned txn return",
        "required": [
          "publicKey",
          "signature"
        ],
        "properties": {
          "publicKey": {
            "type": "string",
            "description": "serialized message"
          },
          "signature": {
            "type": "string",
            "description": "serialized signatures"
          }
        }
      }
    }
  }
}
