Beztack
Payments

Mercado Pago

Payment and subscription flows with Mercado Pago

Beztack supports Mercado Pago as a first-class payment provider, including plan sync, subscriptions, checkout preference, direct payment processing, and webhook/event handling.

For an overview of the provider-agnostic payment system, see Payments Core.

When to use Mercado Pago

Use Mercado Pago when you need:

  • Native Mercado Pago plans/subscriptions
  • Direct card payment processing
  • Mercado Pago webhook-driven state updates
  • Real-time payment events for frontend UX

See also: Polar

Required environment variables

API (apps/api/.env)

MERCADO_PAGO_ACCESS_TOKEN=APP_USR-...
MERCADO_PAGO_WEBHOOK_SECRET=... # optional but recommended
MERCADO_PAGO_INTEGRATOR_ID=...  # optional
PAYMENT_PROVIDER=mercadopago
APP_URL=http://localhost:3000

UI (apps/ui/.env)

VITE_PAYMENT_PROVIDER=mercadopago
VITE_MERCADO_PAGO_PUBLIC_KEY=APP_USR-...
VITE_API_URL=http://localhost:3000

Implementation references:

  • Env schemas: packages/env/src/api.ts, packages/env/src/ui.ts
  • Provider factory: apps/api/lib/payments/index.ts
  • React provider wiring: apps/ui/src/app.tsx

API Routes

Unified routes (shared across all providers)

These routes are provider-agnostic and work with whichever provider is active:

  • GET /api/subscriptions/products — List products/plans from the active provider.
  • POST /api/subscriptions/checkout — Create a checkout session.
  • GET /api/subscriptions — List subscriptions for the current user.
  • GET /api/subscriptions/:id — Get a specific subscription.
  • PATCH /api/subscriptions/:id — Update a subscription.
  • DELETE /api/subscriptions/:id — Cancel a subscription.
  • POST /api/subscriptions/webhooks — Process webhook payloads (unified handler).

MercadoPago-specific route

  • POST /api/payments/mercado-pago/webhook — Validate and process MercadoPago-specific webhook payloads.

Admin plan management routes

  • GET /api/admin/plans — List all plans from the local DB.
  • POST /api/admin/plans — Create a new plan.
  • POST /api/admin/plans/import — Import plans from the provider.
  • POST /api/admin/plans/sync — Sync all plans from the provider into the local DB.
  • GET /api/admin/plans/sync-status — Check the current sync status.
  • PATCH /api/admin/plans/:id — Update a plan.
  • DELETE /api/admin/plans/:id — Delete a plan.

Plan sync flow

Beztack keeps a local plan mirror in the plan table (provider-agnostic, with a providerPlanId field linking to the remote product ID) to make plan selection and checkout flows predictable in the app.

  • GET /api/admin/plans reads local plans.
  • POST /api/admin/plans/sync performs an explicit admin-triggered sync from the provider.
  • POST /api/admin/plans/import imports plans from the provider into the local DB.
  • GET /api/admin/plans/sync-status reports the current sync state.

Client integration

In UI, Mercado Pago is enabled by environment flags and wrapped with MercadoPagoProvider.

<MercadoPagoProvider apiBaseUrl={env.VITE_API_URL} publicKey={mpPublicKey}>
  {children}
</MercadoPagoProvider>

The package @beztack/mercadopago/react exposes:

  • Provider + context
  • Hooks (usePlans, useSyncPlans, useSubscriptions, etc.)
  • Components for subscriptions, status badges, billing history, and bricks

Testing checklist

  1. Configure sandbox credentials and VITE_MERCADO_PAGO_PUBLIC_KEY.
  2. Test checkout via POST /api/subscriptions/checkout.
  3. Trigger/receive webhook events and verify local DB updates.
  4. Validate plan sync via admin routes (/api/admin/plans/sync).
  5. Verify SSE events in the UI (if using the events endpoint).

Troubleshooting

  • 401/403 on plan sync/create: verify admin session.
  • Missing webhook updates: verify MERCADO_PAGO_WEBHOOK_SECRET and public URL.
  • Provider not active in UI: check VITE_PAYMENT_PROVIDER=mercadopago and public key presence.
  • Wrong API base: confirm VITE_API_URL points to the running API.