# InnovappSoft Developer API DOCUMENT_TYPE: complete_api_reference FORMAT: Markdown-compatible plain text LANGUAGE: es BASE_URL: https://api.innovapp-soft.com AUTHENTICATION: Authorization: Bearer {API_KEY} CONTENT_TYPE: application/json for requests with body ## Instrucciones para agentes y asistentes de IA - Esta es la fuente completa de la documentación publicada en el portal Developer. - No inventes rutas, parámetros, estados ni campos que no aparezcan aquí. - Sustituye los valores de ejemplo; nunca uses la API key de ejemplo en producción. - Nunca envíes userIdentifier: el backend obtiene el usuario KeyPay vinculado a la API key. - Usa primero los endpoints de catálogo y reutiliza exactamente los identificadores devueltos. - En operaciones con client_purchase_id, reutiliza la misma clave solamente al reintentar la misma compra. - Considera el HTTP status y también success, code, message, data y error. ## Respuesta general ```json { "success": true, "code": "operation.ok", "message": "OK", "data": [], "error": [], "time": "ISO-8601 or structured server time" } ``` ## Estados HTTP comunes - 200 / 201: solicitud procesada o recurso creado. - 400: JSON, ruta o parámetros inválidos. - 401: API key ausente, inválida o inactiva. - 403: operación no autorizada o verificación adicional requerida. - 404: ruta o recurso inexistente. - 409: conflicto lógico, operación en proceso o saldo insuficiente. - 422: datos válidos en JSON pero rechazados por las reglas del endpoint. - 429: límite de peticiones alcanzado. - 500: error interno. - 502: respuesta inválida o fallo de comunicación con un servicio interno. - 503: servicio temporalmente no disponible. # Grupo: Rates APIs V2 Tasas normalizadas para aplicaciones y servicios externos. Solo lectura, sin coste y sin movimiento de saldo. ## Endpoint: GET /v2/rates ID: rates-v2-get ACTION: GET /v2/rates METHOD: GET PATH: /v2/rates URL: https://api.innovapp-soft.com/v2/rates AUTH: Bearer API Key DESCRIPTION: Devuelve tasas V2 globales o por pais con secciones normalizadas, variacion y recursos de imagen. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json ### Query parameters - country | required=No | type=string | description=country=GLOBAL devuelve comparativas globales contra USD. country=CU devuelve las fuentes cubanas. Otros paises devuelven tasas contra la moneda local del pais. | example=CU - scope | required=No | type=string | description=Fuerza la vista devuelta: global, cuba, country, all u overview. Alias aceptado: view. Si se omite se deduce de country. | example=cuba - section | required=No | type=string | description=Filtra una fuente/seccion especifica. Ejemplos: innovapp, eltoque, bcc_segment1, global, usd_value. | example=eltoque - full | required=No | type=string | description=Usa 1 para incluir el snapshot normalizado completo ademas de las secciones visibles. | example=1 ### cURL ```bash curl -X GET 'https://api.innovapp-soft.com/v2/rates?country=CU' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/rates?country=CU', { method: 'GET', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json' } }) .then(r => r.json()) .then(res => { const sections = res.data.sections || []; const eltoque = sections.find(s => s.id === 'eltoque'); console.log(res.data.date, eltoque && eltoque.rates); }); ``` ### Esquema de respuesta verificado ```json { "success": true, "code": "ok", "message": "OK", "data": { "status": "true", "message": "ok", "version": "2", "scope": "cuba", "base": "USD", "date": "YYYY-MM-DD", "updated_at": "YYYY-MM-DD HH:MM:SS", "generated_at": "YYYY-MM-DD HH:MM:SS", "country": { "code": "CU", "name": "Cuba", "currency": "CUP", "supported": true }, "countries": [ { "code": "GLOBAL", "name": "Global", "currency": "USD", "supported": true }, { "code": "CU", "name": "Cuba", "currency": "CUP", "supported": true } ], "history": { "today": { "date": "YYYY-MM-DD", "updated_at": "YYYY-MM-DD HH:MM:SS" }, "yesterday": { "date": "YYYY-MM-DD", "updated_at": "YYYY-MM-DD HH:MM:SS" }, "week": { "date": "YYYY-MM-DD", "updated_at": "YYYY-MM-DD HH:MM:SS" } }, "sections": [ { "id": "eltoque", "title": "elToque", "base": "CUP", "unit": "CUP per 1 unit", "rates": [ { "code": "CUP", "name": "Cuban Peso", "country": "Cuba", "type": "fiat", "value": "dynamic", "yesterday": "dynamic", "week": "dynamic", "change": "dynamic", "change_week": "dynamic", "source": "cu_eltoque_trmi", "image_url": "https://innovapp-soft.com/assets/img/tasas/CUP.png", "image_png": "https://innovapp-soft.com/assets/img/tasas/CUP.png", "image_jpg": "https://innovapp-soft.com/assets/img/tasas/CUP.jpg", "image_fallback": "CU" } ] } ] }, "error": [], "time": { "datetime": "2026-09-13T10:15:00-04:00", "date": "2026-09-13", "time": "10:15:00", "timezone": "America/Kentucky/Louisville", "offset": "-04:00", "timestamp": 1789222500 } } ``` ### Errores específicos - HTTP 401 | 401 API key ausente o invalida ```json { "success": false, "code": 10023, "message": "Unauthorized", "data": [], "error": [] } ``` - HTTP 405 | 405 Metodo no permitido ```json { "success": false, "code": 40501, "message": "Method not allowed", "data": [], "error": { "details": "POST" } } ``` - HTTP 200 | 200 sin snapshot de tasas disponible ```json { "success": false, "code": "rates_snapshot_unavailable", "message": "rates_snapshot_unavailable", "data": { "status": "false", "message": "rates_snapshot_unavailable", "version": "2", "scope": "global", "base": "USD", "date": "YYYY-MM-DD", "updated_at": null, "country": { "code": "GLOBAL", "name": "Global", "currency": "USD", "supported": true }, "countries": [], "history": [], "sections": [] }, "error": [] } ``` ### Notas - Devuelve tasas globales y por pais en secciones normalizadas. Cuba incluye fuentes locales como InnovappSoft KeyCoin, elToque y segmentos BCC cuando hay data. - /v2/tasas es un alias compatible de /v2/rates. - data.sections es la parte recomendada para UI: cada seccion trae rates con value, yesterday, week, change y change_week. - Solo acepta GET. Cualquier otro metodo responde 405 con code 40501. - Paises soportados: GLOBAL, US, CU, MX, CO, BR, VE, UY, PE, GY, CA, CH, EU. Un valor no soportado, incluido country=auto, devuelve el scope global. - Las tasas salen del snapshot diario de KeyPay. No es un feed en tiempo real: lee siempre data.date y data.updated_at. - base es siempre USD y KCOIN vale 1 USD dentro del mapa global. - change y change_week son diferencias absolutas, no porcentajes. - Si falta el dato de ayer se reutiliza el de hoy, y si falta el de la semana se reutiliza el de ayer. En ese caso change o change_week salen en 0. - CUP dentro del mapa global se resuelve con la fuente cubana mas alta disponible, elToque o los segmentos del BCC. El origen exacto queda en sources_by_code.CUP cuando pides full=1. - Secciones de Cuba: innovapp, eltoque, bcc_segment1, bcc_segment2 y bcc_segment3. Secciones globales: global y usd_value. Un pais distinto de CU y GLOBAL devuelve una sola seccion country_local. - Una seccion solo aparece si tiene tasas. No asumas un numero fijo de elementos en sections: recorrelo buscando por id. - Los codigos se normalizan: USDT, TETHER y TRC20 llegan como USDT_TRC20, y KC o KEYCOIN llegan como KCOIN. - No cachees mas de unos minutos en el cliente y usa data.date como clave de cache. - Este endpoint no esta incluido en el Sandbox. Pruebalo con tu dk_live contra produccion: es de solo lectura y no mueve saldo. --- # Grupo: Mercado V2 Catalogo, carrito e historial de pedidos del Mercado de KeyPay, sobre la misma cuenta KeyPay enlazada a tu API key. Flujo recomendado: locations y categories para conocer los filtros, products para listar, detail antes de anadir, y despues el carrito. ## Endpoint: POST /v2/marketplace/status ID: marketplace-v2-status ACTION: Estado del Mercado METHOD: POST PATH: /v2/marketplace/status URL: https://api.innovapp-soft.com/v2/marketplace/status AUTH: Bearer API Key DESCRIPTION: Devuelve si el Mercado esta activo para la cuenta, las comisiones vigentes, las provincias, las categorias, el carrito actual, la direccion y el perfil de facturacion guardados, las tarifas de entrega y el credito disponible. Es la llamada de arranque. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - language | required=No | type=string | description=Idioma de los textos de la respuesta: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v2/marketplace/status' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"language":"es"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/marketplace/status', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "language": "es" }) }).then(r => r.json()).then(console.log); ``` ### Esquema de respuesta verificado ```json { "success": true, "code": "marketplace.status.ok", "message": "OK", "data": { "api_version": 2, "enabled": true, "purchases_enabled": true, "currency": "USD", "fee": "dynamic", "price_includes_fee": false, "fee_basis": "products_subtotal", "locations": "dynamic", "categories": "dynamic", "cart": "dynamic", "address": "dynamic", "billing_profile": "dynamic", "delivery_rates": "dynamic", "marketplace_faq": "dynamic", "credito": "dynamic" }, "error": [], "time": "2026-09-13T10:15:00-04:00" } ``` ### Errores específicos - HTTP 401 | 401 API key ausente o invalida ```json { "success": false, "code": 10023, "message": "Unauthorized", "data": [], "error": [] } ``` - HTTP 422 | 422 Campo requerido o invalido ```json { "success": false, "code": 48003, "message": "Required field is missing: product_token", "data": [], "error": { "service": "marketplace", "action": "cart-add" } } ``` - HTTP 403 | 403 La cuenta no tiene acceso al Mercado ```json { "success": false, "code": "marketplace.status.failed", "message": "No tienes acceso al Mercado.", "data": [], "error": { "service": "marketplace", "action": "status" } } ``` - HTTP 503 | 503 Servicio temporalmente no disponible ```json { "success": false, "code": "marketplace.products.failed", "message": "Marketplace is temporarily unavailable.", "data": [], "error": { "service": "marketplace", "action": "products" } } ``` - HTTP 502 | 502 No se pudo contactar con KeyPay ```json { "success": false, "code": 47020, "message": "The Mercado service is temporarily unavailable.", "data": [], "error": [] } ``` ### Notas - No envies userIdentifier: la cuenta KeyPay sale de la API key autenticada. - Todas las rutas son POST con cuerpo JSON, incluidas las de solo lectura. - product_token va firmado y atado al province_id y al localities_key con los que pediste el catalogo. Caduca a los 30 minutos: no lo guardes ni lo compartas entre usuarios. - Sin localities_key el catalogo es de toda la provincia y el detalle no puede confirmar existencias en una bodega concreta. Manda siempre el municipio si lo conoces. - El carrito admite hasta 30 productos distintos y 20 unidades por producto. Muchos productos tienen ademas un minimo por bodega que el servidor aplica solo. - Los precios llegan sin la comision: price_includes_fee es false y fee_basis es products_subtotal. Calcula el total con los importes que devuelve el carrito, no sumando precios. - orders y order-get solo devuelven pedidos del Mercado, los que empiezan por MKT-. Los pedidos de Amazon no forman parte de esta API. - Crear el pedido no esta disponible en esta API todavia. Puedes montar el carrito, pero el cobro se cierra desde la app de KeyPay. - Antes de poder pedir hacen falta una direccion de envio y un perfil de facturacion guardados. Usa la familia de direcciones. - Las imagenes llegan como https://api.innovapp-soft.com/v2/media/. Usalas tal cual en tu : son publicas, no piden Authorization y se cachean una semana. No intentes construir el token ni deducir la URL de origen. - El producto trae el nombre en name y las traducciones en translations.es y translations.en. Si pides language=es, name y description ya vienen traducidos. - Cada producto pertenece a una bodega y esa bodega tiene un pedido minimo. El carrito devuelve bodega_groups y minimum_failures con lo que falta para alcanzarlo. - Disponible en el Sandbox: pon /sandbox delante de la ruta y usa una clave dk_test_. El catalogo de prueba tiene dos productos en Villa Clara (province_id 5, localities_key 77); llama antes a products para obtener un product_token valido. - En el Sandbox orders siempre viene vacio y order-get responde 404, porque el pedido no se puede crear desde esta API. --- ## Endpoint: POST /v2/marketplace/locations ID: marketplace-v2-locations ACTION: Provincias y municipios METHOD: POST PATH: /v2/marketplace/locations URL: https://api.innovapp-soft.com/v2/marketplace/locations AUTH: Bearer API Key DESCRIPTION: Lista las provincias con sus municipios. De aqui salen province_id y localities_key, que son los que fijan el contexto de precios y existencias del catalogo. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - language | required=No | type=string | description=Idioma de los textos de la respuesta: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v2/marketplace/locations' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"language":"es"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/marketplace/locations', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "language": "es" }) }).then(r => r.json()).then(console.log); ``` ### Esquema de respuesta verificado ```json { "success": true, "code": "marketplace.locations.ok", "message": "OK", "data": { "locations": [ { "province_id": 5, "province": "La Habana", "municipalities": [ { "localities_key": 512, "municipality": "Playa" } ] } ] }, "error": [], "time": "2026-09-13T10:15:00-04:00" } ``` ### Errores específicos - HTTP 401 | 401 API key ausente o invalida ```json { "success": false, "code": 10023, "message": "Unauthorized", "data": [], "error": [] } ``` - HTTP 422 | 422 Campo requerido o invalido ```json { "success": false, "code": 48003, "message": "Required field is missing: product_token", "data": [], "error": { "service": "marketplace", "action": "cart-add" } } ``` - HTTP 403 | 403 La cuenta no tiene acceso al Mercado ```json { "success": false, "code": "marketplace.status.failed", "message": "No tienes acceso al Mercado.", "data": [], "error": { "service": "marketplace", "action": "status" } } ``` - HTTP 503 | 503 Servicio temporalmente no disponible ```json { "success": false, "code": "marketplace.products.failed", "message": "Marketplace is temporarily unavailable.", "data": [], "error": { "service": "marketplace", "action": "products" } } ``` - HTTP 502 | 502 No se pudo contactar con KeyPay ```json { "success": false, "code": 47020, "message": "The Mercado service is temporarily unavailable.", "data": [], "error": [] } ``` ### Notas - No envies userIdentifier: la cuenta KeyPay sale de la API key autenticada. - Todas las rutas son POST con cuerpo JSON, incluidas las de solo lectura. - product_token va firmado y atado al province_id y al localities_key con los que pediste el catalogo. Caduca a los 30 minutos: no lo guardes ni lo compartas entre usuarios. - Sin localities_key el catalogo es de toda la provincia y el detalle no puede confirmar existencias en una bodega concreta. Manda siempre el municipio si lo conoces. - El carrito admite hasta 30 productos distintos y 20 unidades por producto. Muchos productos tienen ademas un minimo por bodega que el servidor aplica solo. - Los precios llegan sin la comision: price_includes_fee es false y fee_basis es products_subtotal. Calcula el total con los importes que devuelve el carrito, no sumando precios. - orders y order-get solo devuelven pedidos del Mercado, los que empiezan por MKT-. Los pedidos de Amazon no forman parte de esta API. - Crear el pedido no esta disponible en esta API todavia. Puedes montar el carrito, pero el cobro se cierra desde la app de KeyPay. - Antes de poder pedir hacen falta una direccion de envio y un perfil de facturacion guardados. Usa la familia de direcciones. - Las imagenes llegan como https://api.innovapp-soft.com/v2/media/. Usalas tal cual en tu : son publicas, no piden Authorization y se cachean una semana. No intentes construir el token ni deducir la URL de origen. - El producto trae el nombre en name y las traducciones en translations.es y translations.en. Si pides language=es, name y description ya vienen traducidos. - Cada producto pertenece a una bodega y esa bodega tiene un pedido minimo. El carrito devuelve bodega_groups y minimum_failures con lo que falta para alcanzarlo. - Disponible en el Sandbox: pon /sandbox delante de la ruta y usa una clave dk_test_. El catalogo de prueba tiene dos productos en Villa Clara (province_id 5, localities_key 77); llama antes a products para obtener un product_token valido. - En el Sandbox orders siempre viene vacio y order-get responde 404, porque el pedido no se puede crear desde esta API. --- ## Endpoint: POST /v2/marketplace/categories ID: marketplace-v2-categories ACTION: Categorias METHOD: POST PATH: /v2/marketplace/categories URL: https://api.innovapp-soft.com/v2/marketplace/categories AUTH: Bearer API Key DESCRIPTION: Lista las categorias del Mercado con sus clasificadores. Usa category_id y classifier_id en products. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - language | required=No | type=string | description=Idioma de los textos de la respuesta: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v2/marketplace/categories' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"language":"es"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/marketplace/categories', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "language": "es" }) }).then(r => r.json()).then(console.log); ``` ### Esquema de respuesta verificado ```json { "success": true, "code": "marketplace.categories.ok", "message": "OK", "data": { "categories": [ { "category_id": 18, "name": "dynamic", "classifiers": "dynamic" } ] }, "error": [], "time": "2026-09-13T10:15:00-04:00" } ``` ### Errores específicos - HTTP 401 | 401 API key ausente o invalida ```json { "success": false, "code": 10023, "message": "Unauthorized", "data": [], "error": [] } ``` - HTTP 422 | 422 Campo requerido o invalido ```json { "success": false, "code": 48003, "message": "Required field is missing: product_token", "data": [], "error": { "service": "marketplace", "action": "cart-add" } } ``` - HTTP 403 | 403 La cuenta no tiene acceso al Mercado ```json { "success": false, "code": "marketplace.status.failed", "message": "No tienes acceso al Mercado.", "data": [], "error": { "service": "marketplace", "action": "status" } } ``` - HTTP 503 | 503 Servicio temporalmente no disponible ```json { "success": false, "code": "marketplace.products.failed", "message": "Marketplace is temporarily unavailable.", "data": [], "error": { "service": "marketplace", "action": "products" } } ``` - HTTP 502 | 502 No se pudo contactar con KeyPay ```json { "success": false, "code": 47020, "message": "The Mercado service is temporarily unavailable.", "data": [], "error": [] } ``` ### Notas - No envies userIdentifier: la cuenta KeyPay sale de la API key autenticada. - Todas las rutas son POST con cuerpo JSON, incluidas las de solo lectura. - product_token va firmado y atado al province_id y al localities_key con los que pediste el catalogo. Caduca a los 30 minutos: no lo guardes ni lo compartas entre usuarios. - Sin localities_key el catalogo es de toda la provincia y el detalle no puede confirmar existencias en una bodega concreta. Manda siempre el municipio si lo conoces. - El carrito admite hasta 30 productos distintos y 20 unidades por producto. Muchos productos tienen ademas un minimo por bodega que el servidor aplica solo. - Los precios llegan sin la comision: price_includes_fee es false y fee_basis es products_subtotal. Calcula el total con los importes que devuelve el carrito, no sumando precios. - orders y order-get solo devuelven pedidos del Mercado, los que empiezan por MKT-. Los pedidos de Amazon no forman parte de esta API. - Crear el pedido no esta disponible en esta API todavia. Puedes montar el carrito, pero el cobro se cierra desde la app de KeyPay. - Antes de poder pedir hacen falta una direccion de envio y un perfil de facturacion guardados. Usa la familia de direcciones. - Las imagenes llegan como https://api.innovapp-soft.com/v2/media/. Usalas tal cual en tu : son publicas, no piden Authorization y se cachean una semana. No intentes construir el token ni deducir la URL de origen. - El producto trae el nombre en name y las traducciones en translations.es y translations.en. Si pides language=es, name y description ya vienen traducidos. - Cada producto pertenece a una bodega y esa bodega tiene un pedido minimo. El carrito devuelve bodega_groups y minimum_failures con lo que falta para alcanzarlo. - Disponible en el Sandbox: pon /sandbox delante de la ruta y usa una clave dk_test_. El catalogo de prueba tiene dos productos en Villa Clara (province_id 5, localities_key 77); llama antes a products para obtener un product_token valido. - En el Sandbox orders siempre viene vacio y order-get responde 404, porque el pedido no se puede crear desde esta API. --- ## Endpoint: POST /v2/marketplace/products ID: marketplace-v2-products ACTION: Listar productos METHOD: POST PATH: /v2/marketplace/products URL: https://api.innovapp-soft.com/v2/marketplace/products AUTH: Bearer API Key DESCRIPTION: Lista los productos disponibles para una provincia y municipio, con filtros de categoria, texto y orden. Cada producto trae un token firmado que es lo unico que aceptan detail y cart-add. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - province_id | required=No | type=integer | description=Id de la provincia devuelto por locations. Por defecto 5. | example=5 - localities_key | required=No | type=integer | description=Id del municipio devuelto por locations. Sin el, el catalogo es de toda la provincia y el detalle no puede confirmar existencias exactas. | example=512 - category_id | required=No | type=integer | description=Filtra por categoria. Usa el id devuelto por categories. | example=18 - classifier_id | required=No | type=integer | description=Filtra por subcategoria o clasificador dentro de la categoria. | example=204 - q | required=No | type=string | description=Texto de busqueda. Maximo 80 caracteres. | example=arroz - page | required=No | type=integer | description=Pagina solicitada. Empieza en 1. | example=1 - page_size | required=No | type=integer | description=Productos por pagina, entre 1 y 48. Por defecto 24. | example=24 - sort | required=No | type=string | description=Orden del listado: relevance, price_asc, price_desc o newest. | example=price_asc - language | required=No | type=string | description=Idioma de los textos de la respuesta: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v2/marketplace/products' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"province_id":5,"localities_key":512,"page":1,"language":"es"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/marketplace/products', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "province_id": 5, "localities_key": 512, "page": 1, "language": "es" }) }).then(r => r.json()).then(console.log); ``` ### Esquema de respuesta verificado ```json { "success": true, "code": "marketplace.products.ok", "message": "OK", "data": { "filters": { "province_id": 5, "province": "dynamic", "localities_key": 77, "municipality": "dynamic", "category_id": 0, "classifier_id": 0, "language": "es", "q": "", "sort": "relevance" }, "pagination": { "page": 1, "page_size": 24, "total": "dynamic", "pages": "dynamic", "has_more": "dynamic" }, "products": [ { "id": 393121, "name": "dynamic", "language": "es", "translations": { "es": { "name": "dynamic", "description": "dynamic" }, "en": { "name": "dynamic", "description": "dynamic" } }, "description": "dynamic", "description_available": true, "price": "dynamic", "old_price": null, "price_includes_fee": false, "image": "https://api.innovapp-soft.com/v2/media/m1_...", "image_large": "https://api.innovapp-soft.com/v2/media/m1_...", "images": [ "https://api.innovapp-soft.com/v2/media/m1_..." ], "thumbnails": [ "https://api.innovapp-soft.com/v2/media/m1_..." ], "gallery": [ { "id": "dynamic", "main": true, "display_order": 1, "thumbnail": "https://api.innovapp-soft.com/v2/media/m1_...", "middle": "https://api.innovapp-soft.com/v2/media/m1_..." } ], "category": "dynamic", "brand": "dynamic", "available": true, "available_quantity": "dynamic", "availability": { "available": true, "status": "available", "message": "dynamic", "available_quantity": "dynamic", "catalog_active": true, "provider_active": true, "bodega_active": true, "preorder": null, "distribution_provinces": [ { "province_id": 5, "province": "dynamic" } ] }, "bodega": "dynamic", "bodega_id": "dynamic", "bodega_assignment": "assigned", "bodega_details": "dynamic", "bodega_minimum": { "amount": "dynamic", "currency": "USD", "amounts": "dynamic" }, "provider_id": "dynamic", "distributor_id": "dynamic", "shipping_group_key": "bodega:67", "quantity_limits": { "minimum": 1, "maximum_configured": "dynamic", "maximum_current": "dynamic" }, "is_bundle": false, "bundle": "dynamic", "has_purchase_options": false, "purchase_options": [ { "product_id": 393121, "package_units": 1, "selected": true, "name": "dynamic", "price": "dynamic", "available": true, "available_quantity": "dynamic", "status": "available", "image": "https://api.innovapp-soft.com/v2/media/m1_...", "component_product_ids": [] } ], "is_dairy": false, "requires_refrigeration": false, "weight": { "grams": "dynamic", "kilograms": "dynamic", "source": "OtherInfo.Weight" }, "logistics": "dynamic", "token": "sb_eyJwIjozOTMxMjEsImMiOjUsImwiOjc3fQ" } ], "fee": "dynamic", "price_includes_fee": false, "transport": "dynamic" }, "error": [], "time": "2026-09-13T10:15:00-04:00" } ``` ### Errores específicos - HTTP 401 | 401 API key ausente o invalida ```json { "success": false, "code": 10023, "message": "Unauthorized", "data": [], "error": [] } ``` - HTTP 422 | 422 Campo requerido o invalido ```json { "success": false, "code": 48003, "message": "Required field is missing: product_token", "data": [], "error": { "service": "marketplace", "action": "cart-add" } } ``` - HTTP 403 | 403 La cuenta no tiene acceso al Mercado ```json { "success": false, "code": "marketplace.status.failed", "message": "No tienes acceso al Mercado.", "data": [], "error": { "service": "marketplace", "action": "status" } } ``` - HTTP 503 | 503 Servicio temporalmente no disponible ```json { "success": false, "code": "marketplace.products.failed", "message": "Marketplace is temporarily unavailable.", "data": [], "error": { "service": "marketplace", "action": "products" } } ``` - HTTP 502 | 502 No se pudo contactar con KeyPay ```json { "success": false, "code": 47020, "message": "The Mercado service is temporarily unavailable.", "data": [], "error": [] } ``` ### Notas - No envies userIdentifier: la cuenta KeyPay sale de la API key autenticada. - Todas las rutas son POST con cuerpo JSON, incluidas las de solo lectura. - product_token va firmado y atado al province_id y al localities_key con los que pediste el catalogo. Caduca a los 30 minutos: no lo guardes ni lo compartas entre usuarios. - Sin localities_key el catalogo es de toda la provincia y el detalle no puede confirmar existencias en una bodega concreta. Manda siempre el municipio si lo conoces. - El carrito admite hasta 30 productos distintos y 20 unidades por producto. Muchos productos tienen ademas un minimo por bodega que el servidor aplica solo. - Los precios llegan sin la comision: price_includes_fee es false y fee_basis es products_subtotal. Calcula el total con los importes que devuelve el carrito, no sumando precios. - orders y order-get solo devuelven pedidos del Mercado, los que empiezan por MKT-. Los pedidos de Amazon no forman parte de esta API. - Crear el pedido no esta disponible en esta API todavia. Puedes montar el carrito, pero el cobro se cierra desde la app de KeyPay. - Antes de poder pedir hacen falta una direccion de envio y un perfil de facturacion guardados. Usa la familia de direcciones. - Las imagenes llegan como https://api.innovapp-soft.com/v2/media/. Usalas tal cual en tu : son publicas, no piden Authorization y se cachean una semana. No intentes construir el token ni deducir la URL de origen. - El producto trae el nombre en name y las traducciones en translations.es y translations.en. Si pides language=es, name y description ya vienen traducidos. - Cada producto pertenece a una bodega y esa bodega tiene un pedido minimo. El carrito devuelve bodega_groups y minimum_failures con lo que falta para alcanzarlo. - Disponible en el Sandbox: pon /sandbox delante de la ruta y usa una clave dk_test_. El catalogo de prueba tiene dos productos en Villa Clara (province_id 5, localities_key 77); llama antes a products para obtener un product_token valido. - En el Sandbox orders siempre viene vacio y order-get responde 404, porque el pedido no se puede crear desde esta API. --- ## Endpoint: POST /v2/marketplace/detail ID: marketplace-v2-detail ACTION: Detalle de un producto METHOD: POST PATH: /v2/marketplace/detail URL: https://api.innovapp-soft.com/v2/marketplace/detail AUTH: Bearer API Key DESCRIPTION: Devuelve la ficha completa de un producto a partir de su token: descripcion, imagenes, variantes de compra, minimos por bodega y disponibilidad confirmada. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - product_token | required=Si | type=string | description=Token firmado del producto devuelto por products. Caduca a los 30 minutos y va atado al contexto de provincia y municipio con el que se pidio. | example=eyJwIjoxMiwiYyI6NX0.Zm9vYmFy - selected_product_id | required=No | type=integer | description=Id de la variante concreta dentro de purchase_options. Por defecto, el producto del token. | example=90312 - language | required=No | type=string | description=Idioma de los textos de la respuesta: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v2/marketplace/detail' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"product_token":"eyJwIjoxMiwiYyI6NX0.Zm9vYmFy","language":"es"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/marketplace/detail', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "product_token": "eyJwIjoxMiwiYyI6NX0.Zm9vYmFy", "language": "es" }) }).then(r => r.json()).then(console.log); ``` ### Esquema de respuesta verificado ```json { "success": true, "code": "marketplace.detail.ok", "message": "OK", "data": { "product": { "id": 393121, "name": "dynamic", "language": "es", "translations": { "es": { "name": "dynamic", "description": "dynamic" }, "en": { "name": "dynamic", "description": "dynamic" } }, "description": "dynamic", "description_available": true, "price": "dynamic", "old_price": null, "price_includes_fee": false, "image": "https://api.innovapp-soft.com/v2/media/m1_...", "image_large": "https://api.innovapp-soft.com/v2/media/m1_...", "images": [ "https://api.innovapp-soft.com/v2/media/m1_..." ], "thumbnails": [ "https://api.innovapp-soft.com/v2/media/m1_..." ], "gallery": [ { "id": "dynamic", "main": true, "display_order": 1, "thumbnail": "https://api.innovapp-soft.com/v2/media/m1_...", "middle": "https://api.innovapp-soft.com/v2/media/m1_..." } ], "category": "dynamic", "brand": "dynamic", "available": true, "available_quantity": "dynamic", "availability": { "available": true, "status": "available", "message": "dynamic", "available_quantity": "dynamic", "catalog_active": true, "provider_active": true, "bodega_active": true, "preorder": null, "distribution_provinces": [ { "province_id": 5, "province": "dynamic" } ] }, "bodega": "dynamic", "bodega_id": "dynamic", "bodega_assignment": "assigned", "bodega_details": "dynamic", "bodega_minimum": { "amount": "dynamic", "currency": "USD", "amounts": "dynamic" }, "provider_id": "dynamic", "distributor_id": "dynamic", "shipping_group_key": "bodega:67", "quantity_limits": { "minimum": 1, "maximum_configured": "dynamic", "maximum_current": "dynamic" }, "is_bundle": false, "bundle": "dynamic", "has_purchase_options": false, "purchase_options": [ { "product_id": 393121, "package_units": 1, "selected": true, "name": "dynamic", "price": "dynamic", "available": true, "available_quantity": "dynamic", "status": "available", "image": "https://api.innovapp-soft.com/v2/media/m1_...", "component_product_ids": [] } ], "is_dairy": false, "requires_refrigeration": false, "weight": { "grams": "dynamic", "kilograms": "dynamic", "source": "OtherInfo.Weight" }, "logistics": "dynamic", "token": "sb_eyJwIjozOTMxMjEsImMiOjUsImwiOjc3fQ", "context": { "province_id": 5, "localities_key": 77 } } }, "error": [], "time": "2026-09-13T10:15:00-04:00" } ``` ### Errores específicos - HTTP 401 | 401 API key ausente o invalida ```json { "success": false, "code": 10023, "message": "Unauthorized", "data": [], "error": [] } ``` - HTTP 422 | 422 Campo requerido o invalido ```json { "success": false, "code": 48003, "message": "Required field is missing: product_token", "data": [], "error": { "service": "marketplace", "action": "cart-add" } } ``` - HTTP 403 | 403 La cuenta no tiene acceso al Mercado ```json { "success": false, "code": "marketplace.status.failed", "message": "No tienes acceso al Mercado.", "data": [], "error": { "service": "marketplace", "action": "status" } } ``` - HTTP 503 | 503 Servicio temporalmente no disponible ```json { "success": false, "code": "marketplace.products.failed", "message": "Marketplace is temporarily unavailable.", "data": [], "error": { "service": "marketplace", "action": "products" } } ``` - HTTP 502 | 502 No se pudo contactar con KeyPay ```json { "success": false, "code": 47020, "message": "The Mercado service is temporarily unavailable.", "data": [], "error": [] } ``` ### Notas - No envies userIdentifier: la cuenta KeyPay sale de la API key autenticada. - Todas las rutas son POST con cuerpo JSON, incluidas las de solo lectura. - product_token va firmado y atado al province_id y al localities_key con los que pediste el catalogo. Caduca a los 30 minutos: no lo guardes ni lo compartas entre usuarios. - Sin localities_key el catalogo es de toda la provincia y el detalle no puede confirmar existencias en una bodega concreta. Manda siempre el municipio si lo conoces. - El carrito admite hasta 30 productos distintos y 20 unidades por producto. Muchos productos tienen ademas un minimo por bodega que el servidor aplica solo. - Los precios llegan sin la comision: price_includes_fee es false y fee_basis es products_subtotal. Calcula el total con los importes que devuelve el carrito, no sumando precios. - orders y order-get solo devuelven pedidos del Mercado, los que empiezan por MKT-. Los pedidos de Amazon no forman parte de esta API. - Crear el pedido no esta disponible en esta API todavia. Puedes montar el carrito, pero el cobro se cierra desde la app de KeyPay. - Antes de poder pedir hacen falta una direccion de envio y un perfil de facturacion guardados. Usa la familia de direcciones. - Las imagenes llegan como https://api.innovapp-soft.com/v2/media/. Usalas tal cual en tu : son publicas, no piden Authorization y se cachean una semana. No intentes construir el token ni deducir la URL de origen. - El producto trae el nombre en name y las traducciones en translations.es y translations.en. Si pides language=es, name y description ya vienen traducidos. - Cada producto pertenece a una bodega y esa bodega tiene un pedido minimo. El carrito devuelve bodega_groups y minimum_failures con lo que falta para alcanzarlo. - Disponible en el Sandbox: pon /sandbox delante de la ruta y usa una clave dk_test_. El catalogo de prueba tiene dos productos en Villa Clara (province_id 5, localities_key 77); llama antes a products para obtener un product_token valido. - En el Sandbox orders siempre viene vacio y order-get responde 404, porque el pedido no se puede crear desde esta API. --- ## Endpoint: POST /v2/marketplace/cart ID: marketplace-v2-cart ACTION: Ver el carrito METHOD: POST PATH: /v2/marketplace/cart URL: https://api.innovapp-soft.com/v2/marketplace/cart AUTH: Bearer API Key DESCRIPTION: Devuelve el carrito actual de la cuenta con sus lineas, subtotales, comision y avisos de logistica. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - language | required=No | type=string | description=Idioma de los textos de la respuesta: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v2/marketplace/cart' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"language":"es"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/marketplace/cart', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "language": "es" }) }).then(r => r.json()).then(console.log); ``` ### Esquema de respuesta verificado ```json { "success": true, "code": "marketplace.cart.ok", "message": "OK", "data": { "cart": { "items": [ "dynamic" ], "products_subtotal": "dynamic", "fee": "dynamic" } }, "error": [], "time": "2026-09-13T10:15:00-04:00" } ``` ### Errores específicos - HTTP 401 | 401 API key ausente o invalida ```json { "success": false, "code": 10023, "message": "Unauthorized", "data": [], "error": [] } ``` - HTTP 422 | 422 Campo requerido o invalido ```json { "success": false, "code": 48003, "message": "Required field is missing: product_token", "data": [], "error": { "service": "marketplace", "action": "cart-add" } } ``` - HTTP 403 | 403 La cuenta no tiene acceso al Mercado ```json { "success": false, "code": "marketplace.status.failed", "message": "No tienes acceso al Mercado.", "data": [], "error": { "service": "marketplace", "action": "status" } } ``` - HTTP 503 | 503 Servicio temporalmente no disponible ```json { "success": false, "code": "marketplace.products.failed", "message": "Marketplace is temporarily unavailable.", "data": [], "error": { "service": "marketplace", "action": "products" } } ``` - HTTP 502 | 502 No se pudo contactar con KeyPay ```json { "success": false, "code": 47020, "message": "The Mercado service is temporarily unavailable.", "data": [], "error": [] } ``` ### Notas - No envies userIdentifier: la cuenta KeyPay sale de la API key autenticada. - Todas las rutas son POST con cuerpo JSON, incluidas las de solo lectura. - product_token va firmado y atado al province_id y al localities_key con los que pediste el catalogo. Caduca a los 30 minutos: no lo guardes ni lo compartas entre usuarios. - Sin localities_key el catalogo es de toda la provincia y el detalle no puede confirmar existencias en una bodega concreta. Manda siempre el municipio si lo conoces. - El carrito admite hasta 30 productos distintos y 20 unidades por producto. Muchos productos tienen ademas un minimo por bodega que el servidor aplica solo. - Los precios llegan sin la comision: price_includes_fee es false y fee_basis es products_subtotal. Calcula el total con los importes que devuelve el carrito, no sumando precios. - orders y order-get solo devuelven pedidos del Mercado, los que empiezan por MKT-. Los pedidos de Amazon no forman parte de esta API. - Crear el pedido no esta disponible en esta API todavia. Puedes montar el carrito, pero el cobro se cierra desde la app de KeyPay. - Antes de poder pedir hacen falta una direccion de envio y un perfil de facturacion guardados. Usa la familia de direcciones. - Las imagenes llegan como https://api.innovapp-soft.com/v2/media/. Usalas tal cual en tu : son publicas, no piden Authorization y se cachean una semana. No intentes construir el token ni deducir la URL de origen. - El producto trae el nombre en name y las traducciones en translations.es y translations.en. Si pides language=es, name y description ya vienen traducidos. - Cada producto pertenece a una bodega y esa bodega tiene un pedido minimo. El carrito devuelve bodega_groups y minimum_failures con lo que falta para alcanzarlo. - Disponible en el Sandbox: pon /sandbox delante de la ruta y usa una clave dk_test_. El catalogo de prueba tiene dos productos en Villa Clara (province_id 5, localities_key 77); llama antes a products para obtener un product_token valido. - En el Sandbox orders siempre viene vacio y order-get responde 404, porque el pedido no se puede crear desde esta API. --- ## Endpoint: POST /v2/marketplace/cart-add ID: marketplace-v2-cart-add ACTION: Anadir al carrito METHOD: POST PATH: /v2/marketplace/cart-add URL: https://api.innovapp-soft.com/v2/marketplace/cart-add AUTH: Bearer API Key DESCRIPTION: Anade un producto al carrito usando su token. Si el producto ya estaba, suma la cantidad. El servidor recorta al minimo y al maximo del producto y rechaza los que no esten disponibles. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - product_token | required=Si | type=string | description=Token firmado del producto devuelto por products. Caduca a los 30 minutos y va atado al contexto de provincia y municipio con el que se pidio. | example=eyJwIjoxMiwiYyI6NX0.Zm9vYmFy - quantity | required=No | type=integer | description=Cantidad, entre 1 y 20. El servidor la ajusta al minimo y al maximo del producto. | example=2 - language | required=No | type=string | description=Idioma de los textos de la respuesta: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v2/marketplace/cart-add' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"product_token":"eyJwIjoxMiwiYyI6NX0.Zm9vYmFy","quantity":2,"language":"es"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/marketplace/cart-add', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "product_token": "eyJwIjoxMiwiYyI6NX0.Zm9vYmFy", "quantity": 2, "language": "es" }) }).then(r => r.json()).then(console.log); ``` ### Esquema de respuesta verificado ```json { "success": true, "code": "marketplace.cart-add.ok", "message": "OK", "data": { "cart": "dynamic" }, "error": [], "time": "2026-09-13T10:15:00-04:00" } ``` ### Errores específicos - HTTP 401 | 401 API key ausente o invalida ```json { "success": false, "code": 10023, "message": "Unauthorized", "data": [], "error": [] } ``` - HTTP 422 | 422 Campo requerido o invalido ```json { "success": false, "code": 48003, "message": "Required field is missing: product_token", "data": [], "error": { "service": "marketplace", "action": "cart-add" } } ``` - HTTP 403 | 403 La cuenta no tiene acceso al Mercado ```json { "success": false, "code": "marketplace.status.failed", "message": "No tienes acceso al Mercado.", "data": [], "error": { "service": "marketplace", "action": "status" } } ``` - HTTP 503 | 503 Servicio temporalmente no disponible ```json { "success": false, "code": "marketplace.products.failed", "message": "Marketplace is temporarily unavailable.", "data": [], "error": { "service": "marketplace", "action": "products" } } ``` - HTTP 502 | 502 No se pudo contactar con KeyPay ```json { "success": false, "code": 47020, "message": "The Mercado service is temporarily unavailable.", "data": [], "error": [] } ``` ### Notas - No envies userIdentifier: la cuenta KeyPay sale de la API key autenticada. - Todas las rutas son POST con cuerpo JSON, incluidas las de solo lectura. - product_token va firmado y atado al province_id y al localities_key con los que pediste el catalogo. Caduca a los 30 minutos: no lo guardes ni lo compartas entre usuarios. - Sin localities_key el catalogo es de toda la provincia y el detalle no puede confirmar existencias en una bodega concreta. Manda siempre el municipio si lo conoces. - El carrito admite hasta 30 productos distintos y 20 unidades por producto. Muchos productos tienen ademas un minimo por bodega que el servidor aplica solo. - Los precios llegan sin la comision: price_includes_fee es false y fee_basis es products_subtotal. Calcula el total con los importes que devuelve el carrito, no sumando precios. - orders y order-get solo devuelven pedidos del Mercado, los que empiezan por MKT-. Los pedidos de Amazon no forman parte de esta API. - Crear el pedido no esta disponible en esta API todavia. Puedes montar el carrito, pero el cobro se cierra desde la app de KeyPay. - Antes de poder pedir hacen falta una direccion de envio y un perfil de facturacion guardados. Usa la familia de direcciones. - Las imagenes llegan como https://api.innovapp-soft.com/v2/media/. Usalas tal cual en tu : son publicas, no piden Authorization y se cachean una semana. No intentes construir el token ni deducir la URL de origen. - El producto trae el nombre en name y las traducciones en translations.es y translations.en. Si pides language=es, name y description ya vienen traducidos. - Cada producto pertenece a una bodega y esa bodega tiene un pedido minimo. El carrito devuelve bodega_groups y minimum_failures con lo que falta para alcanzarlo. - Disponible en el Sandbox: pon /sandbox delante de la ruta y usa una clave dk_test_. El catalogo de prueba tiene dos productos en Villa Clara (province_id 5, localities_key 77); llama antes a products para obtener un product_token valido. - En el Sandbox orders siempre viene vacio y order-get responde 404, porque el pedido no se puede crear desde esta API. --- ## Endpoint: POST /v2/marketplace/cart-update ID: marketplace-v2-cart-update ACTION: Cambiar la cantidad METHOD: POST PATH: /v2/marketplace/cart-update URL: https://api.innovapp-soft.com/v2/marketplace/cart-update AUTH: Bearer API Key DESCRIPTION: Fija la cantidad exacta de una linea del carrito. Con quantity 0 la elimina. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - product_id | required=Si | type=integer | description=Id del producto tal y como viene en cart.items[].product_id. | example=90312 - quantity | required=Si | type=integer | description=Cantidad nueva, entre 0 y 20. Con 0 se elimina la linea del carrito. | example=3 - language | required=No | type=string | description=Idioma de los textos de la respuesta: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v2/marketplace/cart-update' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"product_id":90312,"quantity":3,"language":"es"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/marketplace/cart-update', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "product_id": 90312, "quantity": 3, "language": "es" }) }).then(r => r.json()).then(console.log); ``` ### Esquema de respuesta verificado ```json { "success": true, "code": "marketplace.cart-update.ok", "message": "OK", "data": { "cart": "dynamic" }, "error": [], "time": "2026-09-13T10:15:00-04:00" } ``` ### Errores específicos - HTTP 401 | 401 API key ausente o invalida ```json { "success": false, "code": 10023, "message": "Unauthorized", "data": [], "error": [] } ``` - HTTP 422 | 422 Campo requerido o invalido ```json { "success": false, "code": 48003, "message": "Required field is missing: product_token", "data": [], "error": { "service": "marketplace", "action": "cart-add" } } ``` - HTTP 403 | 403 La cuenta no tiene acceso al Mercado ```json { "success": false, "code": "marketplace.status.failed", "message": "No tienes acceso al Mercado.", "data": [], "error": { "service": "marketplace", "action": "status" } } ``` - HTTP 503 | 503 Servicio temporalmente no disponible ```json { "success": false, "code": "marketplace.products.failed", "message": "Marketplace is temporarily unavailable.", "data": [], "error": { "service": "marketplace", "action": "products" } } ``` - HTTP 502 | 502 No se pudo contactar con KeyPay ```json { "success": false, "code": 47020, "message": "The Mercado service is temporarily unavailable.", "data": [], "error": [] } ``` ### Notas - No envies userIdentifier: la cuenta KeyPay sale de la API key autenticada. - Todas las rutas son POST con cuerpo JSON, incluidas las de solo lectura. - product_token va firmado y atado al province_id y al localities_key con los que pediste el catalogo. Caduca a los 30 minutos: no lo guardes ni lo compartas entre usuarios. - Sin localities_key el catalogo es de toda la provincia y el detalle no puede confirmar existencias en una bodega concreta. Manda siempre el municipio si lo conoces. - El carrito admite hasta 30 productos distintos y 20 unidades por producto. Muchos productos tienen ademas un minimo por bodega que el servidor aplica solo. - Los precios llegan sin la comision: price_includes_fee es false y fee_basis es products_subtotal. Calcula el total con los importes que devuelve el carrito, no sumando precios. - orders y order-get solo devuelven pedidos del Mercado, los que empiezan por MKT-. Los pedidos de Amazon no forman parte de esta API. - Crear el pedido no esta disponible en esta API todavia. Puedes montar el carrito, pero el cobro se cierra desde la app de KeyPay. - Antes de poder pedir hacen falta una direccion de envio y un perfil de facturacion guardados. Usa la familia de direcciones. - Las imagenes llegan como https://api.innovapp-soft.com/v2/media/. Usalas tal cual en tu : son publicas, no piden Authorization y se cachean una semana. No intentes construir el token ni deducir la URL de origen. - El producto trae el nombre en name y las traducciones en translations.es y translations.en. Si pides language=es, name y description ya vienen traducidos. - Cada producto pertenece a una bodega y esa bodega tiene un pedido minimo. El carrito devuelve bodega_groups y minimum_failures con lo que falta para alcanzarlo. - Disponible en el Sandbox: pon /sandbox delante de la ruta y usa una clave dk_test_. El catalogo de prueba tiene dos productos en Villa Clara (province_id 5, localities_key 77); llama antes a products para obtener un product_token valido. - En el Sandbox orders siempre viene vacio y order-get responde 404, porque el pedido no se puede crear desde esta API. --- ## Endpoint: POST /v2/marketplace/cart-remove ID: marketplace-v2-cart-remove ACTION: Quitar del carrito METHOD: POST PATH: /v2/marketplace/cart-remove URL: https://api.innovapp-soft.com/v2/marketplace/cart-remove AUTH: Bearer API Key DESCRIPTION: Elimina una linea del carrito. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - product_id | required=Si | type=integer | description=Id del producto tal y como viene en cart.items[].product_id. | example=90312 - language | required=No | type=string | description=Idioma de los textos de la respuesta: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v2/marketplace/cart-remove' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"product_id":90312,"language":"es"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/marketplace/cart-remove', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "product_id": 90312, "language": "es" }) }).then(r => r.json()).then(console.log); ``` ### Esquema de respuesta verificado ```json { "success": true, "code": "marketplace.cart-remove.ok", "message": "OK", "data": { "cart": "dynamic" }, "error": [], "time": "2026-09-13T10:15:00-04:00" } ``` ### Errores específicos - HTTP 401 | 401 API key ausente o invalida ```json { "success": false, "code": 10023, "message": "Unauthorized", "data": [], "error": [] } ``` - HTTP 422 | 422 Campo requerido o invalido ```json { "success": false, "code": 48003, "message": "Required field is missing: product_token", "data": [], "error": { "service": "marketplace", "action": "cart-add" } } ``` - HTTP 403 | 403 La cuenta no tiene acceso al Mercado ```json { "success": false, "code": "marketplace.status.failed", "message": "No tienes acceso al Mercado.", "data": [], "error": { "service": "marketplace", "action": "status" } } ``` - HTTP 503 | 503 Servicio temporalmente no disponible ```json { "success": false, "code": "marketplace.products.failed", "message": "Marketplace is temporarily unavailable.", "data": [], "error": { "service": "marketplace", "action": "products" } } ``` - HTTP 502 | 502 No se pudo contactar con KeyPay ```json { "success": false, "code": 47020, "message": "The Mercado service is temporarily unavailable.", "data": [], "error": [] } ``` ### Notas - No envies userIdentifier: la cuenta KeyPay sale de la API key autenticada. - Todas las rutas son POST con cuerpo JSON, incluidas las de solo lectura. - product_token va firmado y atado al province_id y al localities_key con los que pediste el catalogo. Caduca a los 30 minutos: no lo guardes ni lo compartas entre usuarios. - Sin localities_key el catalogo es de toda la provincia y el detalle no puede confirmar existencias en una bodega concreta. Manda siempre el municipio si lo conoces. - El carrito admite hasta 30 productos distintos y 20 unidades por producto. Muchos productos tienen ademas un minimo por bodega que el servidor aplica solo. - Los precios llegan sin la comision: price_includes_fee es false y fee_basis es products_subtotal. Calcula el total con los importes que devuelve el carrito, no sumando precios. - orders y order-get solo devuelven pedidos del Mercado, los que empiezan por MKT-. Los pedidos de Amazon no forman parte de esta API. - Crear el pedido no esta disponible en esta API todavia. Puedes montar el carrito, pero el cobro se cierra desde la app de KeyPay. - Antes de poder pedir hacen falta una direccion de envio y un perfil de facturacion guardados. Usa la familia de direcciones. - Las imagenes llegan como https://api.innovapp-soft.com/v2/media/. Usalas tal cual en tu : son publicas, no piden Authorization y se cachean una semana. No intentes construir el token ni deducir la URL de origen. - El producto trae el nombre en name y las traducciones en translations.es y translations.en. Si pides language=es, name y description ya vienen traducidos. - Cada producto pertenece a una bodega y esa bodega tiene un pedido minimo. El carrito devuelve bodega_groups y minimum_failures con lo que falta para alcanzarlo. - Disponible en el Sandbox: pon /sandbox delante de la ruta y usa una clave dk_test_. El catalogo de prueba tiene dos productos en Villa Clara (province_id 5, localities_key 77); llama antes a products para obtener un product_token valido. - En el Sandbox orders siempre viene vacio y order-get responde 404, porque el pedido no se puede crear desde esta API. --- ## Endpoint: POST /v2/marketplace/cart-clear ID: marketplace-v2-cart-clear ACTION: Vaciar el carrito METHOD: POST PATH: /v2/marketplace/cart-clear URL: https://api.innovapp-soft.com/v2/marketplace/cart-clear AUTH: Bearer API Key DESCRIPTION: Vacia el carrito de la cuenta. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - language | required=No | type=string | description=Idioma de los textos de la respuesta: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v2/marketplace/cart-clear' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"language":"es"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/marketplace/cart-clear', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "language": "es" }) }).then(r => r.json()).then(console.log); ``` ### Esquema de respuesta verificado ```json { "success": true, "code": "marketplace.cart-clear.ok", "message": "OK", "data": { "cart": { "items": [] } }, "error": [], "time": "2026-09-13T10:15:00-04:00" } ``` ### Errores específicos - HTTP 401 | 401 API key ausente o invalida ```json { "success": false, "code": 10023, "message": "Unauthorized", "data": [], "error": [] } ``` - HTTP 422 | 422 Campo requerido o invalido ```json { "success": false, "code": 48003, "message": "Required field is missing: product_token", "data": [], "error": { "service": "marketplace", "action": "cart-add" } } ``` - HTTP 403 | 403 La cuenta no tiene acceso al Mercado ```json { "success": false, "code": "marketplace.status.failed", "message": "No tienes acceso al Mercado.", "data": [], "error": { "service": "marketplace", "action": "status" } } ``` - HTTP 503 | 503 Servicio temporalmente no disponible ```json { "success": false, "code": "marketplace.products.failed", "message": "Marketplace is temporarily unavailable.", "data": [], "error": { "service": "marketplace", "action": "products" } } ``` - HTTP 502 | 502 No se pudo contactar con KeyPay ```json { "success": false, "code": 47020, "message": "The Mercado service is temporarily unavailable.", "data": [], "error": [] } ``` ### Notas - No envies userIdentifier: la cuenta KeyPay sale de la API key autenticada. - Todas las rutas son POST con cuerpo JSON, incluidas las de solo lectura. - product_token va firmado y atado al province_id y al localities_key con los que pediste el catalogo. Caduca a los 30 minutos: no lo guardes ni lo compartas entre usuarios. - Sin localities_key el catalogo es de toda la provincia y el detalle no puede confirmar existencias en una bodega concreta. Manda siempre el municipio si lo conoces. - El carrito admite hasta 30 productos distintos y 20 unidades por producto. Muchos productos tienen ademas un minimo por bodega que el servidor aplica solo. - Los precios llegan sin la comision: price_includes_fee es false y fee_basis es products_subtotal. Calcula el total con los importes que devuelve el carrito, no sumando precios. - orders y order-get solo devuelven pedidos del Mercado, los que empiezan por MKT-. Los pedidos de Amazon no forman parte de esta API. - Crear el pedido no esta disponible en esta API todavia. Puedes montar el carrito, pero el cobro se cierra desde la app de KeyPay. - Antes de poder pedir hacen falta una direccion de envio y un perfil de facturacion guardados. Usa la familia de direcciones. - Las imagenes llegan como https://api.innovapp-soft.com/v2/media/. Usalas tal cual en tu : son publicas, no piden Authorization y se cachean una semana. No intentes construir el token ni deducir la URL de origen. - El producto trae el nombre en name y las traducciones en translations.es y translations.en. Si pides language=es, name y description ya vienen traducidos. - Cada producto pertenece a una bodega y esa bodega tiene un pedido minimo. El carrito devuelve bodega_groups y minimum_failures con lo que falta para alcanzarlo. - Disponible en el Sandbox: pon /sandbox delante de la ruta y usa una clave dk_test_. El catalogo de prueba tiene dos productos en Villa Clara (province_id 5, localities_key 77); llama antes a products para obtener un product_token valido. - En el Sandbox orders siempre viene vacio y order-get responde 404, porque el pedido no se puede crear desde esta API. --- ## Endpoint: POST /v2/marketplace/orders ID: marketplace-v2-orders ACTION: Historial de pedidos METHOD: POST PATH: /v2/marketplace/orders URL: https://api.innovapp-soft.com/v2/marketplace/orders AUTH: Bearer API Key DESCRIPTION: Lista los pedidos del Mercado de la cuenta, paginados y con sus estados. Solo devuelve pedidos del Mercado; los de Amazon no entran en esta API. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - page | required=No | type=integer | description=Pagina solicitada. Empieza en 1. | example=1 - per_page | required=No | type=integer | description=Pedidos por pagina, entre 1 y 50. Por defecto 12. | example=20 - query | required=No | type=string | description=Filtra los pedidos por numero o por producto. Maximo 120 caracteres. | example=MKT- - language | required=No | type=string | description=Idioma de los textos de la respuesta: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v2/marketplace/orders' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"page":1,"language":"es"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/marketplace/orders', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "page": 1, "language": "es" }) }).then(r => r.json()).then(console.log); ``` ### Esquema de respuesta verificado ```json { "success": true, "code": "marketplace.orders.ok", "message": "OK", "data": { "orders": [ { "id": 4471, "order_number": "MKT-000000", "status": "pending", "total": "dynamic", "created_at": "dynamic" } ], "pagination": { "page": 1, "per_page": 12, "total": "dynamic", "pages": "dynamic" }, "status_labels": "dynamic", "unread_count": "dynamic" }, "error": [], "time": "2026-09-13T10:15:00-04:00" } ``` ### Errores específicos - HTTP 401 | 401 API key ausente o invalida ```json { "success": false, "code": 10023, "message": "Unauthorized", "data": [], "error": [] } ``` - HTTP 422 | 422 Campo requerido o invalido ```json { "success": false, "code": 48003, "message": "Required field is missing: product_token", "data": [], "error": { "service": "marketplace", "action": "cart-add" } } ``` - HTTP 403 | 403 La cuenta no tiene acceso al Mercado ```json { "success": false, "code": "marketplace.status.failed", "message": "No tienes acceso al Mercado.", "data": [], "error": { "service": "marketplace", "action": "status" } } ``` - HTTP 503 | 503 Servicio temporalmente no disponible ```json { "success": false, "code": "marketplace.products.failed", "message": "Marketplace is temporarily unavailable.", "data": [], "error": { "service": "marketplace", "action": "products" } } ``` - HTTP 502 | 502 No se pudo contactar con KeyPay ```json { "success": false, "code": 47020, "message": "The Mercado service is temporarily unavailable.", "data": [], "error": [] } ``` ### Notas - No envies userIdentifier: la cuenta KeyPay sale de la API key autenticada. - Todas las rutas son POST con cuerpo JSON, incluidas las de solo lectura. - product_token va firmado y atado al province_id y al localities_key con los que pediste el catalogo. Caduca a los 30 minutos: no lo guardes ni lo compartas entre usuarios. - Sin localities_key el catalogo es de toda la provincia y el detalle no puede confirmar existencias en una bodega concreta. Manda siempre el municipio si lo conoces. - El carrito admite hasta 30 productos distintos y 20 unidades por producto. Muchos productos tienen ademas un minimo por bodega que el servidor aplica solo. - Los precios llegan sin la comision: price_includes_fee es false y fee_basis es products_subtotal. Calcula el total con los importes que devuelve el carrito, no sumando precios. - orders y order-get solo devuelven pedidos del Mercado, los que empiezan por MKT-. Los pedidos de Amazon no forman parte de esta API. - Crear el pedido no esta disponible en esta API todavia. Puedes montar el carrito, pero el cobro se cierra desde la app de KeyPay. - Antes de poder pedir hacen falta una direccion de envio y un perfil de facturacion guardados. Usa la familia de direcciones. - Las imagenes llegan como https://api.innovapp-soft.com/v2/media/. Usalas tal cual en tu : son publicas, no piden Authorization y se cachean una semana. No intentes construir el token ni deducir la URL de origen. - El producto trae el nombre en name y las traducciones en translations.es y translations.en. Si pides language=es, name y description ya vienen traducidos. - Cada producto pertenece a una bodega y esa bodega tiene un pedido minimo. El carrito devuelve bodega_groups y minimum_failures con lo que falta para alcanzarlo. - Disponible en el Sandbox: pon /sandbox delante de la ruta y usa una clave dk_test_. El catalogo de prueba tiene dos productos en Villa Clara (province_id 5, localities_key 77); llama antes a products para obtener un product_token valido. - En el Sandbox orders siempre viene vacio y order-get responde 404, porque el pedido no se puede crear desde esta API. --- ## Endpoint: POST /v2/marketplace/order-get ID: marketplace-v2-order-get ACTION: Detalle de un pedido METHOD: POST PATH: /v2/marketplace/order-get URL: https://api.innovapp-soft.com/v2/marketplace/order-get AUTH: Bearer API Key DESCRIPTION: Devuelve un pedido del Mercado con sus productos, direccion de entrega, facturacion, comisiones y estado. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - order_id | required=Si | type=integer | description=Id del pedido devuelto por orders. | example=4471 - language | required=No | type=string | description=Idioma de los textos de la respuesta: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v2/marketplace/order-get' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"order_id":4471,"language":"es"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/marketplace/order-get', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "order_id": 4471, "language": "es" }) }).then(r => r.json()).then(console.log); ``` ### Esquema de respuesta verificado ```json { "success": true, "code": "marketplace.order-get.ok", "message": "OK", "data": { "order": { "id": 4471, "order_number": "MKT-000000", "status": "pending", "items": [ "dynamic" ], "address": "dynamic", "billing_profile": "dynamic", "total": "dynamic" }, "status_labels": "dynamic", "unread_count": "dynamic" }, "error": [], "time": "2026-09-13T10:15:00-04:00" } ``` ### Errores específicos - HTTP 401 | 401 API key ausente o invalida ```json { "success": false, "code": 10023, "message": "Unauthorized", "data": [], "error": [] } ``` - HTTP 422 | 422 Campo requerido o invalido ```json { "success": false, "code": 48003, "message": "Required field is missing: product_token", "data": [], "error": { "service": "marketplace", "action": "cart-add" } } ``` - HTTP 403 | 403 La cuenta no tiene acceso al Mercado ```json { "success": false, "code": "marketplace.status.failed", "message": "No tienes acceso al Mercado.", "data": [], "error": { "service": "marketplace", "action": "status" } } ``` - HTTP 503 | 503 Servicio temporalmente no disponible ```json { "success": false, "code": "marketplace.products.failed", "message": "Marketplace is temporarily unavailable.", "data": [], "error": { "service": "marketplace", "action": "products" } } ``` - HTTP 502 | 502 No se pudo contactar con KeyPay ```json { "success": false, "code": 47020, "message": "The Mercado service is temporarily unavailable.", "data": [], "error": [] } ``` ### Notas - No envies userIdentifier: la cuenta KeyPay sale de la API key autenticada. - Todas las rutas son POST con cuerpo JSON, incluidas las de solo lectura. - product_token va firmado y atado al province_id y al localities_key con los que pediste el catalogo. Caduca a los 30 minutos: no lo guardes ni lo compartas entre usuarios. - Sin localities_key el catalogo es de toda la provincia y el detalle no puede confirmar existencias en una bodega concreta. Manda siempre el municipio si lo conoces. - El carrito admite hasta 30 productos distintos y 20 unidades por producto. Muchos productos tienen ademas un minimo por bodega que el servidor aplica solo. - Los precios llegan sin la comision: price_includes_fee es false y fee_basis es products_subtotal. Calcula el total con los importes que devuelve el carrito, no sumando precios. - orders y order-get solo devuelven pedidos del Mercado, los que empiezan por MKT-. Los pedidos de Amazon no forman parte de esta API. - Crear el pedido no esta disponible en esta API todavia. Puedes montar el carrito, pero el cobro se cierra desde la app de KeyPay. - Antes de poder pedir hacen falta una direccion de envio y un perfil de facturacion guardados. Usa la familia de direcciones. - Las imagenes llegan como https://api.innovapp-soft.com/v2/media/. Usalas tal cual en tu : son publicas, no piden Authorization y se cachean una semana. No intentes construir el token ni deducir la URL de origen. - El producto trae el nombre en name y las traducciones en translations.es y translations.en. Si pides language=es, name y description ya vienen traducidos. - Cada producto pertenece a una bodega y esa bodega tiene un pedido minimo. El carrito devuelve bodega_groups y minimum_failures con lo que falta para alcanzarlo. - Disponible en el Sandbox: pon /sandbox delante de la ruta y usa una clave dk_test_. El catalogo de prueba tiene dos productos en Villa Clara (province_id 5, localities_key 77); llama antes a products para obtener un product_token valido. - En el Sandbox orders siempre viene vacio y order-get responde 404, porque el pedido no se puede crear desde esta API. --- # Grupo: Direcciones y facturacion Libreta de direcciones de envio y perfil de facturacion de la cuenta KeyPay enlazada a tu API key. Es exactamente la misma libreta que usan las apps moviles: lo que guardes aqui lo ve el usuario en su app y al reves. ## Endpoint: POST /v2/addresses/config ID: addresses-v2-config ACTION: Campos y ubicaciones METHOD: POST PATH: /v2/addresses/config URL: https://api.innovapp-soft.com/v2/addresses/config AUTH: Bearer API Key DESCRIPTION: Devuelve el esquema de campos de direccion y de facturacion, los paises aceptados y el arbol de provincias y municipios. Pidelo antes de pintar un formulario en lugar de codificar las reglas a mano. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - language | required=No | type=string | description=Idioma de los textos de la respuesta: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v2/addresses/config' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"language":"es"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/addresses/config', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "language": "es" }) }).then(r => r.json()).then(console.log); ``` ### Esquema de respuesta verificado ```json { "success": true, "code": "addresses.config.ok", "message": "OK", "data": { "address": "dynamic", "addresses": [ "dynamic" ], "address_config": { "country": "dynamic", "countries": "dynamic", "fields": "dynamic" }, "billing_profile": "dynamic", "billing_config": { "countries": "dynamic", "required_fields": "dynamic" }, "locations": "dynamic" }, "error": [], "time": "2026-09-13T10:15:00-04:00" } ``` ### Errores específicos - HTTP 401 | 401 API key ausente o invalida ```json { "success": false, "code": 10023, "message": "Unauthorized", "data": [], "error": [] } ``` - HTTP 422 | 422 Campo requerido o invalido ```json { "success": false, "code": 48003, "message": "Required field is missing: product_token", "data": [], "error": { "service": "marketplace", "action": "cart-add" } } ``` - HTTP 403 | 403 La cuenta no tiene acceso al Mercado ```json { "success": false, "code": "marketplace.status.failed", "message": "No tienes acceso al Mercado.", "data": [], "error": { "service": "marketplace", "action": "status" } } ``` - HTTP 503 | 503 Servicio temporalmente no disponible ```json { "success": false, "code": "marketplace.products.failed", "message": "Marketplace is temporarily unavailable.", "data": [], "error": { "service": "marketplace", "action": "products" } } ``` - HTTP 502 | 502 No se pudo contactar con KeyPay ```json { "success": false, "code": 47020, "message": "The Mercado service is temporarily unavailable.", "data": [], "error": [] } ``` ### Notas - No envies userIdentifier: la cuenta KeyPay sale de la API key autenticada. - Todas las rutas son POST con cuerpo JSON, incluidas las de solo lectura. - Solo se aceptan direcciones de CU y US. En CU la provincia y el municipio se validan contra locations y el telefono tiene que ser de 8 digitos. - Los campos alternate son un segundo receptor opcional, pero van en bloque: si mandas uno tienes que mandar los cuatro. - No hay borrado de direcciones. Las apps moviles tampoco lo tienen: se edita la que sobra o se marca otra como predeterminada. - save sin address_id crea; save con address_id edita esa direccion. Una direccion que ya es predeterminada no deja de serlo al editarla. - El perfil de facturacion es unico por cuenta: billing-save sobrescribe siempre. - Esta libreta es la misma que usan las apps moviles de KeyPay. Un cambio hecho por API lo ve el usuario en su app. - Disponible en el Sandbox: pon /sandbox delante de la ruta y usa una clave dk_test_. La libreta de prueba admite hasta 20 direcciones y valida provincia y municipio contra las ubicaciones del Sandbox, no contra las reales. --- ## Endpoint: POST /v2/addresses/list ID: addresses-v2-list ACTION: Listar direcciones METHOD: POST PATH: /v2/addresses/list URL: https://api.innovapp-soft.com/v2/addresses/list AUTH: Bearer API Key DESCRIPTION: Devuelve todas las direcciones de envio de la cuenta. address es la predeterminada y siempre es la primera de addresses. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - language | required=No | type=string | description=Idioma de los textos de la respuesta: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v2/addresses/list' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"language":"es"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/addresses/list', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "language": "es" }) }).then(r => r.json()).then(console.log); ``` ### Esquema de respuesta verificado ```json { "success": true, "code": "addresses.list.ok", "message": "OK", "data": { "address": "dynamic", "addresses": [ { "id": 12, "country_code": "CU", "first_name": "Ana", "last_name": "Perez Diaz", "phone": "55512345", "province": "La Habana", "municipality": "Playa", "address_line": "Calle 42 #1706 e/ 17 y 19", "address_extra": "Apto 3B", "identity_number": "85010112345", "neighborhood": "Miramar", "delivery_notes": "dynamic", "is_default": true, "created_at": "dynamic", "updated_at": "dynamic" } ] }, "error": [], "time": "2026-09-13T10:15:00-04:00" } ``` ### Errores específicos - HTTP 401 | 401 API key ausente o invalida ```json { "success": false, "code": 10023, "message": "Unauthorized", "data": [], "error": [] } ``` - HTTP 422 | 422 Campo requerido o invalido ```json { "success": false, "code": 48003, "message": "Required field is missing: product_token", "data": [], "error": { "service": "marketplace", "action": "cart-add" } } ``` - HTTP 403 | 403 La cuenta no tiene acceso al Mercado ```json { "success": false, "code": "marketplace.status.failed", "message": "No tienes acceso al Mercado.", "data": [], "error": { "service": "marketplace", "action": "status" } } ``` - HTTP 503 | 503 Servicio temporalmente no disponible ```json { "success": false, "code": "marketplace.products.failed", "message": "Marketplace is temporarily unavailable.", "data": [], "error": { "service": "marketplace", "action": "products" } } ``` - HTTP 502 | 502 No se pudo contactar con KeyPay ```json { "success": false, "code": 47020, "message": "The Mercado service is temporarily unavailable.", "data": [], "error": [] } ``` ### Notas - No envies userIdentifier: la cuenta KeyPay sale de la API key autenticada. - Todas las rutas son POST con cuerpo JSON, incluidas las de solo lectura. - Solo se aceptan direcciones de CU y US. En CU la provincia y el municipio se validan contra locations y el telefono tiene que ser de 8 digitos. - Los campos alternate son un segundo receptor opcional, pero van en bloque: si mandas uno tienes que mandar los cuatro. - No hay borrado de direcciones. Las apps moviles tampoco lo tienen: se edita la que sobra o se marca otra como predeterminada. - save sin address_id crea; save con address_id edita esa direccion. Una direccion que ya es predeterminada no deja de serlo al editarla. - El perfil de facturacion es unico por cuenta: billing-save sobrescribe siempre. - Esta libreta es la misma que usan las apps moviles de KeyPay. Un cambio hecho por API lo ve el usuario en su app. - Disponible en el Sandbox: pon /sandbox delante de la ruta y usa una clave dk_test_. La libreta de prueba admite hasta 20 direcciones y valida provincia y municipio contra las ubicaciones del Sandbox, no contra las reales. --- ## Endpoint: POST /v2/addresses/save ID: addresses-v2-save ACTION: Crear o editar una direccion METHOD: POST PATH: /v2/addresses/save URL: https://api.innovapp-soft.com/v2/addresses/save AUTH: Bearer API Key DESCRIPTION: Crea una direccion de envio, o edita una existente si envias address_id. La primera direccion de la cuenta queda como predeterminada automaticamente. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - address_id | required=No | type=integer | description=Id de una direccion existente. Sin el se crea una nueva; con el se edita esa. | example=12 - country_code | required=Si | type=string | description=Pais de la direccion. Solo se aceptan CU y US. | example=CU - first_name | required=Si | type=string | description=Nombre de quien recibe. Minimo 2 caracteres. | example=Ana - last_name | required=Si | type=string | description=Apellidos de quien recibe. Minimo 2 caracteres. | example=Perez Diaz - phone | required=Si | type=string | description=Telefono de contacto. En CU son 8 digitos; en US entre 7 y 15. | example=55512345 - province | required=Si | type=string | description=Provincia. En CU tiene que coincidir con una de locations. | example=La Habana - municipality | required=Si | type=string | description=Municipio. En CU tiene que pertenecer a la provincia enviada. | example=Playa - address_line | required=Si | type=string | description=Calle, numero y entre calles. Minimo 5 caracteres. | example=Calle 42 #1706 e/ 17 y 19 - address_extra | required=No | type=string | description=Apartamento, piso o referencia adicional. | example=Apto 3B - identity_number | required=Si | type=string | description=Carne de identidad o documento de quien recibe. Solo letras y numeros. | example=85010112345 - neighborhood | required=No | type=string | description=Reparto o barrio. | example=Miramar - alternate_first_name | required=No | type=string | description=Nombre de un segundo receptor. Si envias uno de los campos alternate hay que enviarlos todos. | example=Luis - alternate_last_name | required=No | type=string | description=Apellidos del segundo receptor. | example=Gomez - alternate_phone | required=No | type=string | description=Telefono del segundo receptor. | example=55598765 - alternate_identity_number | required=No | type=string | description=Documento del segundo receptor. | example=90020254321 - delivery_notes | required=No | type=string | description=Indicaciones para el mensajero. Maximo 300 caracteres. | example=Tocar el timbre del 3B - is_default | required=No | type=boolean | description=Marca la direccion como predeterminada. La primera direccion de la cuenta siempre lo es. | example=true - language | required=No | type=string | description=Idioma de los textos de la respuesta: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v2/addresses/save' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"country_code":"CU","first_name":"Ana","last_name":"Perez Diaz","phone":"55512345","province":"La Habana","municipality":"Playa","address_line":"Calle 42 #1706 e/ 17 y 19","identity_number":"85010112345","language":"es"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/addresses/save', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "country_code": "CU", "first_name": "Ana", "last_name": "Perez Diaz", "phone": "55512345", "province": "La Habana", "municipality": "Playa", "address_line": "Calle 42 #1706 e/ 17 y 19", "identity_number": "85010112345", "language": "es" }) }).then(r => r.json()).then(console.log); ``` ### Esquema de respuesta verificado ```json { "success": true, "code": "addresses.save.ok", "message": "OK", "data": { "saved_address": "dynamic", "address": "dynamic", "addresses": [ "dynamic" ] }, "error": [], "time": "2026-09-13T10:15:00-04:00" } ``` ### Errores específicos - HTTP 401 | 401 API key ausente o invalida ```json { "success": false, "code": 10023, "message": "Unauthorized", "data": [], "error": [] } ``` - HTTP 422 | 422 Campo requerido o invalido ```json { "success": false, "code": 48003, "message": "Required field is missing: product_token", "data": [], "error": { "service": "marketplace", "action": "cart-add" } } ``` - HTTP 403 | 403 La cuenta no tiene acceso al Mercado ```json { "success": false, "code": "marketplace.status.failed", "message": "No tienes acceso al Mercado.", "data": [], "error": { "service": "marketplace", "action": "status" } } ``` - HTTP 503 | 503 Servicio temporalmente no disponible ```json { "success": false, "code": "marketplace.products.failed", "message": "Marketplace is temporarily unavailable.", "data": [], "error": { "service": "marketplace", "action": "products" } } ``` - HTTP 502 | 502 No se pudo contactar con KeyPay ```json { "success": false, "code": 47020, "message": "The Mercado service is temporarily unavailable.", "data": [], "error": [] } ``` ### Notas - No envies userIdentifier: la cuenta KeyPay sale de la API key autenticada. - Todas las rutas son POST con cuerpo JSON, incluidas las de solo lectura. - Solo se aceptan direcciones de CU y US. En CU la provincia y el municipio se validan contra locations y el telefono tiene que ser de 8 digitos. - Los campos alternate son un segundo receptor opcional, pero van en bloque: si mandas uno tienes que mandar los cuatro. - No hay borrado de direcciones. Las apps moviles tampoco lo tienen: se edita la que sobra o se marca otra como predeterminada. - save sin address_id crea; save con address_id edita esa direccion. Una direccion que ya es predeterminada no deja de serlo al editarla. - El perfil de facturacion es unico por cuenta: billing-save sobrescribe siempre. - Esta libreta es la misma que usan las apps moviles de KeyPay. Un cambio hecho por API lo ve el usuario en su app. - Disponible en el Sandbox: pon /sandbox delante de la ruta y usa una clave dk_test_. La libreta de prueba admite hasta 20 direcciones y valida provincia y municipio contra las ubicaciones del Sandbox, no contra las reales. --- ## Endpoint: POST /v2/addresses/select ID: addresses-v2-select ACTION: Marcar como predeterminada METHOD: POST PATH: /v2/addresses/select URL: https://api.innovapp-soft.com/v2/addresses/select AUTH: Bearer API Key DESCRIPTION: Marca una direccion como predeterminada. Es la que el Mercado usa para calcular la entrega. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - address_id | required=Si | type=integer | description=Id de la direccion devuelta por list. | example=12 - language | required=No | type=string | description=Idioma de los textos de la respuesta: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v2/addresses/select' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"address_id":12,"language":"es"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/addresses/select', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "address_id": 12, "language": "es" }) }).then(r => r.json()).then(console.log); ``` ### Esquema de respuesta verificado ```json { "success": true, "code": "addresses.select.ok", "message": "OK", "data": { "address": "dynamic", "addresses": [ "dynamic" ] }, "error": [], "time": "2026-09-13T10:15:00-04:00" } ``` ### Errores específicos - HTTP 401 | 401 API key ausente o invalida ```json { "success": false, "code": 10023, "message": "Unauthorized", "data": [], "error": [] } ``` - HTTP 422 | 422 Campo requerido o invalido ```json { "success": false, "code": 48003, "message": "Required field is missing: product_token", "data": [], "error": { "service": "marketplace", "action": "cart-add" } } ``` - HTTP 403 | 403 La cuenta no tiene acceso al Mercado ```json { "success": false, "code": "marketplace.status.failed", "message": "No tienes acceso al Mercado.", "data": [], "error": { "service": "marketplace", "action": "status" } } ``` - HTTP 503 | 503 Servicio temporalmente no disponible ```json { "success": false, "code": "marketplace.products.failed", "message": "Marketplace is temporarily unavailable.", "data": [], "error": { "service": "marketplace", "action": "products" } } ``` - HTTP 502 | 502 No se pudo contactar con KeyPay ```json { "success": false, "code": 47020, "message": "The Mercado service is temporarily unavailable.", "data": [], "error": [] } ``` ### Notas - No envies userIdentifier: la cuenta KeyPay sale de la API key autenticada. - Todas las rutas son POST con cuerpo JSON, incluidas las de solo lectura. - Solo se aceptan direcciones de CU y US. En CU la provincia y el municipio se validan contra locations y el telefono tiene que ser de 8 digitos. - Los campos alternate son un segundo receptor opcional, pero van en bloque: si mandas uno tienes que mandar los cuatro. - No hay borrado de direcciones. Las apps moviles tampoco lo tienen: se edita la que sobra o se marca otra como predeterminada. - save sin address_id crea; save con address_id edita esa direccion. Una direccion que ya es predeterminada no deja de serlo al editarla. - El perfil de facturacion es unico por cuenta: billing-save sobrescribe siempre. - Esta libreta es la misma que usan las apps moviles de KeyPay. Un cambio hecho por API lo ve el usuario en su app. - Disponible en el Sandbox: pon /sandbox delante de la ruta y usa una clave dk_test_. La libreta de prueba admite hasta 20 direcciones y valida provincia y municipio contra las ubicaciones del Sandbox, no contra las reales. --- ## Endpoint: POST /v2/addresses/billing ID: addresses-v2-billing ACTION: Ver la facturacion METHOD: POST PATH: /v2/addresses/billing URL: https://api.innovapp-soft.com/v2/addresses/billing AUTH: Bearer API Key DESCRIPTION: Devuelve el perfil de facturacion de la cuenta, o null si todavia no hay ninguno. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - language | required=No | type=string | description=Idioma de los textos de la respuesta: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v2/addresses/billing' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"language":"es"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/addresses/billing', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "language": "es" }) }).then(r => r.json()).then(console.log); ``` ### Esquema de respuesta verificado ```json { "success": true, "code": "addresses.billing.ok", "message": "OK", "data": { "billing_profile": { "first_name": "Ana", "last_name": "Perez Diaz", "country_code": "US", "identity_number": "A1234567", "address_line": "1200 Brickell Ave", "address_extra": "", "city": "Miami", "state": "FL", "postal_code": "33131", "phone": "+13055551234", "updated_at": "dynamic" } }, "error": [], "time": "2026-09-13T10:15:00-04:00" } ``` ### Errores específicos - HTTP 401 | 401 API key ausente o invalida ```json { "success": false, "code": 10023, "message": "Unauthorized", "data": [], "error": [] } ``` - HTTP 422 | 422 Campo requerido o invalido ```json { "success": false, "code": 48003, "message": "Required field is missing: product_token", "data": [], "error": { "service": "marketplace", "action": "cart-add" } } ``` - HTTP 403 | 403 La cuenta no tiene acceso al Mercado ```json { "success": false, "code": "marketplace.status.failed", "message": "No tienes acceso al Mercado.", "data": [], "error": { "service": "marketplace", "action": "status" } } ``` - HTTP 503 | 503 Servicio temporalmente no disponible ```json { "success": false, "code": "marketplace.products.failed", "message": "Marketplace is temporarily unavailable.", "data": [], "error": { "service": "marketplace", "action": "products" } } ``` - HTTP 502 | 502 No se pudo contactar con KeyPay ```json { "success": false, "code": 47020, "message": "The Mercado service is temporarily unavailable.", "data": [], "error": [] } ``` ### Notas - No envies userIdentifier: la cuenta KeyPay sale de la API key autenticada. - Todas las rutas son POST con cuerpo JSON, incluidas las de solo lectura. - Solo se aceptan direcciones de CU y US. En CU la provincia y el municipio se validan contra locations y el telefono tiene que ser de 8 digitos. - Los campos alternate son un segundo receptor opcional, pero van en bloque: si mandas uno tienes que mandar los cuatro. - No hay borrado de direcciones. Las apps moviles tampoco lo tienen: se edita la que sobra o se marca otra como predeterminada. - save sin address_id crea; save con address_id edita esa direccion. Una direccion que ya es predeterminada no deja de serlo al editarla. - El perfil de facturacion es unico por cuenta: billing-save sobrescribe siempre. - Esta libreta es la misma que usan las apps moviles de KeyPay. Un cambio hecho por API lo ve el usuario en su app. - Disponible en el Sandbox: pon /sandbox delante de la ruta y usa una clave dk_test_. La libreta de prueba admite hasta 20 direcciones y valida provincia y municipio contra las ubicaciones del Sandbox, no contra las reales. --- ## Endpoint: POST /v2/addresses/billing-save ID: addresses-v2-billing-save ACTION: Guardar la facturacion METHOD: POST PATH: /v2/addresses/billing-save URL: https://api.innovapp-soft.com/v2/addresses/billing-save AUTH: Bearer API Key DESCRIPTION: Crea o reemplaza el perfil de facturacion. Solo hay uno por cuenta, asi que esta llamada siempre sobrescribe el anterior. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - first_name | required=Si | type=string | description=Nombre del titular de la facturacion. | example=Ana - last_name | required=Si | type=string | description=Apellidos del titular de la facturacion. | example=Perez Diaz - country_code | required=Si | type=string | description=Pais de facturacion. Solo se aceptan CU y US. | example=US - identity_number | required=Si | type=string | description=Documento fiscal o de identidad del titular. | example=A1234567 - address_line | required=Si | type=string | description=Direccion de facturacion. | example=1200 Brickell Ave - address_extra | required=No | type=string | description=Apartamento, piso o referencia adicional. | example=Apto 3B - city | required=Si | type=string | description=Ciudad de facturacion. | example=Miami - state | required=Si | type=string | description=Estado o provincia de facturacion. | example=FL - postal_code | required=Si | type=string | description=Codigo postal. | example=33131 - phone | required=Si | type=string | description=Telefono de facturacion. | example=+13055551234 - language | required=No | type=string | description=Idioma de los textos de la respuesta: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v2/addresses/billing-save' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"first_name":"Ana","last_name":"Perez Diaz","country_code":"US","identity_number":"A1234567","address_line":"1200 Brickell Ave","city":"Miami","state":"FL","postal_code":"33131","phone":"+13055551234","language":"es"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/addresses/billing-save', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "first_name": "Ana", "last_name": "Perez Diaz", "country_code": "US", "identity_number": "A1234567", "address_line": "1200 Brickell Ave", "city": "Miami", "state": "FL", "postal_code": "33131", "phone": "+13055551234", "language": "es" }) }).then(r => r.json()).then(console.log); ``` ### Esquema de respuesta verificado ```json { "success": true, "code": "addresses.billing-save.ok", "message": "OK", "data": { "billing_profile": "dynamic" }, "error": [], "time": "2026-09-13T10:15:00-04:00" } ``` ### Errores específicos - HTTP 401 | 401 API key ausente o invalida ```json { "success": false, "code": 10023, "message": "Unauthorized", "data": [], "error": [] } ``` - HTTP 422 | 422 Campo requerido o invalido ```json { "success": false, "code": 48003, "message": "Required field is missing: product_token", "data": [], "error": { "service": "marketplace", "action": "cart-add" } } ``` - HTTP 403 | 403 La cuenta no tiene acceso al Mercado ```json { "success": false, "code": "marketplace.status.failed", "message": "No tienes acceso al Mercado.", "data": [], "error": { "service": "marketplace", "action": "status" } } ``` - HTTP 503 | 503 Servicio temporalmente no disponible ```json { "success": false, "code": "marketplace.products.failed", "message": "Marketplace is temporarily unavailable.", "data": [], "error": { "service": "marketplace", "action": "products" } } ``` - HTTP 502 | 502 No se pudo contactar con KeyPay ```json { "success": false, "code": 47020, "message": "The Mercado service is temporarily unavailable.", "data": [], "error": [] } ``` ### Notas - No envies userIdentifier: la cuenta KeyPay sale de la API key autenticada. - Todas las rutas son POST con cuerpo JSON, incluidas las de solo lectura. - Solo se aceptan direcciones de CU y US. En CU la provincia y el municipio se validan contra locations y el telefono tiene que ser de 8 digitos. - Los campos alternate son un segundo receptor opcional, pero van en bloque: si mandas uno tienes que mandar los cuatro. - No hay borrado de direcciones. Las apps moviles tampoco lo tienen: se edita la que sobra o se marca otra como predeterminada. - save sin address_id crea; save con address_id edita esa direccion. Una direccion que ya es predeterminada no deja de serlo al editarla. - El perfil de facturacion es unico por cuenta: billing-save sobrescribe siempre. - Esta libreta es la misma que usan las apps moviles de KeyPay. Un cambio hecho por API lo ve el usuario en su app. - Disponible en el Sandbox: pon /sandbox delante de la ruta y usa una clave dk_test_. La libreta de prueba admite hasta 20 direcciones y valida provincia y municipio contra las ubicaciones del Sandbox, no contra las reales. --- # Grupo: Store V2 · Catálogo general KeyStore Empieza aquí para conocer todos los productos habilitados antes de abrir un flujo específico. ## Endpoint: POST /v2/store/catalog/list ID: store-v2-catalog-list ACTION: Catálogo completo METHOD: POST PATH: /v2/store/catalog/list URL: https://api.innovapp-soft.com/v2/store/catalog/list AUTH: Bearer API Key DESCRIPTION: Catálogo general KeyStore: Devuelve el catálogo completo habilitado en KeyStore, incluidos VPN, KeyCode, productos físicos y las entradas V2 disponibles. La visibilidad sigue la configuración activa del Dashboard. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - language | required=No | type=string | description=Idioma de la respuesta: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v2/store/catalog/list' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"language":"es"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/store/catalog/list', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "language": "es" }) }).then(r => r.json()).then(console.log); ``` ### Esquema de respuesta verificado ```json [ { "success": "boolean", "code": "string | integer", "message": "string", "data": "{items:[native catalog row],count:int}", "error": "object | array", "time": "object" }, [] ] ``` ### Errores específicos - HTTP 401 | API key invalida ```json { "success": false, "code": 40101, "message": "Invalid API key." } ``` - HTTP 422 | Parametro requerido ```json { "success": false, "code": 47017, "message": "Required field is missing: client_purchase_id" } ``` - HTTP 502 | Servicio temporalmente no disponible ```json { "success": false, "code": 47020, "message": "The Store service is temporarily unavailable." } ``` ### Notas - No envies userIdentifier: el usuario KeyPay se obtiene del developer autenticado. - Las compras requieren client_purchase_id unico. Si repites la misma solicitud usa exactamente el mismo valor. - El catalogo determina los identificadores, montos y campos validos; no construyas offer_id, service_id ni e164 manualmente. - La API puede devolver pending, processing, completed, failed o refunded segun el producto. - Esquema parcial verificado en el código de KeyPay. Los valores dynamic se resuelven en ejecución; no representan una respuesta JSON de producción. Los datos externos sin contrato verificable se omiten. --- # Grupo: Store V2 · Recargas internacionales Flujo recomendado: consultar catálogo, validar promoción si existe, comprar y después consultar la orden o su estado. ## Endpoint: POST /v2/store/topups/catalog ID: store-v2-topups-catalog ACTION: Consultar catálogo METHOD: POST PATH: /v2/store/topups/catalog URL: https://api.innovapp-soft.com/v2/store/topups/catalog AUTH: Bearer API Key DESCRIPTION: Recargas internacionales: Lista paises, operadores y ofertas. Usa mode=countries para iniciar; despues envia country y finalmente country + brand. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - mode | required=No | type=string | description=Vista del catalogo. En eSIM usa countries para listar destinos y plans (u offers como alias) para listar los planes del country enviado. | example=countries - country | required=Depende | type=string | description=Codigo ISO 3166-1 alpha-2 del pais. En el catalogo eSIM es obligatorio cuando mode es plans u offers. | example=CU - brand | required=Depende | type=string | description=Marca u operador devuelto por el catalogo. | example=Cubacel - sub_type | required=No | type=string | description=Subtipo de producto dentro de una marca. | example=MOBILE - language | required=No | type=string | description=Idioma de la respuesta: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v2/store/topups/catalog' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"mode":"countries","language":"es"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/store/topups/catalog', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "mode": "countries", "language": "es" }) }).then(r => r.json()).then(console.log); ``` ### Esquema de respuesta verificado ```json [ { "success": "boolean", "code": "string | integer", "message": "string", "data": "Mode/resource-specific local object; catalog arrays are named data, not generic items. See controller source and local model.", "error": "object | array", "time": "object" }, { "topup_offer": { "offer_id": "dynamic", "source": "dynamic", "name": "dynamic", "notes": "dynamic", "sent_benefits": "dynamic", "sub_type": "dynamic", "price_type": "dynamic", "margin_percent": "dynamic", "is_promotional": "dynamic", "promotion_label": "dynamic", "price": "dynamic", "amount_min": "dynamic", "amount_max": "dynamic", "provider_service_fee_percent": "dynamic", "price_min": "dynamic", "price_max": "dynamic" } } ] ``` ### Errores específicos - HTTP 401 | API key invalida ```json { "success": false, "code": 40101, "message": "Invalid API key." } ``` - HTTP 422 | Parametro requerido ```json { "success": false, "code": 47017, "message": "Required field is missing: client_purchase_id" } ``` - HTTP 502 | Servicio temporalmente no disponible ```json { "success": false, "code": 47020, "message": "The Store service is temporarily unavailable." } ``` ### Notas - No envies userIdentifier: el usuario KeyPay se obtiene del developer autenticado. - Las compras requieren client_purchase_id unico. Si repites la misma solicitud usa exactamente el mismo valor. - El catalogo determina los identificadores, montos y campos validos; no construyas offer_id, service_id ni e164 manualmente. - La API puede devolver pending, processing, completed, failed o refunded segun el producto. - Esquema parcial verificado en el código de KeyPay. Los valores dynamic se resuelven en ejecución; no representan una respuesta JSON de producción. Los datos externos sin contrato verificable se omiten. --- ## Endpoint: POST /v2/store/topups/promo ID: store-v2-topups-promo ACTION: Validar promoción METHOD: POST PATH: /v2/store/topups/promo URL: https://api.innovapp-soft.com/v2/store/topups/promo AUTH: Bearer API Key DESCRIPTION: Recargas internacionales: Valida un codigo promocional para una oferta antes de comprar. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - country | required=Depende | type=string | description=Codigo ISO 3166-1 alpha-2 del pais. En el catalogo eSIM es obligatorio cuando mode es plans u offers. | example=CU - brand | required=Depende | type=string | description=Marca u operador devuelto por el catalogo. | example=Cubacel - offer_id | required=Si en compra | type=string | description=Identificador exacto de la oferta seleccionada. | example=61 - promo_code | required=Depende | type=string | description=Codigo promocional que se desea validar o aplicar. | example=PROMO2026 - amount | required=No | type=number | description=Monto elegido cuando la oferta permite un rango. | example=25.00 - language | required=No | type=string | description=Idioma de la respuesta: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v2/store/topups/promo' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"country":"CU","brand":"Cubacel","offer_id":"61","promo_code":"PROMO2026","language":"es"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/store/topups/promo', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "country": "CU", "brand": "Cubacel", "offer_id": "61", "promo_code": "PROMO2026", "language": "es" }) }).then(r => r.json()).then(console.log); ``` ### Esquema de respuesta verificado ```json [ { "success": "boolean", "code": "string | integer", "message": "string", "data": "Direct record fields under Developer data (no extra order wrapper). Status adds credito; eSIM/number status adds poll_after_seconds.", "error": "object | array", "time": "object" }, [] ] ``` ### Errores específicos - HTTP 401 | API key invalida ```json { "success": false, "code": 40101, "message": "Invalid API key." } ``` - HTTP 422 | Parametro requerido ```json { "success": false, "code": 47017, "message": "Required field is missing: client_purchase_id" } ``` - HTTP 502 | Servicio temporalmente no disponible ```json { "success": false, "code": 47020, "message": "The Store service is temporarily unavailable." } ``` ### Notas - No envies userIdentifier: el usuario KeyPay se obtiene del developer autenticado. - Las compras requieren client_purchase_id unico. Si repites la misma solicitud usa exactamente el mismo valor. - El catalogo determina los identificadores, montos y campos validos; no construyas offer_id, service_id ni e164 manualmente. - La API puede devolver pending, processing, completed, failed o refunded segun el producto. - Esquema parcial verificado en el código de KeyPay. Los valores dynamic se resuelven en ejecución; no representan una respuesta JSON de producción. Los datos externos sin contrato verificable se omiten. --- ## Endpoint: POST /v2/store/topups/buy ID: store-v2-topups-buy ACTION: Comprar METHOD: POST PATH: /v2/store/topups/buy URL: https://api.innovapp-soft.com/v2/store/topups/buy AUTH: Bearer API Key DESCRIPTION: Recargas internacionales: Compra una recarga internacional. client_purchase_id hace la operacion idempotente y no debe reutilizarse para otra compra. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - country | required=Depende | type=string | description=Codigo ISO 3166-1 alpha-2 del pais. En el catalogo eSIM es obligatorio cuando mode es plans u offers. | example=CU - brand | required=Depende | type=string | description=Marca u operador devuelto por el catalogo. | example=Cubacel - offer_id | required=Si en compra | type=string | description=Identificador exacto de la oferta seleccionada. | example=61 - phone_number | required=Si en compra | type=string | description=Numero de telefono que recibira la recarga. | example=+5351234567 - client_purchase_id | required=Si en compra | type=string | description=Idempotency key unica creada por tu sistema para esta compra. | example=order-2026-000184 - promo_code | required=Depende | type=string | description=Codigo promocional que se desea validar o aplicar. | example=PROMO2026 - amount | required=No | type=number | description=Monto elegido cuando la oferta permite un rango. | example=25.00 - language | required=No | type=string | description=Idioma de la respuesta: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v2/store/topups/buy' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"country":"CU","brand":"Cubacel","offer_id":"61","phone_number":"+5351234567","client_purchase_id":"topup-2026-000184","language":"es"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/store/topups/buy', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "country": "CU", "brand": "Cubacel", "offer_id": "61", "phone_number": "+5351234567", "client_purchase_id": "topup-2026-000184", "language": "es" }) }).then(r => r.json()).then(console.log); ``` ### Esquema de respuesta verificado ```json [ { "success": "boolean", "code": "string | integer", "message": "string", "data": "Direct record fields under Developer data (no extra order wrapper). Status adds credito; eSIM/number status adds poll_after_seconds.", "error": "object | array", "time": "object" }, { "topup_buy_pending": { "order_id": "dynamic", "order_status": "dynamic", "brand": "dynamic", "sent_benefits": "dynamic", "phone_masked": "dynamic", "charged_amount": "dynamic", "price_before_discount": "dynamic", "discount_amount": "dynamic", "promo_code": "dynamic", "credito": "dynamic" } } ] ``` ### Errores específicos - HTTP 401 | API key invalida ```json { "success": false, "code": 40101, "message": "Invalid API key." } ``` - HTTP 422 | Parametro requerido ```json { "success": false, "code": 47017, "message": "Required field is missing: client_purchase_id" } ``` - HTTP 502 | Servicio temporalmente no disponible ```json { "success": false, "code": 47020, "message": "The Store service is temporarily unavailable." } ``` ### Notas - No envies userIdentifier: el usuario KeyPay se obtiene del developer autenticado. - Las compras requieren client_purchase_id unico. Si repites la misma solicitud usa exactamente el mismo valor. - El catalogo determina los identificadores, montos y campos validos; no construyas offer_id, service_id ni e164 manualmente. - La API puede devolver pending, processing, completed, failed o refunded segun el producto. - Esquema parcial verificado en el código de KeyPay. Los valores dynamic se resuelven en ejecución; no representan una respuesta JSON de producción. Los datos externos sin contrato verificable se omiten. --- ## Endpoint: POST /v2/store/topups/orders ID: store-v2-topups-orders ACTION: Consultar órdenes METHOD: POST PATH: /v2/store/topups/orders URL: https://api.innovapp-soft.com/v2/store/topups/orders AUTH: Bearer API Key DESCRIPTION: Recargas internacionales: Devuelve el historial paginado de recargas del usuario KeyPay vinculado al developer. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - page | required=No | type=integer | description=Pagina del historial. | example=1 - per_page | required=No | type=integer | description=Resultados por pagina, maximo 100. | example=20 - language | required=No | type=string | description=Idioma de la respuesta: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v2/store/topups/orders' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"page":1,"per_page":20,"language":"es"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/store/topups/orders', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "page": 1, "per_page": 20, "language": "es" }) }).then(r => r.json()).then(console.log); ``` ### Esquema de respuesta verificado ```json [ { "success": "boolean", "code": "string | integer", "message": "string", "data": "{data:[record],page,per_page,total,total_pages}", "error": "object | array", "time": "object" }, { "topup_order": { "order_id": "dynamic", "order_status": "dynamic", "country": "dynamic", "brand": "dynamic", "offer_name": "dynamic", "sent_benefits": "dynamic", "phone_masked": "dynamic", "requested_amount": "dynamic", "charged_amount": "dynamic", "price_before_discount": "dynamic", "discount_amount": "dynamic", "promo_code": "dynamic", "mensaje": "dynamic" } } ] ``` ### Errores específicos - HTTP 401 | API key invalida ```json { "success": false, "code": 40101, "message": "Invalid API key." } ``` - HTTP 422 | Parametro requerido ```json { "success": false, "code": 47017, "message": "Required field is missing: client_purchase_id" } ``` - HTTP 502 | Servicio temporalmente no disponible ```json { "success": false, "code": 47020, "message": "The Store service is temporarily unavailable." } ``` ### Notas - No envies userIdentifier: el usuario KeyPay se obtiene del developer autenticado. - Las compras requieren client_purchase_id unico. Si repites la misma solicitud usa exactamente el mismo valor. - El catalogo determina los identificadores, montos y campos validos; no construyas offer_id, service_id ni e164 manualmente. - La API puede devolver pending, processing, completed, failed o refunded segun el producto. - Esquema parcial verificado en el código de KeyPay. Los valores dynamic se resuelven en ejecución; no representan una respuesta JSON de producción. Los datos externos sin contrato verificable se omiten. --- ## Endpoint: POST /v2/store/topups/status ID: store-v2-topups-status ACTION: Consultar estado METHOD: POST PATH: /v2/store/topups/status URL: https://api.innovapp-soft.com/v2/store/topups/status AUTH: Bearer API Key DESCRIPTION: Recargas internacionales: Consulta el estado actualizado de una recarga. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - order_id | required=Si en status | type=string | description=Identificador de la orden devuelto al crearla. | example=1842 - language | required=No | type=string | description=Idioma de la respuesta: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v2/store/topups/status' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"order_id":"1842","language":"es"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/store/topups/status', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "order_id": "1842", "language": "es" }) }).then(r => r.json()).then(console.log); ``` ### Esquema de respuesta verificado ```json [ { "success": "boolean", "code": "string | integer", "message": "string", "data": "Direct record fields under Developer data (no extra order wrapper). Status adds credito; eSIM/number status adds poll_after_seconds.", "error": "object | array", "time": "object" }, { "topup_order": { "order_id": "dynamic", "order_status": "dynamic", "country": "dynamic", "brand": "dynamic", "offer_name": "dynamic", "sent_benefits": "dynamic", "phone_masked": "dynamic", "requested_amount": "dynamic", "charged_amount": "dynamic", "price_before_discount": "dynamic", "discount_amount": "dynamic", "promo_code": "dynamic", "mensaje": "dynamic" } } ] ``` ### Errores específicos - HTTP 401 | API key invalida ```json { "success": false, "code": 40101, "message": "Invalid API key." } ``` - HTTP 422 | Parametro requerido ```json { "success": false, "code": 47017, "message": "Required field is missing: client_purchase_id" } ``` - HTTP 502 | Servicio temporalmente no disponible ```json { "success": false, "code": 47020, "message": "The Store service is temporarily unavailable." } ``` ### Notas - No envies userIdentifier: el usuario KeyPay se obtiene del developer autenticado. - Las compras requieren client_purchase_id unico. Si repites la misma solicitud usa exactamente el mismo valor. - El catalogo determina los identificadores, montos y campos validos; no construyas offer_id, service_id ni e164 manualmente. - La API puede devolver pending, processing, completed, failed o refunded segun el producto. - Esquema parcial verificado en el código de KeyPay. Los valores dynamic se resuelven en ejecución; no representan una respuesta JSON de producción. Los datos externos sin contrato verificable se omiten. --- # Grupo: Store V2 · Gift Cards Flujo recomendado: consultar marcas y ofertas, comprar y después consultar las órdenes o el estado de entrega. ## Endpoint: POST /v2/store/giftcards/catalog ID: store-v2-giftcards-catalog ACTION: Consultar catálogo METHOD: POST PATH: /v2/store/giftcards/catalog URL: https://api.innovapp-soft.com/v2/store/giftcards/catalog AUTH: Bearer API Key DESCRIPTION: Gift Cards: Lista marcas y ofertas de Gift Cards V2 por pais, categoria o busqueda. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - mode | required=No | type=string | description=Vista del catalogo. En eSIM usa countries para listar destinos y plans (u offers como alias) para listar los planes del country enviado. | example=countries - country | required=Depende | type=string | description=Codigo ISO 3166-1 alpha-2 del pais. En el catalogo eSIM es obligatorio cuando mode es plans u offers. | example=CU - brand | required=Depende | type=string | description=Marca u operador devuelto por el catalogo. | example=Cubacel - query | required=No | type=string | description=Texto para filtrar el catalogo. | example=BRAND_FROM_CATALOG - category | required=No | type=string | description=Categoria del catalogo. | example=Gaming - page | required=No | type=integer | description=Pagina del historial. | example=1 - per_page | required=No | type=integer | description=Resultados por pagina, maximo 100. | example=20 - language | required=No | type=string | description=Idioma de la respuesta: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v2/store/giftcards/catalog' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"mode":"countries","country":"US","page":1,"per_page":20,"language":"es"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/store/giftcards/catalog', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "mode": "countries", "country": "US", "page": 1, "per_page": 20, "language": "es" }) }).then(r => r.json()).then(console.log); ``` ### Esquema de respuesta verificado ```json [ { "success": "boolean", "code": "string | integer", "message": "string", "data": "Mode/resource-specific local object; catalog arrays are named data, not generic items. See controller source and local model.", "error": "object | array", "time": "object" }, { "giftcard_offer": { "id": "dynamic", "offer_id": "dynamic", "name": "dynamic", "notes": "dynamic", "sent_benefits": "dynamic", "sub_type": "dynamic", "price_type": "dynamic", "denomination": "dynamic", "currency": "dynamic", "price": "dynamic", "fee_percent": "dynamic", "image": "dynamic" } } ] ``` ### Errores específicos - HTTP 401 | API key invalida ```json { "success": false, "code": 40101, "message": "Invalid API key." } ``` - HTTP 422 | Parametro requerido ```json { "success": false, "code": 47017, "message": "Required field is missing: client_purchase_id" } ``` - HTTP 502 | Servicio temporalmente no disponible ```json { "success": false, "code": 47020, "message": "The Store service is temporarily unavailable." } ``` ### Notas - No envies userIdentifier: el usuario KeyPay se obtiene del developer autenticado. - Las compras requieren client_purchase_id unico. Si repites la misma solicitud usa exactamente el mismo valor. - El catalogo determina los identificadores, montos y campos validos; no construyas offer_id, service_id ni e164 manualmente. - La API puede devolver pending, processing, completed, failed o refunded segun el producto. - Esquema parcial verificado en el código de KeyPay. Los valores dynamic se resuelven en ejecución; no representan una respuesta JSON de producción. Los datos externos sin contrato verificable se omiten. --- ## Endpoint: POST /v2/store/giftcards/buy ID: store-v2-giftcards-buy ACTION: Comprar METHOD: POST PATH: /v2/store/giftcards/buy URL: https://api.innovapp-soft.com/v2/store/giftcards/buy AUTH: Bearer API Key DESCRIPTION: Gift Cards: Compra una Gift Card fija o de rango. KeyPay requiere amount mayor que cero. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - brand | required=Depende | type=string | description=Marca u operador devuelto por el catalogo. | example=Cubacel - country | required=Depende | type=string | description=Codigo ISO 3166-1 alpha-2 del pais. En el catalogo eSIM es obligatorio cuando mode es plans u offers. | example=CU - offer_id | required=Si en compra | type=string | description=Identificador exacto de la oferta seleccionada. | example=61 - client_purchase_id | required=Si en compra | type=string | description=Idempotency key unica creada por tu sistema para esta compra. | example=order-2026-000184 - amount | required=Sí | type=number | description=Importe mayor que cero requerido por KeyPay para la compra. | example=25.00 - language | required=No | type=string | description=Idioma de la respuesta: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v2/store/giftcards/buy' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"brand":"BRAND_FROM_CATALOG","country":"US","offer_id":"OFFER_ID_FROM_CATALOG","client_purchase_id":"gift-2026-000184","amount":25,"language":"es"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/store/giftcards/buy', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "brand": "BRAND_FROM_CATALOG", "country": "US", "offer_id": "OFFER_ID_FROM_CATALOG", "client_purchase_id": "gift-2026-000184", "amount": 25, "language": "es" }) }).then(r => r.json()).then(console.log); ``` ### Esquema de respuesta verificado ```json [ { "success": "boolean", "code": "string | integer", "message": "string", "data": "Direct record fields under Developer data (no extra order wrapper). Status adds credito; eSIM/number status adds poll_after_seconds.", "error": "object | array", "time": "object" }, { "giftcard_order": { "order_id": "dynamic", "order_status": "dynamic", "brand": "dynamic", "country": "dynamic", "denomination": "dynamic", "charged_amount": "dynamic", "mensaje": "dynamic", "details": "dynamic" }, "giftcard_detail": { "titulo": "dynamic", "value": "dynamic", "copy": "dynamic", "url": "dynamic" } } ] ``` ### Errores específicos - HTTP 401 | API key invalida ```json { "success": false, "code": 40101, "message": "Invalid API key." } ``` - HTTP 422 | Parametro requerido ```json { "success": false, "code": 47017, "message": "Required field is missing: client_purchase_id" } ``` - HTTP 502 | Servicio temporalmente no disponible ```json { "success": false, "code": 47020, "message": "The Store service is temporarily unavailable." } ``` ### Notas - No envies userIdentifier: el usuario KeyPay se obtiene del developer autenticado. - Las compras requieren client_purchase_id unico. Si repites la misma solicitud usa exactamente el mismo valor. - El catalogo determina los identificadores, montos y campos validos; no construyas offer_id, service_id ni e164 manualmente. - La API puede devolver pending, processing, completed, failed o refunded segun el producto. - Esquema parcial verificado en el código de KeyPay. Los valores dynamic se resuelven en ejecución; no representan una respuesta JSON de producción. Los datos externos sin contrato verificable se omiten. --- ## Endpoint: POST /v2/store/giftcards/orders ID: store-v2-giftcards-orders ACTION: Consultar órdenes METHOD: POST PATH: /v2/store/giftcards/orders URL: https://api.innovapp-soft.com/v2/store/giftcards/orders AUTH: Bearer API Key DESCRIPTION: Gift Cards: Devuelve las ordenes de Gift Cards del usuario vinculado. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - page | required=No | type=integer | description=Pagina del historial. | example=1 - per_page | required=No | type=integer | description=Resultados por pagina, maximo 100. | example=20 - language | required=No | type=string | description=Idioma de la respuesta: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v2/store/giftcards/orders' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"page":1,"per_page":20,"language":"es"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/store/giftcards/orders', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "page": 1, "per_page": 20, "language": "es" }) }).then(r => r.json()).then(console.log); ``` ### Esquema de respuesta verificado ```json [ { "success": "boolean", "code": "string | integer", "message": "string", "data": "{data:[record],page,per_page,total,total_pages}", "error": "object | array", "time": "object" }, { "giftcard_order": { "order_id": "dynamic", "order_status": "dynamic", "brand": "dynamic", "country": "dynamic", "denomination": "dynamic", "charged_amount": "dynamic", "mensaje": "dynamic", "details": "dynamic" }, "giftcard_detail": { "titulo": "dynamic", "value": "dynamic", "copy": "dynamic", "url": "dynamic" } } ] ``` ### Errores específicos - HTTP 401 | API key invalida ```json { "success": false, "code": 40101, "message": "Invalid API key." } ``` - HTTP 422 | Parametro requerido ```json { "success": false, "code": 47017, "message": "Required field is missing: client_purchase_id" } ``` - HTTP 502 | Servicio temporalmente no disponible ```json { "success": false, "code": 47020, "message": "The Store service is temporarily unavailable." } ``` ### Notas - No envies userIdentifier: el usuario KeyPay se obtiene del developer autenticado. - Las compras requieren client_purchase_id unico. Si repites la misma solicitud usa exactamente el mismo valor. - El catalogo determina los identificadores, montos y campos validos; no construyas offer_id, service_id ni e164 manualmente. - La API puede devolver pending, processing, completed, failed o refunded segun el producto. - Esquema parcial verificado en el código de KeyPay. Los valores dynamic se resuelven en ejecución; no representan una respuesta JSON de producción. Los datos externos sin contrato verificable se omiten. --- ## Endpoint: POST /v2/store/giftcards/status ID: store-v2-giftcards-status ACTION: Consultar estado METHOD: POST PATH: /v2/store/giftcards/status URL: https://api.innovapp-soft.com/v2/store/giftcards/status AUTH: Bearer API Key DESCRIPTION: Gift Cards: Consulta una orden y sus datos de entrega cuando ya estan disponibles. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - order_id | required=Si en status | type=string | description=Identificador de la orden devuelto al crearla. | example=1842 - language | required=No | type=string | description=Idioma de la respuesta: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v2/store/giftcards/status' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"order_id":"1842","language":"es"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/store/giftcards/status', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "order_id": "1842", "language": "es" }) }).then(r => r.json()).then(console.log); ``` ### Esquema de respuesta verificado ```json [ { "success": "boolean", "code": "string | integer", "message": "string", "data": "Direct record fields under Developer data (no extra order wrapper). Status adds credito; eSIM/number status adds poll_after_seconds.", "error": "object | array", "time": "object" }, { "giftcard_order": { "order_id": "dynamic", "order_status": "dynamic", "brand": "dynamic", "country": "dynamic", "denomination": "dynamic", "charged_amount": "dynamic", "mensaje": "dynamic", "details": "dynamic" }, "giftcard_detail": { "titulo": "dynamic", "value": "dynamic", "copy": "dynamic", "url": "dynamic" } } ] ``` ### Errores específicos - HTTP 401 | API key invalida ```json { "success": false, "code": 40101, "message": "Invalid API key." } ``` - HTTP 422 | Parametro requerido ```json { "success": false, "code": 47017, "message": "Required field is missing: client_purchase_id" } ``` - HTTP 502 | Servicio temporalmente no disponible ```json { "success": false, "code": 47020, "message": "The Store service is temporarily unavailable." } ``` ### Notas - No envies userIdentifier: el usuario KeyPay se obtiene del developer autenticado. - Las compras requieren client_purchase_id unico. Si repites la misma solicitud usa exactamente el mismo valor. - El catalogo determina los identificadores, montos y campos validos; no construyas offer_id, service_id ni e164 manualmente. - La API puede devolver pending, processing, completed, failed o refunded segun el producto. - Esquema parcial verificado en el código de KeyPay. Los valores dynamic se resuelven en ejecución; no representan una respuesta JSON de producción. Los datos externos sin contrato verificable se omiten. --- # Grupo: Store V2 · Servicios IMEI Flujo recomendado: consultar servicios y campos requeridos, crear la solicitud y después revisar su resultado. ## Endpoint: POST /v2/store/imei/catalog ID: store-v2-imei-catalog ACTION: Consultar catálogo METHOD: POST PATH: /v2/store/imei/catalog URL: https://api.innovapp-soft.com/v2/store/imei/catalog AUTH: Bearer API Key DESCRIPTION: Servicios IMEI: Lista los servicios IMEI disponibles y los campos que requiere cada uno. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - page | required=No | type=integer | description=Pagina del historial. | example=1 - per_page | required=No | type=integer | description=Resultados por pagina, maximo 100. | example=20 - search | required=No | type=string | description=Texto para buscar un servicio IMEI. | example=iPhone - language | required=No | type=string | description=Idioma de la respuesta: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v2/store/imei/catalog' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"page":1,"per_page":20,"search":"iPhone","language":"es"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/store/imei/catalog', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "page": 1, "per_page": 20, "search": "iPhone", "language": "es" }) }).then(r => r.json()).then(console.log); ``` ### Esquema de respuesta verificado ```json [ { "success": "boolean", "code": "string | integer", "message": "string", "data": "Mode/resource-specific local object; catalog arrays are named data, not generic items. See controller source and local model.", "error": "object | array", "time": "object" }, { "imei_offer": { "id": "dynamic", "service_id": "dynamic", "titulo": "dynamic", "detalles": "dynamic", "categoria": "dynamic", "precio": "dynamic", "discoin": "dynamic", "currency": "dynamic", "disponibles": "dynamic", "input": "dynamic", "inputtypes": "dynamic", "required_input_type": "dynamic" } } ] ``` ### Errores específicos - HTTP 401 | API key invalida ```json { "success": false, "code": 40101, "message": "Invalid API key." } ``` - HTTP 422 | Parametro requerido ```json { "success": false, "code": 47017, "message": "Required field is missing: client_purchase_id" } ``` - HTTP 502 | Servicio temporalmente no disponible ```json { "success": false, "code": 47020, "message": "The Store service is temporarily unavailable." } ``` ### Notas - No envies userIdentifier: el usuario KeyPay se obtiene del developer autenticado. - Las compras requieren client_purchase_id unico. Si repites la misma solicitud usa exactamente el mismo valor. - El catalogo determina los identificadores, montos y campos validos; no construyas offer_id, service_id ni e164 manualmente. - La API puede devolver pending, processing, completed, failed o refunded segun el producto. - Esquema parcial verificado en el código de KeyPay. Los valores dynamic se resuelven en ejecución; no representan una respuesta JSON de producción. Los datos externos sin contrato verificable se omiten. --- ## Endpoint: POST /v2/store/imei/buy ID: store-v2-imei-buy ACTION: Comprar METHOD: POST PATH: /v2/store/imei/buy URL: https://api.innovapp-soft.com/v2/store/imei/buy AUTH: Bearer API Key DESCRIPTION: Servicios IMEI: Solicita un servicio IMEI. Envia input con los mismos nombres de campo entregados por el catalogo. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - service_id | required=Si en compra | type=string | description=Identificador del servicio IMEI. | example=115 - device_id | required=Depende | type=string | description=IMEI, serial u otro identificador solicitado por el servicio. | example=356938035643809 - input | required=Depende | type=object | description=Campos dinamicos solicitados por el servicio IMEI. | example={"IMEI":"356938035643809"} - client_purchase_id | required=Si en compra | type=string | description=Idempotency key unica creada por tu sistema para esta compra. | example=order-2026-000184 - language | required=No | type=string | description=Idioma de la respuesta: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v2/store/imei/buy' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"service_id":"115","input":{"IMEI":"356938035643809"},"client_purchase_id":"imei-2026-000184","language":"es"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/store/imei/buy', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "service_id": "115", "input": { "IMEI": "356938035643809" }, "client_purchase_id": "imei-2026-000184", "language": "es" }) }).then(r => r.json()).then(console.log); ``` ### Esquema de respuesta verificado ```json [ { "success": "boolean", "code": "string | integer", "message": "string", "data": "Direct record fields under Developer data (no extra order wrapper). Status adds credito; eSIM/number status adds poll_after_seconds.", "error": "object | array", "time": "object" }, { "imei_order": { "order_id": "dynamic", "order_status": "dynamic", "service_id": "dynamic", "service_name": "dynamic", "device_id": "dynamic", "charged_amount": "dynamic", "created_at": "dynamic", "completed_at": "dynamic", "details": "dynamic", "mensaje": "dynamic" } } ] ``` ### Errores específicos - HTTP 401 | API key invalida ```json { "success": false, "code": 40101, "message": "Invalid API key." } ``` - HTTP 422 | Parametro requerido ```json { "success": false, "code": 47017, "message": "Required field is missing: client_purchase_id" } ``` - HTTP 502 | Servicio temporalmente no disponible ```json { "success": false, "code": 47020, "message": "The Store service is temporarily unavailable." } ``` ### Notas - No envies userIdentifier: el usuario KeyPay se obtiene del developer autenticado. - Las compras requieren client_purchase_id unico. Si repites la misma solicitud usa exactamente el mismo valor. - El catalogo determina los identificadores, montos y campos validos; no construyas offer_id, service_id ni e164 manualmente. - La API puede devolver pending, processing, completed, failed o refunded segun el producto. - Esquema parcial verificado en el código de KeyPay. Los valores dynamic se resuelven en ejecución; no representan una respuesta JSON de producción. Los datos externos sin contrato verificable se omiten. --- ## Endpoint: POST /v2/store/imei/orders ID: store-v2-imei-orders ACTION: Consultar órdenes METHOD: POST PATH: /v2/store/imei/orders URL: https://api.innovapp-soft.com/v2/store/imei/orders AUTH: Bearer API Key DESCRIPTION: Servicios IMEI: Devuelve el historial paginado de solicitudes IMEI. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - page | required=No | type=integer | description=Pagina del historial. | example=1 - per_page | required=No | type=integer | description=Resultados por pagina, maximo 100. | example=20 - language | required=No | type=string | description=Idioma de la respuesta: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v2/store/imei/orders' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"page":1,"per_page":20,"language":"es"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/store/imei/orders', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "page": 1, "per_page": 20, "language": "es" }) }).then(r => r.json()).then(console.log); ``` ### Esquema de respuesta verificado ```json [ { "success": "boolean", "code": "string | integer", "message": "string", "data": "{data:[record],pagination:{page,per_page,total,total_pages,has_more}}", "error": "object | array", "time": "object" }, { "imei_order": { "order_id": "dynamic", "order_status": "dynamic", "service_id": "dynamic", "service_name": "dynamic", "device_id": "dynamic", "charged_amount": "dynamic", "created_at": "dynamic", "completed_at": "dynamic", "details": "dynamic", "mensaje": "dynamic" } } ] ``` ### Errores específicos - HTTP 401 | API key invalida ```json { "success": false, "code": 40101, "message": "Invalid API key." } ``` - HTTP 422 | Parametro requerido ```json { "success": false, "code": 47017, "message": "Required field is missing: client_purchase_id" } ``` - HTTP 502 | Servicio temporalmente no disponible ```json { "success": false, "code": 47020, "message": "The Store service is temporarily unavailable." } ``` ### Notas - No envies userIdentifier: el usuario KeyPay se obtiene del developer autenticado. - Las compras requieren client_purchase_id unico. Si repites la misma solicitud usa exactamente el mismo valor. - El catalogo determina los identificadores, montos y campos validos; no construyas offer_id, service_id ni e164 manualmente. - La API puede devolver pending, processing, completed, failed o refunded segun el producto. - Esquema parcial verificado en el código de KeyPay. Los valores dynamic se resuelven en ejecución; no representan una respuesta JSON de producción. Los datos externos sin contrato verificable se omiten. --- ## Endpoint: POST /v2/store/imei/status ID: store-v2-imei-status ACTION: Consultar estado METHOD: POST PATH: /v2/store/imei/status URL: https://api.innovapp-soft.com/v2/store/imei/status AUTH: Bearer API Key DESCRIPTION: Servicios IMEI: Consulta el estado y el resultado de una solicitud IMEI. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - order_id | required=Si en status | type=string | description=Identificador de la orden devuelto al crearla. | example=1842 - language | required=No | type=string | description=Idioma de la respuesta: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v2/store/imei/status' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"order_id":"1842","language":"es"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/store/imei/status', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "order_id": "1842", "language": "es" }) }).then(r => r.json()).then(console.log); ``` ### Esquema de respuesta verificado ```json [ { "success": "boolean", "code": "string | integer", "message": "string", "data": "Direct record fields under Developer data (no extra order wrapper). Status adds credito; eSIM/number status adds poll_after_seconds.", "error": "object | array", "time": "object" }, { "imei_order": { "order_id": "dynamic", "order_status": "dynamic", "service_id": "dynamic", "service_name": "dynamic", "device_id": "dynamic", "charged_amount": "dynamic", "created_at": "dynamic", "completed_at": "dynamic", "details": "dynamic", "mensaje": "dynamic" } } ] ``` ### Errores específicos - HTTP 401 | API key invalida ```json { "success": false, "code": 40101, "message": "Invalid API key." } ``` - HTTP 422 | Parametro requerido ```json { "success": false, "code": 47017, "message": "Required field is missing: client_purchase_id" } ``` - HTTP 502 | Servicio temporalmente no disponible ```json { "success": false, "code": 47020, "message": "The Store service is temporarily unavailable." } ``` ### Notas - No envies userIdentifier: el usuario KeyPay se obtiene del developer autenticado. - Las compras requieren client_purchase_id unico. Si repites la misma solicitud usa exactamente el mismo valor. - El catalogo determina los identificadores, montos y campos validos; no construyas offer_id, service_id ni e164 manualmente. - La API puede devolver pending, processing, completed, failed o refunded segun el producto. - Esquema parcial verificado en el código de KeyPay. Los valores dynamic se resuelven en ejecución; no representan una respuesta JSON de producción. Los datos externos sin contrato verificable se omiten. --- # Grupo: Store V2 · eSIM Flujo recomendado: consultar destinos y planes, comprar la eSIM y después consultar sus datos de instalación. ## Endpoint: POST /v2/store/esim/catalog ID: store-v2-esim-catalog ACTION: Consultar catálogo METHOD: POST PATH: /v2/store/esim/catalog URL: https://api.innovapp-soft.com/v2/store/esim/catalog AUTH: Bearer API Key DESCRIPTION: eSIM: Consulta los paises o los planes disponibles del catalogo eSIM. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - mode | required=No | type=enum | description=Valores permitidos: countries (lista paises), plans (lista planes del country) y offers (alias de plans). Predeterminado: countries. | example=plans - country | required=Si para plans/offers | type=string(2) | description=Codigo ISO 3166-1 alpha-2. Omitir con countries; obligatorio con plans u offers. | example=US - language | required=No | type=string | description=Idioma de la respuesta: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v2/store/esim/catalog' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"mode":"plans","country":"US","language":"es"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/store/esim/catalog', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "mode": "plans", "country": "US", "language": "es" }) }).then(r => r.json()).then(console.log); ``` ### Esquema de respuesta verificado ```json [ { "success": "boolean", "code": "string | integer", "message": "string", "data": "Mode/resource-specific local object; catalog arrays are named data, not generic items. See controller source and local model.", "error": "object | array", "time": "object" }, { "esim_offer": { "id": "dynamic", "offer_id": "dynamic", "name": "dynamic", "sent_benefits": "dynamic", "region": "dynamic", "sub_type": "dynamic", "price_type": "dynamic", "price": "dynamic", "fee_percent": "dynamic" } } ] ``` ### Errores específicos - HTTP 401 | API key invalida ```json { "success": false, "code": 40101, "message": "Invalid API key." } ``` - HTTP 422 | Parametro requerido ```json { "success": false, "code": 47017, "message": "Required field is missing: client_purchase_id" } ``` - HTTP 502 | Servicio temporalmente no disponible ```json { "success": false, "code": 47020, "message": "The Store service is temporarily unavailable." } ``` ### Notas - No envies userIdentifier: el usuario KeyPay se obtiene del developer autenticado. - Las compras requieren client_purchase_id unico. Si repites la misma solicitud usa exactamente el mismo valor. - El catalogo determina los identificadores, montos y campos validos; no construyas offer_id, service_id ni e164 manualmente. - La API puede devolver pending, processing, completed, failed o refunded segun el producto. - Esquema parcial verificado en el código de KeyPay. Los valores dynamic se resuelven en ejecución; no representan una respuesta JSON de producción. Los datos externos sin contrato verificable se omiten. --- ## Endpoint: POST /v2/store/esim/buy ID: store-v2-esim-buy ACTION: Comprar METHOD: POST PATH: /v2/store/esim/buy URL: https://api.innovapp-soft.com/v2/store/esim/buy AUTH: Bearer API Key DESCRIPTION: eSIM: Compra uno de los planes devueltos por el catalogo eSIM. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - country | required=Si | type=string(2) | description=Mismo codigo ISO utilizado para consultar los planes. | example=US - offer_id | required=Si | type=string | description=Valor exacto de offer_id devuelto por el catalogo con mode=plans. | example=OFFER_ID_FROM_CATALOG - client_purchase_id | required=Si | type=string(8..100) | description=Clave de idempotencia creada por tu sistema. Admite letras, numeros, punto, guion bajo, dos puntos y guion. Reutilizar solo al reintentar la misma compra. | example=esim-2026-000184 - language | required=No | type=string | description=Idioma de la respuesta: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v2/store/esim/buy' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"country":"US","offer_id":"OFFER_ID_FROM_CATALOG","client_purchase_id":"esim-2026-000184","language":"es"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/store/esim/buy', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "country": "US", "offer_id": "OFFER_ID_FROM_CATALOG", "client_purchase_id": "esim-2026-000184", "language": "es" }) }).then(r => r.json()).then(console.log); ``` ### Esquema de respuesta verificado ```json [ { "success": "boolean", "code": "string | integer", "message": "string", "data": "Direct record fields under Developer data (no extra order wrapper). Status adds credito; eSIM/number status adds poll_after_seconds.", "error": "object | array", "time": "object" }, { "esim_order": { "order_id": "dynamic", "order_status": "dynamic", "country": "dynamic", "offer_id": "dynamic", "plan": "dynamic", "region": "dynamic", "sub_type": "dynamic", "charged_amount": "dynamic", "mensaje": "dynamic", "activation": "dynamic" }, "esim_activation": { "lpa": "dynamic", "smdp_address": "dynamic", "activation_code": "dynamic", "iccid": "dynamic" } } ] ``` ### Errores específicos - HTTP 401 | API key invalida ```json { "success": false, "code": 40101, "message": "Invalid API key." } ``` - HTTP 422 | Parametro requerido ```json { "success": false, "code": 47017, "message": "Required field is missing: client_purchase_id" } ``` - HTTP 502 | Servicio temporalmente no disponible ```json { "success": false, "code": 47020, "message": "The Store service is temporarily unavailable." } ``` ### Notas - No envies userIdentifier: el usuario KeyPay se obtiene del developer autenticado. - Las compras requieren client_purchase_id unico. Si repites la misma solicitud usa exactamente el mismo valor. - El catalogo determina los identificadores, montos y campos validos; no construyas offer_id, service_id ni e164 manualmente. - La API puede devolver pending, processing, completed, failed o refunded segun el producto. - Esquema parcial verificado en el código de KeyPay. Los valores dynamic se resuelven en ejecución; no representan una respuesta JSON de producción. Los datos externos sin contrato verificable se omiten. --- ## Endpoint: POST /v2/store/esim/orders ID: store-v2-esim-orders ACTION: Consultar órdenes METHOD: POST PATH: /v2/store/esim/orders URL: https://api.innovapp-soft.com/v2/store/esim/orders AUTH: Bearer API Key DESCRIPTION: eSIM: Devuelve las ordenes eSIM del usuario vinculado. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - page | required=No | type=integer | description=Pagina del historial. | example=1 - per_page | required=No | type=integer | description=Resultados por pagina, maximo 100. | example=20 - language | required=No | type=string | description=Idioma de la respuesta: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v2/store/esim/orders' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"page":1,"per_page":20,"language":"es"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/store/esim/orders', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "page": 1, "per_page": 20, "language": "es" }) }).then(r => r.json()).then(console.log); ``` ### Esquema de respuesta verificado ```json [ { "success": "boolean", "code": "string | integer", "message": "string", "data": "{data:[record],page,per_page,total,total_pages}", "error": "object | array", "time": "object" }, { "esim_order": { "order_id": "dynamic", "order_status": "dynamic", "country": "dynamic", "offer_id": "dynamic", "plan": "dynamic", "region": "dynamic", "sub_type": "dynamic", "charged_amount": "dynamic", "mensaje": "dynamic", "activation": "dynamic" }, "esim_activation": { "lpa": "dynamic", "smdp_address": "dynamic", "activation_code": "dynamic", "iccid": "dynamic" } } ] ``` ### Errores específicos - HTTP 401 | API key invalida ```json { "success": false, "code": 40101, "message": "Invalid API key." } ``` - HTTP 422 | Parametro requerido ```json { "success": false, "code": 47017, "message": "Required field is missing: client_purchase_id" } ``` - HTTP 502 | Servicio temporalmente no disponible ```json { "success": false, "code": 47020, "message": "The Store service is temporarily unavailable." } ``` ### Notas - No envies userIdentifier: el usuario KeyPay se obtiene del developer autenticado. - Las compras requieren client_purchase_id unico. Si repites la misma solicitud usa exactamente el mismo valor. - El catalogo determina los identificadores, montos y campos validos; no construyas offer_id, service_id ni e164 manualmente. - La API puede devolver pending, processing, completed, failed o refunded segun el producto. - Esquema parcial verificado en el código de KeyPay. Los valores dynamic se resuelven en ejecución; no representan una respuesta JSON de producción. Los datos externos sin contrato verificable se omiten. --- ## Endpoint: POST /v2/store/esim/status ID: store-v2-esim-status ACTION: Consultar estado METHOD: POST PATH: /v2/store/esim/status URL: https://api.innovapp-soft.com/v2/store/esim/status AUTH: Bearer API Key DESCRIPTION: eSIM: Consulta una orden eSIM y sus datos de instalacion cuando esten disponibles. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - order_id | required=Si | type=string | description=Identificador publico devuelto por la compra; comienza con esimv2_. | example=esimv2_0123456789abcdef0123456789abcdef - language | required=No | type=string | description=Idioma de la respuesta: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v2/store/esim/status' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"order_id":"esimv2_0123456789abcdef0123456789abcdef","language":"es"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/store/esim/status', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "order_id": "esimv2_0123456789abcdef0123456789abcdef", "language": "es" }) }).then(r => r.json()).then(console.log); ``` ### Esquema de respuesta verificado ```json [ { "success": "boolean", "code": "string | integer", "message": "string", "data": "Direct record fields under Developer data (no extra order wrapper). Status adds credito; eSIM/number status adds poll_after_seconds.", "error": "object | array", "time": "object" }, { "esim_order": { "order_id": "dynamic", "order_status": "dynamic", "country": "dynamic", "offer_id": "dynamic", "plan": "dynamic", "region": "dynamic", "sub_type": "dynamic", "charged_amount": "dynamic", "mensaje": "dynamic", "activation": "dynamic" }, "esim_activation": { "lpa": "dynamic", "smdp_address": "dynamic", "activation_code": "dynamic", "iccid": "dynamic" } } ] ``` ### Errores específicos - HTTP 401 | API key invalida ```json { "success": false, "code": 40101, "message": "Invalid API key." } ``` - HTTP 422 | Parametro requerido ```json { "success": false, "code": 47017, "message": "Required field is missing: client_purchase_id" } ``` - HTTP 502 | Servicio temporalmente no disponible ```json { "success": false, "code": 47020, "message": "The Store service is temporarily unavailable." } ``` ### Notas - No envies userIdentifier: el usuario KeyPay se obtiene del developer autenticado. - Las compras requieren client_purchase_id unico. Si repites la misma solicitud usa exactamente el mismo valor. - El catalogo determina los identificadores, montos y campos validos; no construyas offer_id, service_id ni e164 manualmente. - La API puede devolver pending, processing, completed, failed o refunded segun el producto. - Esquema parcial verificado en el código de KeyPay. Los valores dynamic se resuelven en ejecución; no representan una respuesta JSON de producción. Los datos externos sin contrato verificable se omiten. --- # Grupo: Store V2 · Números virtuales Flujo recomendado: consultar disponibilidad, alquilar, listar tus números y después gestionar renovación, estado, conversaciones y mensajes. ## Endpoint: POST /v2/store/virtual-numbers/catalog ID: store-v2-virtual-numbers-catalog ACTION: Consultar catálogo METHOD: POST PATH: /v2/store/virtual-numbers/catalog URL: https://api.innovapp-soft.com/v2/store/virtual-numbers/catalog AUTH: Bearer API Key DESCRIPTION: Números virtuales: Lista los numeros virtuales que se pueden alquilar por pais. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - country | required=Depende | type=string | description=Codigo ISO 3166-1 alpha-2 del pais. En el catalogo eSIM es obligatorio cuando mode es plans u offers. | example=CU - limit | required=No | type=integer | description=Cantidad maxima de resultados, maximo 100. | example=20 - language | required=No | type=string | description=Idioma de la respuesta: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v2/store/virtual-numbers/catalog' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"country":"US","limit":20,"language":"es"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/store/virtual-numbers/catalog', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "country": "US", "limit": 20, "language": "es" }) }).then(r => r.json()).then(console.log); ``` ### Esquema de respuesta verificado ```json [ { "success": "boolean", "code": "string | integer", "message": "string", "data": "Mode/resource-specific local object; catalog arrays are named data, not generic items. See controller source and local model.", "error": "object | array", "time": "object" }, { "number_offer": { "country": "dynamic", "e164": "dynamic", "number_type": "dynamic", "price": "dynamic", "price_cents": "dynamic", "monthly_price": "dynamic", "monthly_price_cents": "dynamic", "billing_period_days": "dynamic", "recurring": "dynamic", "capabilities": "dynamic" } } ] ``` ### Errores específicos - HTTP 401 | API key invalida ```json { "success": false, "code": 40101, "message": "Invalid API key." } ``` - HTTP 422 | Parametro requerido ```json { "success": false, "code": 47017, "message": "Required field is missing: client_purchase_id" } ``` - HTTP 502 | Servicio temporalmente no disponible ```json { "success": false, "code": 47020, "message": "The Store service is temporarily unavailable." } ``` ### Notas - No envies userIdentifier: el usuario KeyPay se obtiene del developer autenticado. - Las compras requieren client_purchase_id unico. Si repites la misma solicitud usa exactamente el mismo valor. - El catalogo determina los identificadores, montos y campos validos; no construyas offer_id, service_id ni e164 manualmente. - La API puede devolver pending, processing, completed, failed o refunded segun el producto. - Esquema parcial verificado en el código de KeyPay. Los valores dynamic se resuelven en ejecución; no representan una respuesta JSON de producción. Los datos externos sin contrato verificable se omiten. --- ## Endpoint: POST /v2/store/virtual-numbers/rent ID: store-v2-virtual-numbers-rent ACTION: Alquilar número METHOD: POST PATH: /v2/store/virtual-numbers/rent URL: https://api.innovapp-soft.com/v2/store/virtual-numbers/rent AUTH: Bearer API Key DESCRIPTION: Números virtuales: Alquila el numero E.164 seleccionado en el catalogo. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - country | required=Depende | type=string | description=Codigo ISO 3166-1 alpha-2 del pais. En el catalogo eSIM es obligatorio cuando mode es plans u offers. | example=CU - e164 | required=Si en rent | type=string | description=Numero internacional E.164 seleccionado en el catalogo. | example=+12125550123 - client_purchase_id | required=Si en compra | type=string | description=Idempotency key unica creada por tu sistema para esta compra. | example=order-2026-000184 - language | required=No | type=string | description=Idioma de la respuesta: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v2/store/virtual-numbers/rent' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"country":"US","e164":"+12125550123","client_purchase_id":"number-2026-000184","language":"es"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/store/virtual-numbers/rent', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "country": "US", "e164": "+12125550123", "client_purchase_id": "number-2026-000184", "language": "es" }) }).then(r => r.json()).then(console.log); ``` ### Esquema de respuesta verificado ```json [ { "success": false, "code": "store.virtual_numbers.rent.failed", "message": "string", "data": [], "error": { "service": "virtual_numbers", "action": "string" }, "time": "object" } ] ``` ### Errores específicos - HTTP 401 | API key invalida ```json { "success": false, "code": 40101, "message": "Invalid API key." } ``` - HTTP 422 | Parametro requerido ```json { "success": false, "code": 47017, "message": "Required field is missing: client_purchase_id" } ``` - HTTP 502 | Servicio temporalmente no disponible ```json { "success": false, "code": 47020, "message": "The Store service is temporarily unavailable." } ``` ### Notas - No envies userIdentifier: el usuario KeyPay se obtiene del developer autenticado. - Las compras requieren client_purchase_id unico. Si repites la misma solicitud usa exactamente el mismo valor. - El catalogo determina los identificadores, montos y campos validos; no construyas offer_id, service_id ni e164 manualmente. - La API puede devolver pending, processing, completed, failed o refunded segun el producto. - Contrato con incidencia detectada: KeyPay sobrescribe status con el estado del número y el adaptador Developer lo interpreta como fallo. Esta respuesta no se simula como éxito. - Esquema parcial verificado en el código de KeyPay. Los valores dynamic se resuelven en ejecución; no representan una respuesta JSON de producción. Los datos externos sin contrato verificable se omiten. --- ## Endpoint: POST /v2/store/virtual-numbers/numbers ID: store-v2-virtual-numbers-numbers ACTION: Mis números METHOD: POST PATH: /v2/store/virtual-numbers/numbers URL: https://api.innovapp-soft.com/v2/store/virtual-numbers/numbers AUTH: Bearer API Key DESCRIPTION: Números virtuales: Lista los numeros virtuales alquilados por el usuario vinculado. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - page | required=No | type=integer | description=Pagina del historial. | example=1 - per_page | required=No | type=integer | description=Resultados por pagina, maximo 100. | example=20 - language | required=No | type=string | description=Idioma de la respuesta: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v2/store/virtual-numbers/numbers' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"page":1,"per_page":20,"language":"es"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/store/virtual-numbers/numbers', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "page": 1, "per_page": 20, "language": "es" }) }).then(r => r.json()).then(console.log); ``` ### Esquema de respuesta verificado ```json [ { "success": "boolean", "code": "string | integer", "message": "string", "data": "{data:[record],page,per_page,total,total_pages}", "error": "object | array", "time": "object" }, { "number_order": { "order_id": "dynamic", "number_id": "dynamic", "country": "dynamic", "e164": "dynamic", "status": "dynamic", "provider_status": "dynamic", "price": "dynamic", "renewal_price": "dynamic", "renews_at": "dynamic", "renewal_status": "dynamic", "auto_renew": "dynamic", "billing_period_days": "dynamic", "created_at": "dynamic", "activated_at": "dynamic", "capabilities": "dynamic" } } ] ``` ### Errores específicos - HTTP 401 | API key invalida ```json { "success": false, "code": 40101, "message": "Invalid API key." } ``` - HTTP 422 | Parametro requerido ```json { "success": false, "code": 47017, "message": "Required field is missing: client_purchase_id" } ``` - HTTP 502 | Servicio temporalmente no disponible ```json { "success": false, "code": 47020, "message": "The Store service is temporarily unavailable." } ``` ### Notas - No envies userIdentifier: el usuario KeyPay se obtiene del developer autenticado. - Las compras requieren client_purchase_id unico. Si repites la misma solicitud usa exactamente el mismo valor. - El catalogo determina los identificadores, montos y campos validos; no construyas offer_id, service_id ni e164 manualmente. - La API puede devolver pending, processing, completed, failed o refunded segun el producto. - Esquema parcial verificado en el código de KeyPay. Los valores dynamic se resuelven en ejecución; no representan una respuesta JSON de producción. Los datos externos sin contrato verificable se omiten. --- ## Endpoint: POST /v2/store/virtual-numbers/status ID: store-v2-virtual-numbers-status ACTION: Consultar estado METHOD: POST PATH: /v2/store/virtual-numbers/status URL: https://api.innovapp-soft.com/v2/store/virtual-numbers/status AUTH: Bearer API Key DESCRIPTION: Números virtuales: Consulta el estado de un numero virtual o de su orden. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - number_id | required=Depende | type=string | description=Identificador del numero virtual alquilado. | example=vn_1842 - order_id | required=Si en status | type=string | description=Identificador de la orden devuelto al crearla. | example=1842 - language | required=No | type=string | description=Idioma de la respuesta: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v2/store/virtual-numbers/status' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"number_id":"vn_1842","language":"es"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/store/virtual-numbers/status', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "number_id": "vn_1842", "language": "es" }) }).then(r => r.json()).then(console.log); ``` ### Esquema de respuesta verificado ```json [ { "success": false, "code": "store.virtual_numbers.status.failed", "message": "string", "data": [], "error": { "service": "virtual_numbers", "action": "string" }, "time": "object" } ] ``` ### Errores específicos - HTTP 401 | API key invalida ```json { "success": false, "code": 40101, "message": "Invalid API key." } ``` - HTTP 422 | Parametro requerido ```json { "success": false, "code": 47017, "message": "Required field is missing: client_purchase_id" } ``` - HTTP 502 | Servicio temporalmente no disponible ```json { "success": false, "code": 47020, "message": "The Store service is temporarily unavailable." } ``` ### Notas - No envies userIdentifier: el usuario KeyPay se obtiene del developer autenticado. - Las compras requieren client_purchase_id unico. Si repites la misma solicitud usa exactamente el mismo valor. - El catalogo determina los identificadores, montos y campos validos; no construyas offer_id, service_id ni e164 manualmente. - La API puede devolver pending, processing, completed, failed o refunded segun el producto. - Contrato con incidencia detectada: KeyPay sobrescribe status con el estado del número y el adaptador Developer lo interpreta como fallo. Esta respuesta no se simula como éxito. - Esquema parcial verificado en el código de KeyPay. Los valores dynamic se resuelven en ejecución; no representan una respuesta JSON de producción. Los datos externos sin contrato verificable se omiten. --- ## Endpoint: POST /v2/store/virtual-numbers/messages ID: store-v2-virtual-numbers-messages ACTION: Mensajes recibidos METHOD: POST PATH: /v2/store/virtual-numbers/messages URL: https://api.innovapp-soft.com/v2/store/virtual-numbers/messages AUTH: Bearer API Key DESCRIPTION: Números virtuales: Obtiene los mensajes recibidos por un numero virtual. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - number_id | required=Depende | type=string | description=Identificador del numero virtual alquilado. | example=vn_1842 - limit | required=No | type=integer | description=Cantidad maxima de resultados, maximo 100. | example=20 - cursor | required=No | type=integer | description=Cursor para continuar una lista de mensajes. | example=0 - conversation_id | required=No | type=string | description=Conversacion que se desea consultar. | example=conv_102 - language | required=No | type=string | description=Idioma de la respuesta: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v2/store/virtual-numbers/messages' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"number_id":"vn_1842","limit":20,"cursor":0,"language":"es"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/store/virtual-numbers/messages', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "number_id": "vn_1842", "limit": 20, "cursor": 0, "language": "es" }) }).then(r => r.json()).then(console.log); ``` ### Esquema de respuesta verificado ```json [ { "success": "boolean", "code": "string | integer", "message": "string", "data": "{number:number_order,data:[number_message],next_cursor:int|null,has_more:bool}", "error": "object | array", "time": "object" }, { "number_message": { "id": "dynamic", "conversation_id": "dynamic", "direction": "dynamic", "from": "dynamic", "to": "dynamic", "body": "dynamic", "attachments": "dynamic", "attachment_count": "dynamic", "segments": "dynamic", "status": "dynamic", "created_at": "dynamic", "is_read": "dynamic" } } ] ``` ### Errores específicos - HTTP 401 | API key invalida ```json { "success": false, "code": 40101, "message": "Invalid API key." } ``` - HTTP 422 | Parametro requerido ```json { "success": false, "code": 47017, "message": "Required field is missing: client_purchase_id" } ``` - HTTP 502 | Servicio temporalmente no disponible ```json { "success": false, "code": 47020, "message": "The Store service is temporarily unavailable." } ``` ### Notas - No envies userIdentifier: el usuario KeyPay se obtiene del developer autenticado. - Las compras requieren client_purchase_id unico. Si repites la misma solicitud usa exactamente el mismo valor. - El catalogo determina los identificadores, montos y campos validos; no construyas offer_id, service_id ni e164 manualmente. - La API puede devolver pending, processing, completed, failed o refunded segun el producto. - Esquema parcial verificado en el código de KeyPay. Los valores dynamic se resuelven en ejecución; no representan una respuesta JSON de producción. Los datos externos sin contrato verificable se omiten. --- ## Endpoint: POST /v2/store/virtual-numbers/conversations ID: store-v2-virtual-numbers-conversations ACTION: Conversaciones METHOD: POST PATH: /v2/store/virtual-numbers/conversations URL: https://api.innovapp-soft.com/v2/store/virtual-numbers/conversations AUTH: Bearer API Key DESCRIPTION: Números virtuales: Lista las conversaciones agrupadas de un numero virtual. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - number_id | required=Depende | type=string | description=Identificador del numero virtual alquilado. | example=vn_1842 - page | required=No | type=integer | description=Pagina del historial. | example=1 - per_page | required=No | type=integer | description=Resultados por pagina, maximo 100. | example=20 - language | required=No | type=string | description=Idioma de la respuesta: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v2/store/virtual-numbers/conversations' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"number_id":"vn_1842","page":1,"per_page":20,"language":"es"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/store/virtual-numbers/conversations', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "number_id": "vn_1842", "page": 1, "per_page": 20, "language": "es" }) }).then(r => r.json()).then(console.log); ``` ### Esquema de respuesta verificado ```json [ { "success": "boolean", "code": "string | integer", "message": "string", "data": "{number:number_order,data:[number_conversation],page,per_page,total,total_pages}", "error": "object | array", "time": "object" }, { "number_conversation": { "conversation_id": "dynamic", "contact": "dynamic", "last_message": "dynamic", "has_attachments": "dynamic", "last_direction": "dynamic", "last_message_at": "dynamic", "unread_count": "dynamic" } } ] ``` ### Errores específicos - HTTP 401 | API key invalida ```json { "success": false, "code": 40101, "message": "Invalid API key." } ``` - HTTP 422 | Parametro requerido ```json { "success": false, "code": 47017, "message": "Required field is missing: client_purchase_id" } ``` - HTTP 502 | Servicio temporalmente no disponible ```json { "success": false, "code": 47020, "message": "The Store service is temporarily unavailable." } ``` ### Notas - No envies userIdentifier: el usuario KeyPay se obtiene del developer autenticado. - Las compras requieren client_purchase_id unico. Si repites la misma solicitud usa exactamente el mismo valor. - El catalogo determina los identificadores, montos y campos validos; no construyas offer_id, service_id ni e164 manualmente. - La API puede devolver pending, processing, completed, failed o refunded segun el producto. - Esquema parcial verificado en el código de KeyPay. Los valores dynamic se resuelven en ejecución; no representan una respuesta JSON de producción. Los datos externos sin contrato verificable se omiten. --- ## Endpoint: POST /v2/store/virtual-numbers/mark-read ID: store-v2-virtual-numbers-mark-read ACTION: Marcar mensajes leídos METHOD: POST PATH: /v2/store/virtual-numbers/mark-read URL: https://api.innovapp-soft.com/v2/store/virtual-numbers/mark-read AUTH: Bearer API Key DESCRIPTION: Números virtuales: Marca como leidos los mensajes de un numero virtual. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - number_id | required=Depende | type=string | description=Identificador del numero virtual alquilado. | example=vn_1842 - message_id | required=No | type=integer | description=Mensaje hasta el cual se marcara como leido. | example=509 - language | required=No | type=string | description=Idioma de la respuesta: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v2/store/virtual-numbers/mark-read' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"number_id":"vn_1842","message_id":509,"language":"es"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/store/virtual-numbers/mark-read', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "number_id": "vn_1842", "message_id": 509, "language": "es" }) }).then(r => r.json()).then(console.log); ``` ### Esquema de respuesta verificado ```json [ { "success": "boolean", "code": "string | integer", "message": "string", "data": "{unread_count:int}", "error": "object | array", "time": "object" }, [] ] ``` ### Errores específicos - HTTP 401 | API key invalida ```json { "success": false, "code": 40101, "message": "Invalid API key." } ``` - HTTP 422 | Parametro requerido ```json { "success": false, "code": 47017, "message": "Required field is missing: client_purchase_id" } ``` - HTTP 502 | Servicio temporalmente no disponible ```json { "success": false, "code": 47020, "message": "The Store service is temporarily unavailable." } ``` ### Notas - No envies userIdentifier: el usuario KeyPay se obtiene del developer autenticado. - Las compras requieren client_purchase_id unico. Si repites la misma solicitud usa exactamente el mismo valor. - El catalogo determina los identificadores, montos y campos validos; no construyas offer_id, service_id ni e164 manualmente. - La API puede devolver pending, processing, completed, failed o refunded segun el producto. - Esquema parcial verificado en el código de KeyPay. Los valores dynamic se resuelven en ejecución; no representan una respuesta JSON de producción. Los datos externos sin contrato verificable se omiten. --- ## Endpoint: POST /v2/store/virtual-numbers/auto-renew ID: store-v2-virtual-numbers-auto-renew ACTION: Configurar renovación METHOD: POST PATH: /v2/store/virtual-numbers/auto-renew URL: https://api.innovapp-soft.com/v2/store/virtual-numbers/auto-renew AUTH: Bearer API Key DESCRIPTION: Números virtuales: Activa o desactiva la renovacion automatica de un numero virtual alquilado. Al desactivarla, el numero permanece activo hasta su vencimiento. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - number_id | required=Depende | type=string | description=Identificador del numero virtual alquilado. | example=vn_1842 - auto_renew | required=Si | type=boolean | description=Usa true para activar la renovacion automatica o false para desactivarla. | example=1 - client_request_id | required=No | type=string | description=Identificador opcional de la solicitud generado por tu sistema. | example=renew-2026-000184 - language | required=No | type=string | description=Idioma de la respuesta: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v2/store/virtual-numbers/auto-renew' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"number_id":"vn_1842","auto_renew":true,"client_request_id":"renew-2026-000184","language":"es"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v2/store/virtual-numbers/auto-renew', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ "number_id": "vn_1842", "auto_renew": true, "client_request_id": "renew-2026-000184", "language": "es" }) }).then(r => r.json()).then(console.log); ``` ### Esquema de respuesta verificado ```json [ { "success": false, "code": "store.virtual_numbers.auto_renew.failed", "message": "string", "data": [], "error": { "service": "virtual_numbers", "action": "string" }, "time": "object" } ] ``` ### Errores específicos - HTTP 401 | API key invalida ```json { "success": false, "code": 40101, "message": "Invalid API key." } ``` - HTTP 422 | Parametro requerido ```json { "success": false, "code": 47017, "message": "Required field is missing: client_purchase_id" } ``` - HTTP 502 | Servicio temporalmente no disponible ```json { "success": false, "code": 47020, "message": "The Store service is temporarily unavailable." } ``` ### Notas - No envies userIdentifier: el usuario KeyPay se obtiene del developer autenticado. - Las compras requieren client_purchase_id unico. Si repites la misma solicitud usa exactamente el mismo valor. - El catalogo determina los identificadores, montos y campos validos; no construyas offer_id, service_id ni e164 manualmente. - La API puede devolver pending, processing, completed, failed o refunded segun el producto. - Contrato con incidencia detectada: KeyPay sobrescribe status con el estado del número y el adaptador Developer lo interpreta como fallo. Esta respuesta no se simula como éxito. - Esquema parcial verificado en el código de KeyPay. Los valores dynamic se resuelven en ejecución; no representan una respuesta JSON de producción. Los datos externos sin contrato verificable se omiten. --- # Grupo: Store APIs V1 (legacy) Version anterior de recargas moviles. Para integraciones nuevas usa Store APIs V2. ## Endpoint: GET /v1/store/mobile_topup ID: store-mobile-topup-get ACTION: GET /v1/store/mobile_topup METHOD: GET PATH: /v1/store/mobile_topup URL: https://api.innovapp-soft.com/v1/store/mobile_topup AUTH: Bearer API Key DESCRIPTION: Devuelve los planes disponibles para recarga móvil. Permite filtrar opcionalmente por categoría. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json ### Query parameters - category | required=No | type=string | description=Filtra los productos por categoría. | example=Mobile-Top-Up ### cURL ```bash curl -X GET 'https://api.innovapp-soft.com/v1/store/mobile_topup?category=Mobile-Top-Up' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v1/store/mobile_topup?category=Mobile-Top-Up', { method: 'GET', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json' } }) .then(r => r.json()) .then(console.log); ``` ### Respuesta exitosa ```json { "success": true, "code": "ok", "message": "OK", "data": [ { "id": "4f", "category": "Mobile-Top-Up", "title": "SUPER OFERTA 6GB 60 MIN 60 SMS", "details": [ "6GB", "60 MIN", "60 SMS" ], "price": "21.00" }, { "id": "4g", "category": "Mobile-Micro-Top-Up", "title": "Plan de saldo 250 CUP", "details": [ "250 CUP" ], "price": "5.25" } ], "error": [], "time": { "datetime": "2026-04-22T18:10:00-04:00", "date": "2026-04-22", "time": "18:10:00", "timezone": "America/Kentucky/Louisville", "offset": "-04:00", "timestamp": 1776895800 } } ``` ### Errores específicos - HTTP 401 | 401 Unauthorized ```json { "success": false, "code": 10023, "message": "Unauthorized", "data": [], "error": [], "time": { "datetime": "2026-04-22T18:10:00-04:00", "date": "2026-04-22", "time": "18:10:00", "timezone": "America/Kentucky/Louisville", "offset": "-04:00", "timestamp": 1776895800 } } ``` - HTTP 405 | 405 Method Not Allowed ```json { "success": false, "code": 45001, "message": "Method not allowed", "data": [], "error": { "details": "PUT" }, "time": { "datetime": "2026-04-22T18:10:00-04:00", "date": "2026-04-22", "time": "18:10:00", "timezone": "America/Kentucky/Louisville", "offset": "-04:00", "timestamp": 1776895800 } } ``` ### Notas - El parámetro category es opcional. - Valores soportados actualmente para category: Mobile-Top-Up y Mobile-Micro-Top-Up. - El campo details puede traer un array descriptivo del plan. --- ## Endpoint: POST /v1/store/mobile_topup ID: store-mobile-topup-post ACTION: POST /v1/store/mobile_topup METHOD: POST PATH: /v1/store/mobile_topup URL: https://api.innovapp-soft.com/v1/store/mobile_topup AUTH: Bearer API Key DESCRIPTION: Procesa la compra de una recarga móvil a partir del id del plan y el número telefónico. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - id | required=Sí | type=string | description=Identificador del plan, obtenido desde el GET. | example=4f - phone | required=Sí | type=string | description=Número móvil destino a recargar. | example=51234567 ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v1/store/mobile_topup' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"id":"4f","phone":"51234567"}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v1/store/mobile_topup', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ id: '4f', phone: '51234567' }) }) .then(r => r.json()) .then(console.log); ``` ### Respuesta exitosa ```json { "success": true, "code": "ok", "message": "Purchase completed successfully.", "data": { "transation_id": "et_153_x9Ab3Kp2", "recharge_status": "Completed" }, "error": [], "time": { "datetime": "2026-04-22T18:14:00-04:00", "date": "2026-04-22", "time": "18:14:00", "timezone": "America/Kentucky/Louisville", "offset": "-04:00", "timestamp": 1776896040 } } ``` ### Errores específicos - HTTP 409 | 409 Operation In Process ```json { "success": false, "code": 46001, "message": "Operation in progress. Please check your history before buying again.", "data": [], "error": [], "time": { "datetime": "2026-04-22T18:14:00-04:00", "date": "2026-04-22", "time": "18:14:00", "timezone": "America/Kentucky/Louisville", "offset": "-04:00", "timestamp": 1776896040 } } ``` - HTTP 422 | 422 Invalid Phone ```json { "success": false, "code": 46009, "message": "The phone number is invalid.", "data": [], "error": [], "time": { "datetime": "2026-04-22T18:14:00-04:00", "date": "2026-04-22", "time": "18:14:00", "timezone": "America/Kentucky/Louisville", "offset": "-04:00", "timestamp": 1776896040 } } ``` - HTTP 409 | 409 Insufficient Credit ```json { "success": false, "code": 46012, "message": "Insufficient credit.", "data": [], "error": [], "time": { "datetime": "2026-04-22T18:14:00-04:00", "date": "2026-04-22", "time": "18:14:00", "timezone": "America/Kentucky/Louisville", "offset": "-04:00", "timestamp": 1776896040 } } ``` ### Notas - El campo id debe ser exactamente el id devuelto por GET /v1/store/mobile_topup. - El campo phone se valida y normaliza antes de enviar la recarga. - El endpoint usa control de concurrencia por lock para evitar compras duplicadas. - Si el débito de crédito ocurre y luego falla la compra, el crédito se revierte. - El estado final devuelto hoy es transation_id + recharge_status. --- # Grupo: Payments APIs Endpoints para crear enlaces de pago y gestionar cobros. ## Endpoint: POST /v1/payment_links ID: payment-links-post ACTION: POST /v1/payment_links METHOD: POST PATH: /v1/payment_links URL: https://api.innovapp-soft.com/v1/payment_links AUTH: Bearer API Key DESCRIPTION: Crea un enlace de pago único para que un usuario realice una transferencia hacia tu cuenta. El sistema genera un payment_id no predecible, guarda la solicitud en estado pending y devuelve la URL pública de pago. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - amount | required=Sí | type=string | description=Monto a cobrar. Acepta hasta 3 decimales. | example=25.00 - currency | required=No | type=string | description=Moneda del cobro. Actualmente soportado: KCOIN. | example=KCOIN - external_reference | required=No | type=string | description=Referencia interna del comercio o sistema externo. | example=ORDER-10045 - title | required=No | type=string | description=Título corto del cobro. | example=Payment request - description | required=No | type=string | description=Descripción corta del cobro. | example=Recharge order - message | required=No | type=string | description=Mensaje opcional asociado al enlace. | example=Complete the payment from your KeyCard app - expires_in_minutes | required=No | type=integer | description=Tiempo de expiración del enlace en minutos. | example=60 - metadata | required=No | type=object | description=Objeto JSON libre para información auxiliar del comercio. | example={"customer_id":"CUST-88"} ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v1/payment_links' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"amount":"25.00","currency":"KCOIN","external_reference":"ORDER-10045","title":"Payment request","description":"Recharge order","message":"Complete the payment from your KeyCard app","expires_in_minutes":60,"metadata":{"customer_id":"CUST-88"}}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v1/payment_links', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ amount: '25.00', currency: 'KCOIN', external_reference: 'ORDER-10045', title: 'Payment request', description: 'Recharge order', message: 'Complete the payment from your KeyCard app', expires_in_minutes: 60, metadata: { customer_id: 'CUST-88' } }) }) .then(r => r.json()) .then(console.log); ``` ### Respuesta exitosa ```json { "success": true, "code": "ok", "message": "Payment link created successfully.", "data": { "payment_id": "6d4f21d15e7bc3d9276ea4f0d89ab21c", "payment_url": "https://keypay.innovapp-soft.com/pay/6d4f21d15e7bc3d9276ea4f0d89ab21c", "status": "pending", "amount": "25.000", "currency": "KCOIN", "external_reference": "ORDER-10045", "title": "Payment request", "description": "Recharge order", "message": "Complete the payment from your KeyCard app", "expires_at": "2026-06-02 19:30:00", "created_at": "2026-06-02 18:30:00" }, "error": [], "time": { "datetime": "2026-06-02T18:30:00-04:00", "date": "2026-06-02", "time": "18:30:00", "timezone": "America/Kentucky/Louisville", "offset": "-04:00", "timestamp": 1770100200 } } ``` ### Errores específicos - HTTP 400 | 400 Amount Required ```json { "success": false, "code": 47001, "message": "Amount is required.", "data": [], "error": [], "time": { "datetime": "2026-06-02T18:30:00-04:00", "date": "2026-06-02", "time": "18:30:00", "timezone": "America/Kentucky/Louisville", "offset": "-04:00", "timestamp": 1770100200 } } ``` - HTTP 422 | 422 Invalid Amount ```json { "success": false, "code": 47002, "message": "The amount is invalid.", "data": [], "error": [], "time": { "datetime": "2026-06-02T18:30:00-04:00", "date": "2026-06-02", "time": "18:30:00", "timezone": "America/Kentucky/Louisville", "offset": "-04:00", "timestamp": 1770100200 } } ``` - HTTP 422 | 422 Invalid Metadata ```json { "success": false, "code": 47009, "message": "The metadata is invalid.", "data": [], "error": [], "time": { "datetime": "2026-06-02T18:30:00-04:00", "date": "2026-06-02", "time": "18:30:00", "timezone": "America/Kentucky/Louisville", "offset": "-04:00", "timestamp": 1770100200 } } ``` - HTTP 405 | 405 Method Not Allowed ```json { "success": false, "code": 47012, "message": "Method not allowed", "data": [], "error": { "details": "GET" }, "time": { "datetime": "2026-06-02T18:30:00-04:00", "date": "2026-06-02", "time": "18:30:00", "timezone": "America/Kentucky/Louisville", "offset": "-04:00", "timestamp": 1770100200 } } ``` ### Notas - El campo amount es obligatorio y acepta hasta 3 decimales. - El campo currency hoy soporta KCOIN. - El campo payment_id es generado por el sistema y no es predecible. - El enlace público devuelto en payment_url debe abrirse desde la app o el flujo externo de pago. - El cobro se crea inicialmente en estado pending. - El usuario paga el monto del enlace. La liquidación al developer puede descontar el fee de payment link configurado por la plataforma. - Ejemplo: si el enlace es de 100.000 KCOIN y el fee configurado es 2%, el usuario paga 100.000 KCOIN y el developer recibe 98.000 KCOIN. --- ## Endpoint: GET /v1/transactions ID: transactions-get ACTION: GET /v1/transactions METHOD: GET PATH: /v1/transactions URL: https://api.innovapp-soft.com/v1/transactions AUTH: Bearer API Key DESCRIPTION: Devuelve las últimas 10 transacciones creadas por el developer autenticado. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json ### cURL ```bash curl -X GET 'https://api.innovapp-soft.com/v1/transactions' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v1/transactions', { method: 'GET', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json' } }) .then(r => r.json()) .then(console.log); ``` ### Respuesta exitosa ```json { "success": true, "code": "ok", "message": "OK", "data": [ { "payment_id": "6d4f21d15e7bc3d9276ea4f0d89ab21c", "status": "pending", "amount": "25.000", "currency": "KCOIN", "external_reference": "ORDER-10045", "title": "Payment request", "description": "Recharge order", "message": "Complete the payment from your KeyCard app", "paid_transaction_id": null, "paid_at": null, "expires_at": "2026-06-02 19:30:00", "created_at": "2026-06-02 18:30:00", "updated_at": "2026-06-02 18:30:00" }, { "payment_id": "9f61ad13db19e6d2a80b8b6248ca5f88", "status": "paid", "amount": "14.500", "currency": "KCOIN", "external_reference": "ORDER-10046", "title": "Service payment", "description": "Premium service", "message": "Please complete your payment", "paid_transaction_id": "trx_4K91AB2", "paid_at": "2026-06-02 18:42:11", "expires_at": "2026-06-02 19:10:00", "created_at": "2026-06-02 18:10:00", "updated_at": "2026-06-02 18:42:11" } ], "error": [], "time": { "datetime": "2026-06-02T18:45:00-04:00", "date": "2026-06-02", "time": "18:45:00", "timezone": "America/Kentucky/Louisville", "offset": "-04:00", "timestamp": 1770101100 } } ``` ### Errores específicos - HTTP 401 | 401 Unauthorized ```json { "success": false, "code": 47110, "message": "Unauthorized", "data": [], "error": [], "time": { "datetime": "2026-06-02T18:45:00-04:00", "date": "2026-06-02", "time": "18:45:00", "timezone": "America/Kentucky/Louisville", "offset": "-04:00", "timestamp": 1770101100 } } ``` - HTTP 405 | 405 Method Not Allowed ```json { "success": false, "code": 47111, "message": "Method not allowed", "data": [], "error": { "details": "POST" }, "time": { "datetime": "2026-06-02T18:45:00-04:00", "date": "2026-06-02", "time": "18:45:00", "timezone": "America/Kentucky/Louisville", "offset": "-04:00", "timestamp": 1770101100 } } ``` ### Notas - Si no se envía un public_id en la ruta, el endpoint devuelve las últimas 10 transacciones del developer autenticado. - La respuesta en data es un array. - Cada elemento representa un payment link creado previamente. --- ## Endpoint: GET /v1/transactions/{public_id} ID: transactions-public-id-get ACTION: GET /v1/transactions/{public_id} METHOD: GET PATH: /v1/transactions/{public_id} URL: https://api.innovapp-soft.com/v1/transactions/{public_id} AUTH: Bearer API Key DESCRIPTION: Devuelve el detalle de una transacción específica usando su payment_id/public_id. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json ### cURL ```bash curl -X GET 'https://api.innovapp-soft.com/v1/transactions/6d4f21d15e7bc3d9276ea4f0d89ab21c' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v1/transactions/6d4f21d15e7bc3d9276ea4f0d89ab21c', { method: 'GET', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json' } }) .then(r => r.json()) .then(console.log); ``` ### Respuesta exitosa ```json { "success": true, "code": "ok", "message": "OK", "data": { "payment_id": "6d4f21d15e7bc3d9276ea4f0d89ab21c", "status": "pending", "amount": "25.000", "currency": "KCOIN", "external_reference": "ORDER-10045", "title": "Payment request", "description": "Recharge order", "message": "Complete the payment from your KeyCard app", "metadata": { "customer_id": "CUST-88" }, "paid_transaction_id": null, "paid_at": null, "expires_at": "2026-06-02 19:30:00", "created_at": "2026-06-02 18:30:00", "updated_at": "2026-06-02 18:30:00" }, "error": [], "time": { "datetime": "2026-06-02T18:45:00-04:00", "date": "2026-06-02", "time": "18:45:00", "timezone": "America/Kentucky/Louisville", "offset": "-04:00", "timestamp": 1770101100 } } ``` ### Errores específicos - HTTP 404 | 404 Transaction Not Found ```json { "success": false, "code": 47103, "message": "The transaction does not exist.", "data": [], "error": [], "time": { "datetime": "2026-06-02T18:45:00-04:00", "date": "2026-06-02", "time": "18:45:00", "timezone": "America/Kentucky/Louisville", "offset": "-04:00", "timestamp": 1770101100 } } ``` - HTTP 422 | 422 Invalid Public ID ```json { "success": false, "code": 47102, "message": "The transaction identifier is invalid.", "data": [], "error": [], "time": { "datetime": "2026-06-02T18:45:00-04:00", "date": "2026-06-02", "time": "18:45:00", "timezone": "America/Kentucky/Louisville", "offset": "-04:00", "timestamp": 1770101100 } } ``` ### Notas - El valor {public_id} debe ser el payment_id generado al crear el payment link. - La respuesta en data es un objeto único. - Solo el developer dueño de la transacción puede consultarla. --- # Grupo: PaymentIntent SDK APIs Endpoints para crear cobros con client_secret y abrir checkout desde SDK iOS/Android. ## Endpoint: POST /v1/payment_intents ID: payment-intents-post ACTION: POST /v1/payment_intents METHOD: POST PATH: /v1/payment_intents URL: https://api.innovapp-soft.com/v1/payment_intents AUTH: Bearer API Key DESCRIPTION: Crea un PaymentIntent para SDK. El backend del developer usa su API key secreta y devuelve client_secret + checkout_url a la app móvil. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json - Content-Type: application/json ### Body parameters - amount | required=Sí | type=string | description=Monto a cobrar. Acepta hasta 3 decimales. | example=10.00 - currency | required=No | type=string | description=Moneda del cobro. Actualmente soportado: KCOIN. | example=KCOIN - external_reference | required=No | type=string | description=Referencia interna del comercio. | example=ORDER-1001 - title | required=No | type=string | description=Título corto del cobro. | example=Premium purchase - return_url | required=No | type=string | description=Deep link o URL de retorno de la app. | example=myapp://keypay-return - platform | required=No | type=string | description=ios, android o web. | example=ios - bundle_id | required=No | type=string | description=Bundle ID iOS. | example=com.example.app - package_name | required=No | type=string | description=Package Android. | example=com.example.app - metadata | required=No | type=object | description=JSON libre para tu orden. | example={"order_id":"1001"} ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/v1/payment_intents' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{"amount":"10.00","currency":"KCOIN","external_reference":"ORDER-1001","title":"Premium purchase","return_url":"myapp://keypay-return","platform":"ios","bundle_id":"com.example.app","metadata":{"order_id":"1001"}}' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v1/payment_intents', { method: 'POST', headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ amount: '10.00', currency: 'KCOIN', external_reference: 'ORDER-1001', title: 'Premium purchase', return_url: 'myapp://keypay-return', platform: 'ios', bundle_id: 'com.example.app', metadata: { order_id: '1001' } }) }).then(r => r.json()).then(console.log); ``` ### Respuesta exitosa ```json { "success": true, "code": "ok", "message": "PaymentIntent created successfully.", "data": { "id": "pi_6d4f21d15e7bc3d9276ea4f0d89ab21c", "object": "payment_intent", "status": "requires_payment", "amount": "10.000", "currency": "KCOIN", "client_secret": "kpi_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "checkout_url": "https://keypay.innovapp-soft.com/pay/6d4f21d15e7bc3d9276ea4f0d89ab21c?intent=pi_...", "payment_link_id": "6d4f21d15e7bc3d9276ea4f0d89ab21c", "expires_at": "2026-06-16 19:30:00", "created_at": "2026-06-16 18:30:00" }, "error": [] } ``` ### Notas - Nunca coloques la API key dk_live dentro de iOS o Android. - El backend del developer crea el PaymentIntent y entrega a la app solo client_secret + checkout_url. - En esta versión el PaymentIntent está respaldado por el flujo existente de payment links. - La confirmación final debe hacerse por webhook o consultando GET /v1/payment_intents/{id}. --- ## Endpoint: SDK KeyPayPaymentSDK ID: payment-intents-swiftui-sdk ACTION: SwiftUI SDK METHOD: SDK PATH: KeyPayPaymentSDK URL: https://github.com/innovappsoft/KeyPayPaymentSDK.git AUTH: Developer Backend DESCRIPTION: SDK oficial para integrar PaymentIntent en apps SwiftUI. El developer instala el paquete desde GitHub, configura su backend y usa KeyPayPaymentButton para abrir el sheet de pago listo. ### Headers - Package URL: https://github.com/innovappsoft/KeyPayPaymentSDK.git - Version: v1.0.0 o superior - Import: import KeyPayPaymentSDK ### Body parameters - paymentIntentEndpoint | required=Sí | type=URL | description=Endpoint de tu backend que crea PaymentIntent con dk_live. | example=https://tuapp.com/api/keypay/payment-intents - paymentStatusEndpoint | required=Recomendado | type=URL | description=Endpoint de tu backend que consulta GET /v1/payment_intents/{id}. | example=https://tuapp.com/api/keypay/payment-intents - returnURLScheme | required=Sí | type=string | description=URL Scheme registrado en Xcode para volver a la app. | example=myapp - merchantDisplayName | required=Sí | type=string | description=Nombre visible del comercio dentro del sheet. | example=My App ### cURL ```bash git clone https://github.com/innovappsoft/KeyPayPaymentSDK.git # O en Xcode: # File > Add Package Dependencies > https://github.com/innovappsoft/KeyPayPaymentSDK.git # Version: Up to Next Major desde 1.0.0 ``` ### Ejemplo SwiftUI ```text import SwiftUI import KeyPayPaymentSDK @main struct MyApp: App { init() { KeyPay.configure( paymentIntentEndpoint: URL(string: "https://tuapp.com/api/keypay/payment-intents")!, paymentStatusEndpoint: URL(string: "https://tuapp.com/api/keypay/payment-intents")!, returnURLScheme: "myapp", merchantDisplayName: "My App" ) } var body: some Scene { WindowGroup { ContentView() } } } struct ContentView: View { @State private var status = "" var body: some View { KeyPayPaymentButton( request: KeyPayPaymentRequest( amount: 10, title: "Premium Plan", description: "Monthly subscription", externalReference: "order_1001", metadata: ["order_id": "1001"] ) ) { result in switch result { case .succeeded(let intent): status = "Paid: \(intent.id)" case .pending(let intent): status = "Pending: \(intent.id)" case .cancelled: status = "Cancelled" case .failed(let error): status = error.localizedDescription } } } } ``` ### Respuesta exitosa ```json { "package": "KeyPayPaymentSDK", "github": "https://github.com/innovappsoft/KeyPayPaymentSDK.git", "current_version": "v1.0.0", "product": "KeyPayPaymentSDK", "minimum_ios": "15.0", "main_components": [ "KeyPay.configure", "KeyPayPaymentButton", "KeyPayPaymentSheet", "KeyPayPaymentRequest", "KeyPayPaymentResult" ] } ``` ### Notas - El proyecto del SDK está en GitHub: https://github.com/innovappsoft/KeyPayPaymentSDK.git - Para instalar en Xcode usa File > Add Package Dependencies y pega la URL del repo. - El developer no debe poner dk_live dentro de la app; dk_live vive solo en su backend. - El backend del developer debe exponer POST /payment-intents y GET /payment-intents/{id}. - El SDK incluye UI SwiftUI lista, traducciones EN/ES y sheet de pago tipo plug-and-play. - Para publicar nuevas versiones crea tags semánticos como v1.0.1, v1.1.0 o v2.0.0. --- ## Endpoint: SDK KeyPayPaymentAndroidSDK ID: payment-intents-android-sdk ACTION: Android SDK METHOD: SDK PATH: KeyPayPaymentAndroidSDK URL: https://github.com/innovappsoft/KeyPayPaymentAndroidSDK.git AUTH: Developer Backend DESCRIPTION: SDK oficial para integrar PaymentIntent en apps Android con Kotlin o Java. El developer instala la librería desde GitHub, configura su backend y usa KeyPayCheckoutButton para abrir el checkout nativo listo. ### Headers - Repository URL: https://github.com/innovappsoft/KeyPayPaymentAndroidSDK.git - Version: v1.0.1 o superior - Package: com.innovappsoft.keypay.payment - Main module: keypay-payment-sdk ### Body parameters - paymentIntentEndpoint | required=Sí | type=String | description=Endpoint de tu backend que crea PaymentIntent con dk_live. | example=https://tuapp.com/api/keypay/payment-intents - paymentStatusEndpoint | required=Recomendado | type=String | description=Endpoint de tu backend que consulta GET /v1/payment_intents/{id}. | example=https://tuapp.com/api/keypay/payment-intents - returnUrlScheme | required=Sí | type=String | description=Scheme registrado en AndroidManifest para volver a la app. | example=myapp - merchantDisplayName | required=Sí | type=String | description=Nombre visible del comercio dentro del checkout. | example=My App - package_name | required=Recomendado | type=String | description=Package name Android de la app del developer. | example=com.example.app ### cURL ```bash 1) Instalación recomendada con JitPack settings.gradle.kts: dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { google() mavenCentral() maven { url = uri("https://jitpack.io") } } } gradle/libs.versions.toml: [versions] keypaySdkVersion = "v1.0.1" [libraries] keypay-android-sdk = { module = "com.github.innovappsoft.KeyPayPaymentAndroidSDK:keypay-payment-sdk", version.ref = "keypaySdkVersion" } app/build.gradle.kts: dependencies { implementation(libs.keypay.android.sdk) } Importante: - Usa v1.0.1 o superior. v1.0.0 no se debe usar para Gradle porque fue source-only y no tenía metadata Maven para JitPack. - El módulo que se importa es keypay-payment-sdk. El módulo sample-app es solo una demo. - Si JitPack todavía no terminó de construir el tag, espera unos minutos o usa la opción AAR local. 2) AndroidManifest para recibir el callback El returnUrlScheme configurado en el SDK debe coincidir con android:scheme. Ejemplo: returnUrlScheme = "myapp" usa myapp://keypay-return. 3) Opción de prueba local con AAR En el repo del SDK: ./gradlew :keypay-payment-sdk:assembleRelease Copia: keypay-payment-sdk/build/outputs/aar/keypay-payment-sdk-release.aar a: app/libs/keypay-payment-sdk-release.aar app/build.gradle.kts: dependencies { implementation(files("libs/keypay-payment-sdk-release.aar")) implementation(libs.androidx.appcompat) implementation(libs.material) } Cuando se usa AAR local, Android no descarga dependencias transitivas automáticamente, por eso appcompat y material deben estar en la app. 4) Backend requerido del developer La app nunca debe guardar dk_live. La API key vive en el backend del developer. El backend debe exponer: - POST /payment-intents para crear el PaymentIntent usando dk_live. - GET /payment-intents/{id} para consultar estado y devolverlo a la app. 5) Errores comunes Could not find com.github.innovappsoft.KeyPayPaymentAndroidSDK:keypay-payment-sdk:v1.0.0 Solución: usar v1.0.1 o superior, o probar con AAR local. KeyPayReturnActivity aparece en rojo en Android Studio Solución: la dependencia no está resuelta. Revisa JitPack, Sync Gradle o usa el AAR local. Cannot generate dependency accessors Solución: no dupliques alias en libs.versions.toml. Usa keypaySdkVersion para la versión y keypay-android-sdk para la librería. AndroidX core 1.19 pide compileSdk 37 / AGP 9.1 Solución: baja coreKtx a 1.17.0 o actualiza compileSdk y Android Gradle Plugin. ``` ### Ejemplo Kotlin / Java ```text import com.innovappsoft.keypay.payment.KeyPay import com.innovappsoft.keypay.payment.KeyPayCheckoutButton import com.innovappsoft.keypay.payment.KeyPayConfiguration import com.innovappsoft.keypay.payment.KeyPayPaymentRequest import com.innovappsoft.keypay.payment.KeyPayPaymentResult KeyPay.configure( KeyPayConfiguration( paymentIntentEndpoint = "https://tuapp.com/api/keypay/payment-intents", paymentStatusEndpoint = "https://tuapp.com/api/keypay/payment-intents", returnUrlScheme = "myapp", merchantDisplayName = "My App" ) ) val request = KeyPayPaymentRequest( amount = "10.00", title = "Premium Plan", description = "Monthly subscription", externalReference = "order_1001", metadata = mapOf("order_id" to "1001") ) val button = KeyPayCheckoutButton(this).apply { configure( activity = this@MainActivity, request = request, callback = { result -> when (result.status) { KeyPayPaymentResult.Status.SUCCEEDED -> {} KeyPayPaymentResult.Status.PENDING -> {} KeyPayPaymentResult.Status.CANCELLED -> {} KeyPayPaymentResult.Status.FAILED -> {} } }, title = "Pay with KeyPay" ) } // Java compatible: // KeyPay.configure(new KeyPayConfiguration( // "https://tuapp.com/api/keypay/payment-intents", // "https://tuapp.com/api/keypay/payment-intents", // "myapp", // "My App" // )); // KeyPay.startCheckout(this, request, result -> { }); ``` ### Respuesta exitosa ```json { "package": "KeyPayPaymentAndroidSDK", "github": "https://github.com/innovappsoft/KeyPayPaymentAndroidSDK.git", "current_version": "v1.0.1", "product": "keypay-payment-sdk", "minimum_sdk": "API 24 / Android 7.0", "languages": [ "Kotlin", "Java" ], "modules": [ "keypay-payment-sdk", "sample-app" ], "main_components": [ "KeyPay.configure", "KeyPayCheckoutButton", "KeyPayCheckoutActivity", "KeyPayPaymentRequest", "KeyPayPaymentResult", "KeyPayReturnActivity" ], "manifest_callback": "" } ``` ### Errores específicos - HTTP | dependency_not_found ```json { "code": "dependency_not_found", "message": "Gradle no encuentra com.github.innovappsoft.KeyPayPaymentAndroidSDK:keypay-payment-sdk:v1.0.0.", "fix": "Usa v1.0.1 o superior. v1.0.0 fue source-only y no tenía metadata Maven para JitPack." } ``` - HTTP | return_activity_unresolved ```json { "code": "return_activity_unresolved", "message": "Android Studio muestra KeyPayReturnActivity en rojo.", "fix": "La dependencia no está resuelta. Ejecuta Sync Gradle, revisa JitPack o usa AAR local." } ``` - HTTP | duplicate_version_catalog_alias ```json { "code": "duplicate_version_catalog_alias", "message": "Cannot generate dependency accessors.", "fix": "Evita alias duplicados en libs.versions.toml. Usa keypaySdkVersion para la versión y keypay-android-sdk para la librería." } ``` - HTTP | androidx_core_compile_sdk ```json { "code": "androidx_core_compile_sdk", "message": "AndroidX core 1.19 exige compileSdk 37 o AGP 9.1.", "fix": "Baja coreKtx a 1.17.0 o actualiza compileSdk y Android Gradle Plugin." } ``` ### Notas - El proyecto del SDK Android está en GitHub: https://github.com/innovappsoft/KeyPayPaymentAndroidSDK.git - Usa v1.0.1 o superior para JitPack. v1.0.0 fue una versión source-only y no tenía metadata Maven para Gradle. - El módulo real de la librería es keypay-payment-sdk; sample-app es solo una app de ejemplo. - Si Android Studio marca KeyPayReturnActivity en rojo, la dependencia no está resuelta: revisa JitPack, Sync Gradle o usa AAR local. - Si Gradle dice Could not find com.github..., usa v1.0.1 o genera/copias el AAR local. - Si Gradle dice Cannot generate dependency accessors, evita alias duplicados: usa keypaySdkVersion para la versión y keypay-android-sdk para la librería. - Si AndroidX core 1.19 exige compileSdk 37 / AGP 9.1, baja coreKtx a 1.17.0 o actualiza AGP/compileSdk. - El SDK incluye UI Android nativa, traducciones EN/ES y botón plug-and-play KeyPayCheckoutButton. - Compatible con Kotlin y Java mediante API pública Java-friendly. - El developer debe registrar el returnUrlScheme en AndroidManifest usando KeyPayReturnActivity. - El developer no debe poner dk_live dentro de la app; dk_live vive solo en su backend. - El backend del developer debe exponer POST /payment-intents y GET /payment-intents/{id}. - Para publicar nuevas versiones crea tags semánticos como v1.0.2, v1.1.0 o v2.0.0. --- ## Endpoint: GET /v1/payment_intents/{id} ID: payment-intents-get ACTION: GET /v1/payment_intents/{id} METHOD: GET PATH: /v1/payment_intents/{id} URL: https://api.innovapp-soft.com/v1/payment_intents/{id} AUTH: Bearer API Key DESCRIPTION: Consulta el estado de un PaymentIntent creado por tu cuenta. ### Headers - Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx - Accept: application/json ### cURL ```bash curl -X GET 'https://api.innovapp-soft.com/v1/payment_intents/pi_6d4f21d15e7bc3d9276ea4f0d89ab21c' \ -H 'Authorization: Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Accept: application/json' ``` ### Ejemplo de código ```text fetch('https://api.innovapp-soft.com/v1/payment_intents/pi_6d4f21d15e7bc3d9276ea4f0d89ab21c', { headers: { 'Authorization': 'Bearer dk_live_xxxxxxxxxxxxxxxxxxxxxxxxxx', 'Accept': 'application/json' } }).then(r => r.json()).then(console.log); ``` ### Respuesta exitosa ```json { "success": true, "code": "ok", "message": "OK", "data": { "id": "pi_6d4f21d15e7bc3d9276ea4f0d89ab21c", "object": "payment_intent", "status": "succeeded", "amount": "10.000", "currency": "KCOIN", "paid_transaction_id": "trx_4K91AB2", "paid_at": "2026-06-16 18:42:11" }, "error": [] } ``` ### Notas - Este endpoint es para backend. No lo llames desde la app móvil con dk_live. - El SDK móvil debe devolver control a tu app; tu backend confirma el estado real. --- # Grupo: Sandbox Pruebas con saldo virtual, claves independientes y respuestas simuladas. ## Endpoint: POST /sandbox/v2/store/esim/catalog ID: sandbox-start ACTION: Sandbox · Inicio rápido METHOD: POST PATH: /sandbox/v2/store/esim/catalog URL: https://api.innovapp-soft.com/sandbox/v2/store/esim/catalog AUTH: Bearer dk_test_ DESCRIPTION: Abre Sandbox en tu panel, crea una clave de prueba y añade /sandbox a la URL base. Conserva la versión y la ruta del endpoint. ### Headers - Authorization: Bearer YOUR_SANDBOX_KEY - Accept: application/json - Content-Type: application/json - X-Sandbox-Scenario: success ### Body parameters - mode | required=No | type=string | description=Usa plans para consultar planes de un país. | example=plans - country | required=Sí para plans | type=string | description=Código ISO alpha-2 del país. | example=US - language | required=No | type=string | description=Idioma: es o en. | example=es ### cURL ```bash curl -X POST 'https://api.innovapp-soft.com/sandbox/v2/store/esim/catalog' \ -H 'Authorization: Bearer YOUR_SANDBOX_KEY' \ -H 'Content-Type: application/json' \ -H 'X-Sandbox-Scenario: success' \ --data '{"mode":"plans","country":"US","language":"es"}' ``` ### Ejemplo de código ```text // Backend only: keep the test key on your server. const response = await fetch('https://api.innovapp-soft.com/sandbox/v2/store/esim/catalog', { method: 'POST', headers: { Authorization: 'Bearer YOUR_SANDBOX_KEY', 'Content-Type': 'application/json', 'X-Sandbox-Scenario': 'success' }, body: JSON.stringify({ mode: 'plans', country: 'US', language: 'es' }) }); const result = await response.json(); ``` ### Notas - El Sandbox cubre unicamente las APIs Developer publicadas en esta documentacion. Las APIs internas de las apps de KeyPay no se simulan aqui ni son accesibles con una clave de developer. - Las claves dk_test_ solo funcionan en /sandbox. Las claves dk_live_ se rechazan en Sandbox. No uses claves secretas en aplicaciones públicas. - El saldo inicial es 10 000 KC virtuales. No se modifica tu saldo real ni se envían compras, retiros, depósitos, notificaciones o webhooks a servicios externos. - Los escenarios disponibles dependen del endpoint y se muestran en el selector. Solo las operaciones que lo admiten permiten transiciones pending, success o failed. - Todas las respuestas incluyen sandbox.simulated = true y se identifican con X-API-Environment: sandbox. Solo se reproducen campos verificados; las cantidades e identificadores son valores de prueba. - Usa los identificadores que devuelve cada creación en get, status y list. En Store, repite la referencia de cliente con el mismo cuerpo para probar idempotencia; cambia el cuerpo para probar un conflicto. - Los datos de prueba se comparten dentro de tu cuenta developer. Reiniciar borra las operaciones simuladas y restaura el saldo virtual; conserva las claves de prueba. - Límites: 120 peticiones por minuto por developer, 64 KB por cuerpo JSON y 200 operaciones. Reinicia los datos cuando alcances el límite de operaciones. - Envía un objeto JSON con Content-Type: application/json para POST y parámetros de consulta para GET. Las rutas no disponibles devuelven un error y nunca se reenvían a producción. - Los estados pendientes no avanzan por sí solos. El Sandbox simula contratos y escenarios; no valida entregas reales, firmas de webhook ni tiempos de proveedores. ---