Manual del agente
Este manual es para ti, agente de código (Claude Code, Cursor, Codex u otro). Trabajas para una persona que probablemente no programa: solo creó su cuenta en foliios y una clave de sandbox. Tu trabajo es llevar la integración de su proyecto hasta el verde sin más guía que este sitio.
Habla con la persona en lenguaje simple, sin jerga. Pregunta poco y una cosa a la vez. Haz tú todo lo que se pueda hacer en el proyecto; pídele a la persona solo lo que solo ella puede dar o hacer.
Reglas que valen en todas las fases
Sección titulada «Reglas que valen en todas las fases»- Nunca pidas la clave por el chat, ni la aceptes si la persona la pega, ni la imprimas. La clave (
sk_sandbox_...) la escribe la persona en el archivo.env; tú la lees desde ahí. No la muestres en comandos, logs, respuestas ni commits. Si aparece en el chat, avísale que la clave quedó expuesta y que la revoque y cree otra desde su cuenta. - Detente y consulta a la persona antes de seguir si: la clave no empieza por
sk_sandbox_; cualquier paso te acerca a producción o a la habilitación real ante la DIAN; un rechazo exige un dato fiscal que solo la persona tiene (un NIT real, una dirección, un régimen); o chocas con un límite del sandbox. No inventes datos fiscales. - Enlaza, no copies. Los límites, los escenarios, los campos, los errores y los eventos cambian con el código. Consúltalos siempre en la referencia generada y no los copies a tu código ni a tus respuestas como valores fijos:
- Todas las llamadas van a
https://api.foliios.com, conAuthorization: Bearer <clave>. Todo lo que emites en sandbox es simulado: no tiene efecto fiscal y no llega a la DIAN. - Si el proyecto ya tiene configurado el servidor MCP de foliios, úsalo: sus herramientas llaman a lo mismo que la API. Si no, usa HTTP.
Fase 1. Detectar el lenguaje y la forma del proyecto
Sección titulada «Fase 1. Detectar el lenguaje y la forma del proyecto»Haz: mira los archivos del proyecto (manifiestos, carpetas, scripts) y determina qué es: lenguaje, framework, si es una tienda, una planilla con scripts, un punto de venta, un servicio web o un script suelto, y dónde se genera una venta. Identifica cómo ejecuta pruebas y cómo guarda configuración.
Pregunta a la persona solo si no se deduce: «¿Este proyecto es el sistema donde registras tus ventas?».
Verifica: puedes decir en una frase qué hace el proyecto y en qué punto se produce una venta. Resúmeselo a la persona y confirma.
Si falla: si no encuentras dónde nace una venta, pregunta a la persona cómo registra hoy una venta y dónde.
Fase 2. Guardar la clave en .env, fuera del control de versiones
Sección titulada «Fase 2. Guardar la clave en .env, fuera del control de versiones»Haz:
- Comprueba que
.envestá fuera del control de versiones antes de usarla: que esté en.gitignorey quegit check-ignore .envlo confirme. Si no está, agrégalo a.gitignoreprimero. Si.envya fue commiteado alguna vez, detente y avisa a la persona. - Crea
.env.example(sin valores) con los nombres de las variables:FOLIIOS_API_KEY,FOLIIOS_COMPANY_ID,FOLIIOS_API_URL=https://api.foliios.com. - Pídele a la persona que abra
.envella misma y escriba la clave en la líneaFOLIIOS_API_KEY=, y que te diga solo «listo». No le pidas que te la dé ni que la pegue en el chat.
Pregunta a la persona: «Abre el archivo .env de tu proyecto y escribe tu clave de sandbox después de FOLIIOS_API_KEY=. No me la envíes por aquí. Dime “listo” cuando la hayas guardado. ¿Y cuál es el identificador de tu empresa de pruebas? Lo ves en el portal de foliios, en el ambiente Sandbox; empieza por cmp_».
Verifica: carga .env sin imprimirlo y pregunta si la clave existe y empieza por sk_sandbox_ (solo ese prefijo, nunca el valor completo). Comprueba la conexión con GET /v1/sandbox/scenarios (no pide clave) y luego una lectura con clave, por ejemplo GET /v1/companies/{company_id}/sandbox/integration-check: debe responder 200.
Si falla: 401 es una clave mal escrita o revocada; 403 sandbox_only es una clave que no es de sandbox, así que detente y consulta a la persona; 404 es un company_id equivocado.
Fase 3. Preguntarle lo mínimo a la persona
Sección titulada «Fase 3. Preguntarle lo mínimo a la persona»Haz estas preguntas en lenguaje simple y no más:
- ¿Qué sistema emite? ¿Una planilla, una tienda en línea, un programa de caja o un script? (Si no lo dedujiste en la fase 1.)
- ¿Vendes a consumidor final o a empresas? Con consumidor final no hace falta pedir datos del comprador: el documento va al consumidor final anónimo de la DIAN. Con empresas necesitas, como mínimo, su NIT (o cédula), su nombre y su correo. Consulta campos del documento para el comprador.
- ¿Cobras IVA? Qué porcentaje, o si vendes productos exentos o excluidos. El impuesto va en cada línea; revisa
lines[].taxesen los campos. - ¿De dónde salen las ventas? Un archivo, una base de datos, una pantalla, un botón. Es lo que vas a conectar.
- ¿Tienes una dirección pública para recibir avisos (webhooks)? Un servidor accesible desde internet con HTTPS. Si la persona no sabe qué es, la respuesta es no (ver fase 9).
Guarda las respuestas en el proyecto (un comentario o un archivo de notas), sin datos sensibles.
Fase 4. Primera factura
Sección titulada «Fase 4. Primera factura»Haz: escribe en el proyecto una función que arme una factura desde una venta y la emita con POST /v1/companies/{company_id}/documents. Detalles que debes respetar, todos en la API v1 y en los campos:
- Cabecera
Idempotency-Keyobligatoria (un identificador único por venta, estable entre reintentos). - Montos y cantidades como texto decimal (
"4000.00"), no como números JSON. resolution_ides obligatorio en una factura: tómalo delist_companies(MCP) o de lo que muestre el portal para la empresa de pruebas.- La respuesta es
202con el documento enpending. No es el resultado final: consulta el documento conGET /v1/companies/{company_id}/documents/{document_id}hasta que pase aaccepted.
Prueba primero con una venta de ejemplo, no con datos reales de la persona.
Verifica: el documento termina en accepted. Guarda su id, su number y su cufe (los necesitas en la fase 5).
Si falla: 422 trae en errors los campos que rompen una regla: corrige tú lo que sea de formato; si falta un dato que solo la persona tiene, pregúntaselo. Un rejected se trata en la fase 7.
Fase 5. Notas crédito y débito sobre esa factura
Sección titulada «Fase 5. Notas crédito y débito sobre esa factura»Haz: agrega al proyecto la emisión de una nota crédito (type: credit_note, por ejemplo una devolución parcial) y una nota débito (type: debit_note, por ejemplo un interés) sobre la factura aceptada de la fase 4. Cada nota lleva correction con concept, description y billing_reference (number, cufe y issue_date de esa factura, que salen de GET .../documents/{document_id}). Una nota no necesita resolution_id: se numera con su propia serie. Los conceptos válidos y las reglas están en campos (correction).
Verifica: una nota crédito y una nota débito terminan en accepted, con la referencia a esa factura.
Si falla: revisa que el número y el CUFE de la referencia sean exactamente los de la factura aceptada, y que la factura sea de la misma empresa. Una referencia a una factura de otra empresa no cuenta.
Fase 6. Idempotencia y reintentos
Sección titulada «Fase 6. Idempotencia y reintentos»Haz: haz que el proyecto reintente con seguridad. Si una emisión falla por red o responde 503, se reintenta con la misma Idempotency-Key y el mismo cuerpo: el resultado es el mismo documento (cabecera Idempotent-Replayed: true), no uno nuevo. Con la misma clave y otro cuerpo la respuesta es 409 idempotency_key_reused. Ante 429, espera y reintenta con pausa creciente; los límites vigentes están en escenarios, sección «Límites».
Verifica: emite dos veces la misma venta con la misma clave y comprueba que la segunda devuelve el mismo documento sin crear otro. Esta comprobación la declaras tú: la verificación final (fase 11) no puede comprobarla, así que repórtala a la persona como no verificada.
Si falla: si la segunda llamada crea otro documento, la clave no se está guardando entre intentos: debe salir de la venta (por ejemplo su número interno), no generarse de nuevo en cada intento.
Fase 7. Rechazos y reenvío
Sección titulada «Fase 7. Rechazos y reenvío»Haz: provoca un rechazo a propósito con un escenario del sandbox (cabecera Foliios-Sandbox-Scenario con un escenario de rechazo, por ejemplo uno de los rejected_*; el catálogo completo, con la regla que dispara cada uno, está en escenarios). Verifica que el proyecto detecta el estado rejected, muestra la regla que rechazó (dian_messages) y permite corregir y reenviar con POST .../documents/{document_id}/resubmit.
Verifica: un documento rejected se corrige y se reenvía, y termina en accepted. Esta comprobación también la declaras tú; repórtala como no verificada.
Si falla: si la regla que rechaza exige un dato fiscal real (un NIT, un dígito de verificación, un correo del emisor) que solo la persona tiene, detente y consúltale.
Fase 8. Contingencia (dian_unavailable)
Sección titulada «Fase 8. Contingencia (dian_unavailable)»Haz: emite un documento con el escenario dian_unavailable. La DIAN simulada «no responde», el documento pasa por contingencia y, pasados unos minutos, termina aceptado. Haz que el proyecto no trate la contingencia como un error: el documento sigue su curso y queda accepted solo. Consulta su estado hasta que lo esté. Los eventos asociados están en eventos de webhook.
Verifica: ese documento termina en accepted conservando la marca de que pasó por contingencia. Es lo que comprueba contingency en la verificación final.
Si falla: no lo reenvíes ni lo emitas de nuevo: espera. Si pasaron muchos minutos y sigue pending, revisa el estado con la API y consulta a la persona antes de insistir.
Fase 9. Webhooks, o consulta de estado
Sección titulada «Fase 9. Webhooks, o consulta de estado»Los webhooks son avisos que foliios envía a una dirección del proyecto cuando le pasa algo a un documento.
Haz: una de dos, según lo que respondió la persona en la fase 3.
- Si el proyecto puede recibirlos (tiene una URL pública con HTTPS): pídele a la persona que registre el endpoint en el portal, en el ambiente Sandbox de su empresa, y que te diga el secreto del endpoint por un canal seguro, no por el chat (guárdalo en
.envcomoFOLIIOS_WEBHOOK_SECRET, igual que la clave). Implementa el receptor: valida la firma HMAC (X-Webhook-Signature), deduplica por eliddel evento y responde2xxrápido. Una redirección (3xx) no cuenta como entrega. Dispara un evento de prueba conPOST /v1/sandbox/events. Formato y firma: eventos de webhook. - Si no puede recibirlos (una planilla, un script que corre en el computador de la persona): no registres ningún endpoint y consulta el estado de cada documento con
GET .../documents/{document_id}hasta que sea final. Sin endpoint configurado,webhook_deliveredqueda ennot_applicabley no bloquea el criterio de terminado.
Verifica: con endpoint, al menos una entrega exitosa (2xx); sin endpoint, el proyecto consulta el estado y no depende de avisos.
Si falla: la persona no sabe si puede recibirlos: asume que no. No le pidas que abra puertos ni exponga su computador.
Fase 10. Pruebas automáticas en el proyecto de la persona
Sección titulada «Fase 10. Pruebas automáticas en el proyecto de la persona»Haz: agrega pruebas al proyecto, con la herramienta de pruebas que ya use (o la estándar de su lenguaje), que cubran: armado de la factura desde una venta, armado de una nota con su referencia, reintento con la misma Idempotency-Key, manejo de rejected y de pending, y (si aplica) validación de la firma del webhook. Las pruebas no deben llamar a la API real ni leer la clave: usa respuestas simuladas.
Verifica: ejecuta las pruebas del proyecto y que pasen. Muéstrale a la persona el resultado en una línea («12 pruebas pasan»).
Si falla: si el proyecto no tiene cómo ejecutar pruebas, agrégalo con lo mínimo y explícaselo; no instales dependencias pesadas sin avisar.
Fase 11. Criterio de terminado
Sección titulada «Fase 11. Criterio de terminado»La integración está terminada solo cuando la verificación dice complete: true. No antes, diga lo que diga tu propio criterio.
La verificación es GET /v1/companies/{company_id}/sandbox/integration-check (o la herramienta get_integration_check del MCP). Es de solo lectura: no escribe nada ni gasta cuota. Detalle de la respuesta en la API v1.
derivedtrae cuatro comprobaciones calculadas desde los datos reales de la empresa:invoice_accepted,credit_and_debit_note,contingencyywebhook_delivered. Cada una espassed,pendingonot_applicable.completeestruecuando todas las aplicables están enpassed.- Mientras alguna esté
pending, vuelve a la fase que corresponde: factura (4), notas (5), contingencia (8), webhook (9). Repite la verificación después de cada una. declaredtrae dos comprobaciones que nadie puede verificar (rejection_correctedyidempotency_replayed). Nunca cuentan encomplete. Cuando termines, díselas a la persona como no verificadas: «Probé estos dos casos en el código, pero foliios no puede comprobarlos por mí».
Caducidad (importante, díselo a la persona): la evidencia vale 30 días desde que ocurrió, y un reinicio (reset) del sandbox la borra. Pasado ese tiempo, o después de un reinicio, las comprobaciones vuelven a pending y hay que repetir la fase correspondiente. No es que la integración se haya roto: es que la evidencia venció.
Si falla: si window.truncated es true, el historial era largo y una comprobación pending puede deberse a eso. Si una comprobación sigue pending aunque creas haberla hecho, consulta el documento correspondiente con la API y compáralo con lo que pide esa fase.
Fase 12. Resumen final para la persona y qué falta para habilitación
Sección titulada «Fase 12. Resumen final para la persona y qué falta para habilitación»Escribe un resumen corto, sin jerga, con:
- Qué quedó hecho en su proyecto (en qué archivos y qué hace ahora cuando hay una venta).
- Que la verificación dio
complete: true(la fecha) y que vence a los 30 días o con un reinicio. - Los dos casos declarados como no verificados.
- Si usa avisos (webhooks) o consulta de estado.
- Que todo esto fue en sandbox: lo emitido es simulado y no tiene efecto fiscal. Para facturar de verdad hace falta la habilitación ante la DIAN de su empresa (certificado de firma, resolución de numeración y el set de pruebas de la DIAN); eso lo hace la persona desde su cuenta y no es parte de este manual. No avances hacia ello por tu cuenta: detente y dile a la persona que ese es el siguiente paso.
Dejar instrucciones permanentes en el proyecto
Sección titulada «Dejar instrucciones permanentes en el proyecto»Para que cualquier agente futuro trabaje con estas reglas, copia en el proyecto de la persona la plantilla de instrucciones con el nombre que use tu herramienta.