PearPear
API IntegrationAccess Management

Trade Accounts

Connect and manage the exchange accounts Pear trades on your behalf.

A trade account links your Pear identity to one connected exchange account on Hyperliquid, Binance, Bybit, OKX, or Lighter. You connect an account once, then scope every trading call to it with the x-trade-account-id header.

Exchange credentials are stored encrypted. One endpoint returns them decrypted to the account's owner, POST /trade-accounts/{id}/credentials, which is how a client talks to the venue directly.

Manage trade accounts

EndpointPurpose
GET /trade-accountsList your connected accounts.
POST /trade-accountsConnect an exchange account. Returns 201 with { "account": … }.
PATCH /trade-accounts/{id}Change the alias, the credentials, or the metadata.
POST /trade-accounts/{id}/credentialsRead the account's decrypted venue credentials.
DELETE /trade-accounts/{id}Soft-delete an account. Returns 204.
POST /trade-accounts/{id}/restoreRestore a soft-deleted account. Returns 204.

List your accounts

curl "https://pro-gateway.pearprotocol.io/trade-accounts" \
  -H "x-api-key: $PEAR_API_KEY"
{
  "accounts": [
    {
      "id": "9c1b2d3e-4f56-4789-a0b1-c2d3e4f56789",
      "alias": "main",
      "connector": "hyperliquid",
      "exchangeIdentifier": "0x1f9840a85d5af5bf1d1762f925bdaddc4201f984",
      "metadata": {
        "agentWalletAddress": "0xa1b2c3d4e5f60718293a4b5c6d7e8f9012345678",
        "isSubaccount": false,
        "mainAccountAddress": "0x1f9840a85d5af5bf1d1762f925bdaddc4201f984"
      },
      "createdAt": "2026-01-01T00:00:00.000Z",
      "updatedAt": "2026-01-01T00:00:00.000Z"
    }
  ]
}

Hyperliquid always reports all three metadata keys, and Lighter always reports l1_address. Binance, Bybit, and OKX carry no metadata at all, so the key is absent.

Pass the id as x-trade-account-id on every account-scoped request. Add ?includeDeleted=true to see soft-deleted accounts before you restore one; those rows also carry deletedAt.

Connect an account

Connecting takes that venue's credentials. On Hyperliquid:

{
  "connector": "hyperliquid",
  "alias": "main",
  "exchangeIdentifier": "0x1f9840a85d5af5bf1d1762f925bdaddc4201f984",
  "credentials": { "signer_key": "0x…" },
  "metadata": {
    "agentWalletAddress": "0xa1b2c3d4e5f60718293a4b5c6d7e8f9012345678",
    "isSubaccount": false,
    "mainAccountAddress": "0x1f9840a85d5af5bf1d1762f925bdaddc4201f984"
  }
}

Creation calls the venue before it stores anything. The gateway validates the credentials against the live exchange and resolves the exchange account they control. Any refusal by the venue comes back as a 400 carrying the venue's own wording. See Connect an Exchange for what each venue checks.

Connecting the same exchange account twice is also a 400: Exchange account already linked to another trade account. If the existing row is soft-deleted, the message asks you to restore it instead, which is what POST /trade-accounts/{id}/restore is for.

Credentials per venue

ExchangecredentialsAlso required
Hyperliquidsigner_keyexchangeIdentifier (the wallet address), and metadata with agentWalletAddress, isSubaccount, mainAccountAddress.
Binanceread and write key pairs
Bybitapi_key, api_secret
OKXapi_key, api_secret, api_pass
Lighterapi_private_key, api_key_index (4–254)exchangeIdentifier (the account index, digits only), and metadata.l1_address.

Every venue takes an alias, 1 to 100 characters, which is the label you see in listings.

exchangeIdentifier is a request field on Hyperliquid and Lighter only. Binance, Bybit, and OKX do not accept one: the gateway reads the account id back from the venue (the Binance uid, the Bybit userID, the OKX uid) and stores that.

This endpoint does not set up the venue. Hyperliquid and Lighter both need a funded account and on-chain approvals before the credentials work, and those steps happen against the exchange. Binance, Bybit, and OKX need only an API key. See Connect an Exchange for the per-venue walkthrough, including the builder and integrator approvals and the 6 bps minimum both require.

Update an account

PATCH /trade-accounts/{id} takes a body keyed by connector:

{
  "connector": "hyperliquid",
  "alias": "main-agent",
  "credentials": { "signer_key": "0x…" },
  "metadata": {
    "agentWalletAddress": "0xa1b2c3d4e5f60718293a4b5c6d7e8f9012345678",
    "isSubaccount": false,
    "mainAccountAddress": "0x1f9840a85d5af5bf1d1762f925bdaddc4201f984"
  }
}
FieldRule
connectorRequired on every PATCH. It selects which venue's shape the rest of the body is read as. It must equal the stored connector, or the call returns 403 Cannot change connector type.
aliasOptional. 1 to 100 characters.
credentialsOptional, and complete for that venue when sent. New credentials are validated against the exchange.
metadataOptional, and not partial: send every key the venue defines. Binance, Bybit, and OKX accept no metadata.

exchangeIdentifier is not patchable. A body with nothing but connector returns 400 No data to update or 400 No changes detected.

Two Hyperliquid rules follow from the venue call:

  • Changing metadata without sending credentials returns 400 Private key is required to update Hyperliquid wallet metadata. The private key is the proof that you control the agent wallet you are naming.
  • Credentials that resolve to a different exchange account return 400 Cannot change exchange account. Delete this trade account and create a new one.

Read the stored credentials

POST /trade-accounts/{id}/credentials returns the account's venue credentials in plaintext, so a client can call the exchange itself. It is a POST, not a GET, so that the write-scope rule applies to it: a read-only API key and a read-only OAuth grant are both refused. See Authentication.

{
  "connector": "hyperliquid",
  "account": {
    "id": "9c1b2d3e-4f56-4789-a0b1-c2d3e4f56789",
    "alias": "main",
    "connector": "hyperliquid",
    "exchangeIdentifier": "0x1f9840a85d5af5bf1d1762f925bdaddc4201f984",
    "metadata": {
      "agentWalletAddress": "0xa1b2c3d4e5f60718293a4b5c6d7e8f9012345678",
      "isSubaccount": false,
      "mainAccountAddress": "0x1f9840a85d5af5bf1d1762f925bdaddc4201f984"
    },
    "createdAt": "2026-01-01T00:00:00.000Z",
    "updatedAt": "2026-01-01T00:00:00.000Z"
  },
  "credentials": { "signer_key": "0x…" }
}

credentials carries the same field names the connect call took: signer_key for Hyperliquid, read and write pairs for Binance, api_key/api_secret for Bybit, plus api_pass for OKX, and api_private_key/api_key_index for Lighter.

The TypeScript exchanges SDK is built on this endpoint: exchanges.connect(tradeAccountId) calls it and hands the result to status(), createTracker(), and the rest. See Venue Accounts.

Scoping requests

Send the account id on each trading call or account read:

x-trade-account-id: 9c1b2d3e-4f56-4789-a0b1-c2d3e4f56789

There is no default. One connected account is treated the same as ten: an account-scoped route with no header returns 400 Missing required header: X-Trade-Account-Id.

StatusWhen
400The header is missing on an account-scoped route.
400The header value is not a UUID.
404No such trade account, or the account belongs to another user. The two cases are deliberately indistinguishable.

The same 404 applies to PATCH, DELETE, restore, and credentials when the id in the path is not yours.

On this page