GSG Corp · Integraciones

Guía de inicio

Versión 1.2 · Actualizado el 2026-09-29 · API de integrador 1.1

Esta guía te lleva desde cero hasta tu primera llamada exitosa: cómo obtener credenciales según tu escenario, cómo autenticarte, qué forma tienen las respuestas y cómo comprobar la conexión.

1.Obtener credenciales

Escenario A · Plataforma multi-tienda

CredencialQuién la entregaAlcance
API key (gsg_<prefijo>_<secreto>) GSG, al dar de alta la plataforma. Se muestra una sola vez. Identifica a la plataforma. Una por plataforma.
store_token (st_…) Cada negocio, desde su panel GSG (Integraciones → Plataformas → Vincular). Si la plataforma exige aprobación manual, el token se habilita cuando GSG aprueba el vínculo. Identifica la tienda. Uno por negocio vinculado.

La plataforma obtiene el store_token de dos formas: el negocio lo copia de su panel GSG y lo pega en la configuración de tu producto, o tu backend lo recupera automáticamente con POST /api/integration/bindings/lookup usando el external_store_id que el negocio declaró al vincularse.

Escenario B · Integración directa

  1. El negocio entra a su panel GSG → Integraciones → Integración directa y envía la solicitud (nombre del sistema, descripción, contacto técnico, URL de webhook opcional).
  2. GSG revisa la solicitud. Mientras está pendiente, el panel muestra "en revisión"; si se rechaza, muestra el motivo y permite volver a solicitar.
  3. Aprobada la solicitud, el negocio pulsa Generar API key (pide re-autenticación). El panel muestra una sola vez la api_key y el store_token. El webhook_secret se mostró una sola vez al enviar la solicitud (si indicó URL de webhook); si no lo guardó, rótelo desde Integraciones → Integración directa → Webhook (rotate_secret: true) o marque "rotar el secret" al regenerar la API key.

Mientras la solicitud está pendiente, el negocio puede retirarla desde el mismo panel (queda inactiva y puede volver a solicitarse más adelante).

store_token opcional: en una integración directa la API key ya identifica al negocio. Puedes omitir X-Store-Token en todas las llamadas. Si lo envías, debe ser el de tu propio vínculo.

2.URL base y entornos

En toda la documentación las rutas se muestran relativas a {BASE_URL}. Sustitúyela por la URL base que te indique GSG. La URL base de producción es la que se muestra en el panel de negocios GSG (sección Integraciones); GSG puede facilitarte además un ambiente de pruebas.

GrupoPrefijoAutenticación
Registro de pedidos{BASE_URL}/api/v1/integration/orders (alias idéntico: {BASE_URL}/api/v1/orders/integration)API key + tienda
API de integrador{BASE_URL}/api/v1/integration/…API key (+ tienda donde aplica)
Lookup de tiendas (plataformas){BASE_URL}/api/integration/bindings/lookupSolo API key

3.Cabeceras de autenticación

CabeceraObligatoriaDescripción
X-API-Key Sí* La API key completa, tal como se entregó (gsg_<prefijo_hex>_<secreto>).
Authorization Sí* Bearer <API_KEY>. Alternativa a X-API-Key; si llegan ambas, prevalece X-API-Key.
X-Store-Token Según escenario Token de la tienda (st_…). Obligatorio para plataformas en los endpoints con alcance de tienda (registro, cotización, consulta, listado, cancelación). Opcional para integraciones directas. También se acepta en el cuerpo JSON como store_token.
Idempotency-Key No Solo en el registro de pedidos. Identificador único por intento (máx. 100 caracteres). Alias: X-Idempotency-Key. Ver idempotencia.

* Debes enviar una de las dos formas de API key.

Qué endpoint exige qué

EndpointAPI keyX-Store-Token
GET /api/v1/integration/meSíOpcional (si lo envías, se valida y la respuesta incluye la tienda)
GET /api/v1/integration/catalogsSíOpcional (con tienda: your_courier_cost con tu descuento y business)
POST /api/v1/integration/quoteSíPlataformas: obligatorio · Directas: opcional
POST /api/v1/integration/orders (o /api/v1/orders/integration)SíPlataformas: obligatorio · Directas: opcional
GET /api/v1/integration/orders… y POST …/cancelSíPlataformas: obligatorio · Directas: opcional
POST /api/integration/bindings/lookupSíNo aplica

4.Formato de respuesta y códigos

Todas las respuestas de la API de integrador usan el mismo envelope. En éxito hay message y data; en error solo message. El campo message.code es "90" + código HTTP.

