0G Pay
Docs / Partner Regrant · Operators

Partner Regrant API — for operators

For 0G operators: the two routes a partner can take, how to onboard one, and where this documentation comes from. The contract partners integrate against is on the partner tab.

For partnersFor operators
EN中文

1. Two routes — decide which one first

There are two entirely different ways a partner can distribute credit. They differ in identity model, entry point and how involved we are, and choosing between them is most of the product decision.

A. Through the PortalB. Direct API
How the partner actsSigns in to the Portal and uses the “Share credit” formTheir own backend calls our endpoint with a signature
Recipients per callOneUp to 500 rows
IdentityPrivy login yields a DID; seated by DIDSigns with their own wallet; seated by address, never signs in
Do they need engineers?NoYes
What our frontend must buildAlready builtNothing for the call itself; the Partner kit on the campaign page hands over what they need
StatusShippedBackend ready; frontend not involved
Route B needs nothing from our roadmap. The partner calls POST /v1/regrants directly; we neither proxy it nor sit in the path. Onboarding a partner is one admin seating operation — no config change, no release.
The click-by-click steps for route A are in the handbook, section 5.

2. Onboarding a partner

1
Get their wallet address
One they already own and can sign with. The private key stays with them; we only ever see the address.
2
An admin seats that address as a partner
POST /admin/roles with subject set to the wallet address and role set to partner. Seating is the allowlist: unseat and it stops working immediately, with no key rotation on their side.
3
BD grants credit to that same address
The lot_id produced by that grant is the source_lot_id they will pass when they redistribute. The grant form shows it once issued, and the campaign's Grants issued table keeps it in the Lot column.
4
Send them the Partner kit
On the campaign page, the Partner kit button on that wallet's row assembles everything they need — API host, source_lot_id, the lot's amount, expiry and scope, their external_ref prefix — and checks the seat. Copy it and send it to them directly: it names the unpublished host.
Seating is not account creation. Seating only records what a subject is allowed to do. A partner’s wallet has to have been granted credit before there is anything to redistribute — seated but with no account gets a 403.

Note that a partner’s subject is a wallet address, not a DID. The other three roles (distributor / finance_approver / admin) go through the Portal and are seated by the DID their Privy login yields; a partner may never sign in at all, and the wallet they sign with is their identity.

After they go live

A row sent to the wrong address can only be revoked by us. A finance approver (or the distributor who funds the campaign) revokes that one lot from the campaign page. Only what the recipient has not spent comes back, along with anything they re-granted onward, and it returns to the campaign’s budget, not the partner’s lot, so grant it to the partner again if they should have it.

Partners are not rate-limited. 500 rows a call, each of which may create an account; a retry-on-error loop on their side is not stopped here. Ask them to back off on errors.

3. Provenance

This page describes the Pay backend’s API, which does not live in this repository and therefore does not update when this repository’s code changes. Check it against the source of truth before integrating.
Source of truth0gfoundation/0g-pay-v2 → backend/deploy/PARTNER-REDISTRIBUTION.md (partner-facing) and FRONTEND-INTEGRATION.md §3.5 / §“Re-granting at scale”
Written fromcommit 51706ce (2026-09-18)
This page written2026-09-21; signing string and failure codes revised 2026-09-24 from the Pay team; partner kit, complete example and per-lot revoke added 2026-10-01 (revoke from backend/internal/ops/reclaim_lot.go); Privy key export added 2026-10-03
What this repo does hereNothing — the Portal does not call /v1/regrants. “Share credit” goes through /v1/grants with source_lot_id.
← Back to Docs