Skip to main content
This guide walks you through creating your first payment in under 5 minutes.

Prerequisites

Merchant Account

A CeyPay merchant account (sign up here)

KYC Verification

Completed merchant onboarding and KYC verification

Programming Language

Your preferred programming language (Node.js, Python, PHP, etc.)

Base URL

Production

Live environment for real transactions
https://api.ceypay.io

Sandbox

Test environment for integration testing
https://sandbox-api.ceypay.io
Getting StartedIf you want to integrate CeyPay without signing up for a sandbox account, use the sandbox API key below.Sandbox API Key:
ak_live_d86855bbd8651fcb5f469203621c88e3.sk_live_6985fca378cd894dee359813bd6bb12f4a2922bc81f023f0d062631e3190ff3e
Remember: The x-api-key header should contain ONLY the key ID (the part before the dot), NOT the full API key. The secret key is used locally to derive the signing key and is never transmitted.

Get Started

1

Generate API Key

  1. Log in to your CeyPay Dashboard
  2. Navigate to SettingsAPI Keys
  3. Click Generate New API Key
  4. Give it a descriptive name (e.g., “Production API Key”)
  5. Copy the API key immediately (you’ll only see it once!)
Your API key looks like: ak_live_abc123xyz.sk_live_def456uvw
  • ak_live_abc123xyz - Public key ID (sent in x-api-key header)
  • sk_live_def456uvw - Secret key (used locally to derive signing key, NEVER transmitted)
Important: Store your API key securely (environment variable, secrets manager, etc.)
2

Make Your First API Call

Create a Payment

Let’s create a simple payment for $100 USDT:
const crypto = require("crypto");
const axios = require("axios");

// Your API key (store in environment variable)
const API_KEY = process.env.CEYPAY_API_KEY; // e.g., ak_live_xxx.sk_live_yyy
const [keyId, secret] = API_KEY.split(".");

// Derive signing key from secret (do this once)
const signingKey = crypto.createHash("sha256").update(secret).digest("hex");

// Create payment
async function createPayment() {
  const timestamp = Date.now().toString();
  const method = "POST";
  const path = "/v1/payment";

  const body = JSON.stringify({
    amount: 100,
    currency: "USDT",
    goods: [
      {
        name: "Premium Plan",
        description: "Monthly subscription to premium features",
      },
    ],
    customerBilling: {
      email: "[email protected]",
      firstName: "John",
      lastName: "Doe",
    },
  });

  // Generate signature using derived key (NOT raw secret)
  const message = timestamp + method + path + body;
  const signature = crypto
    .createHmac("sha256", signingKey)
    .update(message)
    .digest("hex");

  // Make request - send ONLY key ID, not full API key
  const response = await axios.post(
    `https://api.ceypay.io${path}`,
    JSON.parse(body),
    {
      headers: {
        "Content-Type": "application/json",
        "x-api-key": keyId, // Only the key ID!
        "x-timestamp": timestamp,
        "x-signature": signature,
      },
    },
  );

  console.log("Payment created:", response.data);
  console.log("Checkout link:", response.data.checkoutLink);
  console.log("QR code:", response.data.qrContent);

  return response.data;
}

createPayment().catch(console.error);

Response

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "payId": "bybit_pay_abc123",
  "merchantTradeNo": "TXN-2025-12345",
  "amount": 100,
  "currency": "USDT",
  "status": "INITIATED",
  "qrContent": "bybit://pay?id=abc123",
  "checkoutLink": "https://checkout.bybit.com/pay/abc123",
  "createdAt": "2025-01-15T10:30:00.000Z",
  "feeBreakdown": {
    "exchangeFeePercentage": 1.0,
    "exchangeFeeAmount": 1.0,
    "ceypayFeePercentage": 0.5,
    "ceypayFeeAmount": 0.5,
    "netAmount": 98.5
  }
}
Save the id and qrContent from the response. You’ll need them to direct customers to payment.
3

Direct Customer to Payment

You have two options to collect payment:

Redirect to Checkout

Redirect users to the hosted checkout page:
// Redirect user to the checkout link
window.location.href = response.data.checkoutLink;

Display QR Code

Show a QR code for mobile wallet scanning:
// Show QR code for mobile wallet scanning
<img src={`https://api.qrserver.com/v1/create-qr-code/?data=${encodeURIComponent(response.data.qrContent)}&size=300x300`} />
4

Handle Webhook Notifications

Set up a webhook endpoint to receive payment status updates. CeyPay uses ED25519 signatures for security.
const express = require("express");
const crypto = require("crypto");
const app = express();

const CEYPAY_PUBLIC_KEY = `-----BEGIN PUBLIC KEY-----
MCowBQYDK2VwAyEAs+hotF0u5tdoATwAIezK58lzfMZIoKDTlRgoUU+6Qr4=
-----END PUBLIC KEY-----`;

// Use raw body for signature verification
app.use("/webhooks/ceypay", express.raw({ type: "application/json" }));

