push_to_card rail.
Push to card is available to verified US users, in USD, for Visa and Mastercard debit
cards. Credit cards are not eligible, and the card network has the final say on whether a
given card can receive a push.
How card data stays out of scope
Spritz never accepts a raw card number, and neither should you. Card entry runs inside an Evervault Card component: an iframe served from Evervault’s domain that encrypts the card number in the user’s browser before your code ever sees it. What comes out is an opaqueev: token plus the plaintext metadata Spritz needs (expiry,
last four, BIN, brand). You forward those to POST /v1/debit-cards; only Spritz’s
infrastructure can decrypt the token, and only to hand the card to the payout network.
The component needs two identifiers to initialise: an Evervault team ID and an
app ID. They are public-key material, not credentials — anyone holding them can only
encrypt to Spritz, never decrypt — but they are environment-specific, so a card
encrypted for sandbox cannot be used in production and vice versa.
Spritz provides the Evervault team ID and the app IDs for sandbox and production
during onboarding. If you do not have them, ask your Spritz contact.
Before you start
- Authenticate as an integrator acting for a user. See Authentication.
- The user’s capabilities on
GET /v1/users/meinclude the pairproduct: "crypto_to_fiat"andmethod: "push_to_card"withstatus: "active". See Onboarding. Adding a card without it returns403. - You have the Evervault team ID and the app ID for the environment you are calling.
Step 1 — Collect the card in the browser
Install the Evervault SDK for your stack (@evervault/react, @evervault/js, or the
mobile SDKs) and render the Card component with
number and expiry fields. Spritz does not need the CVC — leave it out.
onChange payload carries everything the API needs:
Collect the cardholder’s first and last name and their US billing address in your own
form. The name must be the name printed on the card — Spritz checks it against the user’s
verified identity — and the card network requires the billing address to accept pushes.
Step 2 — Add the card
Send the captured values from your backend, signed with your integrator key, on behalf of the user. Your backend only ever handles the encrypted token, which keeps it outside PCI scope.201 returns the card, ready to use:
List a user’s cards with
GET /v1/debit-cards ({ "data": [...], "hasMore": false } —
no pagination, users hold few cards), read one with GET /v1/debit-cards/{id}, and
remove one with DELETE /v1/debit-cards/{id}. A deleted card reads back as 404.
Errors when adding a card
Step 3 — Quote, pay, and track
From here the off-ramp guide applies unchanged. Pass the card’sid as accountId and choose the push_to_card rail:
- Timing: minutes, seven days a week. The off-ramp usually moves
in_flight→completedwithin a few minutes of the on-chain confirmation. See Settlement timing. - Pricing: the crypto-to-fiat base rate plus the
push_to_cardadjustment, with a weekend and US-bank-holiday surcharge. See End-user pricing. - Failure: if the network declines the push after the crypto has been paid, the
off-ramp reaches
failedand the refund flow applies. A decline that is a verdict on the card itself (expired, inactive, cannot receive pushes) also flips the card torejected— collect a different card before offering a reissue.
payment.* and offramp.* events as any off-ramp. See
Webhooks.
Sandbox testing
Sandbox has its own Evervault app ID. Initialise the Card component with it when targetinghttps://sandbox.spritz.finance; a token encrypted for the production app is
refused there, and the other way round. Card entry accepts any Luhn-valid Visa or
Mastercard number with a future expiry, and the add flow runs against a sandbox card
registration, so the 201, 403, 422, and 400 paths above are all reachable.
As with every sandbox off-ramp, the fiat leg parks at queued — no push is submitted, so
completed, failed, and the rejected card state are contract-tested from this guide,
not end-to-end tested. Exercise your handling of them with fixtures. See
Sandbox for the environment as a whole.
Integration checklist
- Card number is captured only inside the Evervault Card component, with the team ID and the app ID for the environment you are calling
- Your backend forwards the encrypted token and never logs it, and your frontend never posts it to Spritz directly (that would expose your integrator key)
-
expiryMonthandexpiryYearare forwarded as the component returns them, not re-formatted - Cardholder name is collected as first and last name, as printed on the card
-
403and422on card add produce specific user guidance, and503offers “try a different card” rather than a retry - Quotes use
rail: "push_to_card"with the cardidasaccountId - A
rejectedcard is hidden from the destination picker and the user is prompted to add another
Related
Off-ramp: crypto to bank
The full off-ramp lifecycle this guide builds on.
Onboarding
Reading capabilities to know when push to card is active.
End-user pricing
Fee tiers by rail, including push to card.
Sandbox
Test users, bypasses, and what the sandbox can and cannot simulate.