Prefer to hand this to a coding agent? Your program’s Tracking step and Settings → Store generate an Install Kit from this same contract. Both paths produce the same diagnostics and pass the same fixtures; neither generates a standalone partner portal, ledger or payout service.
1. Configure the workspace endpoint
The route is POST /api/ingest/<tenant-id>/generic. Copy your actual endpoint from workspace settings. Create the signing secret in your own secure environment and enter it through the secure integration settings. Never expose it in browser code.
2. Send a stable event
Use Content-Type: application/json. Amounts use integer minor units. Preserve the event ID and exact signed body on retries. Use one stable transaction ID for the underlying purchase across its payment and refund messages; each distinct message has its own stable event ID.
{
"schema_version": 2,
"environment": "live",
"event_id": "your-stable-payment-message-id",
"transaction_id": "your-stable-purchase-id",
"type": "conversion",
"amount_cents": 10000,
"eligible_amount_cents": 9000,
"currency": "USD",
"customer_ref": "your-stable-customer-id",
"philos_ref": "captured-referral-uuid",
"occurred_at": "2026-09-17T12:00:00Z"
}The first conversion needs a captured philos_ref and stable customer_ref. A later eligible renewal joins the existing qualified customer reference. Code attribution requires an explicitly enabled program policy. Conflicts and self-referrals require review; a code alone is not proof of an eligible sale.
A Philos-minted protocol token may instead be sent as token (≤200 chars). Only its SHA-256 digest is stored; the token is consumed exactly once on a valid credit, takes precedence over a code, and any conflict with another identifier is held for review — never auto-credited.
For new programs, eligible_amount_cents is collected product revenue after customer discounts, excluding tax, shipping and ineligible products. Supply an explicit allocation; Philos does not infer it from the total. Processor fees are not deducted from this basis. Existing qualifications keep their saved calculation and terms.
3. Sign the exact body
Calculate the hexadecimal HMAC-SHA256 digest of the exact raw JSON body using the configured webhook_hmac secret. Send it in X-Philos-Signature. Re-serializing or altering whitespace after signing changes the signature. HTTPS protects transport; the signature authenticates the delivered content.
4. Reference the original purchase for a refund
{
"schema_version": 2,
"environment": "live",
"event_id": "your-stable-refund-message-id",
"transaction_id": "your-stable-purchase-id",
"refund_id": "your-stable-refund-id",
"type": "refund",
"amount_cents": 2500,
"eligible_amount_cents": 2250,
"currency": "USD",
"occurred_at": "2026-09-17T13:00:00Z"
}The adjustment must inherit the original referral, currency, and accepted terms. Keep each refund identifier stable. These amounts describe this individual refund, not a cumulative total. Refunds delivered before the purchase remain in review until reconciliation. Missing eligible allocation on a mixed purchase requires evidence and review; Philos does not invent a proportional split.
5. Prove an isolated installation
Select Signed events in your program’s Tracking step. Save a separate webhook_hmac_test key in Store settings under Isolated setup tests, then create a test. Send its exact reference and displayed amount to /api/ingest-test/<tenant-id>/generic with test: true, schema_version: 2, the displayed eligible_amount_cents, a stable event ID, a fictional customer and a fresh occurred_at within five minutes. Sign the exact body with the test key. The receipt compares the expected commission with an isolated calculation; it never writes to a partner ledger.
Verify your live signing configuration separately: send type: philos.configuration_check, environment: live_configuration, the test UUID as check_id and a fresh occurred_at to /api/ingest-test/<tenant-id>/generic-configuration, signed with the live key. This non-transactional check proves configuration delivery, not a live purchase. The live and test keys must differ. Live ingestion rejects explicit test and configuration-check traffic.
The tracking console provides complete request examples and receipt status. Evidence expires after 24 hours and is bound to the current offer and signing configuration. Generic events remain merchant-signed evidence; Philos does not independently verify the underlying sale with your payment provider.
6. Verify outcomes, not just HTTP success
| Outcome | Next step |
|---|---|
| 200 with disposition | Inspect whether the event counted, was duplicate, or needs an attribution/eligibility fix. HTTP success is not always an earning. |
| 400 | Check the body and required fields. Do not reuse an accepted event ID with a changed payload; inspect the receipt and correction workflow first. |
| 401 | Check endpoint and signature configuration. The public response intentionally does not expose workspace secrets or existence. |
| 503 | Keep the original event in your delivery queue and retry with bounded backoff after the service recovers. |
Release checks: eligible first conversion, renewal, duplicate replay, invalid signature, unknown referral, wrong currency, partial refund, duplicate refund, and out-of-order refund. Reconcile each ledger result before using real events.
Contract basis: the version 2 canonical signed-event adapter. Legacy version 1 records retain their original terms and basis. Your installed database adapter and workspace test results determine readiness. A signature authenticates your source; it does not independently establish incremental sales impact.