Create Invoice

Creates a payment invoice and returns the URL of a hosted payment page. Redirect your customer to that URL — they pick a coin, send the payment, and Payid19 handles detection, confirmation and crediting your balance in USDT. One request is enough for a complete checkout; everything else on this page is optional fine-tuning.

POSThttps://payid19.com/api/v1/create_invoice
Want the whole payment flow under your own domain and brand? Use the White Label integration — same endpoint, plus white_label=1.

Request parameters

Authentication
public_keystringREQUIRED
Your public API key, from the Settings page.
private_keystringREQUIRED
Your private API key. Keep it secret — it authorizes calls on your account and verifies callbacks.
Amount & currency
price_amountdecimalREQUIRED
Price of the product or service, in price_currency. The customer sees this amount converted to the coin they pick at the current exchange rate.
min0.0001
price_currencystringoptional
Pricing currency. Besides USD you can charge in EUR, GBP, TRY and 150+ other local currencies — the conversion to crypto happens automatically when the customer opens the payment page, so you never touch exchange rates yourself.
defaultUSD
add_fee_to_priceintegeroptional
Send 1 to pass the platform commission on to your customer: it is added on top of your price at checkout, so you receive your full price_amount. For very small invoices (under about 0.20 USD) this is enabled automatically.
values1
margin_ratiodecimaloptional
Underpayment tolerance in USDT. If the received amount falls short of the invoice total by no more than this value, the payment is still completed as successful. Example: with margin_ratio=1 on a 5 USDT invoice, 4 USDT completes the payment, 3.9 USDT does not. Useful because first-time crypto users often send slightly less than requested (their wallet deducts the network fee from the amount they type).
min0.01
Your references — echoed back in the callback
order_idstringoptional
Your own order reference. Echoed back in the callback and searchable with get_invoices — the easiest way to match a payment to an order in your system.
max length100
merchant_idstringoptional
Your own merchant reference, echoed back in the callback. Handy when one Payid19 account serves several shops.
max length150
customer_idintegeroptional
Your own numeric customer reference, echoed back in the callback.
max11 digits
emailstringoptional
Buyer’s email address. If omitted, the customer enters it on the payment page. Must be a valid email address when sent.
Payment page appearance
titlestringoptional
Title shown at the top of the payment page — typically your product or order name.
max length150
descriptionstringoptional
Description shown under the title on the payment page. Values up to 300 characters are accepted, but only the first 180 are stored and displayed.
max length300shownfirst 180
banned_coinsJSONoptional

Coins you do not want offered on this invoice, as a JSON array. A bare coin code hides it on every network; a COIN-NETWORK pair hides that network only.

["BTC","ETH","USDT-ERC20"] hides Bitcoin, Ethereum and USDT on ERC20 only · ["USDT","BNB"] hides USDT on all networks and BNB.

Redirects & notifications
callback_urlURLoptional
Your webhook URL. Payid19 POSTs the payment result here when the invoice is paid — see Payment callback below. Must be a public domain (not an IP address or localhost); for local development use ngrok or webhook.site.
max length300
success_urlURLoptional
Where the customer is redirected after a successful payment — your “thank you” page. Treat it as cosmetic only: mark orders as paid from the callback, never from the customer reaching this URL.
max length300
cancel_urlURLoptional
Where the customer is redirected if they cancel on the payment page.
max length300
Behavior
testintegeroptional
Send 1 to create a test invoice: it completes automatically within seconds — including the callback — without any real payment. The fastest way to verify your whole integration end to end before going live.
values1
expiration_dateintegeroptional
Accepted for backwards compatibility (1–360, in hours). Invoices are currently valid for 24 hours; unpaid invoices are removed after they expire.
white_labelintegeroptional
Send 1 to receive a JSON list of available coins instead of a payment page URL, and build the checkout under your own brand. See White Label.
values1
referralnumericoptional
Your own referral ID — the 10-digit number on the Referral page of your dashboard. Send it when you create invoices for someone else’s business and half of the Payid19 commission on every payment that invoice receives is credited to you. See Earning on the invoices you create below.
example9670126418
About add_fee_to_price: a higher, less round checkout total makes incorrect transfers slightly more likely and can reduce conversion. Unless you specifically need to receive the exact price_amount, leaving it off usually converts better.

