API de facturación electrónica

Emite facturas y notas de crédito autorizadas por el SRI de Ecuador desde tu tienda web, tu ERP o cualquier sistema. Solverline firma el comprobante, lo envía al SRI, le manda el correo al comprador y lo registra en la contabilidad de la empresa.

Dirección base: https://facturacion.solverline.com/api/v1
Todo viaja en JSON por HTTPS. Las fechas van en formato ISO (2026-09-23) y los montos en dólares, con punto decimal.

  1. La empresa crea una credencial en Solverline y te entrega el client_id y la clave secreta.
  2. Tu sistema cambia esos datos por un token, que dura 1 hora.
  3. Con el token llamas a las funciones: emitir factura, nota de crédito, consultar, catálogo, pedidos.

1. Credenciales

El administrador de la empresa entra a Solverline → API — Integraciones → Nueva credencial y elige:

  • De pruebas o real. Las de pruebas empiezan con slv_test_ y no envían nada al SRI (ver Modo pruebas).
  • Permisos. Cada función exige uno:
PermisoQué permite
catalogo:readLeer productos, precios y stock.
pedidos:writeCrear pedidos (quedan como proformas) y consultarlos.
facturas:writeEmitir facturas y notas de crédito al SRI.
comprobantes:readConsultar el estado de un comprobante y bajar su PDF y XML.
La clave secreta se muestra una sola vez. Guárdala en tu servidor, nunca en el navegador ni en una app que el usuario pueda abrir. Si se filtra, desactiva la credencial en Solverline y crea otra.

2. Obtener el token

POST/oauth/token
curl -X POST https://facturacion.solverline.com/api/v1/oauth/token \
  -H "Content-Type: application/json" \
  -d '{"grant_type": "client_credentials",
       "client_id": "slv_xxxxxxxx",
       "client_secret": "slv_secret_xxxxxxxx"}'

Respuesta:

{
  "access_token": "eyJhbGciOi...",
  "refresh_token": "eyJhbGciOi...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "facturas:write comprobantes:read"
}

Envía el token en cada llamada con la cabecera Authorization: Bearer <access_token>.

Renovar sin volver a mandar la clave

El refresh_token dura 30 días y sirve una sola vez: cada renovación entrega uno nuevo.

{"grant_type": "refresh_token", "refresh_token": "eyJhbGciOi..."}

Otras funciones del token

RutaPara qué
GET /oauth/meComprueba el token: devuelve la empresa, su RUC, los permisos y cuándo vence.
POST /oauth/revokeAnula el token que envías en la cabecera.

Modo pruebas

Con una credencial de pruebas (slv_test_…) todas las funciones responden con la misma forma que en real, pero:

  • No se envía nada al SRI y no se crean clientes, proformas ni comprobantes en la empresa.
  • Los comprobantes de prueba usan la serie 999-999 y el ambiente 1. Su PDF dice «COMPROBANTE DE PRUEBA — SIN VALIDEZ TRIBUTARIA».
  • Las notas de crédito solo se pueden hacer sobre facturas de prueba.
  • Los pedidos de prueba no se guardan, así que no se pueden consultar después.
  • Una credencial real no ve los comprobantes de prueba, y una de prueba no ve los reales.
Recomendado: desarrolla y prueba todo con una credencial de pruebas. Cuando funcione, cambia el client_id y la clave por los de una credencial real. No hay que cambiar nada más del código.

Límites y errores

LímiteValor
Llamadas por minuto, por credencial60. Si te pasas, recibes 429 con la cabecera Retry-After.
Duración del token60 minutos.
Duración del refresh token30 días.
Intentos fallidos de clave10 en 10 minutos bloquean esa credencial durante 10 minutos.
Productos por página en el catálogo200 como máximo.

Los errores llegan así: {"detail": "texto que explica el problema"}. El texto está pensado para mostrarlo tal cual.

CódigoQué significa
400Faltan datos o no son válidos (por ejemplo, un IVA que no existe).
401Token ausente, vencido o anulado. Pide uno nuevo.
403Tu credencial no tiene ese permiso, está desactivada o la empresa llegó al límite de su plan.
404No existe o no pertenece a tu empresa.
409El comprobante todavía no está autorizado por el SRI.
422El JSON no tiene la forma esperada (falta un campo obligatorio o tiene otro tipo).
429Demasiadas llamadas. Espera los segundos que indica Retry-After.

Emitir una factura

POST/public/facturaspermiso: facturas:write

Solverline toma el secuencial, firma, envía al SRI y espera la autorización. La respuesta llega cuando el SRI contesta, normalmente en pocos segundos.

