Quickstart

Workspace to first commission

Seven steps. Each one is a real capability call. Field names below are the ones the code accepts. A step marked as a human gate needs a person.

1. Create a workspace

A workspace is one isolated tenant. An operator creates it from the command line with a database role that is not the runtime role. The command prints the new workspace record and its first service key. The key appears once and never again.

operator shell
npm run workspace:create -- \
  --workspace acme \
  --name "Acme" \
  --key-label "acme-runtime"

2. Create a program

A program is one partner offering inside the workspace. It takes an id, a name and a config object.

api
POST /v1/invoke
Authorization: Bearer trk_...

{
  "capability": "ticket4:createProgram",
  "program": "partner-2027",
  "payload": {
    "id": "partner-2027",
    "name": "Acme partner program",
    "config": {}
  }
}

3. Draft and activate a rulebook

A rulebook version holds the commission terms of one program from a stated instant. An agent drafts it. A person activates it.

payload
{
  "capability": "ticket6:draftRulebookVersion",
  "program": "partner-2027",
  "payload": {
    "version": "v1",
    "effectiveFrom": "2027-01-01T00:00:00.000Z",
    "maturityDays": 30,
    "approvalMode": "manual",
    "recurringDays": "lifetime",
    "rounding": "half-up",
    "currency": "USD",
    "rules": [{ "id": "rate", "kind": "rate", "rateBps": 3000 }]
  }
}

The draft does nothing until a person activates that exact version. Activation is immutable, and the effective instant must be later than every payment the program has already ledgered.

Human gateticket6:activateRulebookVersion
payload
{
  "capability": "ticket6:activateRulebookVersion",
  "program": "partner-2027",
  "payload": {
    "version": "v1",
    "activatedAt": "2027-01-01T00:00:00.000Z"
  }
}

4. Invite a partner

An invitation creates a pending partner relationship bound to one workspace, one program and one creator record. The relationship id is derived from the program and the creator record.

payload
{
  "capability": "ticket4:invitePartner",
  "program": "partner-2027",
  "payload": {
    "programId": "partner-2027",
    "creatorRecordId": "creator-1",
    "partnerActorIdentity": "partner-1"
  }
}

Then call ticket4:completeOnboarding with the relationship id, and the contact and payout details you hold. The partner accepts the terms through ticket4:acceptStandardTerms, which is a human gate.

6. Take the first commission

The runtime polls Stripe events and ingests each collected payment. Parka resolves the partner from the subscription referral code, applies the rulebook and writes one commission entry. An event it cannot resolve is held, and nothing is posted.

  • ticket6:queryPendingAccruals lists what has accrued and not yet matured.
  • ticket6:readLedger returns the entries, the holds and the balance.
  • ticket7:explainEntries returns the payment and the terms behind each line.
Human gateticket6:approveCommission
payload
{
  "capability": "ticket6:approveCommission",
  "program": "partner-2027",
  "relationship": "relationship:partner-2027:creator-1",
  "payload": {
    "ledgerId": "commission:evt_1",
    "approvedAt": "2027-02-01T00:00:00.000Z"
  }
}

7. Pay and record the receipt

Parka never moves money. You pay the partner with your own rails. Then a person records the receipt, and the ledger shows the entry as paid.

Human gateticket7:recordPayoutReceipt
payload
{
  "capability": "ticket7:recordPayoutReceipt",
  "program": "partner-2027",
  "relationship": "relationship:partner-2027:creator-1",
  "payload": {
    "receiptId": "receipt-1",
    "commissionId": "commission:evt_1",
    "amountMinor": 3000,
    "currency": "USD",
    "externalReference": "bank-transfer-8841",
    "receivedAt": "2027-02-02T00:00:00.000Z",
    "operatorEvidence": "paid from the Acme account"
  }
}

Partner programs on Stripe, run by agents. People approve the money.

Get started