Alle talen en veiligheidsafspraken · API-referentie
Python 3.11+, alleen de standaardbibliotheek.
1. Herbruikbare client
Bewaar dit als binadit.py. De client volgt geen redirects en herhaalt geen aanvragen. Geef geheimen via je secretmanager aan de omgeving door; niets wordt automatisch opgeslagen of gelogd.
"""Python 3.11+, standard library only. No network calls when imported."""
import json
import hashlib
import hmac
import os
import re
import time
import urllib.error
import urllib.parse
import urllib.request
ORIGIN = "https://my.binadit.com"
LIMIT = 8 * 1024 * 1024
class NoRedirect(urllib.request.HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
def send(method, path, headers, content=None):
if not (path.startswith("/api/v1/") or path == "/oauth/token") or "\\" in path or "#" in path:
raise ValueError("Use a relative Binadit API path")
request = urllib.request.Request(ORIGIN + path, content, headers, method=method)
try:
response = urllib.request.build_opener(NoRedirect()).open(request, timeout=30)
except urllib.error.HTTPError as error:
response = error
except (OSError, urllib.error.URLError):
raise RuntimeError("Transport outcome unknown; preserve the original request") from None
with response:
raw = response.read(LIMIT + 1)
if len(raw) > LIMIT:
raise RuntimeError("Response exceeds the example's 8 MiB limit")
if not 200 <= response.status < 300:
raise RuntimeError(f"API HTTP {response.status}; inspect the original operation")
return response.headers, raw
def access_token():
token = os.environ.get("BINADIT_ACCESS_TOKEN")
if token:
return token
body = urllib.parse.urlencode({"grant_type": "client_credentials",
"client_id": os.environ["BINADIT_CLIENT_ID"],
"client_secret": os.environ["BINADIT_CLIENT_SECRET"]}).encode()
_, raw = send("POST", "/oauth/token", {"Accept": "application/json",
"Content-Type": "application/x-www-form-urlencoded"}, body)
token = json.loads(raw)["access_token"]
if not isinstance(token, str) or not token:
raise RuntimeError("Token response is invalid")
return token
def api(token, method, path, body=None, *, version=None, key=None, binary=False):
if not path.startswith("/api/v1/") or method not in {"GET", "POST", "PUT", "PATCH", "DELETE"}:
raise ValueError("Use a supported API method and path")
headers = {"Authorization": f"Bearer {token}", "Accept": "application/pdf" if binary else "application/json"}
if method != "GET":
if not key or not re.fullmatch(r"[A-Za-z0-9_.:-]{16,128}", key):
raise ValueError("Supply the persisted original Idempotency-Key")
headers["Idempotency-Key"] = key
if version:
headers["If-Match"] = version
encoded = None if body is None else json.dumps(body, ensure_ascii=False).encode()
if encoded is not None:
headers["Content-Type"] = "application/json"
response, raw = send(method, path, headers, encoded)
if binary and response.get_content_type() != "application/pdf":
raise RuntimeError("Expected an invoice PDF")
return {"etag": response.get("ETag"), "data": raw if binary else (json.loads(raw) if raw else None)}
def verify_webhook(raw, delivery_id, timestamp, signature, expected_key_id, secret, now=None):
"""Signature/time check only; separately deduplicate in a durable transaction."""
uuid = r"[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"
if (len(raw) > 1024 * 1024 or len(secret) < 32
or not re.fullmatch(uuid, delivery_id) or not re.fullmatch(uuid, expected_key_id)
or not re.fullmatch(r"[1-9][0-9]{8,10}", timestamp)):
return False
if abs((time.time() if now is None else now) - int(timestamp)) > 300:
return False
digest = hmac.new(secret.encode(), timestamp.encode() + b"." + delivery_id.encode() + b"." + raw, hashlib.sha256).hexdigest()
expected = f"v1={digest},key_id={expected_key_id}"
return signature.isascii() and hmac.compare_digest(expected, signature)
2. Eenmalig voor deze workflow
from binadit import access_token, api
import os
token = access_token()
De tokenaanvraag gebeurt één keer voor deze korte workflow. Een servicesleutel is geen menselijke step-up. Stop bij 401 en onderzoek eerst een mogelijk verzonden mutatie. Iedere onderstaande codeblok is een afzonderlijk voorbeeld: plak ze niet allemaal achter elkaar. Alle IDs en example.test-adressen zijn fictief. Schrijfvoorbeelden met mogelijke gevolgen gebruiken dry_run.
Identiteit controleren
GET /api/v1/me · scope account:read
result = api(token, 'GET', '/api/v1/me')
Bedrijven ophalen
GET /api/v1/accounts · scope account:read
result = api(token, 'GET', '/api/v1/accounts')
Beschikbaarheid en scopes controleren
GET /api/v1/accounts/123/capabilities · scope account:read
result = api(token, 'GET', '/api/v1/accounts/123/capabilities')
Bedrijfsgegevens en ETag lezen
GET /api/v1/accounts/123/profile · scope account:read
result = api(token, 'GET', '/api/v1/accounts/123/profile')
Bedrijfsgegevens wijzigen
PATCH /api/v1/accounts/123/profile · scope account:write
Lees eerst GET profile en bewaar de bijbehorende HTTP ETag (of expliciet beschreven planversie) als BINADIT_RESOURCE_VERSION. Versies van verschillende resources zijn niet uitwisselbaar.
Gebruik voor exact deze beoordeelde aanvraag een vooraf duurzaam bewaarde BINADIT_REQUEST_KEY van 16–128 veilige tekens. Hergebruik haar alleen voor dezelfde methode, URL en JSON; nooit voor een volgende stap.
result = api(token, 'PATCH', '/api/v1/accounts/123/profile', {'city': 'Utrecht', 'dry_run': True}, version=os.environ["BINADIT_RESOURCE_VERSION"], key=os.environ["BINADIT_REQUEST_KEY"])
Producten en prijzen bekijken
GET /api/v1/accounts/123/products · scope products:read
result = api(token, 'GET', '/api/v1/accounts/123/products')
Bestaande domeinhouders ophalen
GET /api/v1/accounts/123/holders · scope holders:read
result = api(token, 'GET', '/api/v1/accounts/123/holders')
Standaardhouder uit bedrijfs- of particuliere gegevens voorbereiden
POST /api/v1/accounts/123/holders/default · scope holders:read, holders:write
Gebruik voor exact deze beoordeelde aanvraag een vooraf duurzaam bewaarde BINADIT_REQUEST_KEY van 16–128 veilige tekens. Hergebruik haar alleen voor dezelfde methode, URL en JSON; nooit voor een volgende stap.
result = api(token, 'POST', '/api/v1/accounts/123/holders/default', {'dry_run': True}, key=os.environ["BINADIT_REQUEST_KEY"])
Een eigen domeinhouder aanmaken
POST /api/v1/accounts/123/holders · scope holders:write
Gebruik voor exact deze beoordeelde aanvraag een vooraf duurzaam bewaarde BINADIT_REQUEST_KEY van 16–128 veilige tekens. Hergebruik haar alleen voor dezelfde methode, URL en JSON; nooit voor een volgende stap.
result = api(token, 'POST', '/api/v1/accounts/123/holders', {'initials': 'A', 'firstname': 'Ada', 'lastname': 'Example', 'gender': 'F', 'street': 'Voorbeeldstraat', 'number': '1', 'zipcode': '1234 AB', 'city': 'Utrecht', 'country': 'NL', 'email': 'ada@example.test', 'tel1': '+31', 'tel3': '612345678', 'dry_run': True}, key=os.environ["BINADIT_REQUEST_KEY"])
Beschikbaarheid van een domein opvragen
POST /api/v1/accounts/123/domains/check · scope domains:read
Gebruik voor exact deze beoordeelde aanvraag een vooraf duurzaam bewaarde BINADIT_REQUEST_KEY van 16–128 veilige tekens. Hergebruik haar alleen voor dezelfde methode, URL en JSON; nooit voor een volgende stap.
result = api(token, 'POST', '/api/v1/accounts/123/domains/check', {'domains': ['example.test']}, key=os.environ["BINADIT_REQUEST_KEY"])
Domeinregistratie offreren
POST /api/v1/accounts/123/order-quotes · scope orders:write
Gebruik voor exact deze beoordeelde aanvraag een vooraf duurzaam bewaarde BINADIT_REQUEST_KEY van 16–128 veilige tekens. Hergebruik haar alleen voor dezelfde methode, URL en JSON; nooit voor een volgende stap.
result = api(token, 'POST', '/api/v1/accounts/123/order-quotes', {'kind': 'domain_register', 'input': {'domain': 'example.test', 'product_id': 9, 'holder_id': 17}, 'dry_run': True}, key=os.environ["BINADIT_REQUEST_KEY"])
Een bewaarde offerte opnieuw lezen
GET /api/v1/accounts/123/order-quotes/11111111-1111-4111-8111-111111111111 · scope orders:read
result = api(token, 'GET', '/api/v1/accounts/123/order-quotes/11111111-1111-4111-8111-111111111111')
Bestelling en betaling voorbereiden
POST /api/v1/accounts/123/orders · scope orders:commit
Gebruik voor exact deze beoordeelde aanvraag een vooraf duurzaam bewaarde BINADIT_REQUEST_KEY van 16–128 veilige tekens. Hergebruik haar alleen voor dezelfde methode, URL en JSON; nooit voor een volgende stap.
result = api(token, 'POST', '/api/v1/accounts/123/orders', {'quote_id': '11111111-1111-4111-8111-111111111111', 'dry_run': True}, key=os.environ["BINADIT_REQUEST_KEY"])
Registratie, verlenging en abonnementstatus lezen
GET /api/v1/accounts/123/domains/31/subscription · scope domains:read
result = api(token, 'GET', '/api/v1/accounts/123/domains/31/subscription')
Domein niet meer automatisch verlengen
POST /api/v1/accounts/123/domains/31/actions/cancel · scope domains:write
Lees eerst GET domains/31 en bewaar de bijbehorende HTTP ETag (of expliciet beschreven planversie) als BINADIT_RESOURCE_VERSION. Versies van verschillende resources zijn niet uitwisselbaar.
Gebruik voor exact deze beoordeelde aanvraag een vooraf duurzaam bewaarde BINADIT_REQUEST_KEY van 16–128 veilige tekens. Hergebruik haar alleen voor dezelfde methode, URL en JSON; nooit voor een volgende stap.
result = api(token, 'POST', '/api/v1/accounts/123/domains/31/actions/cancel', {'confirm_domain': 'example.test', 'dry_run': True}, version=os.environ["BINADIT_RESOURCE_VERSION"], key=os.environ["BINADIT_REQUEST_KEY"])
DNS-zones ophalen
GET /api/v1/accounts/123/dns/zones · scope dns.zones:read
result = api(token, 'GET', '/api/v1/accounts/123/dns/zones')
Huidige DNS-records en versie ophalen
GET /api/v1/accounts/123/dns/zones/8/records · scope dns.records:read
result = api(token, 'GET', '/api/v1/accounts/123/dns/zones/8/records')
DNS-templates ophalen
GET /api/v1/accounts/123/dns/templates · scope dns.templates:read
result = api(token, 'GET', '/api/v1/accounts/123/dns/templates')
Een DNS-template voorbereiden
POST /api/v1/accounts/123/dns/templates · scope dns.templates:write
Gebruik voor exact deze beoordeelde aanvraag een vooraf duurzaam bewaarde BINADIT_REQUEST_KEY van 16–128 veilige tekens. Hergebruik haar alleen voor dezelfde methode, URL en JSON; nooit voor een volgende stap.
result = api(token, 'POST', '/api/v1/accounts/123/dns/templates', {'name': 'Websitevoorbeeld', 'replace': 'none', 'records': [{'name': '@', 'type': 'A', 'value': '192.0.2.50', 'ttl': 300}, {'name': 'www', 'type': 'CNAME', 'value': 'example.test', 'ttl': 300}], 'dry_run': True}, key=os.environ["BINADIT_REQUEST_KEY"])
Toepassen van een template voorstellen
POST /api/v1/accounts/123/dns/zones/8/template-plans · scope dns.records:write
Gebruik voor exact deze beoordeelde aanvraag een vooraf duurzaam bewaarde BINADIT_REQUEST_KEY van 16–128 veilige tekens. Hergebruik haar alleen voor dezelfde methode, URL en JSON; nooit voor een volgende stap.
result = api(token, 'POST', '/api/v1/accounts/123/dns/zones/8/template-plans', {'template_id': 11, 'dry_run': True}, key=os.environ["BINADIT_REQUEST_KEY"])
Meerdere DNS-records in één plan voorbereiden
POST /api/v1/accounts/123/dns/change-plans · scope dns.records:write
Gebruik voor exact deze beoordeelde aanvraag een vooraf duurzaam bewaarde BINADIT_REQUEST_KEY van 16–128 veilige tekens. Hergebruik haar alleen voor dezelfde methode, URL en JSON; nooit voor een volgende stap.
result = api(token, 'POST', '/api/v1/accounts/123/dns/change-plans', {'zone': 'example.test', 'changes': [{'action': 'create', 'name': 'proef', 'type': 'A', 'value': '192.0.2.50', 'ttl': 300}, {'action': 'create', 'name': '_verify', 'type': 'TXT', 'value': 'binadit-example', 'ttl': 300}], 'dry_run': True}, key=os.environ["BINADIT_REQUEST_KEY"])
Een bekeken DNS-plan toepassen
POST /api/v1/accounts/123/dns/change-plans/11111111-1111-4111-8111-111111111111/apply · scope dns.records:write
Lees eerst version van het oorspronkelijke bekeken DNS-plan en bewaar de bijbehorende HTTP ETag (of expliciet beschreven planversie) als BINADIT_RESOURCE_VERSION. Versies van verschillende resources zijn niet uitwisselbaar.
Gebruik voor exact deze beoordeelde aanvraag een vooraf duurzaam bewaarde BINADIT_REQUEST_KEY van 16–128 veilige tekens. Hergebruik haar alleen voor dezelfde methode, URL en JSON; nooit voor een volgende stap.
result = api(token, 'POST', '/api/v1/accounts/123/dns/change-plans/11111111-1111-4111-8111-111111111111/apply', {'dry_run': True}, version=os.environ["BINADIT_RESOURCE_VERSION"], key=os.environ["BINADIT_REQUEST_KEY"])
Een oorspronkelijke operatie volgen
GET /api/v1/accounts/123/operations/22222222-2222-4222-8222-222222222222 · scope operations:read
result = api(token, 'GET', '/api/v1/accounts/123/operations/22222222-2222-4222-8222-222222222222')
Facturen ophalen
GET /api/v1/accounts/123/billing/invoices · scope billing.invoices:read
result = api(token, 'GET', '/api/v1/accounts/123/billing/invoices')
Een factuur als PDF ophalen
GET /api/v1/accounts/123/billing/invoices/45/pdf · scope billing.invoices:read
result = api(token, 'GET', '/api/v1/accounts/123/billing/invoices/45/pdf', binary=True)
result["data"] bevat uitsluitend PDF-bytes. Gebruik de aparte privé-bestandsvoorbeelden hieronder; print geen PDF- of persoonsgegevens.
Workspaces ophalen
GET /api/v1/accounts/123/workspaces · scope workspace:read
result = api(token, 'GET', '/api/v1/accounts/123/workspaces')
Mailboxen ophalen
GET /api/v1/accounts/123/workspaces/7/mailboxes · scope workspace.mailboxes:read
result = api(token, 'GET', '/api/v1/accounts/123/workspaces/7/mailboxes')
Gemachtigden en gebruikersdelingen lezen
GET /api/v1/accounts/123/workspaces/7/mailboxes/23/delegates · scope workspace.mailboxes:read
result = api(token, 'GET', '/api/v1/accounts/123/workspaces/7/mailboxes/23/delegates')
Volledige mailboxtoegang en agenda bewerken
PUT /api/v1/accounts/123/workspaces/7/mailboxes/23/delegates/24 · scope workspace.mailboxes:write
Lees eerst GET workspaces/7/mailboxes/23 en bewaar de bijbehorende HTTP ETag (of expliciet beschreven planversie) als BINADIT_RESOURCE_VERSION. Versies van verschillende resources zijn niet uitwisselbaar.
Gebruik voor exact deze beoordeelde aanvraag een vooraf duurzaam bewaarde BINADIT_REQUEST_KEY van 16–128 veilige tekens. Hergebruik haar alleen voor dezelfde methode, URL en JSON; nooit voor een volgende stap.
result = api(token, 'PUT', '/api/v1/accounts/123/workspaces/7/mailboxes/23/delegates/24', {'level': 'full', 'send_as': False, 'calendar_level': 'write', 'dry_run': True}, version=os.environ["BINADIT_RESOURCE_VERSION"], key=os.environ["BINADIT_REQUEST_KEY"])
Een gratis verzendlijst voorbereiden
POST /api/v1/accounts/123/workspaces/7/mailing-lists · scope workspace.mailboxes:write
Lees eerst GET workspaces/7 en bewaar de bijbehorende HTTP ETag (of expliciet beschreven planversie) als BINADIT_RESOURCE_VERSION. Versies van verschillende resources zijn niet uitwisselbaar.
Gebruik voor exact deze beoordeelde aanvraag een vooraf duurzaam bewaarde BINADIT_REQUEST_KEY van 16–128 veilige tekens. Hergebruik haar alleen voor dezelfde methode, URL en JSON; nooit voor een volgende stap.
result = api(token, 'POST', '/api/v1/accounts/123/workspaces/7/mailing-lists', {'domain_id': 12, 'local_part': 'team', 'display_name': 'Team', 'members': [{'kind': 'mailbox', 'id': 23}, {'kind': 'mailbox', 'id': 24}], 'dry_run': True}, version=os.environ["BINADIT_RESOURCE_VERSION"], key=os.environ["BINADIT_REQUEST_KEY"])
Eén lijstlid toevoegen
PUT /api/v1/accounts/123/workspaces/7/mailing-lists/10/members/mailbox-24 · scope workspace.mailboxes:write
Lees eerst GET workspaces/7/mailing-lists/10 en bewaar de bijbehorende HTTP ETag (of expliciet beschreven planversie) als BINADIT_RESOURCE_VERSION. Versies van verschillende resources zijn niet uitwisselbaar.
Gebruik voor exact deze beoordeelde aanvraag een vooraf duurzaam bewaarde BINADIT_REQUEST_KEY van 16–128 veilige tekens. Hergebruik haar alleen voor dezelfde methode, URL en JSON; nooit voor een volgende stap.
result = api(token, 'PUT', '/api/v1/accounts/123/workspaces/7/mailing-lists/10/members/mailbox-24', {'dry_run': True}, version=os.environ["BINADIT_RESOURCE_VERSION"], key=os.environ["BINADIT_REQUEST_KEY"])
Eén lijstlid verwijderen
DELETE /api/v1/accounts/123/workspaces/7/mailing-lists/10/members/mailbox-24 · scope workspace.mailboxes:write
Lees eerst GET workspaces/7/mailing-lists/10 en bewaar de bijbehorende HTTP ETag (of expliciet beschreven planversie) als BINADIT_RESOURCE_VERSION. Versies van verschillende resources zijn niet uitwisselbaar.
Gebruik voor exact deze beoordeelde aanvraag een vooraf duurzaam bewaarde BINADIT_REQUEST_KEY van 16–128 veilige tekens. Hergebruik haar alleen voor dezelfde methode, URL en JSON; nooit voor een volgende stap.
result = api(token, 'DELETE', '/api/v1/accounts/123/workspaces/7/mailing-lists/10/members/mailbox-24', {'dry_run': True}, version=os.environ["BINADIT_RESOURCE_VERSION"], key=os.environ["BINADIT_REQUEST_KEY"])
Een gratis ruimte voorbereiden
POST /api/v1/accounts/123/workspaces/7/rooms · scope workspace.mailboxes:write
Lees eerst GET workspaces/7 en bewaar de bijbehorende HTTP ETag (of expliciet beschreven planversie) als BINADIT_RESOURCE_VERSION. Versies van verschillende resources zijn niet uitwisselbaar.
Gebruik voor exact deze beoordeelde aanvraag een vooraf duurzaam bewaarde BINADIT_REQUEST_KEY van 16–128 veilige tekens. Hergebruik haar alleen voor dezelfde methode, URL en JSON; nooit voor een volgende stap.
result = api(token, 'POST', '/api/v1/accounts/123/workspaces/7/rooms', {'domain_id': 12, 'local_part': 'vergaderzaal', 'display_name': 'Vergaderzaal 1', 'kind': 'room', 'capacity': 8, 'location': 'Eerste verdieping', 'manager_ids': [23], 'dry_run': True}, version=os.environ["BINADIT_RESOURCE_VERSION"], key=os.environ["BINADIT_REQUEST_KEY"])
Een ruimtebeheerder toevoegen
PUT /api/v1/accounts/123/workspaces/7/rooms/11/managers/24 · scope workspace.mailboxes:write
Lees eerst GET workspaces/7/rooms/11 en bewaar de bijbehorende HTTP ETag (of expliciet beschreven planversie) als BINADIT_RESOURCE_VERSION. Versies van verschillende resources zijn niet uitwisselbaar.
Gebruik voor exact deze beoordeelde aanvraag een vooraf duurzaam bewaarde BINADIT_REQUEST_KEY van 16–128 veilige tekens. Hergebruik haar alleen voor dezelfde methode, URL en JSON; nooit voor een volgende stap.
result = api(token, 'PUT', '/api/v1/accounts/123/workspaces/7/rooms/11/managers/24', {'dry_run': True}, version=os.environ["BINADIT_RESOURCE_VERSION"], key=os.environ["BINADIT_REQUEST_KEY"])
Een ruimte opheffen met persoonlijke verificatie
DELETE /api/v1/accounts/123/workspaces/7/rooms/11 · scope workspace.mailboxes:write
Lees eerst GET workspaces/7/rooms/11 en bewaar de bijbehorende HTTP ETag (of expliciet beschreven planversie) als BINADIT_RESOURCE_VERSION. Versies van verschillende resources zijn niet uitwisselbaar.
Gebruik voor exact deze beoordeelde aanvraag een vooraf duurzaam bewaarde BINADIT_REQUEST_KEY van 16–128 veilige tekens. Hergebruik haar alleen voor dezelfde methode, URL en JSON; nooit voor een volgende stap.
Vereist ook recente sterke menselijke verificatie, actuele bevoegdheden en ingeschakelde gevoelige acties. Een servicesleutel kan die verificatie niet leveren.
result = api(token, 'DELETE', '/api/v1/accounts/123/workspaces/7/rooms/11', {'confirm_address': 'vergaderzaal@example.test', 'dry_run': True}, version=os.environ["BINADIT_RESOURCE_VERSION"], key=os.environ["BINADIT_REQUEST_KEY"])
Hostingabonnementen ophalen
GET /api/v1/accounts/123/hosting/subscriptions · scope hosting:read
result = api(token, 'GET', '/api/v1/accounts/123/hosting/subscriptions')
Hostingopzegging voorbereiden
POST /api/v1/accounts/123/hosting/subscriptions/41/actions/cancel · scope hosting:write
Lees eerst GET hosting/subscriptions/41 en bewaar de bijbehorende HTTP ETag (of expliciet beschreven planversie) als BINADIT_RESOURCE_VERSION. Versies van verschillende resources zijn niet uitwisselbaar.
Gebruik voor exact deze beoordeelde aanvraag een vooraf duurzaam bewaarde BINADIT_REQUEST_KEY van 16–128 veilige tekens. Hergebruik haar alleen voor dezelfde methode, URL en JSON; nooit voor een volgende stap.
result = api(token, 'POST', '/api/v1/accounts/123/hosting/subscriptions/41/actions/cancel', {'intent_id': '33333333-3333-4333-8333-333333333333', 'dry_run': True}, version=os.environ["BINADIT_RESOURCE_VERSION"], key=os.environ["BINADIT_REQUEST_KEY"])
Spamfilters ophalen
GET /api/v1/accounts/123/spam/filters · scope spam:read
result = api(token, 'GET', '/api/v1/accounts/123/spam/filters')
Een collega met beperkte rechten uitnodigen
POST /api/v1/accounts/123/team/invitations · scope team:write
Lees eerst GET profile en bewaar de bijbehorende HTTP ETag (of expliciet beschreven planversie) als BINADIT_RESOURCE_VERSION. Versies van verschillende resources zijn niet uitwisselbaar.
Gebruik voor exact deze beoordeelde aanvraag een vooraf duurzaam bewaarde BINADIT_REQUEST_KEY van 16–128 veilige tekens. Hergebruik haar alleen voor dezelfde methode, URL en JSON; nooit voor een volgende stap.
Vereist ook recente sterke menselijke verificatie, actuele bevoegdheden en ingeschakelde gevoelige acties. Een servicesleutel kan die verificatie niet leveren.
result = api(token, 'POST', '/api/v1/accounts/123/team/invitations', {'email': 'collega@example.test', 'role': 'member', 'permissions': [{'module': 'module_dns', 'level': 'read'}], 'dry_run': True}, version=os.environ["BINADIT_RESOURCE_VERSION"], key=os.environ["BINADIT_REQUEST_KEY"])
Een gepauzeerde webhook voorbereiden
POST /api/v1/accounts/123/webhooks · scope webhooks:write
Gebruik voor exact deze beoordeelde aanvraag een vooraf duurzaam bewaarde BINADIT_REQUEST_KEY van 16–128 veilige tekens. Hergebruik haar alleen voor dezelfde methode, URL en JSON; nooit voor een volgende stap.
Vereist ook recente sterke menselijke verificatie, actuele bevoegdheden en ingeschakelde gevoelige acties. Een servicesleutel kan die verificatie niet leveren.
result = api(token, 'POST', '/api/v1/accounts/123/webhooks', {'name': 'Orderstatus', 'url': 'https://receiver.example.test/binadit', 'integration_id': '44444444-4444-4444-8444-444444444444', 'dry_run': True}, key=os.environ["BINADIT_REQUEST_KEY"])
Webhookafleveringen inspecteren
GET /api/v1/accounts/123/webhooks/55555555-5555-4555-8555-555555555555/deliveries · scope webhooks:read
result = api(token, 'GET', '/api/v1/accounts/123/webhooks/55555555-5555-4555-8555-555555555555/deliveries')
De actuele productversie lezen
GET /api/v1/accounts/123/products/9 · scope products:read
result = api(token, 'GET', '/api/v1/accounts/123/products/9')
Een betaalde normale mailbox offreren
POST /api/v1/accounts/123/order-quotes · scope orders:write
Gebruik voor exact deze beoordeelde aanvraag een vooraf duurzaam bewaarde BINADIT_REQUEST_KEY van 16–128 veilige tekens. Hergebruik haar alleen voor dezelfde methode, URL en JSON; nooit voor een volgende stap.
result = api(token, 'POST', '/api/v1/accounts/123/order-quotes', {'kind': 'workspace_mailbox', 'input': {'workspace_id': 7, 'product_id': 9, 'domain_id': 12, 'local_part': 'ada', 'display_name': 'Ada', 'drive': False}, 'dry_run': True}, key=os.environ["BINADIT_REQUEST_KEY"])
Een betaalde gedeelde mailbox voorbereiden
POST /api/v1/accounts/123/workspaces/7/shared-mailboxes · scope workspace.mailboxes:write, orders:commit
Lees eerst GET workspaces/7 en bewaar de bijbehorende HTTP ETag (of expliciet beschreven planversie) als BINADIT_RESOURCE_VERSION. Versies van verschillende resources zijn niet uitwisselbaar.
Gebruik voor exact deze beoordeelde aanvraag een vooraf duurzaam bewaarde BINADIT_REQUEST_KEY van 16–128 veilige tekens. Hergebruik haar alleen voor dezelfde methode, URL en JSON; nooit voor een volgende stap.
Lees ook GET products/9 en bewaar zijn ongequote data.version als BINADIT_PRODUCT_VERSION. Deze betaalde gedeelde mailbox vraagt naast mailrechten ook orders:commit en actuele bestel- en bestedingsrechten. Een productversie is geen Workspace-versie.
payload = {'domain_id': 12, 'product_id': 9, 'local_part': 'support', 'display_name': 'Support', 'member_ids': [23, 24], 'dry_run': True}
payload['product_version'] = os.environ['BINADIT_PRODUCT_VERSION']
result = api(token, 'POST', '/api/v1/accounts/123/workspaces/7/shared-mailboxes', payload, version=os.environ["BINADIT_RESOURCE_VERSION"], key=os.environ["BINADIT_REQUEST_KEY"])
Versturen als afzonderlijk inschakelen
PUT /api/v1/accounts/123/workspaces/7/mailboxes/23/delegates/24 · scope workspace.mailboxes:write
Lees eerst GET workspaces/7/mailboxes/23 en bewaar de bijbehorende HTTP ETag (of expliciet beschreven planversie) als BINADIT_RESOURCE_VERSION. Versies van verschillende resources zijn niet uitwisselbaar.
Gebruik voor exact deze beoordeelde aanvraag een vooraf duurzaam bewaarde BINADIT_REQUEST_KEY van 16–128 veilige tekens. Hergebruik haar alleen voor dezelfde methode, URL en JSON; nooit voor een volgende stap.
Send As aanzetten vereist recente sterke persoonlijke verificatie en volledige mailtoegang. Een servicesleutel met alleen de genoemde scope is niet voldoende.
result = api(token, 'PUT', '/api/v1/accounts/123/workspaces/7/mailboxes/23/delegates/24', {'level': 'full', 'send_as': True, 'calendar_level': 'write', 'dry_run': True}, version=os.environ["BINADIT_RESOURCE_VERSION"], key=os.environ["BINADIT_REQUEST_KEY"])
Mail- en agendatoegang samen intrekken
DELETE /api/v1/accounts/123/workspaces/7/mailboxes/23/delegates/24 · scope workspace.mailboxes:write
Lees eerst GET workspaces/7/mailboxes/23 en bewaar de bijbehorende HTTP ETag (of expliciet beschreven planversie) als BINADIT_RESOURCE_VERSION. Versies van verschillende resources zijn niet uitwisselbaar.
Gebruik voor exact deze beoordeelde aanvraag een vooraf duurzaam bewaarde BINADIT_REQUEST_KEY van 16–128 veilige tekens. Hergebruik haar alleen voor dezelfde methode, URL en JSON; nooit voor een volgende stap.
result = api(token, 'DELETE', '/api/v1/accounts/123/workspaces/7/mailboxes/23/delegates/24', {'dry_run': True}, version=os.environ["BINADIT_RESOURCE_VERSION"], key=os.environ["BINADIT_REQUEST_KEY"])
Verder werken
Pagineren zonder resources over te slaan
Lees meta.next_cursor, ook wanneer de gefilterde data-lijst leeg is. Volg geen willekeurige next-URL met je Bearer-token. Onderstaande lus stopt met een fout als de begrenzing wordt bereikt.
import urllib.parse
cursor = None
seen = set()
for page in range(20):
path = "/api/v1/accounts/123/domains?limit=25"
if cursor is not None:
path += "&cursor=" + urllib.parse.quote(str(cursor), safe="")
result = api(token, "GET", path)
for domain in result["data"]["data"]:
print(domain["id"]) # Only the chosen safe field.
cursor = result["data"].get("meta", {}).get("next_cursor")
if cursor is None:
break
if str(cursor) in seen:
raise RuntimeError("Repeated pagination cursor")
seen.add(str(cursor))
else:
raise RuntimeError("Page limit reached; explicitly continue from the saved cursor")
PDF opslaan zonder bestaand bestand te overschrijven
import os
result = api(token, "GET", "/api/v1/accounts/123/billing/invoices/45/pdf", binary=True)
fd = os.open("factuur-45.pdf", os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600)
with os.fdopen(fd, "wb") as output:
output.write(result["data"])
Gebruik op Windows een map waarvan alleen de bedoelde gebruiker de ACL-toegang heeft. Een fout is geen toestemming om een bestaand bestand alsnog te overschrijven.
Webhookhandtekening controleren
from binadit import verify_webhook
# Obtain raw bytes and the headers from your server framework before parsing JSON.
valid = verify_webhook(raw_body, delivery_id_header, timestamp_header, signature_header,
os.environ["BINADIT_WEBHOOK_KEY_ID"], os.environ["BINADIT_WEBHOOK_SECRET"])
if not valid:
raise ValueError("Reject this webhook")
# Next: atomically insert the delivery ID (UNIQUE) and enqueue the work in your DB.
Configureer een passende bodylimiet en controleer ontbrekende of dubbele headers in je framework. De functie weigert meer dan 1 MiB, een onjuist tijdvenster, onbekende sleutel-ID en foutieve HMAC. Zij voorkomt zelf geen replay: voeg de unieke delivery-ID en het werkitem in dezelfde duurzame transactie toe voordat je 2xx antwoordt. Lees de afspraken voor alle talen.