/api/qmail/raida/payments/send
GET POSTSend a Payment Tell (tell_type 3) — a direct coin transfer over the Tell channel with no message body, only a 1-byte purpose code. The core funds a fresh single-use locker from the sender's wallet and tells the recipient's beacon RAIDA; the recipient's client claims the coins into its wallet automatically. Async: returns a task_id immediately.
Description
A payment tell is the money-moving counterpart of an email tell. There is no upload step and no manifest — the fixed 194-byte tell carries the sender identity (AN-authenticated), a timestamp, the funded locker key, and one purpose byte. The recipient's transaction log shows who paid, when, how much, and the purpose label (e.g. “Subscription payment”); nothing appears in their mail inbox. See the payment-tell wire format.
Primary use case — subscription payouts: a webserver holding subscriber mailbox addresses calls this endpoint once per member each month with purpose=0. Each member's client auto-claims the coins; the sender can later verify pickup by peeking the locker (empty = claimed).
Payment tells are exempt from the recipient's inbox fee (they carry no message), but a flat minimum of 5000 CC is enforced so the channel cannot spray dust-value notifications. Below-minimum amounts are rejected locally with HTTP 400, and by the beacon with ERROR_PAYMENT_INSUFFICIENT (168).
Exactly one recipient per payment tell — each payee gets their own funded locker. Paying N subscribers means N calls. Comma/semicolon-separated to lists are rejected.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
to |
string | Yes | Recipient QMail address (or contact resolvable by the standard address parser). Exactly one recipient; lists are rejected with HTTP 400. |
amount |
string (decimal CC) | Yes | Payment amount in CC, e.g. 5000 or 7500.25 (0.0001 CC granularity). Must be at least 5000 CC. |
purpose |
integer 0–255 | No | Payment purpose code shown in the recipient's transaction log. Default 255 (unspecified). See the registry below. |
wallet_path / wallet |
string | No | Wallet that funds the payment locker. Defaults to Default. |
debug |
boolean | No | Per-request LOG_DEBUG verbosity (grep QMAIL-PAYMENT in main.log). |
Purpose codes
| Code | Name | Meaning |
|---|---|---|
0 | subscription | Subscription payment |
1 | invoice | Invoice payment |
2 | gift_tip | Gift / tip |
3 | refund | Refund |
4 | payroll | Payroll |
5 | purchase | Purchase |
255 | unspecified | Unspecified |
Response
Returns HTTP 200 immediately with a task_id; poll /api/system/tasks?id=<task_id>. The worker funds the locker, then sends the tell to the recipient's beacon RAIDA.
Task Poll — Accepted
{
"status": "success",
"task_id": "task_3fa2b911",
"progress": 100,
"message": "Payment tell accepted",
"data": {
"payment_id": "9f2ab3c4d5e6f7a8b9c0d1e2f3a4b5c6",
"server_status": 250,
"retry_queued": false,
"recipient_sn": 4321,
"amount_units": 500000000000
}
}
Task Poll — Beacon Unreachable, Queued for Retry (still success)
The locker is already funded; the pending-tell retry worker re-sends automatically. This is not a failure — do not re-call /raida/payments/send, or the recipient will be paid twice.
{
"status": "success",
"task_id": "task_3fa2b911",
"progress": 100,
"message": "Payment locker funded; tell queued for retry",
"data": {
"payment_id": "9f2ab3c4d5e6f7a8b9c0d1e2f3a4b5c6",
"retry_queued": true
}
}
Errors
- HTTP
400— invalidtoaddress, invalid amount, “Amount below minimum payment of 5000 CC”, or invalid purpose. - Task
failed— insufficient wallet funds to fund the locker, or a permanent beacon rejection:ERROR_PAYMENT_INSUFFICIENT(168, below-minimum locker),ERROR_SENDER_BLACKLISTED(236, the recipient blacklisted this sender). - Temporary beacon conditions (
ERROR_PAYMENT_PROCESSING, 167; network timeouts) end as the queued-for-retry success above.
Examples
# Monthly subscription payout loop (one call per member)
for ADDR in $(cat subscribers.txt); do
curl -s "http://localhost:8081/api/qmail/raida/payments/send?to=$ADDR&amount=5000&purpose=0"
done
# Poll a payout task
curl "http://localhost:8081/api/system/tasks?id=<TASK_ID>"
Important Notes
The recipient's beacon loop recognizes tell_type 3, skips the mail-download flow, claims the locker (13-of-25 consensus), grades the coins into the wallet, and records the payment in qmail_received_tells with its purpose and amount. Received payments are listed by /api/qmail/db/payments/list; a claim that failed (e.g. client offline mid-claim) can be re-driven manually with /api/qmail/raida/payments/claim.
Peek the payment locker after sending: an empty locker means the recipient claimed it. The send is also recorded in the local qmail_sent_payments table with the payment GUID, recipient, amount, purpose, and locker key.