Migración desde v1
La API v2 es una reconstrucción desde cero. Convive con la v1 hasta el 10 de septiembre de 2026, fecha en la que la v1 se retira.
Cambios principales
Autenticación (cambio incompatible)
El esquema antiguo (X-API-KEY + firma RSA x509) desaparece en v2. En su
lugar se usa el esquema de dos niveles: llaves
bearer skp_live_… para lecturas y JWT firmado con EdDSA para mover dinero.
El onboarding es de auto-servicio (ya no se envía un certificado por correo).
Errores
v2 devuelve siempre application/problem+json (RFC 9457) con
un code estable, en lugar de formatos de error heterogéneos.
Renombrados de rutas
| v1 | v2 |
|---|---|
/convert_orders | /orders |
/converts | ⚠️ /fills — una fila por ejecución, no por orden (ver aviso abajo) |
/converts/quotations | /quotes |
/converts/quotations:confirm | POST /orders |
/currencies | /balances |
/historical_balances/{currencyId} | /balances/{assetSymbol}/history |
/ledger_movements/{currencyId} | /ledger?assetSymbol= |
/supported_currencies | /assets |
/supported_markets | /markets |
/users/current | /account |
/convert_orders/id/{id} | GET /orders/{id} |
/converts/id/{id} | ⚠️ sin equivalente 1:1 — ver Consultas por id |
/…/clOrdId/{clOrdId} | ⚠️ sin equivalente — ver Consultas por id |
/converts es /fills, no /ordersEn v1, /converts devuelve una fila por ejecución y /convert_orders una fila por
orden. Su equivalente en v2 es /fills y /orders respectivamente. Si apuntas a /orders
lo que hoy lee /converts, el número de filas cambia: una orden con varias ejecuciones
devuelve una sola fila en /orders donde v1 devolvía varias.
El recurso se llama orden, no "conversión": Convert es la marca del producto, pero el
modelo es de intercambio (una orden con un type), para que en el futuro se puedan añadir
otros tipos de orden sin romper el contrato.
Consultas por id que cambian de forma
Tres rutas de v1 no tienen un equivalente 1:1 en v2:
| v1 | v2 | Qué cambia en tu código |
|---|---|---|
/convert_orders/id/{id} | GET /v2/orders/{id} | Nada: sigue devolviendo una fila. |
/converts/id/{id} | GET /v2/orders/{id}/fills o GET /v2/fills?orderId={id} | Cambia la cardinalidad: recibes una lista de ejecuciones, no una fila. No existe GET /v2/fills/{id}. |
/convert_orders/clOrdId/{clOrdId} | — | No hay búsqueda por clientOrderId en v2. Ese campo sólo se devuelve en la respuesta de POST /v2/quotes, junto al orderId que sí puedes consultar después. Guarda esa correspondencia en tu lado al cotizar. |
?sourceId= sólo existe en el libro contable?orderId= está en /v2/fills y /v2/ledger. ?sourceId= está sólo en
/v2/ledger — no filtra órdenes ni ejecuciones. Ver
ids y correlación.
Renombrados de parámetros y campos
Los renombrados de rutas se delatan solos con un 404. Los de parámetros y los de
campos de respuesta no se comportan igual entre sí, así que van por separado.
Parámetros de query — v2 rechaza los que no reconoce
v2 no ignora un parámetro desconocido: responde 400
validation_error nombrando el parámetro sobrante
(property take should not exist). Es deliberado — en una API de dinero un filtro
ignorado devuelve el resultado equivocado sin avisar — y en la práctica significa
que un renombrado que se te pase aparece en la primera llamada, no en la
conciliación de fin de mes.
| v1 | v2 |
|---|---|
take= | limit= |
currencyId= | assetSymbol= |
currencyBase= / currencyQuote= | baseAsset= / quoteAsset= |
Campos de respuesta — estos sí fallan en silencio
Aquí no hay red: leer un campo que ya no existe da undefined, no un error.
| v1 | v2 | Si no lo cambias |
|---|---|---|
meta.currentSize | pagination.limit | Los cuatro cambian a la vez, así que un bucle de paginación escrito para v1 no encuentra los totales y para tras la primera página. |
meta.totalCount | pagination.totalItems | ⬑ |
meta.totalPages | pagination.totalPages | ⬑ |
meta.currentPage | pagination.page | ⬑ |
quantity | amount | Importe nulo. Ojo también al signo — ver abajo. |
date | createdAt | Fecha nula. |
currencyId | assetSymbol | Activo nulo. |
transactionId | source.id (con source.type) | ⚠️ No es id. id existe en v1 y en v2 y es otro campo: el de la propia entrada. Ver ids y correlación. |
qtyCumBase / qtyCumQuote | filledBaseAmount / filledQuoteAmount | Cantidad ejecutada nula. |
currencyBase / currencyQuote | baseAsset / quoteAsset | Mercado sin identificar. |
Cambios de significado, no de nombre
Dos cambios conservan un nombre razonable pero cambian el valor. Ningún error los delata: revísalos explícitamente.
Los importes públicos son magnitudes positivas
En v1, quantity venía con signo (un retiro era negativo). En v2 amount,
fee y total son siempre positivos: la dirección la da el type de la
entrada, y el propio recurso (un retiro debita, un depósito acredita).
Si sumas movimientos para calcular un neto, el mismo código da otro resultado:
en v2 los débitos suman en vez de restar. Ramifica sobre type antes de acumular.
assetFormat viene por defecto en rebased
/orders, /fills y /withdrawals aceptan assetFormat, y su valor por defecto
es rebased — un cambio deliberado respecto al comportamiento anterior, que
devolvía base. Para equities tokenizadas eso
cambia los importes que ves respecto a v1, sin ninguna señal de error. En los demás
activos el multiplicador es 1 y no cambia nada.
Es una decisión contable antes que técnica: si tu integración depende de las cifras
liquidadas, pide assetFormat=base explícitamente.
Novedades en v2
- Fills como recurso de primer nivel —
GET /v2/fillsyGET /v2/orders/{id}/fills. - Libro contable con trazabilidad —
GET /v2/ledger, consource: {type, id}y filtros?sourceId=/?orderId=(guía). - Precio indicativo —
GET /v2/markets/{market}/price, una tasa no vinculante que no reserva nada y no requiere firma. (Los listados de mercados y activos ya existían en v1 como/supported_marketsy/supported_currencies; lo nuevo aquí es el precio.) - Webhooks firmados (guía).
- Límites de tasa por cuenta y por llave con cabeceras
RateLimit-*.
Calendario
La v1 se retira el 10 de septiembre de 2026 (2026-09-10). A partir de esa
fecha sus endpoints dejan de atender tráfico: completa la migración a v2 antes de
ese día.
Antes del apagado, la v1 empezará a devolver cabeceras Deprecation / Sunset
que anuncian esa misma fecha, y se pueden ejecutar brownouts —ventanas breves y
anunciadas en las que la v1 devuelve error— para que verifiques que tu migración
está completa.