Skip to main content
A DCA order splits one deposit into a series of swaps that run automatically on a fixed schedule, so you buy a little at a time instead of all at once. You deposit your full budget, choose how many rounds and how often, and Jupiter’s keeper executes each round and sends the output to your wallet. DCA is part of the Trigger API. It shares the same vault, authentication, and deposit flow as price orders, so if you have already integrated those, the only new endpoint is POST /trigger/v2/orders/dca. This page covers creating an order; see Track a DCA Order to monitor it and Cancel a DCA Order to withdraw the unfilled remainder.

How it works

Every wallet has one Privy-managed vault. You fund a DCA order by depositing into that vault, then the keeper draws from it each round: You manage two moments: creating the order (deposit + schedule) and optionally cancelling it (withdraw the unfilled remainder). Everything in between, the per-round swaps, is handled by the keeper.

Order types

Set orderType on create to choose how rounds execute. Both types retry a stuck round within a window of min(max(30, intervalSeconds / 2), 7200) seconds before rescheduling it.
The deposit’s orderType is dca (with no orderSubType). That is a different field from the create call’s orderType (time_based or price_conditional) above, which selects the DCA behaviour.

Quick start

Creating a DCA order is four calls: authenticate, get your vault, craft and sign the deposit, then submit the order.
Install the signing dependencies:
You also need a Jupiter API key and a funded wallet. The example below loads the wallet from BS58_PRIVATE_KEY and the key from JUPITER_API_KEY in your .env. For the browser-wallet (signMessage) version of authentication, see Authentication.
Never commit private keys. Use environment variables for testing and a proper key-management solution in production.
The deposit lands on-chain during the create call, so a 200 means the order is live. The response is { id, txSignature }, where txSignature is the on-chain deposit signature:
The vault address is resolved from your JWT, so you never pass it. The deposit requestId is single-use and is consumed by the create call as depositRequestId. Once the order is live, track it.

Request parameters

The body of POST /trigger/v2/orders/dca:

Validation

The API validates the request before any funds move, so a rejected order costs nothing. Active orders are those in depositing, active, executing, or withdrawing. Cancel orders you no longer need to free up slots.

Price-conditional orders

To accumulate only within a target price range, set orderType: "price_conditional", at least one of minPriceUsd / maxPriceUsd, and a triggerMint:
triggerMint must be the input or output mint, and cannot be the stablecoin side of the pair. In practice that is the volatile leg (here, SOL). A stablecoin trigger such as USDC is rejected with 400 "Trigger mint is not supported", and a pair where both legs are stable returns 400 "Mint pair is not supported". Omitting the bounds or the trigger returns a 400 identifying the missing field, and a time_based order that sets price bounds is rejected.

Earn While You Wait

Set jlEnabled: true to earn yield on the part of your budget that has not been swapped yet. While the stablecoin sits in the vault between rounds, it is supplied to Jupiter Lend and earns yield until each round draws from it. The yield accrues to you and is returned when the order finishes or is cancelled. Earn While You Wait has two requirements:
  • The order must be time_based. A price_conditional order with jlEnabled: true returns 400 "jlEnabled is only supported for time_based orders".
  • The input mint must be a supported stablecoin. Any other input returns 400 "jlEnabled is not supported for this input mint".
Supported stablecoins and their Jupiter Lend tokens: You can also resolve the pairing at runtime: GET https://api.jup.ag/lend/v1/earn/tokens, match assetAddress to your inputMint, and use that token’s address as jlMint. To create an Earn While You Wait order:
  1. Craft the deposit with jlMint (POST /trigger/v2/deposit/craft with orderType: "dca" and jlMint). The response returns jlTokenAccount instead of inputTokenAccount. A jlMint that is not the Lend token for your input stablecoin returns 400 "jlMint does not match the JL token for this input mint".
  2. Create the order with jlEnabled: true and the same jlMint on POST /trigger/v2/orders/dca.
The create response is unchanged ({ id, txSignature }). When you track the order, it carries jlEnabled: true and jlYieldUsd (yield accrued so far in USD, or null while a required price is uncached). Cancelling unwinds the Lend position and returns the remaining stablecoin, plus the accrued yield, to your wallet.

Errors

Beyond the create-time validation above, these are the runtime errors you are most likely to hit across the DCA endpoints:

Track a DCA Order

Monitor progress, fills, and state.

Cancel a DCA Order

Withdraw the unfilled remainder.

Create DCA Order (API)

Full request and response schema in the API reference.

Authentication

The challenge-response JWT flow every request needs.