SDKs
One client per language, each with nothing outside its standard library.
Base316 has a client for seven languages. Each one depends on nothing beyond
its standard library — the TypeScript one uses global fetch, the .NET one the
BCL — so adding Base316 never changes your dependency graph.
| Language | Where |
|---|---|
| TypeScript / JavaScript | npm install @base316/sdk |
| Python 3.9+ | sdks/python — the base316 package |
| Go 1.22+ | sdks/go — github.com/base316/base316-go |
| Ruby 2.6+ | sdks/ruby — lib/base316.rb |
| Java 17+ | sdks/java — com.base316 |
| C# / .NET 8+ | sdks/csharp — the Base316 project |
| PHP 8.1+ | sdks/php — base316/sdk |
Only the TypeScript SDK is published to a registry today. The other six are single-file clients in the Base316 repository: copy the source into your project, or vendor the directory. Each one is a handful of files with no dependencies, which is what makes that practical.
The TypeScript package covers the whole API — every endpoint has a method — and
includes Base316Browser, the client for a publishable key in a browser. The
other six cover what an application's server actually touches, listed below;
anything beyond that is one HTTPS call with your secret key.
For drop-in screens rather than calls, see Components.
What every SDK covers
| Area | What |
|---|---|
| Keys | Parse a key and refuse one that cannot do the job, at construction |
| Sign-in | Build the hosted sign-in URL; exchange the one-time code for a session |
| Sessions | Resolve and revoke |
| Access | checkAccess — entitlement, permission and relationship in one call |
| Usage | recordEvent, with a required idempotency key |
| Customers | Create, read, list; the accounts a customer pays for; every feature evaluated (customers.entitlements · get_customer_entitlements · GetCustomerEntitlements · getCustomerEntitlements · GetCustomerEntitlementsAsync) |
| Subscriptions | Create, with an optional trialDays for a no-card trial; preview the next invoice (subscriptions.upcomingInvoice · get_upcoming_invoice · GetUpcomingInvoice · getUpcomingInvoice · GetUpcomingInvoiceAsync); change the quantity, prorated, after previewing it (previewQuantity / setQuantity · preview_quantity_change / change_subscription_quantity · PreviewQuantityChange / ChangeSubscriptionQuantity); preview, make or schedule a plan change and undo a scheduled one (previewPlanChange · changePlan · cancelScheduledChange, preview_plan_change · change_plan · cancel_scheduled_change in Python and Ruby). Ramps: subscriptions.setPhases in TypeScript |
| Retention | The retention offer and its report; start a cancellation, then accept the offer or confirm (retention.start / accept / confirm · start_cancellation / accept_retention_offer / confirm_cancellation · StartCancellation / AcceptRetentionOffer / ConfirmCancellation · startCancellation · StartCancellationAsync). See Retention offers |
| Organizations | List, create (parentId for a managed tenant), children, detach, members |
| Managed tenants | Read and replace the inherited-role mapping |
| White-label | Read and set a tenant's branding; claim, verify and remove its sign-in domain |
| Webhooks | Verify a signature in constant time, with a timestamp tolerance; parse the event |
Managed tenants, by language
The same calls, named the way each language names things. TypeScript groups
them under organizations and customers.
| Call | TypeScript | Python / Ruby | Go | Java · PHP · C# |
|---|---|---|---|---|
| Create a client tenant | organizations.create({ parentId }) | create_organization(parent_id=) | CreateOrganization | createOrganization · CreateOrganizationAsync |
| List a parent's clients | organizations.children(id) | list_child_organizations | ListChildOrganizations | listChildOrganizations |
| Detach | organizations.detach(id) | detach_organization | DetachOrganization | detachOrganization |
| Read the role mapping | organizations.inheritedRoles(id) | get_inherited_roles | GetInheritedRoles | getInheritedRoles |
| Replace it | organizations.setInheritedRoles(id, …) | set_inherited_roles | SetInheritedRoles | setInheritedRoles |
| What a firm pays for | customers.billed(id) | list_billed_customers | ListBilledCustomers | listBilledCustomers |
| A tenant's branding | organizations.branding · setBranding | get_ · set_organization_branding | Get · SetOrganizationBranding | get · setOrganizationBranding |
| A tenant's domain | organizations.domain · addDomain · verifyDomain · removeDomain | get_ · add_ · verify_ · remove_organization_domain | …OrganizationDomain | …OrganizationDomain |
C# methods end in Async and take a CancellationToken. Setting branding is a
patch in every language: leave a key out to keep it, pass an explicit null to
clear it so the tenant falls back to its parent and then the environment.
See Managed tenants for what these do.
Three things they do that hand-rolled code gets wrong
A secret key in a browser throws. The TypeScript client refuses to construct
in a browser with a b316_sk_ key — the one mistake that leaks an entire
environment and stays invisible afterwards, because the code keeps working.
Webhook comparison is constant time, and the timestamp is checked. A plain
== leaks how much of a forged signature was right; a missing timestamp check
lets one captured delivery be replayed for ever.
Retries are selective. A 429 or a 5xx is retried with jittered backoff,
honouring Retry-After. A 4xx is not — it will fail the same way every time.
Errors
Every client raises a typed error carrying code, status and requestId.
The request id is the one value support can find a specific call by, so log it.

