Pull a billing cycle
POST /trigger-pull signs and submits pull_funds for a subscription.
Builds pull_funds(user, merchant), simulates it with prepareTransaction, signs it with the merchant key and submits it to Soroban Testnet. Once the transaction is confirmed, it sets next_billing_date to the pull time plus the plan's interval_seconds.
Testnet only. The merchant's secret seed travels in the request body. In production, sign on the client (Freighter) or with a KMS-held key.
Body
Subscription to bill. Must be a valid UUID.
Merchant's secret seed (S...). Must be a valid Stellar secret key and match the wallet of the plan's owner.
Request
curl -X POST http://localhost:3001/trigger-pull \
-H "Content-Type: application/json" \
-d '{ "subscription_id": "b2a9e4c1-...", "merchant_secret": "S..." }'Response 200
{
"message": "Successfully pulled funds on-chain!",
"txHash": "6f4a8b...19e0"
}Errors
| Status | When |
|---|---|
202 | Submitted but not confirmed before the poll timeout. next_billing_date is unchanged |
400 | subscription_id is not a valid UUID, or merchant_secret is missing or is not a valid Stellar secret key |
401 | Secret does not match the plan owner's wallet |
404 | Subscription not found, or the plan's merchant no longer exists |
500 | Simulation or submission failed, or the server is missing ORBIT_CONTRACT_ID. See contract errors |
502 | The transaction failed on-chain. The subscription is marked past_due |
How next_billing_date is calculated
When the pull is confirmed on-chain, the API sets:
next_billing_date = pull time + plan.interval_seconds- Pull time is the API server's clock at the moment it sees the confirmation, not the previous
next_billing_dateand not the ledger timestamp. - The interval is a fixed number of seconds, not a calendar month. See the "Intervals are fixed durations" note in Plans.
- A late pull pushes every later cycle back by the same delay. The schedule does not catch up.
next_billing_dateonly moves on a200. A202or502leaves it where it was.
Example. A plan with interval_seconds: 604800 (7 days) pulled at 2026-10-01T10:00:00Z gets next_billing_date 2026-10-08T10:00:00Z.
On a 202 the outcome is unknown. Poll getTransaction(txHash) before you mark the cycle as paid or retry the pull.