Automated Swaps & Withdrawals

Set up standing orders to automatically on or off ramp Bitcoin, Ethereum & Stablecoins. Use the Lightning Network to guarantee rates to users.

A standing order on Striga allows your application to build simpler on/off-ramp flows while remaining out of scope of MiCA compliance. You can -

  1. Create a standing order using the Create Standing Order API, which will initiate an OTP to be sent to the user (SMS and/or email - using your pre-verified email address on Striga).
    1. When creating a standing order you need to specify a source account ID which must be enriched with an IBAN or blockchain deposit address. This is the account that will be monitored for incoming payments to be automatically converted and paid out.
    2. When creating a standing order, you need to pass in a whitelisted address ID or a whitelisted IBAN ID (Please refer to the Whitelist Address API). Incoming funds are converted and paid out to that destination.
  2. Confirm a standing order by passing along the OTP that the user entered into your application. Once confirmed, the Standing Order will have an ACTIVE status and any incoming fiat is automatically converted into the currency of the destination and paid out.
  3. Cancel a standing order by passing in a user ID. This will initiate an OTP, same as above, to be used in the Confirm endpoint, same as above. This will update a standing order status to CANCELLED.
  4. Modify or Update a standing order by simply creating a new one. This will automatically cancel the last active one.
📘

Standing Order Parameters

  1. There are no limits to swapping funds but depending upon the KYC tier of a user, there may be a withdrawal limit. If during a standing order, the swap is successful but a withdrawal would exceed the users' limits, the withdrawal does not take place. Your user interface may redirect the user to complete the next Tier of KYC to unlock higher limits after which you can use the "Resume Standing Order" API.
  2. The "Resume Standing Order" API can also be used to force run a standing order if it failed for whatever reason. It will -
    1. Check if the user has an active standing order
    2. Check if the user has any funds in the source account ID specified when creating the standing order. If yes, It will swap funds into the destination currency, provided it is above the minimum tradeable value.
    3. Check if there is are any assets to be withdrawn in the destination account of the same wallet as the source account.
    4. Check if a withdrawal can be made by checking the users' limits and applicable network fees/application fees.
    5. If both above checks pass, a withdrawal is attempted. If a withdrawal to an IBAN fails you might want to create a new standing order to replace the old one, since the user must consent to the change of destination IBAN in the case of a standing order.

Webhooks are sent in an identical format to the swap and withdrawal webhooks if you did this manually. The primary difference is that with a single OTP confirmation, a user can set up a recurring order to on/off ramp without needing to confirm each transaction manually.

Standing orders have two directions, i.e. either FIAT_TO_CRYPTO or CRYPTO_TO_FIAT which is computed based on the provided sourceAccountId and whitelistedAddressId OR whitelistedIbanId in the Create Standing Order API.

🚧

Testing Standing Orders on the Sandbox in the FIAT_TO_CRYPTO direction

To test the full flow of standing orders on the sandbox, you must have a valid "testnet" balance of the coin you are testing the standing order with. Testnet coins are hard to come by at times and since EUR on the sandbox is entirely fictional, trading fictional EUR into a real testnet coin and withdrawing it on chain would not be feasible on the sandbox.

We recommend creating one separate wallet on the sandbox to deposit testnet coins and then testing standing orders on another wallet. When attempting to execute an on-chain withdrawal at the end of a standing order flow on the sandbox, the users' "Testnet Balance" is checked which is the sum of all on-chain + LN deposits minus the sum of all on-chain + LN withdrawals.

We recommend using a separate "Wallet" object within Striga dedicated for Standing Orders such that you can still use another "Wallet" for cards, IBANs, one-off on-ramps and off-ramps or whatever other use case you have in mind.

An example of the standing orders object -

