Skip to main content
This section explains how to move positions from one subaccount to another within the same main account using the API. Before calling any private method you must authenticate.
Please refer to API Authentication Guide for more information regarding authentication.
This method requires main account authorization. The API token used must have the mainaccount scope to perform position moves between subaccounts.

Prerequisites

  • Both the source and destination subaccounts must belong to the same main account
  • The API key must have trade:read_write scope
  • The API key must have mainaccount scope for moving positions between subaccounts
  • You need the subaccount IDs (UIDs) which can be found in My Account >> Subaccounts tab

Rate limits

This method has distinct API rate limiting requirements: Sustained rate: 6 requests/minute. For more information, see Rate Limits.
If you exceed the rate limit, you will receive error code 13780 (move_positions_over_limit) with a wait parameter indicating how many seconds you should wait before trying again.

Moving positions

To move positions from a source subaccount to a target subaccount, use the private/move_positions method.

Example Request

{
  "jsonrpc": "2.0",
  "method": "private/move_positions",
  "params": {
    "currency": "BTC",
    "source_uid": 3,
    "target_uid": 23,
    "trades": [
      {
        "instrument_name": "BTC-PERPETUAL",
        "price": "35800",
        "amount": "110"
      },
      {
        "instrument_name": "BTC-28JAN22-32500-C",
        "amount": "0.1"
      }
    ]
  },
  "id": 1
}

Parameters

  • currency (optional): The currency symbol to filter positions. If not specified, positions for all currencies will be considered.
  • source_uid (required): ID of the source subaccount. Can be found in My Account >> Subaccounts tab.
  • target_uid (required): ID of the target subaccount. Can be found in My Account >> Subaccounts tab.
  • trades (required): Array of trade objects specifying which positions to move. Each trade object can contain:
    • instrument_name (required): The instrument name (e.g., “BTC-PERPETUAL”, “BTC-28JAN22-32500-C”)
    • amount (required): The amount/quantity of the position to move
    • price (optional): The price at which to move the position. If not specified, Deribit defaults to using the average entry price of the position.

Response

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": [
    {
      "target_uid": 23,
      "source_uid": 3,
      "price": 0.1223,
      "instrument_name": "BTC-28JAN22-32500-C",
      "direction": "sell",
      "amount": 0.1
    },
    {
      "target_uid": 23,
      "source_uid": 3,
      "price": 35800,
      "instrument_name": "BTC-PERPETUAL",
      "direction": "buy",
      "amount": 110
    }
  ]
}
The response is an array of objects, each representing a successfully moved position. Each object contains:
  • target_uid: The target subaccount ID
  • source_uid: The source subaccount ID
  • price: The price at which the position was moved
  • instrument_name: The instrument name
  • direction: The direction of the position (“buy” for long positions, “sell” for short positions)
  • amount: The amount that was moved

Pricing

If no price is specified in the request for a particular trade, Deribit defaults to using the average entry price of the position in the source subaccount. This ensures that the position is moved at its original cost basis. You can also explicitly specify a price if you want to move the position at a different price level.

Moving full vs partial positions

You can move either full or partial positions:
  • Full position: Specify the entire position amount in the amount field
  • Partial position: Specify a portion of the position amount
The amount must not exceed the available position size in the source subaccount.

Error handling

Rate limit errors

If you exceed the rate limit (6 requests/minute), you will receive:
{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": 13780,
    "message": "move_positions_over_limit",
    "data": {
      "wait": 10
    }
  }
}
Wait for the number of seconds specified in the wait field before retrying.

Internal server errors

In rare cases, the request may return an internal_server_error. This does not necessarily mean the operation failed entirely. Part or all of the position transfer might have still been processed successfully.If you receive an internal server error, check the positions in both the source and target subaccounts to verify the actual state.

Common errors

  • Invalid subaccount IDs: Ensure both source_uid and target_uid are valid and belong to the same main account
  • Insufficient position: The amount specified exceeds the available position in the source subaccount
  • Invalid instrument: The instrument_name is not valid or the position doesn’t exist
  • Scope errors: Ensure your API key has both trade:read_write and mainaccount scopes

Best practices

  • Check positions first: Before moving positions, verify the current positions in the source subaccount using private/get_positions
  • Move in batches: Due to rate limits, if you need to move many positions, consider batching them into a single request rather than making multiple requests
  • Verify after move: After moving positions, verify the positions in both source and target subaccounts to confirm the move was successful
  • Handle errors gracefully: Implement retry logic with exponential backoff for rate limit errors
  • Monitor rate limits: Keep track of your request rate to avoid hitting the 6 requests/minute limit

Example: Moving multiple positions

Here’s an example of moving multiple positions across different instruments:
{
  "jsonrpc": "2.0",
  "method": "private/move_positions",
  "params": {
    "currency": "BTC",
    "source_uid": 3,
    "target_uid": 23,
    "trades": [
      {
        "instrument_name": "BTC-PERPETUAL",
        "amount": "110",
        "price": "35800"
      },
      {
        "instrument_name": "BTC-28JAN22-32500-C",
        "amount": "0.1"
      },
      {
        "instrument_name": "BTC-28JAN22-40000-P",
        "amount": "5",
        "price": "0.05"
      }
    ]
  },
  "id": 2
}