> ## Documentation Index
> Fetch the complete documentation index at: https://docs.artu.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Evidence

> Upload and manage supporting evidence for transactions

Evidence records store supporting files and records — receipts, statements, screenshots, scanned documents, contracts — that substantiate transactions. Evidence attaches to **transactions** (whereas [documents](/guides/documents) attach to clients), and supports the same lifecycle: upload → submit → officer verify/reject, plus OCR field extraction.

## Creating Evidence Records

Evidence is created in two steps: create the record, then upload the file. The high-level `upload` helper combines both.

```typescript theme={null}
// Low-level: create a record, get presigned URL, upload, confirm
const { evidence, upload } = await sdk.evidence.create({
  scope: "MX",
  type: "contrato_compraventa",
  contentType: "application/pdf",
  transactionIds: ["txn_abc123"],
});

await fetch(upload.url, {
  method: "PUT",
  body: fileBlob,
  headers: { "Content-Type": "application/pdf" },
});

await sdk.evidence.confirmUpload({
  id: evidence.id,
  filename: "contrato.pdf",
  contentType: "application/pdf",
  size: fileBlob.size,
});

console.log(evidence.id);
console.log(evidence.status); // "pending_upload"
```

```typescript theme={null}
// High-level helper: create + upload + confirm in one call
const evidence = await sdk.evidence.upload(file, {
  scope: "MX",
  type: "contrato_compraventa",
  transactionIds: ["txn_abc123"],
}, {
  onProgress: (progress) => console.log(`${Math.round(progress * 100)}%`),
  signal: abortController.signal,
});
```

### Retry a Failed Upload

If the storage PUT step fails but the record was already created:

```typescript theme={null}
const evidence = await sdk.evidence.retryUpload("evid_xyz789", file);
```

## Retrieving Evidence

```typescript theme={null}
const evidence = await sdk.evidence.retrieve("evid_xyz789");

console.log(evidence.id);
console.log(evidence.type);
console.log(evidence.status);
console.log(evidence.isAvailable);
```

You can also look up evidence by metadata:

```typescript theme={null}
const evidence = await sdk.evidence.retrieveByMetadata("internalRef", "REF-001");
```

## Downloading Evidence

```typescript theme={null}
const { url, expiresAt } = await sdk.evidence.getDownloadUrl("evid_xyz789");
```

## Updating Evidence

```typescript theme={null}
const updated = await sdk.evidence.update("evid_xyz789", {
  metadata: {
    reviewedBy: "admin@example.com",
  },
});
```

## Review Lifecycle

Evidence follows the same review lifecycle as documents — submit an uploaded record for officer review, then verify or reject it.

```typescript theme={null}
await sdk.evidence.submit("evid_xyz789");          // uploaded → pending_review
await sdk.evidence.verify("evid_xyz789");           // pending_review → verified
await sdk.evidence.reject("evid_xyz789", {          // pending_review → rejected
  reason: "Illegible scan",
});
```

## OCR Extraction

Extract structured fields from an evidence file via the OCR pipeline:

```typescript theme={null}
const result = await sdk.evidence.extract("evid_xyz789");
// Returns structured fields extracted from the evidence file
```

## Linking Evidence to Transactions

Evidence can be linked to transactions from either side. Use the evidence resource:

```typescript theme={null}
await sdk.evidence.linkTransaction({
  evidenceId: "evid_xyz789",
  transactionId: "txn_abc123",
});

await sdk.evidence.unlinkTransaction({
  evidenceId: "evid_xyz789",
  transactionId: "txn_abc123",
});

// Replace all transaction links at once
await sdk.evidence.setTransactions({
  evidenceId: "evid_xyz789",
  transactionIds: ["txn_abc123", "txn_def456"],
});
```

Or link from the transaction side:

```typescript theme={null}
await sdk.transactions.linkEvidence({
  transactionId: "txn_abc123",
  evidenceId: "evid_xyz789",
});

await sdk.transactions.unlinkEvidence({
  transactionId: "txn_abc123",
  evidenceId: "evid_xyz789",
});
```

## Listing Evidence

### All Evidence

```typescript theme={null}
const { data } = await sdk.evidence.list({
  limit: 50,
});
```

### For a Transaction

List all evidence linked to a transaction — from either resource:

```typescript theme={null}
const { data } = await sdk.evidence.listForTransaction("txn_abc123");

// Or from the transaction side
const { data: evidenceList } = await sdk.transactions.listEvidence("txn_abc123");
```

### Linked Transaction IDs

```typescript theme={null}
const transactionIds = await sdk.evidence.listLinkedTransactions("evid_xyz789");
```

### Async Iterator

```typescript theme={null}
for await (const evidence of sdk.evidence.iterate()) {
  console.log(evidence.id, evidence.type);
}
```

## Checking Evidence Existence

```typescript theme={null}
// Check if a transaction has at least one verified evidence of a given type
const hasCfdi = await sdk.evidence.hasEvidenceType(
  "txn_abc123",
  "factura_cfdi_4_0",
);

if (!hasCfdi) {
  console.log("Transaction is missing a CFDI");
}
```

## Counting Evidence

```typescript theme={null}
const count = await sdk.evidence.count({ type: "contrato_compraventa" });
console.log(`${count} matching evidence records`);
```

## Deleting Evidence

```typescript theme={null}
await sdk.evidence.delete("evid_xyz789");
```

## Batch Operations

Create or update multiple evidence records at once:

```typescript theme={null}
const result = await sdk.evidence.createMany([
  { scope: "MX", type: "contrato_compraventa", transactionIds: ["txn_abc123"] },
  { scope: "MX", type: "comprobante_pago", transactionIds: ["txn_abc123"] },
]);

const updated = await sdk.evidence.updateMany([
  { id: "evid_1", data: { metadata: { reviewed: true } } },
]);
```

## Upsert

Create or update evidence by your own external ID:

```typescript theme={null}
const result = await sdk.evidence.upsertByExternalId({
  externalId: "erp-evid-123",
  scope: "MX",
  type: "contrato_compraventa",
  transactionIds: ["txn_abc123"],
});
console.log(result.action); // "created" | "updated"

const batch = await sdk.evidence.upsertManyByExternalId([...items]);
```
