API docs
The Ninefold API
One address, plain JSON, and a bearer key. Base address: https://api.bestninefold.com/v1
Your key
Every call except the public ones carries your key:
Authorization: Bearer nf_<account>_<secret>
Your key is shown once, right after checkout. Keep it somewhere safe. Best Pay stores only a fingerprint of it, so a lost key can’t be shown again. Anyone who has the key can seal records to your ledger.
Seal a record
| Field | Rule |
|---|---|
ref | 1 to 64 characters: letters, digits, and . _ / - |
sha256 | the file’s SHA-256, 64 lowercase hex characters |
label | optional, 1 to 32 characters: letters, digits, _ and - |
Any other field is refused, including a document.
SEAL=$(shasum -a 256 invoice.pdf | cut -c1-64) curl https://api.bestninefold.com/v1/records \ -H "Authorization: Bearer $NINEFOLD_KEY" \ -H "Content-Type: application/json" \ -d '{"ref":"INV-1001","sha256":"'$SEAL'","label":"invoice"}'
{"status": "SEALED", "seq": 41, "anchored": false,
"used": 42, "included": 6000, "overage": 0}
seq is the record’s number on your ledger. Keep it: you use it to fetch the receipt.
import hashlib, os, requests digest = hashlib.sha256(open("invoice.pdf", "rb").read()).hexdigest() r = requests.post("https://api.bestninefold.com/v1/records", headers={"Authorization": "Bearer " + os.environ["NINEFOLD_KEY"]}, json={"ref": "INV-1001", "sha256": digest, "label": "invoice"}) r.raise_for_status() print(r.json()["seq"])
List your records
Every record on your ledger: seq, ref, sha256, label, sealed_at, whether it is anchored yet, whether its receipt is downloadable, and download_until (empty while Receipt Backup is on).
Get a receipt
Returns the Best Pay Receipt as plain text after the record is anchored. Save it as a file and keep it.
curl -H "Authorization: Bearer $NINEFOLD_KEY" \
https://api.bestninefold.com/v1/records/41/receipt > INV-1001.receipt.txtBefore the anchor it answers 409 pending_anchor. A receipt can be downloaded for 30 days after it is anchored; after that it answers 410 receipt_expired, unless Receipt Backup is on.
Check your plan
Your billing period and when it ends, your allowance, seals used, extra seals this period, whether Receipt Backup is on, and how many records are anchored or still waiting for the next anchor.
Billing portal
Returns a link to your Stripe billing portal, where you can change your plan, add or remove Receipt Backup, update your card, see invoices, or cancel. Accounts paid by invoice don’t have a portal: email cs@bestninefold.com.
Public, no key needed
Best Pay’s public key, the one every receipt is checked against.
Send the raw receipt text and get {"valid": true|false, "detail": "…"}.
curl https://api.bestninefold.com/v1/verify --data-binary @INV-1001.receipt.txt
The receipt doesn’t need this service to be checked: anyone holding the public key can check it on their own.
Errors
Errors answer with JSON: {"error": "code", "detail": "a sentence for people"}.
| Status | Code | Meaning |
|---|---|---|
| 400 | bad_ref, bad_sha256, bad_label, unexpected_field | The body broke a field rule. Nothing was recorded. |
| 401 | unauthorized | The key is missing or not recognized. Nothing was recorded. |
| 402 | allowance_spent, payment_required | No new seals for now: the allowance is used up on an account that can’t be billed for extras, or payment is due. |
| 403 | subscription_ended, account_under_review | New seals are stopped. Your records and receipts stay available. |
| 409 | pending_anchor | The record isn’t anchored yet. Try after the next anchor. |
| 410 | receipt_expired | The 30-day download window passed and Receipt Backup isn’t on. |
| 429 | slow_down | Too many calls. Wait a minute. |
| 503 | anchoring_try_again | Your records are being signed right now. Retry after the Retry-After seconds; nothing is lost. |
Past your allowance on a paid plan, calls keep sealing and each extra seal is billed at 9¢. GET /v1/status shows how many are extra.
What never to send
Don’t send files, account numbers, government ID numbers or medical records. Send seals and short references only.