Ninefoldby Best Pay

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

POST/v1/records
FieldRule
ref1 to 64 characters: letters, digits, and . _ / -
sha256the file’s SHA-256, 64 lowercase hex characters
labeloptional, 1 to 32 characters: letters, digits, _ and -

Any other field is refused, including a document.

Requestcurl
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"}'
Answer201 Created
{"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.

Pythonrequests
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

GET/v1/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

GET/v1/records/<seq>/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.txt

Before 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

GET/v1/status

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

POST/v1/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

GET/v1/pubkey

Best Pay’s public key, the one every receipt is checked against.

POST/v1/verify

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"}.

StatusCodeMeaning
400bad_ref, bad_sha256, bad_label, unexpected_fieldThe body broke a field rule. Nothing was recorded.
401unauthorizedThe key is missing or not recognized. Nothing was recorded.
402allowance_spent, payment_requiredNo new seals for now: the allowance is used up on an account that can’t be billed for extras, or payment is due.
403subscription_ended, account_under_reviewNew seals are stopped. Your records and receipts stay available.
409pending_anchorThe record isn’t anchored yet. Try after the next anchor.
410receipt_expiredThe 30-day download window passed and Receipt Backup isn’t on.
429slow_downToo many calls. Wait a minute.
503anchoring_try_againYour 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.