External Payments API

The External Payments API allows you to create payment prompts programmatically from your backend. When a payment is created, you receive a checkout URL to redirect your customer.

Authentication

All API requests require HTTP Basic Authentication using your Client ID and API Key:

Authorization: Basic base64(clientId:apiKey)

The credentials must belong to a Merchant Admin user with an active account. See Prerequisites for details on obtaining and using your credentials.

Create Payment Prompt

Creates a new payment prompt and returns a checkout URL.

Endpoint: POST /external/payments/prompt

Headers:

Header

Required

Description

Content-Type

Yes

Must be application/json

Authorization

Yes

Basic authentication (Base64 encoded clientId:apiKey)

Request Body:

Payer Options:

  • customer: The customer pays the network fee (added to the payment amount)

  • merchant: You absorb the network fee (deducted from your settlement)

Warning

Every blockchain ID in the blockchainIds array must have a payment address configured for your merchant account. If any of the requested blockchains are missing a payment address, the request will be rejected. Use GET /external/blockchains/active to check which blockchains are available, and configure payment addresses in your merchant dashboard.

Example Request:

curl -X POST https://api.miraclecash.info/external/payments/prompt \
  -H "Content-Type: application/json" \
   -H "Authorization: Basic $(echo -n 'your_client_id:your_api_key' | base64)" \
   -d '{
    "amount": 100.50,
    "blockchainIds": ["eth"],
    "payer": "customer",
    "note": "Order #12345",
    "redirectUrl": "https://shop.example.com/order/12345/complete"
  }'

Example Response:

{
  "prompt": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "amount": 103.52,
    "commissionAmount": "3.02",
    "status": "pending",
    "sessionStatus": "pending",
    "expiresAt": "2025-01-29T14:30:00.000Z",
    "createdAt": "2025-01-28T14:30:00.000Z",
    "redirectUrl": "https://shop.example.com/order/12345/complete"
  },
  "checkoutUrl": "https://checkout.miraclepay.com/?sessionId=550e8400-e29b-41d4-a716-446655440000"
}

Response Fields:

Field

Type

Description

prompt.id

string

Unique payment prompt ID (UUID)

prompt.amount

number

Final amount including commission (if payer is customer)

prompt.commissionAmount

string

Commission fee amount in USD

prompt.status

string

Payment status: pending

prompt.sessionStatus

string

Checkout session status: pending

prompt.expiresAt

string

ISO 8601 timestamp when payment expires (24 hours)

prompt.createdAt

string

ISO 8601 timestamp when payment was created

prompt.redirectUrl

string or null

The redirect URL provided in the request, or null if not provided

checkoutUrl

string

URL to redirect the customer for payment

Get Payment Status

Retrieves the current status of a payment prompt.

Endpoint: GET /external/payments/prompt/:id

Headers:

Header

Required

Description

Authorization

Yes

Basic authentication (Base64 encoded clientId:apiKey)

Path Parameters:

Parameter

Type

Description

id

string

The payment prompt UUID

Example Request:

curl -X GET https://api.miraclecash.info/external/payments/prompt/550e8400-e29b-41d4-a716-446655440000 \
  -H "Authorization: Basic $(echo -n 'your_client_id:your_api_key' | base64)"

Example Response:

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "blockchainId": "eth",
  "status": "successful",
  "createdAt": "2025-01-28T14:30:00.000Z"
}

Payment Status Values:

Status

Description

pending

Payment initiated, awaiting customer action

successful

Payment confirmed on the blockchain

unsuccessful

Payment failed (e.g., insufficient funds)

expired

Customer did not complete payment within 24 hours

cancelled

Payment was cancelled

Error Responses

HTTP Status Codes:

Error Response Format:

{
  "statusCode": 401,
  "message": "Invalid client ID",
  "error": "Unauthorized"
}

Integration Examples

Node.js / TypeScript

import axios from 'axios';

const MIRACLEPAY_CLIENT_ID = process.env.MIRACLEPAY_CLIENT_ID;
const MIRACLEPAY_API_KEY = process.env.MIRACLEPAY_API_KEY;
const MIRACLEPAY_BASE_URL = 'https://api.miraclecash.info';

// Create Basic Auth header
const authHeader = `Basic ${Buffer.from(`${MIRACLEPAY_CLIENT_ID}:${MIRACLEPAY_API_KEY}`).toString('base64')}`;

interface CreatePaymentResponse {
  prompt: {
    id: string;
    amount: number;
    status: string;
    createdAt: string;
  };
  checkoutUrl: string;
}

async function createPayment(
  amount: number,
  blockchainIds: string[],
  note?: string,
  redirectUrl?: string
): Promise<CreatePaymentResponse> {
  const response = await axios.post<CreatePaymentResponse>(
    `${MIRACLEPAY_BASE_URL}/external/payments/prompt`,
    {
      amount,
      blockchainIds,
      payer: 'customer',
      note,
      redirectUrl,
    },
    {
      headers: {
        'Content-Type': 'application/json',
        'Authorization': authHeader,
      },
    }
  );
  return response.data;
}

async function getPaymentStatus(promptId: string) {
  const response = await axios.get(
    `${MIRACLEPAY_BASE_URL}/external/payments/prompt/${promptId}`,
    {
      headers: {
        'Authorization': authHeader,
      },
    }
  );
  return response.data;
}

// Usage
async function handleCheckout(orderId: string, amount: number) {
  const returnUrl = `https://shop.example.com/orders/${orderId}/complete`;
  const payment = await createPayment(amount, ['eth'], `Order #${orderId}`, returnUrl);

  // Store prompt.id in your database linked to the order
  await savePaymentToOrder(orderId, payment.prompt.id);

  // Redirect customer to checkout
  return { redirectUrl: payment.checkoutUrl };
}

Best Practices

  1. Store payment IDs: Always save the prompt.id in your database linked to the corresponding order for reconciliation.

  2. Handle errors gracefully: Implement retry logic with exponential backoff for transient failures.

  3. Validate amounts: Ensure payment amounts are valid numbers with up to 2 decimal places.

  4. Test first: Always test your integration using testnet blockchain IDs before going live.

  5. Do not trust the redirect: When using redirectUrl, the customer is redirected with ?promptId=...&status=... query parameters. Never use these parameters as proof of payment. Always verify the payment status server-side via GET /external/payments/prompt/:id before fulfilling orders.

  6. Configure allowed redirect domains: Before using redirectUrl, you must add the domain to your allowed redirect domains list in the MiraclePay dashboard. Only fully qualified domain names (e.g., shop.example.com) are allowed, up to 20 domains maximum.

Allowed Redirect Domains

For security reasons, redirect URLs are validated against an allowlist of domains configured in your merchant account.

Dashboard Configuration:

Configure your allowed redirect domains in the MiraclePay merchant dashboard under Developer Settings. Each domain must be a valid fully qualified domain name (FQDN).

Example allowed domains:

  • shop.example.com

  • store.mysite.com

  • checkout.yourdomain.com

Limits:

  • Maximum 20 domains per merchant account

  • Only FQDNs are accepted (no paths, protocols, or wildcards)

  • The hostname of your redirectUrl must exactly match one of the configured domains