Try Opteryx

Billing API

Base URL: https://billing.opteryx.app

Overview

Billing account and membership management, payment methods and charges, and workspace lifecycle (creation, deletion, locking).

Endpoints

ServiceDocs
List Accountsget/v1/accounts View
Create Accountpost/v1/accounts View
Get Accountget/v1/accounts/{account_id} View
Update Accountpatch/v1/accounts/{account_id} View
Delete Accountdelete/v1/accounts/{account_id} View
List Membersget/v1/accounts/{account_id}/members View
Invite Memberpost/v1/accounts/{account_id}/members View
Update Member Rolepatch/v1/accounts/{account_id}/members/{identity} View
Remove Memberdelete/v1/accounts/{account_id}/members/{identity} View
Accept Invitepost/v1/accounts/{account_id}/members/{identity}/accept View
Get Payment Methodget/v1/accounts/{account_id}/payment-methods View
Attach Payment Methodpost/v1/accounts/{account_id}/payment-methods View
Detach Payment Methoddelete/v1/accounts/{account_id}/payment-methods View
Create Paymentpost/v1/accounts/{account_id}/payments View
List Account Workspacesget/v1/accounts/{account_id}/workspaces View
List Invoicesget/v1/invoices View
Get Invoiceget/v1/invoices/{invoice_id} View
Create Workspaceput/v1/workspaces/{name} View
Delete Workspacedelete/v1/workspaces/{name} View
Lock Workspaceput/v1/workspaces/{name}/lock View
Unlock Workspacedelete/v1/workspaces/{name}/lock View
Restore Workspacepost/v1/workspaces/{name}/restore View

List Accounts

Request: get/v1/accounts

List accounts the caller is an active member of.

Membership is exclusive (find_existing_membership), so this returns at most one row in practice - still a list per the design doc's shape, not collapsed to a single object.

Header Parameters

  • authorization string | null [header; optional]

Responses

  • 200 — Successful Response (application/json array<object>)
  • 422 — Validation Error (application/json HTTPValidationError)

Try it live

get https://billing.opteryx.app/v1/accounts
Bearer token required
Held in this tab only — never stored or logged. See the Authentication API for how to get one.

    

Create Account

Request: post/v1/accounts

Create a billing account. The caller becomes its first billing_admin immediately as an active member (not a pending invite) - see new_genesis_member_doc's docstring for why.

Header Parameters

  • authorization string | null [header; optional]

Request Body

  • Content-Type: application/json Schema: AccountCreateRequest
    • name string [required]
    • tax_id string | null [optional]
    • address object | null [optional]

Responses

  • 201 — Successful Response (application/json object)
  • 422 — Validation Error (application/json HTTPValidationError)

Try it live

post https://billing.opteryx.app/v1/accounts
Bearer token required
Held in this tab only — never stored or logged. See the Authentication API for how to get one.
Request body application/json · AccountCreateRequest

    

Get Account

Request: get/v1/accounts/{account_id}

Read. Only visible to active members of the account - an account's name/tax_id/address are not public to any authenticated caller who happens to know or guess an account id.

Path Parameters

  • account_id string [path; required]

Header Parameters

  • authorization string | null [header; optional]

Responses

  • 200 — Successful Response (application/json object)
  • 422 — Validation Error (application/json HTTPValidationError)

Try it live

get https://billing.opteryx.app/v1/accounts/{account_id}
Bearer token required
Held in this tab only — never stored or logged. See the Authentication API for how to get one.
Path parameters
account_idstring · required

    

Update Account

Request: patch/v1/accounts/{account_id}

Partial update: name, tax_id, address, member_min_age_ms. Only billing_admins of the account may update it.

Path Parameters

  • account_id string [path; required]

Header Parameters

  • authorization string | null [header; optional]

Request Body

  • Content-Type: application/json Schema: AccountUpdateRequest
    • name string | null [optional]
    • tax_id string | null [optional]
    • address object | null [optional]
    • member_min_age_ms integer | null [optional]

Responses

  • 200 — Successful Response (application/json object)
  • 422 — Validation Error (application/json HTTPValidationError)

Try it live

patch https://billing.opteryx.app/v1/accounts/{account_id}
Bearer token required
Held in this tab only — never stored or logged. See the Authentication API for how to get one.
Path parameters
account_idstring · required
Request body application/json · AccountUpdateRequest

    

Delete Account

Request: delete/v1/accounts/{account_id}

Soft-delete: status: deactivated. Only billing_admins may call this.

409 if any workspace still references this account. On success, cascades to delete every member subdocument - no "deactivated but still has members" state should exist afterward.

