> ## Documentation Index
> Fetch the complete documentation index at: https://facturas-sdk.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Métodos directos de ARCA

> Usá WSFE, WSMTXCA y Padrón cuando necesites controlar el pedido o la numeración.

Para la emisión habitual usá `issue()`. Los métodos de esta página sirven
cuando tu aplicación ya reservó un número, necesita un campo de ARCA que
`issue()` no recibe o tiene que consultar directamente WSFE, WSMTXCA o
Padrón.

## Control manual de la numeración

Este bloque es
[examples/factura-b-consumidor-final.ts](https://github.com/LaPyme/facturas/blob/main/examples/factura-b-consumidor-final.ts):

```ts theme={null}
import { buildFacturaB, createArcaClient } from "facturas";
import {
  ARCA_CONCEPT_TYPES,
  ARCA_DOCUMENT_TYPES,
  ARCA_RECEIVER_VAT_CONDITIONS,
} from "facturas/constants";

const environment = process.env.ARCA_ENVIRONMENT;
if (environment !== "test" && environment !== "production") {
  throw new Error("ARCA_ENVIRONMENT debe ser test o production");
}

const client = createArcaClient({
  taxId: process.env.ARCA_TAX_ID,
  certificatePem: process.env.ARCA_CERTIFICATE_PEM,
  privateKeyPem: process.env.ARCA_PRIVATE_KEY_PEM,
  environment,
});

async function main() {
  const data = buildFacturaB({
    salesPoint: 1,
    concept: ARCA_CONCEPT_TYPES.PRODUCTOS,
    documentType: ARCA_DOCUMENT_TYPES.CONSUMIDOR_FINAL,
    documentNumber: 0,
    receiverVatConditionId: ARCA_RECEIVER_VAT_CONDITIONS.CONSUMIDOR_FINAL,
    voucherDate: "2026-09-02",
    taxableAmount: 10_000,
    vatRate: 21,
  });

  // Reservá el número y emitilo una sola vez.
  const voucherNumber = await client.wsfe.getNextVoucherNumber({
    salesPoint: data.salesPoint,
    voucherType: data.voucherType,
  });
  const issued = await client.wsfe.issue({ voucherNumber, data });

  if (issued.kind === "authorized") {
    console.log(issued.cae, issued.caeExpiry, issued.voucherNumber);
  } else {
    console.error(issued.kind, issued);
  }
}

main().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});
```

`buildFacturaB()` deriva el tipo Factura B, el neto, el detalle de IVA, el
importe de IVA, los campos en cero y el total, sin aritmética fiscal de punto
flotante. `buildFacturaC()` arma aparte la forma de la Factura C con IVA cero.
Las dos funciones aceptan enteros en centavos de la moneda y soportan las ISO
`ARS` (la de por defecto) y `USD`. Factura B requiere un `taxableAmount`
positivo. Cuando `vatRate` es positivo, el importe tiene que producir al menos
un centavo de IVA después del redondeo. El IVA usa el criterio Round Half Even
documentado por ARCA, así que un medio centavo exacto se redondea al centavo
par.

Para una factura en USD, pasá el tipo de cambio como string decimal:

```ts theme={null}
const usdData = buildFacturaB({
  salesPoint: 1,
  concept: ARCA_CONCEPT_TYPES.PRODUCTOS,
  documentType: ARCA_DOCUMENT_TYPES.CONSUMIDOR_FINAL,
  documentNumber: 0,
  receiverVatConditionId: ARCA_RECEIVER_VAT_CONDITIONS.CONSUMIDOR_FINAL,
  voucherDate: "2026-09-02",
  taxableAmount: 10_000, // USD 100.00.
  vatRate: 21,
  currency: "USD",
  exchangeRate: "1095.500000",
});
```

## Métodos por servicio

### `client.wsfe`

Facturación electrónica WSFE. Los inputs usan nombres habituales en JS y el SDK los
mapea internamente a los campos SOAP de AFIP / ARCA.

* Los campos de fecha aceptan `YYYY-MM-DD` o `YYYYMMDD`.
* Armá facturas A/B/C desde afirmaciones explícitas con `client.issue()`.
* Emití facturas y notas de crédito con los métodos directos de WSFE.
* `issue({ voucherNumber, data })` manda un pedido de autorización y devuelve
  evidencia `authorized`, `rejected` o `indeterminate`.
* `getNextVoucherNumber({ salesPoint, voucherType })` lee el próximo número a
  reservar.
* `getVoucherInfo({ number, salesPoint, voucherType })` devuelve el detalle del
  comprobante o `null`.
* Consultá números y detalles de comprobantes.
* Leé los catálogos de ARCA con métodos como `getVoucherTypes()` y
  `getVatRates()`. Hay métodos de catálogo disponibles para datos de referencia
  en vivo cuando no querés valores fijos en el código.
* Verificá el estado del servidor con `getServerStatus()`.
* Los métodos autenticados aceptan `forceRefresh: true` para descartar el TA
  WSAA cacheado y pedir un Token Authorization nuevo para el mismo servicio.

### `client.padron`

* `getTaxpayerDetails(taxId)` devuelve los datos del contribuyente o `null`.
* `getTaxIdByDocument(documentNumber)` resuelve CUIT candidatos a partir de un
  número de documento, o `null`.

El manejo de "no encontrado" en Padrón depende hoy del texto del mensaje del
SOAP fault de ARCA, así que es más frágil que los flujos de WSFE basados en
códigos.

### `client.wsmtxca`

* `issue({ data })`
* `getLastAuthorizedVoucher({ voucherType, salesPoint })`
* `getVoucher({ voucherType, salesPoint, voucherNumber })`
* Los métodos autenticados aceptan `forceRefresh: true` para renovar el TA WSAA
  de WSMTXCA antes de la llamada.

`client.issue()` también emite por WSMTXCA, con detalle de ítems, cuando pasás
`{ service: "wsmtxca" }`. La guía de [WSMTXCA](/guides/wsmtxca) explica ese
flujo. Para armar el request completo, llamá directamente a `issue`,
`getLastAuthorizedVoucher`, `lookupVoucher`, `getVoucher` o `getSalesPoints`.

## Emitir un pedido armado por tu aplicación

`client.issue()` deriva el pedido de WSFE, reserva el número y recupera
después de una caída por vos. Cuando necesitás algo que no deriva (una nota en
otra moneda o a otro receptor, o cualquier campo fuera de la
[entrada de `issue()`](/guides/invoices#datos-de-la-factura)) o la
numeración es de tu aplicación, usá `client.wsfe.issue(...)`. Este método
manda un FECAESolicitar para un número de comprobante que reservaste vos de
forma persistente. Devuelve si ese intento quedó autorizado, rechazado o
indeterminado. Preserva cada error y observación estructurados con su servicio,
operación, código, origen y nivel de resultado.

```ts theme={null}
const outcome = await client.wsfe.issue({
  voucherNumber: reservedVoucherNumber,
  data,
});

if (outcome.kind === "authorized") {
  console.log(outcome.cae, outcome.voucherNumber);
} else if (outcome.kind === "rejected") {
  console.error(outcome.errors, outcome.observations);
} else {
  if (outcome.reason === "authentication_rejected") {
    console.error(outcome.authentication?.reason);
  }
  // Consultá el mismo número antes de volver a intentar una autorización.
  const lookup = await client.wsfe.lookupVoucher({
    number: reservedVoucherNumber,
    salesPoint: data.salesPoint,
    voucherType: data.voucherType,
  });
  console.log(lookup.kind);
}
```

`wsfe.issue()` y `wsmtxca.issue()` fuerzan un único intento de transporte SOAP,
incluso cuando el cliente tiene configurados reintentos generales de
transporte. Nunca refrescan credenciales ni reenvían de forma automática. Un
rechazo de autenticación explícito del proveedor vuelve como
`reason: "authentication_rejected"` con evidencia tipada y segura en
`authentication`. Un timeout, una falla de conexión, una respuesta inválida o
un resultado incompleto o contradictorio quedan indeterminados y sin reenvío.
Así se evita que un trabajo fiscal incierto provoque una segunda autorización
oculta.

Las operaciones autenticadas de lectura, catálogo y consulta pueden repetirse
una vez con un refresco forzado de credenciales después de un rechazo de
autenticación explícito y tipado. Pasar `forceRefresh: true` desactiva
cualquier otro intento de recuperación de autenticación.

La ausencia en las consultas directas depende de la operación:

* WSFE `FECompConsultar` código 602 devuelve `not_found`.
* WSFE `FEParamGetPtosVenta` código 602 devuelve una lista vacía: ARCA responde así
  cuando el contribuyente no tiene puntos de venta para web services.
* WSMTXCA `consultarComprobante` código 1503 devuelve `not_found`.
* WSMTXCA `consultarUltimoComprobanteAutorizado` código 1502 devuelve el número
  de comprobante `0`.
* El código 602 de WSMTXCA no es ausencia de comprobante exacto y sigue siendo
  un error.

El SDK normaliza solamente la evidencia de protocolo del proveedor. Tu
aplicación sigue siendo responsable de guardar el pedido enviado, de ser
dueña de su secuencia o carril, y de decidir cuándo un reintento es seguro.

Para los campos fiscales que `issue()` no recibe, usá `WsfeVoucherInput`.
También soporta exenciones, importes no gravados y varias alícuotas de IVA. Sus
importes son números en unidades
mayores, se validan localmente y se serializan como strings canónicos de dos
decimales:

```ts theme={null}
import type { WsfeVoucherInput } from "facturas/wsfe";
import {
  ARCA_CONCEPT_TYPES,
  ARCA_CURRENCY_IDS,
  ARCA_DOCUMENT_TYPES,
  ARCA_RECEIVER_VAT_CONDITIONS,
  ARCA_VAT_RATES,
  ARCA_VOUCHER_TYPES,
} from "facturas/constants";

const data: WsfeVoucherInput = {
  salesPoint: 1,
  voucherType: ARCA_VOUCHER_TYPES.FACTURA_B,
  concept: ARCA_CONCEPT_TYPES.PRODUCTOS,
  documentType: ARCA_DOCUMENT_TYPES.CONSUMIDOR_FINAL,
  documentNumber: 0,
  receiverVatConditionId: ARCA_RECEIVER_VAT_CONDITIONS.CONSUMIDOR_FINAL,
  voucherDate: "2026-09-02",
  totalAmount: 121,
  nonTaxableAmount: 0,
  netAmount: 100,
  exemptAmount: 0,
  taxAmount: 0,
  vatAmount: 21,
  currencyId: ARCA_CURRENCY_IDS.ARS,
  exchangeRate: "1",
  vatRates: [{ id: ARCA_VAT_RATES.IVA_21, baseAmount: 100, amount: 21 }],
};
```

## Importes y monedas

`client.issue()`, `buildFacturaB()` y `buildFacturaC()` reciben enteros en
centavos y monedas ISO `ARS` o `USD`. `WsfeVoucherInput` usa valores decimales
en unidades mayores e identificadores de ARCA como `PES` y `DOL`.
