API de GoCargo
Versión 1 · https://www.gocargo.com.ar/api/v1
GoCargo conecta comercios de La Plata con cadetes que llevan sus envíos. Con esta API tu tienda online o tu sistema crea envíos, los sigue y cotiza sin pasar por la app, y recibe un aviso cada vez que un envío cambia de estado.
Todo va por HTTPS y en JSON. Las fechas son milisegundos desde 1970 (UTC) y los montos, pesos argentinos enteros.
Autenticación
Cada pedido lleva una API key de tu comercio. Se crea desde la app, en la sección API, y se muestra una sola vez: guardala en un lugar seguro, nunca en el código de una página web. Si la perdés, creá otra y revocá la vieja. Podés tener hasta 3 activas.
Authorization: Bearer gc_live_abc123_TU-SECRETOgc_live_…crea envíos reales: un cadete los va a buscar.gc_test_…crea envíos de prueba, con códigoTEST-…. Se cotizan de verdad, se consultan, se cancelan y disparan su aviso de cancelación, pero no los ve ningún cadete y nunca salen a la calle. Una key de prueba solo ve envíos de prueba, y una real, solo reales. Empezá por acá.
Cada key tiene permisos: envios:crear (crear y cancelar), envios:leer y cotizar. Por defecto, los tres.
Cuotas. 120 pedidos por minuto y 5.000 por día por key, y 200 envíos creados por hora por comercio. Pasado un tope, 429 CUOTA_EXCEDIDA.
Errores
Siempre con la misma forma. El código no cambia; el mensaje, puede.
{
"error": {
"codigo": "DATOS_INVALIDOS",
"mensaje": "Falta la dirección de entrega.",
"detalle": { "campo": "entrega.direccion" }
}
}| HTTP | codigo | cuándo |
|---|---|---|
| 401 | KEY_INVALIDA | Falta la key, está mal escrita, no existe o fue revocada. Todas contestan igual. |
| 403 | SIN_PERMISO | La key existe pero no tiene el permiso que pide la ruta. |
| 403 | COMERCIO_SUSPENDIDO | La cuenta del comercio no está activa. |
| 403 | COMERCIO_SIN_VERIFICAR | El comercio todavía no fue verificado por GoCargo. |
| 403 | TERMINOS_PENDIENTES | El comercio tiene que aceptar los Términos vigentes, entrando a la app. |
| 404 | NO_ENCONTRADO | No existe un envío con ese código para tu comercio. El de otro comercio contesta igual. |
| 409 | NO_CANCELABLE | El envío ya no se puede cancelar: lo tomó un cadete o ya terminó. |
| 422 | DATOS_INVALIDOS | Algo del pedido está mal; detalle.campo dice qué. |
| 422 | FUERA_DE_COBERTURA | No pudimos cotizar ese recorrido: fuera de la zona de servicio o entre ciudades distintas. |
| 422 | SIN_PRECIO | No hay precio para ese recorrido con el tarifario de tu cadete. |
| 422 | COMERCIO_SIN_CONFIGURAR | Al comercio le falta cargar su dirección de retiro en la app. |
| 429 | CUOTA_EXCEDIDA | Llegaste a una cuota. Esperá y reintentá. |
| 500 | ERROR_INTERNO | Un problema nuestro. Reintentá en unos minutos. |
Crear un envío
POST /api/v1/envios
El retiro es siempre la dirección de tu comercio: no se manda. El precio lo calcula GoCargo con la distancia real de la ruta; si tu cadete de cabecera tiene tarifario propio, rige el suyo.
curl -X POST https://www.gocargo.com.ar/api/v1/envios \
-H "Authorization: Bearer gc_live_abc123_TU-SECRETO" \
-H "Content-Type: application/json" \
-d '{
"entrega": {
"direccion": "Calle 7 nro 1234, La Plata",
"lat": -34.9214,
"lng": -57.9545,
"telefono": "2215550000"
},
"modalidad": "programado",
"altoValor": false,
"nota": "Timbre 2B",
"referenciaExterna": "pedido-10482"
}'entrega.direccion, obligatoria.latylng, muy recomendadas: sin coordenadas no se puede medir la distancia y hay que mandarzona(sale de ciudades).entrega.telefono: el de quien recibe, para el cadete. No vuelve en ninguna respuesta.modalidad:programado(ventana de 4 horas) oexpress(inmediato).altoValor, obligatorio,trueofalse: si el paquete supera los $100.000 o contiene celulares o electrónica. Contruehay que mandarprecinto, y el envío lleva PIN de entrega.conPin, opcional: pedir PIN aunque no sea de alto valor.valorDeclaradoynota, opcionales.referenciaExterna, opcional, hasta 100 caracteres: el id del pedido en tu sistema. Es única por comercio. Si mandás la misma dos veces no se crea otro envío: te devolvemos el que ya existe, con200en vez de201. Así podés reintentar sin miedo a duplicar.
Respuesta 201:
{
"codigo": "GC-7KQ2MX",
"referenciaExterna": "pedido-10482",
"prueba": false,
"estado": "pendiente",
"modalidad": "programado",
"precio": 3500,
"desglose": [ { "id": "base", "nombre": "Tarifa base", "monto": 3500 } ],
"retiro": { "direccion": "Calle 50 nro 800, La Plata" },
"entrega": { "direccion": "Calle 7 nro 1234, La Plata", "lat": -34.9214, "lng": -57.9545 },
"km": 1.9,
"altoValor": false,
"valorDeclarado": null,
"precinto": null,
"conPin": false,
"tracking": "https://www.gocargo.com.ar/t/GC-7KQ2MX#c=…",
"creado": 1789590000000,
"aceptado": null,
"retirado": null,
"entregado": null,
"cancelado": null,
"motivoCancelacion": null,
"vencido": null
}tracking es el link para mandarle a quien recibe: ve el estado del envío y, si lleva PIN, el PIN. Los envíos de prueba no tienen.
Listar envíos
GET /api/v1/envios
curl "https://www.gocargo.com.ar/api/v1/envios?limite=50&estado=entregado&desde=2026-10-01" \
-H "Authorization: Bearer gc_live_abc123_TU-SECRETO"Del más nuevo al más viejo. Filtros opcionales: desde y hasta (fecha ISO o milisegundos), estado y limite (de 1 a 100, por defecto 50).
{ "envios": [ … ], "siguiente": "eyJrIjoi…" }Si siguiente no es null, pedí la página que sigue con cursor= y ese valor, y los mismos filtros. El cursor es opaco: no lo armes a mano. Con filtro de estado, una página puede traer menos envíos que el límite y aun así tener siguiente.
Consultar un envío
GET /api/v1/envios/{codigo}
curl https://www.gocargo.com.ar/api/v1/envios/GC-7KQ2MX \
-H "Authorization: Bearer gc_live_abc123_TU-SECRETO"Devuelve el envío con la misma forma que al crearlo.
Estados
pendiente | Creado, esperando que lo tome un cadete. |
aceptado | Un cadete lo tomó y va a buscarlo. |
retirado | El cadete lo retiró de tu comercio. |
entregado | Entregado. |
cancelado | Cancelado, con su motivo. |
vencido | Nadie lo tomó a tiempo. No se hizo: se vuelve a pedir. |
Cancelar un envío
DELETE /api/v1/envios/{codigo}
curl -X DELETE https://www.gocargo.com.ar/api/v1/envios/GC-7KQ2MX \
-H "Authorization: Bearer gc_live_abc123_TU-SECRETO" \
-H "Content-Type: application/json" \
-d '{ "motivo": "El cliente anuló la compra" }'Solo mientras está pendiente. Una vez que un cadete lo tomó contesta 409 NO_CANCELABLE: para cancelarlo, escribinos. El motivo es opcional. Devuelve el envío cancelado.
Cotizar
POST /api/v1/cotizar
curl -X POST https://www.gocargo.com.ar/api/v1/cotizar \
-H "Authorization: Bearer gc_live_abc123_TU-SECRETO" \
-H "Content-Type: application/json" \
-d '{
"retiroLat": -34.9205, "retiroLng": -57.9536,
"entregaLat": -34.9109, "entregaLng": -57.9543,
"modalidad": "express"
}'Con key, cotiza con el tarifario de tu comercio si tiene uno. Sin key también funciona, con el precio de referencia y una cuota por IP. La cotización vale 10 minutos (expiraEn) y no reserva nada: el precio que rige es el que devuelve la creación del envío.
Ciudades
GET /api/v1/ciudades
curl https://www.gocargo.com.ar/api/v1/ciudadesPública, sin key. Las ciudades donde funciona GoCargo, con sus zonas y sus precios de referencia vigentes.
Webhooks
Configurá una dirección https en la sección API de la app. Por cada envío creado después de configurarla, te mandamos un POST cuando cambia de estado. Tiene que ser una dirección pública: no se aceptan IPs privadas ni localhost.
envio.aceptado | Un cadete lo tomó y va a buscarlo. |
envio.retirado | El cadete lo retiró de tu comercio. |
envio.entregado | Lo entregó. |
envio.cancelado | Se canceló: desde la app, desde la API o desde GoCargo. |
envio.incidente | Hoy no se dispara nunca: está reservado. Preparate para recibirlo, pero no lo esperes. |
POST /gocargo HTTP/1.1
Host: tu-tienda.com.ar
Content-Type: application/json
X-GoCargo-Evento: envio.entregado
X-GoCargo-Entrega: 9sKq2vXw…
X-GoCargo-Timestamp: 1789593616764
X-GoCargo-Firma: sha256=5d41402abc4b2a76b9719d911017c592…
{
"evento": "envio.entregado",
"envio": {
"codigo": "GC-7KQ2MX",
"referenciaExterna": "pedido-10482",
"prueba": false,
"estado": "entregado",
"creado": 1789590000000,
"aceptado": 1789590600000,
"retirado": 1789591200000,
"entregado": 1789593616000,
"cancelado": null,
"motivoCancelacion": null
},
"timestamp": 1789593616764
}X-GoCargo-Entrega identifica el aviso y es el mismo en cada reintento.
Verificá siempre la firma. Es HMAC-SHA256, con el secreto del webhook (whsec_…, que también se muestra una sola vez), de <X-GoCargo-Timestamp>.<cuerpo tal cual llegó>. Calculala sobre el cuerpo crudo, antes de parsear el JSON, y rechazá los avisos con un timestamp de hace más de cinco minutos.
// Node.js
const crypto = require('crypto');
function esDeGoCargo(cuerpoCrudo, headers, secreto) {
const ts = headers['x-gocargo-timestamp'];
const esperada = 'sha256=' + crypto
.createHmac('sha256', secreto)
.update(`${ts}.${cuerpoCrudo}`)
.digest('hex');
const recibida = String(headers['x-gocargo-firma'] || '');
return recibida.length === esperada.length
&& crypto.timingSafeEqual(Buffer.from(recibida), Buffer.from(esperada))
&& Math.abs(Date.now() - Number(ts)) < 5 * 60 * 1000;
}Contestá un 2xx rápido. Esperamos hasta 5 s. Cualquier otra cosa —otro código, una redirección, un timeout— cuenta como fallo, y reintentamos a los 10 s, 60 s, 300 s. Si falla el último intento, lo vas a ver en la app como un aviso que no llegó. El envío sigue igual: lo que no llegó es el aviso.
Los avisos salen en segundos, no al instante, y el mismo aviso puede llegar más de una vez: usá X-GoCargo-Entrega para no procesarlo dos veces y, ante la duda, consultá el envío.
Verificación sin blockchain
GoCargo no usa blockchain para probar que algo no se tocó: usa HMAC-SHA256 con una clave propia. Es HONESTO sobre lo que eso prueba y lo que no: que un hash o un certificado salió de un servidor de GoCargo que tenía la clave, y que no cambió desde entonces. No prueba que una foto sea real ni que un cadete estuvo en un lugar — eso no tiene prueba criptográfica posible sin GPS en vivo, que GoCargo no usa.
Como es HMAC (una clave compartida, no un par de claves pública/privada), nadie fuera de GoCargo puede verificar una firma por su cuenta: hace falta preguntarle a un servidor de GoCargo, que es el único que tiene la clave. Las dos rutas de abajo son esa pregunta, hecha pública.
Prueba de entrega
Al entregar, GoCargo calcula SHA-256(código + hora + latitud + longitud + foto), en ese orden, y lo firma. Los dos quedan guardados en el envío y se muestran con la llave del seguimiento (/t/{codigo}#c={clave}): ahí hay un botón "Verificar autenticidad" que recalcula el hash en el navegador con lo que la pantalla tiene delante, y le pregunta al servidor si la firma es válida. No hay una ruta pública separada para esto: es parte del seguimiento.
Certificado de reputación
Desde su cuenta, un cadete puede descargar un JSON firmado con SUS números — nada de otro cadete, nada de un comercio en particular: cuántos viajes hizo, qué porcentaje con foto, su antigüedad, cuántos comercios captó y su escala de bonificación actual. Se lo lleva si se va: no tiene que pedirle a GoCargo una constancia, ni GoCargo tiene que dársela.
{
"certificado": {
"version": 1,
"nombre": "Juan Pérez",
"codigoAfiliacion": "JUAN-7K",
"totalViajes": 842,
"porcentajeConFoto": 97,
"antiguedadDias": 214,
"comerciosCaptados": 6,
"escala": "experto",
"escalaNombre": "Experto",
"emitidoEn": 1789600000000
},
"firma": "5d41402abc4b2a76b9719d911017c592…"
}Para confirmar que un certificado es genuino —que salió de GoCargo y no se editó después— mandá el mismo certificado y la misma firma, tal cual los recibiste, a esta ruta:
POST https://www.gocargo.com.ar/api/v1/certificados/verificar
Content-Type: application/json
{
"certificado": { ... },
"firma": "5d41402abc4b2a76b9719d911017c592…"
}
→ { "valido": true }Pública, sin API key —quien pregunta no necesita cuenta en GoCargo—, acotada a 30 pedidos por minuto por IP. valido: false significa que el certificado no coincide con la firma: se editó un número, o la firma no es de GoCargo.
Lo que no sale por la API
Ningún teléfono —ni el de quien recibe ni el del cadete—, ni datos de cobro, ni documentos, ni quién es el cadete. Lo que necesitás del recorrido está en el estado y en el link de seguimiento.
¿Dudas o algo que no anda? Escribinos por WhatsApp. · Términos y Condiciones · Privacidad