Check out working demo: Live Demo
Repo: openfort-machines-cards-example
Repo: openfort-machines-cards-example
- Partner API integration (
/partner/v1) only. - Openfort for auth + embedded wallet UX.
- Your backend holds partner credentials and calls Machines.
- Simple EVM-first flow for create card, deposits, and withdrawals.
Architecture
- Frontend uses Openfort for sign-in and embedded wallet creation.
- Frontend calls your backend only.
- Your backend calls Machines Partner API.
- Your backend executes withdrawal transactions with the signer path you control.
Prerequisites
- Openfort project with:
- publishable key for frontend
- secret key for backend routes that call Openfort server APIs
- embedded wallet (Shield) key configured
- policy id configured for sponsored transactions
- Machines partner API key
- A backend service that can securely store:
X-Partner-Key- Openfort server credentials
Openfort 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+ Openfort 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.
- Gas sponsorship
- Openfort policy id is configured and attached for EVM sends.
- Use sponsored send options for wallet execution paths where required.
Recommended Data to Persist
Per user:machinesUserIdopenfortUserIdembeddedWalletAddresslinkedAt/lastUsedAt
sessionIdscopesexpiresAt
- idempotency key
- execution path (
controller_v1orcoordinator_v2) - submitted tx hash
- confirmed tx hash
End-to-End Partner Flow
1) Set up Openfort 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)
execution.callTarget using the signer you control.
controller_v1:- call
withdrawAsset(address,address,uint256,address,uint256,bytes32,bytes)
- call
coordinator_v2:- build admin typed-data signature
- call 10-arg
withdrawAsset(...)with admin signature arrays
Environment Variables
Frontend:NEXT_PUBLIC_OPENFORT_PUBLISHABLE_KEYNEXT_PUBLIC_OPENFORT_SHIELD_PUBLISHABLE_KEYNEXT_PUBLIC_OPENFORT_POLICY_IDNEXT_PUBLIC_OPENFORT_DEFAULT_CHAIN
MACHINES_PARTNER_BASE_URLMACHINES_PARTNER_API_KEYMACHINES_PARTNER_DEFAULT_SCOPESMACHINES_PARTNER_EXTERNAL_USER_PREFIX- Openfort server credentials for your execution routes
API Routes Used
User/session:POST /partner/v1/users/resolvePOST /partner/v1/sessions
GET /partner/v1/kyc/valuesPOST /partner/v1/kyc/applicationsGET /partner/v1/kyc/status
GET /partner/v1/agreementsPOST /partner/v1/agreements
GET /partner/v1/cardsPOST /partner/v1/cardsPOST /partner/v1/cards/secrets/sessionPOST /partner/v1/cards/{cardId}/secrets
GET /partner/v1/deposits/assetsPOST /partner/v1/deposits/rangePOST /partner/v1/deposits/estimatePOST /partner/v1/deposits
GET /partner/v1/withdrawals/assetsPOST /partner/v1/withdrawals/rangePOST /partner/v1/withdrawals/estimatePOST /partner/v1/withdrawals
GET /partner/v1/transactionsGET /partner/v1/transactions/{transactionId}
Notes
- Keep all partner calls server-side.
- Keep idempotency keys stable on retries.
- Keep one wallet mapping per user to avoid identity drift.