Response

statusstring
success or error.
messagestring / array
The payment page URL on success; an array of error messages on error. With white_label=1, a JSON list of coins instead.

Successful response — redirect your customer to the URL in message:

{"status":"success","message":"https:\/\/payid19.com\/invoice\/Xy3kP9..."}

Error responses come with HTTP status 421 and a human-readable message array — show or log message[0]:

{"status":"error","message":["Wrong public or private key."]}

Example request

curl -X POST https://payid19.com/api/v1/create_invoice \
  -d public_key=YOUR_PUBLIC_KEY \
  -d private_key=YOUR_PRIVATE_KEY \
  -d price_amount=100 \
  -d price_currency=USD \
  -d order_id=42 \
  -d [email protected] \
  -d callback_url=https://yoursite.com/payment/callback \
  -d success_url=https://yoursite.com/payment/success \
  -d cancel_url=https://yoursite.com/payment/cancel
<?php
$post = [
    'public_key'   => 'YOUR_PUBLIC_KEY',
    'private_key'  => 'YOUR_PRIVATE_KEY',
    'price_amount' => 100,
    'price_currency' => 'USD',
    'order_id'     => 42,
    'email'        => '[email protected]',
    'callback_url' => 'https://yoursite.com/payment/callback',
    'success_url'  => 'https://yoursite.com/payment/success',
    'cancel_url'   => 'https://yoursite.com/payment/cancel',
    // 'test' => 1,                // test invoice: completes automatically
    // 'banned_coins' => json_encode(["BTC","ETH"]),
];

$ch = curl_init('https://payid19.com/api/v1/create_invoice');
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post));
$result = curl_exec($ch);
curl_close($ch);

$response = json_decode($result);
if ($response->status == 'error') {
    echo $response->message[0];          // handle the error
} else {
    header('Location: ' . $response->message);  // redirect to the payment page
}
const axios = require('axios');

const postData = {
    public_key:   'YOUR_PUBLIC_KEY',
    private_key:  'YOUR_PRIVATE_KEY',
    price_amount: 100,
    price_currency: 'USD',
    order_id:     42,
    email:        '[email protected]',
    callback_url: 'https://yoursite.com/payment/callback',
    success_url:  'https://yoursite.com/payment/success',
    cancel_url:   'https://yoursite.com/payment/cancel',
};

axios.post('https://payid19.com/api/v1/create_invoice', postData)
    .then(({ data }) => {
        if (data.status === 'error') {
            console.error(data.message[0]);   // handle the error
        } else {
            console.log(data.message);        // the payment page URL
        }
    })
    .catch(err => console.error(err.message));
import requests

post_data = {
    'public_key':   'YOUR_PUBLIC_KEY',
    'private_key':  'YOUR_PRIVATE_KEY',
    'price_amount': 100,
    'price_currency': 'USD',
    'order_id':     42,
    'email':        '[email protected]',
    'callback_url': 'https://yoursite.com/payment/callback',
    'success_url':  'https://yoursite.com/payment/success',
    'cancel_url':   'https://yoursite.com/payment/cancel',
}

response = requests.post('https://payid19.com/api/v1/create_invoice', data=post_data)
result = response.json()

if result['status'] == 'error':
    print(result['message'][0])   # handle the error
else:
    print(result['message'])      # the payment page URL

Payment callback (webhook)

When the invoice is paid, Payid19 sends a POST request with a JSON body (Content-Type: application/json) to your callback_url. A callback is only sent for completed payments — receiving one means the invoice is paid; you never get callbacks for pending or expired invoices.

