API de Mercado Pago con Node.js y TypeScript
La API de Mercado Pago desde Node.js y TypeScript: SDK oficial o fetch, credenciales, pagos, preferencias, idempotencia y errores, con código real.
La API de Mercado Pago es una API REST en https://api.mercadopago.com que se
autentica con un access token en el header Authorization: Bearer …. Todo lo
demás —Checkout Pro, pagos, webhooks— sale de ahí. Esta guía cubre lo que
necesitás para integrarla bien desde un backend Node.js con TypeScript, con el
código que usamos en producción en useDeploy.
Credenciales: de prueba y de producción
En el panel de desarrolladores de Mercado Pago cada aplicación tiene dos juegos de credenciales: de prueba y de producción. Cada juego trae una public key (para el frontend, si usás Bricks) y un access token (solo backend).
Reglas que no conviene romper:
- El access token va en una variable de entorno del servidor
(
MERCADO_PAGO_ACCESS_TOKEN). En Next.js, nunca con prefijoNEXT_PUBLIC_: ese prefijo lo manda al navegador. - Probá con las credenciales de prueba y con usuarios de prueba, no con tu cuenta real.
- El secret para validar webhooks es otro valor distinto; lo ves en la configuración de Webhooks de la aplicación.
¿SDK oficial o fetch directo?
El SDK oficial es el paquete mercadopago de npm (versión 3.6.1 al 4 de
noviembre de 2026). Expone clases como MercadoPagoConfig, Payment y
Preference, valida firmas de webhooks y agrega solo el header de idempotencia
en los POST.
import { MercadoPagoConfig, Preference } from 'mercadopago';
const client = new MercadoPagoConfig({
accessToken: process.env.MERCADO_PAGO_ACCESS_TOKEN!,
options: { timeout: 15_000 },
});
const preference = await new Preference(client).create({ body: { /* … */ } });En useDeploy elegimos fetch directo, por tres motivos concretos:
- Usamos dos endpoints: crear una preferencia y leer un pago. No hace falta una dependencia entera para eso.
- Tipos propios y chicos. Declaramos solo los campos que leemos, así un cambio en la respuesta que no nos afecta no rompe el build.
- Control del timeout y de los errores, con
AbortSignal.timeouty unResulttipado en vez de excepciones.
Si vas a usar muchos productos de Mercado Pago (Bricks, suscripciones, órdenes),
el SDK te ahorra trabajo. Si es Checkout Pro y webhooks, fetch alcanza.
Leer un pago
Es la llamada que más vas a hacer, porque el webhook solo te avisa que algo pasó (más sobre eso en webhooks de Mercado Pago):
const MP_API_BASE = 'https://api.mercadopago.com';
interface MpPayment {
readonly id: number;
readonly status: string; // 'approved' | 'rejected' | 'cancelled' | 'pending' | …
readonly transaction_amount: number; // unidades MAYORES: 199.5 = $199,50
readonly currency_id: string; // 'ARS', 'MXN', 'BRL', …
readonly external_reference?: string;
readonly metadata?: Record<string, unknown>;
}
export async function getPayment(paymentId: string): Promise<MpPayment> {
const res = await fetch(`${MP_API_BASE}/v1/payments/${paymentId}`, {
headers: { Authorization: `Bearer ${process.env.MERCADO_PAGO_ACCESS_TOKEN}` },
signal: AbortSignal.timeout(15_000),
});
if (!res.ok) throw new Error(`GET /v1/payments/${paymentId} → ${res.status}`);
return (await res.json()) as MpPayment;
}Dos detalles que causan bugs reales:
- Los montos van en unidades mayores.
transaction_amount: 199.5son $199,50. Si tu base guarda centavos (como debería), convertí en el borde:Math.round(amount * 100)al leer ycents / 100al crear. external_referencees tu puente. Es el id de tu sistema (usuario, orden) que mandaste al crear la preferencia. Con eso sabés a quién acreditar, sin confiar en nada que venga del navegador.
Crear una preferencia (Checkout Pro)
POST /checkout/preferences devuelve un init_point, la URL de pago a la que
redirigís al usuario. El flujo completo —qué campos mandar, por qué el precio
tiene que salir del servidor y cómo tratar la vuelta— está en Checkout Pro de
Mercado Pago en Next.js.
Idempotencia
Los POST que crean cosas (por ejemplo, un pago con POST /v1/payments) aceptan
el header X-Idempotency-Key: si un timeout te hace reintentar, la misma
clave evita que se cree dos veces. El SDK oficial lo agrega solo; con fetch lo
ponés vos:
await fetch(`${MP_API_BASE}/v1/payments`, {
method: 'POST',
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json',
'X-Idempotency-Key': orderId, // estable por intento lógico, no un random por request
},
body: JSON.stringify(payload),
});Del otro lado también hace falta idempotencia: Mercado Pago puede mandarte el
mismo webhook varias veces, así que tu escritura en la base tiene que tolerar
duplicados (un upsert sobre el id del pago resuelve casi todo).
Errores y timeouts
- Poné timeout a cada llamada (15 s en nuestro caso). Sin timeout, una API lenta te deja requests colgados.
- Ante un
4xx, logueá el cuerpo de la respuesta: Mercado Pago explica ahí qué campo falló. - Ante un
5xxo un timeout en un webhook, respondé con error para que Mercado Pago reintente; no marques nada como pagado sin haber leído el pago.
Dónde poner todo esto
La parte más cara de integrar Mercado Pago no es la API; es dejarla bien encapsulada. En useDeploy todo vive en un solo adapter detrás de un puerto de billing, así el resto de la app no sabe si cobra con Mercado Pago o con Polar (cómo funciona ese puerto). Si estás eligiendo cómo cobrar en pesos, este post compara las opciones.
Preguntas frecuentes
¿Necesito el SDK oficial para usar la API?
No. Es una API REST con autenticación Bearer; fetch alcanza. El SDK suma
comodidad (clases tipadas, validador de firmas, idempotencia automática).
¿Cómo pruebo sin plata real? Con las credenciales de prueba de tu aplicación y usuarios de prueba. Nunca mezcles credenciales de prueba con una cuenta real.
¿Sirve para suscripciones?
Mercado Pago tiene una API de suscripciones (preapproval). El adapter de
useDeploy hoy hace pagos únicos con Checkout Pro y no implementa suscripciones;
si se las pedís, devuelve un error explícito.
¿En qué moneda cobro?
La que define cada ítem con currency_id (ARS, MXN, BRL…). Usá la moneda
local de tu cuenta de Mercado Pago; cada país opera con la suya.
useDeploy trae este adapter de Mercado Pago ya integrado —Checkout Pro, webhooks con firma verificada e idempotencia— junto con auth, organizaciones y el resto de la base de un SaaS. Mirá la integración.