Skip to documentation

Exchange will be rebuilt separately and is unavailable through the API or CLI. Availability in this release

Code examples in four languages

Workflow guides

Markdown

On this page

Getting started

Choose a language above. Each language guide includes a complete reusable HTTP client and the same important tasks. Source files are in docs/examples/; these are inspectable examples, not a separate official SDK package. Python and JavaScript use only their standard libraries; PHP requires cURL and C# uses .NET 10. Run JavaScript on the server, even when the rest of your application uses TypeScript.

Under Account → API and integrations, create a dedicated service connection with minimal scopes. Have your secret manager provide BINADIT_CLIENT_ID and BINADIT_CLIENT_SECRET. The client uses them to request one short-lived token through POST /oauth/token with grant_type=client_credentials. It does not save or print the secret or token. You can supply a personal token obtained by your own OAuth application through BINADIT_ACCESS_TOKEN. Do not extract personal tokens from the CLI's system keychain. For normal interactive use, run binadit login.

A service credential cannot replace recent human verification. Team invitations, webhook administration, enabling Send As and deleting rooms may require an authorised person with recent strong verification. Use your own approved personal OAuth connection or the existing CLI for those actions. The snippets do not bypass company policy or feature flags. Exchange and legacy balance top-ups remain outside this release.

The clients use only https://my.binadit.com, normal TLS verification, a timeout and no redirects or automatic retries. The fixed origin prevents a pagination or payment URL from unintentionally receiving a Bearer token. For your own test installation, deliberately change the origin constant; do not disable certificate verification. The examples read at most 8 MiB per response. Use a separate bounded streaming implementation for larger files.

Supplying values and versions

All example.test addresses, documentation IP addresses, IDs and UUIDs are fictional. Replace them with resources read through the same company connection. 123 is the company, 7 a Workspace, 23/24 mailboxes, 8 a DNS zone and 12 a mail domain. An ID from another company grants no authority.

For pagination, follow meta.next_cursor even when permission filtering leaves the data array empty. The language guides show a bounded loop that also rejects repeated cursors. Do not follow an arbitrary next-page URL with your token.

The client returns etag and data; data is the complete JSON envelope, for example result.data.data in JavaScript. C# uses ETag, Data and, for a PDF, Bytes. Associate each ETag with its exact resource. For version-controlled mutations, the language guide identifies the GET to perform first. Put that reviewed ETag or explicit plan version in BINADIT_RESOURCE_VERSION. Do not invent a hash or use a version belonging to another object.

Before sending each reviewed write, durably preserve the original principal, method, URL, exact JSON, resource version and a random Idempotency-Key containing 16–128 safe characters. Supply that original key through BINADIT_REQUEST_KEY. A UUID is suitable: generate it once in your own durable request store, not again on every script launch. As a precaution, the example clients also require a key for read-oriented POST requests; that does not turn those endpoints into mutations.

Write examples use dry_run: true where relevant. A dry run does not save an executable order, grant or DNS plan. For real execution, review the preview first, read current versions and preserve the final JSON without dry_run together with its own key. Do not paste all examples into one sequence: each snippet is a separate task with its own input and key. A dry run of a sensitive action does not remove its human-verification requirement.

Ordering, paying and cancelling

  1. Read products, your company holder and capabilities. Ask the server for pricing; do not calculate your own selling price.
  2. Review a quote preview. Then deliberately request a saved quote by omitting dry_run. Use the actual data.id and inspect that same quote with GET. A preview ID must not be treated as a real quote.
  3. Preview confirmation through orders with dry_run: true. Only after approval, submit that same quote ID without dry_run, with a durably recorded key for that action. This can create an invoice and order. orders:commit and current ordering/spending privileges remain required.
  4. The order may return checkout_url. Open it separately in a browser to confirm payment. Never send the Binadit token to the payment provider or fetch that URL with the example client.
  5. Follow the original operation and read the domain again. queued or awaiting_payment does not prove registration. Check registrar status, DNS publication and subscription/automatic renewal separately.

Cancelling a domain disables automatic renewal; it does not immediately delete the registration. Afterwards, read domains/{id}/subscription again and check the recorded end date and billing status. Hosting and other services have their own cancellation intents; a domain and a hosting package are separate agreements.

DNS and Workspace

DNS always goes through the Binadit API and the existing portal processing. Read records, create a plan, review the records and version, then apply the original plan separately. A template plan is also a proposal. Never use PowerDNS, NS1 or Cloudflare credentials directly in these clients. The record value field is value; CNAME targets follow the portal notation without a trailing dot. When updating or deleting, use record IDs actually returned by the read, not their positions in a newly sorted list.

Personal and shared mailboxes are paid products. Order a personal mailbox through a quote of kind workspace_mailbox; shared mailboxes follow their own paid contract. The delegate, calendar, mailing-list and room examples are free and require no product or invoice. full also grants Send on Behalf; send_as is a separate sensitive choice. When Send As is disabled while full remains, recipients see the delegate again. A list member is an existing typed ID such as mailbox-24, not an external address or nested list. Rooms have no login password; recurring meetings are checked only for their first occurrence. See the complete mail contract.

