Stitchflow
Maxio logo

Maxio User Management API Guide

API workflow

How to automate user lifecycle operations through APIs with caveats that matter in production.

UpdatedMar 11, 2026

Summary and recommendation

Maxio Advanced Billing (the Chargify-lineage API) exposes a REST API at https://{subdomain}.chargify.com authenticated exclusively via HTTP Basic Auth - API key as username, literal string x as password. There are no OAuth 2.0 flows and no scope-based permissions; every API key carries full site-level access.

The rate limit is 10,000 requests per hour per site subdomain, returning HTTP 429 on breach; rate-limit headers are not returned, so exponential backoff must be implemented client-side. Pagination is offset-based using page and per_page params (default 20, max 200 per request, 1-based indexing).

Responses wrap resources in a named key (e.g., {"user": {...}}); SDKs handle unwrapping automatically. A critical architectural distinction governs every integration: Site Users (admin/staff accounts at /users.json) and Customers (billing subscribers at /customers.json) are entirely separate object types with separate endpoints. Provisioning integrations almost always target /customers, not /users.

Maxio has no SCIM 2.0 endpoint; any identity graph synchronization mapping IdP user records to Maxio customer or staff objects requires custom middleware using the reference field as the external ID anchor.

API quick reference

Has user APIYes
Auth methodHTTP Basic Auth (API key as username, 'x' as password)
Base URLOfficial docs
SCIM availableNo

Authentication

Auth method: HTTP Basic Auth (API key as username, 'x' as password)

Setup steps

  1. Log in to your Maxio Advanced Billing (Chargify) site as an admin.
  2. Navigate to Config > Integrations > API Keys.
  3. Generate or copy an existing API key.
  4. Use the API key as the HTTP Basic Auth username and the literal string 'x' as the password in all API requests.
  5. All requests must use HTTPS; HTTP is not supported.

User object / data model

Field Type Description On create On update Notes
id integer Unique identifier for the site user auto-assigned immutable Read-only
first_name string User's first name required optional
last_name string User's last name required optional
email string User's email address; used as login identifier required optional Must be unique within the site
username string Login username for the site user required optional
password string User's password (write-only) required optional Never returned in responses
created_at datetime (ISO 8601) Timestamp when the user was created auto-assigned immutable Read-only
updated_at datetime (ISO 8601) Timestamp of last update auto-assigned auto-updated Read-only

Core endpoints

List Users

  • Method: GET
  • URL: https://{subdomain}.chargify.com/users.json
  • Watch out for: Returns site-level admin/staff users only, not end-customer (subscriber) records.

Request example

GET /users.json?page=1&per_page=20 HTTP/1.1
Host: {subdomain}.chargify.com
Authorization: Basic {base64(api_key:x)}

Response example

[
  {
    "user": {
      "id": 123,
      "first_name": "Jane",
      "last_name": "Doe",
      "email": "jane@example.com",
      "username": "janedoe"
    }
  }
]

Read User

  • Method: GET
  • URL: https://{subdomain}.chargify.com/users/{id}.json
  • Watch out for: Returns 404 if the user ID does not exist in the site.

Request example

GET /users/123.json HTTP/1.1
Host: {subdomain}.chargify.com
Authorization: Basic {base64(api_key:x)}

Response example

{
  "user": {
    "id": 123,
    "first_name": "Jane",
    "last_name": "Doe",
    "email": "jane@example.com",
    "username": "janedoe"
  }
}

Create User

  • Method: POST
  • URL: https://{subdomain}.chargify.com/users.json
  • Watch out for: Creates a site admin/staff user. Does not create a billing customer (use /customers.json for that).

Request example

POST /users.json HTTP/1.1
Host: {subdomain}.chargify.com
Authorization: Basic {base64(api_key:x)}
Content-Type: application/json

{"user":{"first_name":"Jane","last_name":"Doe","email":"jane@example.com","username":"janedoe","password":"secret"}}

Response example

{
  "user": {
    "id": 124,
    "first_name": "Jane",
    "last_name": "Doe",
    "email": "jane@example.com",
    "username": "janedoe"
  }
}

Update User

  • Method: PUT
  • URL: https://{subdomain}.chargify.com/users/{id}.json
  • Watch out for: Only fields included in the request body are updated; omitted fields retain existing values.

Request example

PUT /users/123.json HTTP/1.1
Host: {subdomain}.chargify.com
Authorization: Basic {base64(api_key:x)}
Content-Type: application/json

{"user":{"first_name":"Janet"}}

Response example

