Check out working demo: Live Demo
Repo: crossmint-machines-cards-example
Repo: crossmint-machines-cards-example
- Partner API integration (
/partner/v1) only. - Crossmint for auth + embedded wallet UX.
- Your backend holds partner credentials and calls Machines.
- Simple EVM-first path for create card, deposits, and withdrawals.
Architecture
- Frontend uses Crossmint for sign-in and wallet creation.
- Frontend calls your backend only.
- Your backend calls Machines Partner API.
- Your backend executes withdrawal transactions with the embedded wallet signer path you control.
Prerequisites
- Crossmint project with:
- client key for frontend
- server key for backend (if you run server-side wallet operations)
- embedded EVM wallet creation enabled
- Machines partner API key
- A backend service that can securely store:
X-Partner-Key- Crossmint server credentials (if used)
Crossmint Embedded Wallet Checklist
Before sending traffic:- Wallet creation
- New users get an embedded EVM wallet at login.
- You can read the wallet address after auth.
- Stable mapping
- You persist partner
userId+ Crossmint user id + wallet address. - You always send the same mapped user identity to Machines.
- You persist partner
- Session bootstrap server-side
POST /partner/v1/users/resolveandPOST /partner/v1/sessionshappen on your backend.X-Partner-Keyis never exposed to browser code.
- Browser request path
- Browser calls your backend routes, not Machines directly.
- This avoids CORS failures and secret leakage.
- Withdrawal execution
- Use one signer path consistently.
- Persist tx ids/hashes and reconcile status.
Recommended Data to Persist
Per user:machinesUserIdcrossmintUserIdembeddedWalletAddresslinkedAt/lastUsedAt
sessionIdscopesexpiresAt
- idempotency key
- execution path (
controller_v1orcoordinator_v2) - submitted tx id/hash
- confirmed tx hash
End-to-End Partner Flow
1) Set up Crossmint providers (frontend)
2) Resolve user + create partner session (backend)
3) Call Machines through your backend proxy
Use the partner session token from step 2. At minimum, support these routes:GET /partner/v1/kyc/valuesPOST /partner/v1/kyc/applicationsGET /partner/v1/kyc/statusGET /partner/v1/agreementsPOST /partner/v1/agreementsGET /partner/v1/cardsPOST /partner/v1/cardsGET /partner/v1/deposits/assetsPOST /partner/v1/deposits/rangePOST /partner/v1/deposits/estimatePOST /partner/v1/depositsGET /partner/v1/transactions
4) Create withdrawals
Call sequence:GET /partner/v1/withdrawals/assetsPOST /partner/v1/withdrawals/rangePOST /partner/v1/withdrawals/estimatePOST /partner/v1/withdrawals
5) Execute withdrawal transaction
Use response fields:execution.callTargetexecution.callPathparameters
- send tx to
execution.callTarget - sender must match
adminAddressused in create request - if status is
pending, retry create with the same idempotency key
Execution Model and Contract Call Paths
Machines withdrawal create response includes:execution.callTargetexecution.callPath(controller_v1orcoordinator_v2)parameters(7-arg withdrawal payload)
controller_v1: call 7-argwithdrawAsset(...)coordinator_v2: build admin typed-data signature, then call 10-argwithdrawAsset(...)
Common Integration Pitfalls
- Calling Machines directly from browser code.
- Use your backend proxy for all partner calls.
- Creating sessions without wallet context.
- Always pass wallet data when resolving users/sessions.
- Not reusing idempotency keys on pending withdrawals.
- Retry with the same
Idempotency-Key.
- Retry with the same
- Executing on the wrong target contract.
- Always use
execution.callTargetfrom response.
- Always use
Further Reading
- Crossmint auth quickstart:
- Crossmint wallets React quickstart:
- Crossmint wallets overview:
- Machines partner docs: