All posts
payment testingwebhooksapistripecheckout

How to Test Payment Integrations with MockCard.io

March 16, 20265 min read

Payment testing tools are usually either too simple (a list of Stripe test card numbers) or too complex (a full sandbox environment that takes a day to configure). MockCard.io sits in the middle: a real API endpoint you can call in seconds that returns a test card complete with a signed webhook event — no account needed for your first 10 tries.

This guide walks through everything from signing up to receiving your first webhook in under five minutes.


The Problem MockCard.io Solves

When you are building a checkout flow you typically need to test at least five scenarios before going live:

  • A successful payment
  • An insufficient funds decline
  • A do-not-honor hard decline
  • An expired card
  • A 3DS challenge redirect

Getting consistent, repeatable test cards for all of these from a live payment gateway is painful. MockCard.io generates structurally valid cards (Luhn-correct, real BIN ranges, realistic CVVs) for each scenario on demand, and immediately fires a signed payment_intent.succeeded or payment_intent.payment_failed webhook to whatever URL you point at — so you can develop your webhook handler without touching a real gateway at all.


Step 1 — Get Your Free API Key

  1. Open mockcard.io and click Get API Key in the top navigation.
  2. Enter your email address. A six-digit OTP arrives within a few seconds.
  3. Enter the code. Your API key is shown immediately — it looks like mc_2c65....
  4. Copy it. You will not see it again (but you can always generate a new one from the dashboard).

Free tier gives you 500 generations per calendar month. No credit card required.


Step 2 — Your First Request

The single endpoint is:

POST https://mockcard.io/api/v1/generate
Content-Type: application/json
X-Api-Key: YOUR_KEY

cURL

curl -s -X POST https://mockcard.io/api/v1/generate \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: YOUR_KEY" \
  -d '{
    "brand":       "visa",
    "scenario":    "success",
    "amount":      1999,
    "currency":    "usd",
    "webhook_url": "https://webhook.site/your-unique-id"
  }' | jq .

Postman / Insomnia

  1. Create a new POST request to https://mockcard.io/api/v1/generate.
  2. Set the Content-Type header to application/json and add X-Api-Key with your key.
  3. Paste the JSON body above into the raw body tab.
  4. Hit Send.

Step 3 — Understanding the Response

A successful call returns HTTP 201 with a JSON body like this:

{
  "status": "success",
  "scenario": "success",
  "card": {
    "brand": "visa",
    "card_number": "4474045071275931",
    "masked_number": "••••••••••••5931",
    "expiry_month": "06",
    "expiry_year": "2029",
    "cvv": "982",
    "cardholder_name": "PRIYA PATEL",
    "luhn_valid": true
  },
  "webhook_event": {
    "id": "evt_mock_765bb955a3b5",
    "object": "event",
    "type": "payment_intent.succeeded",
    "created": 1773577425,
    "livemode": false,
    "data": {
      "object": {
        "id": "pi_mock_05b6de1ab8ba",
        "object": "payment_intent",
        "amount": 1999,
        "currency": "usd",
        "status": "succeeded"
      }
    }
  }
}

The card object contains everything a payment form needs: a 16-digit Luhn-valid number, expiry, CVV, and a plausible cardholder name. The webhook_event mirrors a real Stripe-style event payload and is delivered to your webhook_url simultaneously.


Step 4 — Receiving the Webhook

If you passed a webhook_url, MockCard.io will POST the webhook_event object to that URL within a second of your API call. The request includes two headers:

Header Description
X-MockCard-Event Event type, e.g. payment_intent.succeeded
X-MockCard-Signature sha256=<HMAC-SHA256 hex> signed with your webhook secret

Verifying the signature (Node.js)

const crypto = require("crypto");

function verifyMockCardWebhook(rawBody, signatureHeader, secret) {
  const expected = "sha256=" + crypto
    .createHmac("sha256", secret)
    .update(rawBody)
    .digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(signatureHeader)
  );
}

Verifying the signature (Python)

import hmac, hashlib

def verify_mockcard_webhook(raw_body: bytes, signature_header: str, secret: str) -> bool:
    expected = "sha256=" + hmac.new(
        secret.encode(), raw_body, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, signature_header)

For a quick throwaway receiver during development, webhook.site gives you a public URL that logs every incoming request — no setup needed.


Step 5 — Testing Other Scenarios

Change the scenario field to simulate different outcomes:

Scenario HTTP Status Webhook Event
success 201 payment_intent.succeeded
insufficient_funds 402 payment_intent.payment_failed
do_not_honor 402 payment_intent.payment_failed
expired_card 402 payment_intent.payment_failed
incorrect_cvv 402 payment_intent.payment_failed
3ds_challenge 402 — (redirect URL returned instead)
network_timeout 504 payment_intent.payment_failed

Example — testing an insufficient funds decline:

curl -s -X POST https://mockcard.io/api/v1/generate \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: YOUR_KEY" \
  -d '{"brand":"mastercard","scenario":"insufficient_funds","amount":5000,"currency":"inr","webhook_url":"https://webhook.site/your-unique-id"}' \
  | jq .error

You will receive a 402 response with a structured error and a payment_intent.payment_failed event at your webhook URL.


Step 6 — The 3DS Challenge Flow

When you request the 3ds_challenge scenario, the API returns a challenge_url instead of a card. Open that URL in the browser — you will see a mock bank OTP screen. Enter 123456, and MockCard.io fires a payment_intent.succeeded webhook to your webhook_url and redirects to your return_url.

curl -s -X POST https://mockcard.io/api/v1/generate \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: YOUR_KEY" \
  -d '{
    "brand":       "visa",
    "scenario":    "3ds_challenge",
    "amount":      2500,
    "currency":    "usd",
    "webhook_url": "https://webhook.site/your-unique-id",
    "return_url":  "https://yourapp.com/payment/complete"
  }' | jq .error.challenge_url

Supported Card Brands

MockCard.io generates cards across four networks, each with realistic BIN ranges:

  • Visa — 16-digit, prefix 4
  • Mastercard — 16-digit, prefix 51–55
  • RuPay — 16-digit, prefix 60
  • Amex — 15-digit, prefix 34 or 37

What's Next

  • Dashboard — log in at mockcard.io/dashboard to see your usage, manage API keys, and review every request with its full request/response log and webhook delivery status.
  • Playgroundmockcard.io/playground lets you fire requests and watch the card and webhook event animate in — useful for demos or quick sanity checks.
  • Test Cards referencemockcard.io/test-cards lists every scenario with a sample response.

If you have feedback or feature requests, reach out at support@mockcard.io or use the contact form.