Deposit to Perps
Moves an asset from one of the portfolio's trading vaults into the perps account. Unlike withdrawals, no wallet signature is required: the trading vault is custodied by Definitive, so a WRITE-scoped API key is sufficient and the transfer is executed server-side.
POST /perps/deposit/vault-fund-hl/quote— prices the transfer and returns aquoteId.POST /perps/deposit/vault-fund-hl— executes the quoted transfer and returns arequestId.
Endpoints
Portfolio API: POST https://ddp.definitive.fi/v2/portfolio/perps/deposit/vault-fund-hl/quote and POST https://ddp.definitive.fi/v2/portfolio/perps/deposit/vault-fund-hl
Organization API: Replace
/v2/portfolio/with/v2/organization/portfolios/{portfolioId}/. See Portfolio vs. Organization API.
Both require a WRITE-scoped API key (all POST endpoints do).
Identifying the source and destination
| Field | Where it comes from |
|---|---|
| sourceVaultId | A vault of the key's portfolio — vaults[].vaultId on Portfolio Details. The asset is sent from this vault. |
| fromAssetAddress | Contract address of the asset to send, on the source vault's own chain. Unrecognized addresses return 400. |
| destinationPortfolioId | The portfolio whose perps account receives the funds. It must already have a perps account — check Account Status. |
Step 1 — Quote the transfer
POST /perps/deposit/vault-fund-hl/quote
| Field | Type | Required | Description |
|---|---|---|---|
| sourceVaultId | string | Yes | UUID of the trading vault funding the deposit |
| destinationPortfolioId | string | Yes | UUID of the portfolio whose perps account receives the funds |
| fromAssetAddress | string | Yes | Contract address of the asset to send, on the source vault's chain |
| fromAmount | string | Yes | Amount to send as a positive decimal string, e.g. "250" |
const quote = await AuthHelpers.signAndSend({
path: "/v2/portfolio/perps/deposit/vault-fund-hl/quote",
method: "POST",
body: {
sourceVaultId: "00000000-0000-0000-0000-000000000003",
destinationPortfolioId: "00000000-0000-0000-0000-000000000001",
fromAssetAddress: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
fromAmount: "250",
},
apiKey: process.env.API_KEY,
apiSecret: process.env.API_SECRET,
});Response:
{
quoteId: "0x9f2c...",
provider: "relay",
toAmount: "249.62",
toAmountRaw: "249620000",
fromAmountQuotedRaw: "250000000",
serviceTime: 45,
gasFeesUsd: 0.38,
protocols: ["relay"],
fromAssetInstanceId: "...",
toAssetInstanceId: "...",
destinationPerpsVaultId: "..."
}toAmount is what lands in the perps account after routing and gas; it is normally lower than fromAmount. gasInFromAsset, nativeAssetFromAssetNotional and maxGasCostInNative appear only when the route charges gas in the sent asset.
Step 2 — Execute the transfer
POST /perps/deposit/vault-fund-hl
Repeat the four quote fields exactly as sent in step 1 and add the quoteId you received.
| Field | Type | Required | Description |
|---|---|---|---|
| quoteId | string | Yes | The quoteId returned by step 1 |
| sourceVaultId | string | Yes | Same value as step 1 |
| destinationPortfolioId | string | Yes | Same value as step 1 |
| fromAssetAddress | string | Yes | Same value as step 1 |
| fromAmount | string | Yes | Same value as step 1 |
const json = await AuthHelpers.signAndSend({
path: "/v2/portfolio/perps/deposit/vault-fund-hl",
method: "POST",
body: {
quoteId: quote.quoteId,
sourceVaultId: "00000000-0000-0000-0000-000000000003",
destinationPortfolioId: "00000000-0000-0000-0000-000000000001",
fromAssetAddress: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
fromAmount: "250",
},
apiKey: process.env.API_KEY,
apiSecret: process.env.API_SECRET,
});Response:
{
requestId: "..."
}The transfer settles asynchronously. Poll /perps/account and watch the account balance rather than treating the response as final settlement.
Errors
| Status | Meaning | What to do |
|---|---|---|
| 400 | Invalid body, or fromAssetAddress is not a recognized asset on the source vault's chain | Check the address against the source vault's chain |
| 401 | Organization API: {portfolioId} is not in your organization; or the source vault does not belong to it, or the destination portfolio is in another organization | Use a portfolio and vault of your own organization |
| 403 | READ-scoped key | Use a WRITE-scoped key |
| 404 | Source vault not found, destination portfolio not found, or the destination portfolio has no perps account | Check the vault id, and Account Status for the destination |
Deposit errors are returned by the transfers backend, not the perps service, so they do not carry the
errorTypefield used by the rest of the perps surface — a destination without a perps account is a404here and a422 PERPS_ACCOUNT_NOT_CONFIGUREDon the read endpoints.
Notes
- The deposit endpoints are not behind the perps 20 requests/second limiter; on the Portfolio API they fall under the standard per-key limit.
- Get the funds back out with Withdraw, which returns USDC to the portfolio's Arbitrum trading vault.