app.post("/webhooks/ceypay", (req, res) => {
  const signature = req.headers["x-webhook-signature"];
  const timestamp = req.headers["x-webhook-timestamp"];
  const rawBody = req.body.toString("utf8");

  // Verify signature using ED25519
  const message = timestamp + rawBody;

  try {
    const isValid = crypto.verify(
      null,
      Buffer.from(message),
      CEYPAY_PUBLIC_KEY,
      Buffer.from(signature, "base64"),
    );

    if (!isValid) {
      return res.status(401).send("Invalid signature");
    }
  } catch (err) {
    return res.status(401).send("Invalid signature");
  }

  // Process webhook
  const payload = JSON.parse(rawBody);
  if (payload.status === "PAID") {
    console.log("Payment successful! Fulfill order:", payload.paymentId);
  }

  res.status(200).json({ received: true });
});

app.listen(3000, () => console.log("Webhook server running on port 3000"));
See webhooks.md for complete webhook integration guide.

Step 5: Test Your Integration

Test Webhook Endpoint

# Derive signing key first
SIGNING_KEY=$(echo -n "$SECRET" | sha256sum | cut -d' ' -f1)

# Generate signature
TIMESTAMP=$(date +%s)000
MESSAGE="${TIMESTAMP}POST/v1/webhooks/test{\"webhookUrl\": \"https://your-app.com/webhooks/ceypay\"}"
SIGNATURE=$(echo -n "$MESSAGE" | openssl dgst -sha256 -hmac "$SIGNING_KEY" | cut -d' ' -f2)

curl -X POST https://api.ceypay.io/v1/webhooks/test \
  -H "x-api-key: $KEY_ID" \
  -H "x-timestamp: $TIMESTAMP" \
  -H "x-signature: $SIGNATURE" \
  -d '{"webhookUrl": "https://your-app.com/webhooks/ceypay"}'

Test Payment Flow

1

Create a test payment

2

Open the checkout link in your browser

3

Complete the payment (use Bybit test account if available)

4

Verify webhook is received

5

Check payment status via API

Common Use Cases

E-commerce Checkout

// Create payment from shopping cart
const payment = await createPayment({
  amount: cart.total,
  currency: "USDT",
  goods: cart.items.map((item) => ({
    name: item.name,
    description: item.description,
  })),
  customerBilling: {
    email: customer.email,
    firstName: customer.firstName,
    lastName: customer.lastName,
  },
  webhookUrl: "https://mystore.com/api/webhooks/payment",
});

// Redirect to checkout
res.redirect(payment.checkoutLink);
// Create reusable payment link
const paymentLink = await createPaymentLink({
  name: "Premium Plan - Monthly",
  description: "Subscription to premium features",
  amount: 49.99,
  currency: "USDT",
  reusable: true,
});

// Share the link
console.log("Payment link:", `https://pay.ceypay.io/${paymentLink.slug}`);

Invoice Payment

// Create single-use payment link for invoice
const invoice = await createPaymentLink({
  name: `Invoice #${invoiceNumber}`,
  description: "Web development services",
  amount: invoiceAmount,
  currency: "USDT",
  reusable: false,
  expirationDate: "2025-02-28T23:59:59Z",
});

// Email invoice link to customer
sendEmail({
  to: customer.email,
  subject: `Invoice #${invoiceNumber}`,
  body: `Pay your invoice: ${invoice.checkoutUrl}`,
});

Next Steps

Learn More

Authentication

Deep dive into HMAC signature

Webhooks

Complete webhook integration guide

Payment Links

Guide to using payment links

Error Handling

Error codes and troubleshooting

Rate Limits

API rate limiting policies

Explore API Endpoints

Payments:
  • POST /v1/payment - Create payment
  • GET /v1/payment/:id - Get payment details
  • GET /v1/payment - List payments
Payment Links:
  • POST /v1/payment-link - Create payment link
  • GET /v1/payment-link/:id - Get payment link
  • GET /v1/payment-link - List payment links
  • PATCH /v1/payment-link/:id - Update payment link
  • DELETE /v1/payment-link/:id - Deactivate payment link
Webhooks:
  • GET /v1/webhooks/config - Get webhook configuration
  • POST /v1/webhooks/test - Test webhook delivery

API Reference

Full API documentation available at: https://api.ceypay.io/api-docs

Support

Checklist

Before going live, ensure you:
  • Completed merchant onboarding and KYC
  • Generated production API key
  • Stored API key securely (environment variable)
  • Implemented HMAC signature authentication with derived signing key
  • Set up webhook endpoint with signature verification
  • Tested payment flow end-to-end
  • Implemented error handling
  • Configured monitoring and logging
  • Reviewed security best practices
  • Read rate limiting policies

Tips

Security

  • Never commit API keys to version control
  • Use environment variables for secrets
  • Always verify webhook signatures
  • Use HTTPS for all webhook endpoints
  • Send only the key ID in x-api-key, never the full API key

Performance

  • Cache exchange rates when possible
  • Implement idempotent webhook handling
  • Use exponential backoff for retries
  • Monitor rate limit headers

Testing

  • Use ngrok for local webhook testing
  • Create test payments regularly
  • Monitor webhook delivery logs
  • Set up alerts for failed webhooks
Happy coding!