{
    "orders": [
        {
            "id": "59e0057a-8a40-43b5-a619-1b957209489e",
            "rootAccountId": "91559a0e294a361a7b23f4ff7e542bd1",
            "parentWalletId": "7dfb38e1-8098-4974-98f8-c0e76ca1c80c",
            "userId": "5ed0e4a0-3943-443b-a7bb-77d5bc100c53",
            "status": "CANCELLED",
            "currency": "BTC",
            "network": {
                "name": "Bitcoin Testnet 3"
            },
            "address": "tb1qdwpczmqhwvk9unkxlccdgzwmucguuhk4hx3qd3",
            "whitelistedAddressId": "9bab31ff-7aa0-4ec6-9128-d9657cc63973",
            "createdAt": "2025-08-04T10:24:42.439Z",
            "standingOrderDirection": "FIAT_TO_CRYPTO",
            "swaps": [
                {
                    "id": "49096fbc-18a3-4905-a808-48ca5ed1a6e0"
                }
            ],
            "payouts": []
        },
        {
            "id": "fc38b4d0-6f2d-4180-a348-cf09bebfe183",
            "rootAccountId": "f604544f28ca1dbc6f9cfa88a92ab78b",
            "parentWalletId": "7dfb38e1-8098-4974-98f8-c0e76ca1c80c",
            "userId": "5ed0e4a0-3943-443b-a7bb-77d5bc100c53",
            "status": "CANCELLED",
            "currency": "EUR",
            "network": {},
            "whitelistedIbanId": "ea8e3305-fbf6-439a-a9c6-a3cb0a37a903",
            "iban": "LV91LAPB0000000992511",
            "bic": "LAPBLV2X",
            "createdAt": "2025-08-04T09:32:30.615Z",
            "standingOrderDirection": "CRYPTO_TO_FIAT",
            "swaps": [
                {
                    "id": "18002254-4703-4583-bd13-81910e74b769"
                },
                {
                    "id": "8e8dfeba-73e1-4e30-b9ed-e4e3110e4fa7"
                },
                {
                    "id": "a3f81c79-6015-48c4-be5a-9a1e44d1ed01"
                }
            ],
            "payouts": [
                {
                    "id": "52970c11-eb94-4ea8-838b-e46cc1d6ed2a"
                },
                {
                    "id": "76a971e1-a7ee-4012-9929-df512be859e0"
                },
                {
                    "id": "85f3892c-d889-454b-aa86-48c3758c9bcd"
                }
            ]
        },
        {
            "id": "10f95ff7-6f3d-4893-8ecd-4ae31f526cce",
            "rootAccountId": "f604544f28ca1dbc6f9cfa88a92ab78b",
            "parentWalletId": "7dfb38e1-8098-4974-98f8-c0e76ca1c80c",
            "userId": "5ed0e4a0-3943-443b-a7bb-77d5bc100c53",
            "status": "CANCELLED",
            "currency": "EUR",
            "network": {},
            "whitelistedIbanId": "a3bc9b44-710d-4ab7-90f8-9509a7a668a6",
            "iban": "EE351006084010080096",
            "bic": "MSLITKV1",
            "createdAt": "2025-08-03T16:13:51.405Z",
            "standingOrderDirection": "CRYPTO_TO_FIAT",
            "swaps": [
                {
                    "id": "86f8b730-11d2-43ea-8845-0aac68027058"
                }
            ],
            "payouts": []
        },
        {
            "id": "ede0bdfb-4a61-47c8-819b-3f038b5ebcb3",
            "rootAccountId": "f604544f28ca1dbc6f9cfa88a92ab78b",
            "parentWalletId": "7dfb38e1-8098-4974-98f8-c0e76ca1c80c",
            "userId": "5ed0e4a0-3943-443b-a7bb-77d5bc100c53",
            "status": "CANCELLED",
            "currency": "BTC",
            "network": {},
            "whitelistedIbanId": "a3bc9b44-710d-4ab7-90f8-9509a7a668a6",
            "iban": "EE351006084010080096",
            "bic": "MSLITKV1",
            "createdAt": "2025-08-03T14:50:57.326Z",
            "standingOrderDirection": "CRYPTO_TO_FIAT",
            "swaps": [],
            "payouts": []
        }
    ],
    "count": 4,
    "total": 4
}

When creating a standing order you may specify a fixedFee and a percentFeeBps to override your default Crypto Exchange fee configuration. The standing order by default uses your crypto exchange fee configuration otherwise.


Note that standingOrderId and standingOrderSpanId are now parameters present in the transaction object, throughout the lifecycle of a standing order. For instance, below is a sample sequence of objects that are part of a Standing Order executed with a fixed proposedRate and fillOrKillAtProposedRate set to true for a BTC to EUR standing order -

