Your First Payment
This guide walks you through creating and processing your first payment with Finternet, from creation to settlement.
๐งช Testing Environment: All examples in this guide use the sandbox environment (api.fmm.finternetlab.io).
๐ Production API will be available once deployed.
Overviewโ
We'll create a simple payment intent, confirm it, and track it through the complete lifecycle. This example uses a Conditional Payment type, which is the simplest payment flow.
Step 1: Create a Payment Intentโ
A payment intent represents a request to collect payment from a payer. Let's create one:
curl https://api.fmm.finternetlab.io/v1/payment-intents \
-H "X-API-Key: sk_test_your_key_here" \
-H "Content-Type: application/json" \
-X POST \
-d '{
"amount": "100.00",
"currency": "USDC",
"type": "CONDITIONAL",
"settlementMethod": "OFF_RAMP_MOCK",
"settlementDestination": "bank_account_123",
"description": "Order #12345"
}'
Response:
{
"id": "intent_2xYz9AbC123",
"object": "payment_intent",
"status": "INITIATED",
"data": {
"id": "intent_2xYz9AbC123",
"object": "payment_intent",
"status": "INITIATED",
"amount": "100.00",
"currency": "USDC",
"type": "CONDITIONAL",
"settlementMethod": "OFF_RAMP_MOCK",
"settlementDestination": "bank_account_123",
"paymentUrl": "https://pay.fmm.finternetlab.io/?intent=intent_2xYz9AbC123",
"contractAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f42318",
"typedData": {
"types": {
"EIP712Domain": [...],
"ConditionalPayment": [...]
},
"domain": {...},
"message": {...}
},
"phases": [
{
"phase": "SIGNATURE_VERIFICATION",
"status": "IN_PROGRESS"
}
],
"created": 1704067200,
"updated": 1704067200
},
"created": 1704067200,
"updated": 1704067200
}
What Happened?โ
- โ
Payment intent created with status
INITIATED - โ
Frontend payment URL generated - Available in
data.paymentUrl - โ EIP-712 typed data generated for signature
- โ Contract address assigned
Using the Payment URLโ
Important: The response includes a paymentUrl in the data object. This is the URL where your users should complete the payment.
const response = await apiRequest('/payment-intents', {...});
const paymentUrl = response.data.paymentUrl;
// Redirect user to payment page
window.location.href = paymentUrl;
The payment URL format is: https://pay.fmm.finternetlab.io/?intent={intentId}
Step 2: Redirect User to Payment Pageโ
After creating the payment intent, redirect your user to the paymentUrl:
// After creating payment intent
const intent = await createPaymentIntent({...});
// Redirect user to payment page
window.location.href = intent.data.paymentUrl;
// or open in new tab
window.open(intent.data.paymentUrl, '_blank');
Step 3: Payer Completes Paymentโ
The payer visits the paymentUrl and:
- Connects their wallet (MetaMask, WalletConnect, etc.)
- Reviews payment details
- Signs the EIP-712 message
- Executes the blockchain transaction
Note: This step happens on the frontend. The payer's wallet executes the transaction directly on the blockchain. The frontend will automatically call the API to update the transaction hash.
Step 4: Confirm the Paymentโ
Once the payer has executed the transaction, confirm it with the signature and transaction hash:
curl https://api.fmm.finternetlab.io/v1/payment-intents/intent_2xYz9AbC123/confirm \
-H "X-API-Key: sk_test_your_key_here" \
-H "Content-Type: application/json" \
-X POST \
-d '{
"signature": "0x1234567890abcdef...",
"payerAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f42318"
}'
Response:
{
"id": "intent_2xYz9AbC123",
"object": "payment_intent",
"status": "PROCESSING",
"transactionHash": "0xabc123def456...",
"phases": [
{
"phase": "SIGNATURE_VERIFICATION",
"status": "COMPLETED"
},
{
"phase": "BLOCKCHAIN_CONFIRMATION",
"status": "IN_PROGRESS"
}
],
"updated": 1704067250
}
What Happened?โ
- โ Signature verified
- โ Transaction submitted to blockchain
- โ
Status updated to
PROCESSING - โ Blockchain confirmation phase started
Step 5: Check Payment Statusโ
Poll the payment intent to track blockchain confirmation:
curl https://api.fmm.finternetlab.io/v1/payment-intents/intent_2xYz9AbC123 \
-H "X-API-Key: sk_test_your_key_here"
After 5+ confirmations:
{
"id": "intent_2xYz9AbC123",
"object": "payment_intent",
"status": "SUCCEEDED",
"transactionHash": "0xabc123def456...",
"settlementStatus": "IN_PROGRESS",
"phases": [
{
"phase": "BLOCKCHAIN_CONFIRMATION",
"status": "COMPLETED"
},
{
"phase": "SETTLEMENT",
"status": "IN_PROGRESS"
}
],
"updated": 1704067300
}
What Happened?โ
- โ Blockchain transaction confirmed (5+ blocks)
- โ
Status updated to
SUCCEEDED - โ Settlement process initiated
- โ Merchant account credited
Step 6: Settlement Completesโ
Settlement happens automatically in the background. Check status again:
curl https://api.fmm.finternetlab.io/v1/payment-intents/intent_2xYz9AbC123 \
-H "X-API-Key: sk_test_your_key_here"
After settlement:
{
"id": "intent_2xYz9AbC123",
"object": "payment_intent",
"status": "SETTLED",
"settlementStatus": "COMPLETED",
"phases": [
{
"phase": "SETTLEMENT",
"status": "COMPLETED"
}
],
"updated": 1704067400
}
What Happened?โ
- โ Funds converted from crypto to fiat
- โ Funds sent to merchant's bank account
- โ
Status updated to
SETTLED - โ Payment complete!
Complete Flow Diagramโ
flowchart TD
A[Create Intent<br/>Get paymentUrl] -->|INITIATED| B[Redirect user to paymentUrl]
B --> C[Payer signs transaction<br/>on frontend]
C -->|PROCESSING| D[Confirm payment<br/>(auto or manual)]
D -->|SUCCEEDED| E[Blockchain confirmations (5+)]
E -->|SETTLED| F[Settlement completed]
Next Stepsโ
- ๐ Learn about Delivery vs Payment for conditional payment transactions
- โฑ๏ธ Explore Time-Based Payouts for scheduled releases
- ๐ฏ Check out Milestone Payments for project-based payments
- ๐ Read the API Reference for complete details
Common Questionsโ
Q: How long does settlement take?
A: Settlement typically completes within 10-30 seconds for mock settlements. Real bank settlements may take 1-3 business days.
Q: What if the transaction fails?
A: If the blockchain transaction fails, the payment intent status will be REQUIRES_ACTION and you can retry.
Q: Can I cancel a payment?
A: Yes, you can cancel a payment intent in INITIATED or REQUIRES_SIGNATURE status.
Q: How do I handle errors?
A: Check the Error Handling guide for all error codes and how to handle them.