Skip to content

Customers

Customers represent the tenant, account, workspace, or end user whose usage should be tracked.

When To Use This

Create a customer after creating a project. Runtime provider calls should resolve to a customer either through a customer key, an internal Spendware customer ID, or your own external customer ID.

Example

curl "$SPENDWARE_BASE_URL/api/v1/customers/" \
  -H "Authorization: Bearer $SPENDWARE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"project_id":"PROJECT_ID","title":"Customer A","currency":"USD","external_id":"customer-a"}'
from spendware_provider_sdk.management import EndCustomerCreate, SpendwareManagementClient

client = SpendwareManagementClient(base_url="SPENDWARE_BASE_URL", api_key="SPENDWARE_API_KEY")
customer = client.endcustomers.create(
    EndCustomerCreate(project_id="PROJECT_ID", title="Customer A", external_id="customer-a")
)
client.close()
import { SpendwareManagementClient } from "@spendware/provider-adapters-sdk/management";

const client = new SpendwareManagementClient({ baseUrl: "SPENDWARE_BASE_URL", apiKey: "SPENDWARE_API_KEY" });
const customer = await client.customers.create({
  project_id: "PROJECT_ID",
  title: "Customer A",
  external_id: "customer-a",
});

Lookup By External ID

Use external ID lookup when your application has a stable customer identifier:

customer = client.endcustomers.get_by_external_id("customer-a", project_id="PROJECT_ID")
const customer = await client.customers.getByExternalId("customer-a", { projectId: "PROJECT_ID" });

Customer Credits

Customer credit is an immutable grant (CustomerCreditGrant) that offsets eligible customer spend as usage is accepted. A usage allocation (CustomerCreditAllocation) consumes part of a grant for one accepted UsageEventLedger record. It is not a mutable customer balance or a fixed invoice discount. The credit summary exposes both gross accrued cost and the credit-adjusted net accrued cost.

Credit reads require viewer access. Creating grants and reversing unused value require editor access. Credit currency must match the customer currency, and an expiry date is inclusive through that UTC date. Omit expires_on for a grant that does not expire.

Allocation consumption priority: earliest expiry first, then earliest created. Grants without expiry are consumed only after all expiring grants are exhausted. Historical imports, replays, and backfills do not allocate credit.

curl "$SPENDWARE_BASE_URL/api/v1/customers/CUSTOMER_ID/credits" \
  -H "Authorization: Bearer $SPENDWARE_API_KEY"

curl -X POST "$SPENDWARE_BASE_URL/api/v1/customers/CUSTOMER_ID/credits" \
  -H "Authorization: Bearer $SPENDWARE_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: customer-credit-grant-REQUEST_ID" \
  -d '{"currency":"USD","amount":25.00,"expires_on":"2026-12-31","reason":"Service recovery"}'
from spendware_provider_sdk.management import EndCustomerCreditGrantCreate

grant = client.endcustomer_credits.grant(
    "CUSTOMER_ID",
    EndCustomerCreditGrantCreate(
        currency="USD",
        amount=25.00,
        reason="Service recovery",
    ),
    idempotency_key="customer-credit-grant-REQUEST_ID",
)
balance = client.endcustomer_credits.list("CUSTOMER_ID").summary
const grant = await client.customerCredits.grant(
  "CUSTOMER_ID",
  { currency: "USD", amount: 25.0, reason: "Service recovery" },
  { idempotencyKey: "customer-credit-grant-REQUEST_ID" },
);
const balance = (await client.customerCredits.list("CUSTOMER_ID")).summary;

Reverse unused credit from a specific grant with POST /api/v1/customers/{id}/credits/{grant_id}/reversals. Reversals are immutable, require a reason, and cannot reclaim credit already consumed by usage.

Common Errors

  • Customer creation requires a valid project ID.
  • External IDs should be URL-safe strings and should remain stable.
  • Read-side usage totals may be scaled if you pass presentation unit options.