Path Parameters

  • account_id string [path; required]

Header Parameters

  • authorization string | null [header; optional]

Responses

  • 200 — Successful Response (application/json object)
  • 422 — Validation Error (application/json HTTPValidationError)

Try it live

delete https://billing.opteryx.app/v1/accounts/{account_id}
Bearer token required
Held in this tab only — never stored or logged. See the Authentication API for how to get one.
Path parameters
account_idstring · required

    

List Members

Request: get/v1/accounts/{account_id}/members

List members. Any active member of the account may list.

Expired pending rows (now > invite_expires_at) are filtered out of the response and lazily deleted from Firestore when encountered - no separate sweep job, per api-v2.md.

Path Parameters

  • account_id string [path; required]

Header Parameters

  • authorization string | null [header; optional]

Responses

  • 200 — Successful Response (application/json array<object>)
  • 422 — Validation Error (application/json HTTPValidationError)

Try it live

get https://billing.opteryx.app/v1/accounts/{account_id}/members
Bearer token required
Held in this tab only — never stored or logged. See the Authentication API for how to get one.
Path parameters
account_idstring · required

    

Invite Member

Request: post/v1/accounts/{account_id}/members

Invite a new member. Only existing billing_admins of this account may invite.

409 if the invitee already has an active/pending membership on another account (checked via the collection-group find_existing_membership query). Re-inviting an identity that's still pending on this same account resets the 7-day clock instead of erroring - a fresh new_member_doc is written over the existing pending doc.

Path Parameters

  • account_id string [path; required]

Header Parameters

  • authorization string | null [header; optional]

Request Body

  • Content-Type: application/json Schema: InviteMemberRequest
    • identity_or_email string [required]
    • role string [required]

Responses

  • 201 — Successful Response (application/json object)
  • 422 — Validation Error (application/json HTTPValidationError)

Try it live

post https://billing.opteryx.app/v1/accounts/{account_id}/members
Bearer token required
Held in this tab only — never stored or logged. See the Authentication API for how to get one.
Path parameters
account_idstring · required
Request body application/json · InviteMemberRequest

    

Update Member Role

Request: patch/v1/accounts/{account_id}/members/{identity}

{role: "billing_admin"|"member"}. Only billing_admins may change roles.

Path Parameters

  • account_id string [path; required]
  • identity string [path; required]

Header Parameters

  • authorization string | null [header; optional]

Request Body

  • Content-Type: application/json Schema: UpdateMemberRoleRequest
    • role string [required]

Responses

  • 200 — Successful Response (application/json object)
  • 422 — Validation Error (application/json HTTPValidationError)

Try it live

patch https://billing.opteryx.app/v1/accounts/{account_id}/members/{identity}
Bearer token required
Held in this tab only — never stored or logged. See the Authentication API for how to get one.
Path parameters
account_idstring · required
identitystring · required
Request body application/json · UpdateMemberRoleRequest

    

Remove Member

Request: delete/v1/accounts/{account_id}/members/{identity}

Remove a member (also how an unaccepted invite gets withdrawn).

Only billing_admins may remove other members. Self-removal (an identity removing itself, i.e. leaving the account) is allowed without the billing_admin check - api-v2.md is silent on this specifically, but it's a low-risk, clearly-reasonable capability (a member/admin should always be able to leave their own account).

Path Parameters

  • account_id string [path; required]
  • identity string [path; required]

Header Parameters

  • authorization string | null [header; optional]

Responses

  • 200 — Successful Response (application/json object)
  • 422 — Validation Error (application/json HTTPValidationError)

Try it live

delete https://billing.opteryx.app/v1/accounts/{account_id}/members/{identity}
Bearer token required
Held in this tab only — never stored or logged. See the Authentication API for how to get one.
Path parameters
account_idstring · required
identitystring · required

    

Accept Invite

Request: post/v1/accounts/{account_id}/members/{identity}/accept

Invitee (authenticated as {identity}) flips pending -> active.

Stamps added_at/min_age_ms/eligible_at at acceptance time - min_age_ms is read fresh from the account doc now, not from whatever was on the invite, per api-v2.md's "snapshot at accept time" behavior. 410 if the invite has expired; 404 if there's no pending invite for this identity on this account.

Path Parameters

  • account_id string [path; required]
  • identity string [path; required]

Header Parameters

  • authorization string | null [header; optional]

Responses

  • 200 — Successful Response (application/json object)
  • 422 — Validation Error (application/json HTTPValidationError)

Try it live

post https://billing.opteryx.app/v1/accounts/{account_id}/members/{identity}/accept
Bearer token required
Held in this tab only — never stored or logged. See the Authentication API for how to get one.
Path parameters
account_idstring · required
identitystring · required

    

