Documentación del servidor MCP
Cómo conectar Cefidia a Claude u otro asistente de IA, qué puede hacer y qué cuesta. Al final
está la referencia de las 50 herramientas, generada de la misma definición que el
servidor publica en tools/list, así que siempre está al día.
Qué es
Cefidia emite facturas electrónicas CFDI 4.0 desde un cliente MCP: le pides a tu asistente de IA (Claude u otro) que facture, y él prepara el borrador, lo timbra con el PAC y te entrega el XML y el PDF. También registra complementos de pago, notas de crédito y cancelaciones, y consulta tus facturas, receptores, productos y catálogos del SAT.
Requisitos
- Una cuenta de Cefidia.
- Un emisor registrado, con su CSD (Certificado de Sello Digital) subido en el navegador. El CSD nunca pasa por el chat: las herramientas dan la liga de la página donde se sube.
- Crédito de timbrado para timbrar. Los borradores, los catálogos y las consultas no cuestan nada.
Conectar
URL del servidor
https://cefidia.com/mcpClaude (claude.ai, Claude Desktop y la app móvil)
En Configuración → Conectores, elige Agregar conector personalizado y pega la URL del servidor. La primera vez Claude abre una ventana para que inicies sesión con tu cuenta de Cefidia. El conector queda disponible en todos los dispositivos donde uses esa cuenta de Claude.
Claude Code
claude mcp add --transport http cefidia https://cefidia.com/mcp
Cualquier otro cliente MCP
Agrega un servidor MCP remoto (HTTP) con la URL del servidor e inicia sesión con OAuth en la ventana que abre el cliente. No se necesita ID ni secreto de cliente: el cliente se registra solo. Para los clientes que aceptan una configuración JSON:
{
"mcpServers": {
"cefidia": {
"url": "https://cefidia.com/mcp"
}
}
}
El servidor habla MCP sobre HTTP (Streamable HTTP): un único endpoint que recibe
peticiones JSON-RPC 2.0 por POST y sólo expone herramientas.
Permisos
Al conectar, el cliente te lleva a iniciar sesión en Cefidia (OAuth 2.1 con PKCE y registro
dinámico de clientes, RFC 7591) y recibe un token con permisos (scopes). Cada
herramienta exige uno; sin él, la llamada responde con el error
insufficient_scope. Los documentos de descubrimiento están en
/.well-known/oauth-protected-resource y
/.well-known/oauth-authorization-server.
En Claude, las herramientas que crean, cambian o borran datos piden tu confirmación antes de ejecutarse. Puedes ver los asistentes conectados y desconectar cualquiera en Conexiones; la desconexión aplica a toda tu cuenta, y un asistente desconectado deja de funcionar hasta que lo vuelvas a autorizar.
Qué cuesta
- Sólo dos cosas gastan crédito de timbrado: timbrar con
sign_cfdi, y que un receptor timbre un borrador desde la liga que generórequest_receiver_data. - Todo lo demás es gratis: borradores, consultas, catálogos, descargas de XML y PDF.
create_account_topup_linkno cobra nada por sí misma: sólo genera la liga de pago, y la recarga ocurre si tú la pagas.cancel_cfdies definitiva: la cancelación queda registrada en el SAT y no se puede deshacer.
Ejemplos
Algunas peticiones que puedes hacerle a tu asistente, con las herramientas que suele usar para resolverlas:
-
«¿Qué facturas emití este mes y cuáles siguen con saldo pendiente?»
Herramientas:
list_issuers,list_cfdi,get_invoice_balance -
«Factura a mi cliente Comercializadora Ejemplo 10 horas de consultoría a $1,500 más IVA, pagadas en una sola exhibición por transferencia, y timbrala.»
Herramientas:
list_issuers,list_receivers,list_products,search_sat_catalog,create_invoice_draft,sign_cfdi -
«Mi cliente pagó hoy $5,000 por transferencia de la factura PPD que le emití el mes pasado; haz el complemento de pago y timbralo.»
Herramientas:
list_issuers,list_cfdi,get_invoice_balance,create_payment_complement_draft,sign_cfdi -
«¿El servicio está disponible y cuánto crédito de timbrado me queda? Si es poco, dame una liga para recargar.»
Herramientas:
get_service_status,list_issuers,get_account_credit,create_account_topup_link -
«Abre un ticket de soporte: el PDF de mi última factura no muestra el logotipo.»
Herramientas:
create_support_ticket,list_support_tickets
Datos
Por cada llamada, el servidor guarda sólo el nombre de la herramienta, el resultado (correcto o error) y el código de error, con la fecha, el cliente y el emisor; nunca los argumentos ni las respuestas. Ese registro lo ves en Registros. Lo que las herramientas crean o cambian (emisores, facturas, receptores, productos) se guarda en tu cuenta igual que si lo hicieras en la aplicación web.
Los detalles están en el Aviso de Privacidad.
Soporte
Desde el propio asistente puedes abrir un ticket con create_support_ticket,
ver los tuyos con list_support_tickets y
get_support_ticket, y responder con
add_support_ticket_message. Soporte nunca necesita tus archivos del CSD, su
contraseña ni tus tokens.
Referencia de herramientas
Elegir el emisor
Una cuenta puede tener varios emisores (RFC). Cada herramienta que actúa por un emisor lleva
su id en el argumento obligatorio issuer, aunque la cuenta tenga un solo emisor;
list_issuers da los ids. Sin él, o con un id que no es de uno de tus emisores,
la respuesta es el error issuer_selection_required con la lista de emisores entre los
que elegir. list_issuers, get_service_status,
register_issuer y las herramientas de soporte no necesitan emisor.
Errores
Los errores de una herramienta llegan como resultado con isError: true y un
texto JSON con error (el código) y message.
Emisores y cuenta
Alta y consulta del emisor, logotipo del PDF, estado del servicio y soporte.
get_issuer Consultar razón social
Permiso: issuers:read
Return one issuer (id, RFC, business name) with its CSD status and sat_test (true when its CSD is one of the SAT's test CSDs: a test issuer, whose CFDIs are not real). If the issuer has no CSD on file, also returns upload_url, the issuer's page where the CSD is uploaded in the browser after signing in.
| Argumento | Tipo | Descripción |
|---|---|---|
issuer requerido |
string |
Id of the issuer the call acts for, from list_issuers. |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"issuer": {
"type": "string",
"format": "uuid",
"description": "Id of the issuer the call acts for, from list_issuers."
}
},
"additionalProperties": false,
"required": [
"issuer"
]
}
get_pdf_branding Consultar personalización del PDF
Permiso: issuers:read
Return the calling issuer's saved PDF branding: accent color, phone, email, website, footer and whether a logo is stored. It is what the CFDI PDFs are drawn with.
| Argumento | Tipo | Descripción |
|---|---|---|
issuer requerido |
string |
Id of the issuer the call acts for, from list_issuers. |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"issuer": {
"type": "string",
"format": "uuid",
"description": "Id of the issuer the call acts for, from list_issuers."
}
},
"additionalProperties": false,
"required": [
"issuer"
]
}
set_pdf_branding Configurar personalización del PDF
Permiso: issuers:write
Change the calling issuer's PDF branding. Fields passed replace the saved ones, omitted fields are kept, an empty string clears one. Nothing is saved if anything is invalid. The logo is sent as base64 (PNG or JPEG, at most 1 MB and 2000x2000 px) and is re-encoded as PNG.
| Argumento | Tipo | Descripción |
|---|---|---|
accent_color |
string |
One color, six hex digits like #05668d. Headings, table headers and rules are drawn from it. |
phone |
string |
At most 30 characters. |
email |
string |
|
website |
string |
Must start with https:// |
footer |
string |
Plain text, at most 500 characters and 8 lines. |
logo_base64 |
string |
The logo image, base64 encoded (a data: URI is accepted). |
remove_logo |
boolean |
Delete the stored logo. Not with logo_base64. |
issuer requerido |
string |
Id of the issuer the call acts for, from list_issuers. |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"accent_color": {
"type": "string",
"description": "One color, six hex digits like #05668d. Headings, table headers and rules are drawn from it."
},
"phone": {
"type": "string",
"description": "At most 30 characters."
},
"email": {
"type": "string"
},
"website": {
"type": "string",
"description": "Must start with https://"
},
"footer": {
"type": "string",
"description": "Plain text, at most 500 characters and 8 lines."
},
"logo_base64": {
"type": "string",
"description": "The logo image, base64 encoded (a data: URI is accepted)."
},
"remove_logo": {
"type": "boolean",
"description": "Delete the stored logo. Not with logo_base64."
},
"issuer": {
"type": "string",
"format": "uuid",
"description": "Id of the issuer the call acts for, from list_issuers."
}
},
"required": [
"issuer"
]
}
get_service_status Consultar estado del servicio
Permiso: issuers:read
Check whether the service is ready to use, in one read-only call; works with no issuer and takes no issuer selection. Returns {service: {status: available|interrupted, message?}, setup: {complete, issues: [missing_issuer | missing_csd | incomplete_theming, each with where it is resolved: missing_issuer carries setup_url, the page where the user registers their issuer and uploads its CSD (register_issuer also creates the issuer; its CSD is then uploaded in the browser), missing_csd carries upload_url, the page where the CSD is uploaded in the browser]}, balance: {billing: on, balance, currency, stamp_price, stamp_currency, stamps_affordable (the folios left), bonuses (top-up bonus tiers)} or {billing: off}, notifications: [{id, severity, message}]}. Nothing can be issued (created, updated or signed: an invoice, credit note or payment complement) while service.status is interrupted or setup.issues has a missing_issuer or missing_csd, and nothing can be signed while the balance does not cover a stamp. notifications are the service's current notices, and setup lists what is left to set up.
Sin argumentos.
Esquema JSON de entrada
{
"type": "object",
"properties": {},
"additionalProperties": false
}
register_issuer Registrar razón social
Permiso: issuers:write
Register a new issuer (a business that issues invoices) for the caller, who becomes its owner. Works with no issuer yet and takes no issuer selection. It takes the fiscal data only: rfc, business_name, fiscal_regime (SAT c_RegimenFiscal key, e.g. 601) and lugar_expedicion (5-digit postal code). The CSD (certificate, private key and password) is uploaded in the browser at the returned upload_url, the issuer's page; this tool never receives it, and the issuer cannot issue until it is uploaded. Returns {id, rfc, business_name, has_active_csd: false, upload_url}.
| Argumento | Tipo | Descripción |
|---|---|---|
rfc requerido |
string |
The issuer's RFC (12 or 13 characters) |
business_name requerido |
string |
Legal name, as on the SAT |
fiscal_regime requerido |
string |
c_RegimenFiscal key, e.g. 601 |
lugar_expedicion requerido |
string |
5-digit postal code of the place of issue |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"rfc": {
"type": "string",
"description": "The issuer's RFC (12 or 13 characters)"
},
"business_name": {
"type": "string",
"description": "Legal name, as on the SAT"
},
"fiscal_regime": {
"type": "string",
"description": "c_RegimenFiscal key, e.g. 601"
},
"lugar_expedicion": {
"type": "string",
"description": "5-digit postal code of the place of issue"
}
},
"required": [
"rfc",
"business_name",
"fiscal_regime",
"lugar_expedicion"
]
}
list_issuers Listar razones sociales
Permiso: issuers:read
List the caller's authorized issuers (UUID + RFC + business name + sat_test, true for a test issuer whose CSD is one of the SAT's test CSDs): the issuers the caller can act on.
Sin argumentos.
Esquema JSON de entrada
{
"type": "object",
"properties": {},
"additionalProperties": false
}
create_support_ticket Create support ticket
Permiso: issuers:write
Open a support ticket with the Cefidia team for the caller: a problem, a question or a request about the service. Works with no issuer and takes no issuer selection. Support works from the details in the title and description: what was tried, the invoice id or the error code returned. Support staff read the ticket; support never needs CSD files, key passwords or tokens. Support answers inside the ticket, and nothing is pushed to the caller: get_support_ticket returns the answers. Returns {ticket: {id, title, description, state, created_at, updated_at, messages}}; the id is what get_support_ticket and add_support_ticket_message take. Errors: invalid_argument, support_unavailable.
| Argumento | Tipo | Descripción |
|---|---|---|
title requerido |
string |
A short summary of the problem. |
description requerido |
string |
What happened, in detail. |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"title": {
"type": "string",
"maxLength": 200,
"description": "A short summary of the problem."
},
"description": {
"type": "string",
"maxLength": 10000,
"description": "What happened, in detail."
}
},
"required": [
"title",
"description"
]
}
list_support_tickets List support tickets
Permiso: issuers:read
List the caller's support tickets, newest first. Read-only; works with no issuer. Returns {tickets: [{id, title, state (open | in_progress | resolved | closed), created_at, updated_at, message_count, last_message_from (user | support | null)}]}. A ticket whose last_message_from is support has an answer to read with get_support_ticket. Error: support_unavailable.
Sin argumentos.
Esquema JSON de entrada
{
"type": "object",
"properties": {},
"additionalProperties": false
}
get_support_ticket Get support ticket
Permiso: issuers:read
Read one of the caller's support tickets with its whole conversation: the answers from the Cefidia team are the messages whose from is support. Read-only; works with no issuer. Returns {ticket: {id, title, description, state (open | in_progress | resolved | closed), created_at, updated_at, messages: [{from (user | support), text, at}]}}. Errors: invalid_argument, not_found (no such ticket of the caller's), support_unavailable.
| Argumento | Tipo | Descripción |
|---|---|---|
ticket_id requerido |
string |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"ticket_id": {
"type": "string"
}
},
"required": [
"ticket_id"
]
}
add_support_ticket_message Add support ticket message
Permiso: issuers:write
Add the caller's reply to one of their support tickets: an answer to support's question or more details. Works with no issuer. Support staff read the message; support never needs CSD files, key passwords or tokens. Returns {ticket} with the whole conversation, as get_support_ticket. Errors: invalid_argument, not_found, ticket_closed (a closed ticket takes no replies; create_support_ticket opens a new one), support_unavailable.
| Argumento | Tipo | Descripción |
|---|---|---|
ticket_id requerido |
string |
|
message requerido |
string |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"ticket_id": {
"type": "string"
},
"message": {
"type": "string",
"maxLength": 10000
}
},
"required": [
"ticket_id",
"message"
]
}
Facturación
Borradores, timbrado, cancelación, receptores y saldo.
create_invoice_draft Crear borrador de factura
Permiso: invoices:write
Create a CFDI draft for the calling issuer from a whole CFDI document (the Comprobante JSON object). The document is validated and stored as given; the result is the stored invoice in the get_cfdi shape, with version 1. A type I draft may omit Receptor (a receiver can fill it in through request_receiver_data), but it is required to sign. Returns a needs_csd status instead of a draft if the issuer has no CSD.
| Argumento | Tipo | Descripción |
|---|---|---|
cfdi requerido |
object |
The CFDI 4.0 Comprobante document. |
issuer requerido |
string |
Id of the issuer the call acts for, from list_issuers. |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"cfdi": {
"type": "object",
"description": "The CFDI 4.0 Comprobante document."
},
"issuer": {
"type": "string",
"format": "uuid",
"description": "Id of the issuer the call acts for, from list_issuers."
}
},
"required": [
"cfdi",
"issuer"
]
}
draft_cfdi Draft CFDI
Permiso: invoices:write
Create a CFDI draft for the calling issuer as a copy of a template: the template's cfdi is copied in, and its note is recorded on the draft, so get_cfdi shows what the draft still needs. template_id is a global template or one of the issuer's own, from list_cfdi_template; another issuer's template is not_found. The draft is validated and stored like create_invoice_draft, with version 1. Returns a needs_csd status instead of a draft if the issuer has no CSD.
| Argumento | Tipo | Descripción |
|---|---|---|
template_id requerido |
string |
Id of the template, from list_cfdi_template. |
issuer requerido |
string |
Id of the issuer the call acts for, from list_issuers. |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"template_id": {
"type": "string",
"description": "Id of the template, from list_cfdi_template."
},
"issuer": {
"type": "string",
"format": "uuid",
"description": "Id of the issuer the call acts for, from list_issuers."
}
},
"required": [
"template_id",
"issuer"
]
}
replace_cfdi Replace CFDI
Permiso: invoices:write
Replace the whole CFDI document of a draft: cfdi is the complete new Comprobante, and nothing of the old one is kept. expected_version is the draft's revision counter (the version field of get_cfdi, which starts at 1 and goes up on every change), not the CFDI Version attribute (4.0). A stale expected_version answers a conflict with the current version. Drafts only: a signed or canceled CFDI answers invalid_state, and so does a draft with an open receiver request (revoke_receiver_request closes it). Returns the stored CFDI in the get_cfdi shape with the new version.
| Argumento | Tipo | Descripción |
|---|---|---|
invoice_id requerido |
string |
|
expected_version requerido |
integer |
The draft's version from get_cfdi (starts at 1), not the CFDI Version attribute. |
cfdi requerido |
object |
The CFDI 4.0 Comprobante document. |
issuer requerido |
string |
Id of the issuer the call acts for, from list_issuers. |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"invoice_id": {
"type": "string"
},
"expected_version": {
"type": "integer",
"minimum": 1,
"description": "The draft's version from get_cfdi (starts at 1), not the CFDI Version attribute."
},
"cfdi": {
"type": "object",
"description": "The CFDI 4.0 Comprobante document."
},
"issuer": {
"type": "string",
"format": "uuid",
"description": "Id of the issuer the call acts for, from list_issuers."
}
},
"required": [
"invoice_id",
"expected_version",
"cfdi",
"issuer"
]
}
patch_cfdi Patch CFDI
Permiso: invoices:write
Apply an RFC 6902 JSON Patch to a draft's CFDI document. patch is an array of at most 100 operations (add, remove, replace, move, copy, test), applied in order to a copy of the stored CFDI. Paths are JSON Pointers from the CFDI root, for example /Conceptos/0/Cantidad. expected_version is the draft's revision counter (the version field of get_cfdi, which starts at 1 and goes up on every change), not the CFDI Version attribute (4.0). A stale expected_version answers a conflict with the current version. A patch that does not apply (a missing path, an unknown operation, a failed test, or more than 100 operations) answers invalid_argument with op_index, path and reason, and nothing is written. Drafts only: a signed or canceled CFDI answers invalid_state, and so does a draft with an open receiver request (revoke_receiver_request closes it). Returns the stored CFDI in the get_cfdi shape with the new version.
| Argumento | Tipo | Descripción |
|---|---|---|
invoice_id requerido |
string |
|
expected_version requerido |
integer |
The draft's version from get_cfdi (starts at 1), not the CFDI Version attribute. |
patch requerido |
object[] |
RFC 6902 operations, applied in order. add, replace and test take a value; move and copy take a from. |
issuer requerido |
string |
Id of the issuer the call acts for, from list_issuers. |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"invoice_id": {
"type": "string"
},
"expected_version": {
"type": "integer",
"minimum": 1,
"description": "The draft's version from get_cfdi (starts at 1), not the CFDI Version attribute."
},
"patch": {
"type": "array",
"maxItems": 100,
"description": "RFC 6902 operations, applied in order. add, replace and test take a value; move and copy take a from.",
"items": {
"type": "object",
"properties": {
"op": {
"type": "string",
"enum": [
"add",
"remove",
"replace",
"move",
"copy",
"test"
]
},
"path": {
"type": "string",
"description": "A JSON Pointer from the CFDI root."
},
"from": {
"type": "string",
"description": "The source JSON Pointer of move and copy."
},
"value": {
"description": "The value of add, replace and test."
}
},
"required": [
"op",
"path"
]
}
},
"issuer": {
"type": "string",
"format": "uuid",
"description": "Id of the issuer the call acts for, from list_issuers."
}
},
"required": [
"invoice_id",
"expected_version",
"patch",
"issuer"
]
}
sign_cfdi Firmar factura
Permiso: invoices:write
Stamp (timbrar) a draft invoice through the PAC. When billing is on this debits the stamp price from the caller's credit first (see get_account_credit): a credit that does not cover it answers insufficient_balance and nothing is stamped; a failed stamp is credited back. The deployment, not an argument, decides whether stamps are real CFDIs or PAC test stamps, except that an issuer using a SAT test CSD or a document addressed to a SAT test RFC is stamped in the sandbox: no credit is charged and no balance is needed. Every successful result reports which in ambiente ("produccion" or "prueba"); get_cfdi and list_cfdi carry the same ambiente for signed invoices. expected_version is the version last read; a stale version answers a conflict with the current version. A type I draft without a Receptor cannot be signed (invalid_argument, receptor_missing). A Fecha more than 72 hours old is replaced by the current Mexico City time. The stored amounts are signed exactly as saved. Drafts only, invoices and payment complements alike (signing a complement locks the paid PPD invoices and revalidates their balance: a stale one answers invalid_argument with payment_balance). Returns the signed invoice in the get_cfdi shape (timbre.uuid and timbre.fecha_timbrado set), including downloads (permanent XML and PDF links, see get_cfdi), plus ambiente, or a needs_csd status if the issuer has no CSD.
| Argumento | Tipo | Descripción |
|---|---|---|
invoice_id requerido |
string |
|
expected_version requerido |
integer |
|
issuer requerido |
string |
Id of the issuer the call acts for, from list_issuers. |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"invoice_id": {
"type": "string"
},
"expected_version": {
"type": "integer",
"minimum": 1
},
"issuer": {
"type": "string",
"format": "uuid",
"description": "Id of the issuer the call acts for, from list_issuers."
}
},
"required": [
"invoice_id",
"expected_version",
"issuer"
]
}
create_payment_complement_draft Crear borrador de complemento de pago
Permiso: invoices:write
Build a draft payment complement (comprobante type P, Pagos 2.0) that records payments received for one or more PPD invoices, without writing the document by hand. Arguments: fecha (the complement's own Fecha, YYYY-MM-DDTHH:MM:SS, required: the server never picks the clock) and pagos, an array of {fecha_pago, forma_de_pago (SAT c_FormaPago key, never 99), num_operacion (optional), documentos: [{invoice_id (the id of a signed PPD invoice of yours), imp_pagado (decimal string)}]}. The server takes Receptor from the paid invoices (they must share one receptor), numbers each installment from its ledger and computes the balances and taxes; the result is the stored draft in the get_cfdi shape, an ordinary draft that replace_cfdi replaces and sign_cfdi stamps. Validation problems (an invoice that is a draft, canceled, PUE or unknown, an amount above the balance, ...) answer invalid_argument with the per-field errors. Returns a needs_csd status instead of a draft if the issuer has no CSD.
| Argumento | Tipo | Descripción |
|---|---|---|
fecha requerido |
string |
YYYY-MM-DDTHH:MM:SS |
pagos requerido |
object[] |
|
issuer requerido |
string |
Id of the issuer the call acts for, from list_issuers. |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"fecha": {
"type": "string",
"description": "YYYY-MM-DDTHH:MM:SS"
},
"pagos": {
"type": "array",
"minItems": 1,
"maxItems": 10,
"items": {
"type": "object",
"properties": {
"fecha_pago": {
"type": "string",
"description": "YYYY-MM-DDTHH:MM:SS"
},
"forma_de_pago": {
"type": "string",
"description": "SAT c_FormaPago key of the payment, not 99"
},
"num_operacion": {
"type": "string",
"maxLength": 100
},
"documentos": {
"type": "array",
"minItems": 1,
"maxItems": 20,
"items": {
"type": "object",
"properties": {
"invoice_id": {
"type": "string"
},
"imp_pagado": {
"type": "string",
"description": "Decimal string, e.g. '500.00'"
}
},
"required": [
"invoice_id",
"imp_pagado"
]
}
}
},
"required": [
"fecha_pago",
"forma_de_pago",
"documentos"
]
}
},
"issuer": {
"type": "string",
"format": "uuid",
"description": "Id of the issuer the call acts for, from list_issuers."
}
},
"required": [
"fecha",
"pagos",
"issuer"
]
}
create_credit_note_draft Crear borrador de nota de crédito
Permiso: invoices:write
Build a draft credit note (nota de crédito, comprobante type E with CfdiRelacionados TipoRelacion 01) that reduces or reverses an invoice, without writing the document by hand. The invoice is named by exactly one of invoice_id (the id of one of your signed invoices, PUE or PPD; a draft, canceled or non-invoice document is refused) or folio_fiscal (its UUID; also valid for an invoice issued elsewhere). For your own invoice the server takes Receptor and, when conceptos is omitted, the concepts from it (a full credit); for an invoice issued elsewhere receptor ({Rfc, Nombre, DomicilioFiscalReceptor, RegimenFiscalReceptor, UsoCFDI?}) and conceptos are required, and nothing about that invoice is checked here. Other arguments: fecha (the note's own Fecha, YYYY-MM-DDTHH:MM:SS, required: the server never picks the clock), forma_pago (SAT c_FormaPago key, never 99: the note is PUE), uso_cfdi (default G02) and conceptos, the concepts to credit in the same shape as the document's Conceptos (ClaveProdServ, Cantidad, ClaveUnidad, Descripcion, ValorUnitario, ObjetoImp, Impuestos). moneda (SAT c_Moneda key) and tipo_cambio (required for a currency other than MXN) default to your invoice's own, or MXN for one issued elsewhere. informacion_global ({Periodicidad, Meses, Año}) is required exactly when the receptor is XAXX010101000 (público en general); for your own invoice it is copied from it when omitted. The server computes every amount and tax; the result is the stored draft in the get_cfdi shape, an ordinary draft that replace_cfdi replaces and sign_cfdi stamps. The total credited across one of your invoices' signed notes cannot exceed its Total (credit_exceeds_total says what is left). Validation problems answer invalid_argument with the per-field errors. Returns a needs_csd status instead of a draft if the issuer has no CSD. An invoice with signed credit notes cannot be canceled until they are.
| Argumento | Tipo | Descripción |
|---|---|---|
invoice_id |
string |
Id of one of your signed invoices |
folio_fiscal |
string |
UUID of the invoice credited |
fecha requerido |
string |
YYYY-MM-DDTHH:MM:SS |
forma_pago requerido |
string |
SAT c_FormaPago key of the note, not 99 |
uso_cfdi |
string |
SAT c_UsoCFDI key, default G02 |
receptor |
object |
Required for an invoice issued elsewhere; overrides the invoice's receptor otherwise. |
conceptos |
object[] |
Concept inputs as in the document; when omitted the whole invoice is credited. |
moneda |
string |
SAT c_Moneda key; default the invoice's, else MXN |
tipo_cambio |
string |
Exchange rate to MXN, up to 6 decimals; not for MXN |
informacion_global |
object |
{Periodicidad, Meses, Año}; only for the generic public receptor, copied from your own invoice when omitted. |
issuer requerido |
string |
Id of the issuer the call acts for, from list_issuers. |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"invoice_id": {
"type": "string",
"description": "Id of one of your signed invoices"
},
"folio_fiscal": {
"type": "string",
"description": "UUID of the invoice credited"
},
"fecha": {
"type": "string",
"description": "YYYY-MM-DDTHH:MM:SS"
},
"forma_pago": {
"type": "string",
"description": "SAT c_FormaPago key of the note, not 99"
},
"uso_cfdi": {
"type": "string",
"description": "SAT c_UsoCFDI key, default G02"
},
"receptor": {
"type": "object",
"description": "Required for an invoice issued elsewhere; overrides the invoice's receptor otherwise."
},
"conceptos": {
"type": "array",
"minItems": 1,
"items": {
"type": "object"
},
"description": "Concept inputs as in the document; when omitted the whole invoice is credited."
},
"moneda": {
"type": "string",
"description": "SAT c_Moneda key; default the invoice's, else MXN"
},
"tipo_cambio": {
"type": "string",
"description": "Exchange rate to MXN, up to 6 decimals; not for MXN"
},
"informacion_global": {
"type": "object",
"description": "{Periodicidad, Meses, Año}; only for the generic public receptor, copied from your own invoice when omitted."
},
"issuer": {
"type": "string",
"format": "uuid",
"description": "Id of the issuer the call acts for, from list_issuers."
}
},
"required": [
"fecha",
"forma_pago",
"issuer"
]
}
get_invoice_balance Consultar saldo de factura
Permiso: invoices:read
The payment balance of one signed PPD invoice (MetodoPago PPD): total, pagado, saldo, next_parcialidad, payable (false when saldo is 0.00) and the installments already applied by signed payment complements. Read-only. For a payment complement written by hand, uuid, next_parcialidad and saldo are the values of IdDocumento, NumParcialidad and ImpSaldoAnt. A draft (no folio fiscal yet), a canceled invoice, a PUE invoice or a payment complement answers invalid_state with the reason.
| Argumento | Tipo | Descripción |
|---|---|---|
invoice_id requerido |
string |
|
issuer requerido |
string |
Id of the issuer the call acts for, from list_issuers. |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"invoice_id": {
"type": "string"
},
"issuer": {
"type": "string",
"format": "uuid",
"description": "Id of the issuer the call acts for, from list_issuers."
}
},
"required": [
"invoice_id",
"issuer"
]
}
get_account_credit Consultar saldo de la cuenta
Permiso: invoices:read
Get the caller's prepaid stamp credit (the account balance used to pay for stamping) and the price of one stamp. Read-only. This is not the outstanding balance of an invoice (that is get_invoice_balance). Every sign_cfdi debits the stamp price from this credit (invoices, credit notes and payment complements alike); when it does not cover it sign_cfdi answers insufficient_balance and nothing is stamped. Returns {billing: on, balance, currency, stamp_price, stamp_currency, stamps_affordable (null if the credit is kept in another currency than the price)} or {billing: off} when stamps are free. create_account_topup_link adds credit.
| Argumento | Tipo | Descripción |
|---|---|---|
issuer requerido |
string |
Id of the issuer the call acts for, from list_issuers. |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"issuer": {
"type": "string",
"format": "uuid",
"description": "Id of the issuer the call acts for, from list_issuers."
}
},
"additionalProperties": false,
"required": [
"issuer"
]
}
list_account_credit_history Listar historial de saldo
Permiso: invoices:read
List the caller's stamp-credit history, newest first: the top-ups that added credit and the stamps that used it. Read-only. This concerns the account's prepaid credit only, not CFDIs (those are in list_cfdi) and not payments received for an invoice. Returns {billing: on, total, limit, offset, entries: [{when (ISO 8601 UTC or null), kind (topup | bonus | welcome_bonus | referral_bonus | promotion | stamp | stamp_refund | adjustment), amount (signed: stamps are negative), currency, cfdi_id (the stamped document, for stamp rows, else null)}]} or {billing: off}.
| Argumento | Tipo | Descripción |
|---|---|---|
limit |
integer |
|
offset |
integer |
|
issuer requerido |
string |
Id of the issuer the call acts for, from list_issuers. |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"limit": {
"type": "integer",
"minimum": 1,
"maximum": 100,
"default": 20
},
"offset": {
"type": "integer",
"minimum": 0,
"default": 0
},
"issuer": {
"type": "string",
"format": "uuid",
"description": "Id of the issuer the call acts for, from list_issuers."
}
},
"required": [
"issuer"
]
}
get_account_referrals Consultar referidos
Permiso: invoices:read
Get the caller's referral link and the people they referred. Creates the link the first time it is called. Read-only: nothing is charged or credited by this call. Returns {referrals: on, code, link (the referral link the caller shares; null with a message when it could not be created), total, limit, offset, entries: [{email_masked, joined (ISO 8601 UTC)}]} or {referrals: off}. The referred people's emails are masked. Error: referrals_unavailable.
| Argumento | Tipo | Descripción |
|---|---|---|
limit |
integer |
|
offset |
integer |
|
issuer requerido |
string |
Id of the issuer the call acts for, from list_issuers. |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"limit": {
"type": "integer",
"minimum": 1,
"maximum": 100,
"default": 20
},
"offset": {
"type": "integer",
"minimum": 0,
"default": 0
},
"issuer": {
"type": "string",
"format": "uuid",
"description": "Id of the issuer the call acts for, from list_issuers."
}
},
"required": [
"issuer"
]
}
create_account_topup_link Crear enlace de recarga
Permiso: invoices:write
Create a payment link that adds credit to the caller's stamp-credit balance (see get_account_credit). Nothing is charged by this call: it only returns a link the user opens in their browser to pay with the payment provider. This is not a CFDI payment complement and has nothing to do with invoices. Every top-up is invoiced (a CFDI is issued to the customer once the payment is confirmed), so invoice_to says to whom: the RFC of one of the caller's issuers (list_issuers); the CFDI uses the fiscal data on that issuer's profile. It is required where top-ups are invoiced and ignored elsewhere; a user with no issuer must first register a razón social in the web app. Returns {billing: on, amount, payment_url, message} (the payment is made by opening payment_url in a browser; the credit arrives once the provider confirms the payment) or {billing: off}. Errors: invalid_argument (invoice_to missing, unknown or not the caller's), topup_unavailable (the deployment has no top-up product), topup_failed (the provider refused; the message says why).
| Argumento | Tipo | Descripción |
|---|---|---|
amount requerido |
number |
Amount to add, in the product's currency, up to two decimals. |
invoice_to requerido |
string |
Who the top-up is invoiced to: the RFC of one of the caller's issuers. |
uso_cfdi |
string |
SAT CFDI use for the receiver (for example G03). Default: the one used for that RFC last time, else G03. |
issuer requerido |
string |
Id of the issuer the call acts for, from list_issuers. |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"amount": {
"type": "number",
"exclusiveMinimum": 0,
"description": "Amount to add, in the product's currency, up to two decimals."
},
"invoice_to": {
"type": "string",
"description": "Who the top-up is invoiced to: the RFC of one of the caller's issuers."
},
"uso_cfdi": {
"type": "string",
"description": "SAT CFDI use for the receiver (for example G03). Default: the one used for that RFC last time, else G03."
},
"issuer": {
"type": "string",
"format": "uuid",
"description": "Id of the issuer the call acts for, from list_issuers."
}
},
"required": [
"amount",
"invoice_to",
"issuer"
]
}
get_invoice_document_schema Consultar esquema del documento
Permiso: invoices:read
Explains the document that create_invoice_draft and replace_cfdi accept: JSON Schema, amount and date encoding, fixed values, forbidden fields, how to compute totals, tax rules, small catalogs, four valid examples filled with your issuer's data (an invoice, a multi-concept invoice, a payment complement of a PPD invoice, comprobante type P, and a credit note, type E), the validation error format, and how to use `version` / `expected_version` when replacing a draft. Read-only; it is the reference for writing a draft.
| Argumento | Tipo | Descripción |
|---|---|---|
issuer requerido |
string |
Id of the issuer the call acts for, from list_issuers. |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"issuer": {
"type": "string",
"format": "uuid",
"description": "Id of the issuer the call acts for, from list_issuers."
}
},
"additionalProperties": false,
"required": [
"issuer"
]
}
search_sat_catalog Buscar en catálogo del SAT
Permiso: invoices:read
Looks up SAT catalog keys (ClaveProdServ, ClaveUnidad) by key or by text; the results are valid keys for a concept.
| Argumento | Tipo | Descripción |
|---|---|---|
catalog requerido |
string |
Valores: clave_prod_serv, clave_unidad |
key |
string |
Exact key lookup: returns the entry or an empty list. |
query |
string |
Text matched (case- and accent-insensitive) against the description and as a key prefix. Either key or query is given. |
limit |
integer |
|
issuer requerido |
string |
Id of the issuer the call acts for, from list_issuers. |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"catalog": {
"type": "string",
"enum": [
"clave_prod_serv",
"clave_unidad"
]
},
"key": {
"type": "string",
"description": "Exact key lookup: returns the entry or an empty list."
},
"query": {
"type": "string",
"description": "Text matched (case- and accent-insensitive) against the description and as a key prefix. Either key or query is given."
},
"limit": {
"type": "integer",
"minimum": 1,
"maximum": 50,
"default": 20
},
"issuer": {
"type": "string",
"format": "uuid",
"description": "Id of the issuer the call acts for, from list_issuers."
}
},
"required": [
"catalog",
"issuer"
]
}
get_invoice_status Consultar estado de factura
Permiso: invoices:read
Look up an invoice's short summary (id, status, fecha, receptor_rfc, total, tipo_de_comprobante: I for an invoice, E for a credit note, P for a payment complement) for the calling issuer.
| Argumento | Tipo | Descripción |
|---|---|---|
invoice_id requerido |
string |
|
issuer requerido |
string |
Id of the issuer the call acts for, from list_issuers. |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"invoice_id": {
"type": "string"
},
"issuer": {
"type": "string",
"format": "uuid",
"description": "Id of the issuer the call acts for, from list_issuers."
}
},
"required": [
"invoice_id",
"issuer"
]
}
get_cfdi Consultar factura
Permiso: invoices:read
Return everything stored about one invoice of the calling issuer: its version, the whole CFDI document (cfdi), and the stamp and cancellation data, which are null until the invoice is signed / canceled, and receiver_request: null, or the state of its receiver request link (status open, stamped, expired or revoked, failed_attempts and last_error, never the url). Also carries direction (issued or received) and origin (cefidia or sat), and template_id and template_note, which are the template a draft was made from and its note, null for any other invoice; the id is explicit, so a received CFDI is found by its id whatever list_cfdi' direction default is. Also carries downloads: null for a draft, otherwise {xml, pdf}, the links to download the stamped XML and PDF, each {filename, content_type, size_bytes, download_url} or {error} when its file cannot be checked or rendered. Open a link in a browser to save the file; the file never passes through this tool. A PDF not generated yet is generated once, here, before its link is returned. The links never expire, are the same on every call and show the CFDI's current state (a canceled one has its PDF marked as canceled). Anyone who holds a link can download the file, so it can be given to the receiver; do not post it anywhere public.
| Argumento | Tipo | Descripción |
|---|---|---|
invoice_id requerido |
string |
|
direction |
string |
Optional narrowing; all (default) finds any direction. Valores: issued, received, all |
origin |
string |
Optional narrowing; every origin when omitted. Valores: cefidia, sat |
issuer requerido |
string |
Id of the issuer the call acts for, from list_issuers. |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"invoice_id": {
"type": "string"
},
"direction": {
"type": "string",
"enum": [
"issued",
"received",
"all"
],
"description": "Optional narrowing; all (default) finds any direction."
},
"origin": {
"type": "string",
"enum": [
"cefidia",
"sat"
],
"description": "Optional narrowing; every origin when omitted."
},
"issuer": {
"type": "string",
"format": "uuid",
"description": "Id of the issuer the call acts for, from list_issuers."
}
},
"required": [
"invoice_id",
"issuer"
]
}
delete_cfdi Eliminar borrador de factura
Permiso: invoices:write
Permanently delete a draft; it returns {deleted: true, invoice_id}. Only drafts can be deleted: a signed or canceled CFDI answers invalid_state, and cancel_cfdi cancels a signed one. A draft with an open receiver request is refused until revoke_receiver_request closes it.
| Argumento | Tipo | Descripción |
|---|---|---|
invoice_id requerido |
string |
|
issuer requerido |
string |
Id of the issuer the call acts for, from list_issuers. |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"invoice_id": {
"type": "string"
},
"issuer": {
"type": "string",
"format": "uuid",
"description": "Id of the issuer the call acts for, from list_issuers."
}
},
"required": [
"invoice_id",
"issuer"
]
}
cancel_cfdi Cancelar factura
Permiso: invoices:write
Cancel a signed invoice belonging to the calling issuer. A payment complement is refused (invalid_state, naming the blocking ones) while a later installment of an invoice it pays is still active, and a PPD invoice while it has active payment complements: the later complements are canceled first. motivo is the SAT cancellation reason: 01 issued with errors, with a related document (then substitution_uuid, the folio fiscal of the CFDI that replaces this one, is required); 02 issued with errors, without a related document; 03 the operation was not carried out; 04 nominative operation related to a global invoice. substitution_uuid is refused with any other motivo.
| Argumento | Tipo | Descripción |
|---|---|---|
invoice_id requerido |
string |
|
motivo requerido |
string |
Valores: 01, 02, 03, 04 |
substitution_uuid |
string |
|
issuer requerido |
string |
Id of the issuer the call acts for, from list_issuers. |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"invoice_id": {
"type": "string"
},
"motivo": {
"type": "string",
"enum": [
"01",
"02",
"03",
"04"
]
},
"substitution_uuid": {
"type": "string",
"format": "uuid"
},
"issuer": {
"type": "string",
"format": "uuid",
"description": "Id of the issuer the call acts for, from list_issuers."
}
},
"required": [
"invoice_id",
"motivo",
"issuer"
]
}
request_receiver_data Pedir datos al receptor
Permiso: invoices:write
Create the link a receiver uses to fill in their own fiscal data for a draft type I invoice, so the issuer does not collect it. The receiver opens the link, reviews the invoice, enters their RFC, name, postal code, tax regime and CFDI use (and optionally email and phone), and the invoice is stamped automatically; the same link then offers the PDF and XML downloads, and the receiver is saved in your receiver directory (list_receivers). The draft has no Receptor and is otherwise valid. expected_version is the version last read. The result's url is returned only once and Cefidia does not send it to the receiver. Anyone who has the url can enter the receiver data and trigger the stamp, which is charged to the caller's credit (see get_account_credit); revoke_receiver_request turns it off. While the link is open the draft cannot be updated or deleted; sign_cfdi still works. One open link per invoice: requesting again answers already_requested until the link is revoked. Returns a needs_csd status if the issuer has no CSD.
| Argumento | Tipo | Descripción |
|---|---|---|
invoice_id requerido |
string |
|
expected_version requerido |
integer |
|
issuer requerido |
string |
Id of the issuer the call acts for, from list_issuers. |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"invoice_id": {
"type": "string"
},
"expected_version": {
"type": "integer",
"minimum": 1
},
"issuer": {
"type": "string",
"format": "uuid",
"description": "Id of the issuer the call acts for, from list_issuers."
}
},
"required": [
"invoice_id",
"expected_version",
"issuer"
]
}
revoke_receiver_request Revocar solicitud al receptor
Permiso: invoices:write
Turn off an invoice's receiver request, open or already stamped: the url stops working (a stamped link stops offering its downloads). A revoked draft can be edited again, and requested again for a new url. get_cfdi shows the link's state in receiver_request.
| Argumento | Tipo | Descripción |
|---|---|---|
invoice_id requerido |
string |
|
issuer requerido |
string |
Id of the issuer the call acts for, from list_issuers. |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"invoice_id": {
"type": "string"
},
"issuer": {
"type": "string",
"format": "uuid",
"description": "Id of the issuer the call acts for, from list_issuers."
}
},
"required": [
"invoice_id",
"issuer"
]
}
save_receiver Guardar receptor
Permiso: invoices:write
Save a receiver (a customer the issuer invoices) in the calling issuer's directory, or update the one with the same RFC. Receivers reached through request_receiver_data are saved automatically. email and phone are optional and kept when omitted. The result's receptor is the CFDI Receptor node to copy into a draft.
| Argumento | Tipo | Descripción |
|---|---|---|
rfc requerido |
string |
|
nombre requerido |
string |
Name as in the Constancia fiscal. |
domicilio_fiscal requerido |
string |
Postal code (5 digits). |
regimen_fiscal requerido |
string |
SAT c_RegimenFiscal key. |
uso_cfdi requerido |
string |
SAT c_UsoCFDI key, e.g. G03. |
email |
string |
|
phone |
string |
10 to 15 digits. |
issuer requerido |
string |
Id of the issuer the call acts for, from list_issuers. |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"rfc": {
"type": "string"
},
"nombre": {
"type": "string",
"description": "Name as in the Constancia fiscal."
},
"domicilio_fiscal": {
"type": "string",
"description": "Postal code (5 digits)."
},
"regimen_fiscal": {
"type": "string",
"description": "SAT c_RegimenFiscal key."
},
"uso_cfdi": {
"type": "string",
"description": "SAT c_UsoCFDI key, e.g. G03."
},
"email": {
"type": "string"
},
"phone": {
"type": "string",
"description": "10 to 15 digits."
},
"issuer": {
"type": "string",
"format": "uuid",
"description": "Id of the issuer the call acts for, from list_issuers."
}
},
"required": [
"rfc",
"nombre",
"domicilio_fiscal",
"regimen_fiscal",
"uso_cfdi",
"issuer"
]
}
list_receivers Listar receptores
Permiso: invoices:read
List the calling issuer's saved receivers ordered by name, with their ready-to-use receptor node. search matches the RFC or name (case and accent insensitive).
| Argumento | Tipo | Descripción |
|---|---|---|
search |
string |
|
limit |
integer |
|
offset |
integer |
|
issuer requerido |
string |
Id of the issuer the call acts for, from list_issuers. |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"search": {
"type": "string"
},
"limit": {
"type": "integer",
"minimum": 1,
"maximum": 100,
"default": 20
},
"offset": {
"type": "integer",
"minimum": 0,
"default": 0
},
"issuer": {
"type": "string",
"format": "uuid",
"description": "Id of the issuer the call acts for, from list_issuers."
}
},
"required": [
"issuer"
]
}
get_receiver Consultar receptor
Permiso: invoices:read
Return one saved receiver of the calling issuer, with its receptor node.
| Argumento | Tipo | Descripción |
|---|---|---|
receiver_id requerido |
string |
|
issuer requerido |
string |
Id of the issuer the call acts for, from list_issuers. |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"receiver_id": {
"type": "string"
},
"issuer": {
"type": "string",
"format": "uuid",
"description": "Id of the issuer the call acts for, from list_issuers."
}
},
"required": [
"receiver_id",
"issuer"
]
}
delete_receiver Eliminar receptor
Permiso: invoices:write
Delete a saved receiver from the calling issuer's directory. Invoices are untouched.
| Argumento | Tipo | Descripción |
|---|---|---|
receiver_id requerido |
string |
|
issuer requerido |
string |
Id of the issuer the call acts for, from list_issuers. |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"receiver_id": {
"type": "string"
},
"issuer": {
"type": "string",
"format": "uuid",
"description": "Id of the issuer the call acts for, from list_issuers."
}
},
"required": [
"receiver_id",
"issuer"
]
}
list_cfdi Listar facturas
Permiso: invoices:read
List the calling issuer's invoice summaries, newest first. Optionally filter by status and by tipo_de_comprobante (I invoices, E credit notes, P payment complements), by direction (issued by default; received lists the CFDIs other parties issued to the issuer, downloaded from the SAT; all lists both) and by origin (cefidia or sat). Every invoice carries its direction and origin.
| Argumento | Tipo | Descripción |
|---|---|---|
direction |
string |
issued (default): the issuer's own CFDIs; received: CFDIs issued to it by others; all: both. Valores: issued, received, all |
origin |
string |
cefidia: created here; sat: downloaded from the SAT. Every origin when omitted. Valores: cefidia, sat |
status |
string |
Filter by invoice status; every status when omitted. Valores: draft, signed, canceled |
tipo_de_comprobante |
string |
Filter by document type: I invoices, E credit notes, P payment complements. Valores: I, E, P |
limit |
integer |
Maximum number of invoices to return (default 50, max 100). |
issuer requerido |
string |
Id of the issuer the call acts for, from list_issuers. |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"direction": {
"type": "string",
"enum": [
"issued",
"received",
"all"
],
"description": "issued (default): the issuer's own CFDIs; received: CFDIs issued to it by others; all: both."
},
"origin": {
"type": "string",
"enum": [
"cefidia",
"sat"
],
"description": "cefidia: created here; sat: downloaded from the SAT. Every origin when omitted."
},
"status": {
"type": "string",
"enum": [
"draft",
"signed",
"canceled"
],
"description": "Filter by invoice status; every status when omitted."
},
"tipo_de_comprobante": {
"type": "string",
"enum": [
"I",
"E",
"P"
],
"description": "Filter by document type: I invoices, E credit notes, P payment complements."
},
"limit": {
"type": "integer",
"description": "Maximum number of invoices to return (default 50, max 100)."
},
"issuer": {
"type": "string",
"format": "uuid",
"description": "Id of the issuer the call acts for, from list_issuers."
}
},
"required": [
"issuer"
]
}
list_cfdi_template List CFDI template
Permiso: invoices:read
List the CFDI templates the issuer sees: the global templates, which every issuer sees, and the issuer's own scoped templates. scope narrows the list to global, issuer or all (the default). Each template carries its note, which says what a draft made from it still needs. A scope outside those three is invalid_argument.
| Argumento | Tipo | Descripción |
|---|---|---|
scope |
string |
Which templates to list. Defaults to all. Valores: global, issuer, all |
issuer requerido |
string |
Id of the issuer the call acts for, from list_issuers. |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"scope": {
"type": "string",
"enum": [
"global",
"issuer",
"all"
],
"description": "Which templates to list. Defaults to all."
},
"issuer": {
"type": "string",
"format": "uuid",
"description": "Id of the issuer the call acts for, from list_issuers."
}
},
"required": [
"issuer"
]
}
get_cfdi_template Get CFDI template
Permiso: invoices:read
Get one CFDI template the issuer can see, global or scoped. The result has the template's name, note, scope, issuer_id (null for a global template), cfdi and timestamps. Another issuer's scoped template is not_found.
| Argumento | Tipo | Descripción |
|---|---|---|
template_id requerido |
string |
Id of the template, from list_cfdi_template. |
issuer requerido |
string |
Id of the issuer the call acts for, from list_issuers. |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"template_id": {
"type": "string",
"description": "Id of the template, from list_cfdi_template."
},
"issuer": {
"type": "string",
"format": "uuid",
"description": "Id of the issuer the call acts for, from list_issuers."
}
},
"required": [
"template_id",
"issuer"
]
}
create_cfdi_template Create CFDI template
Permiso: invoices:write
Save a new scoped template of the issuer. Without from_template_id, note and cfdi are required. With from_template_id, the new template starts as a copy of that template's cfdi and note, and a note or cfdi given here replaces that field whole. cfdi must contain TipoDeComprobante, which is I, E or P, and a blank note is refused. The rest of the CFDI is checked when a draft made from the template is validated. The result is the template. A from_template_id the issuer cannot see is not_found.
| Argumento | Tipo | Descripción |
|---|---|---|
name requerido |
string |
Name of the template. |
note |
string |
What a draft made from the template still needs before it can be signed. |
cfdi |
object |
The partial CFDI document as a JSON object. |
from_template_id |
string |
Id of a template to copy the cfdi and note from. |
issuer requerido |
string |
Id of the issuer the call acts for, from list_issuers. |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Name of the template."
},
"note": {
"type": "string",
"description": "What a draft made from the template still needs before it can be signed."
},
"cfdi": {
"type": "object",
"description": "The partial CFDI document as a JSON object."
},
"from_template_id": {
"type": "string",
"description": "Id of a template to copy the cfdi and note from."
},
"issuer": {
"type": "string",
"format": "uuid",
"description": "Id of the issuer the call acts for, from list_issuers."
}
},
"required": [
"name",
"issuer"
]
}
replace_cfdi_template Replace CFDI template
Permiso: invoices:write
Replace the whole body of a scoped template of the issuer: its cfdi, and its name and note when given. An omitted note keeps the current one. A global template is invalid_state, since global templates are read-only. Drafts made from the template are not changed. The result is the template.
| Argumento | Tipo | Descripción |
|---|---|---|
template_id requerido |
string |
Id of the template, from list_cfdi_template. |
cfdi requerido |
object |
The partial CFDI document as a JSON object. |
name |
string |
New name of the template. |
note |
string |
New note of the template. |
issuer requerido |
string |
Id of the issuer the call acts for, from list_issuers. |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"template_id": {
"type": "string",
"description": "Id of the template, from list_cfdi_template."
},
"cfdi": {
"type": "object",
"description": "The partial CFDI document as a JSON object."
},
"name": {
"type": "string",
"description": "New name of the template."
},
"note": {
"type": "string",
"description": "New note of the template."
},
"issuer": {
"type": "string",
"format": "uuid",
"description": "Id of the issuer the call acts for, from list_issuers."
}
},
"required": [
"template_id",
"cfdi",
"issuer"
]
}
patch_cfdi_template Patch CFDI template
Permiso: invoices:write
Patch a scoped template of the issuer: an RFC 6902 JSON Patch applied to a copy of its cfdi, and its name and note when given. patch is an array of at most 100 operations (add, remove, replace, move, copy, test), applied in order. Paths are JSON Pointers from the CFDI root, for example /Conceptos/0/Cantidad. At least one of patch, name and note is required. The save checks run on the result: TipoDeComprobante must stay I, E or P, a blank note is refused, and the cfdi may not contain Version, Emisor, LugarExpedicion or Fecha. A patch that does not apply (a missing path, an unknown operation, a failed test, or more than 100 operations) answers invalid_argument with op_index, path and reason. Nothing is written on any failure. A global template is invalid_state, since global templates are read-only. Drafts made from the template are not changed. The result is the template.
| Argumento | Tipo | Descripción |
|---|---|---|
template_id requerido |
string |
Id of the template, from list_cfdi_template. |
patch |
object[] |
RFC 6902 operations, applied in order. add, replace and test take a value; move and copy take a from. |
name |
string |
New name of the template. |
note |
string |
New note of the template. |
issuer requerido |
string |
Id of the issuer the call acts for, from list_issuers. |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"template_id": {
"type": "string",
"description": "Id of the template, from list_cfdi_template."
},
"patch": {
"type": "array",
"maxItems": 100,
"description": "RFC 6902 operations, applied in order. add, replace and test take a value; move and copy take a from.",
"items": {
"type": "object",
"properties": {
"op": {
"type": "string",
"enum": [
"add",
"remove",
"replace",
"move",
"copy",
"test"
]
},
"path": {
"type": "string",
"description": "A JSON Pointer from the CFDI root."
},
"from": {
"type": "string",
"description": "The source JSON Pointer of move and copy."
},
"value": {
"description": "The value of add, replace and test."
}
},
"required": [
"op",
"path"
]
}
},
"name": {
"type": "string",
"description": "New name of the template."
},
"note": {
"type": "string",
"description": "New note of the template."
},
"issuer": {
"type": "string",
"format": "uuid",
"description": "Id of the issuer the call acts for, from list_issuers."
}
},
"required": [
"template_id",
"issuer"
]
}
delete_cfdi_template Delete CFDI template
Permiso: invoices:write
Permanently delete a scoped template of the issuer. Drafts made from it are not changed. A global template is invalid_state, since global templates are read-only. The result is deleted and template_id.
| Argumento | Tipo | Descripción |
|---|---|---|
template_id requerido |
string |
Id of the template, from list_cfdi_template. |
issuer requerido |
string |
Id of the issuer the call acts for, from list_issuers. |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"template_id": {
"type": "string",
"description": "Id of the template, from list_cfdi_template."
},
"issuer": {
"type": "string",
"format": "uuid",
"description": "Id of the issuer the call acts for, from list_issuers."
}
},
"required": [
"template_id",
"issuer"
]
}
Productos
El catálogo de productos del emisor.
list_products Listar productos
Permiso: products:read
List the calling issuer's registered products.
| Argumento | Tipo | Descripción |
|---|---|---|
issuer requerido |
string |
Id of the issuer the call acts for, from list_issuers. |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"issuer": {
"type": "string",
"format": "uuid",
"description": "Id of the issuer the call acts for, from list_issuers."
}
},
"additionalProperties": false,
"required": [
"issuer"
]
}
register_product Registrar producto
Permiso: products:write
Register a new product in the calling issuer's catalog. Each tax in impuestos must already be in the issuer's tax catalog: add it with add_tax first.
| Argumento | Tipo | Descripción |
|---|---|---|
name requerido |
string |
|
unit_price requerido |
string |
Decimal string, e.g. '199.00' |
clave_prod_serv requerido |
string |
SAT c_ClaveProdServ code |
clave_unidad requerido |
string |
SAT c_ClaveUnidad code |
description |
string |
|
impuestos |
object[] |
The taxes the product carries. Omit or pass [] for a product without taxes. Each entry must already be in the issuer's tax catalog (add it with add_tax; the keys are listed by list_tax_presets). Each entry is one traslado or retencion, for example IVA 16%: {"tipo": "traslado", "impuesto": "002", "tipo_factor": "Tasa", "tasa_o_cuota": "0.160000"}. Exento entries take tasa_o_cuota null. ISR (001) is only a retencion; Cuota is only for IEPS (003). |
issuer requerido |
string |
Id of the issuer the call acts for, from list_issuers. |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"name": {
"type": "string"
},
"unit_price": {
"type": "string",
"description": "Decimal string, e.g. '199.00'"
},
"clave_prod_serv": {
"type": "string",
"description": "SAT c_ClaveProdServ code"
},
"clave_unidad": {
"type": "string",
"description": "SAT c_ClaveUnidad code"
},
"description": {
"type": "string"
},
"impuestos": {
"type": "array",
"description": "The taxes the product carries. Omit or pass [] for a product without taxes. Each entry must already be in the issuer's tax catalog (add it with add_tax; the keys are listed by list_tax_presets). Each entry is one traslado or retencion, for example IVA 16%: {\"tipo\": \"traslado\", \"impuesto\": \"002\", \"tipo_factor\": \"Tasa\", \"tasa_o_cuota\": \"0.160000\"}. Exento entries take tasa_o_cuota null. ISR (001) is only a retencion; Cuota is only for IEPS (003).",
"items": {
"type": "object",
"properties": {
"tipo": {
"type": "string",
"enum": [
"traslado",
"retencion"
]
},
"impuesto": {
"type": "string",
"enum": [
"001",
"002",
"003"
]
},
"tipo_factor": {
"type": "string",
"enum": [
"Tasa",
"Cuota",
"Exento"
]
},
"tasa_o_cuota": {
"type": [
"string",
"null"
],
"description": "Decimal string with at most 6 decimals, e.g. '0.160000'; null for Exento."
}
},
"required": [
"tipo",
"impuesto",
"tipo_factor",
"tasa_o_cuota"
],
"additionalProperties": false
}
},
"issuer": {
"type": "string",
"format": "uuid",
"description": "Id of the issuer the call acts for, from list_issuers."
}
},
"required": [
"name",
"unit_price",
"clave_prod_serv",
"clave_unidad",
"issuer"
]
}
get_product Consultar producto
Permiso: products:read
Return one product of the calling issuer's catalog.
| Argumento | Tipo | Descripción |
|---|---|---|
product_id requerido |
string |
|
issuer requerido |
string |
Id of the issuer the call acts for, from list_issuers. |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"product_id": {
"type": "string"
},
"issuer": {
"type": "string",
"format": "uuid",
"description": "Id of the issuer the call acts for, from list_issuers."
}
},
"required": [
"product_id",
"issuer"
]
}
update_product Actualizar producto
Permiso: products:write
Replace every field of a product in the calling issuer's catalog, with the same fields as register_product. impuestos replaces the product's taxes too: omit it or pass [] to clear them. Each tax in impuestos must already be in the issuer's tax catalog: add it with add_tax first.
| Argumento | Tipo | Descripción |
|---|---|---|
product_id requerido |
string |
|
name requerido |
string |
|
unit_price requerido |
string |
Decimal string, e.g. '199.00' |
clave_prod_serv requerido |
string |
SAT c_ClaveProdServ code |
clave_unidad requerido |
string |
SAT c_ClaveUnidad code |
description |
string |
|
impuestos |
object[] |
The taxes the product carries. Omit or pass [] for a product without taxes. Each entry must already be in the issuer's tax catalog (add it with add_tax; the keys are listed by list_tax_presets). Each entry is one traslado or retencion, for example IVA 16%: {"tipo": "traslado", "impuesto": "002", "tipo_factor": "Tasa", "tasa_o_cuota": "0.160000"}. Exento entries take tasa_o_cuota null. ISR (001) is only a retencion; Cuota is only for IEPS (003). |
issuer requerido |
string |
Id of the issuer the call acts for, from list_issuers. |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"product_id": {
"type": "string"
},
"name": {
"type": "string"
},
"unit_price": {
"type": "string",
"description": "Decimal string, e.g. '199.00'"
},
"clave_prod_serv": {
"type": "string",
"description": "SAT c_ClaveProdServ code"
},
"clave_unidad": {
"type": "string",
"description": "SAT c_ClaveUnidad code"
},
"description": {
"type": "string"
},
"impuestos": {
"type": "array",
"description": "The taxes the product carries. Omit or pass [] for a product without taxes. Each entry must already be in the issuer's tax catalog (add it with add_tax; the keys are listed by list_tax_presets). Each entry is one traslado or retencion, for example IVA 16%: {\"tipo\": \"traslado\", \"impuesto\": \"002\", \"tipo_factor\": \"Tasa\", \"tasa_o_cuota\": \"0.160000\"}. Exento entries take tasa_o_cuota null. ISR (001) is only a retencion; Cuota is only for IEPS (003).",
"items": {
"type": "object",
"properties": {
"tipo": {
"type": "string",
"enum": [
"traslado",
"retencion"
]
},
"impuesto": {
"type": "string",
"enum": [
"001",
"002",
"003"
]
},
"tipo_factor": {
"type": "string",
"enum": [
"Tasa",
"Cuota",
"Exento"
]
},
"tasa_o_cuota": {
"type": [
"string",
"null"
],
"description": "Decimal string with at most 6 decimals, e.g. '0.160000'; null for Exento."
}
},
"required": [
"tipo",
"impuesto",
"tipo_factor",
"tasa_o_cuota"
],
"additionalProperties": false
}
},
"issuer": {
"type": "string",
"format": "uuid",
"description": "Id of the issuer the call acts for, from list_issuers."
}
},
"required": [
"product_id",
"name",
"unit_price",
"clave_prod_serv",
"clave_unidad",
"issuer"
]
}
delete_product Eliminar producto
Permiso: products:write
Delete a product from the calling issuer's catalog. Invoices are untouched.
| Argumento | Tipo | Descripción |
|---|---|---|
product_id requerido |
string |
|
issuer requerido |
string |
Id of the issuer the call acts for, from list_issuers. |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"product_id": {
"type": "string"
},
"issuer": {
"type": "string",
"format": "uuid",
"description": "Id of the issuer the call acts for, from list_issuers."
}
},
"required": [
"product_id",
"issuer"
]
}
list_tax_presets List tax presets
Permiso: products:read
List the global tax presets (IVA, retenciones and IEPS). Each key can be added to the calling issuer's tax catalog with add_tax.
Sin argumentos.
Esquema JSON de entrada
{
"type": "object",
"properties": {},
"additionalProperties": false
}
list_taxes List taxes
Permiso: products:read
List the calling issuer's tax catalog, the presets it added with add_tax. The impuestos of a product must be entries of this catalog.
| Argumento | Tipo | Descripción |
|---|---|---|
issuer requerido |
string |
Id of the issuer the call acts for, from list_issuers. |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"issuer": {
"type": "string",
"format": "uuid",
"description": "Id of the issuer the call acts for, from list_issuers."
}
},
"additionalProperties": false,
"required": [
"issuer"
]
}
add_tax Add tax
Permiso: products:write
Add a tax preset to the calling issuer's tax catalog. The preset is a key from list_tax_presets. Adding a preset the catalog already has returns that entry.
| Argumento | Tipo | Descripción |
|---|---|---|
preset requerido |
string |
Key of a preset from list_tax_presets, e.g. 'traslado:002:Tasa:0.160000'. |
issuer requerido |
string |
Id of the issuer the call acts for, from list_issuers. |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"preset": {
"type": "string",
"description": "Key of a preset from list_tax_presets, e.g. 'traslado:002:Tasa:0.160000'."
},
"issuer": {
"type": "string",
"format": "uuid",
"description": "Id of the issuer the call acts for, from list_issuers."
}
},
"required": [
"preset",
"issuer"
]
}
remove_tax Remove tax
Permiso: products:write
Remove a tax from the calling issuer's tax catalog. Refused while a product of the issuer carries it.
| Argumento | Tipo | Descripción |
|---|---|---|
tax_id requerido |
string |
|
issuer requerido |
string |
Id of the issuer the call acts for, from list_issuers. |
Esquema JSON de entrada
{
"type": "object",
"properties": {
"tax_id": {
"type": "string"
},
"issuer": {
"type": "string",
"format": "uuid",
"description": "Id of the issuer the call acts for, from list_issuers."
}
},
"required": [
"tax_id",
"issuer"
]
}