Éxito (HTTP 200)
{
  "message": { "description": "Ok", "title": "OK OK", "code": "90200" },
  "data": { ... }
}
Error (HTTP 400, 401, 404, 409, 429, 500)
{
  "message": {
    "description": "texto explicativo del error",
    "title": "Error",
    "code": "90400"
  }
}
HTTPmessage.codemessage.titleSignificado
20090200OK OKOperación correcta. Incluye data.
40090400ErrorValidación de datos o regla de negocio (distrito sin cobertura, agencia inexistente, tamaño inválido…). Corrige y reenvía. Un JSON malformado responde El cuerpo JSON no es válido con este mismo envelope.
40190401Unauthorized ErrorCredenciales inválidas: API key ausente, mal formada, revocada o expirada; cliente inactivo/pendiente/rechazado; store_token ausente, ajeno o vínculo no activo (Vínculo de tienda inactivo o bloqueado (…)).
40490404ErrorEl pedido no existe para esta tienda (solo se ven pedidos creados por API con la misma tienda). La descripción empieza con Error: .
40990409ErrorConflicto: idempotencia (order_external_id reutilizado con otro contenido, pedido en proceso, Idempotency-Key reutilizada) o el estado del pedido no admite la acción (cancelación).
42990429Too Many RequestsRate limit superado. Espera y reintenta con backoff.
50090500Error ServerError interno de GSG con un texto fijo por endpoint (nunca el detalle interno). Puedes reintentar; en el registro de pedidos el reintento con el mismo cuerpo es seguro (nada quedó a medias).
Excepción: el endpoint POST /api/integration/bindings/lookup valida el cuerpo con un validador genérico. Si external_store_id falta o supera 120 caracteres responde HTTP 400 con { "message": { "code": "90100", ... }, "errors": [ { "path": "external_store_id", "msg": "..." } ] } (un JSON malformado sí usa el envelope estándar: El cuerpo JSON no es válido, 90400). Su rate limit (100/min) responde 429 con { "ok": false, "error": { "code": "TOO_MANY_REQUESTS", "message": "..." } }.

5.Prueba de conexión: GET /api/v1/integration/me

GET {BASE_URL}/api/v1/integration/me API key · store_token opcional

Devuelve quién eres para GSG: tu cliente de integración, el prefijo de la API key en uso, la tienda (si enviaste store_token o eres integración directa), el estado de tu webhook (solo integración directa) y el rate limit. No tiene efectos secundarios: úsalo como health check de credenciales.

curl
curl "https://{BASE_URL}/api/v1/integration/me" \
  -H "X-API-Key: gsg_PREFIJO_SECRETO" \
  -H "X-Store-Token: st_TOKEN_DE_TIENDA"
Respuesta 200
{
  "message": { "description": "Ok", "title": "OK OK", "code": "90200" },
  "data": {
    "api_version": "1.4",
    "server_time": "2026-09-03T15:00:00.000Z",
    "integration_client": {
      "id": 1,
      "code": "stocky_360",
      "name": "Stocky360",
      "type": "PLATFORM",
      "status": "active"
    },
    "api_key": {
      "prefix": "2d35df56256315f7",
      "created_at": "2026-08-01T14:02:11.000Z",
      "last_used_at": "2026-09-03T14:59:40.000Z"
    },
    "store": {
      "binding_id": 12,
      "business_id": 2120,
      "business_name": "Ctrl go",
      "external_store_id": "flujos_ctrlgo",
      "status": "active"
    },
    "webhook": null,
    "rate_limit": { "per_minute": 300 },
    "docs_url": "https://business.gsgcorp.pe/documentacion_publica/"
  }
}
CampoDescripción
integration_client.typePLATFORM (multi-tienda) o DIRECT (integración directa).
api_key.prefixPrefijo hexadecimal de la key en uso; sirve para confirmar qué key está configurada sin exponer el secreto.
storenull si no enviaste store_token (plataformas). Para integraciones directas se resuelve automáticamente el negocio dueño.
webhookSolo para integraciones directas: { configured, is_active, url_masked, last_delivery_at } (url_masked = host y último segmento del path, null si no hay webhook). Para plataformas es null (el webhook de la plataforma no se describe a la tienda).
rate_limit.per_minuteTecho vigente de peticiones por minuto por cliente de integración (tu API key).

Respuesta con Cache-Control: no-store.

6.Recuperar el store_token de una tienda (plataformas)

POST {BASE_URL}/api/integration/bindings/lookup Solo API key · 100 req/min por IP

Servidor a servidor. Devuelve el store_token de una tienda ya vinculada a tu plataforma a partir del external_store_id que el negocio declaró al vincularse en su panel GSG. No es para polling: consúltalo al conectar una tienda o al recibir 401 por token inválido, y cachea el resultado.

Petición
POST {BASE_URL}/api/integration/bindings/lookup
X-API-Key: gsg_PREFIJO_SECRETO
Content-Type: application/json

