Powered by PviumInstall GitHub App
Pvium logo

Pvium GitHub App

Reward GitHub contributors with Pvium payment links.

Turn merged pull requests into payable rewards. Maintainers label bounty issues, contributors close them with PRs, and Pvium handles the invite, payment link, funded webhook, and paid status updates.

GitHub webhook/api/github/webhook
Pvium webhook/api/pvium/webhook
OAuth callback/api/pvium/oauth/callback

Flow

  1. A repository owner installs the GitHub App.
  2. A maintainer labels an issue with a Pvium bounty label, for example pvium:20USDC or pvium:10.
  3. When a pull request is merged into a configured reward target branch and closes that issue, the app checks the PR author.
  4. If the PR author is already linked to a Pvium account, the app creates a Pvium payment link and comments a Pay reward link on the PR.
  5. If the PR author is not linked, the app generates a signed Pvium OAuth invite for type: github and comments the invite link on the PR.
  6. Once the user accepts the invite and connects the matching GitHub account in Pvium, the Pvium webhook creates the payment link and comments the Pay reward link on the PR.
  7. When Pvium sends a paid or funded webhook, the app marks the reward and bounty as PAID.

Local Setup

The reward automation uses the local Pvium SDK at /Users/Projects/Javascript/paytrack/sdks/node. The package points @pvium/sdk at file:../sdks/node, so rebuild the SDK after changing it.

cd /Users/Projects/Javascript/paytrack/sdks/node
npm install
npm run build

cd /Users/Projects/Javascript/paytrack/github-app
npm install
cp .env.example .env
npm run prisma:generate
npm run prisma:migrate
npm run dev

Environment

Required values are documented in .env.example:

DATABASE_URL="postgresql://postgres:postgres@localhost:5432/pvium_github_app"

GITHUB_APP_ID=""
GITHUB_APP_PRIVATE_KEY=""
GITHUB_WEBHOOK_SECRET=""
GITHUB_REWARD_TARGET_BRANCHES="main,master"
PVIUM_BOUNTY_LABEL_PREFIX="pvium:"

PVIUM_ENVIRONMENT="sandbox"
PVIUM_API_BASE_URL=""
PVIUM_CONSENT_HOST=""
PVIUM_SDK_LOG_REQUESTS="false"
PVIUM_API_KEY=""
PVIUM_CLIENT_ID=""
PVIUM_WEBHOOK_SECRET=""
PVIUM_INVITE_SIGNER_PRIVATE_KEY=""
PVIUM_OAUTH_REDIRECT_URI="http://localhost:3000/api/pvium/oauth/callback"
PVIUM_REWARD_PAYMENT_MODEL="instant-batch"
PVIUM_REWARD_PAYMENT_SIGNER_PRIVATE_KEY=""
PVIUM_REWARD_PAYMENT_CHAIN="base"
PVIUM_REWARD_PAYMENT_CHAIN_ID="8453"
PVIUM_REWARD_PAYMENT_CURRENCY="USDC"
PVIUM_REWARD_PAYMENT_TOKEN_ADDRESS=""
PVIUM_REWARD_PAYMENT_TOKEN_DECIMALS="6"
PVIUM_REWARD_PLATFORM_FEE_WALLET=""
PVIUM_REWARD_PLATFORM_FEE_BASIS_POINTS="0"
PVIUM_REWARD_MAX_FEE_AMOUNT="0"
PVIUM_INVOICE_REDIRECT_URI="http://localhost:3000/api/pvium/oauth/callback"

APP_BASE_URL="http://localhost:3000"

GitHub App

Generate GITHUB_APP_PRIVATE_KEY from the GitHub App settings page under Private keys, then copy the full PEM contents into the environment with line breaks replaced by \n.

Configure the webhook URL as https://<your-host>/api/github/webhook.

Repository Permissions

  • Issues: read and write
  • Pull requests: read and write
  • Metadata: read-only

Subscribed Events

  • issues
  • pull_request

Pvium Configuration

Configure the Pvium webhook URL as https://<your-host>/api/pvium/webhook. Set PVIUM_WEBHOOK_SECRET to the same secret configured on the Pvium client app.

When PVIUM_REWARD_PLATFORM_FEE_WALLET is set and the fee basis points are greater than zero, instant batches include the platform fee as the first payee with memo platform fee. The contributor reward amount is not reduced by the fee.

Handled Events

GitHub

  • issues.labeled
  • pull_request.closed

Pvium

  • oauth.invite.accepted
  • invoice.paid
  • invoice.payment_completed
  • invoice.payment.succeeded
  • payment.attached
  • batch.funded
  • batch.payment_completed
  • batch.payment.succeeded

Usage

  1. Install the GitHub App on a repository.
  2. Add a bounty label to an issue, such as pvium:20USDC or pvium:20. If PVIUM_BOUNTY_LABEL_PREFIX is changed, use that prefix instead.
  3. Merge a PR into a configured reward target branch with a closing reference like Closes #123.
  4. The app comments on the merged PR.
  5. If the contributor needs to link Pvium, they use the invite link in the comment.
  6. Pvium redirects back to /api/pvium/oauth/callback with an OAuth code.
  7. The app exchanges the code through the local Pvium SDK, verifies the accepted GitHub handle, saves the OAuth token set, creates the payment link, and comments a Pay reward link.
  8. The maintainer clicks Pay reward and completes payment in Pvium.

The app stores Pvium OAuth access and refresh tokens on the GitHub user link so future merged PRs for the same contributor can create rewards without asking the contributor to authorize again. Treat these OAuth tokens as secrets; production deployments should encrypt them at rest and restrict database access.