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 devfromapps/convex-backend)
1. Get Your Yoco API Keys
- Log in to the Yoco Business Portal
- Navigate to Developers → API Keys
- Copy your Secret Key (starts with
sk_live_orsk_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:registerWebhookEndpointThis 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 Settings → Environment Variables and add:
| Variable | Value | Description |
|---|---|---|
YOCO_SECRET_KEY | sk_live_... or sk_test_... | Your Yoco API secret key |
YOCO_WEBHOOK_SECRET | The secret from step 2 | Used 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
- Start the dev server:
bun run dev - Visit your marketing site's Yoco pricing section
- Click a package to start checkout
- Complete a test payment (use Yoco's test card numbers in sandbox mode)
- Check the Convex Dashboard → Data tab:
- A
yocoCheckoutsrecord should appear withstatus: "succeeded" - An
accessGrantsrecord should appear with the correctexpiresAttimestamp - A
webhooksrecord should appear withprovider: "yoco"
- A
What Happens After Setup
Once connected, the full flow runs automatically:
- Customer pays → Yoco hosts the checkout, handles card/EFT
- Webhook fires → Your Convex backend receives and verifies the payment notification
- Access granted → The backend creates an
accessGrantsrecord with the expiry date - Reminders sent → A cron job checks for expiring access and sends emails at 14, 7, 1, and 0 days before expiry
- Duration stacking → If a customer buys again before expiry, the new duration is added to their current expiry (not from today)
Next Steps
- Yoco Pricing & Access Packages — in-depth guide on customizing packages, access gating, and the expiry reminder system
- Payments Overview — comparison of Yoco vs Polar and when to use each