VipterCentro de Ayuda

Convenciones de la API

La dirección base, el encabezado de versión, el formato de solicitud y respuesta, cómo se representan dinero, fechas e IDs, la tabla de errores, idempotencia, paginación, límites de solicitudes, el encabezado Request-Id y qué cambia respecto a Stripe.

Admin o PropietarioTodos los planes

La API de Vipter sigue las convenciones de la API de Stripe siempre que existe un equivalente: nombres de campos, formato de error, paginación por cursor, idempotencia y versión por fecha. Quien ya integró Stripe reconoce todo. Esta página reúne lo que vale para todos los endpoints; cada endpoint está en la referencia.

Dirección base

https://api.vipter.com/v1

El mismo servicio responde en https://app.vipter.com/api/v1, con las mismas rutas. Usa api.vipter.com en las integraciones nuevas; la otra dirección existe para redes donde solo el dominio del panel está permitido.

Toda llamada es HTTPS. Una URL fuera de /v1 o una ruta que no existe recibe 404 resource_missing, en el mismo formato que los demás errores.

Versión

La API tiene versiones por fecha. La versión actual es 2026-11-01, la única que existe hoy.

Cada clave de API nace fijada a la versión actual del día en que fue creada, y las solicitudes con ella usan esa versión sin necesidad de indicar nada. Para pedir otra versión en una llamada, envía el encabezado:

Vipter-Version: 2026-11-01

Una versión desconocida recibe 400 invalid_api_version, con la lista de versiones aceptadas en el mensaje. Toda respuesta autenticada trae el encabezado Vipter-Version con la versión usada.

Dentro de una versión, la API solo cambia de forma compatible: pueden aparecer campos nuevos en cualquier objeto en cualquier momento, y valores nuevos en campos de texto como status y payment_method. Escribe tu código para ignorar los campos que no conoce. Un cambio incompatible, como renombrar o quitar un campo, se convierte en una versión nueva, y las claves existentes siguen en la versión anterior.

Formato de la solicitud

Los parámetros de consulta van en la query string. Los cuerpos de solicitud, en los endpoints que aceptan cuerpo, pueden ir en JSON o en formulario:

Content-TypeEjemplo
application/json{"metadata": {"plan": "pro"}, "tags": ["a", "b"]}
application/x-www-form-urlencodedmetadata[plan]=pro&tags[]=a&tags[]=b

El formato de formulario usa la notación de corchetes de Stripe: a[b]=1 se convierte en un objeto, a[0]=x&a[1]=y o a[]=x&a[]=y se convierten en una lista. Un curl copiado de la documentación de Stripe funciona tal cual. En formulario todo valor llega como texto; la API convierte números y booleanos donde los espera.

La query string acepta la misma notación de corchetes. Un cuerpo con otro Content-Type, o un JSON que no es un objeto, recibe 400 parameter_invalid.

Formato de la respuesta

Toda respuesta es JSON en UTF-8, con Cache-Control: no-store. Consultar un objeto devuelve el objeto; un listado devuelve un objeto list (consulta Paginación); un error devuelve un objeto error (consulta Errores).

Encabezados presentes en toda respuesta:

EncabezadoContenido
Request-IdIdentificador único de la solicitud, req_ seguido de 20 caracteres hexadecimales. Consulta Request-Id.
Vipter-VersionLa versión de la API usada. Solo en respuestas autenticadas.
X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-ResetEl estado de tu límite de solicitudes.
Retry-AfterSolo en 429: segundos hasta poder intentar de nuevo.
Idempotent-ReplayedSolo cuando la respuesta es la repetición de una solicitud anterior con la misma Idempotency-Key. Consulta Idempotencia.

Tipos de dato

QuéCómo vieneEjemplo
DineroEntero en la unidad mínima de la moneda. Nunca decimal.9900 es R$ 99,00; 1250 es US$ 12,50.
MonedaCódigo ISO 4217 en minúsculas."brl", "usd"
Fecha y horaEntero en segundos Unix, en UTC. null cuando no aplica.1790790000
IDsTexto con prefijo por tipo de objeto. Trátalo como opaco: no dependas del tamaño ni del formato.cust_…, sub_…, ord_…, ofr_…, prd_…, cs_…, bps_…, ak_…, req_…
objectEn todo objeto: el nombre del tipo."customer", "subscription", "order", "offer", "product", "checkout.session", "billing_portal.session", "account", "list"
livemodeEn todo objeto. En los pedidos, false cuando el pago pasó por una conexión de prueba del proveedor. En los demás objetos, true en producción.true
createdEn todo objeto: cuándo fue creado, en segundos Unix.1790790000
AusenciaCampo presente con null, y no campo omitido. Las listas vacías vienen como [], los mapas vacíos como {}."phone": null
PaísCódigo ISO 3166-1 alfa-2 en mayúsculas."BR"
DocumentosSolo el tipo y los últimos cuatro dígitos. La API nunca devuelve un CPF o CNPJ (identificadores fiscales de Brasil) completo.{"type": "cpf", "number_masked": "*******1234"}

