El emisor es el CUIT que figura como vendedor en el comprobante. Cada emisor tiene un único punto de venta y un certificado, y recién emite cuando está verificado. Lo identificás por su CUIT: es lo que mandás en issuer_cuit al emitir.
Endpoints
| Método y ruta | Qué hace |
|---|---|
POST /v1/issuers | Crea un emisor. |
GET /v1/issuers | Lista los emisores, con filtros y paginación. |
GET /v1/issuers/:id | Devuelve un emisor. |
PUT /v1/issuers/:id | Modifica un emisor: datos, punto de venta, certificado o estado. |
DELETE /v1/issuers/:id | Borra un emisor. Sus comprobantes quedan. |
GET /v1/issuers/lookup?tax_id= | Devuelve los datos de la constancia de inscripción de un CUIT, para dar de alta el emisor. |
POST /v1/issuers/sales-points | Lista los puntos de venta de un CUIT en ARCA, con su clave fiscal. |
POST /v1/issuers/sales-points/create | Crea en ARCA un punto de venta de web services para un CUIT, con su clave fiscal. |
POST /v1/issuers/:id/certificate | Crea un certificado para el emisor y se lo asigna. Ver Certificados. |
POST /v1/issuers/:id/delegation | Autoriza en ARCA que el certificado de otro CUIT firme por el emisor. |
POST /v1/issuers/:id/verify | Verifica el emisor: emite una factura de $1 y su nota de crédito. Lo pasa a active. |
El emisor
{
"id": "0f8f3c2a-5b1e-4c7d-9a2e-6d4b8e1f2a3c",
"tax_id": "20111111112",
"business_name": "Emisor de prueba",
"address": "Av. Siempre Viva 742, CABA",
"vat_condition": 1,
"gross_income": "20111111112",
"activity_start_date": "2020-01-01",
"sales_point": 1,
"certificate_id": "c3a1e7d9-8b2f-4e6a-a1d4-5f7b9c0e2d31",
"status": "active",
"verified_at": "2026-10-14T14:03:00.000Z",
"created_at": "2026-10-14T14:00:00.000Z",
"updated_at": "2026-10-14T14:03:00.000Z"
}
| Campo | Descripción |
|---|---|
id | Identificador del emisor. Se usa en las rutas /v1/issuers/:id. |
tax_id | CUIT, 11 dígitos. Único por proyecto entre los emisores no borrados. Es el issuer_cuit al emitir. |
business_name | Razón social, impresa en el comprobante. |
address | Domicilio comercial, impreso en el comprobante. |
vat_condition | Condición frente al IVA. Define qué comprobantes puede emitir. Ver condiciones frente al IVA. |
gross_income | Número de ingresos brutos, impreso en el comprobante. |
activity_start_date | Inicio de actividades, YYYY-MM-DD, impreso en el comprobante. |
sales_point | Punto de venta por el que salen sus comprobantes, o null. Ver punto de venta. |
certificate_id | Certificado con el que firma, o null. Ver certificado. |
status | pending, active o inactive. Ver estados. |
verified_at | Cuándo se verificó, o null. |
Estados
| Estado | Qué significa |
|---|---|
pending | Recién creado. No emite. Pasa a active al verificarlo. |
active | Verificado. Emite. |
inactive | Pausado. No emite hasta que lo vuelvas a poner active. |
deleted | Borrado. No aparece en los listados ni en el detalle; sus comprobantes quedan. |
El pase a active es automático al verificar: no se puede setear a mano. PUT solo acepta status active o inactive, y solo si el emisor ya fue verificado alguna vez (verified_at).
Crear un emisor
POST /v1/issuers crea el emisor. Los datos fiscales se imprimen en cada comprobante, por eso son obligatorios. El punto de venta y el certificado podés darlos acá o después.
const response = await fetch('https://app.afipsdk.com/api/v1/issuers', {
method: 'POST',
headers: {
'Authorization': 'Bearer <ACCESS_TOKEN>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
tax_id: '20111111112',
business_name: 'Emisor de prueba',
address: 'Av. Siempre Viva 742, CABA',
vat_condition: 1,
gross_income: '20111111112',
activity_start_date: '2020-01-01',
sales_point: 1,
certificate_id: 'c3a1e7d9-8b2f-4e6a-a1d4-5f7b9c0e2d31'
})
});
const issuer = await response.json();
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
tax_id | string | Sí | CUIT válido, 11 dígitos sin guiones. No se puede cambiar después. |
business_name | string | Sí | Razón social. Hasta 200 caracteres. |
address | string | Sí | Domicilio. Hasta 300 caracteres. |
vat_condition | integer | Sí | Condición frente al IVA. |
gross_income | string | Sí | Número de ingresos brutos. Hasta 50 caracteres. |
activity_start_date | string | Sí | Inicio de actividades, YYYY-MM-DD. |
sales_point | integer | No | Punto de venta, de 1 a 99999. |
certificate_id | string | No | Un certificado activo. Ver Certificados. |
En los campos opcionales, null o "" equivale a no mandarlos.
Datos de la constancia de inscripción
Para no cargar los datos a mano, GET /v1/issuers/lookup?tax_id= devuelve lo que figura en la constancia de inscripción del CUIT en ARCA: razón social, domicilio fiscal, condición frente al IVA e inicio de actividades. No guarda nada: vos elegís qué mandar a POST /v1/issuers.
const response = await fetch('https://app.afipsdk.com/api/v1/issuers/lookup?tax_id=20111111112', {
headers: {
'Authorization': 'Bearer <ACCESS_TOKEN>'
}
});
const { issuer, unresolved } = await response.json();
{
"tax_id": "20111111112",
"synced_at": "2026-10-14T13:58:00.000Z",
"issuer": {
"business_name": "PEREZ JUAN",
"address": "AV SIEMPRE VIVA 742 - CIUDAD AUTONOMA BUENOS AIRES",
"vat_condition": 1,
"activity_start_date": "2020-01-01"
},
"unresolved": [],
"warnings": [],
"taxpayer": { "...": "el contribuyente según ARCA" },
"inscription_proof": { "...": "la constancia completa" }
}
unresolved lista los campos que no se pudieron resolver desde la constancia (business_name, address, vat_condition o activity_start_date); warnings avisa si el CUIT no está activo en ARCA. activity_start_date es el primer día del período de actividad más antiguo. El número de ingresos brutos y el punto de venta nunca salen de acá. La consulta es siempre al padrón real, también desde el sandbox.
Certificado
ARCA exige firmar cada comprobante con un certificado digital. El emisor firma con el certificado de certificate_id, mas detalles en Certificados.
Punto de venta
Cada emisor tiene un solo punto de venta (sales_point), por el que salen todos sus comprobantes.
Tiene que ser un punto de venta del CUIT habilitado en ARCA para facturación electrónica por web services. Si no sabés cuál es, podes listar los puntos de ventas con: POST /v1/issuers/sales-points.
const response = await fetch('https://app.afipsdk.com/api/v1/issuers/sales-points', {
method: 'POST',
headers: {
'Authorization': 'Bearer <ACCESS_TOKEN>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
tax_id: '20111111112',
username: '20111111112',
password: '<CLAVE_FISCAL>'
})
});
const { automation_id } = await response.json();
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
tax_id | string | Sí | CUIT del que se listan los puntos de venta. |
username | string | Sí | Usuario de ARCA (normalmente el mismo CUIT). |
password | string | Sí | Clave fiscal. No se guarda. |
Ver como obtener la respuesta de una Automatización
{
"id": "a9e2c4b6-1d3f-4a5b-8c7d-2e4f6a8b0c1d",
"status": "complete",
"data": {
"tax_id": "20111111112",
"sales_points": [
{ "number": 1, "system": "RECE1 - FACTURA ELECTRONICA - WEB SERVICES", "display_name": "Casa central", "address": "Av. Siempre Viva 742", "blocked": false, "deactivated": false },
{ "number": 3, "system": "RECE1 - FACTURA ELECTRONICA - WEB SERVICES", "display_name": "Depósito", "address": "Ruta 8 km 42", "blocked": true, "deactivated": false }
],
"next_number": 4
}
}
next_number es el número que tendría un punto de venta nuevo: uno más que el último de todos los del CUIT, sean de web services o no.
Elegí uno que no esté blocked ni deactivated (la lista ya trae solo los de web services), y asignalo al emisor con PUT /v1/issuers/:id:
{
"sales_point": 1
}
Si la clave fiscal es incorrecta, la automatización termina en error: GET /v1/automations/:id responde 400 con el motivo en data.message. En sandbox, password: "INVALID_PASSWORD" simula ese caso.
Crear un punto de venta
Si el CUIT no tiene un punto de venta de web services, o querés uno aparte para la API, POST /v1/issuers/sales-points/create lo da de alta en ARCA con la clave fiscal: para facturación electrónica por web services, con el número que sigue al último del CUIT y el sistema que corresponde a la condición frente al IVA del emisor. ARCA pide que el CUIT tenga un domicilio cargado; si no lo tiene, la automatización termina en error.
const response = await fetch('https://app.afipsdk.com/api/v1/issuers/sales-points/create', {
method: 'POST',
headers: {
'Authorization': 'Bearer <ACCESS_TOKEN>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
tax_id: '20111111112',
username: '20111111112',
password: '<CLAVE_FISCAL>',
vat_condition: 1
})
});
const { automation_id } = await response.json();
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
tax_id | string | Sí | CUIT para el que se crea. |
username | string | Sí | Usuario de ARCA (normalmente el mismo CUIT). |
password | string | Sí | Clave fiscal. No se guarda. |
vat_condition | integer | No | Condición frente al IVA del emisor, del mismo catálogo que vat_condition del emisor: elige el sistema de ARCA (responsable inscripto, monotributo o exento). Sin ella se pide el de responsable inscripto y, si ARCA no lo ofrece para el CUIT, el único de web services que ofrezca. |
number | integer | No | Número del punto de venta, de 1 a 99999. Por defecto, next_number. |
name | string | No | Nombre de fantasía con el que queda en ARCA, hasta 50 caracteres. Por defecto, Factura SDK. |
system | string | No | Sistema de ARCA, por código o por un fragmento de su nombre, para cuando ARCA ofrece más de uno de web services y hay que elegir. |
Ver como obtener la respuesta de una Automatización
{
"id": "b7c1d2e3-4f5a-4b6c-9d8e-1f2a3b4c5d6e",
"status": "complete",
"data": {
"tax_id": "20111111112",
"sales_point": { "number": 4, "display_name": "Factura SDK", "status": "created", "message": null }
}
}
status es created, o exists si ese número ya estaba dado de alta en ARCA, con el motivo en message.
Delegación
Si el CUIT emite comprobantes para otros usuarios se deben cumplir estos pasos:
- El emisor delega el web service de facturación electrónica (
wsfe) al CUIT dueño del certificado, desde su clave fiscal en ARCA: cómo delegar un web service. POST /v1/issuers/:id/delegationcon la clave fiscal del dueño del certificado (no la del emisor): Factura SDK acepta la delegación en ARCA y autoriza el certificado para facturar por el emisor.
Requiere que el emisor ya tenga en certificate_id ese certificado, active.
const response = await fetch('https://app.afipsdk.com/api/v1/issuers/<ISSUER_ID>/delegation', {
method: 'POST',
headers: {
'Authorization': 'Bearer <ACCESS_TOKEN>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
username: '30715000004',
password: '<CLAVE_FISCAL>'
})
});
const { automation_id } = await response.json();
Ver como obtener la respuesta de una Automatización
{
"id": "a9e2c4b6-1d3f-4a5b-8c7d-2e4f6a8b0c1d",
"status": "complete",
"data": {
"issuer_id": "0f8f3c2a-5b1e-4c7d-9a2e-6d4b8e1f2a3c",
"certificate_id": "c3a1e7d9-8b2f-4e6a-a1d4-5f7b9c0e2d31",
"delegation": "accepted",
"authorization": "created"
}
}
En el sandbox la delegación es simulada e instantánea; password: "INVALID_PASSWORD" simula una clave fiscal incorrecta.
Verificar un emisor
POST /v1/issuers/:id/verify comprueba que el emisor puede facturar. Factura SDK emite, con su certificado y su punto de venta, una factura de $1 a consumidor final y la nota de crédito que la anula. Si ARCA aprueba las dos, el emisor queda active.
Los dos comprobantes son reales: quedan registrados en ARCA a nombre del emisor y no cuentan para tu plan.
El emisor tiene que tener certificado y punto de venta; si falta alguno, la respuesta es 400.
const response = await fetch('https://app.afipsdk.com/api/v1/issuers/<ISSUER_ID>/verify', {
method: 'POST',
headers: {
'Authorization': 'Bearer <ACCESS_TOKEN>'
}
});
const { automation_id } = await response.json();
Ver como obtener la respuesta de una Automatización
{
"id": "a9e2c4b6-1d3f-4a5b-8c7d-2e4f6a8b0c1d",
"status": "complete",
"data": {
"verified": true,
"issuer": {
"id": "0f8f3c2a-5b1e-4c7d-9a2e-6d4b8e1f2a3c",
"tax_id": "20111111112",
"status": "active",
"verified_at": "2026-10-14T14:03:00.000Z"
},
"invoice": { "id": "…", "verification": true, "status": "approved", "invoice_type": 6, "sales_point": 1, "number": 1, "total_amount": 1, "cae": "76412345678901", "...": "..." },
"credit_note": { "id": "…", "verification": true, "status": "approved", "invoice_type": 8, "sales_point": 1, "number": 1, "total_amount": 1, "cae": "76412345678902", "...": "..." }
}
}
Si alguno de los dos no se aprueba, la automatización termina en error y GET /v1/automations/:id responde 400: step dice cuál falló (invoice o credit_note) y errors por qué.
{
"id": "a9e2c4b6-1d3f-4a5b-8c7d-2e4f6a8b0c1d",
"status": "error",
"data": {
"statusCode": 400,
"message": "La factura de verificación no fue aprobada: El numero o fecha del comprobante no se corresponde con el proximo a autorizar. Consultar metodo FECompUltimoAutorizado.",
"verified": false,
"step": "invoice",
"issuer": { "id": "0f8f3c2a-5b1e-4c7d-9a2e-6d4b8e1f2a3c", "tax_id": "20111111112", "status": "pending" },
"invoice": { "id": "…", "verification": true, "status": "rejected", "invoice_type": 6, "...": "..." },
"credit_note": null,
"errors": [
{ "code": "10016", "message": "El numero o fecha del comprobante no se corresponde con el proximo a autorizar. Consultar metodo FECompUltimoAutorizado." }
]
}
}
Las causas típicas son un punto de venta que no es de web services, un certificado que ARCA no tiene autorizado para wsfe, un certificado vencido, o una delegación sin aceptar. Cuando la causa es del certificado, errors[0].code lo dice:
code | Qué pasa | Qué hacer |
|---|---|---|
web_service_not_authorized | El certificado no está autorizado para wsfe en ARCA. | Autorizarlo con POST /v1/certificates/:id/authorize; si es de otro CUIT, la delegación. |
certificate_expired | ARCA lo rechazó como vencido; quedó expired. | Crear un certificado nuevo con POST /v1/issuers/:id/certificate. |
certificate_key_mismatch | La clave privada no corresponde al certificado. | Subirlo de nuevo con la clave correcta, o crear uno nuevo. |
certificate_untrusted | ARCA no reconoce el certificado como emitido por ella. | Crear un certificado nuevo en ARCA. |
certificate_invalid | ARCA no pudo leer el certificado. | Crear un certificado nuevo. |
Modificar un emisor
PUT /v1/issuers/:id cambia solo los campos que mandás. tax_id no se puede modificar: si cambió, creá otro emisor.
const response = await fetch('https://app.afipsdk.com/api/v1/issuers/<ISSUER_ID>', {
method: 'PUT',
headers: {
'Authorization': 'Bearer <ACCESS_TOKEN>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
address: 'Av. Siempre Viva 744, CABA',
sales_point: 2
})
});
const issuer = await response.json();
| Campo | Descripción |
|---|---|
business_name, address, vat_condition, gross_income, activity_start_date | Los datos fiscales. Los comprobantes ya emitidos no cambian: el PDF conserva los datos del momento de la aprobación. |
sales_point | El punto de venta. null lo borra; el emisor no emite hasta que tenga uno. |
certificate_id | Un certificado activo. null lo borra; el emisor no emite hasta que tenga uno. |
status | active o inactive, solo en un emisor ya verificado. |
Pausar y reactivar
Un emisor inactive no emite. Sirve para detener la facturación a un cliente sin borrarlo.
{
"status": "inactive"
}
Para reactivarlo, status: "active". No hace falta verificarlo de nuevo.
Borrar un emisor
DELETE /v1/issuers/:id responde 204. El emisor desaparece de la API y del dashboard; sus comprobantes quedan y se siguen pudiendo consultar y listar. El mismo CUIT se puede volver a dar de alta como un emisor nuevo, que arranca pending.
await fetch('https://app.afipsdk.com/api/v1/issuers/<ISSUER_ID>', {
method: 'DELETE',
headers: {
'Authorization': 'Bearer <ACCESS_TOKEN>'
}
});
Consultar y listar
GET /v1/issuers/:id devuelve un emisor; 404 si no existe o fue borrado.
GET /v1/issuers lista los emisores, nunca los borrados, con paginación por cursor.
| Parámetro | Tipo | Descripción |
|---|---|---|
tax_id | string | CUIT. |
certificate_id | string | Emisores que firman con ese certificado. |
status | string | pending, active o inactive. |
limit | integer | Cantidad por página: por defecto 10, hasta 100. Un valor fuera de rango se ajusta. |
cursor | string | El next_cursor de la página anterior, que es el id del último emisor de la página. |
const response = await fetch('https://app.afipsdk.com/api/v1/issuers?status=active&limit=50', {
headers: {
'Authorization': 'Bearer <ACCESS_TOKEN>'
}
});
const { data, next_cursor, total_count } = await response.json();
{
"data": [
{ "id": "0f8f3c2a-5b1e-4c7d-9a2e-6d4b8e1f2a3c", "tax_id": "20111111112", "status": "active", "...": "..." }
],
"next_cursor": null,
"total_count": 1
}
Errores
| HTTP | Cuándo |
|---|---|
400 | Errores de forma (data_errors); CUIT inválido; certificate_id inexistente o no active; status en un emisor sin verificar; tax_id en un PUT; verificación sin certificado, con uno vencido o revocado, sin punto de venta, o de un emisor que no emite por su condición frente al IVA; delegación sin certificado o con uno del propio CUIT; suscripción vencida o impaga; proyecto que no es de Factura SDK. |
401 | Access token inválido, ausente o revocado. |
404 | El emisor no existe o fue borrado. En el lookup, el CUIT no tiene constancia de inscripción. En GET /v1/automations/:id, la automatización no existe o es de otro proyecto. |
409 | Ya hay un emisor con ese CUIT. |
422, 502, 503 | Solo en el lookup: ARCA rechazó la consulta, falló, o la consulta no está disponible. |
El formato de cada código y cómo consultar una automatización están en Errores y respuestas.