SK Billing · Developers

Same rails as the whole suite.

Bearer keys, prefixed ULIDs, cursor pagination, idempotency on every mutation, signed webhooks. Learn it once for SK Billing; it holds across all of Softknack.

⚠ In development. These endpoint shapes reflect the designed contract and are being reconciled against the implementation before docs go live.
01

How it fits together

Invoices reference CRM contacts and Catalog items by ID; payments post to the ledger atomically. Bearer keys, prefixed ULIDs, idempotency on every mutation, signed webhooks.

fig · the shape of itCRM contactPriya R. · GSTINCatalog itemsAC · ₹1,499tax rulesGST 18%Invoice#SK-2048sentreferences, not copies — change a price once, correct everywhere
02

Your first invoice in three steps

Get a test key, make one authenticated call, and listen for the webhook. The same three moves work for every endpoint in the suite.

1

Get a test key

Test and live keys are separate environments. Build against sk_test_ without touching a real customer.

2

Create a invoice

One authenticated POST with an idempotency key. Same key + same body always returns the same result.

3

Receive the webhook

A signed invoice.created event hits your endpoint — verify the HMAC, act on it, return 200.

Terminal
curl -X POST https://api.softknack.com/billing/v1/invoices \
  -H "Authorization: Bearer sk_live_..." \
  -H "Idempotency-Key: 9f2c-4d1a-...-e7b3" \
  -H "Content-Type: application/json" \
  -d '{
    "contact_id": "ctc_01J9X...",
    "items": [{ "catalog_item_id": "itm_01J9X...", "qty": 1 }],
    "due_in_days": 7
  }'
03

Webhooks you can trust

Signed with HMAC-SHA256, delivered at-least-once, retried on a fixed schedule, and replayable from a dead-letter queue. You will never miss an event because a deploy was mid-flight.

EventWhen it fires
invoice.createdDrafted — from an agent flow, the API, or by hand.
invoice.sentDelivered with its payment link; reminder sequence armed.
payment.recordedRazorpay webhook or manual entry — posted to the ledger atomically.
invoice.overdueThe chase begins via SK Notifications.
invoice.paidSettled in full; ledger balanced.
credit_note.issuedA first-class reversing posting.
retry schedule
1s4s16s1m5m30m2hdead-letter
04

Guarantees, not vibes

The platform conventions every SK product obeys — learn them once, rely on them everywhere.

Idempotency, 24h

Every mutation takes an Idempotency-Key. Same key + body returns the original result; a conflicting body gets 409.

Prefixed ULIDs

Sortable, debuggable IDs like inv_01J9X... — you can read the type and the time right off the wire.

Cursor pagination

Stable cursors that never skip or repeat a row when data changes mid-list. No page-offset drift.

Row-level tenancy

Isolation enforced in the database. 404-over-403, so the existence of another tenant's record never leaks.

Signed webhooks

HMAC-SHA256 on every delivery, with the full retry schedule and dead-letter replay above.

Spec drift-checked

The OpenAPI spec is generated from the code's validators and checked in CI — the docs can't lie.

05

Bring your own agent

Drive billing from your own systems: create invoices over REST, subscribe to payment events, and let SK Notifications handle the chase. Or expose invoicing to your own AI agents over MCP with scoped permissions — the same tools SUKI uses to bill from a call.

fig · MCP, scopedcatalogheadlessAPI · webhook · MCPservedyour agentsbuild on your catalog instead of being held by it
06

Just want a payment link?

Generate a hosted payment link for any amount over the API, drop it in a message, and collect via Razorpay — the payment still posts to the ledger and fires payment.recorded.

The docs go deeper.

Auth, errors, pagination, every endpoint and schema — written once for the platform, shared by every product.

docs.softknack.com/billing  See pricing →