Backups and portability
Data portability is an architectural commitment, not a checkbox. Your partners, programs, attribution and ledger export in three formats, and a hosted export restores into a self-hosted instance.
Exporting
From the admin dashboard, Admin → Export / import:
- Full bundle — every exportable table in one file, as JSON (
GET /export.json) or as a SQL dump (GET /export.sql). These are the two restore formats. - Per table — any one table as JSON, CSV or SQL (
GET /export/<Table>.<format>). CSV is for spreadsheets and one-off analysis, not for restoring.
Exports take an admin key. The JSON bundle looks like this:
{ "exportedAt": "2026-10-17T12:00:00.000Z", "schemaVersion": 5, "tables": { "Partner": [ … ], "Program": [ … ], … }}Rows are the raw database rows, with no reshaping. Attribution and commissions are there as their own tables, and can also be re-derived from the raw clicks, identities and events.
What’s in the bundle
In restore order:
| Table | What it holds |
|---|---|
Partner | The roster, including each partner’s portalAccess |
Program | Programs and their commission rules, including value bands, performance tiers and renewalsStayWithPartner |
PartnerProgram | Which partners may promote which programs |
PartnerCommission | Per-partner commission terms (partner-wide or per program) |
PartnerNetworkConsent | Each partner’s own OpenPartner Network opt-in |
Coupon | Partner coupon codes |
Link | Share links |
Click | The raw click log |
Identity | Click → user stitches |
Event | Raw conversion events, refunds and chargebacks included |
Attribution | Derived attribution (re-derivable) |
Commission | The commission ledger, including replacements left by partial refunds |
Payout | The payout ledger |
PortalCustomDomain | White-label domain history (inert on self-host) |
CommissionAdjustment | Clawbacks and corrections, including refund clawbacks on paid commissions |
BrandAsset | Your marketing-asset library |
WebhookEndpoint | Your outbound webhook endpoints |
PartnerPostback | Each partner’s own tracker postback URLs |
ConversionPostbackToken | The conversion postback URL’s IP allowlist and rotation history |
Config | Your program settings, join-page policy and partner portal access default |
BrandAsset, WebhookEndpoint, PartnerPostback, ConversionPostbackToken and Config,
plus the Program.renewalsStayWithPartner and Partner.portalAccess columns, are new in
schema version 5 (October 2026).
Credentials are never exported
Anyone holding an export file must not be able to sign a webhook or record a conversion with it, so a bundle contains no credentials:
- Webhook signing secrets are left out. On restore each endpoint gets a fresh secret and
comes back paused, because its receiver doesn’t know the new secret yet.
POST /importreturns each new secret once. Give it to the receiver, then turn the endpoint back on. - The conversion postback token is left out. The restored token keeps its IP allowlist and history, but no postback URL works until you rotate it under Admin → Integrations and update the URL wherever it’s fired.
Partner postback URLs travel as the partner entered them. They hold no OpenPartner credential, but a partner’s tracker may put its own token in the URL, so treat an export file as you would the partner list itself.
Settings
Config carries only three keys:
| Key | What it holds |
|---|---|
program_settings | Program name, support email, router URL, whether partners see the Network |
partner_signup | Your join page: auto-approve, review, or closed |
partner_access | Whether partners added without an invite may sign in to the partner portal |
Mail settings and your Network connection hold encrypted credentials tied to the source deployment, so they stay out: set them up again on the destination.
Brand asset files
BrandAsset rows are exported, but image files aren’t: an image row carries its file’s
public URL, which keeps working while the source’s storage does. If you’re leaving an
instance for good, download the files first:
jq -r '.tables.BrandAsset[] | select(.url) | .url' openpartner-export.json | xargs -n 1 curl -fsSONot in the bundle
Sessions, sign-in links, API keys, admins and delivery logs are never exported. Your brand profile (name, logo, colours, default currency, payout settings), payout reversal records, hosted payout-funding records and the hosted billing ledger aren’t exported yet. Set up your brand profile on the destination.
Importing
JSON — POST /import
Self-host only. Restores a JSON bundle into the instance’s tenant:
curl -X POST "$API/import" \ -H "Authorization: Bearer $ADMIN_KEY" \ -H 'Content-Type: application/json' \ --data-binary @openpartner-export.jsonEvery row is rewritten to the importing tenant. Rows that already exist are skipped, so re-running an import is safe and a partial import can be resumed. The response reports rows inserted and skipped per table, plus the new webhook secrets.
SQL — psql
The dump restores into any instance. Pass the destination tenant’s id, not its slug:
psql "$DATABASE_URL" -v tenant_id=01J0000000DEFAULTTENANT0000 -f openpartner-export.sqlLeave out -v and it uses the default self-host tenant’s id. Needs psql 10 or newer and
Postgres 13 or newer. After a SQL restore, read the new webhook secrets from the
WebhookEndpoint table.
Older bundles
Bundles from schema versions 1 to 4 still import. They simply lack the tables and columns added later:
- A v4 or older bundle restores no settings, asset library, webhooks or partner postbacks. Configure those on the destination.
- Its programs restore with
renewalsStayWithPartneron, and its partners withportalAccesson, which is what they had when they were exported. Moving an in-app referral program? Turn portal access off for those partners after the import, and set the default under Admin → Settings → Partner portal access.
Why this matters
Most attribution platforms collapse raw events into a single attribution decision and store only that. When you export, you get a snapshot of decisions — not the data those decisions were made from. You can’t migrate, you can’t re-run, and you can’t audit.
OpenPartner stores the raw layers immutably and treats attribution as a query. Every export carries both the raw clicks, identities and events and the decisions made from them.