Callback payload
privatekeystring
Your private key. Compare it with your own copy — a match proves the callback really came from Payid19.
idinteger
Payid19’s invoice ID.
order_id / merchant_id / customer_idstring / integer
The references you set when creating the invoice, echoed back unchanged — use them to find the matching order in your database.
price_amount / price_currencydecimal / string
The original invoice amount and currency you requested.
amount / amount_currencydecimal / string
What the customer actually paid, in the coin they picked.
…and the rest
user_id, email, add_fee_to_price, title, description, ref_url, cancel_url, success_url, callback_url, ip, test, created_at, expiration_date — a full snapshot of the invoice, so you rarely need a follow-up API call.
Security checklist: verify that privatekey equals your own private key before trusting a callback, and respond with HTTP 2xx. If your endpoint does not return 2xx, delivery is attempted up to 3 times in total (two automatic retries with increasing delays). Callbacks can arrive from different IP addresses, so do not filter by sender IP — the privatekey check is the right way to authenticate them. When in doubt, you can always confirm a payment independently with get_invoices.
<?php
$data = json_decode(file_get_contents('php://input'));

if ($data->privatekey != 'YOUR_PRIVATE_KEY') {   // verify the sender
    http_response_code(403);
    die;
}

// payment confirmed - mark order $data->order_id as paid
http_response_code(200);
const express = require('express');
const app = express();
app.use(express.json());

app.post('/payment/callback', (req, res) => {
    if (req.body.privatekey !== 'YOUR_PRIVATE_KEY') {   // verify the sender
        return res.status(403).send('Forbidden');
    }
    // payment confirmed - mark order req.body.order_id as paid
    res.sendStatus(200);
});

app.listen(3000);
from flask import Flask, request

app = Flask(__name__)

@app.route('/payment/callback', methods=['POST'])
def payment_callback():
    data = request.get_json()
    if data.get('privatekey') != 'YOUR_PRIVATE_KEY':   # verify the sender
        return 'Forbidden', 403
    # payment confirmed - mark order data['order_id'] as paid
    return 'OK', 200

app.run(port=5000)

How the payment flow works

  1. Checkout: your customer chooses to pay with crypto and you redirect them to the invoice URL returned by this endpoint.
  2. Payment: they pick a coin and network, and send the shown amount to a unique deposit address (QR code included).
  3. Confirmation: Payid19 monitors the blockchain and marks the invoice as paid once the payment is confirmed. Your balance is credited in USDT with the fee already deducted.
  4. Webhook: the callback hits your server; you verify privatekey, mark the order as paid and respond with 200.
  5. Redirect: the customer lands on your success_url; they receive an email receipt and the payment appears in your dashboard notifications.

Earning on the invoices you create

If you build stores or software for other businesses, add your own referral ID to the invoices you create for them. Payid19 charges the merchant a 1% commission on incoming payments; when an invoice carries your referral ID, half of that commission is credited to your balance in USDT every time the invoice is paid — not just on the first payment, but for as long as the integration keeps running.

curl -X POST https://payid19.com/api/v1/create_invoice \
  -d public_key=CLIENT_PUBLIC_KEY \
  -d private_key=CLIENT_PRIVATE_KEY \
  -d price_amount=100 \
  -d referral=9670126418          # your referral ID - you earn on this invoice
Your client is not charged anything extra: your share comes out of the Payid19 commission, not out of their payment. Referral earnings land directly in your withdrawable balance, without the holding period that applies to your own sales. Full terms are on the developer referral program page.

Integration tips

  • Always set an order_id and treat the callback as the single source of truth — reaching success_url is not proof of payment (a customer can open that URL by hand).
  • Make your callback handler idempotent: because failed deliveries are retried, the same callback can occasionally arrive more than once. Marking an already-paid order as paid again must be harmless.
  • Start with test=1. A test invoice runs the whole pipeline — payment page, confirmation, callback — in seconds, with no real money.
  • Don’t reuse invoices. Create a fresh invoice for every checkout attempt; they cost nothing and each one gets its own deposit address.
Underpayments and overpayments are handled automatically — partial payments can be completed to the same address, accepted from your Invoices page, or refunded. See the FAQ for details.