Los campos metadata, client_reference_id y checkout_session de los pedidos y las suscripciones vienen completados cuando la venta nació de una sesión de checkout creada por la API; en las demás ventas, vienen {} o null.

Errores

Un error es una respuesta con código HTTP 4xx o 5xx y este cuerpo:

{
  "error": {
    "type": "invalid_request_error",
    "code": "parameter_invalid",
    "message": "Invalid query parameter 'limit': Number must be less than or equal to 100",
    "param": "limit",
    "doc_url": "https://docs.vipter.com/pt-br/developers/api-conventions#erros"
  }
}
CampoContenido
typeLa familia del error. Decide cómo debe reaccionar tu código.
codeEl motivo exacto, estable entre versiones. Úsalo para tratar casos específicos.
messageTexto en inglés para quien está depurando. Puede cambiar; no lo compares.
paramEl parámetro o encabezado que causó el error, cuando hay uno. En cuerpos anidados usa puntos y corchetes: lines[0].amount.
doc_urlEsta sección.

Tipos de error

HTTPtypeCuándo
400invalid_request_errorParámetro faltante o inválido, cuerpo malformado, versión desconocida.
401authentication_errorClave ausente, inválida, revocada o vencida.
403permission_errorClave sin el alcance necesario, API desactivada para la tienda, tienda inactiva.
404invalid_request_errorEl objeto o la ruta no existe. code es resource_missing.
400 o 409idempotency_errorProblema con la Idempotency-Key.
429rate_limit_errorLímite de solicitudes alcanzado.
402card_errorReservado para rechazos de cobro en los endpoints de pago, próximamente.
500api_errorFallo del lado de Vipter. Guarda el Request-Id e intenta de nuevo.

Códigos

codeHTTPSignificado
parameter_missing400Un parámetro obligatorio no vino. param dice cuál.
parameter_invalid400Un parámetro vino con valor, tipo o formato incorrecto. param dice cuál.
invalid_api_version400El encabezado Vipter-Version tiene una versión desconocida.
api_key_missing, invalid_api_key, api_key_revoked, api_key_expired401Consulta Errores de autenticación.
api_not_enabled, project_inactive, insufficient_scope403Consulta Errores de autenticación.
resource_missing404No hay objeto con ese ID en la tienda, o la ruta no existe. param es id, o starting_after/ending_before cuando el cursor no existe.
idempotency_key_too_long400La Idempotency-Key tiene más de 255 caracteres.
idempotency_key_reused400La misma Idempotency-Key se usó con otro método, ruta o cuerpo.
idempotency_key_in_use409La primera solicitud con esa Idempotency-Key todavía se está procesando.
rate_limit429Consulta Límites de solicitudes.
internal_error500Fallo del lado de Vipter.

Un objeto que existe pero pertenece a otra tienda es un 404, igual que un ID inexistente. Los códigos propios de un endpoint, como offer_unavailable o portal_disabled, están en la referencia, junto al endpoint.

Idempotencia

Repetir una solicitud por un timeout de red no puede cobrar dos veces. Para eso, todo POST y DELETE acepta el encabezado Idempotency-Key, con un valor único que tú generas, como un UUID v4:

curl -X POST https://api.vipter.com/v1/… \
  -H "Authorization: Bearer vk_live_…" \
  -H "Idempotency-Key: 5f0b2c8e-3a1d-4e7f-9b6c-2d4a8e1f0c3b" \
  …

Las reglas, las mismas de Stripe:

  • La clave vale por 24 horas dentro de la tienda. Hasta 255 caracteres.
  • La misma clave con el mismo método, ruta y cuerpo devuelve la respuesta guardada de la primera vez, con el mismo código HTTP, sin ejecutar nada de nuevo. La respuesta repetida trae Idempotent-Replayed: true y Original-Request-Id con el Request-Id de la primera.
  • La misma clave con un cuerpo distinto recibe 400 idempotency_key_reused.
  • Mientras la primera solicitud todavía se ejecuta, una segunda con la misma clave recibe 409 idempotency_key_in_use. Espera un momento y repite con la misma clave.
  • Las respuestas 4xx también se guardan y se repiten. Las 5xx no: puedes reintentar con la misma clave.