Get Payment Method

Request: get/v1/accounts/{account_id}/payment-methods

Return the single attached payment method, or null if none is attached.

A bare null (rather than e.g. a 404) is used because "no payment method attached" is a normal, expected state for this resource - not an error - matching how billing_account: null is treated as a normal free-tier state elsewhere in this design.

Path Parameters

  • account_id string [path; required]

Header Parameters

  • authorization string | null [header; optional]

Responses

  • 200 — Successful Response (application/json object | null)
  • 422 — Validation Error (application/json HTTPValidationError)

Try it live

get https://billing.opteryx.app/v1/accounts/{account_id}/payment-methods
Bearer token required
Held in this tab only — never stored or logged. See the Authentication API for how to get one.
Path parameters
account_idstring · required

    

Attach Payment Method

Request: post/v1/accounts/{account_id}/payment-methods

Attach a Stripe payment method, replacing whatever's already attached.

Verifies the token against Stripe's API before trusting it, then - if a different payment method was already attached - detaches the old one on Stripe's side so it isn't left orphaned there.

Path Parameters

  • account_id string [path; required]

Header Parameters

  • authorization string | null [header; optional]

Request Body

  • Content-Type: application/json Schema: AttachPaymentMethodRequest
    • stripe_payment_method_id string [required]
    • brand string [required]
    • last4 string [required]

Responses

  • 200 — Successful Response (application/json object)
  • 422 — Validation Error (application/json HTTPValidationError)

Try it live

post https://billing.opteryx.app/v1/accounts/{account_id}/payment-methods
Bearer token required
Held in this tab only — never stored or logged. See the Authentication API for how to get one.
Path parameters
account_idstring · required
Request body application/json · AttachPaymentMethodRequest

    

Detach Payment Method

Request: delete/v1/accounts/{account_id}/payment-methods

Detach the account's payment method, if any. Idempotent - detaching when nothing is attached is a no-op 204, not an error.

Path Parameters

  • account_id string [path; required]

Header Parameters

  • authorization string | null [header; optional]

Responses

  • 204 — Successful Response
  • 422 — Validation Error (application/json HTTPValidationError)

Try it live

delete https://billing.opteryx.app/v1/accounts/{account_id}/payment-methods
Bearer token required
Held in this tab only — never stored or logged. See the Authentication API for how to get one.
Path parameters
account_idstring · required

    

Create Payment

Request: post/v1/accounts/{account_id}/payments

Ad hoc charge against the account's attached payment method.

400 if no payment method is attached. A real PaymentIntent is created and confirmed synchronously against the attached Stripe payment method id - this moves real money, so this deliberately does not fake a successful response; a Stripe failure surfaces as 402.

Path Parameters

  • account_id string [path; required]

Header Parameters

  • authorization string | null [header; optional]

Request Body

  • Content-Type: application/json Schema: CreatePaymentRequest
    • amount integer [required]
    • currency string [optional] Default: usd
    • description string | null [optional]

Responses

  • 201 — Successful Response (application/json object)
  • 422 — Validation Error (application/json HTTPValidationError)

Try it live

post https://billing.opteryx.app/v1/accounts/{account_id}/payments
Bearer token required
Held in this tab only — never stored or logged. See the Authentication API for how to get one.
Path parameters
account_idstring · required
Request body application/json · CreatePaymentRequest

    

List Account Workspaces

Request: get/v1/accounts/{account_id}/workspaces

Manage-workspaces listing. Caller must be an active member of the account (any role).

A genuine two-database read per workspace (api-v2.md): this service's own workspaces/{name} doc for billing_account/members, plus the catalogs database's $properties doc (via an OpteryxCatalog handle) for lock/delete state. Active (non-deleted) workspaces are visible to any account member; a soft-deleted-but-still-in-grace-period workspace is included only for callers who are an owner in that specific workspace's own members list.

Path Parameters

  • account_id string [path; required]

Header Parameters

  • authorization string | null [header; optional]

Responses

  • 200 — Successful Response (application/json array<object>)
  • 422 — Validation Error (application/json HTTPValidationError)

Try it live

get https://billing.opteryx.app/v1/accounts/{account_id}/workspaces
Bearer token required
Held in this tab only — never stored or logged. See the Authentication API for how to get one.
Path parameters
account_idstring · required

    

List Invoices

Request: get/v1/invoices

Placeholder: return an empty invoices list.

Header Parameters

  • authorization string | null [header; optional]

Responses

  • 200 — Successful Response (application/json array<object>)
  • 422 — Validation Error (application/json HTTPValidationError)

