YeetCode
Setup

7. Connect Yoco to Convex

Configure Yoco for one-time access purchases from your Convex backend.

Yoco is a South African payment gateway. YeetCode uses it for one-time access purchases — customers buy a time-limited package (3 months, 6 months, or lifetime) and get access until it expires.

If you don't need ZAR payments or the access-package model, you can skip this step and use Polar only.

Prerequisites

  • A Yoco business account (South African business required)
  • Your Convex backend running (bun run dev from apps/convex-backend)

1. Get Your Yoco API Keys

  1. Log in to the Yoco Business Portal
  2. Navigate to DevelopersAPI Keys
  3. Copy your Secret Key (starts with sk_live_ or sk_test_)

2. Register the Webhook Endpoint

Yoco needs to send payment notifications to your Convex backend. Run the setup script:

npx convex run --no-push yoco/init:registerWebhookEndpoint

This will:

  • Connect to the Yoco API using your secret key
  • Register a webhook at https://your-convex-url.convex.site/webhook-events/yoco
  • Return the webhook secret for signature verification

If a webhook already exists for your Convex URL, the script returns the existing registration instead of creating a duplicate.

Save the webhook secret — you'll need it in the next step.

3. Set Environment Variables

In the Convex Dashboard, go to SettingsEnvironment Variables and add:

VariableValueDescription
YOCO_SECRET_KEYsk_live_... or sk_test_...Your Yoco API secret key
YOCO_WEBHOOK_SECRETThe secret from step 2Used to verify webhook signatures (HMAC-SHA256)

4. Configure Access Packages

Edit config.yaml at the repo root to define your access packages:

accessPackages:
  - id: "3-month"
    name: "3 Month Access"
    durationDays: 90
    priceInCents: 29900      # R299.00
    currency: "ZAR"
  - id: "6-month"
    name: "6 Month Access"
    durationDays: 180
    priceInCents: 49900      # R499.00
    currency: "ZAR"
  - id: "lifetime"
    name: "Lifetime Access"
    durationDays: 36500      # ~100 years
    priceInCents: 99900      # R999.00
    currency: "ZAR"

These packages define what customers can purchase. The id is used to look up duration when granting access. Prices are in cents (29900 = R299.00).

After editing, run bun run dev or bun run config:generate to regenerate the typed config.

5. Verify the Integration

  1. Start the dev server: bun run dev
  2. Visit your marketing site's Yoco pricing section
  3. Click a package to start checkout
  4. Complete a test payment (use Yoco's test card numbers in sandbox mode)
  5. Check the Convex Dashboard → Data tab:
    • A yocoCheckouts record should appear with status: "succeeded"
    • An accessGrants record should appear with the correct expiresAt timestamp
    • A webhooks record should appear with provider: "yoco"

What Happens After Setup

Once connected, the full flow runs automatically:

  1. Customer pays → Yoco hosts the checkout, handles card/EFT
  2. Webhook fires → Your Convex backend receives and verifies the payment notification
  3. Access granted → The backend creates an accessGrants record with the expiry date
  4. Reminders sent → A cron job checks for expiring access and sends emails at 14, 7, 1, and 0 days before expiry
  5. Duration stacking → If a customer buys again before expiry, the new duration is added to their current expiry (not from today)

Next Steps

On this page