Loading Ascend…

Ascend API

Programmatically create customers, products, and invoices, and receive webhook events when invoices are sent or paid.

Authentication

All requests need a Bearer token. Create one in Settings → Developer API.

Authorization: Bearer ak_live_xxxxxxxxxxxxxxxx

Each key is scoped to one business. To work across businesses, mint a key per business.

Base URL

https://ascendinvoice.com/api/public/v1

Customers

POST /customers
curl https://ascendinvoice.com/api/public/v1/customers \
  -H "Authorization: Bearer ak_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme Inc",
    "email": "billing@acme.com",
    "country": "IN"
  }'
GET /customers · GET /customers/:id
curl https://ascendinvoice.com/api/public/v1/customers?limit=50 \
  -H "Authorization: Bearer ak_live_xxx"

Products

POST /products
curl https://ascendinvoice.com/api/public/v1/products \
  -H "Authorization: Bearer ak_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Consulting hour",
    "unit_price": 5000,
    "default_tax_rate": 18,
    "currency": "INR",
    "type": "service"
  }'

Invoices

POST /invoices
curl https://ascendinvoice.com/api/public/v1/invoices \
  -H "Authorization: Bearer ak_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "customer_id": "uuid-from-customers",
    "currency": "INR",
    "due_date": "2026-07-15",
    "status": "sent",
    "items": [
      { "description": "Consulting", "quantity": 4, "unit_price": 5000, "tax_rate": 18 }
    ]
  }'

The invoice number is assigned automatically using your business's prefix and counter. Totals are computed from items.

GET /invoices · GET /invoices/:id
curl https://ascendinvoice.com/api/public/v1/invoices?status=sent&limit=20 \
  -H "Authorization: Bearer ak_live_xxx"

Webhooks

Add an endpoint URL in Settings → Developer API. We'll POST JSON events with a signature header.

X-Ascend-Signature: t=1719500000,v1=<hex hmac>
X-Ascend-Event: invoice.paid
Content-Type: application/json

{
  "id": "evt_…",
  "type": "invoice.paid",
  "created": 1719500000,
  "data": { "invoice": { ... } }
}

Verify the signature with your endpoint's signing secret:

const [tPart, sigPart] = header.split(",");
const ts = tPart.split("=")[1];
const sig = sigPart.split("=")[1];
const expected = crypto
  .createHmac("sha256", SIGNING_SECRET)
  .update(`${ts}.${rawBody}`)
  .digest("hex");
// timing-safe compare(expected, sig)

Available events: invoice.created, invoice.sent, invoice.paid. Use * to receive all.

Errors

{ "error": { "code": "validation_error", "message": "..." } }

HTTP status codes: 200/201 success, 401 bad auth, 404 not found, 422 validation, 500 server error.