{
  "cliente": {
    "identificacion": "1790012345001",
    "razon_social": "COMERCIAL EJEMPLO S.A.",
    "email": "compras@ejemplo.com",
    "telefono": "0991234567",
    "direccion": "AV. AMAZONAS N24-100, QUITO"
  },
  "items": [
    { "sku": "ST-001", "descripcion": "SOPORTE TECNICO POR HORAS",
      "cantidad": 2, "precio_unitario": 35.00, "descuento": 0, "iva": 15 }
  ],
  "forma_pago": "TRANSFERENCIA",
  "referencia_externa": "PEDIDO-10025",
  "info_adicional": { "Vendedor": "Ana" }
}
CampoObligatorioDetalle
cliente.identificacionsíRUC (13 dígitos), cédula (10), pasaporte o 9999999999999 para consumidor final.
cliente.tipo_identificacionnoSe deduce solo. Ver tabla.
cliente.razon_socialsíNombre como figura en el RUC o la cédula.
cliente.emailnoSi viene, el comprador recibe la factura en su correo.
cliente.telefono, cliente.direccionnoAparecen en la factura.
items[].descripcionsíTexto de la línea.
items[].cantidadsíMayor que cero.
items[].precio_unitario*Precio sin IVA. Si no lo envías, se usa el precio del producto en Solverline (necesita sku).
items[].skunoCódigo o SKU del producto en Solverline. Si coincide, la venta descuenta inventario.
items[].descuentonoMonto en dólares de toda la línea, no porcentaje. Por defecto 0.
items[].ivanoPorcentaje: 0, 5 o 15. Por defecto 15.
forma_pagonoVer formas de pago. Por defecto SISTEMA_FINANCIERO.
plazo_diasnoDías de crédito, si aplica.
referencia_externanoTu número de pedido. Aparece en la factura como información adicional.
info_adicionalnoPares nombre → valor que se imprimen en la factura.

Respuesta:

{
  "estado": "AUTORIZADO",
  "clave_acceso": "2309202601179999999900120010010000009624089753012",
  "numero_autorizacion": "2309202601179999999900120010010000009624089753012",
  "fecha_autorizacion": "2026-09-23 00:19:09-05:00",
  "ambiente": "2",
  "mensajes": []
}

Guarda la clave_acceso: identifica la factura para consultarla, bajar su PDF o hacerle una nota de crédito.

Si estado no es AUTORIZADO, revisa mensajes: ahí llega lo que respondió el SRI. Si llega EN_PROCESO, el SRI aún no contesta; consulta la factura en unos segundos con GET /public/comprobantes/{clave}. No la vuelvas a enviar, o se emitiría dos veces.

Una factura emitida por la API queda pendiente de cobro en Solverline, aunque la forma de pago sea efectivo. El cobro se registra en la app.

Emitir una nota de crédito

POST/public/notas-creditopermiso: facturas:write

Solo necesitas la clave de acceso de la factura original. Solverline toma de ella al comprador, el número y la fecha.

Anular toda la factura

{ "factura_clave_acceso": "2309202601179999999900120010010000009624089753012" }

Devolver una parte

{
  "factura_clave_acceso": "2309202601179999999900120010010000009624089753012",
  "motivo": "01",
  "items": [ { "codigo": "ST-001", "cantidad": 1 } ]
}
CampoDetalle
factura_clave_accesoObligatorio. La factura tiene que estar autorizada y ser de tu empresa.
itemsOpcional. Sin ítems, la nota de crédito cubre toda la factura. Con ítems, usa el codigo con que se facturó (el sku) y una cantidad que no supere la facturada. El precio y el IVA se toman de la factura.
motivoOpcional. 01 devolución, 02 anulación, 03 rebaja, 04 otros. Por defecto 02 si es toda la factura y 01 si es parcial.

La respuesta tiene la misma forma que la de la factura, con la clave_acceso de la nota de crédito.

Consultar un comprobante, bajar el PDF y el XML

GET/public/comprobantes/{clave_acceso}permiso: comprobantes:read
{
  "clave_acceso": "2309202601179999999900120010010000009624089753012",
  "tipo": "FACTURA",
  "secuencial": "000000962",
  "estado": "AUTORIZADO",
  "numero_autorizacion": "2309202601179999999900120010010000009624089753012",
  "fecha_emision": "2026-09-23",
  "fecha_autorizacion": "2026-09-23T00:19:09-05:00",
  "total": 80.5,
  "ambiente": "produccion",
  "mensaje_sri": null,
  "pdf": "https://facturacion.solverline.com/api/v1/public/comprobantes/2309.../pdf",
  "xml": "https://facturacion.solverline.com/api/v1/public/comprobantes/2309.../xml"
}
GET/public/comprobantes/{clave_acceso}/pdfpermiso: comprobantes:read
GET/public/comprobantes/{clave_acceso}/xmlpermiso: comprobantes:read

