Skip to main content

Customers

A customer is someone you bill. Usually that’s one of YOUR customers — the person, company, or account that’s using your product and that you want to charge or track usage for. When you create a customer in MarginFront, you’re saying “here’s a person I want to track, here’s how to reach them, here’s the ID I use for them in my own system.” Once a customer exists in MarginFront, you can:
  • Log usage events against them (for usage-based billing)
  • Subscribe them to a pricing plan
  • Generate invoices for them
  • Read their billing history

Create a customer

In plain English: Tell MarginFront about a new customer of yours. Do this right after your own app creates a new user or account. Method & URL:
POST /v1/customers
Authentication: Secret API key in the x-api-key header. See Authentication. Publishable keys are rejected on writes with 403. Required fields:
  • name (string) — The customer’s company name or full name. Shows up on invoices, so make it readable.
Optional but highly recommended:
  • externalId (string) — Your internal ID for this customer. Pick something you already use in your own system. This is how you’ll reference the customer in other API calls (like usage events) without having to remember MarginFront’s internal UUID.
  • email (string) — The billing email. Where invoices get sent.
Other optional fields:
  • phone (string) — Customer phone number
  • addressLine1, addressLine2, city, state, zipCode, country (string) — Mailing address, used on invoices
  • timezone (string, default "UTC") — Customer’s timezone, used for billing period calculations
  • status ("active" | "inactive" | "suspended", default "active")
  • billingContactName (string) — If the billing contact is different from the main contact
  • billingContactEmail (string) — Same, for email
  • netTerms (number, default 30) — Payment terms in days
  • invoiceEmailRecipients (array of strings) — Additional email addresses to CC on invoices
  • metadata (object) — Any custom key/value pairs you want to attach. MarginFront stores and returns them but doesn’t interpret them.
Example curl call:
curl -X POST https://api.marginfront.com/v1/customers \
  -H "x-api-key: $MF_API_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme Inc",
    "externalId": "acme-001",
    "email": "billing@acme.com"
  }'
What you get back (201 Created):
{
  "id": "5e7f8a3d-1234-5678-9abc-def012345678",
  "name": "Acme Inc",
  "externalId": "acme-001",
  "email": "billing@acme.com",
  "status": "active",
  "createdAt": "2026-04-10T14:30:00.000Z"
}
Common errors:
  • 400 Bad Request — You’re missing the name field, or one of your fields has the wrong type (e.g., an email that isn’t a valid email). The response body will tell you exactly which field is wrong.
  • 409 Conflict — A customer with that externalId already exists in this org. Either pick a different externalId, or update the existing customer instead.
  • 401 Unauthorized — Your API key is missing or wrong.
  • 403 Forbidden — You used a publishable key (mf_pk_*) on a write. Use a secret key (mf_sk_*) instead.
When to call this: Right when you create a new customer in your own system, BEFORE you try to log any usage events for them.
Heads up: If you log a usage event for an externalId that MarginFront has never seen before, MarginFront will auto-create a minimal customer record for you. This is convenient but means you miss the chance to set the name/email/etc. Creating the customer explicitly first gives you much richer data.

Read a customer

Method & URL:
GET /v1/customers/{customerId}
What it returns: The full customer object, same shape as the create response. Example:
curl https://api.marginfront.com/v1/customers/5e7f8a3d-... \
  -H "x-api-key: $MF_API_SECRET_KEY"
Common errors:
  • 404 Not Found — No customer with that ID exists in this org.

List customers

Method & URL:
GET /v1/customers
What it returns: An array of customers, with optional pagination info. Example:
curl https://api.marginfront.com/v1/customers \
  -H "x-api-key: $MF_API_SECRET_KEY"
When to use it: Usually for syncing — pulling a fresh list of what’s in MarginFront to compare against your own system. Not ideal for UI (the list can get long).

Update a customer

Method & URL:
PATCH /v1/customers/{customerId}
Fields: Any of the fields you could send on create. All are optional on update — only send what you want to change. Example:
curl -X PATCH https://api.marginfront.com/v1/customers/5e7f8a3d-... \
  -H "x-api-key: $MF_API_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"phone": "+1-555-0100"}'
What you get back (200 OK): The updated customer object. Common errors:
  • 404 Not Found — Customer doesn’t exist.
  • 409 Conflict — You tried to change externalId to one that another customer in this org already has.
  • 403 Forbidden — You used a publishable key on a write.

Delete a customer

Method & URL:
DELETE /v1/customers/{customerId}
What it does: Soft-deletes the customer. Any subscriptions attached to this customer should be canceled or deleted first — if they aren’t, the delete may fail with a foreign-key error. Example:
curl -X DELETE https://api.marginfront.com/v1/customers/5e7f8a3d-... \
  -H "x-api-key: $MF_API_SECRET_KEY"
Common errors:
  • 404 Not Found — Customer doesn’t exist.
  • 409 Conflict — Customer still has active subscriptions. Cancel or delete those first.
  • 403 Forbidden — You used a publishable key on a write.

Using the Node SDK

If you’re using the published @marginfront/sdk npm package, you never type these URLs yourself. Instead:
import { MarginFrontClient } from "@marginfront/sdk";

const mf = new MarginFrontClient(process.env.MF_API_SECRET_KEY);

// Create
const customer = await mf.customers.create({
  name: "Acme Inc",
  externalId: "acme-001",
  email: "billing@acme.com",
});

// Read
const existing = await mf.customers.get("acme-001");

// Update
await mf.customers.update("acme-001", { phone: "+1-555-0100" });

// List
const { data } = await mf.customers.list();

// Delete
await mf.customers.delete("acme-001");
The SDK wraps the exact HTTP endpoints described above. If something works via curl, it works via the SDK — they’re the same thing.