Get started
Quickstart
Take a payment end to end: create it, send the buyer to the hosted checkout, and confirm it with a signed webhook.
-
Get your API key
Sign in, open Developer in the dashboard and copy your key. It identifies your account on every request.
Keep the key on your serverAnyone holding it can create transactions, change your settings and withdraw your balance. Never put it in a web page, an app or a repository.
-
Create a transaction
Ask for 20 USD and pass the URL that should receive webhooks. Store the
private_keyfrom the response with your order: it is returned once, and it is the secret your webhooks are signed with.Request curl https://anonpay.org/api/transaction/create \ -H "Authorization: Bearer $APA_KEY" \ -d amount=20 \ -d currency=usd \ -d allowed_payment_methods=btc,xmr,usdt-erc20 \ -d webhook=https://seller.example/hooks/apa \ -d idempotency_key=2c9a4e7b-8d1f-4a6cimport os import requests KEY = os.environ["APA_KEY"] response = requests.post( "https://anonpay.org/api/transaction/create", headers={"Authorization": f"Bearer {KEY}"}, data={ "amount": "20", "currency": "usd", "allowed_payment_methods": "btc,xmr,usdt-erc20", "webhook": "https://seller.example/hooks/apa", "idempotency_key": "2c9a4e7b-8d1f-4a6c", }, timeout=30, ) print(response.json())const url = "https://anonpay.org/api/transaction/create"; const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${process.env.APA_KEY}` }, body: new URLSearchParams({ amount: "20", currency: "usd", allowed_payment_methods: "btc,xmr,usdt-erc20", webhook: "https://seller.example/hooks/apa", idempotency_key: "2c9a4e7b-8d1f-4a6c", }), }); console.log(await response.json());$url = 'https://anonpay.org/api/transaction/create'; $key = getenv("APA_KEY"); $ch = curl_init($url); curl_setopt_array($ch, [ CURLOPT_HTTPHEADER => ["Authorization: Bearer $key"], CURLOPT_POSTFIELDS => http_build_query([ "amount" => '20', "currency" => 'usd', "allowed_payment_methods" => 'btc,xmr,usdt-erc20', "webhook" => 'https://seller.example/hooks/apa', "idempotency_key" => '2c9a4e7b-8d1f-4a6c', ]), CURLOPT_RETURNTRANSFER => true, ]); $response = json_decode(curl_exec($ch), true); -
Send the buyer to checkout
Redirect the buyer to the hosted checkout. They choose a payment method there and get an address, or PayPal details, to pay. Hosted checkout shows what they see and how to style it.
Checkout URL https://anonpay.org/checkout/9c1f0b7a4e2d8f6a3b5c7d9e1f0a2b4c -
Receive the webhook
When the payment confirms we POST a
completedevent to your URL. Find the order, verify the signature with its private key, mark it paid, and answer with any 2xx.verifyis the function from Webhooks.Handler import json from flask import Flask, request from shop.orders import Order from shop.webhooks import verify app = Flask(__name__) @app.post("/hooks/anonpay") def anonpay(): raw = request.get_data() event = json.loads(raw) order = Order.by_transaction(event.get("transaction_id")) if order is None: return "", 404 signature = request.headers.get("X-Signature", "") if not verify(order.private_key, signature, raw): return "", 400 if event["event"] == "completed": order.mark_paid() return "", 204import express from "express"; import { Order } from "./orders.js"; import { verify } from "./webhooks.js"; const app = express(); app.post("/hooks/anonpay", express.raw({ type: "application/json" }), async (req, res) => { const event = JSON.parse(req.body); const order = await Order.byTransaction(event.transaction_id); if (!order) return res.sendStatus(404); const signature = req.get("X-Signature") ?? ""; if (!verify(order.privateKey, signature, req.body)) { return res.sendStatus(400); } if (event.event === "completed") await order.markPaid(); res.sendStatus(204); });$raw = file_get_contents("php://input"); $event = json_decode($raw, true); $order = Order::byTransaction($event["transaction_id"] ?? ""); if ($order === null) { http_response_code(404); exit; } $signature = $_SERVER["HTTP_X_SIGNATURE"] ?? ""; if (!verify($order->privateKey, $signature, $raw)) { http_response_code(400); exit; } if ($event["event"] === "completed") { $order->markPaid(); } http_response_code(204); -
Check before you ship
A webhook tells you something changed; the API is the record. Fetch the transaction and check that
statusiscompletedbefore you deliver anything valuable.Request curl https://anonpay.org/api/transaction/info \ -H "Authorization: Bearer $APA_KEY" \ -d transaction_id=9c1f0b7a4e2d8f6a3b5c7d9e1f0a2b4cimport os import requests KEY = os.environ["APA_KEY"] response = requests.post( "https://anonpay.org/api/transaction/info", headers={"Authorization": f"Bearer {KEY}"}, data={ "transaction_id": "9c1f0b7a4e2d8f6a3b5c7d9e1f0a2b4c", }, timeout=30, ) print(response.json())const url = "https://anonpay.org/api/transaction/info"; const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${process.env.APA_KEY}` }, body: new URLSearchParams({ transaction_id: "9c1f0b7a4e2d8f6a3b5c7d9e1f0a2b4c", }), }); console.log(await response.json());$url = 'https://anonpay.org/api/transaction/info'; $key = getenv("APA_KEY"); $ch = curl_init($url); curl_setopt_array($ch, [ CURLOPT_HTTPHEADER => ["Authorization: Bearer $key"], CURLOPT_POSTFIELDS => http_build_query([ "transaction_id" => '9c1f0b7a4e2d8f6a3b5c7d9e1f0a2b4c', ]), CURLOPT_RETURNTRANSFER => true, ]); $response = json_decode(curl_exec($ch), true);