Corpland Revenue

Customers

Your app's users, keyed by your own id, with everything Revenue knows about them.

customers.get_or_create

Call it whenever you see a user, typically on sign in. The first call creates the customer and attaches every free default plan. Later calls update name, email and fingerprint if they changed.

Body
{
  "customer_id": "user_123",
  "email": "ama@example.com",
  "name": "Ama Mensah",
  "currency": "GHS",
  "fingerprint": "device_8f2c",
  "metadata": { "team": "growth" },
  "expand": ["invoices", "payment_methods"]
}

Only customer_id is required. An email is needed before a paid plan can be attached, because Paystack asks for one. fingerprint (a device or browser id) limits free trials to one per device. currency is set on create only; once a customer has paid, they stay in that currency.

Answer
{
  "id": "user_123",
  "name": "Ama Mensah",
  "email": "ama@example.com",
  "currency": "GHS",
  "env": "test",
  "credits": [],
  "subscriptions": [
    {
      "plan_id": "pro",
      "status": "active",
      "amount": 2000,
      "currency": "USD",
      "interval": "month",
      "quantities": [],
      "current_period_end": "2026-11-11T13:00:00.000Z",
      "cancel_at_period_end": false,
      "scheduled_for": null
    }
  ],
  "purchases": [],
  "balances": {
    "messages": {
      "feature_id": "messages",
      "type": "metered",
      "granted": 150,
      "used": 30,
      "remaining": 120,
      "overage_allowed": false,
      "next_reset_at": "2026-11-11T13:00:00.000Z",
      "interval": "month",
      "breakdown": [{ "id": "plan:pro", "plan_id": "pro", "amount": 100, "interval": "month", "expires_at": null }],
      "rollovers": [{ "amount": 50, "expires_at": "2026-12-11T13:00:00.000Z" }],
      "usage_limits": [{ "limit": 200, "interval": "day", "usage": 37, "source": "plan" }]
    }
  },
  "flags": { "sso": { "feature_id": "sso", "plan_id": "pro", "expires_at": null } },
  "billing_controls": { "usage_limits": [{ "feature_id": "messages", "limit": 200, "interval": "day", "source": "plan" }], "spend_limits": [], "overage_allowed": [], "usage_alerts": [], "auto_topups": [] }
}
  • subscriptions are recurring plans and add ons, including a scheduled one waiting for renewal. purchases are one off plans. plans is kept for older integrations and lists both.
  • balances covers metered features and credit systems. On and off features are in flags, so customer.flags.sso is all you need to show a button.
  • billing_controls are the effective limits, with source telling you whether each came from the plan or was set on the customer.
  • credits is money on account from plan changes; it pays the next invoices first.
  • expand adds invoices, entities, payment_methods, rewards and referrals.

customers.get

{ "customer_id": "user_123", "expand"?: [...] } returns the same shape. 404 customer_not_found if you never created them.

customers.update

{ "customer_id": "user_123", "name"?, "email"?, "currency"?, "fingerprint"?, "metadata"?, "billing_controls"? }

billing_controls is merged by feature into what the customer already has. Send "replace_billing_controls": true to replace them all. See Limits and alerts.

customers.delete

{ "customer_id": "user_123" } ends every plan now without a refund and hides the customer. Calling customers.get_or_create with the same id brings them back with default plans.

customers.list

{ "search"?: "ama", "plan_id"?: "pro", "status"?: "past_due", "limit"?: 50, "start_cursor"?: "..." } returns { "list": [...], "next_cursor": "..." | null }.

plans.list with a customer

{ "customer_id": "user_123", "entity_id"?: "ws_1" } adds customer_eligibility to every plan, which is what a pricing table needs:

{ "attach_action": "upgrade", "status": null, "canceling": false, "trial_available": true }

attach_action is activate, upgrade, downgrade, purchase or none (their current plan).

On this page