{
  "user": {
    "id": 123,
    "first_name": "Janet",
    "last_name": "Doe",
    "email": "jane@example.com"
  }
}

Delete User

  • Method: DELETE
  • URL: https://{subdomain}.chargify.com/users/{id}.json
  • Watch out for: Deletion is permanent and cannot be undone via the API.

Request example

DELETE /users/123.json HTTP/1.1
Host: {subdomain}.chargify.com
Authorization: Basic {base64(api_key:x)}

Response example

HTTP/1.1 204 No Content

List Customers

  • Method: GET
  • URL: https://{subdomain}.chargify.com/customers.json
  • Watch out for: Customers are billing entities (subscribers), distinct from site Users (admin accounts). Most provisioning integrations target /customers, not /users.

Request example

GET /customers.json?page=1&per_page=50 HTTP/1.1
Host: {subdomain}.chargify.com
Authorization: Basic {base64(api_key:x)}

Response example

[
  {
    "customer": {
      "id": 5001,
      "first_name": "Bob",
      "last_name": "Smith",
      "email": "bob@acme.com",
      "reference": "acme-001"
    }
  }
]

Create Customer

  • Method: POST
  • URL: https://{subdomain}.chargify.com/customers.json
  • Watch out for: The 'reference' field is your external ID; it must be unique per site. Duplicate reference values return a 422 error.

Request example

POST /customers.json HTTP/1.1
Host: {subdomain}.chargify.com
Authorization: Basic {base64(api_key:x)}
Content-Type: application/json

{"customer":{"first_name":"Bob","last_name":"Smith","email":"bob@acme.com","reference":"acme-001"}}

Response example

{
  "customer": {
    "id": 5002,
    "first_name": "Bob",
    "last_name": "Smith",
    "email": "bob@acme.com",
    "reference": "acme-001"
  }
}

Update Customer

  • Method: PUT
  • URL: https://{subdomain}.chargify.com/customers/{id}.json
  • Watch out for: Changing email does not trigger any re-verification flow via the API.

Request example

PUT /customers/5001.json HTTP/1.1
Host: {subdomain}.chargify.com
Authorization: Basic {base64(api_key:x)}
Content-Type: application/json

{"customer":{"email":"bob.new@acme.com"}}

Response example

{
  "customer": {
    "id": 5001,
    "email": "bob.new@acme.com"
  }
}

Rate limits, pagination, and events

  • Rate limits: Maxio Advanced Billing enforces per-site rate limits. The default limit is 10,000 API calls per hour per site. Exceeding the limit returns HTTP 429.
  • Rate-limit headers: No
  • Retry-After header: No
  • Rate-limit notes: Rate limit headers are not documented as returned by the API. Retry after receiving a 429 response; official docs recommend exponential backoff. Limits apply per site subdomain.
  • Pagination method: offset
  • Default page size: 20
  • Max page size: 200
  • Pagination pointer: page / per_page
Plan Limit Concurrent
All plans (default) 10,000 requests/hour per site 0
  • Webhooks available: Yes
  • Webhook notes: Maxio Advanced Billing supports webhooks for subscription and customer lifecycle events. Webhooks are configured per site in the dashboard under Config > Integrations > Webhooks.
  • Alternative event strategy: Poll /customers.json or /subscriptions.json with updated_at filters for change detection if webhooks are not feasible.
  • Webhook events: customer_update, signup_success, signup_failure, subscription_state_change, subscription_product_change, renewal_success, renewal_failure, payment_success, payment_failure, expiring_card, billing_date_change, subscription_deletion

SCIM API status

  • SCIM available: No
  • SCIM version: Not documented
  • Plan required: Not documented
  • Endpoint: Not documented

Limitations:

  • Maxio does not offer a SCIM 2.0 endpoint for automated user provisioning/deprovisioning.
  • SSO via SAML is available (Okta, Entra ID documented) but SCIM sync is not supported.
  • User lifecycle management must be performed via the REST API or manually in the dashboard.

Common scenarios

Three scenarios cover the primary provisioning lifecycle. To provision a new billing customer, POST to /customers.

json with first_name, last_name, email, and a unique reference (your external or IdP user ID). Capture the returned customer.

id, then POST to /subscriptions. json with customer_id and product_handle to activate.

Always check GET /customers/lookup. json?

reference={ref} before creating - duplicate reference values return a 422 with no upsert behavior. To deprovision, resolve the customer via the reference lookup, list active subscriptions via GET /customers/{id}/subscriptions.

json, then cancel each via POST /subscriptions/{id}/cancel. json.