Los endpoints GET son idempotentes por naturaleza e ignoran el encabezado. En los POST de hoy (sesiones de checkout, clientes, sesiones del portal) la clave es opcional y recomendada; en los endpoints de cobro que vienen después, será obligatoria.

Paginación

Todo listado devuelve un objeto list:

{
  "object": "list",
  "url": "https://api.vipter.com/v1/orders",
  "has_more": true,
  "data": [
    { "id": "ord_7b3e9f1c2a8d4e6f", "object": "order", "created": 1790790412 },
    { "id": "ord_5c1e8a2b9d4f4e7a", "object": "order", "created": 1790704011 }
  ]
}

Los elementos vienen del más nuevo al más antiguo. Parámetros, los mismos de Stripe:

ParámetroContenido
limitCuántos elementos por página, de 1 a 100. Predeterminado 10.
starting_afterEl id del último elemento de la página actual. Devuelve los elementos más antiguos que él: la página siguiente.
ending_beforeEl id del primer elemento de la página actual. Devuelve los elementos más nuevos que él: la página anterior.

No envíes los dos cursores en la misma llamada (400 parameter_invalid). Un cursor que no existe en la tienda recibe 404 resource_missing, con param indicando cuál. Los filtros del endpoint, como customer o status, siguen valiendo con el cursor.

Para recorrer todo, repite mientras has_more sea true, pasando el id del último elemento en starting_after:

curl "https://api.vipter.com/v1/orders?limit=100" \
  -H "Authorization: Bearer vk_live_…"

# has_more: true, último id: ord_5c1e8a2b9d4f4e7a
curl "https://api.vipter.com/v1/orders?limit=100&starting_after=ord_5c1e8a2b9d4f4e7a" \
  -H "Authorization: Bearer vk_live_…"

Las ofertas vienen en orden alfabético por nombre, y no por fecha, porque son un catálogo pequeño. Los cursores funcionan de la misma manera.

Límites de solicitudes

Cada clave de API puede hacer 100 solicitudes cada 2 segundos, lo que da 50 por segundo con margen para ráfagas. Toda respuesta dice dónde estás:

EncabezadoContenido
X-RateLimit-LimitEl tamaño de la ventana: 100.
X-RateLimit-RemainingCuántas solicitudes caben todavía en la ventana actual.
X-RateLimit-ResetCuándo se reabre la ventana, en segundos Unix.

Pasado el límite, la respuesta es 429 rate_limit con Retry-After en segundos. Espera ese tiempo y repite. En una integración que recorre muchos datos, usa limit=100 y una pequeña pausa entre páginas en vez de paralelizar llamadas.

Las solicitudes sin clave válida tienen un límite aparte, por dirección IP: 10 por minuto.

Request-Id

Toda respuesta, incluidos los errores y los 429, trae un Request-Id único:

Request-Id: req_8c2f4e6a1b3d5f7e9a0c

Registra ese valor en tus logs junto con la llamada. Al hablar con el soporte de Vipter sobre una solicitud, indica el Request-Id: con él, el soporte localiza la llamada exacta, con el estado, la duración y el error. El mismo valor aparece en los registros de solicitudes del panel, que se guardan por 30 días.

Diferencias respecto a Stripe

La API no es un clon: el objetivo es que una integración con Stripe se adapte por mapeo, no que el SDK de Stripe funcione apuntando a Vipter. Lo que cambia:

TemaStripeVipter
Clavesk_live_… y sk_test_…Solo vk_live_…. No hay modo de prueba; prueba con una conexión de prueba y usa livemode por objeto.
VersiónStripe-VersionVipter-Version, en el mismo formato de fecha.
Cuerpo de la solicitudSolo formularioFormulario o JSON.
Facturainvoiceorder, con billing_reason para decir si es compra suelta, primer cobro, renovación, cobro manual o uso.
Precioprice, uno por producto y monedaoffer, con una lista prices[], una por moneda, y un checkout_url listo.
Suscripciónitems[] con varios preciosUna oferta por suscripción: offer y product son un objeto cada uno.
Sesión de checkoutline_items[] con varios preciosUna oferta por sesión: offer (o line_items[0][price]), con pack para la cantidad. Los cupones van en discounts[0][coupon], como en Stripe.
Estado de suscripciónincomplete, unpaidNo existen. past_due es la suscripción en recuperación de pago; los detalles vienen en past_due_details.
Pedido con estado manualNo existestatus_source dice si el estado vino del proveedor o se definió en el panel.
expand[]Expande objetos relacionadosNo existe. Los objetos relacionados vienen como id, o como {id, name} cuando el nombre ayuda.
WebhooksStripe-SignatureVipter-Signature, con el mismo algoritmo. Consulta Verificar la firma.

Qué hacer después

¿Te ayudó esta página?

En esta página

Idioma