{
  "uid": "d3165465-2e4a-475d-9c5b-5f3a006bbc7d",
  "type": "LN_INCOMING_CONFIRMED",
  "id": "3ed8aaf2-c072-4a4e-86d6-847b7594605b",
  "accountId": "f604544f28ca1dbc6f9cfa88a92ab78b",
  "syncedOwnerId": "5ed0e4a0-3943-443b-a7bb-77d5bc100c53",
  "sourceSyncedOwnerId": "5ed0e4a0-3943-443b-a7bb-77d5bc100c53",
  "credit": "10000",
  "timestamp": "2025-08-04T09:35:05.770Z",
  "txType": "LN_INCOMING_CONFIRMED",
  "memo": "experiences",
  "otherCryptoIdentifier": "lntb100u1p5fql4epp5lst7n54zu37tnn9cj4gr774ylht6km2r9mmwd7fw3kslng6jwxesdqjv4u8qetjd9jkucm9wvcqzzsxqyzjpqsp5jwmj30htj5dyuyy7jlydp0yjwxg35unj4vw9w2yu9ylrusd9ztxs9qyyssqecder8hs9ce0jja07w8xpjf4am87cygk3u0r84mjfyu0qntr726qywym0qzdjyev774j6fukdp7ju4mjjtsemt2e6lyzwqmyw9a7avcp2mv5qu",
  "currency": "BTC",
  "strigaFee": "100",
  "strigaFeeCurrency": "BTC",
  "exchangeRate": "99101",
  "proposedRate": "99175.92",
  "fillOrKillAtProposedRate": true,
  "standingOrderId": "fc38b4d0-6f2d-4180-a348-cf09bebfe183",
  "standingOrderSpanId": "103bd442-79bd-4994-9218-72cd2e1e065b",
  "balanceBefore": {
    "amount": "1000",
    "balance": "1000",
    "currency": "satoshis"
  },
  "balanceAfter": {
    "amount": "11000",
    "balance": "11000",
    "currency": "satoshis"
  },
  "feeEstimate": {
    "totalFee": "100",
    "networkFee": "100",
    "ourFee": "100",
    "theirFee": "0",
    "feeCurrency": "BTC",
    "fixedFeeDetails": {
      "amount": "0",
      "exchangeRate": "0"
    },
    "percentageFeeDetails": {
      "amount": "0"
    }
  },
  "ts": 1754300110018
}
{
  "uid": "71c9be57-5c97-4cb3-a4f0-7cfccfef7c0f",
  "type": "CURRENCY_EXCHANGE",
  "id": "18002254-4703-4583-bd13-81910e74b769",
  "accountId": "f604544f28ca1dbc6f9cfa88a92ab78b",
  "syncedOwnerId": "5ed0e4a0-3943-443b-a7bb-77d5bc100c53",
  "sourceSyncedOwnerId": "5ed0e4a0-3943-443b-a7bb-77d5bc100c53",
  "destinationSyncedOwnerId": "5ed0e4a0-3943-443b-a7bb-77d5bc100c53",
  "debit": "10978",
  "timestamp": "2025-08-04T09:35:15.542Z",
  "txType": "EXCHANGE_DEBIT",
  "txSubType": "CURRENCY_EXCHANGE_PENDING",
  "memo": "Swap 0.00010978 BTC to EUR",
  "memoPayer": "experiences STANDING_ORDER_fc38b4d0-6f2d-4180-a348-cf09bebfe183_CRYPTO_TO_FIAT_103bd442-79bd-4994-9218-72cd2e1e065b",
  "currency": "BTC",
  "exchangeRate": "99101.1",
  "proposedRate": "99175.92",
  "fillOrKillAtProposedRate": true,
  "standingOrderId": "fc38b4d0-6f2d-4180-a348-cf09bebfe183",
  "standingOrderSpanId": "103bd442-79bd-4994-9218-72cd2e1e065b",
  "order": {
    "price": "99175.92",
    "debit": {
      "currency": "BTC",
      "amountFloat": "0.00010978",
      "amount": "10978"
    },
    "credit": {
      "currency": "EUR",
      "amountFloat": "10.88",
      "amount": "1088"
    }
  },
  "balanceBefore": {
    "amount": "10978",
    "balance": "10978",
    "currency": "satoshis"
  },
  "balanceAfter": {
    "amount": "0",
    "balance": "0",
    "currency": "satoshis"
  },
  "feeEstimate": {
    "totalFee": "22",
    "networkFee": "0",
    "ourFee": "0",
    "theirFee": "22",
    "feeCurrency": "BTC",
    "fixedFeeDetails": {
      "amount": "0",
      "exchangeRate": "1",
      "appliedFeeCents": "0"
    },
    "percentageFeeDetails": {
      "amount": "22",
      "appliedFeeBps": "20"
    }
  },
  "ts": 1754300121606
}
{
  "uid": "0cc6f7ad-de29-4675-883f-e801676bf740",
  "type": "CURRENCY_EXCHANGE",
  "id": "18002254-4703-4583-bd13-81910e74b769",
  "accountId": "91559a0e294a361a7b23f4ff7e542bd1",
  "syncedOwnerId": "5ed0e4a0-3943-443b-a7bb-77d5bc100c53",
  "sourceSyncedOwnerId": "5ed0e4a0-3943-443b-a7bb-77d5bc100c53",
  "destinationSyncedOwnerId": "5ed0e4a0-3943-443b-a7bb-77d5bc100c53",
  "credit": "1088",
  "timestamp": "2025-08-04T09:35:18.135Z",
  "txType": "EXCHANGE_CREDIT",
  "txSubType": "CURRENCY_EXCHANGE_CONFIRMED",
  "memo": "Swap 0.00010978 BTC to EUR",
  "memoPayer": "experiences STANDING_ORDER_fc38b4d0-6f2d-4180-a348-cf09bebfe183_CRYPTO_TO_FIAT_103bd442-79bd-4994-9218-72cd2e1e065b",
  "currency": "EUR",
  "exchangeRate": "99101.1",
  "proposedRate": "99175.92",
  "fillOrKillAtProposedRate": true,
  "standingOrderId": "fc38b4d0-6f2d-4180-a348-cf09bebfe183",
  "standingOrderSpanId": "103bd442-79bd-4994-9218-72cd2e1e065b",
  "order": {
    "price": "99175.92",
    "debit": {
      "currency": "BTC",
      "amountFloat": "0.00010978",
      "amount": "10978"
    },
    "credit": {
      "currency": "EUR",
      "amountFloat": "10.88",
      "amount": "1088"
    }
  },
  "balanceBefore": {
    "amount": "2254",
    "balance": "2254",
    "currency": "cents"
  },
  "balanceAfter": {
    "amount": "3342",
    "balance": "3342",
    "currency": "cents"
  },
  "feeEstimate": {
    "totalFee": "22",
    "networkFee": "0",
    "ourFee": "0",
    "theirFee": "22",
    "feeCurrency": "BTC",
    "fixedFeeDetails": {
      "amount": "0",
      "exchangeRate": "1",
      "appliedFeeCents": "0"
    },
    "percentageFeeDetails": {
      "amount": "22",
      "appliedFeeBps": "20"
    }
  },
  "ts": 1754300121780
}
{
  "uid": "4431d620-429e-4070-8001-60df60da087f",
  "type": "SEPA_PAYOUT_INITIATED",
  "id": "52970c11-eb94-4ea8-838b-e46cc1d6ed2a",
  "accountId": "91559a0e294a361a7b23f4ff7e542bd1",
  "syncedOwnerId": "5ed0e4a0-3943-443b-a7bb-77d5bc100c53",
  "sourceSyncedOwnerId": "5ed0e4a0-3943-443b-a7bb-77d5bc100c53",
  "debit": "2275",
  "timestamp": "2025-08-04T09:35:36.793Z",
  "txType": "SEPA_PAYOUT_INITIATED",
  "memo": "SEPA_PAYOUT_INITIATED 33.42 EUR PFKZjsoT6V",
  "currency": "EUR",
  "exchangeRate": "1",
  "standingOrderId": "fc38b4d0-6f2d-4180-a348-cf09bebfe183",
  "standingOrderSpanId": "103bd442-79bd-4994-9218-72cd2e1e065b",
  "balanceBefore": {
    "amount": "2275",
    "balance": "2275",
    "currency": "cents"
  },
  "balanceAfter": {
    "amount": "0",
    "balance": "0",
    "currency": "cents"
  },
  "bankingTransactionShortId": "20250804-W5LW5F",
  "bankingTransactionAmount": "22.75",
  "bankingSenderBic": "SEOUGB21",
  "bankingSenderIban": "GB36SEOU19870010401530",
  "bankingSenderName": "John Doe",
  "bankingPaymentType": "SEPA",
  "bankingBeneficiaryBic": "EEUHEE2X",
  "bankingBeneficiaryIban": "EE351010052031000004",
  "feeEstimate": {
    "totalFee": "1067",
    "networkFee": "0",
    "ourFee": "0",
    "theirFee": "1067",
    "feeCurrency": "EUR",
    "fixedFeeDetails": {
      "amount": "1000",
      "exchangeRate": "1",
      "appliedFeeCents": "1000"
    },
    "percentageFeeDetails": {
      "amount": "67",
      "appliedFeeBps": "200"
    }
  },
  "ts": 1754300141994
}