Errors, uncertain outcomes and progress

Outcome Action
401 Stop. First check whether a mutation could already have been sent. Request a new token for subsequent deliberate actions; do not automatically repeat a POST.
403/404 Check the company, scopes, resource restrictions and any human-verification requirement; do not work around the refusal with another company or administrator token.
409 Inspect the existing request or blocker. Do not replace it with a new key, quote or supplier request.
412/428 Read the correct resource again and review the changed situation; do not force a fresh ETag onto an old command.
422 Check fields, types and the OpenAPI contract.
429 Respect Retry-After. The helpers do not retry. Inspect an uncertain mutation before later reading again or requesting another action.
Timeout/5xx The outcome may be unknown. Keep the original metadata and inspect the operation. A timeout does not prove that the server performed no action.

operation.request_status: succeeded confirms the HTTP receipt, not necessarily the supplier action. Follow operation.status, including queued, running, awaiting_payment, requires_approval, requires_reconciliation, failed and succeeded. A held free mail task is requires_reconciliation, not a payment request. A failed colleague/DNS task is no reason to submit a second paid order.

Keep returned operation, plan and intent IDs with your original request. With operations:read, poll the same operation at a bounded rate, for example once every five seconds for at most two minutes per script execution. Stop at a review or payment status; do not force it through. After a new personal login, the original principal may have changed: use the original receipt rather than automatically replaying under the new connection.

The clients deliberately report errors without the unfiltered response body. Do not log Bearer tokens, client secrets, one-time claims, personal details, mail content or PDFs. One-time password and key claims have a separate protocol and do not belong in a generic retry loop.

Receiving webhooks

The language guides include an HMAC check for the unmodified raw body and the three headers Binadit-Webhook-Id, Binadit-Webhook-Timestamp and Binadit-Webhook-Signature. Obtain the expected key ID and secret from your own secret manager. Use TLS, check the time window, compare in constant time, then prevent replay with a unique delivery ID in durable storage. A valid signature alone does not prevent duplicate execution.

After verification, atomically record the delivery ID and a work item in one database transaction with a unique constraint. Return 2xx only after that commits. An already durably received, validly signed delivery gets 2xx again without repeating its work. Never process an invoice notification twice. When rotating keys, retain only deliberately approved key IDs belonging to your integration; never trust an unknown key_id from a header.

Contract and verification

Examples are generated from the actual operation catalog and shared recipes. Routes, scopes, methods and JSON bodies are checked locally against OpenAPI. The client code is separately executed against a local test receiver; this does not modify customer data or submit paid production actions. Development notes alongside the source record the PHP/Python/Node versions and .NET build check. This is not a claim that every illustrated paid action was ordered on production in all four languages.

The examples follow the current release scope, API reference and agent guide. Standard-library references: HttpClient redirects, Node fetch and timeouts.

Tasks available in every language

Task Method Scope
Check the authenticated identity GET account:read
List accessible companies GET account:read
Check capabilities and scopes GET account:read
Read company details and their ETag GET account:read
Update company details PATCH account:write
Read products and prices GET products:read
List existing domain holders GET holders:read
Preview a default holder from company or personal details POST holders:read, holders:write
Create a company domain holder POST holders:write
Check domain availability POST domains:read
Quote a domain registration POST orders:write
Read a saved quote again GET orders:read
Preview an order and payment POST orders:commit
Read registration renewal and subscription status GET domains:read
Disable automatic domain renewal POST domains:write
List DNS zones GET dns.zones:read
Read current DNS records and version GET dns.records:read
List DNS templates GET dns.templates:read
Preview a DNS template POST dns.templates:write
Propose applying a template POST dns.records:write
Preview multiple DNS records in one plan POST dns.records:write
Apply a reviewed DNS plan POST dns.records:write
Follow the original operation GET operations:read
List invoices GET billing.invoices:read
Download an invoice PDF GET billing.invoices:read
List Workspaces GET workspace:read
List mailboxes GET workspace.mailboxes:read
Read delegates and user-configured shares GET workspace.mailboxes:read
Grant full mail access and calendar editing PUT workspace.mailboxes:write
Preview a free mailing list POST workspace.mailboxes:write
Add one mailing-list member PUT workspace.mailboxes:write
Remove one mailing-list member DELETE workspace.mailboxes:write
Preview a free room POST workspace.mailboxes:write
Add a room manager PUT workspace.mailboxes:write
Delete a room with personal verification DELETE workspace.mailboxes:write
List hosting subscriptions GET hosting:read
Preview hosting cancellation POST hosting:write
List spam filters GET spam:read
Invite a colleague with limited permissions POST team:write
Preview a paused webhook POST webhooks:write
Inspect webhook deliveries GET webhooks:read
Read the current product version GET products:read
Quote a paid personal mailbox POST orders:write
Preview a paid shared mailbox POST workspace.mailboxes:write, orders:commit
Enable Send As separately PUT workspace.mailboxes:write
Revoke mail and calendar access together DELETE workspace.mailboxes:write