Cancellation is preferred over DELETE because it allows reactivation; deletion is permanent and irreversible via the API. Customer-record deletion is not available via a standard API endpoint and must be handled in the dashboard.

To sync an email change from an IdP, resolve the Maxio customer ID via the reference lookup, then PUT /customers/{id}. json with {"customer": {"email": "new@example.

com"}}. Email changes do not trigger re-verification; log the updated_at timestamp from the 200 response for audit trail purposes.

Provision a new billing customer and assign a subscription

  1. POST /customers.json with first_name, last_name, email, and a unique reference (your external user ID).
  2. Capture the returned customer.id.
  3. POST /subscriptions.json with customer_id, product_handle, and payment_profile attributes to activate the subscription.
  4. Store the returned subscription.id for future lifecycle management.

Watch out for: If the reference already exists, the API returns 422. Check for existing customers via GET /customers/lookup.json?reference={ref} before creating.

Deprovision a user (cancel subscription and archive customer)

  1. GET /customers/lookup.json?reference={external_id} to resolve the Maxio customer ID.
  2. GET /customers/{id}/subscriptions.json to list active subscriptions.
  3. DELETE /subscriptions/{subscription_id}.json (or POST /subscriptions/{id}/cancel.json) for each active subscription.
  4. Optionally archive the customer record via the dashboard; there is no dedicated customer-delete API endpoint in standard plans.

Watch out for: Deleting a subscription is irreversible via the API. Use cancellation (which allows reactivation) unless permanent removal is intended.

Sync updated email address from IdP to Maxio customer record

  1. Receive user update event from your IdP (e.g., Okta webhook or SCIM update to your middleware).
  2. GET /customers/lookup.json?reference={external_id} to find the Maxio customer ID.
  3. PUT /customers/{id}.json with {"customer": {"email": "new@example.com"}} to update the email.
  4. Verify the 200 response and log the updated_at timestamp.

Watch out for: Maxio has no SCIM endpoint; this sync must be implemented in custom middleware. Email changes do not trigger re-verification.

Why building this yourself is a trap

The absence of SCIM is the primary integration trap: there is no standards-based endpoint for automated provisioning, so any identity graph that needs to reflect Maxio staff or customer state must maintain its own sync layer.

The API key model compounds this - keys are site-scoped and grant full access with no granular scopes, meaning a compromised or orphaned key exposes the entire site. Multi-site organizations face a multiplier effect: each site has its own subdomain, its own API keys, and its own user list, with no cross-site API surface.

Webhook payloads default to form-encoded POST bodies rather than JSON, which surprises integrators expecting standard JSON delivery. The Maxio entity also covers two distinct API surfaces - Advanced Billing (Chargify lineage) and SaaS Metrics (SaaSOptics lineage) - which have separate APIs; assuming a single unified API is a common and costly architectural mistake.

An integration platform offering an MCP server with 60+ deep IT/identity integrations can abstract per-site key management, normalize the Users/Customers object split, and maintain the identity graph sync that Maxio's native API does not provide.

Automate Maxio workflows without one-off scripts

Stitchflow builds and maintains end-to-end IT automation across your SaaS stack, including apps without APIs. Built for exactly how your company works, with human approvals where they matter.

Every app coverage, including apps without APIs
60+ app integrations plus browser automation for apps without APIs
IT graph reconciliation across apps and your IdP
Less than a week to launch, maintained as APIs and admin consoles change
SOC 2 Type II. ~2 hours of your team's time

UpdatedMar 11, 2026

* Details sourced from official product documentation and admin references.

Keep exploring

Related apps

Abnormal Security logo

Abnormal Security

API Only
AutomationAPI only
Last updatedMar 2026

Abnormal Security is an enterprise email security platform focused on detecting and investigating threats such as phishing, account takeover (ATO), and vendor email compromise. It does not support SCIM provisioning, which means every app in your stack

ActiveCampaign logo

ActiveCampaign

API Only
AutomationAPI only
Last updatedFeb 2026

ActiveCampaign uses a group-based permission model: every user belongs to exactly one group, and all feature-area access (Contacts, Campaigns, Automations, Deals, Reports, Templates) is configured at the group level, not per individual. The default Adm

ADP logo

ADP

API Only
AutomationAPI only
Last updatedFeb 2026

ADP Workforce Now is a mid-market to enterprise HCM platform that serves as the HR source of record for employee data — payroll, benefits, time, and talent. User access is governed by a hybrid permission model: predefined security roles (Security Maste