{ "external_store_id": "flujos_ctrlgo" }
Respuesta 200 · vínculo activo (único caso en que viaja el token)
{
  "message": { "description": "Ok", "title": "OK OK", "code": "90200" },
  "data": {
    "exists": true,
    "binding": {
      "id": 12,
      "business_id": 2120,
      "user_id": 3310,
      "store_token": "st_a1b2c3…",
      "external_store_id": "flujos_ctrlgo",
      "status": "active",
      "created_at": "2026-08-20T16:45:00.000Z"
    }
  }
}
Respuesta 200 · vínculo existe pero no está activo
{
  "message": { "description": "Ok", "title": "OK OK", "code": "90200" },
  "data": {
    "exists": true,
    "binding": { "id": 12, "business_id": 2120, "user_id": 3310, "store_token": null,
                 "external_store_id": "flujos_ctrlgo", "status": "pending", "created_at": "…" },
    "reason": "El vínculo existe pero está pendiente de aprobación por GSG."
  }
}
Respuesta 200 · no hay vínculo
{ "message": { "description": "Ok", "title": "OK OK", "code": "90200" }, "data": { "exists": false } }
binding.statusreasonQué hacer
active—Guarda el store_token y úsalo en las llamadas de esa tienda.
pendingEl vínculo existe pero está pendiente de aprobación por GSG.Espera la aprobación; reintenta más tarde.
rejectedEl vínculo fue rechazado por GSG; el negocio puede volver a solicitarlo desde su panel.Indica al negocio que revise el motivo en su panel.
blockedEl vínculo existe pero está bloqueado por administración; contacte a soporte.Contacta a GSG.
inactiveEl vínculo existe pero está inactivo; reactívelo desde el flujo de registro.El negocio debe volver a vincular desde su panel.

7.Rate limit

Todos los endpoints de integrador (/api/v1/integration/* y POST /api/v1/orders/integration) aplican dos límites independientes:

LímiteTechoCuándo se evalúaMensaje (message.description)
Por cliente de integración (tu API key, sumando todas tus tiendas e IPs)300/min (el valor vigente lo devuelve /me → rate_limit.per_minute)Después de autenticar; el 429 queda registrado en tu actividadDemasiadas peticiones: máximo 300 por minuto por cliente de integración. Espere y reintente con backoff.
Por dirección IP900/minAntes de autenticar (frena ráfagas con credenciales inválidas)Demasiadas peticiones desde esta IP; espere y reintente con backoff

Al superar cualquiera de los dos, la respuesta es 429 con el envelope estándar:

{
  "message": {
    "description": "Demasiadas peticiones: máximo 300 por minuto por cliente de integración. Espere y reintente con backoff.",
    "title": "Too Many Requests",
    "code": "90429"
  }
}

Cada respuesta incluye las cabeceras estándar RateLimit-* (borrador IETF draft-7): RateLimit-Policy: 300;w=60 y RateLimit: limit=300, remaining=<n>, reset=<segundos> (las del límite que esté más cerca de agotarse). Úsalas para regular tus ráfagas. Recomendaciones:

8.Seguridad de las credenciales

  1. Guarda la API key en un vault o gestor de secretos (o variables de entorno cifradas). Nunca en el repositorio, en logs ni en tickets.
  2. Nunca la uses desde un frontend (navegador, app móvil, plugin cliente). Todas las llamadas deben salir de tu backend.
  3. Rota la key periódicamente y ante cualquier sospecha de filtración. Integraciones directas: botón "Rotar API key" en el panel (la anterior queda revocada al instante). Plataformas: solicítalo a GSG. Planifica el despliegue de la key nueva antes de rotar: no hay periodo de convivencia.
  4. Trata cada store_token como credencial: quien lo tenga junto con tu API key puede registrar pedidos a nombre de esa tienda. Guárdalo y envíalo exactamente como lo recibiste (la comparación no distingue mayúsculas, pero usa siempre la misma caja).
  5. Guarda el webhook_secret igual que la key y verifica siempre la firma de los eventos.
  6. Registra en tu sistema el api_key.prefix que devuelve /me: te permite saber qué key está desplegada en cada ambiente sin exponer el secreto.

9.Siguientes pasos

  1. Descarga la colección Postman y configura base_url, api_key y store_token.
  2. Llama a GET /catalogs y guarda distritos, tamaños, agencias y sedes (Catálogos y tarifas).
  3. Cotiza con POST /quote y registra tu primer pedido con POST /api/v1/integration/orders (API de pedidos). El ejemplo mínimo está en la portada.
  4. Consulta el pedido con GET /orders/:orderExternalId y configura tu webhook (Seguimiento, Webhooks).

10.Historial de cambios

VersiónFechaCambios
1.22026-09-29 El ejemplo de GET /me muestra api_version "1.4" (hora límite de registro del día; ver API de pedidos 1.4).
1.12026-09-15 Registro de pedidos también en POST /api/v1/integration/orders (alias idéntico de /api/v1/orders/integration); enlace al quickstart de la portada.
1.02026-09-03 Revisión del mismo día: en integración directa el webhook_secret se muestra al enviar la solicitud (no al generar la API key) y la solicitud pendiente puede retirarse desde el panel; GET /me devuelve webhook: null para plataformas; rate limit en dos niveles (300/min por cliente de integración + 900/min por IP) con sus mensajes; 400 El cuerpo JSON no es válido para JSON malformado; 500 con textos fijos; 401 de vínculo con prefijo Vínculo de tienda inactivo o bloqueado (…) y 401 por API key expirada; regla "misma caja" para store_token.
1.02026-09-03 Versión inicial: credenciales por escenario (plataforma / directa), cabeceras, envelope y códigos, prueba con GET /api/v1/integration/me, lookup de tiendas, rate limit 300/min y seguridad.