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.