Playground API
DocsStatsBlogStudio
Documentation Tree
Technical BlogFeature Deep Dives
  • Introduction
  • Quickstart
    5 min
  • How It Works
  • Recipes & Cookbooks
  • Platform Comparisons
  • Real-World Showcase
  • Interactive Studio
    Studio
  • GraphiQL IDE
    IDE
  • Session Quotas & Activity
  • Network Chaos Simulator
  • Atomic Sandbox Reset
  • Overview & Models
    Hub
  • Users Resource
  • Posts Resource
  • Comments Resource
  • Todos Resource
  • Custom Collections
    Custom
  • Multipart File Uploads
    Upload
  • Dynamic SVG Avatars
    SVG
  • Image Thumbnails
    CDN
  • Relational Filtering
  • Full-Text Search
  • Dynamic Sorting
  • Offset Pagination
  • Cursor Pagination
    Scroll
  • CSV & Excel Export & Import
    IO
  • Custom Collections
    CRUD
  • Overview & Architecture
    Hub
  • JWT Auth Flow
  • Refresh Token Rotation
    Mutex
  • RBAC Permission Matrix
    Roles
  • Expiry Simulation
  • Clock Skew Drift
  • Password Recovery Loop
  • Dual-Mode Sandboxing
  • GraphiQL IDE
    IDE
  • Relational Queries
  • Stateful Mutations
  • Realtime Subscriptions
  • Overview & Flowcharts
    Hub
  • Hosted Checkout
    Stripe
  • Payment Intents API
  • 3DS Challenge Modal
    Modal
  • Customers Vault
  • Charges & Refunds
  • Test Cards Catalog
  • Overview & Channels
    Hub
  • Virtual Email Mailbox
    Mailtrap
  • Virtual SMS Terminal
    Phone
  • In-App Notifications
  • Message Dispatcher
  • Realtime Studio
    Studio
  • Native WebSocket (/ws)
  • Socket.io Gateway
  • Presence & Echo Bot
  • Server-Sent Events (SSE)
    SSE
  • Analytics Telemetry
  • Webhook Subscriptions
  • HMAC SHA-256 Signatures
  • Delivery Logs
  • Manual Retry Simulator
  • Network Latency Delay
  • HTTP Status Codes
  • Rate-Limit Simulator
    429
  • Flaky Network & Jitter
    Chaos
  • Session Quotas & Activity
  • JSON Snapshots
    JSON
  • Headless CI/CD Testing
    CI
  • Mobile QR Code Sync
  • System Metrics & Health
  • Atomic Sandbox Reset
  • Official TypeScript SDK
  • Multi-Language Generators
  • DevTools Extension
  • OpenAPI 3.1 Spec
    JSON
  • Postman Collection v2.1
  • Bruno Collection
  • Insomnia Workspace
  • TypeScript .d.ts
    .d.ts
  • AI Prompt Rules
    Rules
  • Context Index (llms.txt)
  • Full Schema (llms-full.txt)
  • Manifest (product.json)
  • All Feature Articles
    Blog
  • React CRUD Without Backend
    Deep Dive
  • Why Static APIs Fail
  • Mocking Stateful Auth
  • WebSockets & SSE Guide
Technical Blog
Articles

In-depth articles explaining stateful mock APIs, WebSockets, payments, and frontend resilience.

Read Articles
PreviousHosted Checkout
Next3DS Challenge Modal
Mock Commerce & Billing

Payment Intents API

Model production payment lifecycles with stateful intents, client secrets, two-phase authorizations, and automated webhook events. Supports both automatic immediate capture and manual two-step authorization/capture workflows.

State Machine LifecycleInteractive PlaygroundIdempotency Keys

Payment Intent State Machine

Every PaymentIntent transitions through well-defined, immutable terminal or transitional states.

Step 1

requires_payment_method

Intent created on backend. Safe client_secret returned to frontend UI.

Action

requires_action

3DS 2.0 challenge or biometric authorization required before the bank approves funds.

Auth

requires_capture

Card authorized for two-step fulfillment (capture_method: "manual"). Awaiting capture.

Final

succeeded

Funds debited. Email receipt delivered to Virtual Inbox. Webhook dispatched.

Interactive Intent Execution

Test every step of the payment pipeline directly against your live isolated visitor sandbox.

Workflow: Backend invokes this endpoint when user initializes checkout. Amount is in the smallest currency unit (e.g. 4900 = $49.00 USD).

Create Payment Intent

POST
response.json
1
{
2
// Click "Send" above to execute this request against the live server.
3
}

Idempotency & Replay Protection

Prevent double-billing on network drops, mobile connection switching, and client retries.

How Idempotency Works

Attach a unique Idempotency-Key: <uuid> header to any POST request. If a retry occurs with the exact same key:

  • No duplicate charges or cards are processed.
  • The initial response payload is replayed verbatim.
  • The response includes header Idempotent-Replay: true.
  • Keys are cached per visitor sandbox for 24 hours.

Recommended Key Generation

Always tie your idempotency key to a specific checkout cart ID or user action attempt rather than a generic random string:

const idempotencyKey = `pay_${cartId}_${attemptIndex}`;

Production Integration Recipes

Complete client-side and server-side code samples for modern frameworks.

Frontend React Hook (Custom / Stripe Elements)

typescript
1
import { useState } from 'react';
2
3
export function usePaymentIntent() {
4
const [loading, setLoading] = useState(false);
5
const [error, setError] = useState<string | null>(null);
6
7
const processPayment = async (amount: number, cardDetails: any) => {
8
setLoading(true);
9
setError(null);
10
11
try {
12
// 1. Create intent on your backend
13
const res = await fetch('/api/create-intent', {
14
method: 'POST',
15
headers: { 'Content-Type': 'application/json' },
16
body: JSON.stringify({ amount }),
17
});
18
const { clientSecret, intentId } = await res.json();
19
20
// 2. Confirm intent with card data
21
const confirmRes = await fetch(https://playground.nileslabs.com/api/v1/payments/intents/${intentId}/confirm`, {
22
method: 'POST',
23
headers: {
24
'Content-Type': 'application/json',
25
'Idempotency-Key': idem_${intentId},
26
},
27
body: JSON.stringify({ payment_method: cardDetails }),
28
});
29
30
const result = await confirmRes.json();
31
return result;
32
} catch (err: any) {
33
setError(err.message || 'Payment failed');
34
throw err;
35
} finally {
36
setLoading(false);
37
}
38
};
39
40
return { processPayment, loading, error };
41
}

Python Backend Client

python
1
import requests
2
import uuid
3
4
API_BASE = "https://playground.nileslabs.com/api/v1"
5
6
def create_and_confirm_payment(amount_cents: int, card_num: str):
7
idempotency_key = f"order_py_{uuid.uuid4().hex[:12]}"
8
9
# 1. Create Intent
10
intent = requests.post(
11
f"{API_BASE}/payments/intents",
12
json={
13
"amount": amount_cents,
14
"currency": "usd",
15
"capture_method": "automatic",
16
"description": "Python SDK Test Order"
17
},
18
headers={"Idempotency-Key": idempotency_key}
19
).json()
20
21
intent_id = intent["id"]
22
23
# 2. Confirm Intent
24
confirmed = requests.post(
25
f"{API_BASE}/payments/intents/{intent_id}/confirm",
26
json={
27
"payment_method": {
28
"card_number": card_num,
29
"exp_month": 12,
30
"exp_year": 2028,
31
"cvc": "123"
32
}
33
}
34
).json()
35
36
return confirmed