Integration Guide

This guide explains how to integrate MiraclePay into your application to accept cryptocurrency payments. The External Payments API (base path /external/v1) lets you create payment requests programmatically and redirect customers to a hosted checkout page. All requests are signed with your API key — see Authentication.

Merchant partners can also create payments for assigned merchants and use signed reporting routes under /external/partner; see Merchant-Partner API. This guide reflects the current backend controller, DTO, authentication, idempotency and webhook implementations as reviewed on 2026-09-14.

Quick Start

  1. Create an API key in the merchant panel under Settings → Developer → API Keys — you get a key ID (mpay_pk_...), a secret (mpay_sk_..., shown only once) and a passphrase

  2. Sign your requests with HMAC-SHA512 — see Authentication

  3. Create a payment prompt via POST /external/v1/payments/prompt — amounts are in cents (1099 = $10.99). Networks are optional: omit blockchainIds and the customer is offered everything your account can be paid on — see External Payments API

  4. Redirect your customer to the returned checkoutUrl

  5. Confirm the outcome via Webhooks or GET /external/v1/payments/:id — never from redirect query parameters

import { createHmac, randomUUID } from "node:crypto";

const BASE_URL = "https://api.miraclecash.info";

async function createPayment(idempotencyKey: string) {
  // Persist one key per intended payment and pass it again on retries.
  const method = "POST";
  const path = "/external/v1/payments/prompt";
  const rawBody = JSON.stringify({
    amount: 1099, // $10.99 in cents
  });

  const timestamp = Math.floor(Date.now() / 1000).toString();
  const nonce = randomUUID();
  const signature = createHmac("sha512", process.env.MPAY_SECRET!)
    .update([timestamp, nonce, method, path, rawBody].join("\n"))
    .digest("hex");

  const response = await fetch(`${BASE_URL}${path}`, {
    method,
    headers: {
      "Content-Type": "application/json",
      "X-MP-KEY-ID": process.env.MPAY_KEY_ID!,
      "X-MP-PASSPHRASE": process.env.MPAY_PASSPHRASE!,
      "X-MP-TIMESTAMP": timestamp,
      "X-MP-NONCE": nonce,
      "X-MP-SIGNATURE": signature,
      "Idempotency-Key": idempotencyKey,
    },
    body: rawBody,
  });

  if (!response.ok) {
    const { error } = await response.json();
    throw new Error(`${error.errorCode}: ${error.message}`);
  }
  const { prompt, checkoutUrl } = await response.json();
  // Redirect your customer to checkoutUrl
}