Other SoftKnack products and verticals build on SK Franchise. It is versioned at /v1, publishes an OpenAPI contract generated from its own code, accepts service tokens, and emits domain events other products can subscribe to.
Identity comes from SoftKnack sign-in — SK Franchise has no login of its own. Invoices are raised in SK Billing, events go out through an outbox after each change commits, and every table is isolated per organisation in the database.
Sign in, read the network, then make a change with an idempotency key.
Use the SoftKnack session cookie, or a bearer token — a user token, or a service token delegated through the platform backbone.
GET /v1/network/units lists the outlets your role may see. A franchisee only ever sees their own.
Every POST and PATCH needs an Idempotency-Key. Without one the API refuses the write; with the same key it returns the first result.
curl -X POST https://franchise.dev.api.softknack.com/v1/settlements/runs \ -H "Authorization: Bearer <platform token>" \ -H "Idempotency-Key: 9f2c-4d1a-...-e7b3" \ -H "Content-Type: application/json" \ -d '{ "period": "2026-09" }'
Illustrative — the exact request and response shapes are in the published OpenAPI contract.
Events are written to an outbox in the same transaction as the change, and sent after it commits — so an event is never sent for a change that rolled back, and never lost for one that didn't. Failed deliveries show up in /v1/outbox and can be retried.
| Event | When it fires |
|---|---|
franchise.unit.created | A new outlet is added to the network. |
franchise.unit.status_changed | An outlet moves stage or status. |
franchise.unit.went_live | Onboarding is complete and the outlet is open. |
franchise.settlement.approved | A settlement has all the approvals it needs. |
franchise.settlement.posted | The settlement is invoiced in SK Billing. |
franchise.payment.recorded | A payment is recorded against a settlement. |
franchise.fund.request_decided | A Marketing Fund request is approved or rejected. |
franchise.agreement.renewal_due | An agreement is nearing its renewal date. |
The rules are enforced in the database, not just in the code that calls it.
Every POST and PATCH takes an Idempotency-Key. A retried request returns the original result instead of doing the work twice.
Every table is isolated per organisation with forced row-level security. One org can never read another's outlets.
Amounts are decimal strings with their currency, never floating-point numbers. The client never computes money.
Royalty rules used by a settlement, and posted settlements themselves, can't be changed — database triggers refuse it.
Approval quorums and document confirmations are constraints, so a second click by the same person is refused.
The OpenAPI contract is generated from the API's own validators, so the documentation matches what the API accepts.
Every endpoint, schema and error, from the published contract.
docs.softknack.com/franchise See pricing →