Reference
Billing
Cards, yearly prices, the monthly sending allowance, overage and the hard stop.
Calls go to https://address.seleya.ai/api. A refusal is {"error": {"code", "message"}} with its status; every code is in Errors.
Billing
GET /v1/billing
Called with a key or a person signed in.
The owner's payment status, plan and price, card, the month's sending allowance (with overage and the hard stop), and the next charge.
Parameters
-
ownerstring, in query - Who pays. Defaults to you.
Answers
- 200
- Done
- 401
- No valid key, session or token
- 403
- Not allowed for this caller
- 404
- Not found, or not yours to see
- 503
- Payments are not open here yet
Fields of the 200 answer
-
statusstring - none, checking, ready_to_pay, payment_required, active, past_due, cancelled, refused or review. First-payment failure never activates mail.
-
reasonstring, or null - Why the status is what it is, when it isn't active.
-
planstring - company or person.
-
priceobject - What this owner pays.
-
allowanceobject, or null - This month's sending: 1,000 sends for each paid-for address, pooled.
-
nextobject, or null - The next charge, when a subscription runs.
-
cardobject - The card that pays: brand, last four digits, funding, country and the 3-D Secure result.
-
receive_onlyboolean - A prepaid card pays, so the addresses receive but don't send.
-
billableinteger - The addresses paid for: the owner's active ones.
-
customerobject - The Stripe customer id.
-
ownerobject - Whose billing this is: id, name and kind.
-
capabilitiesCapabilities -
card_statestring, or null -
card_pendingboolean -
purchaseobject, or null -
paymentobject, or null -
invoicesarray of objects
curl https://address.seleya.ai/api/v1/billing \
-H "Authorization: Bearer $SELEYA_KEY"import os, requests
r = requests.get(
"https://address.seleya.ai/api/v1/billing",
headers={"Authorization": f"Bearer {os.environ['SELEYA_KEY']}"},
)
print(r.status_code, r.json())const r = await fetch("https://address.seleya.ai/api/v1/billing", {
method: "GET",
headers: { Authorization: `Bearer ${process.env.SELEYA_KEY}` },
});
console.log(r.status, await r.json());{
"allowance": {
"hard_stop": false,
"included": 1000,
"included_used": 0,
"overage": 0
},
"billable": 1,
"card": null,
"customer": "cus_VU7sXsMd8VZkDA",
"next": null,
"owner": {
"id": "7f3c9a2e-0000-4000-8000-000000000020",
"kind": "company",
"name": "Pay Co 10220001"
},
"plan": "company",
"price": {
"cents_per_address_year": 1800,
"overage_cents_per_1000_sends": 100
},
"reason": null,
"receive_only": false,
"status": "none"
}Save a card
POST /v1/billing/checkout
Called with a key or a person signed in.
Saves a card and requests 3-D Secure. Eligibility checks run before payment. Saving a card does not create a subscription; a person reviews the price and confirms purchase separately.
Body
-
ownerstring - Who pays: a company's owner id or your own. Defaults to yours.
Answers
- 201
- Made
- 401
- No valid key, session or token
- 403
- Not allowed for this caller
- 409
- Conflicts with the current state
- 503
- Payments are not open here yet
Fields of the 201 answer
-
urlstring
curl -X POST https://address.seleya.ai/api/v1/billing/checkout \
-H "Authorization: Bearer $SELEYA_KEY" \
-H "Content-Type: application/json" \
-d '{}'import os, requests
r = requests.post(
"https://address.seleya.ai/api/v1/billing/checkout",
headers={"Authorization": f"Bearer {os.environ['SELEYA_KEY']}"},
json={},
)
print(r.status_code, r.json())const r = await fetch("https://address.seleya.ai/api/v1/billing/checkout", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.SELEYA_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({}),
});
console.log(r.status, await r.json());{
"customer": "cus_VU7sXsMd8VZkDA",
"session": "cs_test_…",
"url": "https://checkout.stripe.com/c/pay/cs_…"
}Invoices and card
POST /v1/billing/portal
Called by address.seleya.ai, signed in.
A person opens the Address-specific cancellation portal. Card verification, payment retries and invoice PDFs are at address.seleya.ai.
Body
-
ownerstring - Who pays. Defaults to yours.
Answers
- 201
- Made
- 401
- No valid key, session or token
- 403
- Not allowed for this caller
- 409
- Conflicts with the current state
- 503
- Payments are not open here yet
Fields of the 201 answer
-
urlstring
Set the hard stop
POST /v1/billing/hard-stop
Called with a key or a person signed in.
Switches the hard stop at the month's sending allowance on or off. With it on, sending stops once the month's included sends are used; with it off, sends beyond them cost $1 per 1,000, added to the next charge. Anyone who can see the owner's billing may switch it on. Switching it off lets sends cost money, so for a key or an app it becomes an ask: the call answers 202 and the owner's admins get a link to approve it.
Body
-
ownerstring - Whose billing. Defaults to yours.
-
onboolean required - true to stop at the allowance; false to let sends beyond it go on as overage.
Answers
- 200
- Done
- 202
- Waiting for a person to approve switching it off
- 401
- No valid key, session or token
- 403
- Not allowed for this caller
- 404
- No such owner for this caller
- 409
- This owner has no billing yet
- 422
- A value is refused; the message says which
- 503
- Payments are not open here yet
Fields of the 200 answer
-
hard_stopboolean - Whether the hard stop is now on.
curl -X POST https://address.seleya.ai/api/v1/billing/hard-stop \
-H "Authorization: Bearer $SELEYA_KEY" \
-H "Content-Type: application/json" \
-d '{
"on": true
}'import os, requests
r = requests.post(
"https://address.seleya.ai/api/v1/billing/hard-stop",
headers={"Authorization": f"Bearer {os.environ['SELEYA_KEY']}"},
json={
"on": True
},
)
print(r.status_code, r.json())const r = await fetch("https://address.seleya.ai/api/v1/billing/hard-stop", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.SELEYA_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({
"on": true
}),
});
console.log(r.status, await r.json());{
"hard_stop": true
}Your own address
POST /v1/me/address
Called with a key or a person signed in.
A person (or their app) makes their own address on the people's domain, seleya.me. It works once they pay.
Body
-
namestring required - Your full name, as on your card. It is screened against sanctions lists.
-
countrystring required - Where you live, as a two-letter code such as ZA.
-
localstring required - The name before @seleya.me: 1 to 64 of a-z, 0-9, dot, dash and underscore.
-
display_namestring - The name people see. It must say it is an agent. Defaults to "<your name>'s agent".
Answers
- 201
- Made
- 401
- No valid key, session or token
- 403
- Not allowed for this caller
- 409
- Conflicts with the current state
- 422
- A value is refused; the message says which
Fields of the 201 answer
-
idstring -
addressstring -
owner_idstring -
display_namestring -
statusactive | retired -
holder_emailsarray of strings -
holder_person_idstring, or null -
screeningmap of string -
capabilitiesCapabilities -
approvalsoff | unknown_recipients | everything
curl -X POST https://address.seleya.ai/api/v1/me/address \
-H "Authorization: Bearer $SELEYA_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Ada Lovelace",
"country": "GB",
"local": "ada"
}'import os, requests
r = requests.post(
"https://address.seleya.ai/api/v1/me/address",
headers={"Authorization": f"Bearer {os.environ['SELEYA_KEY']}"},
json={
"name": "Ada Lovelace",
"country": "GB",
"local": "ada"
},
)
print(r.status_code, r.json())const r = await fetch("https://address.seleya.ai/api/v1/me/address", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.SELEYA_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({
"name": "Ada Lovelace",
"country": "GB",
"local": "ada"
}),
});
console.log(r.status, await r.json());{
"address": "own@seleya.me",
"display_name": "Test's agent",
"holder_emails": [
"own@acme.com"
],
"holder_person_id": "7f3c9a2e-0000-4000-8000-00000000002d",
"id": "7f3c9a2e-0000-4000-8000-00000000002e",
"owner": {
"id": "7f3c9a2e-0000-4000-8000-00000000002f",
"status": "authorised_unpaid"
},
"owner_id": "7f3c9a2e-0000-4000-8000-00000000002f",
"screening": {},
"status": "active"
}Stripe's events
POST /v1/webhooks/stripe
Called with .
For Stripe only, signed with the endpoint's secret.
Answers
- 200
- Done
- 400
- The request is malformed
- 401
- No valid key, session or token
Review an annual price and optional discount after card verification
POST /v1/billing/review
Called by address.seleya.ai, signed in.
Body
-
ownerstring - An owner the signed-in person administers.
-
codestring
Answers
- 200
- Done
- 403
- The error explains how to continue.
- 409
- The error explains how to continue.
- 422
- The error explains how to continue.
Fields of the 200 answer
-
purchasestring -
quantityinteger -
total_centsinteger -
currencystring -
subtotal_centsinteger -
annual_cents_before_discountinteger -
discountobject, or null -
cardobject -
terms_versionstring
Confirm a reviewed purchase using only its verified card
POST /v1/billing/purchase
Called by address.seleya.ai, signed in.
Body
-
ownerstring - An owner the signed-in person administers.
-
purchasestring required -
accept_termstrue required
Answers
- 200
- Done
- 403
- The error explains how to continue.
- 409
- The error explains how to continue.
- 422
- The error explains how to continue.
Fields of the 200 answer
-
statusstring - none, checking, ready_to_pay, payment_required, active, past_due, cancelled, refused or review. First-payment failure never activates mail.
-
reasonstring, or null - Why the status is what it is, when it isn't active.
-
planstring - company or person.
-
priceobject - What this owner pays.
-
allowanceobject, or null - This month's sending: 1,000 sends for each paid-for address, pooled.
-
nextobject, or null - The next charge, when a subscription runs.
-
cardobject - The card that pays: brand, last four digits, funding, country and the 3-D Secure result.
-
receive_onlyboolean - A prepaid card pays, so the addresses receive but don't send.
-
billableinteger - The addresses paid for: the owner's active ones.
-
customerobject - The Stripe customer id.
-
ownerobject - Whose billing this is: id, name and kind.
-
capabilitiesCapabilities -
card_statestring, or null -
card_pendingboolean -
purchaseobject, or null -
paymentobject, or null -
invoicesarray of objects
Pay an existing invoice using the verified card; may return a bank confirmation URL
POST /v1/billing/payment
Called by address.seleya.ai, signed in.
Body
-
ownerstring - An owner the signed-in person administers.
-
invoicestring required -
total_centsinteger required
Answers
- 200
- Done
- 403
- The error explains how to continue.
- 409
- The error explains how to continue.
- 422
- The error explains how to continue.
Fields of the 200 answer
-
paidboolean -
processingboolean -
urlstring