El PDF es el RIDE oficial; el XML es el comprobante autorizado por el SRI. Los dos exigen el token, así que descárgalos desde tu servidor. Si el comprobante aún no está autorizado, responden 409.

Pedidos (proformas)

Para tiendas que reciben pedidos y los facturan después, desde Solverline.

POST/public/pedidopermiso: pedidos:write
{
  "modo": "proforma",
  "cliente": { "identificacion": "0912345678", "razon_social": "MARIA PEREZ",
               "email": "maria@correo.com" },
  "items": [ { "sku": "ST-001", "descripcion": "SOPORTE TECNICO POR HORAS", "cantidad": 1 } ],
  "notas": "Entregar en la mañana",
  "referencia_externa": "WEB-5541",
  "webhook_url": "https://mitienda.com/avisos/solverline"
}

Respuesta:

{
  "modo": "proforma", "proforma_id": "…", "numero_proforma": "PRO-2026-030",
  "referencia_externa": "WEB-5541",
  "subtotal": 35.0, "total_iva": 5.25, "total": 40.25, "estado": "pendiente",
  "url_ver": "https://facturacion.solverline.com/empresas/…/proformas/…"
}
  • modo solo acepta "proforma". Para facturar usa POST /public/facturas.
  • Si envías webhook_url, Solverline hace un POST a esa dirección con la misma respuesta. Tiene que ser una dirección pública.
  • Los ítems funcionan igual que en la factura: precio_unitario sin IVA, o el precio de Solverline si mandas un sku válido.
GET/public/pedido/{referencia_externa}permiso: pedidos:write

Devuelve el estado de la proforma y, si la empresa ya la facturó, numero_factura y clave_acceso_sri.

Ejemplo completo: token y factura

<?php
$api = "https://facturacion.solverline.com/api/v1";

function llamar($metodo, $url, $datos = null, $token = null) {
    $ch = curl_init($url);
    $cab = ["Content-Type: application/json"];
    if ($token) $cab[] = "Authorization: Bearer $token";
    curl_setopt_array($ch, [CURLOPT_CUSTOMREQUEST => $metodo, CURLOPT_HTTPHEADER => $cab,
        CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 90]);
    if ($datos !== null) curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($datos));
    $resp = json_decode(curl_exec($ch), true);
    $codigo = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    if ($codigo >= 400) throw new Exception($resp["detail"] ?? "Error $codigo");
    return $resp;
}

$t = llamar("POST", "$api/oauth/token", ["grant_type" => "client_credentials",
    "client_id" => getenv("SLV_CLIENT_ID"), "client_secret" => getenv("SLV_CLIENT_SECRET")]);

$factura = llamar("POST", "$api/public/facturas", [
    "cliente" => ["identificacion" => "9999999999999", "razon_social" => "CONSUMIDOR FINAL"],
    "items"   => [["sku" => "ST-001", "descripcion" => "SOPORTE TECNICO POR HORAS", "cantidad" => 1]],
    "forma_pago" => "TARJETA_CREDITO",
    "referencia_externa" => "PEDIDO-10025",
], $t["access_token"]);

echo $factura["estado"] . " " . $factura["clave_acceso"];

Reutiliza el token mientras dure (1 hora); no pidas uno nuevo en cada llamada.

Códigos y valores

IVA

Envías ivaCódigo SRI (catálogo)
00
55
15 (por defecto)4

Tipo de identificación

CódigoTipoSe deduce cuando…
04RUCla identificación tiene 13 dígitos
05Cédulatiene 10 dígitos
06Pasaportecualquier otro caso
07Consumidor finales 9999999999999

Formas de pago

ValorSignificado
EFECTIVOEfectivo
TRANSFERENCIATransferencia bancaria
SISTEMA_FINANCIEROOtro pago por el sistema financiero (por defecto)
TARJETA_CREDITO · TARJETA_DEBITO · TARJETA_PREPAGOTarjetas
DEBITO_BANCARIO · CHEQUEDébito bancario, cheque
DINERO_ELECTRONICO · DEUNABilleteras electrónicas
CREDITO_15 · CREDITO_30 · CREDITO_45 · CREDITO_60 · CREDITO_90Venta a crédito a esos días

Motivos de nota de crédito

CódigoMotivo
01Devolución de mercadería
02Anulación de factura
03Rebaja en precio
04Otros