> ## 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.

# Handling Invoice Outcomes from arca.issue() in facturas

> Every call to arca.issue() returns one of four outcomes: authorized, rejected, indeterminate, or conflict. Learn what each means and how to handle it.

Every call to `arca.issue()` — and to `issueCreditNote()` and `issueDebitNote()` — resolves to a discriminated union. The union's `kind` field tells you exactly what happened and what you need to do next. Exhaustively handling all four outcomes is the correct pattern; TypeScript's type narrowing ensures you never accidentally treat a rejected voucher as authorized.

## The four outcomes

| `kind`          | Meaning                                                                                   | Required action                                                                                                                                                                                                        |
| --------------- | ----------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `authorized`    | ARCA authorized the voucher and returned a CAE.                                           | Save the voucher and CAE to your database. `recoveredByMatch: true` means the stored input matched the consulted identity — it proves consistency, not authorship.                                                     |
| `rejected`      | ARCA rejected the request.                                                                | Review the `issues` array returned by ARCA. The idempotency key remains permanently bound to its input even after rejection — fix the input and use a new key for the corrected attempt.                               |
| `indeterminate` | The outcome could not be determined (network error, timeout, or ambiguous ARCA response). | Preserve the voucher number and all available evidence. Do not issue a new voucher for the same sale. Reconcile by calling `recover()` or by retrying `issue()` with the identical input and the same idempotency key. |
| `conflict`      | A different voucher already occupies the reserved number.                                 | Stop the flow immediately and investigate. Do not retry automatically.                                                                                                                                                 |

## Handling outcomes in TypeScript

```ts twoslash theme={null}
import { createArcaClient, createPostgresStore } from "facturas";
import { sql } from "@vercel/postgres";

const arca = createArcaClient({
  store: createPostgresStore({ query: (text, params) => sql.query(text, params) }),
});

const venta = { id: "sale-abc-123", totalEnCentavos: 150_000 };

const factura = await arca.issue(
  {
    issuer: "monotributo",
    salesPoint: 3,
    to: { condition: "consumidor_final" },
    items: [{ amount: venta.totalEnCentavos }],
  },
  { idempotencyKey: venta.id },
);

switch (factura.kind) {
  case "authorized":
    // factura.voucher contains the CAE, voucher number, amounts, and dates.
    await db.saveInvoice({
      saleId: venta.id,
      cae: factura.voucher.cae,
      voucherNumber: factura.voucher.number,
      amounts: factura.voucher.amounts,
    });
    break;

  case "rejected":
    // factura.issues is an array of ARCA fiscal issues with codes and messages.
    console.error("ARCA rejected the invoice:", factura.issues);
    await db.markSaleRejected(venta.id, factura.issues);
    break;

  case "indeterminate":
    // The number was reserved. Preserve it and reconcile later.
    console.error("Outcome unknown — preserve evidence:", {
      attempted: factura.attempted,
      lookup: factura.lookup,
    });
    await db.markSalePendingReconciliation(venta.id);
    break;

  case "conflict":
    // A different voucher occupies the reserved number. Requires investigation.
    console.error("Conflict — manual review required:", {
      attempted: factura.attempted,
      found: factura.found,
    });
    await alertOps(venta.id, factura);
    break;

  default:
    factura satisfies never;
}
```

## `authorized` — save the CAE

An `authorized` result contains `factura.voucher` with the full fiscal record:

* **`cae`** — the Código de Autorización Electrónica issued by ARCA
* **`number`** — the authorized voucher number
* **`amounts`** — `{ computedTotal, sentTotal, vatAdjustment }`, all in centavos
* **`caeExpirationDate`** — the CAE's expiration date

### `recoveredByMatch: true`

When `factura.recoveredByMatch` is `true`, `issue()` found the reserved number already authorized in ARCA and confirmed that the stored input matched the authorized voucher's identity. This proves **consistency** — the reservation and the ARCA record agree — but it does not prove authorship. It means `issue()` did not send a new authorization request; the voucher was authorized in a previous call.

<Tip>
  Treat `recoveredByMatch: true` the same as a fresh authorization: save the voucher and CAE just as you would for any `authorized` result.
</Tip>

## `rejected` — review ARCA's issues

A `rejected` result means ARCA received and processed the request but declined to authorize the voucher. The `issues` array contains the fiscal error codes and messages from ARCA.

Common causes include an invalid recipient condition for the issuer class, a mismatched VAT rate, a sales point not enabled for your CUIT, or an exceeded identification threshold with no document provided.

<Note>
  After a rejection, the idempotency key remains permanently bound to the input that was rejected. To retry with a corrected input, use a **new idempotency key**. Reusing the same key with a different input throws `ARCA_INPUT_IDEMPOTENCY_MISMATCH`.
</Note>

## `indeterminate` — preserve and reconcile

An `indeterminate` result means `issue()` could not confirm whether ARCA authorized or rejected the voucher. This happens after a network timeout, an ambiguous SOAP response, or a process crash after the reservation was written but before a clear response was received.

The voucher number is reserved. Do not issue a new voucher for this sale.

<Tip>
  Retrying `issue()` with the identical input and the same idempotency key is safe. The SDK finds the existing reservation and consults the stored number. If ARCA confirms the number is authorized, you get an `authorized` result back. If ARCA confirms it is empty, you get another `indeterminate` with `lookup.kind === "not_found"` — and the retry is still safe.
</Tip>

`factura.attempted` contains the evidence from the failed attempt, and `factura.lookup` contains the result of any identity consultation performed. Both are useful for support and audit trails.

## `conflict` — stop and investigate

A `conflict` result means the voucher number that `issue()` reserved is already occupied by a different, authorized document in ARCA. This should not happen in normal operation.

<Warning>
  A `conflict` outcome requires **immediate manual investigation**. Do not retry automatically. Do not issue a new voucher for the same sale without first understanding why the conflict occurred. This may indicate a concurrent write from another process, a misconfigured sales point shared across environments, or a store inconsistency.
</Warning>

`factura.attempted` describes what `issue()` tried to authorize. `factura.found` describes the voucher ARCA returned for the reserved number. Comparing them is the starting point for your investigation.