Try it live

get https://billing.opteryx.app/v1/invoices
Bearer token required
Held in this tab only — never stored or logged. See the Authentication API for how to get one.

    

Get Invoice

Request: get/v1/invoices/{invoice_id}

Placeholder: return a minimal invoice representation.

Path Parameters

  • invoice_id string [path; required]

Header Parameters

  • authorization string | null [header; optional]

Responses

  • 200 — Successful Response (application/json object)
  • 422 — Validation Error (application/json HTTPValidationError)

Try it live

get https://billing.opteryx.app/v1/invoices/{invoice_id}
Bearer token required
Held in this tab only — never stored or logged. See the Authentication API for how to get one.
Path parameters
invoice_idstring · required

    

Create Workspace

Request: put/v1/workspaces/{name}

Idempotent create. Caller must be an active billing_admin on body.billing_account.

Writes workspaces/{name} (billing_account + members), then calls policy.opteryx's genesis-grant endpoint (POL-2) for the explicit member list, forwarding the caller's JWT.

Idempotency: if workspaces/{name} already exists with the same billing_account/members as requested, this is treated as a retry - the genesis call is re-attempted (policy.opteryx's own 409 in that case just means the earlier attempt's genesis call already succeeded, so that's treated as success too), and the existing doc is returned rather than erroring. If the doc exists with different billing_account/ members, that's a real name conflict: 409, no genesis call made.

Path Parameters

  • name string [path; required]

Header Parameters

  • authorization string | null [header; optional]

Request Body

  • Content-Type: application/json Schema: WorkspaceCreateRequest
    • billing_account string [required]
    • members array<WorkspaceMemberGrant> [required]

Responses

  • 200 — Successful Response (application/json object)
  • 422 — Validation Error (application/json HTTPValidationError)

Try it live

put https://billing.opteryx.app/v1/workspaces/{name}
Bearer token required
Held in this tab only — never stored or logged. See the Authentication API for how to get one.
Path parameters
namestring · required
Request body application/json · WorkspaceCreateRequest

    

Delete Workspace

Request: delete/v1/workspaces/{name}

Starts the 24h soft-delete. Caller must be an active billing_admin on the workspace's billing account. 423 if the workspace is currently locked.

Path Parameters

  • name string [path; required]

Header Parameters

  • authorization string | null [header; optional]

Responses

  • 200 — Successful Response (application/json object)
  • 422 — Validation Error (application/json HTTPValidationError)

Try it live

delete https://billing.opteryx.app/v1/workspaces/{name}
Bearer token required
Held in this tab only — never stored or logged. See the Authentication API for how to get one.
Path parameters
namestring · required

    

Lock Workspace

Request: put/v1/workspaces/{name}/lock

Workspace owner sets the lock - workspace-level (checked against this workspace's own members list), not billing-account-level.

Path Parameters

  • name string [path; required]

Header Parameters

  • authorization string | null [header; optional]

Responses

  • 200 — Successful Response (application/json object)
  • 422 — Validation Error (application/json HTTPValidationError)

Try it live

put https://billing.opteryx.app/v1/workspaces/{name}/lock
Bearer token required
Held in this tab only — never stored or logged. See the Authentication API for how to get one.
Path parameters
namestring · required

    

Unlock Workspace

Request: delete/v1/workspaces/{name}/lock

A different owner clears the lock. Not a hard access-control boundary (per api-v2.md) - the point is a second identity on record, so a straightforward identity-inequality check against the current locked-by is sufficient.

Path Parameters

  • name string [path; required]

Header Parameters

  • authorization string | null [header; optional]

Responses

  • 200 — Successful Response (application/json object)
  • 422 — Validation Error (application/json HTTPValidationError)

Try it live

delete https://billing.opteryx.app/v1/workspaces/{name}/lock
Bearer token required
Held in this tab only — never stored or logged. See the Authentication API for how to get one.
Path parameters
namestring · required

    

Restore Workspace

Request: post/v1/workspaces/{name}/restore

Within the 24h grace window, un-deletes. Owner only.

Constructs the catalog handle with include_deleted=True - restoring a deleted workspace requires reaching it in the first place.

Path Parameters

  • name string [path; required]

Header Parameters

  • authorization string | null [header; optional]

Responses

  • 200 — Successful Response (application/json object)
  • 422 — Validation Error (application/json HTTPValidationError)

Try it live

post https://billing.opteryx.app/v1/workspaces/{name}/restore
Bearer token required
Held in this tab only — never stored or logged. See the Authentication API for how to get one.
Path parameters
namestring · required