What you can receive
Native ALGO uses compatible Indexer or algod transaction history. Account minimum balances apply. Algorand Standard Assets, including USDC ASAs, are not accepted invoice assets.
Set up your store
- Install Wholly Crypto, create a project and store, and keep a private wallet backup.
- Check scanner-compatible connections and enable the chain and intended assets in Store → Payment methods.
- Set confirmations and expiry. Test a small invoice and verify settlement before fulfilling orders.
Where your payments arrive
Invoices use separate receiving addresses. Keep the complete backup, address list and derivation details; an imported wallet may not discover every invoice address immediately.
Receiving guideMove funds when you are ready
Manual sends and automatic sweeps support the native coin. Keep enough for fees and any network reserve or storage requirement. Receiving support alone does not prove a provider can submit transfers.
Automatic sweep tutorialPayment troubleshooting
Check this network first
Plan for the receiving account’s minimum balance. Only native ALGO is accepted; an ASA or USDC transfer does not pay this method.
A payment is missing or delayed
Match the network, address, asset and any required reference to the invoice. Check scanner readiness and confirmation progress. Do not ask for a second payment until you have checked the first transaction.
Receiving guideRestore or consolidate wallets
Keep your private backup and derivation details. A different wallet app may not display every receiving address. Sending and recovery depend on the chain and wallet format; neither is guaranteed by importing recovery words alone.
Backup & restoreFees and verification
The default processing fee is 1% of the invoice’s fiat value, paid from separate credits. Your assigned rate applies. Network fees and server costs are separate.
Public providers can have outages or rate limits. A submitted transaction or return redirect is not proof of payment. Use the verified invoice status and signed notifications.
Processing credits API, IPN & webhooksRates calculator
Convert an amount
An estimate, not a payment quote. Network fees, exchange fees and merchant spreads are not included.
Where do the rates come from?
Crypto estimates use cached public Kraken prices, with Binance where available. Some Binance prices use USDT as a USD reference. Fiat rates come from Frankfurter and are daily reference rates, not live trading quotes.
The snapshot refreshes automatically. Check the source dates below your result. Your entered amount stays in your browser. Asset listings do not guarantee payment support.
Kraken · Binance · Frankfurter · Asset names & icons: CoinGecko
Create an invoice with the API
Run these examples on your server. Replace the API host, project ID and store ID, and keep the credential private. Amounts are decimal strings.
Enable the method in the store first. Selection narrows enabled methods; it does not add assets. If nothing matches, store defaults apply. Check the returned methods before presenting checkout.
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new invoice.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/invoices" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: order-1042-attempt-1' \
--header 'Content-Type: application/json' \
--data-raw '{
"amount": "25.00",
"currency": "EUR",
"order_id": "order-1042",
"payment_methods": [
{
"chain_slug": "algorand",
"asset_tickers": [
"ALGO"
]
}
]
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new invoice.
const body = `{
"amount": "25.00",
"currency": "EUR",
"order_id": "order-1042",
"payment_methods": [
{
"chain_slug": "algorand",
"asset_tickers": [
"ALGO"
]
}
]
}`;
const response = await fetch("https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/invoices", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "order-1042-attempt-1",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new invoice.
$body = <<<'JSON'
{
"amount": "25.00",
"currency": "EUR",
"order_id": "order-1042",
"payment_methods": [
{
"chain_slug": "algorand",
"asset_tickers": [
"ALGO"
]
}
]
}
JSON;
$ch = curl_init("https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/invoices");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: order-1042-attempt-1", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new invoice.
headers = {
"Idempotency-Key": "order-1042-attempt-1",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"amount": "25.00",
"currency": "EUR",
"order_id": "order-1042",
"payment_methods": [
{
"chain_slug": "algorand",
"asset_tickers": [
"ALGO"
]
}
]
}""".encode("utf-8")
request = Request("https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/invoices",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))