API de Factura Electrónica en Costa Rica
El API de Factura Electrónica de FACTURATica convierte su sistema en una factoría automática de comprobantes electrónicos integrada con el sistema de Hacienda Costa Rica API. El más completo API de Factura Electrónica Costa Rica y la solución más robusta de facturación electrónica Costa Rica para desarrolladores: webservice REST listo para integrarse con cualquier lenguaje de programación, exclusivo para licencias ILIMITADO TODO anuales.
Timbre factura electrónica, tiquetes electrónicos, facturas de exportación, notas de crédito y facturas electrónicas de compra (FEC) directamente con Hacienda Costa Rica vía API. Consulte estado, descargue XML firmado y PDF, anule documentos — todo desde su sistema, sin login manual.
- Capacidades del API de Factura Electrónica de FACTURATica
- Quick Start del API de Factura Electronica (en 2 minutos)
- Generalidades del API de Factura Electronica
- Limites del API
- Endpoints del API de Factura Electronica
- Estructura de Lineas de Detalle
- Tablas de Referencia
- Condiciones de Venta
- Medios de Pago
- Unidades de Medida
- Tarifas de IVA
- Codigos de Respuesta
- Galeria de 13 Ejemplos PHP del API de Factura Electronica
- Preguntas Frecuentes (FAQ)
- Buenas Practicas
Capacidades del API de Factura Electrónica de FACTURATica
Webservice REST que se integra con cualquier lenguaje de programación. Disponible exclusivamente con licencias ILIMITADO TODO.
PREPAGO |
ILIMITADO TODO |
|---|---|
|
|
|
| Capacidad y Escalabilidad | |
| Concurrencia por defecto1 documento por minuto, virtualmente ~40,000 documentos al mes — suficiente para la mayoría de operaciones medianas | |
| No incluido | Incluido |
| Escalable por bloquesAdquiera licencias adicionales en bloques para incrementar la capacidad concurrente cuando su volumen lo requiera | |
| No incluido | Incluido |
| Consulta y Gestión de Documentos | |
| Consulta de Estado en Tiempo RealVerifique el procesamiento de cualquier documento (aceptado, rechazado, pendiente) sin esperar el correo de Hacienda — respuesta sincrónica al instante | |
| No incluido | Incluido |
| Descarga de Archivos AsociadosRecupere XML firmado, XML respuesta de Hacienda y PDF de cualquier documento desde su sistema — útil para auditoría y trazabilidad continua | |
| No incluido | Incluido |
| Anulación de DocumentosAnule errores con Notas de Crédito generadas desde el API — flujo programático sin intervención manual | |
| No incluido | Incluido |
| Timbraje de Documentos Electrónicos | |
| Timbraje de Facturas ElectrónicasEmita facturas (FE) directamente desde su sistema sin login a la plataforma — endpoint REST con confirmación inmediata y clave numérica de Hacienda | |
| No incluido | Incluido |
| Timbraje de Tiquetes ElectrónicosGenere tiquetes (TE) para ventas de mostrador desde su POS o app — mismo flujo automatizado que el FE, JSON in/out | |
| No incluido | Incluido |
| Timbraje de Facturas de ExportaciónCumpla con normativa Hacienda en operaciones internacionales sin pasos extra — soporte para divisas y receptor extranjero (FEE) | |
| No incluido | Incluido |
Quick Start del API de Factura Electronica (en 2 minutos)
Tres pasos hasta su primera factura electronica timbrada con el API de Factura Electronica de FACTURATica desde un comando de terminal. Si ya tiene su licencia ILIMITADO TODO anual activa, deberia tomarle menos de dos minutos integrar la facturacion electronica de Hacienda Costa Rica con su sistema.
Obtenga su API_KEY y URL del API
Ingrese al panel de su licencia FACTURATica y siga esta ruta:
Esa pantalla muestra los tres datos que necesita anotar:
- URL del API — lo llamaremos
$URL_API - API_KEY de 32 caracteres unica para su licencia
- CORREO e IDENTIFICACION con que se registro la licencia
Pruebe el endpoint mas simple — consultar un nombre
Antes de timbrar, valide que sus credenciales funcionan con el endpoint NOMBRE — no escribe nada en su licencia, es completamente seguro de probar. Reemplace $URL_API con la URL que vio en su panel:
curl -sS -X POST $URL_API
--data-urlencode "ACTION=NOMBRE"
--data-urlencode "CORREO=su-correo@licencia.com"
--data-urlencode "API_KEY=SU_API_KEY_DE_32_CARS"
--data-urlencode "IDENTIFICACION=SU_CEDULA_FISICA_O_JURIDICA"
--data-urlencode "NUMERO=3101360759"
Respuesta esperada (JSON):
{
"success": true,
"numero": "3101360759",
"nombre": "EMPRESA EJEMPLO SOCIEDAD ANONIMA"
}
Timbre su primera factura electronica
Una vez confirmadas las credenciales, este es el llamado minimo que genera una factura electronica de una linea por ¢282.500 con IVA 13%:
curl -sS -X POST $URL_API
--data-urlencode "ACTION=TIMBRAR_FACTURA"
--data-urlencode "CORREO=correo@licencia.com"
--data-urlencode "API_KEY=su-api-key"
--data-urlencode "IDENTIFICACION=101110111"
--data-urlencode "RECEPTOR_NUMERO=3101360759"
--data-urlencode "LINEAS=[{"NumeroLinea":"1","Cantidad":"1.00","UnidadMedida":"Unid","Detalle":"Servicio mensual","PrecioUnitario":"250000.00","MontoTotal":"250000.00","SubTotal":"250000.00","Tarifa":"13","Monto":"32500.00","MontoTotalLinea":"282500.00"}]"
--data-urlencode "SUBTOTAL=250000.00"
--data-urlencode "IV=32500.00"
--data-urlencode "TOTALIVI=282500.00"
--data-urlencode "CONDICIONVENTA=01"
--data-urlencode "MEDIOPAGO=04"
Si todo esta bien, la respuesta sera una cadena de exactamente 50 caracteres numericos (la clave del documento). Cualquier otra cosa es un error — vea la tabla de codigos de respuesta.
ESTADO para verificar la aceptacion final.Generalidades del API de Factura Electronica
El API de Factura Electronica de FACTURATica es un webservice REST que permite a su sistema timbrar facturas electronicas, tiquetes, notas de credito, notas de debito, facturas de exportacion (FEE) y facturas electronicas de compra (FEC) directamente con el Ministerio de Hacienda de Costa Rica. Esta seccion cubre los aspectos comunes a todos los endpoints: el URL base, el modelo de autenticacion, las especificaciones tecnicas y los limites operativos de la facturacion electronica API.
Disponibilidad: el API de Factura Electronica esta disponible exclusivamente para licencias ILIMITADO TODO anuales. Las licencias mensuales y PREPAGO no incluyen acceso al API. Si su licencia se degrada a PREPAGO o cambia a mensual, el API deja de funcionar.
Informacion General
El URL del API es especifico de su licencia y aparece en su panel de FACTURATica (Configuraciones → Otros → API), junto con la API_KEY. Por convencion, en este manual nos referimos a el como $URL_API — reemplacelo con el valor exacto que ve en su panel.
Especificaciones Tecnicas
| Caracteristica | Especificacion |
|---|---|
| Metodo HTTP | POST exclusivamente |
| Encoding | UTF-8 |
| Formato de Entrada | application/x-www-form-urlencoded |
| Formato de Respuesta | String (clave 50 caracteres) o JSON |
| Timeout Recomendado | 30 segundos |
| Licencias Compatibles | Solo licencias ILIMITADO TODO anuales |
Configuracion SSL recomendada (PHP/cURL)
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
Autenticacion
Cada llamada al API requiere tres parametros de autenticacion. La API_KEY es unica por licencia y debe mantenerse segura.
$auth = [
'API_KEY' => 'SU_API_KEY_GENERADO',
'CORREO' => 'correo@registrado.com',
'IDENTIFICACION' => '401870940',
];
Limites del API
El API no impone limites de cantidad siempre que las solicitudes se realicen de forma secuencial e individual.
- Permitido: una solicitud despues de recibir respuesta de la anterior
- No permitido: multiples solicitudes simultaneas o paralelas
- No permitido: bombardeo de solicitudes sin esperar respuestas
En caso de detectar abuso (solicitudes masivas paralelas o comportamiento anormal), el sistema activara automaticamente un limite de 1 solicitud por minuto.
Recomendacion de implementacion
Si su sistema necesita procesar muchos documentos:
- Cola interna: almacene las solicitudes pendientes
- Procesamiento secuencial: despache una solicitud a la vez
- Manejo de respuestas: espere y procese cada respuesta antes de continuar
- Reintentos con espera progresiva en caso de fallo (backoff exponencial)
Endpoints del API de Factura Electronica
El API de Factura Electronica de FACTURATica expone los siguientes endpoints para timbrar factura electronica, anular factura electronica, consultar estado de documentos y validar cedulas con Hacienda Costa Rica. Todos comparten la misma URL base ($URL_API, el valor exacto aparece en su panel) y se distinguen por el valor del parametro ACTION en el cuerpo del POST. Click sobre cada endpoint para expandir o colapsar su contenido.
POST TIMBRAR_FACTURA Timbrar Factura Electronica
Permite timbrar factura electronica completa con informacion detallada del receptor ante Hacienda Costa Rica. Soporta multiples condiciones de venta y medios de pago. Es el endpoint mas usado del API de Factura Electronica de FACTURATica.
Parametros requeridos
| Parametro | Tipo | Descripcion | Validacion |
|---|---|---|---|
ACTION | string | Valor fijo: TIMBRAR_FACTURA | Obligatorio |
CORREO | string | Email del emisor | Email valido |
API_KEY | string | Llave API | 32 caracteres |
IDENTIFICACION | string | ID del emisor | 9-12 digitos |
LINEAS | JSON string | Detalle de lineas (ver mas abajo) | JSON valido |
SUBTOTAL | decimal | Subtotal sin IVA | Mayor a 0 |
IV | decimal | Total de impuestos | >= 0 |
TOTALIVI | decimal | Total con IVA | SUBTOTAL + IV |
Parametros opcionales
| Parametro | Tipo | Descripcion | Default / Notas |
|---|---|---|---|
RECEPTOR_NOMBRE | string | Razon social o nombre | Recomendado |
RECEPTOR_NUMERO | string | Identificacion fiscal | Recomendado |
RECEPTOR_CORREOELECTRONICO | string | Email para envio | Opcional |
RECEPTOR_NUMTELEFONO | string | Telefono (8 digitos) | Opcional |
RECEPTOR_CODIGOPAIS | string | Codigo pais telefono | Default: 506 |
RECEPTOR_DIRECCION_PROVINCIA | string | Codigo provincia (1-7) | Default: 1 |
RECEPTOR_DIRECCION_CANTON | string | Codigo canton | Default: 01 |
RECEPTOR_DIRECCION_DISTRITO | string | Codigo distrito | Default: 01 |
RECEPTOR_DIRECCION_BARRIO | string | Codigo barrio | Default: 01 |
RECEPTOR_DIRECCION_OTRAS | string | Senas adicionales | Default: Centro |
CONDICIONVENTA | string | Ver tabla Condiciones de Venta | Default: 01 |
PLAZOCREDITO | int/string | Dias (entero) o fecha (d/m/Y o Y-m-d H:i:s) | Default: 0 |
MEDIOPAGO | string | Ver tabla Medios de Pago | Default: 01 |
MEDIOPAGO_OTROS | string | Descripcion cuando MEDIOPAGO=99 | — |
CODIGOMONEDA | string | CRC o USD | Default: CRC |
TIPO_DE_CAMBIO | decimal | Requerido para USD | Tipo del dia |
TotalIVADevuelto | decimal | Para servicios medicos | Default: 0.00 |
CODIGOACTIVIDAD | string | Codigo actividad economica | 6 digitos |
OBSERVACIONES | string | Notas adicionales | Maximo 500 caracteres |
Respuesta
Exito: clave numerica de 50 caracteres del documento generado.
Ejemplo cURL
curl -sS -X POST $URL_API
--data-urlencode "ACTION=TIMBRAR_FACTURA"
--data-urlencode "CORREO=correo@licencia.com"
--data-urlencode "API_KEY=su-api-key"
--data-urlencode "IDENTIFICACION=101110111"
--data-urlencode "RECEPTOR_NUMERO=3101360759"
--data-urlencode "LINEAS=[{"NumeroLinea":"1","Cantidad":"1.00","UnidadMedida":"Unid","Detalle":"Servicio mensual","PrecioUnitario":"250000.00","MontoTotal":"250000.00","SubTotal":"250000.00","Tarifa":"13","Monto":"32500.00","MontoTotalLinea":"282500.00"}]"
--data-urlencode "SUBTOTAL=250000.00"
--data-urlencode "IV=32500.00"
--data-urlencode "TOTALIVI=282500.00"
--data-urlencode "CONDICIONVENTA=01"
--data-urlencode "MEDIOPAGO=04"
Ejemplo PHP completo
Ver ejemplo PHP
<?php
// Para que se vea en el navegador formateado el texto
header("Content-Type: text/plain; charset=UTF-8");
/**
* Ejemplo 1: Factura Formato Pequeño - Una Línea
* FACTURATica.com API
*/
$api_url = 'https://SU-DOMINIO-PANEL/_api.php';
$data = [
'ACTION' => 'TIMBRAR_FACTURA',
'CORREO' => 'correo@licencia.com',
'API_KEY' => '8YQ...',
'IDENTIFICACION' => '101110111',
];
/********************************************************************************
* BLOQUE DE PRUEBAS *
* Este bloque se utiliza para cargar datos de prueba durante el desarrollo. *
* Puede eliminarse sin problema alguno *
********************************************************************************/
if (file_exists('datos_prueba.php')) {
require_once 'datos_prueba.php';
}
/********************************************************************************
* FIN DEL BLOQUE DE PRUEBAS *
********************************************************************************/
// Construir líneas de detalle
$lineas = [
[
"NumeroLinea" => "1",
"Cantidad" => "1.00",
"UnidadMedida" => "Unid",
"Detalle" => "Servicio de consultoría mensual",
"PrecioUnitario" => "250000.00",
"MontoTotal" => "250000.00",
"SubTotal" => "250000.00",
"Codigo" => "01",
"Tarifa" => "13",
"Monto" => "32500.00",
"MontoTotalLinea" => "282500.00"
]
];
$data +=[
// Datos del receptor
'RECEPTOR_NUMERO' => '3101360759',
// Líneas de detalle
'LINEAS' => json_encode($lineas),
// Totales
'SUBTOTAL' => 250000.00,
'IV' => 32500.00,
'TOTALIVI' => 282500.00,
// Condiciones comerciales
'CONDICIONVENTA' => '01', // Contado
'MEDIOPAGO' => '04', // Transferencia
'CODIGOMONEDA' => 'CRC',
];
// Ejecutar petición
$ch = curl_init($api_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Mostrar respuesta
echo "==============================================n";
echo "EJEMPLO 1: Factura - Una Línean";
echo "==============================================n";
echo "HTTP Code: " . $http_code . "n";
echo "Respuesta: " . $response . "n";
// Si la respuesta es una clave de 50 caracteres, fue exitoso
if (strlen($response) == 50) {
echo "n✓ FACTURA TIMBRADA EXITOSAMENTEn";
echo "Clave: " . $response . "n";
} else {
echo "n✗ ERROR EN EL TIMBRAJEn";
}
?>
POST TIMBRAR_TIQUETE Tiquete Electronico
Genera un tiquete electronico en formato pequeno, ideal para ventas rapidas a consumidor final donde no se requieren datos del receptor.
Parametros requeridos
| Parametro | Tipo | Descripcion | Validacion |
|---|---|---|---|
ACTION | string | Valor fijo: TIMBRAR_TIQUETE | Obligatorio |
CORREO | string | Email del emisor registrado | Email valido |
API_KEY | string | Llave API del emisor | 32 caracteres |
IDENTIFICACION | string | Cedula/RUC del emisor | 9-12 digitos |
LINEAS | JSON string | Detalle de productos/servicios | JSON valido |
SUBTOTAL | decimal | Total antes de impuestos | Mayor a 0 |
IV | decimal | Impuesto de ventas total | >= 0 |
TOTALIVI | decimal | Total final con impuestos | Igual a SUBTOTAL + IV |
Parametros opcionales
| Parametro | Tipo | Descripcion | Default / Notas |
|---|---|---|---|
TOTAL | decimal | Total del documento | Usa TOTALIVI |
CODIGOMONEDA | string | CRC o USD | Default: CRC |
TIPO_DE_CAMBIO | decimal | Solo para USD | Tipo del dia |
Respuesta
Exito: clave numerica de 50 caracteres del tiquete generado.
Ejemplo cURL
curl -sS -X POST $URL_API
--data-urlencode "ACTION=TIMBRAR_TIQUETE"
--data-urlencode "CORREO=correo@licencia.com"
--data-urlencode "API_KEY=su-api-key"
--data-urlencode "IDENTIFICACION=101110111"
--data-urlencode "LINEAS=[{"NumeroLinea":"1","Cantidad":"1.00","UnidadMedida":"Unid","Detalle":"Cafe americano","PrecioUnitario":"1500.00","MontoTotal":"1500.00","SubTotal":"1500.00","Tarifa":"13","Monto":"195.00","MontoTotalLinea":"1695.00"}]"
--data-urlencode "SUBTOTAL=1500.00"
--data-urlencode "IV=195.00"
--data-urlencode "TOTALIVI=1695.00"
Ejemplo PHP completo
Ver ejemplo PHP
<?php
// Para que se vea en el navegador formateado el texto
header("Content-Type: text/plain; charset=UTF-8");
/**
* Ejemplo 5: Tiquete Electrónico Simple
* FACTURATica.com API
* Para ventas a cliente general sin datos del receptor
*/
$api_url = 'https://SU-DOMINIO-PANEL/_api.php';
$data = [
'ACTION' => 'TIMBRAR_TIQUETE',
'CORREO' => 'correo@licencia.com',
'API_KEY' => '8YQ...',
'IDENTIFICACION' => '101110111',
];
/********************************************************************************
* BLOQUE DE PRUEBAS *
* Este bloque se utiliza para cargar datos de prueba durante el desarrollo. *
* Puede eliminarse sin problema alguno *
********************************************************************************/
if (file_exists('datos_prueba.php')) {
require_once 'datos_prueba.php';
}
/********************************************************************************
* FIN DEL BLOQUE DE PRUEBAS *
********************************************************************************/
// Construir línea simple para tiquete
$lineas = [
[
"NumeroLinea" => "1",
"Cantidad" => "1",
"UnidadMedida" => "Unid",
"Detalle" => "Venta de productos varios",
"PrecioUnitario" => "10000.00",
"MontoTotal" => "10000.00",
"SubTotal" => "10000.00",
"Tarifa" => "13",
"Monto" => "1300.00",
"MontoTotalLinea" => "11300.00"
]
];
$data += [
// Líneas de detalle
'LINEAS' => json_encode($lineas),
// Totales
'SUBTOTAL' => 10000.00,
'IV' => 1300.00,
'TOTALIVI' => 11300.00,
];
// Ejecutar petición
$ch = curl_init($api_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Mostrar respuesta
echo "==============================================n";
echo "EJEMPLO 5: Tiquete Electrónico Simplen";
echo "==============================================n";
echo "HTTP Code: " . $http_code . "n";
echo "Respuesta: " . $response . "n";
// Si la respuesta es una clave de 50 caracteres, fue exitoso
if (strlen($response) == 50) {
echo "n✓ TIQUETE TIMBRADO EXITOSAMENTEn";
echo "Clave: " . $response . "n";
echo "nCaracterísticas del tiquete:n";
echo "- Cliente: General (sin datos)n";
echo "- Pago: Efectivon";
echo "- Total: ₡11,300n";
echo "- Formato: Pequeño (tiquete)n";
} else {
echo "n✗ ERROR EN EL TIMBRAJEn";
}
?>
POST TIMBRAR_FACTURA_EXPORTACION Factura de Exportacion (FEE)
Emite facturas de exportacion para transacciones internacionales con tratamiento fiscal especial. Sin IVA (las exportaciones estan exentas), receptor extranjero soportado (identificacion tipo 05) y direccion internacional via campo dedicado. Importante (Hacienda v4.4): el codigo de condicion de venta 12 (operacion de exportacion) fue removido en v4.4. Usar 01 (contado) o 02 (credito).
Parametros requeridos
| Parametro | Tipo | Descripcion | Validacion |
|---|---|---|---|
ACTION | string | Valor fijo: TIMBRAR_FACTURA_EXPORTACION | Obligatorio |
CONDICIONVENTA | string | Codigo de condicion (01=contado, 02=credito). NO usar 12. | 01 |
RECEPTOR_NUMERO | string | ID extranjero con letras permitidas | EXT123456 |
RECEPTOR_OTRASSENAS_EXT | string | Direccion completa en el extranjero | 123 Main St, Miami FL |
CODIGOMONEDA | string | Tipicamente USD | USD |
IV | decimal | Siempre 0 para exportaciones | 0.00 |
Respuesta
Exito: clave numerica de 50 caracteres de la factura de exportacion.
Ejemplo cURL
curl -sS -X POST $URL_API
--data-urlencode "ACTION=TIMBRAR_FACTURA_EXPORTACION"
--data-urlencode "CORREO=correo@licencia.com"
--data-urlencode "API_KEY=su-api-key"
--data-urlencode "IDENTIFICACION=101110111"
--data-urlencode "RECEPTOR_NOMBRE=Cliente Internacional Inc."
--data-urlencode "RECEPTOR_NUMERO=EXT123456"
--data-urlencode "RECEPTOR_OTRASSENAS_EXT=123 Main St, Miami FL 33101 USA"
--data-urlencode "LINEAS=[{"NumeroLinea":"1","Cantidad":"1.00","UnidadMedida":"Sp","Detalle":"Servicio de consultoria","PrecioUnitario":"500.00","MontoTotal":"500.00","SubTotal":"500.00","Tarifa":"0","Monto":"0.00","MontoTotalLinea":"500.00"}]"
--data-urlencode "SUBTOTAL=500.00"
--data-urlencode "IV=0.00"
--data-urlencode "TOTALIVI=500.00"
--data-urlencode "CONDICIONVENTA=01"
--data-urlencode "MEDIOPAGO=04"
--data-urlencode "CODIGOMONEDA=USD"
--data-urlencode "TIPO_DE_CAMBIO=520.00"
Ejemplo PHP completo
Ver ejemplo PHP
<?php
// Para que se vea en el navegador formateado el texto
header("Content-Type: text/plain; charset=UTF-8");
/**
* Ejemplo 13: Factura Electrónica de Exportación (FEE)
* FACTURATica.com API
*
* ┌─────────────────────────────────────────────────────────────────────────┐
* │ ¿Qué es este caso? │
* ├─────────────────────────────────────────────────────────────────────────┤
* │ Venta a un cliente extranjero (fuera de Costa Rica). Las exportaciones │
* │ son operaciones EXENTAS de IVA, normalmente facturadas en USD u otra │
* │ moneda extranjera. │
* │ │
* │ Características distintivas: │
* │ - ACTION = TIMBRAR_FACTURA_EXPORTACION │
* │ - CONDICIONVENTA = 01 contado (Hacienda v4.4 ya NO acepta el código '12')│
* │ - IV = 0 (sin IVA, exportación exenta) │
* │ - Tarifa de cada línea = 0 │
* │ - CODIGOMONEDA = USD (típico) + TIPO_DE_CAMBIO │
* │ - RECEPTOR_NUMERO contiene letras → identificación tipo 05 │
* │ - RECEPTOR_OTRASSENAS_EXT con la dirección extranjera │
* └─────────────────────────────────────────────────────────────────────────┘
*/
$api_url = 'https://SU-DOMINIO-PANEL/_api.php';
$data = [
'ACTION' => 'TIMBRAR_FACTURA_EXPORTACION',
'CORREO' => 'correo@licencia.com',
'API_KEY' => '8YQ...',
'IDENTIFICACION' => '101110111',
];
/********************************************************************************
* BLOQUE DE PRUEBAS *
* Este bloque se utiliza para cargar datos de prueba durante el desarrollo. *
* Puede eliminarse sin problema alguno *
********************************************************************************/
if (file_exists('datos_prueba.php')) {
require_once 'datos_prueba.php';
}
/********************************************************************************
* FIN DEL BLOQUE DE PRUEBAS *
********************************************************************************/
// Línea de detalle: servicio de consultoría exportado a cliente en Estados Unidos
// Las exportaciones llevan tarifa 0 (exentas de IVA).
$lineas = [
[
"NumeroLinea" => "1",
"Cantidad" => "1.00",
"UnidadMedida" => "Sp", // Servicios Profesionales
"Detalle" => "Consultoría tecnológica - Marzo 2026",
"PrecioUnitario" => "1500.00", // En USD
"MontoTotal" => "1500.00",
"SubTotal" => "1500.00",
"Codigo" => "01",
"Tarifa" => "0", // Exportación: exenta de IVA
"Monto" => "0.00",
"MontoTotalLinea" => "1500.00"
],
[
"NumeroLinea" => "2",
"Cantidad" => "10.00",
"UnidadMedida" => "h", // Horas
"Detalle" => "Soporte técnico remoto",
"PrecioUnitario" => "75.00",
"MontoTotal" => "750.00",
"SubTotal" => "750.00",
"Codigo" => "01",
"Tarifa" => "0",
"Monto" => "0.00",
"MontoTotalLinea" => "750.00"
]
];
$data += [
// =========================================================================
// DATOS DEL RECEPTOR EXTRANJERO
// El sistema detecta receptor extranjero por las letras en RECEPTOR_NUMERO
// y le asigna tipoIdentificacion = 05.
// =========================================================================
'RECEPTOR_NOMBRE' => 'Acme Corporation Inc.',
'RECEPTOR_NUMERO' => 'EIN-841234567', // Tax ID estadounidense (con letras)
'RECEPTOR_CORREOELECTRONICO' => 'accounts-payable@acme.com',
'RECEPTOR_NUMTELEFONO' => '00000000',
// Dirección extranjera del cliente (se coloca en <Receptor><OtrasSenasExtranjero>)
'RECEPTOR_OTRASSENAS_EXT' => '350 Fifth Avenue, New York, NY 10118, USA',
// Líneas de detalle
'LINEAS' => json_encode($lineas),
// Totales (sin IVA — exportación)
'SUBTOTAL' => 2250.00,
'IV' => 0.00,
'TOTALIVI' => 2250.00,
// Condiciones comerciales
'CONDICIONVENTA' => '01', // Contado (Hacienda v4.4 ya no acepta '12')
'MEDIOPAGO' => '04', // Transferencia internacional
'CODIGOMONEDA' => 'USD', // Dólar estadounidense
'TIPO_DE_CAMBIO' => '520.00', // CRC por USD (referencial - el sistema toma del día si se omite)
'OBSERVACIONES' => 'Servicios profesionales prestados desde Costa Rica al exterior',
];
// Ejecutar petición
$ch = curl_init($api_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Mostrar respuesta
echo "==============================================n";
echo "EJEMPLO 13: FEE - Factura de Exportación (USD)n";
echo "==============================================n";
echo "HTTP Code: " . $http_code . "n";
echo "Respuesta: " . $response . "n";
// Si la respuesta es una clave de 50 caracteres, fue exitoso
if (strlen($response) == 50) {
echo "n✓ FACTURA DE EXPORTACIÓN TIMBRADA EXITOSAMENTEn";
echo "Clave: " . $response . "n";
echo "nCaracterísticas:n";
echo "- Receptor: cliente extranjero (USA)n";
echo "- Moneda: USDn";
echo "- IVA: 0 (exportación exenta)n";
echo "- Subtotal USD: $" . number_format($data['SUBTOTAL'], 2) . "n";
} else {
echo "n✗ ERROR EN EL TIMBRAJEn";
}
?>
POST TIMBRAR_COMPRA Factura Electronica de Compra (FEC) a Proveedor No Domiciliado
Genera una Factura Electronica de Compra (FEC, tipo 08) cuando su empresa adquiere bienes o servicios de un proveedor que no puede o no esta obligado a emitir factura electronica (caso FEC proveedor no domiciliado: proveedor extranjero, persona fisica sin facturacion, etc.). Importante: en una FEC su licencia es el comprador, y los campos RECEPTOR_* contienen los datos del proveedor. El sistema intercambia automaticamente Emisor/Receptor al construir el XML bajo el schema FacturaElectronicaCompra. La InformacionReferencia es obligatoria (usualmente TIPODOCREFERENCIA=16 + CODIGOREFERENCIA=11 para Proveedor No Domiciliado).
Parametros requeridos
| Parametro | Tipo | Descripcion | Validacion |
|---|---|---|---|
ACTION | string | Valor fijo: TIMBRAR_COMPRA | Obligatorio |
CORREO | string | Email del emisor (comprador) | Email valido |
API_KEY | string | Llave API del comprador | 32 caracteres |
IDENTIFICACION | string | ID del comprador (titular de la licencia) | 9-12 digitos |
LINEAS | JSON string | Detalle de bienes/servicios adquiridos | JSON valido |
SUBTOTAL | decimal | Subtotal sin IVA | Mayor a 0 |
IV | decimal | Total de impuestos | >= 0 |
TOTALIVI | decimal | Total con IVA | SUBTOTAL + IV |
Parametros opcionales
| Parametro | Tipo | Descripcion | Default / Notas |
|---|---|---|---|
RECEPTOR_NOMBRE | string | Nombre / razon social del proveedor | Recomendado |
RECEPTOR_NUMERO | string | ID del proveedor (cedula CR o ID extranjero con letras) | Recomendado |
RECEPTOR_CORREOELECTRONICO | string | Email del proveedor | Opcional |
RECEPTOR_OTRASSENAS_EXT | string | Direccion extranjera del proveedor | Solo proveedor extranjero |
InformacionReferencia_TIPODOCREFERENCIA | string | Tipo doc referenciado (16 = Comprobante de Proveedor No Domiciliado) | Obligatorio |
InformacionReferencia_Numero | string | Numero del recibo / invoice del proveedor | Obligatorio |
InformacionReferencia_Fecha | string | Fecha del documento del proveedor | dd/mm/yyyy |
InformacionReferencia_CODIGOREFERENCIA | string | Codigo razon (11 = Proveedor No Domiciliado) | Obligatorio |
InformacionReferencia_Razon | string | Descripcion de la razon | 3-180 caracteres |
Respuesta
Exito: clave numerica de 50 caracteres de la FEC generada.
Ejemplo cURL
curl -sS -X POST $URL_API
--data-urlencode "ACTION=TIMBRAR_COMPRA"
--data-urlencode "CORREO=correo@licencia.com"
--data-urlencode "API_KEY=su-api-key"
--data-urlencode "IDENTIFICACION=101110111"
--data-urlencode "RECEPTOR_NOMBRE=Amazon Web Services EMEA SARL"
--data-urlencode "RECEPTOR_NUMERO=LU26375245"
--data-urlencode "RECEPTOR_OTRASSENAS_EXT=38 Avenue J.F. Kennedy, L-1855 Luxembourg"
--data-urlencode "LINEAS=[{"NumeroLinea":"1","Cantidad":"1.00","UnidadMedida":"Sp","Detalle":"AWS - servicios cloud","PrecioUnitario":"250000.00","MontoTotal":"250000.00","SubTotal":"250000.00","Tarifa":"13","Monto":"32500.00","MontoTotalLinea":"282500.00"}]"
--data-urlencode "SUBTOTAL=250000.00"
--data-urlencode "IV=32500.00"
--data-urlencode "TOTALIVI=282500.00"
--data-urlencode "CONDICIONVENTA=01"
--data-urlencode "MEDIOPAGO=04"
--data-urlencode "CODIGOMONEDA=CRC"
--data-urlencode "InformacionReferencia_TIPODOCREFERENCIA=16"
--data-urlencode "InformacionReferencia_CODIGOREFERENCIA=11"
--data-urlencode "InformacionReferencia_Numero=INV-2026-04-001"
--data-urlencode "InformacionReferencia_Fecha=01/05/2026"
--data-urlencode "InformacionReferencia_Razon=Servicios digitales - Proveedor no domiciliado"
Ejemplo PHP completo
Ver ejemplo PHP
<?php
// Para que se vea en el navegador formateado el texto
header("Content-Type: text/plain; charset=UTF-8");
/**
* Ejemplo 12: Factura Electrónica de Compra (FEC) - CASO PROVEEDOR EXTRANJERO
* FACTURATica.com API
*
* ┌─────────────────────────────────────────────────────────────────────────┐
* │ ¿Qué es este caso? │
* ├─────────────────────────────────────────────────────────────────────────┤
* │ Compra de servicios digitales a un proveedor no domiciliado en Costa │
* │ Rica (ej: Amazon Web Services, Google Cloud, Microsoft Azure, OpenAI, │
* │ Anthropic, etc.). El proveedor NO tiene cédula costarricense, por lo │
* │ que su identificación contiene letras o supera los 12 caracteres. │
* │ │
* │ El sistema detecta automáticamente proveedor extranjero por la │
* │ presencia de letras en RECEPTOR_NUMERO (o longitud > 12) y: │
* │ - Asigna TipoIdentificacion = 05 (Extranjero) │
* │ - Usa RECEPTOR_OTRASSENAS_EXT como dirección extranjera del Emisor │
* │ - Omite la Ubicación nacional (Provincia/Cantón/Distrito) │
* │ │
* │ La Información de Referencia debe usar: │
* │ - TipoDocIR = 16 (Comprobante de Proveedor No Domiciliado) │
* │ - Codigo = 11 (Proveedor No Domiciliado) │
* └─────────────────────────────────────────────────────────────────────────┘
*
* En FEC, los campos RECEPTOR_* contienen los datos del PROVEEDOR (AWS).
* Al construir el XML el sistema intercambia Emisor/Receptor: la licencia
* costarricense queda como Receptor y AWS como Emisor extranjero.
*
* La Información de Referencia es OBLIGATORIA en FEC.
*/
$api_url = 'https://SU-DOMINIO-PANEL/_api.php';
$data = [
'ACTION' => 'TIMBRAR_COMPRA',
'CORREO' => 'correo@licencia.com',
'API_KEY' => '8YQ...',
'IDENTIFICACION' => '101110111', // Empresa costarricense (licencia compradora)
];
/********************************************************************************
* BLOQUE DE PRUEBAS *
* Este bloque se utiliza para cargar datos de prueba durante el desarrollo. *
* Puede eliminarse sin problema alguno *
********************************************************************************/
if (file_exists('datos_prueba.php')) {
require_once 'datos_prueba.php';
}
/********************************************************************************
* FIN DEL BLOQUE DE PRUEBAS *
********************************************************************************/
// Línea de detalle: servicios de AWS (convertidos a CRC en este ejemplo)
$lineas = [
[
"NumeroLinea" => "1",
"Cantidad" => "1.00",
"UnidadMedida" => "Sp", // Sp = Servicios Profesionales
"Detalle" => "Amazon Web Services - EC2, S3 y CloudFront (Invoice INV-2026-04-001)",
"PrecioUnitario" => "250000.00",
"MontoTotal" => "250000.00",
"SubTotal" => "250000.00",
"Codigo" => "01",
"Tarifa" => "13",
"Monto" => "32500.00",
"MontoTotalLinea" => "282500.00"
]
];
$data += [
// =========================================================================
// DATOS DEL PROVEEDOR EXTRANJERO: AWS (viajan como RECEPTOR_* y se
// intercambian automáticamente a Emisor al construir el XML de la FEC).
// El sistema detecta extranjero por las letras en RECEPTOR_NUMERO.
// =========================================================================
'RECEPTOR_NOMBRE' => 'Amazon Web Services EMEA SARL',
'RECEPTOR_NUMERO' => 'LU26375245', // VAT europeo (contiene letras)
'RECEPTOR_CORREOELECTRONICO' => 'aws-receivables@amazon.com',
'RECEPTOR_NUMTELEFONO' => '00000000',
// Dirección extranjera del proveedor (se coloca en <Emisor><OtrasSenasExtranjero>)
'RECEPTOR_OTRASSENAS_EXT' => '38 Avenue John F. Kennedy, L-1855 Luxembourg',
// Líneas de detalle
'LINEAS' => json_encode($lineas),
// Totales
'SUBTOTAL' => 250000.00,
'TOTALEXENTO' => 0.00,
'TOTALMERCANCIASGRAVADAS' => 250000.00,
'TOTALDESCUENTOS' => 0.00,
'IV' => 32500.00,
'TOTALIVI' => 282500.00,
// Condiciones comerciales
'CONDICIONVENTA' => '01', // Contado
'MEDIOPAGO' => '04', // Transferencia
'CODIGOMONEDA' => 'CRC', // Si la factura real está en USD, convierta previamente
// =========================================================================
// INFORMACIÓN DE REFERENCIA (OBLIGATORIA para FEC)
// Caso proveedor extranjero: Comprobante de Proveedor No Domiciliado
// =========================================================================
'InformacionReferencia_TIPODOCREFERENCIA' => '16', // Comprobante de Proveedor No Domiciliado
'InformacionReferencia_CODIGOREFERENCIA' => '11', // Proveedor No Domiciliado
'InformacionReferencia_Numero' => 'INV-2026-04-001', // Invoice number del proveedor
'InformacionReferencia_Fecha' => date('d/m/Y'), // Formato d/m/Y
'InformacionReferencia_Razon' => 'Servicios digitales - Proveedor no domiciliado',
];
// Ejecutar petición
$ch = curl_init($api_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Mostrar respuesta
echo "==============================================n";
echo "EJEMPLO 12: FEC - AWS (Proveedor Extranjero)n";
echo "==============================================n";
echo "HTTP Code: " . $http_code . "n";
echo "Respuesta: " . $response . "n";
// Si la respuesta es una clave de 50 caracteres, fue exitoso
if (strlen($response) == 50) {
echo "n✓ FEC TIMBRADA EXITOSAMENTEn";
echo "Clave: " . $response . "n";
} else {
echo "n✗ ERROR EN EL TIMBRAJEn";
}
?>
POST ANULAR Anular Factura Electronica de Costa Rica
Genera una nota de credito para anular factura electronica completamente (o parcialmente) que haya sido previamente aceptada por Hacienda Costa Rica. Requisito previo: el documento afectado debe estar en estado ACEPTADO. No se pueden anular facturas electronicas rechazadas o en proceso.
Parametros requeridos
| Parametro | Tipo | Descripcion | Validacion |
|---|---|---|---|
ACTION | string | Valor fijo: ANULAR | Obligatorio |
CORREO | string | Email del emisor | Email valido |
API_KEY | string | Llave API | 32 caracteres |
IDENTIFICACION | string | ID del emisor | 9-12 digitos |
CLAVENUMERICA | string | Clave del documento a anular | 50 caracteres |
Parametros opcionales
| Parametro | Tipo | Descripcion | Default / Notas |
|---|---|---|---|
PORCENTAJE_ANULACION | float | Porcentaje a anular (1.00 – 100.00) | Default: 100.00 (anulacion total) |
Respuesta
Exito: clave numerica de 50 caracteres de la nota de credito generada.
Ejemplo cURL
curl -sS -X POST $URL_API
--data-urlencode "ACTION=ANULAR"
--data-urlencode "CORREO=correo@licencia.com"
--data-urlencode "API_KEY=su-api-key"
--data-urlencode "IDENTIFICACION=101110111"
--data-urlencode "CLAVENUMERICA=50601072500310136075900100001010000000001..."
Ejemplo PHP completo
Ver ejemplo PHP
<?php
// Para que se vea en el navegador formateado el texto
header("Content-Type: text/plain; charset=UTF-8");
/**
* Ejemplo 6: Anulación de Documento
* FACTURATica.com API
*
* IMPORTANTE: Para usar este ejemplo, primero debes tener una clave
* de un documento previamente timbrado que desees anular.
*/
$api_url = 'https://SU-DOMINIO-PANEL/_api.php';
// IMPORTANTE: Reemplaza esta clave con una clave real de un documento
// que hayas timbrado previamente y que desees anular
$clave_documento = '506...';
$data = [
'ACTION' => 'ANULAR',
'CORREO' => 'correo@licencia.com',
'API_KEY' => '8YQ...',
'IDENTIFICACION' => '101110111',
];
/********************************************************************************
* BLOQUE DE PRUEBAS *
* Este bloque se utiliza para cargar datos de prueba durante el desarrollo. *
* Puede eliminarse sin problema alguno *
********************************************************************************/
if (file_exists('datos_prueba.php')) {
require_once 'datos_prueba.php';
}
/********************************************************************************
* FIN DEL BLOQUE DE PRUEBAS *
********************************************************************************/
// Datos para la anulación
$data +=[
'CLAVENUMERICA' => $clave_documento,
'PORCENTAJE_ANULACION' => 100 // Parámetro opcional
];
echo "==============================================n";
echo "EJEMPLO 6: Anulación de Documenton";
echo "==============================================n";
echo "NOTA: Para probar este ejemplo, necesitas una claven";
echo "de un documento previamente timbrado y ACEPTADO.n";
echo "----------------------------------------------n";
// Validar longitud de la clave
if (strlen($clave_documento) == 50) {
$clave_documento = $clave_documento;
} else {
echo "Error: La clave debe tener exactamente 50 caracteres.n";
echo "Longitud ingresada: " . strlen($clave_documento) . " caracteres.n";
exit;
}
echo "nAnulando documento con clave:n" . $clave_documento . "nn";
// Ejecutar petición
$ch = curl_init($api_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Mostrar respuesta
echo "HTTP Code: " . $http_code . "n";
echo "Respuesta: " . $response . "nn";
// Interpretar respuesta
if (strlen($response) == 50) {
echo "✓ DOCUMENTO ANULADO EXITOSAMENTEn";
echo "Clave de la nota de crédito: " . $response . "n";
} else {
echo "✗ ERROR EN LA ANULACIÓNn";
// Interpretar códigos de error comunes
switch ($response) {
case '-1':
echo "Error: Parámetros faltantes o incorrectosn";
break;
case '-2':
echo "Error: Fallo de conexión con la base de datosn";
break;
case '0':
echo "Error: Credenciales rechazadasn";
break;
default:
echo "Código de error: " . $response . "n";
}
}
echo "n==============================================n";
echo "INSTRUCCIONES PARA PROBAR LA ANULACIÓN:n";
echo "==============================================n";
echo "1. Primero ejecuta uno de los ejemplos 1-5 para timbrar un documenton";
echo "2. Copia la clave de 50 caracteres que se generan";
echo "3. Ejecuta este script e ingresa esa clave cuando se soliciten";
echo "4. El documento será anulado en el sisteman";
POST TIMBRAR_CREDITO Nota de Credito
Genera una nota de credito electronica para anular, corregir o hacer referencia a un comprobante previamente emitido. Disminuye el monto de una transaccion anterior. A diferencia de ANULAR, permite especificar lineas y referenciar el documento original con informacion completa de razon.
Parametros requeridos
| Parametro | Tipo | Descripcion | Validacion |
|---|---|---|---|
ACTION | string | Valor fijo: TIMBRAR_CREDITO | Obligatorio |
CORREO | string | Email del emisor | Email valido |
API_KEY | string | Llave API | 32 caracteres |
IDENTIFICACION | string | ID del emisor | 9-12 digitos |
LINEAS | JSON string | Detalle de lineas | JSON valido |
SUBTOTAL | decimal | Subtotal sin IVA | Mayor a 0 |
IV | decimal | Total de impuestos | >= 0 |
TOTALIVI | decimal | Total con IVA | SUBTOTAL + IV |
Parametros opcionales
| Parametro | Tipo | Descripcion | Default / Notas |
|---|---|---|---|
RECEPTOR_NUMERO | string | Identificacion fiscal | Recomendado |
InformacionReferencia_TIPODOCREFERENCIA | string | Tipo doc referenciado | Codigo de 2 digitos |
InformacionReferencia_Numero | string | Clave del documento original | 50 caracteres |
InformacionReferencia_Fecha | string | Fecha del documento original | dd/mm/yyyy |
InformacionReferencia_CODIGOREFERENCIA | string | Codigo razon NC | 2 digitos |
InformacionReferencia_Razon | string | Descripcion de la razon | 3-180 caracteres |
Respuesta
Exito: clave numerica de 50 caracteres de la nota de credito generada.
Ejemplo cURL
curl -sS -X POST $URL_API
--data-urlencode "ACTION=TIMBRAR_CREDITO"
--data-urlencode "CORREO=correo@licencia.com"
--data-urlencode "API_KEY=su-api-key"
--data-urlencode "IDENTIFICACION=101110111"
--data-urlencode "RECEPTOR_NUMERO=3101360759"
--data-urlencode "LINEAS=[{"NumeroLinea":"1","Cantidad":"10.00","UnidadMedida":"Unid","Detalle":"Producto gravado con IVA 13%","PrecioUnitario":"5000.00","MontoTotal":"50000.00","SubTotal":"50000.00","Tarifa":"13","Monto":"6500.00","MontoTotalLinea":"56500.00"}]"
--data-urlencode "SUBTOTAL=50000.00"
--data-urlencode "IV=6500.00"
--data-urlencode "TOTALIVI=56500.00"
--data-urlencode "CONDICIONVENTA=01"
--data-urlencode "MEDIOPAGO=04"
--data-urlencode "CODIGOMONEDA=CRC"
--data-urlencode "InformacionReferencia_TIPODOCREFERENCIA=01"
--data-urlencode "InformacionReferencia_Numero=CLAVE_50_CHARS_DOC_ORIGINAL"
--data-urlencode "InformacionReferencia_Fecha=01/05/2026"
--data-urlencode "InformacionReferencia_CODIGOREFERENCIA=01"
--data-urlencode "InformacionReferencia_Razon=Anulacion total de la factura"
Ejemplo PHP completo
Ver ejemplo PHP
<?php
// Para que se vea en el navegador formateado el texto
header("Content-Type: text/plain; charset=UTF-8");
/**
* Ejemplo 9: Nota de Crédito Electrónica - Anulación Total
* FACTURATica.com API
*
* Anula completamente una factura previamente emitida
*/
$api_url = 'https://SU-DOMINIO-PANEL/_api.php';
// IMPORTANTE: Reemplaza esta clave con una clave real de un documento
// que haya timbrado previamente y que desee afectar
$clave_documento = '506...';
$data = [
'ACTION' => 'TIMBRAR_CREDITO',
'CORREO' => 'correo@licencia.com',
'API_KEY' => '8YQ...',
'IDENTIFICACION' => '101110111',
// Datos del receptor (mismo de la factura original)
'RECEPTOR_NUMERO' => '3101360759',
// Condiciones comerciales
'CONDICIONVENTA' => '01', // Contado
'MEDIOPAGO' => '04', // Transferencia
'CODIGOMONEDA' => 'CRC',
];
/********************************************************************************
* BLOQUE DE PRUEBAS *
* Este bloque se utiliza para cargar datos de prueba durante el desarrollo. *
* Puede eliminarse sin problema alguno *
********************************************************************************/
if (file_exists('datos_prueba.php')) {
require_once 'datos_prueba.php';
}
/********************************************************************************
* FIN DEL BLOQUE DE PRUEBAS *
********************************************************************************/
// Construir líneas de detalle
$lineas = [
[
"NumeroLinea" => "1",
"Cantidad" => "10.00",
"UnidadMedida" => "Unid",
"Detalle" => "Producto gravado con IVA 13%",
"PrecioUnitario" => "5000.00",
"MontoTotal" => "50000.00",
"SubTotal" => "50000.00",
"Codigo" => "01",
"Tarifa" => "13",
"Monto" => "6500.00",
"MontoTotalLinea" => "56500.00"
]
];
// Añadimos líneas a los datos
$data +=[
// Líneas de detalle
'LINEAS' => json_encode($lineas),
// Totales (mismos de la factura original)
'SUBTOTAL' => 50000.00,
'IV' => 6500.00,
'TOTALIVI' => 56500.00,
// === INFORMACIÓN DE REFERENCIA (NOMBRES CORRECTOS) ===
'InformacionReferencia_TIPODOCREFERENCIA' => '01', // 01 = Factura Electrónica
'InformacionReferencia_Numero' => $clave_documento, // Clave de 50 dígitos
'InformacionReferencia_Fecha' => '01/10/2024', // Formato: dd/mm/yyyy
'InformacionReferencia_CODIGOREFERENCIA' => '01', // 01 = Anula Documento
'InformacionReferencia_Razon' => 'Anulación total de la factura por error en emisión'
];
// Ejecutar petición
$ch = curl_init($api_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Mostrar respuesta
echo "==============================================n";
echo "EJEMPLO 9: Nota de Créditon";
echo "==============================================n";
echo "HTTP Code: " . $http_code . "n";
echo "Respuesta: " . $response . "n";
// Si la respuesta es una clave de 50 caracteres, fue exitoso
if (strlen($response) == 50) {
echo "n✓ NOTA DE CRÉDITO TIMBRADA EXITOSAMENTEn";
echo "Clave NC: " . $response . "n";
echo "nCaracterísticas:n";
echo "- Referencia: Factura " . substr($data['InformacionReferencia_Numero'], -10) . "n";
echo "- Monto anulado: " . $data['TOTALIVI'] . "n";
} else {
echo "n✗ ERROR EN EL TIMBRAJEn";
}
POST TIMBRAR_DEBITO Nota de Debito
Genera una nota de debito electronica para aumentar el monto de un comprobante previamente emitido. Importante: en una Nota de Debito los montos (SUBTOTAL, IV, TOTALIVI) representan unicamente el monto adicional que se esta cobrando, no el total acumulado con el documento original.
Parametros requeridos
| Parametro | Tipo | Descripcion | Validacion |
|---|---|---|---|
ACTION | string | Valor fijo: TIMBRAR_DEBITO | Obligatorio |
CORREO | string | Email del emisor | Email valido |
API_KEY | string | Llave API | 32 caracteres |
IDENTIFICACION | string | ID del emisor | 9-12 digitos |
LINEAS | JSON string | Detalle de lineas (monto adicional) | JSON valido |
SUBTOTAL | decimal | Subtotal sin IVA | Mayor a 0 |
IV | decimal | Total de impuestos | >= 0 |
TOTALIVI | decimal | Total con IVA | SUBTOTAL + IV |
Parametros opcionales
| Parametro | Tipo | Descripcion | Default / Notas |
|---|---|---|---|
RECEPTOR_NUMERO | string | Identificacion fiscal | Recomendado |
InformacionReferencia_TIPODOCREFERENCIA | string | Tipo doc referenciado | Codigo de 2 digitos |
InformacionReferencia_Numero | string | Clave del documento original | 50 caracteres |
InformacionReferencia_Fecha | string | Fecha del documento original | dd/mm/yyyy |
InformacionReferencia_CODIGOREFERENCIA | string | Codigo razon ND | 2 digitos |
InformacionReferencia_Razon | string | Descripcion de la razon | 3-180 caracteres |
Respuesta
Exito: clave numerica de 50 caracteres de la nota de debito generada.
Ejemplo cURL
curl -sS -X POST $URL_API
--data-urlencode "ACTION=TIMBRAR_DEBITO"
--data-urlencode "CORREO=correo@licencia.com"
--data-urlencode "API_KEY=su-api-key"
--data-urlencode "IDENTIFICACION=101110111"
--data-urlencode "RECEPTOR_NUMERO=3101360759"
--data-urlencode "LINEAS=[{"NumeroLinea":"1","Cantidad":"1.00","UnidadMedida":"Sp","Detalle":"Cargo adicional servicio urgente","PrecioUnitario":"15000.00","MontoTotal":"15000.00","SubTotal":"15000.00","Tarifa":"13","Monto":"1950.00","MontoTotalLinea":"16950.00"}]"
--data-urlencode "SUBTOTAL=15000.00"
--data-urlencode "IV=1950.00"
--data-urlencode "TOTALIVI=16950.00"
--data-urlencode "CONDICIONVENTA=01"
--data-urlencode "MEDIOPAGO=04"
--data-urlencode "CODIGOMONEDA=CRC"
--data-urlencode "InformacionReferencia_TIPODOCREFERENCIA=01"
--data-urlencode "InformacionReferencia_Numero=CLAVE_50_CHARS_DOC_ORIGINAL"
--data-urlencode "InformacionReferencia_Fecha=01/05/2026"
--data-urlencode "InformacionReferencia_CODIGOREFERENCIA=04"
--data-urlencode "InformacionReferencia_Razon=Cobro adicional por servicios"
Ejemplo PHP completo
Ver ejemplo PHP
<?php
// Para que se vea en el navegador formateado el texto
header("Content-Type: text/plain; charset=UTF-8");
/**
* Ejemplo 10: Nota de Débito Electrónica - Corrección de Monto
* FACTURATica.com API
*
* Aumenta el monto de una factura previamente emitida
* (Por ejemplo, por cobro adicional o cargo olvidado)
*/
$api_url = 'https://SU-DOMINIO-PANEL/_api.php';
// IMPORTANTE: Reemplaza esta clave con una clave real de un documento
// que haya timbrado previamente y que desee afectar
$clave_documento = '506...';
$data = [
'ACTION' => 'TIMBRAR_DEBITO',
'CORREO' => 'correo@licencia.com',
'API_KEY' => '8YQ...',
'IDENTIFICACION' => '101110111',
// Datos del receptor (mismo de la factura original)
'RECEPTOR_NUMERO' => '3101360759',
// Condiciones comerciales
'CONDICIONVENTA' => '01', // Contado
'MEDIOPAGO' => '04', // Transferencia
'CODIGOMONEDA' => 'CRC',
];
/********************************************************************************
* BLOQUE DE PRUEBAS *
* Este bloque se utiliza para cargar datos de prueba durante el desarrollo. *
* Puede eliminarse sin problema alguno *
********************************************************************************/
if (file_exists('datos_prueba.php')) {
require_once 'datos_prueba.php';
}
/********************************************************************************
* FIN DEL BLOQUE DE PRUEBAS *
********************************************************************************/
// Construir líneas de detalle con el MONTO ADICIONAL a cobrar
$lineas = [
[
"NumeroLinea" => "1",
"Cantidad" => "1.00",
"UnidadMedida" => "Sp",
"Detalle" => "Cargo adicional por servicio de entrega urgente",
"PrecioUnitario" => "15000.00",
"MontoTotal" => "15000.00",
"SubTotal" => "15000.00",
"Codigo" => "01",
"Tarifa" => "13",
"Monto" => "1950.00",
"MontoTotalLinea" => "16950.00"
]
];
// Añadimos líneas a los datos
$data +=[
// Líneas de detalle
'LINEAS' => json_encode($lineas),
// Totales (solo del monto adicional a cobrar)
'SUBTOTAL' => 15000.00,
'IV' => 1950.00,
'TOTALIVI' => 16950.00,
// === INFORMACIÓN DE REFERENCIA (NOMBRES CORRECTOS) ===
'InformacionReferencia_TIPODOCREFERENCIA' => '01', // 01 = Factura Electrónica
'InformacionReferencia_Numero' => $clave_documento, // Clave de 50 dígitos
'InformacionReferencia_Fecha' => '01/10/2024', // Formato: dd/mm/yyyy
'InformacionReferencia_CODIGOREFERENCIA' => '01', // 01 = Anula Documento
'InformacionReferencia_Razon' => 'Anulación total de la factura por error en emisión'
];
// Ejecutar petición
$ch = curl_init($api_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Mostrar respuesta
echo "==============================================n";
echo "EJEMPLO 10: Nota de Débito - Corrección Monton";
echo "==============================================n";
echo "HTTP Code: " . $http_code . "n";
echo "Respuesta: " . $response . "n";
// Si la respuesta es una clave de 50 caracteres, fue exitoso
if (strlen($response) == 50) {
echo "n✓ NOTA DE DÉBITO TIMBRADA EXITOSAMENTEn";
echo "Clave ND: " . $response . "n";
echo "nCaracterísticas:n";
echo "- Tipo: Corrección de monto (incremento)n";
echo "- Referencia: Factura " . substr($data['InformacionReferencia_Numero'], -10) . "n";
echo "- Monto adicional: " . $data['TOTALIVI'] . "n";
} else {
echo "n✗ ERROR EN EL TIMBRAJEn";
}
POST ESTADO Consultar Estado de Documento en Hacienda
Permite consultar estado documento de cualquier factura electronica timbrada con el API y opcionalmente descargar los archivos asociados (XML firmado, PDF, respuesta de Hacienda Costa Rica) en Base64. Indispensable para verificar la aceptacion final por Hacienda tras el timbraje.
Parametros requeridos
| Parametro | Tipo | Descripcion | Validacion |
|---|---|---|---|
ACTION | string | Valor fijo: ESTADO | Obligatorio |
CORREO | string | Email del emisor | Email valido |
API_KEY | string | Llave API | 32 caracteres |
IDENTIFICACION | string | ID del emisor | 9-12 digitos |
CLAVENUMERICA | string | Clave de 50 digitos | 50 caracteres |
Parametros opcionales
| Parametro | Tipo | Descripcion | Default / Notas |
|---|---|---|---|
ADJUNTOS | int | Nivel de archivos: 0 solo estado, 1 +XML, 2 +PDF, 3 +respuesta Hacienda | Default: 0 |
Respuesta
JSON con campos: ind-estado (recibido / procesando / aceptado / rechazado), FIRMADO (XML Base64 si ADJUNTOS>=1), PDF (Base64 si ADJUNTOS>=2), RESPUESTA_XML (Base64 si ADJUNTOS=3). Estados: recibido = FACTURATica recibio el documento, esta por enviarlo a Hacienda; procesando = enviado, esperando respuesta; aceptado = Hacienda lo valido; rechazado = Hacienda lo rechazo (final).
Ejemplo cURL
curl -sS -X POST $URL_API
--data-urlencode "ACTION=ESTADO"
--data-urlencode "CORREO=correo@licencia.com"
--data-urlencode "API_KEY=su-api-key"
--data-urlencode "IDENTIFICACION=101110111"
--data-urlencode "CLAVENUMERICA=506...50chars..."
--data-urlencode "ADJUNTOS=2"
Ejemplo PHP completo
Ver ejemplo PHP
<?php
// Para que se vea en el navegador formateado el texto
header("Content-Type: text/plain; charset=UTF-8");
/**
* Ejemplo 8: Consultar Estado de Documento
* FACTURATica.com API
*
* IMPORTANTE: Para usar este ejemplo, necesitas una clave de 50 caracteres
* de un documento previamente timbrado.
*/
$api_url = 'https://SU-DOMINIO-PANEL/_api.php';
// IMPORTANTE: Reemplaza esta clave con una clave real de un documento
// que hayas timbrado previamente y del cual desees conocer el estado
$clave_documento = '506...';
echo "==============================================n";
echo "EJEMPLO 8: Consultar Estado de Documenton";
echo "==============================================n";
echo "Este ejemplo muestra cómo consultar el estadon";
echo "de un documento y obtener sus archivos.n";
echo "----------------------------------------------nn";
// Ejemplo 1: Solo consultar estado (sin archivos)
echo "═══════════════════════════════════════════════n";
echo "CONSULTA 1: Solo Estado (sin archivos)n";
echo "═══════════════════════════════════════════════n";
$data = [
'ACTION' => 'ESTADO',
'CORREO' => 'correo@licencia.com',
'API_KEY' => '8YQ...',
'IDENTIFICACION' => '101110111',
];
/********************************************************************************
* BLOQUE DE PRUEBAS *
* Este bloque se utiliza para cargar datos de prueba durante el desarrollo. *
* Puede eliminarse sin problema alguno *
********************************************************************************/
if (file_exists('datos_prueba.php')) {
require_once 'datos_prueba.php';
}
/********************************************************************************
* FIN DEL BLOQUE DE PRUEBAS *
********************************************************************************/
// Validar longitud de la clave
if (strlen($clave_documento) != 50) {
echo "⚠ ADVERTENCIA: La clave debe tener exactamente 50 caracteres.n";
echo "Longitud actual: " . strlen($clave_documento) . " caracteres.n";
echo "Por favor, verifica la clave del documento.n";
exit;
}
$data += [
'CLAVENUMERICA' => $clave_documento,
'ADJUNTOS' => 0 // 0 = Solo estado
];
$ch = curl_init($api_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$response_raw = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo "HTTP Code: " . $http_code . "n";
echo "Respuesta: " . $response_raw . "n";
$response = json_decode($response_raw, true);
if ($response && isset($response['ind-estado'])) {
echo "n✓ Estado del documento: " . strtoupper($response['ind-estado']) . "n";
if (isset($response['respuesta-xml'])) {
echo "Mensaje: " . $response['respuesta-xml'] . "n";
}
}
// Ejemplo 2: Estado + XML Firmado
echo "n═══════════════════════════════════════════════n";
echo "CONSULTA 2: Estado + XML Firmadon";
echo "═══════════════════════════════════════════════n";
$data['ADJUNTOS'] = 1; // 1 = Estado + XML
$ch = curl_init($api_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$response_raw = curl_exec($ch);
curl_close($ch);
$response = json_decode($response_raw, true);
if ($response && isset($response['FIRMADO'])) {
echo "✓ XML Firmado incluido (Base64): ";
echo substr($response['FIRMADO'], 0, 50) . "...n";
echo "Longitud del XML en Base64: " . strlen($response['FIRMADO']) . " caracteresn";
// Opcional: Guardar el XML decodificado
// file_put_contents('documento.xml', base64_decode($response['FIRMADO']));
}
// Ejemplo 3: Estado + XML + Respuesta de Hacienda
echo "n═══════════════════════════════════════════════n";
echo "CONSULTA 3: Estado + XML + Respuesta Haciendan";
echo "═══════════════════════════════════════════════n";
$data['ADJUNTOS'] = 2; // 2 = Estado + XML + Respuesta
$ch = curl_init($api_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$response_raw = curl_exec($ch);
curl_close($ch);
$response = json_decode($response_raw, true);
if ($response) {
if (isset($response['FIRMADO'])) {
echo "✓ XML Firmado incluidon";
}
if (isset($response['RESPUESTA_XML'])) {
echo "✓ XML de Respuesta de Hacienda incluidon";
echo "Longitud respuesta Base64: " . strlen($response['RESPUESTA_XML']) . " caracteresn";
}
}
// Ejemplo 4: Estado + XML + PDF + Respuesta
echo "n═══════════════════════════════════════════════n";
echo "CONSULTA 4: Todos los archivos (XML+PDF+Respuesta)n";
echo "═══════════════════════════════════════════════n";
$data['ADJUNTOS'] = 3; // 3 = Todo
$ch = curl_init($api_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$response_raw = curl_exec($ch);
curl_close($ch);
$response = json_decode($response_raw, true);
if ($response) {
echo "nArchivos incluidos en la respuesta:n";
echo "-----------------------------------n";
if (isset($response['ind-estado'])) {
echo "✓ Estado: " . $response['ind-estado'] . "n";
}
if (isset($response['FIRMADO'])) {
echo "✓ XML Firmado (Base64)n";
// Para guardar: file_put_contents('doc.xml', base64_decode($response['FIRMADO']));
}
if (isset($response['PDF'])) {
echo "✓ PDF del documento (Base64)n";
// Para guardar: file_put_contents('doc.pdf', base64_decode($response['PDF']));
}
if (isset($response['RESPUESTA_XML'])) {
echo "✓ Respuesta de Hacienda (Base64)n";
// Para guardar: file_put_contents('respuesta.xml', base64_decode($response['RESPUESTA_XML']));
}
echo "n💡 TIP: Los archivos vienen codificados en Base64.n";
echo "Para guardarlos, usa base64_decode() antes de escribirlos.n";
} else {
echo "n✗ ERROR al consultar el estadon";
echo "Respuesta: " . $response_raw . "n";
}
echo "n═══════════════════════════════════════════════n";
echo "RESUMEN DE NIVELES DE RESPUESTAn";
echo "═══════════════════════════════════════════════n";
echo "ADJUNTOS = 0: Solo estado del documenton";
echo "ADJUNTOS = 1: Estado + XML firmadon";
echo "ADJUNTOS = 2: Estado + XML + Respuesta Haciendan";
echo "ADJUNTOS = 3: Estado + XML + PDF + Respuestan";
echo "nEstados posibles: aceptado, rechazado, procesandon";
echo "n═══════════════════════════════════════════════n";
echo "INSTRUCCIONES PARA PROBARn";
echo "═══════════════════════════════════════════════n";
echo "1. Ejecuta primero uno de los ejemplos 1-5 para timbrarn";
echo "2. Copia la clave de 50 caracteres generadan";
echo "3. Reemplaza la variable $clave_documento con esa claven";
echo "4. Ejecuta este script para ver el estadon";
echo "nNOTA: Los documentos nuevos pueden estar en estadon";
echo "'procesando' por unos minutos antes de ser aceptados.n";
POST NOMBRE Validar Cedula con Hacienda Costa Rica
Permite validar cedula Hacienda consultando el nombre o razon social asociada a un numero de identificacion en la base de datos oficial del Ministerio de Hacienda Costa Rica. Util para auto-completar el campo de razon social cuando el usuario ingresa la cedula del cliente antes de timbrar una factura electronica.
Parametros requeridos
| Parametro | Tipo | Descripcion | Validacion |
|---|---|---|---|
ACTION | string | Valor fijo: NOMBRE | Obligatorio |
CORREO | string | Email del emisor | Email valido |
API_KEY | string | Llave API | 32 caracteres |
IDENTIFICACION | string | ID del emisor | 9-12 digitos |
NUMERO | string | ID a consultar | 9-12 digitos |
Respuesta
JSON: {success: true, numero, nombre} en exito, o {success: false, error} en error.
Ejemplo cURL
curl -sS -X POST $URL_API
--data-urlencode "ACTION=NOMBRE"
--data-urlencode "CORREO=correo@licencia.com"
--data-urlencode "API_KEY=su-api-key"
--data-urlencode "IDENTIFICACION=101110111"
--data-urlencode "NUMERO=3101360759"
Ejemplo PHP completo
Ver ejemplo PHP
<?php
// Para que se vea en el navegador formateado el texto
header("Content-Type: text/plain; charset=UTF-8");
/**
* Ejemplo 7: Obtener nombre por identificación
* FACTURATica.com API
*
* IMPORTANTE: Solo se admiten cédulas físicas, jurídicas, dimex y nites de 9-12 digitos.
*/
$api_url = 'https://SU-DOMINIO-PANEL/_api.php';
// IMPORTANTE: Reemplaza este número por la que desee utilizar
$numero = '3101360759';
echo "=============================================================n";
echo "EJEMPLO 7: Obtener nombre por identificaciónn";
echo "=============================================================n";
echo "NOTA: Para probar este ejemplo, necesita un númeron";
echo "de identificación nacional, dimex o nite de 9-12 digitos.n";
echo "-------------------------------------------------------------n";
$data = [
'ACTION' => 'NOMBRE',
'CORREO' => 'correo@licencia.com',
'API_KEY' => '8YQ...',
'IDENTIFICACION' => '101110111',
];
/********************************************************************************
* BLOQUE DE PRUEBAS *
* Este bloque se utiliza para cargar datos de prueba durante el desarrollo. *
* Puede eliminarse sin problema alguno *
********************************************************************************/
if (file_exists('datos_prueba.php')) {
require_once 'datos_prueba.php';
}
/********************************************************************************
* FIN DEL BLOQUE DE PRUEBAS *
********************************************************************************/
$data += [
'NUMERO' => $numero
];
echo "nObteniendo nombre para la identificación número:n" . $numero . "nn";
// Ejecutar petición
$ch = curl_init($api_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$response_raw = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Mostrar respuesta
echo "HTTP Code: " . $http_code . "n";
echo "Respuesta: " . $response_raw . "nn";
// Interpretar respuesta
$response = json_decode($response_raw, true);
if (isset($response['success']) && $response['success'] === true) {
echo "✓ NOMBRE OBTENIDO EXITOSAMENTEnn";
echo "Número consultado: " . $response['numero'] . "n";
echo "Nombre: " . $response['nombre'] . "n";
} else {
echo "✗ ERROR EN LA OBTENCIÓN DEL NOMBREnn";
print_r($response_raw);
}
Estructura de Lineas de Detalle
El parametro LINEAS contiene el detalle de productos o servicios en formato JSON. Cada linea representa un item individual del documento.
Campos obligatorios
| Campo | Tipo | Descripcion | Ejemplo |
|---|---|---|---|
NumeroLinea | string | Numero secuencial unico | “1”, “2”, “3” |
Cantidad | string decimal | Cantidad del item | “2.00” |
UnidadMedida | string | Ver Unidades de Medida | “Unid” |
Detalle | string | Descripcion (max 500 caracteres) | “Laptop HP” |
PrecioUnitario | string decimal | Precio sin impuestos | “500000.00” |
MontoTotal | string decimal | Cantidad x PrecioUnitario | “1000000.00” |
SubTotal | string decimal | MontoTotal – Descuentos | “950000.00” |
Tarifa | string | Porcentaje de IVA (0, 1, 2, 4, 8, 13) | “13” |
Monto | string decimal | Monto del IVA | “123500.00” |
MontoTotalLinea | string decimal | SubTotal + IVA | “1073500.00” |
Campos opcionales
| Campo | Tipo | Descripcion | Uso |
|---|---|---|---|
Codigo | string | Codigo comercial interno o codigo de barras | Alfanumerico, mayusculas, sin espacios |
Cabys | string | Codigo CABYS | Clasificacion fiscal |
MontoDescuento | string decimal | Descuento aplicado | Promociones |
NaturalezaDescuento | string | Razon del descuento | Texto libre |
Validaciones criticas
- Coherencia de Totales: la suma de todos los
SubTotaldebe coincidir con el parametroSUBTOTAL - Calculo de IVA: la suma de todos los
Monto(IVA) debe coincidir con el parametroIV - Formato Decimal: usar punto (.) como separador decimal, maximo 2 decimales
- Secuencia:
NumeroLineadebe ser consecutivo comenzando en “1”
Ejemplo de una linea
{
"NumeroLinea": "1",
"Cantidad": "2.00",
"UnidadMedida": "Unid",
"Detalle": "Laptop HP EliteBook 840 G8",
"PrecioUnitario": "500000.00",
"MontoTotal": "1000000.00",
"SubTotal": "1000000.00",
"Codigo": "LAP-HP-840",
"Cabys": "4521100100100",
"Tarifa": "13",
"Monto": "130000.00",
"MontoTotalLinea": "1130000.00"
}
Tablas de Referencia
Codigos oficiales de Hacienda usados en distintos parametros del API.
Condiciones de Venta
Usados en el parametro CONDICIONVENTA.
| Codigo | Descripcion |
|---|---|
| 01 | Contado |
| 02 | Credito |
| 03 | Consignacion |
| 04 | Apartado |
| 05 | Arrendamiento con opcion de compra |
| 06 | Arrendamiento en funcion financiera |
| 07 | Cobro a favor de un tercero |
| 08 | Servicios prestados al Estado a credito |
| 10 | Venta a credito en IVA hasta 90 dias (Articulo 27, LIVA) |
| 13 | Venta de mercancia no nacionalizada |
| 14 | Reembolsos o pagos a tercero |
| 15 | Venta de bienes usados |
| 99 | Otros |
Medios de Pago
Usados en el parametro MEDIOPAGO.
| Codigo | Descripcion |
|---|---|
| 01 | Efectivo |
| 02 | Tarjeta |
| 03 | Cheque |
| 04 | Transferencia – deposito bancario |
| 05 | Recaudado por terceros |
| 06 | SINPE MOVIL |
| 07 | Plataforma Digital |
| 99 | Otros |
Unidades de Medida
Usadas en el campo UnidadMedida de cada linea. La lista oficial incluye unidades del SI, comerciales y tipos de servicio.
| Codigo | Descripcion |
|---|---|
| Unid | Unidad |
| Kg | Kilogramo |
| g | Gramo |
| Mg | Miligramo |
| Km | Kilometro |
| m | Metro |
| cm | Centimetro |
| mm | Milimetro |
| m² | Metro cuadrado |
| m³ | Metro cubico |
| L | Litro |
| mL | Mililitro |
| Gal | Galon |
| ln | Pulgada |
| Oz | Onzas |
| Sp | Servicios Profesionales |
| Spe | Servicios personales |
| St | Servicios tecnicos |
| Os | Otro tipo de servicio |
| Al | Alquiler de uso habitacional |
| Alc | Alquiler de uso comercial |
| Cm | Comisiones |
| I | Intereses |
| t | Tonelada |
| h | Hora |
| min | Minuto |
| s | Segundo |
| d | Dia |
| A | Ampere |
| K | Kelvin |
| mol | Mol |
| cd | Candela |
| Hz | Hertz |
| N | Newton |
| Pa | Pascal |
| J | Joule |
| W | Watt |
| C | Coulomb |
| V | Volt |
| F | Farad |
| Ω | Ohm |
| S | Siemens |
| Wb | Weber |
| T | Tesla |
| H | Henry |
| °C | Grado Celsius |
| lm | Lumen |
| lx | Lux |
| Bq | Becquerel |
| Gy | Gray |
| Sv | Sievert |
| kat | Katal |
| kW | Kilovatios |
| Rad | Radian |
| Sr | Estereorradian |
| Otros | Se debe indicar la descripcion de la medida a utilizar |
Tarifas de IVA
Usadas en el campo Tarifa de cada linea.
| Tarifa | Descripcion | Aplicacion |
|---|---|---|
| 0 | Exento | Canasta basica, medicinas |
| 1 | 1% | Tarifa reducida especial |
| 2 | 2% | Tarifa reducida especial |
| 4 | 4% | Servicios medicos privados |
| 8 | 8% | Tarifa reducida |
| 13 | 13% | Tarifa general |
Codigos de Respuesta
Respuestas de exito
| Tipo | Formato | Descripcion |
|---|---|---|
| Timbraje exitoso | String 50 caracteres | Clave unica del documento generado |
| Estado exitoso | JSON | Objeto con estado (ind-estado) y archivos solicitados |
| Nombre exitoso | JSON | Objeto con success: true, numero y nombre |
| Anulacion exitosa | String 50 caracteres | Clave de la nota de credito |
Codigos de error
| Codigo | Operaciones | Descripcion | Accion recomendada |
|---|---|---|---|
| -1 | Todas | Parametros faltantes o mal formados | Verificar todos los campos requeridos |
| -2 | Todas | Error de conexion a base de datos | Reintentar en unos minutos |
| 0 | Todas | Credenciales invalidas | Verificar API_KEY y datos de emisor |
Credenciales rechazadas | Timbraje | API_KEY incorrecto o expirado | Regenerar API_KEY en panel |
json malformated | Timbraje | JSON de lineas con error de sintaxis | Validar estructura JSON |
Su licencia no ha podido ser validada | Todas | Licencia vencida, inactiva o PREPAGO | Verificar tipo de licencia |
Galeria de 13 Ejemplos PHP del API de Factura Electronica
13 ejemplos PHP auto-contenidos para el API de Factura Electronica de Costa Rica cubriendo todos los endpoints: timbrar factura electronica, timbrar tiquete, anular factura electronica, notas de credito, notas de debito, factura electronica de compra (FEC), factura de exportacion (FEE), consultar estado documento y validar cedula con Hacienda. Reemplace el URL del API con el que ve en su panel y use sus credenciales (API_KEY, CORREO, IDENTIFICACION). Click en cada titulo para expandirlo.
01FEFactura Electronica de una linea, con receptor
<?php
// Para que se vea en el navegador formateado el texto
header("Content-Type: text/plain; charset=UTF-8");
/**
* Ejemplo 1: Factura Formato Pequeño - Una Línea
* FACTURATica.com API
*/
$api_url = 'https://SU-DOMINIO-PANEL/_api.php';
$data = [
'ACTION' => 'TIMBRAR_FACTURA',
'CORREO' => 'correo@licencia.com',
'API_KEY' => '8YQ...',
'IDENTIFICACION' => '101110111',
];
/********************************************************************************
* BLOQUE DE PRUEBAS *
* Este bloque se utiliza para cargar datos de prueba durante el desarrollo. *
* Puede eliminarse sin problema alguno *
********************************************************************************/
if (file_exists('datos_prueba.php')) {
require_once 'datos_prueba.php';
}
/********************************************************************************
* FIN DEL BLOQUE DE PRUEBAS *
********************************************************************************/
// Construir líneas de detalle
$lineas = [
[
"NumeroLinea" => "1",
"Cantidad" => "1.00",
"UnidadMedida" => "Unid",
"Detalle" => "Servicio de consultoría mensual",
"PrecioUnitario" => "250000.00",
"MontoTotal" => "250000.00",
"SubTotal" => "250000.00",
"Codigo" => "01",
"Tarifa" => "13",
"Monto" => "32500.00",
"MontoTotalLinea" => "282500.00"
]
];
$data +=[
// Datos del receptor
'RECEPTOR_NUMERO' => '3101360759',
// Líneas de detalle
'LINEAS' => json_encode($lineas),
// Totales
'SUBTOTAL' => 250000.00,
'IV' => 32500.00,
'TOTALIVI' => 282500.00,
// Condiciones comerciales
'CONDICIONVENTA' => '01', // Contado
'MEDIOPAGO' => '04', // Transferencia
'CODIGOMONEDA' => 'CRC',
];
// Ejecutar petición
$ch = curl_init($api_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Mostrar respuesta
echo "==============================================n";
echo "EJEMPLO 1: Factura - Una Línean";
echo "==============================================n";
echo "HTTP Code: " . $http_code . "n";
echo "Respuesta: " . $response . "n";
// Si la respuesta es una clave de 50 caracteres, fue exitoso
if (strlen($response) == 50) {
echo "n✓ FACTURA TIMBRADA EXITOSAMENTEn";
echo "Clave: " . $response . "n";
} else {
echo "n✗ ERROR EN EL TIMBRAJEn";
}
?>
02FEMultiples lineas con tarifas IVA mixtas (13/4/0), a credito 30 dias
<?php
// Para que se vea en el navegador formateado el texto
header("Content-Type: text/plain; charset=UTF-8");
/**
* Ejemplo 2: Factura Formato Carta - Múltiples Líneas con Diferentes IVAs
* FACTURATica.com API
*/
$api_url = 'https://SU-DOMINIO-PANEL/_api.php';
$data = [
'ACTION' => 'TIMBRAR_FACTURA',
'CORREO' => 'correo@licencia.com',
'API_KEY' => '8YQ...',
'IDENTIFICACION' => '101110111',
];
/********************************************************************************
* BLOQUE DE PRUEBAS *
* Este bloque se utiliza para cargar datos de prueba durante el desarrollo. *
* Puede eliminarse sin problema alguno *
********************************************************************************/
if (file_exists('datos_prueba.php')) {
require_once 'datos_prueba.php';
}
/********************************************************************************
* FIN DEL BLOQUE DE PRUEBAS *
********************************************************************************/
// Construir líneas de detalle con diferentes tarifas de IVA
$lineas = [
[
"NumeroLinea" => "1",
"Cantidad" => "10.00",
"UnidadMedida" => "Unid",
"Detalle" => "Producto gravado con IVA 13%",
"PrecioUnitario" => "5000.00",
"MontoTotal" => "50000.00",
"SubTotal" => "50000.00",
"Codigo" => "01",
"Tarifa" => "13",
"Monto" => "6500.00",
"MontoTotalLinea" => "56500.00"
],
[
"NumeroLinea" => "2",
"Cantidad" => "5.00",
"UnidadMedida" => "Unid",
"Detalle" => "Producto gravado con IVA 4%",
"PrecioUnitario" => "3000.00",
"MontoTotal" => "15000.00",
"SubTotal" => "15000.00",
"Codigo" => "01",
"Tarifa" => "4",
"Monto" => "600.00",
"MontoTotalLinea" => "15600.00"
],
[
"NumeroLinea" => "3",
"Cantidad" => "2.00",
"UnidadMedida" => "Kg",
"Detalle" => "Producto exento de IVA",
"PrecioUnitario" => "8000.00",
"MontoTotal" => "16000.00",
"SubTotal" => "16000.00",
"Codigo" => "01",
"Tarifa" => "0",
"Monto" => "0.00",
"MontoTotalLinea" => "16000.00"
],
[
"NumeroLinea" => "4",
"Cantidad" => "1.00",
"UnidadMedida" => "Sp",
"Detalle" => "Servicio profesional",
"PrecioUnitario" => "100000.00",
"MontoTotal" => "100000.00",
"SubTotal" => "100000.00",
"Codigo" => "01",
"Tarifa" => "13",
"Monto" => "13000.00",
"MontoTotalLinea" => "113000.00"
]
];
$data +=[
// Datos del receptor
'RECEPTOR_NOMBRE' => 'Cliente Importante S.A.',
'RECEPTOR_NUMERO' => '3101360759',
// Líneas de detalle
'LINEAS' => json_encode($lineas),
// Totales
'SUBTOTAL' => 181000.00,
'IV' => 20100.00,
'TOTALIVI' => 201100.00,
// Condiciones comerciales
'CONDICIONVENTA' => '02', // Crédito
'PLAZOCREDITO' => '30', // 30 días
'MEDIOPAGO' => '04', // Transferencia
'CODIGOMONEDA' => 'CRC',
];
// Ejecutar petición
$ch = curl_init($api_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Mostrar respuesta
echo "================================================================n";
echo "EJEMPLO 2: Factura Formato Carta - Múltiples Líneas - Créditon";
echo "================================================================n";
echo "HTTP Code: " . $http_code . "n";
echo "Respuesta: " . $response . "n";
// Si la respuesta es una clave de 50 caracteres, fue exitoso
if (strlen($response) == 50) {
echo "n✓ FACTURA TIMBRADA EXITOSAMENTEn";
echo "Clave: " . $response . "n";
echo "nResumen de líneas:n";
echo "- Línea 1: IVA 13%n";
echo "- Línea 2: IVA 4%n";
echo "- Línea 3: Exento (IVA 0%)n";
echo "- Línea 4: IVA 13%n";
} else {
echo "n✗ ERROR EN EL TIMBRAJEn";
}
?>
03FECon descuentos por volumen y promocion + codigos CABYS
<?php
// Para que se vea en el navegador formateado el texto
header("Content-Type: text/plain; charset=UTF-8");
/**
* Ejemplo 3: Factura con Descuentos
* FACTURATica.com API
*/
$api_url = 'https://SU-DOMINIO-PANEL/_api.php';
$data = [
'ACTION' => 'TIMBRAR_FACTURA',
'CORREO' => 'correo@licencia.com',
'API_KEY' => '8YQ...',
'IDENTIFICACION' => '101110111',
];
/********************************************************************************
* BLOQUE DE PRUEBAS *
* Este bloque se utiliza para cargar datos de prueba durante el desarrollo. *
* Puede eliminarse sin problema alguno *
********************************************************************************/
if (file_exists('datos_prueba.php')) {
require_once 'datos_prueba.php';
}
/********************************************************************************
* FIN DEL BLOQUE DE PRUEBAS *
********************************************************************************/
// Construir líneas de detalle con descuentos
$lineas = [
[
"NumeroLinea" => "1",
"Cantidad" => "5.00",
"UnidadMedida" => "Unid",
"Detalle" => "Mouse inalámbrico",
"PrecioUnitario" => "15000.00",
"MontoTotal" => "75000.00",
"MontoDescuento" => "7500.00", // 10% descuento
"NaturalezaDescuento" => "Descuento por volumen",
"SubTotal" => "67500.00",
"Codigo" => "01",
"Cabys" => "4321100000000",
"Tarifa" => "13",
"Monto" => "8775.00",
"MontoTotalLinea" => "76275.00"
],
[
"NumeroLinea" => "2",
"Cantidad" => "3.00",
"UnidadMedida" => "Unid",
"Detalle" => "Teclado mecánico",
"PrecioUnitario" => "45000.00",
"MontoTotal" => "135000.00",
"MontoDescuento" => "20250.00", // 15% descuento
"NaturalezaDescuento" => "Promoción especial",
"SubTotal" => "114750.00",
"Codigo" => "01",
"Cabys" => "4321100000000",
"Tarifa" => "13",
"Monto" => "14917.50",
"MontoTotalLinea" => "129667.50"
]
];
$data += [ // Datos del receptor
'RECEPTOR_NOMBRE' => 'Comprador Final',
'RECEPTOR_NUMERO' => '3101360759',
'RECEPTOR_CORREOELECTRONICO' => '',
'RECEPTOR_NUMTELEFONO' => '70007000',
// Líneas de detalle
'LINEAS' => json_encode($lineas),
// Totales
'TOTALDESCUENTOS' => 27750.00, // Total de descuentos
'SUBTOTAL' => 182250.00, // Subtotal después de descuentos
'IV' => 23692.50,
'TOTALIVI' => 205942.50,
// Condiciones comerciales
'CONDICIONVENTA' => '01', // Contado
'MEDIOPAGO' => '02', // Tarjeta
'CODIGOMONEDA' => 'CRC',
'OBSERVACIONES' => 'Descuentos aplicados por promoción Black Friday'
];
// Ejecutar petición
$ch = curl_init($api_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Mostrar respuesta
echo "==============================================n";
echo "EJEMPLO 3: Factura con Descuentosn";
echo "==============================================n";
echo "HTTP Code: " . $http_code . "n";
echo "Respuesta: " . $response . "n";
// Si la respuesta es una clave de 50 caracteres, fue exitoso
if (strlen($response) == 50) {
echo "n✓ FACTURA TIMBRADA EXITOSAMENTEn";
echo "Clave: " . $response . "n";
echo "nResumen de descuentos:n";
echo "- Mouse inalámbrico: 10% descuento (₡7,500)n";
echo "- Teclado mecánico: 15% descuento (₡20,250)n";
echo "- Total descuentos: ₡27,750n";
echo "- Total factura: ₡205,942.50n";
} else {
echo "n✗ ERROR EN EL TIMBRAJEn";
}
?>
04FEIVA Devuelto en servicios medicos privados (tarifa 4%, tarjeta)
<?php
// Para que se vea en el navegador formateado el texto
header("Content-Type: text/plain; charset=UTF-8");
/**
* Ejemplo 4: Factura con IVA Devuelto
* FACTURATica.com API
*
* IVA Devuelto aplica a:
* - Servicios médicos privados
* - Tarifa del 4%
* - Pago con tarjeta
*/
$api_url = 'https://SU-DOMINIO-PANEL/_api.php';
$data = [
'ACTION' => 'TIMBRAR_FACTURA',
'CORREO' => 'correo@licencia.com',
'API_KEY' => '8YQ...',
'IDENTIFICACION' => '101110111',
// Datos del receptor (paciente)
'RECEPTOR_NUMERO' => '3101360759',
];
/********************************************************************************
* BLOQUE DE PRUEBAS *
* Este bloque se utiliza para cargar datos de prueba durante el desarrollo. *
* Puede eliminarse sin problema alguno *
********************************************************************************/
if (file_exists('datos_prueba.php')) {
require_once 'datos_prueba.php';
}
/********************************************************************************
* FIN DEL BLOQUE DE PRUEBAS *
********************************************************************************/
// Construir líneas de detalle con servicios médicos
$lineas = [
[
"NumeroLinea" => "1",
"Cantidad" => "1.00",
"UnidadMedida" => "Sp",
"Detalle" => "Consulta médica especializada",
"PrecioUnitario" => "85000.00",
"MontoTotal" => "85000.00",
"SubTotal" => "85000.00",
"Codigo" => "01",
"Tarifa" => "4", // Tarifa especial servicios médicos
"Monto" => "3400.00",
"MontoTotalLinea" => "88400.00",
"ImpuestoNeto" => "-3400.00" // IVA Devuelto (negativo)
],
[
"NumeroLinea" => "2",
"Cantidad" => "1.00",
"UnidadMedida" => "Sp",
"Detalle" => "Exámenes de laboratorio",
"PrecioUnitario" => "125000.00",
"MontoTotal" => "125000.00",
"SubTotal" => "125000.00",
"Codigo" => "01",
"Tarifa" => "4", // Tarifa especial servicios médicos
"Monto" => "5000.00",
"MontoTotalLinea" => "130000.00",
"ImpuestoNeto" => "-5000.00" // IVA Devuelto (negativo)
],
[
"NumeroLinea" => "3",
"Cantidad" => "1.00",
"UnidadMedida" => "Sp",
"Detalle" => "Radiografía digital",
"PrecioUnitario" => "45000.00",
"MontoTotal" => "45000.00",
"SubTotal" => "45000.00",
"Codigo" => "01",
"Tarifa" => "4", // Tarifa especial servicios médicos
"Monto" => "1800.00",
"MontoTotalLinea" => "46800.00",
"ImpuestoNeto" => "-1800.00" // IVA Devuelto (negativo)
],
[
"NumeroLinea" => "4",
"Cantidad" => "1.00",
"UnidadMedida" => "Unid",
"Detalle" => "Medicamentos recetados",
"PrecioUnitario" => "35000.00",
"MontoTotal" => "35000.00",
"SubTotal" => "35000.00",
"Codigo" => "01",
"Tarifa" => "0", // Medicamentos están exentos
"Monto" => "0.00",
"MontoTotalLinea" => "35000.00"
]
];
$data += [
// Líneas de detalle
'LINEAS' => json_encode($lineas),
// Totales con IVA devuelto
'SUBTOTAL' => 290000.00, // Subtotal de todos los servicios
'TOTALEXENTO' => 35000.00, // Medicamentos exentos
'TOTALMERCANCIASGRAVADAS' => 255000.00, // Servicios médicos gravados
'IV' => 0.00, // IVA neto es 0 (todo devuelto)
'TOTALIVI' => 290000.00, // Total final (sin IVA por devolución)
'TotalIVADevuelto' => 10200.00, // Total IVA devuelto (3400+5000+1800)
// Condiciones comerciales
'CONDICIONVENTA' => '01', // Contado
'MEDIOPAGO' => '02', // TARJETA (requisito para IVA devuelto)
'CODIGOMONEDA' => 'CRC',
'OBSERVACIONES' => 'IVA devuelto aplicado según normativa para servicios médicos pagados con tarjeta'
];
// Ejecutar petición
$ch = curl_init($api_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Mostrar respuesta
echo "==============================================n";
echo "EJEMPLO 4: Factura con IVA Devuelton";
echo " (Servicios Médicos Privados)n";
echo "==============================================n";
echo "HTTP Code: " . $http_code . "n";
echo "Respuesta: " . $response . "n";
// Si la respuesta es una clave de 50 caracteres, fue exitoso
if (strlen($response) == 50) {
echo "n✓ FACTURA TIMBRADA EXITOSAMENTEn";
echo "Clave: " . $response . "n";
echo "nResumen de IVA Devuelto:n";
echo "╔═══════════════════════════════════════════════╗n";
echo "║ SERVICIOS MÉDICOS (Tarifa 4% - IVA Devuelto) ║n";
echo "╠═══════════════════════════════════════════════╣n";
echo "║ Consulta médica: ₡85,000 (IVA: -₡3,400) ║n";
echo "║ Exámenes lab: ₡125,000 (IVA: -₡5,000) ║n";
echo "║ Radiografía: ₡45,000 (IVA: -₡1,800) ║n";
echo "║ Medicamentos: ₡35,000 (Exento) ║n";
echo "╠═══════════════════════════════════════════════╣n";
echo "║ Subtotal: ₡290,000 ║n";
echo "║ IVA Devuelto Total: ₡10,200 ║n";
echo "║ TOTAL A PAGAR: ₡290,000 ║n";
echo "║ Medio de Pago: TARJETA (requisito) ║n";
echo "╚═══════════════════════════════════════════════╝n";
echo "nNota: El IVA devuelto aplica únicamente a serviciosn";
echo "médicos privados con tarifa del 4% pagados con tarjeta.n";
} else {
echo "n✗ ERROR EN EL TIMBRAJEn";
}
?>
05TETiquete electronico simple para consumidor final
<?php
// Para que se vea en el navegador formateado el texto
header("Content-Type: text/plain; charset=UTF-8");
/**
* Ejemplo 5: Tiquete Electrónico Simple
* FACTURATica.com API
* Para ventas a cliente general sin datos del receptor
*/
$api_url = 'https://SU-DOMINIO-PANEL/_api.php';
$data = [
'ACTION' => 'TIMBRAR_TIQUETE',
'CORREO' => 'correo@licencia.com',
'API_KEY' => '8YQ...',
'IDENTIFICACION' => '101110111',
];
/********************************************************************************
* BLOQUE DE PRUEBAS *
* Este bloque se utiliza para cargar datos de prueba durante el desarrollo. *
* Puede eliminarse sin problema alguno *
********************************************************************************/
if (file_exists('datos_prueba.php')) {
require_once 'datos_prueba.php';
}
/********************************************************************************
* FIN DEL BLOQUE DE PRUEBAS *
********************************************************************************/
// Construir línea simple para tiquete
$lineas = [
[
"NumeroLinea" => "1",
"Cantidad" => "1",
"UnidadMedida" => "Unid",
"Detalle" => "Venta de productos varios",
"PrecioUnitario" => "10000.00",
"MontoTotal" => "10000.00",
"SubTotal" => "10000.00",
"Tarifa" => "13",
"Monto" => "1300.00",
"MontoTotalLinea" => "11300.00"
]
];
$data += [
// Líneas de detalle
'LINEAS' => json_encode($lineas),
// Totales
'SUBTOTAL' => 10000.00,
'IV' => 1300.00,
'TOTALIVI' => 11300.00,
];
// Ejecutar petición
$ch = curl_init($api_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Mostrar respuesta
echo "==============================================n";
echo "EJEMPLO 5: Tiquete Electrónico Simplen";
echo "==============================================n";
echo "HTTP Code: " . $http_code . "n";
echo "Respuesta: " . $response . "n";
// Si la respuesta es una clave de 50 caracteres, fue exitoso
if (strlen($response) == 50) {
echo "n✓ TIQUETE TIMBRADO EXITOSAMENTEn";
echo "Clave: " . $response . "n";
echo "nCaracterísticas del tiquete:n";
echo "- Cliente: General (sin datos)n";
echo "- Pago: Efectivon";
echo "- Total: ₡11,300n";
echo "- Formato: Pequeño (tiquete)n";
} else {
echo "n✗ ERROR EN EL TIMBRAJEn";
}
?>
06NCNota de Credito por anulacion total de factura
<?php
// Para que se vea en el navegador formateado el texto
header("Content-Type: text/plain; charset=UTF-8");
/**
* Ejemplo 9: Nota de Crédito Electrónica - Anulación Total
* FACTURATica.com API
*
* Anula completamente una factura previamente emitida
*/
$api_url = 'https://SU-DOMINIO-PANEL/_api.php';
// IMPORTANTE: Reemplaza esta clave con una clave real de un documento
// que haya timbrado previamente y que desee afectar
$clave_documento = '506...';
$data = [
'ACTION' => 'TIMBRAR_CREDITO',
'CORREO' => 'correo@licencia.com',
'API_KEY' => '8YQ...',
'IDENTIFICACION' => '101110111',
// Datos del receptor (mismo de la factura original)
'RECEPTOR_NUMERO' => '3101360759',
// Condiciones comerciales
'CONDICIONVENTA' => '01', // Contado
'MEDIOPAGO' => '04', // Transferencia
'CODIGOMONEDA' => 'CRC',
];
/********************************************************************************
* BLOQUE DE PRUEBAS *
* Este bloque se utiliza para cargar datos de prueba durante el desarrollo. *
* Puede eliminarse sin problema alguno *
********************************************************************************/
if (file_exists('datos_prueba.php')) {
require_once 'datos_prueba.php';
}
/********************************************************************************
* FIN DEL BLOQUE DE PRUEBAS *
********************************************************************************/
// Construir líneas de detalle
$lineas = [
[
"NumeroLinea" => "1",
"Cantidad" => "10.00",
"UnidadMedida" => "Unid",
"Detalle" => "Producto gravado con IVA 13%",
"PrecioUnitario" => "5000.00",
"MontoTotal" => "50000.00",
"SubTotal" => "50000.00",
"Codigo" => "01",
"Tarifa" => "13",
"Monto" => "6500.00",
"MontoTotalLinea" => "56500.00"
]
];
// Añadimos líneas a los datos
$data +=[
// Líneas de detalle
'LINEAS' => json_encode($lineas),
// Totales (mismos de la factura original)
'SUBTOTAL' => 50000.00,
'IV' => 6500.00,
'TOTALIVI' => 56500.00,
// === INFORMACIÓN DE REFERENCIA (NOMBRES CORRECTOS) ===
'InformacionReferencia_TIPODOCREFERENCIA' => '01', // 01 = Factura Electrónica
'InformacionReferencia_Numero' => $clave_documento, // Clave de 50 dígitos
'InformacionReferencia_Fecha' => '01/10/2024', // Formato: dd/mm/yyyy
'InformacionReferencia_CODIGOREFERENCIA' => '01', // 01 = Anula Documento
'InformacionReferencia_Razon' => 'Anulación total de la factura por error en emisión'
];
// Ejecutar petición
$ch = curl_init($api_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Mostrar respuesta
echo "==============================================n";
echo "EJEMPLO 9: Nota de Créditon";
echo "==============================================n";
echo "HTTP Code: " . $http_code . "n";
echo "Respuesta: " . $response . "n";
// Si la respuesta es una clave de 50 caracteres, fue exitoso
if (strlen($response) == 50) {
echo "n✓ NOTA DE CRÉDITO TIMBRADA EXITOSAMENTEn";
echo "Clave NC: " . $response . "n";
echo "nCaracterísticas:n";
echo "- Referencia: Factura " . substr($data['InformacionReferencia_Numero'], -10) . "n";
echo "- Monto anulado: " . $data['TOTALIVI'] . "n";
} else {
echo "n✗ ERROR EN EL TIMBRAJEn";
}
07NDNota de Debito por cobro adicional
<?php
// Para que se vea en el navegador formateado el texto
header("Content-Type: text/plain; charset=UTF-8");
/**
* Ejemplo 10: Nota de Débito Electrónica - Corrección de Monto
* FACTURATica.com API
*
* Aumenta el monto de una factura previamente emitida
* (Por ejemplo, por cobro adicional o cargo olvidado)
*/
$api_url = 'https://SU-DOMINIO-PANEL/_api.php';
// IMPORTANTE: Reemplaza esta clave con una clave real de un documento
// que haya timbrado previamente y que desee afectar
$clave_documento = '506...';
$data = [
'ACTION' => 'TIMBRAR_DEBITO',
'CORREO' => 'correo@licencia.com',
'API_KEY' => '8YQ...',
'IDENTIFICACION' => '101110111',
// Datos del receptor (mismo de la factura original)
'RECEPTOR_NUMERO' => '3101360759',
// Condiciones comerciales
'CONDICIONVENTA' => '01', // Contado
'MEDIOPAGO' => '04', // Transferencia
'CODIGOMONEDA' => 'CRC',
];
/********************************************************************************
* BLOQUE DE PRUEBAS *
* Este bloque se utiliza para cargar datos de prueba durante el desarrollo. *
* Puede eliminarse sin problema alguno *
********************************************************************************/
if (file_exists('datos_prueba.php')) {
require_once 'datos_prueba.php';
}
/********************************************************************************
* FIN DEL BLOQUE DE PRUEBAS *
********************************************************************************/
// Construir líneas de detalle con el MONTO ADICIONAL a cobrar
$lineas = [
[
"NumeroLinea" => "1",
"Cantidad" => "1.00",
"UnidadMedida" => "Sp",
"Detalle" => "Cargo adicional por servicio de entrega urgente",
"PrecioUnitario" => "15000.00",
"MontoTotal" => "15000.00",
"SubTotal" => "15000.00",
"Codigo" => "01",
"Tarifa" => "13",
"Monto" => "1950.00",
"MontoTotalLinea" => "16950.00"
]
];
// Añadimos líneas a los datos
$data +=[
// Líneas de detalle
'LINEAS' => json_encode($lineas),
// Totales (solo del monto adicional a cobrar)
'SUBTOTAL' => 15000.00,
'IV' => 1950.00,
'TOTALIVI' => 16950.00,
// === INFORMACIÓN DE REFERENCIA (NOMBRES CORRECTOS) ===
'InformacionReferencia_TIPODOCREFERENCIA' => '01', // 01 = Factura Electrónica
'InformacionReferencia_Numero' => $clave_documento, // Clave de 50 dígitos
'InformacionReferencia_Fecha' => '01/10/2024', // Formato: dd/mm/yyyy
'InformacionReferencia_CODIGOREFERENCIA' => '01', // 01 = Anula Documento
'InformacionReferencia_Razon' => 'Anulación total de la factura por error en emisión'
];
// Ejecutar petición
$ch = curl_init($api_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Mostrar respuesta
echo "==============================================n";
echo "EJEMPLO 10: Nota de Débito - Corrección Monton";
echo "==============================================n";
echo "HTTP Code: " . $http_code . "n";
echo "Respuesta: " . $response . "n";
// Si la respuesta es una clave de 50 caracteres, fue exitoso
if (strlen($response) == 50) {
echo "n✓ NOTA DE DÉBITO TIMBRADA EXITOSAMENTEn";
echo "Clave ND: " . $response . "n";
echo "nCaracterísticas:n";
echo "- Tipo: Corrección de monto (incremento)n";
echo "- Referencia: Factura " . substr($data['InformacionReferencia_Numero'], -10) . "n";
echo "- Monto adicional: " . $data['TOTALIVI'] . "n";
} else {
echo "n✗ ERROR EN EL TIMBRAJEn";
}
08FECCompra a proveedor no domiciliado (Airbnb)
<?php
// Para que se vea en el navegador formateado el texto
header("Content-Type: text/plain; charset=UTF-8");
/**
* Ejemplo 11: Factura Electrónica de Compra (FEC) - CASO AIRBNB
* FACTURATica.com API
*
* ┌─────────────────────────────────────────────────────────────────────────┐
* │ ¿Qué es este caso? │
* ├─────────────────────────────────────────────────────────────────────────┤
* │ Airbnb cobra comisiones a sus anfitriones costarricenses. Aunque │
* │ Airbnb opera bajo la cédula jurídica 3-130-195480 (Costa Rica), para │
* │ efectos tributarios califica como "Proveedor No Domiciliado", por lo │
* │ que la Información de Referencia debe usar: │
* │ - TipoDocIR = 16 (Comprobante de Proveedor No Domiciliado) │
* │ - Codigo = 11 (Proveedor No Domiciliado) │
* └─────────────────────────────────────────────────────────────────────────┘
*
* En FEC, los campos RECEPTOR_* contienen los datos del PROVEEDOR (Airbnb).
* El sistema intercambia Emisor/Receptor al generar el XML: la licencia
* (el anfitrión costarricense) queda como Receptor, y Airbnb como Emisor.
*
* La Información de Referencia es OBLIGATORIA en FEC.
*/
$api_url = 'https://SU-DOMINIO-PANEL/_api.php';
$data = [
'ACTION' => 'TIMBRAR_COMPRA',
'CORREO' => 'correo@licencia.com',
'API_KEY' => '8YQ...',
'IDENTIFICACION' => '101110111', // Anfitrión (licencia compradora)
];
/********************************************************************************
* BLOQUE DE PRUEBAS *
* Este bloque se utiliza para cargar datos de prueba durante el desarrollo. *
* Puede eliminarse sin problema alguno *
********************************************************************************/
if (file_exists('datos_prueba.php')) {
require_once 'datos_prueba.php';
}
/********************************************************************************
* FIN DEL BLOQUE DE PRUEBAS *
********************************************************************************/
// Línea de detalle: comisión cobrada por Airbnb en una reservación
$lineas = [
[
"NumeroLinea" => "1",
"Cantidad" => "1.00",
"UnidadMedida" => "Sp", // Sp = Servicios Profesionales
"Detalle" => "Comisión de servicio Airbnb - Reservación HMXY1234",
"PrecioUnitario" => "15000.00",
"MontoTotal" => "15000.00",
"SubTotal" => "15000.00",
"Codigo" => "01",
"Tarifa" => "13",
"Monto" => "1950.00",
"MontoTotalLinea" => "16950.00"
]
];
$data += [
// =========================================================================
// DATOS DEL PROVEEDOR: AIRBNB (viajan como RECEPTOR_* y se intercambian
// automáticamente a Emisor al construir el XML de la FEC)
// =========================================================================
'RECEPTOR_NOMBRE' => 'Airbnb Payments, Inc.',
'RECEPTOR_NUMERO' => '3130195480', // Cédula jurídica reconocida de Airbnb en CR
'RECEPTOR_CORREOELECTRONICO' => 'payments@airbnb.com',
'RECEPTOR_NUMTELEFONO' => '00000000',
// Líneas de detalle
'LINEAS' => json_encode($lineas),
// Totales
'SUBTOTAL' => 15000.00,
'TOTALEXENTO' => 0.00,
'TOTALMERCANCIASGRAVADAS' => 15000.00,
'TOTALDESCUENTOS' => 0.00,
'IV' => 1950.00,
'TOTALIVI' => 16950.00,
// Condiciones comerciales
'CONDICIONVENTA' => '01', // Contado
'MEDIOPAGO' => '04', // Transferencia
'CODIGOMONEDA' => 'CRC',
// =========================================================================
// INFORMACIÓN DE REFERENCIA (OBLIGATORIA para FEC)
// Caso Airbnb: Proveedor No Domiciliado
// =========================================================================
'InformacionReferencia_TIPODOCREFERENCIA' => '16', // Comprobante de Proveedor No Domiciliado
'InformacionReferencia_CODIGOREFERENCIA' => '11', // Proveedor No Domiciliado
'InformacionReferencia_Numero' => 'HMXY1234-RECEIPT', // Número del recibo/invoice de Airbnb
'InformacionReferencia_Fecha' => date('d/m/Y'), // Formato d/m/Y
'InformacionReferencia_Razon' => 'Comisión por servicios de Airbnb',
];
// Ejecutar petición
$ch = curl_init($api_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Mostrar respuesta
echo "==============================================n";
echo "EJEMPLO 11: FEC - Airbnb (Proveedor No Domiciliado)n";
echo "==============================================n";
echo "HTTP Code: " . $http_code . "n";
echo "Respuesta: " . $response . "n";
// Si la respuesta es una clave de 50 caracteres, fue exitoso
if (strlen($response) == 50) {
echo "n✓ FEC TIMBRADA EXITOSAMENTEn";
echo "Clave: " . $response . "n";
} else {
echo "n✗ ERROR EN EL TIMBRAJEn";
}
?>
09FECCompra a proveedor extranjero (AWS)
<?php
// Para que se vea en el navegador formateado el texto
header("Content-Type: text/plain; charset=UTF-8");
/**
* Ejemplo 12: Factura Electrónica de Compra (FEC) - CASO PROVEEDOR EXTRANJERO
* FACTURATica.com API
*
* ┌─────────────────────────────────────────────────────────────────────────┐
* │ ¿Qué es este caso? │
* ├─────────────────────────────────────────────────────────────────────────┤
* │ Compra de servicios digitales a un proveedor no domiciliado en Costa │
* │ Rica (ej: Amazon Web Services, Google Cloud, Microsoft Azure, OpenAI, │
* │ Anthropic, etc.). El proveedor NO tiene cédula costarricense, por lo │
* │ que su identificación contiene letras o supera los 12 caracteres. │
* │ │
* │ El sistema detecta automáticamente proveedor extranjero por la │
* │ presencia de letras en RECEPTOR_NUMERO (o longitud > 12) y: │
* │ - Asigna TipoIdentificacion = 05 (Extranjero) │
* │ - Usa RECEPTOR_OTRASSENAS_EXT como dirección extranjera del Emisor │
* │ - Omite la Ubicación nacional (Provincia/Cantón/Distrito) │
* │ │
* │ La Información de Referencia debe usar: │
* │ - TipoDocIR = 16 (Comprobante de Proveedor No Domiciliado) │
* │ - Codigo = 11 (Proveedor No Domiciliado) │
* └─────────────────────────────────────────────────────────────────────────┘
*
* En FEC, los campos RECEPTOR_* contienen los datos del PROVEEDOR (AWS).
* Al construir el XML el sistema intercambia Emisor/Receptor: la licencia
* costarricense queda como Receptor y AWS como Emisor extranjero.
*
* La Información de Referencia es OBLIGATORIA en FEC.
*/
$api_url = 'https://SU-DOMINIO-PANEL/_api.php';
$data = [
'ACTION' => 'TIMBRAR_COMPRA',
'CORREO' => 'correo@licencia.com',
'API_KEY' => '8YQ...',
'IDENTIFICACION' => '101110111', // Empresa costarricense (licencia compradora)
];
/********************************************************************************
* BLOQUE DE PRUEBAS *
* Este bloque se utiliza para cargar datos de prueba durante el desarrollo. *
* Puede eliminarse sin problema alguno *
********************************************************************************/
if (file_exists('datos_prueba.php')) {
require_once 'datos_prueba.php';
}
/********************************************************************************
* FIN DEL BLOQUE DE PRUEBAS *
********************************************************************************/
// Línea de detalle: servicios de AWS (convertidos a CRC en este ejemplo)
$lineas = [
[
"NumeroLinea" => "1",
"Cantidad" => "1.00",
"UnidadMedida" => "Sp", // Sp = Servicios Profesionales
"Detalle" => "Amazon Web Services - EC2, S3 y CloudFront (Invoice INV-2026-04-001)",
"PrecioUnitario" => "250000.00",
"MontoTotal" => "250000.00",
"SubTotal" => "250000.00",
"Codigo" => "01",
"Tarifa" => "13",
"Monto" => "32500.00",
"MontoTotalLinea" => "282500.00"
]
];
$data += [
// =========================================================================
// DATOS DEL PROVEEDOR EXTRANJERO: AWS (viajan como RECEPTOR_* y se
// intercambian automáticamente a Emisor al construir el XML de la FEC).
// El sistema detecta extranjero por las letras en RECEPTOR_NUMERO.
// =========================================================================
'RECEPTOR_NOMBRE' => 'Amazon Web Services EMEA SARL',
'RECEPTOR_NUMERO' => 'LU26375245', // VAT europeo (contiene letras)
'RECEPTOR_CORREOELECTRONICO' => 'aws-receivables@amazon.com',
'RECEPTOR_NUMTELEFONO' => '00000000',
// Dirección extranjera del proveedor (se coloca en <Emisor><OtrasSenasExtranjero>)
'RECEPTOR_OTRASSENAS_EXT' => '38 Avenue John F. Kennedy, L-1855 Luxembourg',
// Líneas de detalle
'LINEAS' => json_encode($lineas),
// Totales
'SUBTOTAL' => 250000.00,
'TOTALEXENTO' => 0.00,
'TOTALMERCANCIASGRAVADAS' => 250000.00,
'TOTALDESCUENTOS' => 0.00,
'IV' => 32500.00,
'TOTALIVI' => 282500.00,
// Condiciones comerciales
'CONDICIONVENTA' => '01', // Contado
'MEDIOPAGO' => '04', // Transferencia
'CODIGOMONEDA' => 'CRC', // Si la factura real está en USD, convierta previamente
// =========================================================================
// INFORMACIÓN DE REFERENCIA (OBLIGATORIA para FEC)
// Caso proveedor extranjero: Comprobante de Proveedor No Domiciliado
// =========================================================================
'InformacionReferencia_TIPODOCREFERENCIA' => '16', // Comprobante de Proveedor No Domiciliado
'InformacionReferencia_CODIGOREFERENCIA' => '11', // Proveedor No Domiciliado
'InformacionReferencia_Numero' => 'INV-2026-04-001', // Invoice number del proveedor
'InformacionReferencia_Fecha' => date('d/m/Y'), // Formato d/m/Y
'InformacionReferencia_Razon' => 'Servicios digitales - Proveedor no domiciliado',
];
// Ejecutar petición
$ch = curl_init($api_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Mostrar respuesta
echo "==============================================n";
echo "EJEMPLO 12: FEC - AWS (Proveedor Extranjero)n";
echo "==============================================n";
echo "HTTP Code: " . $http_code . "n";
echo "Respuesta: " . $response . "n";
// Si la respuesta es una clave de 50 caracteres, fue exitoso
if (strlen($response) == 50) {
echo "n✓ FEC TIMBRADA EXITOSAMENTEn";
echo "Clave: " . $response . "n";
} else {
echo "n✗ ERROR EN EL TIMBRAJEn";
}
?>
10FEEFactura de Exportacion en USD a cliente extranjero
<?php
// Para que se vea en el navegador formateado el texto
header("Content-Type: text/plain; charset=UTF-8");
/**
* Ejemplo 13: Factura Electrónica de Exportación (FEE)
* FACTURATica.com API
*
* ┌─────────────────────────────────────────────────────────────────────────┐
* │ ¿Qué es este caso? │
* ├─────────────────────────────────────────────────────────────────────────┤
* │ Venta a un cliente extranjero (fuera de Costa Rica). Las exportaciones │
* │ son operaciones EXENTAS de IVA, normalmente facturadas en USD u otra │
* │ moneda extranjera. │
* │ │
* │ Características distintivas: │
* │ - ACTION = TIMBRAR_FACTURA_EXPORTACION │
* │ - CONDICIONVENTA = 01 contado (Hacienda v4.4 ya NO acepta el código '12')│
* │ - IV = 0 (sin IVA, exportación exenta) │
* │ - Tarifa de cada línea = 0 │
* │ - CODIGOMONEDA = USD (típico) + TIPO_DE_CAMBIO │
* │ - RECEPTOR_NUMERO contiene letras → identificación tipo 05 │
* │ - RECEPTOR_OTRASSENAS_EXT con la dirección extranjera │
* └─────────────────────────────────────────────────────────────────────────┘
*/
$api_url = 'https://SU-DOMINIO-PANEL/_api.php';
$data = [
'ACTION' => 'TIMBRAR_FACTURA_EXPORTACION',
'CORREO' => 'correo@licencia.com',
'API_KEY' => '8YQ...',
'IDENTIFICACION' => '101110111',
];
/********************************************************************************
* BLOQUE DE PRUEBAS *
* Este bloque se utiliza para cargar datos de prueba durante el desarrollo. *
* Puede eliminarse sin problema alguno *
********************************************************************************/
if (file_exists('datos_prueba.php')) {
require_once 'datos_prueba.php';
}
/********************************************************************************
* FIN DEL BLOQUE DE PRUEBAS *
********************************************************************************/
// Línea de detalle: servicio de consultoría exportado a cliente en Estados Unidos
// Las exportaciones llevan tarifa 0 (exentas de IVA).
$lineas = [
[
"NumeroLinea" => "1",
"Cantidad" => "1.00",
"UnidadMedida" => "Sp", // Servicios Profesionales
"Detalle" => "Consultoría tecnológica - Marzo 2026",
"PrecioUnitario" => "1500.00", // En USD
"MontoTotal" => "1500.00",
"SubTotal" => "1500.00",
"Codigo" => "01",
"Tarifa" => "0", // Exportación: exenta de IVA
"Monto" => "0.00",
"MontoTotalLinea" => "1500.00"
],
[
"NumeroLinea" => "2",
"Cantidad" => "10.00",
"UnidadMedida" => "h", // Horas
"Detalle" => "Soporte técnico remoto",
"PrecioUnitario" => "75.00",
"MontoTotal" => "750.00",
"SubTotal" => "750.00",
"Codigo" => "01",
"Tarifa" => "0",
"Monto" => "0.00",
"MontoTotalLinea" => "750.00"
]
];
$data += [
// =========================================================================
// DATOS DEL RECEPTOR EXTRANJERO
// El sistema detecta receptor extranjero por las letras en RECEPTOR_NUMERO
// y le asigna tipoIdentificacion = 05.
// =========================================================================
'RECEPTOR_NOMBRE' => 'Acme Corporation Inc.',
'RECEPTOR_NUMERO' => 'EIN-841234567', // Tax ID estadounidense (con letras)
'RECEPTOR_CORREOELECTRONICO' => 'accounts-payable@acme.com',
'RECEPTOR_NUMTELEFONO' => '00000000',
// Dirección extranjera del cliente (se coloca en <Receptor><OtrasSenasExtranjero>)
'RECEPTOR_OTRASSENAS_EXT' => '350 Fifth Avenue, New York, NY 10118, USA',
// Líneas de detalle
'LINEAS' => json_encode($lineas),
// Totales (sin IVA — exportación)
'SUBTOTAL' => 2250.00,
'IV' => 0.00,
'TOTALIVI' => 2250.00,
// Condiciones comerciales
'CONDICIONVENTA' => '01', // Contado (Hacienda v4.4 ya no acepta '12')
'MEDIOPAGO' => '04', // Transferencia internacional
'CODIGOMONEDA' => 'USD', // Dólar estadounidense
'TIPO_DE_CAMBIO' => '520.00', // CRC por USD (referencial - el sistema toma del día si se omite)
'OBSERVACIONES' => 'Servicios profesionales prestados desde Costa Rica al exterior',
];
// Ejecutar petición
$ch = curl_init($api_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Mostrar respuesta
echo "==============================================n";
echo "EJEMPLO 13: FEE - Factura de Exportación (USD)n";
echo "==============================================n";
echo "HTTP Code: " . $http_code . "n";
echo "Respuesta: " . $response . "n";
// Si la respuesta es una clave de 50 caracteres, fue exitoso
if (strlen($response) == 50) {
echo "n✓ FACTURA DE EXPORTACIÓN TIMBRADA EXITOSAMENTEn";
echo "Clave: " . $response . "n";
echo "nCaracterísticas:n";
echo "- Receptor: cliente extranjero (USA)n";
echo "- Moneda: USDn";
echo "- IVA: 0 (exportación exenta)n";
echo "- Subtotal USD: $" . number_format($data['SUBTOTAL'], 2) . "n";
} else {
echo "n✗ ERROR EN EL TIMBRAJEn";
}
?>
11ANULARAnulacion total de un documento previamente aceptado
<?php
// Para que se vea en el navegador formateado el texto
header("Content-Type: text/plain; charset=UTF-8");
/**
* Ejemplo 6: Anulación de Documento
* FACTURATica.com API
*
* IMPORTANTE: Para usar este ejemplo, primero debes tener una clave
* de un documento previamente timbrado que desees anular.
*/
$api_url = 'https://SU-DOMINIO-PANEL/_api.php';
// IMPORTANTE: Reemplaza esta clave con una clave real de un documento
// que hayas timbrado previamente y que desees anular
$clave_documento = '506...';
$data = [
'ACTION' => 'ANULAR',
'CORREO' => 'correo@licencia.com',
'API_KEY' => '8YQ...',
'IDENTIFICACION' => '101110111',
];
/********************************************************************************
* BLOQUE DE PRUEBAS *
* Este bloque se utiliza para cargar datos de prueba durante el desarrollo. *
* Puede eliminarse sin problema alguno *
********************************************************************************/
if (file_exists('datos_prueba.php')) {
require_once 'datos_prueba.php';
}
/********************************************************************************
* FIN DEL BLOQUE DE PRUEBAS *
********************************************************************************/
// Datos para la anulación
$data +=[
'CLAVENUMERICA' => $clave_documento,
'PORCENTAJE_ANULACION' => 100 // Parámetro opcional
];
echo "==============================================n";
echo "EJEMPLO 6: Anulación de Documenton";
echo "==============================================n";
echo "NOTA: Para probar este ejemplo, necesitas una claven";
echo "de un documento previamente timbrado y ACEPTADO.n";
echo "----------------------------------------------n";
// Validar longitud de la clave
if (strlen($clave_documento) == 50) {
$clave_documento = $clave_documento;
} else {
echo "Error: La clave debe tener exactamente 50 caracteres.n";
echo "Longitud ingresada: " . strlen($clave_documento) . " caracteres.n";
exit;
}
echo "nAnulando documento con clave:n" . $clave_documento . "nn";
// Ejecutar petición
$ch = curl_init($api_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Mostrar respuesta
echo "HTTP Code: " . $http_code . "n";
echo "Respuesta: " . $response . "nn";
// Interpretar respuesta
if (strlen($response) == 50) {
echo "✓ DOCUMENTO ANULADO EXITOSAMENTEn";
echo "Clave de la nota de crédito: " . $response . "n";
} else {
echo "✗ ERROR EN LA ANULACIÓNn";
// Interpretar códigos de error comunes
switch ($response) {
case '-1':
echo "Error: Parámetros faltantes o incorrectosn";
break;
case '-2':
echo "Error: Fallo de conexión con la base de datosn";
break;
case '0':
echo "Error: Credenciales rechazadasn";
break;
default:
echo "Código de error: " . $response . "n";
}
}
echo "n==============================================n";
echo "INSTRUCCIONES PARA PROBAR LA ANULACIÓN:n";
echo "==============================================n";
echo "1. Primero ejecuta uno de los ejemplos 1-5 para timbrar un documenton";
echo "2. Copia la clave de 50 caracteres que se generan";
echo "3. Ejecuta este script e ingresa esa clave cuando se soliciten";
echo "4. El documento será anulado en el sisteman";
12NOMBREConsultar razon social por cedula en padron de Hacienda
<?php
// Para que se vea en el navegador formateado el texto
header("Content-Type: text/plain; charset=UTF-8");
/**
* Ejemplo 7: Obtener nombre por identificación
* FACTURATica.com API
*
* IMPORTANTE: Solo se admiten cédulas físicas, jurídicas, dimex y nites de 9-12 digitos.
*/
$api_url = 'https://SU-DOMINIO-PANEL/_api.php';
// IMPORTANTE: Reemplaza este número por la que desee utilizar
$numero = '3101360759';
echo "=============================================================n";
echo "EJEMPLO 7: Obtener nombre por identificaciónn";
echo "=============================================================n";
echo "NOTA: Para probar este ejemplo, necesita un númeron";
echo "de identificación nacional, dimex o nite de 9-12 digitos.n";
echo "-------------------------------------------------------------n";
$data = [
'ACTION' => 'NOMBRE',
'CORREO' => 'correo@licencia.com',
'API_KEY' => '8YQ...',
'IDENTIFICACION' => '101110111',
];
/********************************************************************************
* BLOQUE DE PRUEBAS *
* Este bloque se utiliza para cargar datos de prueba durante el desarrollo. *
* Puede eliminarse sin problema alguno *
********************************************************************************/
if (file_exists('datos_prueba.php')) {
require_once 'datos_prueba.php';
}
/********************************************************************************
* FIN DEL BLOQUE DE PRUEBAS *
********************************************************************************/
$data += [
'NUMERO' => $numero
];
echo "nObteniendo nombre para la identificación número:n" . $numero . "nn";
// Ejecutar petición
$ch = curl_init($api_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$response_raw = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Mostrar respuesta
echo "HTTP Code: " . $http_code . "n";
echo "Respuesta: " . $response_raw . "nn";
// Interpretar respuesta
$response = json_decode($response_raw, true);
if (isset($response['success']) && $response['success'] === true) {
echo "✓ NOMBRE OBTENIDO EXITOSAMENTEnn";
echo "Número consultado: " . $response['numero'] . "n";
echo "Nombre: " . $response['nombre'] . "n";
} else {
echo "✗ ERROR EN LA OBTENCIÓN DEL NOMBREnn";
print_r($response_raw);
}
13ESTADOConsultar estado del documento + descargar XML / PDF
<?php
// Para que se vea en el navegador formateado el texto
header("Content-Type: text/plain; charset=UTF-8");
/**
* Ejemplo 8: Consultar Estado de Documento
* FACTURATica.com API
*
* IMPORTANTE: Para usar este ejemplo, necesitas una clave de 50 caracteres
* de un documento previamente timbrado.
*/
$api_url = 'https://SU-DOMINIO-PANEL/_api.php';
// IMPORTANTE: Reemplaza esta clave con una clave real de un documento
// que hayas timbrado previamente y del cual desees conocer el estado
$clave_documento = '506...';
echo "==============================================n";
echo "EJEMPLO 8: Consultar Estado de Documenton";
echo "==============================================n";
echo "Este ejemplo muestra cómo consultar el estadon";
echo "de un documento y obtener sus archivos.n";
echo "----------------------------------------------nn";
// Ejemplo 1: Solo consultar estado (sin archivos)
echo "═══════════════════════════════════════════════n";
echo "CONSULTA 1: Solo Estado (sin archivos)n";
echo "═══════════════════════════════════════════════n";
$data = [
'ACTION' => 'ESTADO',
'CORREO' => 'correo@licencia.com',
'API_KEY' => '8YQ...',
'IDENTIFICACION' => '101110111',
];
/********************************************************************************
* BLOQUE DE PRUEBAS *
* Este bloque se utiliza para cargar datos de prueba durante el desarrollo. *
* Puede eliminarse sin problema alguno *
********************************************************************************/
if (file_exists('datos_prueba.php')) {
require_once 'datos_prueba.php';
}
/********************************************************************************
* FIN DEL BLOQUE DE PRUEBAS *
********************************************************************************/
// Validar longitud de la clave
if (strlen($clave_documento) != 50) {
echo "⚠ ADVERTENCIA: La clave debe tener exactamente 50 caracteres.n";
echo "Longitud actual: " . strlen($clave_documento) . " caracteres.n";
echo "Por favor, verifica la clave del documento.n";
exit;
}
$data += [
'CLAVENUMERICA' => $clave_documento,
'ADJUNTOS' => 0 // 0 = Solo estado
];
$ch = curl_init($api_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$response_raw = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo "HTTP Code: " . $http_code . "n";
echo "Respuesta: " . $response_raw . "n";
$response = json_decode($response_raw, true);
if ($response && isset($response['ind-estado'])) {
echo "n✓ Estado del documento: " . strtoupper($response['ind-estado']) . "n";
if (isset($response['respuesta-xml'])) {
echo "Mensaje: " . $response['respuesta-xml'] . "n";
}
}
// Ejemplo 2: Estado + XML Firmado
echo "n═══════════════════════════════════════════════n";
echo "CONSULTA 2: Estado + XML Firmadon";
echo "═══════════════════════════════════════════════n";
$data['ADJUNTOS'] = 1; // 1 = Estado + XML
$ch = curl_init($api_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$response_raw = curl_exec($ch);
curl_close($ch);
$response = json_decode($response_raw, true);
if ($response && isset($response['FIRMADO'])) {
echo "✓ XML Firmado incluido (Base64): ";
echo substr($response['FIRMADO'], 0, 50) . "...n";
echo "Longitud del XML en Base64: " . strlen($response['FIRMADO']) . " caracteresn";
// Opcional: Guardar el XML decodificado
// file_put_contents('documento.xml', base64_decode($response['FIRMADO']));
}
// Ejemplo 3: Estado + XML + Respuesta de Hacienda
echo "n═══════════════════════════════════════════════n";
echo "CONSULTA 3: Estado + XML + Respuesta Haciendan";
echo "═══════════════════════════════════════════════n";
$data['ADJUNTOS'] = 2; // 2 = Estado + XML + Respuesta
$ch = curl_init($api_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$response_raw = curl_exec($ch);
curl_close($ch);
$response = json_decode($response_raw, true);
if ($response) {
if (isset($response['FIRMADO'])) {
echo "✓ XML Firmado incluidon";
}
if (isset($response['RESPUESTA_XML'])) {
echo "✓ XML de Respuesta de Hacienda incluidon";
echo "Longitud respuesta Base64: " . strlen($response['RESPUESTA_XML']) . " caracteresn";
}
}
// Ejemplo 4: Estado + XML + PDF + Respuesta
echo "n═══════════════════════════════════════════════n";
echo "CONSULTA 4: Todos los archivos (XML+PDF+Respuesta)n";
echo "═══════════════════════════════════════════════n";
$data['ADJUNTOS'] = 3; // 3 = Todo
$ch = curl_init($api_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$response_raw = curl_exec($ch);
curl_close($ch);
$response = json_decode($response_raw, true);
if ($response) {
echo "nArchivos incluidos en la respuesta:n";
echo "-----------------------------------n";
if (isset($response['ind-estado'])) {
echo "✓ Estado: " . $response['ind-estado'] . "n";
}
if (isset($response['FIRMADO'])) {
echo "✓ XML Firmado (Base64)n";
// Para guardar: file_put_contents('doc.xml', base64_decode($response['FIRMADO']));
}
if (isset($response['PDF'])) {
echo "✓ PDF del documento (Base64)n";
// Para guardar: file_put_contents('doc.pdf', base64_decode($response['PDF']));
}
if (isset($response['RESPUESTA_XML'])) {
echo "✓ Respuesta de Hacienda (Base64)n";
// Para guardar: file_put_contents('respuesta.xml', base64_decode($response['RESPUESTA_XML']));
}
echo "n💡 TIP: Los archivos vienen codificados en Base64.n";
echo "Para guardarlos, usa base64_decode() antes de escribirlos.n";
} else {
echo "n✗ ERROR al consultar el estadon";
echo "Respuesta: " . $response_raw . "n";
}
echo "n═══════════════════════════════════════════════n";
echo "RESUMEN DE NIVELES DE RESPUESTAn";
echo "═══════════════════════════════════════════════n";
echo "ADJUNTOS = 0: Solo estado del documenton";
echo "ADJUNTOS = 1: Estado + XML firmadon";
echo "ADJUNTOS = 2: Estado + XML + Respuesta Haciendan";
echo "ADJUNTOS = 3: Estado + XML + PDF + Respuestan";
echo "nEstados posibles: aceptado, rechazado, procesandon";
echo "n═══════════════════════════════════════════════n";
echo "INSTRUCCIONES PARA PROBARn";
echo "═══════════════════════════════════════════════n";
echo "1. Ejecuta primero uno de los ejemplos 1-5 para timbrarn";
echo "2. Copia la clave de 50 caracteres generadan";
echo "3. Reemplaza la variable $clave_documento con esa claven";
echo "4. Ejecuta este script para ver el estadon";
echo "nNOTA: Los documentos nuevos pueden estar en estadon";
echo "'procesando' por unos minutos antes de ser aceptados.n";
Preguntas Frecuentes (FAQ)
Respuestas rapidas a las preguntas mas comunes de desarrolladores que se integran con el API. Click en cada pregunta para expandirla.
¿Que es el API de Factura Electronica de FACTURATica y para que sirve?
El API de Factura Electronica de FACTURATica es un servicio web (REST) que permite a su sistema emitir, consultar y anular factura electronica directamente con el Ministerio de Hacienda de Costa Rica, sin pasar manualmente por la plataforma. Es la herramienta principal de facturacion electronica API en Costa Rica para automatizar la emision de comprobantes en POS, ERP, CRM, tiendas en linea y cualquier aplicacion que necesite cumplir con la facturacion electronica fiscal de Hacienda Costa Rica.
¿Como conecto mi sistema con la facturacion electronica de Hacienda en Costa Rica?
Para integrar su sistema con la facturacion electronica de Hacienda Costa Rica via el API de Factura Electronica de FACTURATica, el proceso completo toma tres pasos:
- Activar una licencia ILIMITADO TODO anual en FACTURATica.
- Generar la
API_KEYy anotar el URL del API en su panel (Configuraciones → Otros → API). - Implementar peticiones POST a los endpoints del API para timbrar factura electronica (
TIMBRAR_FACTURA,TIMBRAR_TIQUETE,ESTADO, etc.) desde su lenguaje.
La integracion completa puede tomar pocas horas si tiene equipo tecnico, o puede contratar el servicio de integracion asistida de FACTURATica que conecta su sistema con el API de Hacienda Costa Rica en pocos dias.
¿Que requisitos tecnicos necesito para usar el API de Factura Electronica?
Solo tres requisitos basicos:
- Capacidad de hacer peticiones HTTPS POST con cuerpo
application/x-www-form-urlencoded. - Capacidad de parsear respuestas en formato string o JSON.
- Una licencia ILIMITADO TODO anual con API_KEY generada.
No necesita certificado digital propio (FACTURATica firma con el suyo) ni infraestructura especial.
¿En que lenguajes de programacion puedo integrar el API de FACTURATica?
En cualquiera capaz de hacer una peticion HTTP. Probado y documentado en PHP (con ejemplos en este manual), pero funciona identicamente desde Python, Node.js, Java, .NET (C#), Go, Ruby, Perl, Rust, Elixir o cualquier otro lenguaje moderno. El API es REST estandar, sin SDK propietario, asi que el patron es el mismo en todos los lenguajes.
¿Como obtengo mi API_KEY de FACTURATica?
Ingrese al panel de su licencia y siga la ruta Menu → Click sobre el Nombre → Configuraciones → Otros → API. Esa pantalla genera una API_KEY unica de 32 caracteres asociada a su licencia y muestra tambien el URL del API para su nodo. Guarde la API_KEY de forma segura: no la exponga en codigo del lado del cliente ni la suba a repositorios publicos.
¿Por que el API solo funciona con licencias ILIMITADO TODO anuales y no con PREPAGO o mensuales?
Por modelo de cobro. Las licencias PREPAGO se cobran por documento (consumo unitario): no son compatibles con un canal automatizado que puede emitir cientos al dia. Las mensuales tienen un alcance limitado pensado para uso manual. Solo las ILIMITADO TODO anuales son de pago anual fijo y permiten emision continua sin tope, modelo que se alinea con la naturaleza automatizada del API.
¿Cuanto cuesta usar el API de Factura Electronica de FACTURATica?
El API no tiene costo adicional: esta incluido en la licencia ILIMITADO TODO anual de FACTURATica. Una vez adquirida la licencia, no hay cobro por documento, por llamada al API ni por volumen procesado. Si requiere ayuda profesional para integrar, el servicio de integracion asistida tiene un monto unico de $500 (ver aqui).
¿Existe un servicio de integracion asistida si no tengo equipo tecnico?
Si. FACTURATica ofrece un servicio de integracion asistida con monto unico de $500 que incluye: soporte 1:1 via WhatsApp con el equipo tecnico, ajustes en el lado de FACTURATica para casos particulares, ayuda en la implementacion del API en su sistema y pruebas guiadas hasta lograr la primera factura electronica timbrada desde su software.
¿Puedo timbrar facturas electronicas en paralelo o en lote masivo?
No en paralelo. El API aplica una politica de uso secuencial: una solicitud despues de recibir la respuesta de la anterior. Solicitudes simultaneas o el bombardeo sin esperar respuestas activan automaticamente un limite de 1 solicitud por minuto. Para volumenes altos, implemente una cola interna en su sistema que despache secuencialmente; el throughput sostenido tipico permite procesar miles de documentos al dia sin friccion.
¿Cuanto tarda Hacienda en aceptar una factura electronica timbrada por el API?
En la practica, la mayoria de documentos se aceptan en menos de 5 minutos, y muchos en menos de 30 segundos.
Sin embargo, segun la documentacion oficial de Hacienda, el plazo maximo de respuesta en escenarios normales es de hasta 12 horas. Su sistema debe estar preparado para esa ventana, especialmente en periodos de alta carga (cierres fiscales, fin de mes).
El endpoint ESTADO devuelve cuatro valores posibles en ind-estado:
recibido— FACTURATica recibio el documento, esta por enviarlo a Hacienda. Estado tipicamente fugaz (segundos).procesando— enviado a Hacienda, esperando respuesta.aceptado— Hacienda lo valido. Estado final OK.rechazado— Hacienda lo rechazo. Estado final NO.
Reconsulte con polling de espera progresiva (por ejemplo: 30s, 2min, 10min, 1h) hasta obtener aceptado o rechazado. No bloquee la experiencia de su usuario esperando sincronicamente — procese el polling en background.
¿Que hago si el API responde “0” o “Credenciales rechazadas”?
Significa que las credenciales no son validas. Verifique tres cosas:
- El
CORREOcoincide exactamente con el registrado en la licencia. - La
IDENTIFICACIONes la del emisor (cedula/RUC del titular de la licencia, NO del receptor del documento). - La
API_KEYno fue regenerada ni expiro.
Si todo coincide, regenere su API_KEY desde el panel y vuelva a intentar. Si persiste, contacte soporte.
¿Como se si Hacienda realmente acepto mi documento? ¿La clave de 50 caracteres lo confirma?
ESTADO devuelve "ind-estado": "aceptado". Documente esto en su sistema interno: una clave generada NO es equivalente a una factura aceptada hasta que pase la validacion fiscal de Hacienda.¿Cual es la diferencia entre ANULAR y TIMBRAR_CREDITO en el API?
ANULAR es un atajo: genera automaticamente una nota de credito que anula el 100% (o porcentaje indicado) de un documento previamente aceptado por Hacienda, sin que usted especifique lineas, razones ni referencias. TIMBRAR_CREDITO es el endpoint completo de nota de credito: usted controla las lineas, montos, razon de la NC, tipo de documento referenciado y todo el detalle. Use ANULAR para anulaciones simples y totales; use TIMBRAR_CREDITO para anulaciones parciales con lineas distintas, correcciones de monto o descuentos posteriores.¿Como emito una factura electronica de exportacion (FEE) con el API?
Use el endpoint TIMBRAR_FACTURA_EXPORTACION. La factura electronica de exportacion (FEE) tiene tres caracteristicas distintivas:
- El IVA es siempre 0 (las exportaciones estan exentas).
- El receptor puede tener identificacion tipo 05 con letras permitidas.
- Hay un campo especial
RECEPTOR_OTRASSENAS_EXTpara la direccion completa fuera de Costa Rica.
La condicion de venta debe ser 01 (contado) o 02 (credito) y la moneda tipicamente USD. Atencion: el codigo 12 (operacion de exportacion) fue removido de la version 4.4 de Hacienda; usarlo causa rechazo del documento.
¿Como manejo las distintas tarifas de IVA (0%, 1%, 2%, 4%, 8%, 13%) en el API?
Cada linea del documento lleva un campo Tarifa con el porcentaje correspondiente. Las tarifas validas son: 0 (exento, canasta basica/medicinas), 1 y 2 (tarifas reducidas especiales), 4 (servicios medicos privados), 8 (tarifa reducida) y 13 (tarifa general). El campo Monto de la linea contiene el IVA calculado. Una sola factura puede mezclar lineas con distintas tarifas.
¿Como descargo el XML firmado y el PDF de un documento timbrado?
Use el endpoint ESTADO con el parametro ADJUNTOS en uno de cuatro niveles:
- 0 — devuelve solo el estado del documento.
- 1 — agrega el XML firmado en Base64.
- 2 — agrega tambien el PDF en Base64.
- 3 — agrega ademas la respuesta XML de Hacienda.
Para guardar a disco use base64_decode() antes de escribir, por ejemplo: file_put_contents("doc.xml", base64_decode($response["FIRMADO"])).
¿Como valido la cedula o numero de identificacion de un cliente con Hacienda?
Use el endpoint NOMBRE. Pasa el numero de identificacion a consultar en el parametro NUMERO y el API consulta la base de datos del Ministerio de Hacienda y devuelve el nombre o razon social asociada en formato JSON. Soporta cedulas fisicas, juridicas, DIMEX y NITE de 9 a 12 digitos. Util para auto-completar el campo de razon social al ingresar la cedula del cliente.
¿Que pasa si Hacienda rechaza mi factura electronica? ¿Como manejo el estado “rechazado” en el API?
Un rechazo de Hacienda es definitivo: el documento no tiene validez fiscal y no puede “reactivarse”. Debe corregir el problema y emitir un comprobante nuevo (con nueva clave numerica).
Razones mas comunes de rechazo:
- Codigo CABYS ausente, invalido o no autorizado para la actividad economica del emisor.
- Tarifa de IVA aplicada incorrectamente al producto/servicio segun su CABYS.
- Identificacion del receptor mal formada o no encontrada en el padron de Hacienda.
- Montos descuadrados (suma de
SubTotal≠SUBTOTAL, o suma deMontode IVA ≠IV). - Tipo de cambio incorrecto en facturas USD.
- Codigo de actividad economica no registrado en Hacienda para el emisor.
Que debe hacer su sistema cuando recibe "ind-estado": "rechazado":
- Llamar a
ESTADOconADJUNTOS=2o3para descargar el XML de respuesta de Hacienda — ahi viene el motivo exacto. - Marcar el documento como invalido en su BD; no contabilizar la venta como cumplida fiscalmente.
- Corregir el problema (ajustar CABYS, montos, identificacion, etc.).
- Emitir un comprobante nuevo con clave numerica nueva — no se permite “reenviar” el mismo.
- Notificar al usuario operador con el motivo legible (no el codigo crudo de Hacienda).
Documente cada rechazo en un log: las razones recurrentes apuntan a un bug en su integracion que conviene atacar de raiz.
¿Es seguro el API? ¿Como se protegen mis credenciales y datos fiscales?
Si. Toda la comunicacion va sobre HTTPS/SSL. La API_KEY es unica por licencia, regenerable desde el panel en cualquier momento (lo que invalida la anterior) y va en cada peticion como parametro de cuerpo (no en URL).
Buenas practicas de seguridad:
- Guardar la
API_KEYen variables de entorno o vault de secretos. - Nunca exponerla en codigo del lado del cliente (JavaScript del browser, apps moviles distribuidas).
- No commitearla a repositorios de codigo (ni publicos ni privados).
- Rotarla inmediatamente si sospecha que fue filtrada.
¿Como automatizo el envio de facturas electronicas desde mi POS, ERP o CRM existente?
Patron de integracion estandar (5 pasos):
- Capture el evento de venta o emision de factura en su POS/ERP/CRM.
- Arme los parametros del API (lineas, totales, datos del receptor) desde sus tablas internas.
- Haga POST a
TIMBRAR_FACTURA. - Guarde la clave de 50 caracteres en su BD junto al registro original (para trazabilidad y auditoria).
- Corra un job background con polling a
ESTADOhasta confirmar aceptacion.
Si hay rechazo, registre el error y notifique al usuario para correccion.
Buenas Practicas
Seis recomendaciones para que su integracion con el API sea robusta, segura y escalable en produccion.
Proteja su API_KEY
Guarde la API_KEY en variables de entorno o un vault de secretos. Nunca la exponga en codigo del lado del cliente (JavaScript del browser, apps moviles) ni la commitee a repositorios.
Verifique el plan
El API solo funciona con licencias ILIMITADO TODO anuales. Las licencias mensuales y PREPAGO no incluyen acceso. Si su licencia se degrada, el API deja de timbrar.
Reintentos con backoff
Para errores temporales (timeout, rate-limit, 5xx) implemente un sistema de reintentos con espera progresiva (ej: 5s, 15s, 60s, 5min). No reintente con el mismo cuerpo si ya recibio una clave de 50 caracteres.
Solicitudes secuenciales
Procese una solicitud a la vez. Solicitudes paralelas activan automaticamente un limite de 1 por minuto. Para volumen alto, implemente una cola interna que despache secuencialmente.
Polling al estado
Tras cada timbraje, polling al endpoint ESTADO hasta obtener aceptado o rechazado. La clave de 50 caracteres confirma envio, no aceptacion final por Hacienda.
Guarde la CLAVENUMERICA
Persista la CLAVENUMERICA de cada documento en su BD junto al registro original (factura interna, orden, ticket). Le permite auditoria, cross-reference y consulta posterior de XML/PDF.