DoConure

Composizione, firma e flusso in blocco

Componi molti documenti da un template, o manda in firma molte buste, con una sola richiesta. Un batch è accettato per intero o rifiutato per intero, gira in background, e rileggi il risultato di ogni elemento man mano che finisce. Si paga solo ciò che è stato consegnato.

Ogni documento è composto esattamente dal codice che compone una singola POST /api/v1/compose/documents/generate, così un documento in un batch è lo stesso documento che avresti avuto uno alla volta, allo stesso prezzo. Un batch di firma è uguale: ogni busta è creata e inviata dal codice dietro una singola POST /api/v1/sign/envelopes?send=true, con la stessa validazione, gli stessi predefiniti e filtri, gli stessi rifiuti e gli stessi codici di errore. Un batch non è mai un modo per aggirare una regola: quello che una singola chiamata rifiuterebbe, un batch lo rifiuta con lo stesso codice, e quello che costa una singola chiamata lo costa un elemento.

Le chiamate

ChiamataAmbitoCosa fa
POST /api/v1/bulk/composebulk:submit e documents:composeInvia un batch, in linea o con fileId. Risponde 202 con il job.
POST /api/v1/bulk/signbulk:submit e signatures:sesInvia un batch di buste da creare e inviare (firma in blocco). Risponde 202 con il job.
POST /api/v1/bulk/flowbulk:submit e flow:*Invia un batch di flussi: ogni elemento compone un documento e lo manda in firma (Document Fly in blocco). Risponde 202 con il job.
POST /api/v1/bulk/filesbulk:submitCarica un batch JSONL o CSV, ricevi un fileId. Risponde 201.
GET /api/v1/bulk/jobs/{id}bulk:readIl job: stato, conteggi, crediti e, quando è finito, la riconciliazione. Interroga questo.
GET /api/v1/bulk/jobs/{id}/itemsbulk:readIl risultato di ogni documento, in ordine, a pagine.
GET /api/v1/bulk/jobsbulk:readI job della tua organizzazione, dal più recente (status, limit fino a 100).
GET /api/v1/bulk/jobs/{id}/resultsbulk:read e documents:downloadIl pacchetto dei risultati: uno ZIP con ogni PDF prodotto, un manifesto e un results.csv.
POST /api/v1/bulk/jobs/{id}/cancelbulk:submitFerma un job.
POST /api/v1/bulk/jobs/{id}/retrybulk:submitRimette in lavoro gli elementi falliti da ritentare, come nuovi tentativi nello stesso job.

I documenti si scaricano con GET /api/v1/compose/documents/{id} (ambito documents:download); ogni elemento porta il suo documentId e downloadUrl. I batch di composizione richiedono che l'interruttore Composer Fly della tua organizzazione sia acceso e quelli di firma l'interruttore Signer Fly, come le singole chiamate; job e caricamento sono condivisi, così un cliente Signer Fly senza Composer Fly può firmare in blocco e leggere i propri job.

Ogni operazione in blocco è anche un acquisto a sé. Oltre al prodotto a cui appartiene (Composer Fly per /bulk/compose, Signer Fly per /bulk/sign, Document Fly per /bulk/flow), la tua organizzazione ha bisogno dell'opzione bulk corrispondente. Un'organizzazione che si è registrata da sola le ha tutte e tre fin dall'inizio, così puoi provare subito il bulk (usa "isTest": true, che è gratis); per un'organizzazione che abbiamo creato noi, la attiviamo noi. Senza, la chiamata risponde 403 FEATURE_NOT_ENABLED con details.feature uguale a bulkCompose, bulkSign o bulkFlow; non si riserva e non si addebita nulla. GET /api/v1/usage elenca quello che la tua organizzazione ha sotto organisation.entitlements.

Inviare un batch

POST /api/v1/bulk/compose
Authorization: Bearer lpdc_...
Idempotency-Key: month-end-2026-09

{
  "settings": { "templateId": "invoice-standard-8bc99b" },
  "items": [
    { "externalId": "inv-1001", "data": { "customer": { "name": "Acme Srl" }, "total": "1.240,00" } },
    { "externalId": "inv-1002", "data": { "customer": { "name": "Beta SpA" }, "total": "380,00" } }
  ],
  "options": { "maxItems": 500 }
}
  • settings è lo stesso oggetto che prende una singola chiamata e si applica a ogni elemento. Il data di ogni elemento è quello che manderesti come data a una singola chiamata.
  • externalId è il tuo riferimento per l'elemento. È facoltativo, e unico nel batch. Torna sull'elemento così puoi collegare i risultati ai tuoi record.
  • Manda o items o fileId, mai entrambi e mai nessuno dei due (BULK_INPUT_INVALID).
  • options.maxItems può abbassare il limite di elementi per questa richiesta, mai alzarlo. Un batch oltre il limite è rifiutato per intero, mai tagliato.
  • Le chiavi sconosciute in qualunque punto del corpo fuori dal data di un elemento sono rifiutate, come ovunque in questa API.

La risposta è 202 Accepted, con un header Location che punta al job. Le impostazioni tornano come stabilite, e il job sta in output.bulk:

202 Accepted
Location: /api/v1/bulk/jobs/6d1e...

{
  "settings": { "templateId": "invoice-standard-8bc99b", "...": "come stabilito" },
  "output": {
    "status": "pending",
    "bulk": {
      "jobId": "6d1e...",
      "operation": "compose",
      "status": "queued",
      "isTest": false,
      "templateId": "invoice-standard-8bc99b",
      "templateVersion": 3,
      "totalItems": 2,
      "counts": { "queued": 2, "processing": 0, "succeeded": 0, "failed": 0, "cancelled": 0 },
      "creditsReserved": 10,
      "creditsConsumed": 0,
      "creditsHeld": 10,
      "creditsReleased": 0,
      "links": { "self": "/api/v1/bulk/jobs/6d1e...", "items": "/api/v1/bulk/jobs/6d1e.../items" },
      "...": "createdAt, startedAt, completedAt, deadlineAt, resultsExpireAt, error"
    },
    "credits": { "used": 0, "left": 1237 },
    "warnings": [],
    "error": null
  }
}

output.bulk è la quarta chiave di output e compare solo nelle risposte sotto /api/v1/bulk. Le tre sezioni dei prodotti (compose, sign, flow) restano al loro posto e lì sono null.

Cosa non può chiedere un batch

Un batch è rifiutato per intero con FEATURE_NOT_AVAILABLE_IN_BULK (1010), prima di riservare qualunque cosa, se le sue settings chiedono un sigillo qualificato (qeSeal), una marca temporale qualificata (qualifiedTimestamp), una password del documento, un responseFormat diverso da pdf, o un filename. details.fields li nomina uno per uno. Un sigillo o una marca si addebitano a cose fatte e potrebbero superare quanto riservato; una password non si può tenere in un job conservato; un elemento non ha una risposta sua e un nome di file ne nominerebbe molti. Manda quei documenti uno alla volta.

Caricare un batch grande

Oltre il limite in linea, carica gli elementi come file JSONL (un oggetto JSON per riga, {"externalId": "...", "data": {...}}) — o come CSV — e invia con fileId:

POST /api/v1/bulk/files
Authorization: Bearer lpdc_...
Idempotency-Key: month-end-2026-09-file
Content-Type: application/x-ndjson

{"externalId":"inv-1001","data":{"customer":{"name":"Acme Srl"}}}
{"externalId":"inv-1002","data":{"customer":{"name":"Beta SpA"}}}

201 Created
{ "output": { "bulk": { "file": {
    "fileId": "f41a...", "items": 2, "bytes": 131,
    "sha256": "...", "expiresAt": "2026-10-03T09:14:02Z" } }, "...": "..." } }

POST /api/v1/bulk/compose
{ "settings": { "templateId": "invoice-standard-8bc99b" }, "fileId": "f41a..." }
  • Manda le righe come corpo grezzo della richiesta. Non si decomprime nulla: un Content-Encoding è rifiutato.
  • Tutto il file è validato prima di conservare qualunque cosa, e un JSONL è rifiutato per intero se una riga è sbagliata (BULK_INPUT_INVALID, con fino a venti details.problems, ognuno con la sua line). Un file oltre il suo limite di byte è JOB_TOO_LARGE (1812).
  • Un file serve a un job. Un caricamento non usato prima di expiresAt viene eliminato; usarlo dopo, o due volte, è BULK_FILE_NOT_FOUND (1503).

Input CSV

Anche l'esportazione di un foglio di calcolo è un batch. Caricala sulla stessa POST /api/v1/bulk/files con Content-Type: text/csv (o ?format=csv) e invia il fileId come per un JSONL. Viene letta negli stessi identici elementi, quindi tutto ciò che viene dopo il lettore — i limiti, la prenotazione, la composizione, l'addebito — è uguale.

IntestazioneDiventa
externalIdIl riferimento dell'elemento (non un campo del payload).
customerdata.customer, testo.
customer.namedata.customer.name: un punto annida.
lines.0.sku, lines.1.skuUn elenco: data.lines[0].sku, data.lines[1].sku. Gli indici vanno 0, 1, 2… senza buchi.
total:number, paid:bool, lines:jsonUna cella tipizzata. Senza suffisso una cella è testo. :number sono cifre con un meno facoltativo e il punto per i decimali; :bool è true/false, yes/no, 1/0; :json è un valore JSON.
  • La prima riga è l'intestazione. Una cella vuota è assente (il campo non si manda), mai una stringa vuota, e un elemento di elenco con tutte le celle vuote viene scartato.
  • Separatore: virgola, punto e virgola, tab o barra verticale, letto dalla riga di intestazione, o indicato con ?delimiter=comma|semicolon|tab|pipe. Si legge una volta, al caricamento, e si conserva con il file.
  • Codifica: UTF-8 (un byte-order mark va bene), o ?encoding=iso-8859-1 / windows-1252 — quello che un Excel italiano scrive ancora. Non si indovina mai: un file non valido nella sua codifica è rifiutato indicando il byte su cui si è fermato.
  • Un file sbagliato è rifiutato per intero con BULK_INPUT_INVALID e non si conserva nulla: vuoto, byte NUL, un'intestazione che non si legge (una colonna doppia o senza nome, un suffisso di tipo sconosciuto, un elenco con un buco), una virgoletta malformata, più righe del limite del file, o nessuna riga utilizzabile.
  • Una riga sbagliata non fa rifiutare le altre. Diventa un elemento fallito con error.code BULK_INPUT_INVALID (1107) e la sua row e line: una cella che non è il numero che dice l'intestazione, il numero sbagliato di celle, un externalId doppio o non valido, una riga oltre la dimensione per elemento. Non è mai riservata né addebitata, e non è da ritentare (correggi la riga e mandala in un nuovo batch).
  • Formule: quello che mandi non viene mai valutato né modificato; una cella che inizia con =, +, - o @ resta testo, perché finisce in un PDF. Ogni CSV che scriviamo noi (results.csv) antepone un apostrofo a quel testo così un foglio di calcolo non può eseguirlo.
  • Le colonne sono limitate (200, annidate al massimo a 6 livelli, indice di elenco al massimo 99) e non si decomprime nulla.

Firma in blocco

POST /api/v1/bulk/sign invia una busta per elemento. È POST /bulk/compose con un elemento diverso, quindi tutto quello che c'è in questa pagina — il 202 e il job, l'ammissione per intero o per niente, una prenotazione per elemento, il worker, gli stati, Idempotency-Key, i limiti, il CSV, il pacchetto, il nuovo tentativo e il webhook — vale così com'è. Un elemento è creato e inviato dallo stesso servizio che usa una singola POST /sign/envelopes?send=true.

POST /api/v1/bulk/sign
Authorization: Bearer lpdc_...
Idempotency-Key: nda-2026-q4

{
  "settings": {
    "documents": [ { "fileId": "9c2e..." } ],
    "subject": "NDA 2026"
  },
  "items": [
    { "externalId": "C-001",
      "signers": { "A": { "email": "anna@example.com", "fullName": "Anna Rossi" } } },
    { "externalId": "C-002", "subject": "NDA 2026 - condizioni speciali",
      "documents": [ { "fileId": "b17a..." } ],
      "signers": { "A": { "email": "bruno@example.com", "fullName": "Bruno Neri" } } }
  ],
  "callbackUrl": { "onSuccess": "https://example.com/hooks/bulk" }
}
  • settings è la parte condivisa delle settings di una singola busta (isTest, level, language, subject, documents, …). I documents / documentId / subject / message di un elemento vi si sovrappongono, e il risultato è validato come la richiesta stessa che prende una singola chiamata. Lo stesso contratto per ogni firmatario è quindi settings.documents una volta e signers per elemento.
  • Le sorgenti sono un documentId composto o un PDF che hai caricato una volta (POST /api/v1/sign/files, poi fileId). Un fileBase64 in linea è rifiutato in un batch: caricalo una volta.
  • Funziona anche un CSV: externalId,signers.A.email,signers.A.fullName con le impostazioni condivise nella richiesta. Una riga con un indirizzo non valido è un elemento fallito, non addebitato.
  • Si riserva una firma per elemento all'ammissione e la si addebita quando quella busta viene inviata; un elemento che fallisce è rimborsato. Un batch isTest spende un elemento di prova per busta e mai credito.
  • settings.callbackUrl è la callback di ogni busta; il callbackUrl al primo livello è il webhook di completamento del batch.
  • Il token deve avere bulk:submit e signatures:ses: un batch non aggira mai un ambito.

Rifiutato per intero, con i codici di una singola chiamata: FEATURE_NOT_AVAILABLE_IN_TEST_MODE (1009) per una funzione a pagamento con isTest; SIGNATURE_LEVEL_UNAVAILABLE per AES o QES; INVALID_REQUEST_BODY per un oggetto mancante o un firmatario malformato; QUOTA_EXCEEDED. Un sigillo o una marca — chiesti, o richiesti dalla tua organizzazione — sono rifiutati con FEATURE_NOT_AVAILABLE_IN_BULK (1010): si addebitano al completamento e non si possono riservare in anticipo. Una sorgente che non si può usare (STORED_FILE_NOT_FOUND) fa fallire il suo elemento, non addebitato, con il codice della singola chiamata. Ogni elemento dice quale busta ha creato (envelopeId); seguila con GET /api/v1/sign/envelopes/{id}.

Document Fly in blocco

POST /api/v1/bulk/flow esegue un flusso per elemento: il documento è composto dal template e mandato in firma nello stesso passo, esattamente come fa una singola POST /api/v1/flow. Vale tutto quello che c'è in questa pagina: il 202 e il job, l'ammissione per intero o per niente, il worker, gli stati, Idempotency-Key, i limiti, il CSV, il pacchetto, il nuovo tentativo e il webhook.

POST /api/v1/bulk/flow
Authorization: Bearer lpdc_...
Idempotency-Key: contracts-2026-q4

{
  "settings":  { "templateId": "tpl_..." },
  "signature": { "subject": "Contratto di servizio" },
  "items": [
    { "externalId": "C-001",
      "data":    { "customer": "Acme S.r.l." },
      "signers": { "A": { "email": "anna@example.com", "fullName": "Anna Rossi",
                          "fields": [ { "page": 1, "x": 0.1, "y": 0.8, "width": 0.3, "height": 0.08 } ] } } }
  ]
}
  • settings è la metà di composizione delle settings di un singolo flusso e si applica a ogni elemento; signature è la parte condivisa del suo blocco di firma (tutto tranne signers). Un elemento porta il suo data e i suoi signers, e può sovrapporre al blocco condiviso il proprio subject, message e documents (allegati).
  • Ogni elemento riserva due cose all'ammissione, un documento e una firma, come un singolo flusso, e vengono addebitate entrambe quando l'elemento è consegnato. Un elemento che fallisce è rimborsato; un flusso il cui documento è stato composto prima che la busta fosse rifiutata ha addebitato quel documento una volta (il creditsConsumed del job lo conta, per quanti tentativi ci siano), e un nuovo tentativo non lo addebita di nuovo. Un batch isTest spende un elemento di prova per flusso e mai credito.
  • Il token deve avere bulk:submit e flow:*.

Rifiutato per intero, con i codici di un singolo flusso: FEATURE_NOT_AVAILABLE_IN_TEST_MODE per una funzione a pagamento con isTest; SIGNATURE_LEVEL_UNAVAILABLE per AES o QES; DATALESS_NOT_AVAILABLE; QUOTA_EXCEEDED; FEATURE_NOT_ENABLED per un codice SMS o un livello di firma che la tua organizzazione non ha acquistato. Un sigillo o una marca sono rifiutati con FEATURE_NOT_AVAILABLE_IN_BULK. Ogni elemento dice quale documento e quale busta ha creato.

Il job

Un job passa da queued → running → uno tra succeeded, partially_succeeded, failed o cancelled. Interroga su output.status: è pending finché il job può ancora cambiare, poi succeeded solo quando ogni elemento ha consegnato, e failed per tutto il resto (un risultato parziale, un job annullato, uno fallito), quindi leggi output.bulk.status e gli elementi per distinguerli. Non dedurre lo stato dai conteggi.

Stato finaleQuando
succeededOgni elemento ha consegnato un documento.
partially_succeededAlcuni hanno consegnato, altri sono falliti. Il job in sé non è un errore: leggi gli elementi.
failedNessun elemento ha consegnato un documento.
cancelledHai chiesto di fermarlo; prevale sugli altri tre.

Ogni elemento è queued, processing, succeeded, failed o cancelled. counts ha un numero per ciascuno, totalItems è quello che hai inviato, e pending è in coda più in lavorazione.

I risultati si conservano per il periodo indicato in resultsExpireAt (impostato quando il job è finito); dopo, resultsExpired è true. Prendi quello che ti serve prima.

Leggere i risultati

GET /api/v1/bulk/jobs/6d1e.../items?status=failed&limit=100&after=41

{ "output": { "bulk": {
    "jobId": "6d1e...", "...": "il job, come sopra",
    "items": [
      { "index": 57, "externalId": "inv-1058", "status": "failed",
        "documentId": null, "downloadUrl": null, "creditsUsed": 0,
        "error": { "code": "MISSING_TEMPLATE_FIELD", "number": 1401,
                   "message": "...", "retryable": false },
        "warnings": [], "...": "attempts, pageCount, sizeBytes, sha256, durationMs, startedAt, finishedAt" }
    ],
    "page": { "limit": 100, "after": 41, "status": "failed", "nextAfter": 98 } } } }
  • Gli elementi arrivano in ordine di index (la posizione nel tuo batch, da 0). status filtra per stato dell'elemento; limit arriva a 500.
  • Per leggere la pagina successiva, manda after = il nextAfter che hai ricevuto. Quando nextAfter è null, era l'ultima pagina.
  • Un elemento consegnato porta il suo documentId, downloadUrl, numero di pagine, dimensione e SHA-256. Uno fallito porta l'error.code stabile e il numero (vedi Esiti e codici di errore), e retryable dice se vale la pena rimandare lo stesso elemento.
  • La piattaforma non ritenta mai un elemento per te. Lo chiedi tu, con la chiamata di nuovo tentativo; un elemento non da ritentare, o il cui payload non è conservato, lo rimandi in un nuovo batch (riusa il suo externalId).

Il pacchetto dei risultati

GET /api/v1/bulk/jobs/{id}/results restituisce uno ZIP quando il job è finito: documents/<index>.pdf per ogni file prodotto, manifest.json e results.csv (per elemento: stato, tentativi, documentId / envelopeId, lo SHA-256 del file, numero di pagine, crediti usati, codice e numero dell'errore, se è da ritentare) e i crediti del job. Il pacchetto di un job di firma contiene solo il manifesto e il CSV.

  • Richiede bulk:read e documents:download — consegna gli stessi byte del download per documento. Il job di un'altra organizzazione è un 404.
  • Esiste solo quando il job è finito e finché i suoi risultati sono conservati; altrimenti BULK_RESULTS_UNAVAILABLE (1504) con details.reason job_not_finished o results_expired. Un documento che la tua conservazione ha eliminato è elencato con file: null.
  • Si costruisce un documento alla volta in un file temporaneo, con un tetto. Un job i cui documenti superano il tetto è JOB_TOO_LARGE; scaricalo a intervalli con ?after=<index>&limit=<n> (il range.nextAfter del manifesto è quello da mandare dopo).
  • I nomi delle voci sono l'indice dell'elemento, mai quello che hai scritto tu; results.csv antepone un apostrofo a ogni testo che un foglio di calcolo potrebbe leggere come formula.
  • Scaricarlo non costa nulla ed è registrato. Per un documento destinato a qualcuno che non ha una chiave, crea un link di download firmato per il suo documentId.

Ritentare gli elementi falliti

POST /api/v1/bulk/jobs/{id}/retry rimette in lavoro gli elementi falliti da ritentare di un job finito, come nuovi tentativi nello stesso job (attempts li conta, retryCount conta le chiamate). Ogni elemento è ammesso come uno nuovo: la sua prenotazione, gli stessi limiti e lo stesso worker; un nuovo tentativo che non si può pagare è rifiutato per intero e non cambia nulla. La risposta è 202 con il job e retry: {requeued, skippedCount, skipped[]}.

Un elemento torna in lavoro quando…altrimenti viene saltato come
il suo errore dice retryable: truenot_retryable
il suo payload è ancora conservato (un'organizzazione che compone senza conservare dati non ne ha)payload_not_kept
ha girato meno di 3 volteattempts_exhausted
nessuna sua richiesta a un fornitore a pagamento ha un esito sconosciutooutcome_unknown: mai ripetuto, aspetta la sua riconciliazione

Niente da ritentare è BULK_RETRY_NOT_POSSIBLE (1505) con details.reason (nothing_retryable, job_not_finished, job_cancelled, results_expired, payload_not_kept) e gli elementi saltati. È idempotente: una seconda chiamata mentre girano gli elementi della prima trova il job non finito e non cambia nulla, e con una Idempotency-Key si ripete la prima risposta. Richiede bulk:submit e l'ambito dell'operazione del job (documents:compose, o signatures:ses per un job di firma; isTest per un job di prova). Il job finisce di nuovo, e te lo dice di nuovo.

Webhook di completamento

Aggiungi "callbackUrl": {"onSuccess": "https://...", "onError": "https://..."} a un batch di composizione, firma o flusso e vieni avvisato quando il job finisce, invece di interrogare. onSuccess è chiamato quando ogni elemento ha consegnato, onError per ogni altra fine (partially_succeeded, failed, cancelled). È la stessa consegna di una callback di firma: solo https, firmata (X-Signer-Signature: HMAC-SHA256 del corpo grezzo con il segreto di callback della tua organizzazione), mai verso un indirizzo privato o non pubblico, senza seguire reindirizzamenti, ritentata con le stesse attese (fino a circa due giorni), elencata nel registro dei webhook e ripetibile da lì. Gli header aggiungono X-Signer-Bulk-Job. Per autenticarti presso il tuo ricevitore, indica un ambiente di callback e manda percorsi: "callbackUrl": {"env": "prod", "onSuccess": "/hooks/bulk"}; un env sconosciuto è rifiutato all'invio, prima di riservare qualunque cosa.

{
  "bulkJobId": "6d1e...", "operation": "compose", "status": "partially_succeeded",
  "isTest": false, "totalItems": 100, "counts": { "succeeded": 97, "failed": 3, "...": "..." },
  "creditsConsumed": 485, "creditsReleased": 15, "retryCount": 0,
  "reconciliation": { "...": "come nel job" }, "links": { "self": "...", "items": "...", "results": "..." },
  "event": { "id": "evt_...", "type": "bulk.partially_succeeded", "occurredAt": "...", "schema": 1 }
}

event.id è stabile tra i tentativi: elimina i doppioni su quello. Il corpo nomina il job e i numeri e non porta nessun dato degli elementi; leggi gli elementi, a pagine. Un job ritentato che finisce di nuovo manda un nuovo evento. L'URL non viene mai rimandato dall'API.

Crediti: credits.total e credits.block

Come ogni risposta, una risposta bulk porta output.credits come {used, left}. Per un job, used è il totale di quello che i suoi elementi hanno regolato finora (la somma dei creditsUsed per elemento; 0 per isTest), e left è il tuo saldo letto dal registro adesso — mai il tuo saldo precedente meno used, che è sbagliato finché il job tiene una prenotazione.

Dentro output.bulk lo stesso denaro è scomposto per il job:

CampoSignificato
creditsReservedQuanto è stato messo da parte per il batch all'ammissione: il prezzo di un documento per elemento.
creditsConsumedQuanto sono costati davvero i documenti consegnati.
creditsHeldAncora riservato per elementi non finiti. 0 quando il job è finito.
creditsReleasedRestituito: elementi falliti o annullati.

Quando il job è finito porta anche una reconciliation:

"reconciliation": {
  "requested": 100, "succeeded": 97,
  "failed": { "platform": 1, "customer": 1 },
  "cancelled": 1,
  "creditsReserved": 500, "creditsConsumed": 485, "creditsReleased": 15,
  "chargedFailureClasses": []
}

creditsConsumed + creditsReleased = creditsReserved. Gli errori sono divisi in platform (nostri: un errore interno, un problema di composizione, la scadenza di un job) e customer (l'input), così vedi quale è quale; nessuno dei due si paga.

Cosa si paga

Un documento si paga se, e solo se, è stato consegnato. Un job bulk costa esattamente quanto gli stessi documenti mandati uno alla volta.

EsitoAddebito
Il batch è rifiutato (malformato, oltre un limite, credito insufficiente, nessuna capacità)Non si riserva nulla, non si addebita nulla.
Un elemento fallisce per i suoi dati o per il templateNon si paga; il suo credito torna indietro.
Un elemento fallisce per un motivo della piattaformaNon si paga; il suo credito torna indietro.
Un elemento è annullato prima di iniziare, o è ancora in attesa alla scadenza del jobNon si paga; il suo credito torna indietro.
Un elemento è consegnatoSi paga un documento.
Un elemento isTestUsa la dotazione di prova, mai credito. Vedi sotto.

Il credito di tutto il batch è riservato in un passo prima di comporre qualunque documento, così due batch che insieme superano il tuo saldo non possono essere ammessi entrambi: il secondo è rifiutato con QUOTA_EXCEEDED (vedi Esiti e codici di errore) e non resta nulla dietro. È riservato per elemento, e ogni elemento si regola da solo quando finisce.

Annullare

POST /api/v1/bulk/jobs/{id}/cancel ferma il job. Gli elementi non ancora iniziati sono annullati e il loro credito è restituito subito; un elemento in composizione in quel momento finisce ed è addebitato se consegna. La risposta è il job (cancelRequested è true). Annullare un job già finito non cambia nulla e risponde con il job. La chiamata prende una Idempotency-Key come le altre.

Idempotenza

Inviare, caricare un file, annullare e ritentare prendono tutti una Idempotency-Key, e per un invio dovresti mandarne sempre una. Con la chiave, un nuovo tentativo di una richiesta andata in timeout restituisce lo stesso job (la risposta porta Idempotent-Replay: true) invece di ammettere e addebitare un secondo batch. La stessa chiave con un corpo diverso è IDEMPOTENCY_KEY_REUSED. Le regole sono quelle di ogni altra chiamata; usa una chiave del tuo dominio, come il riferimento di un lotto o di un periodo.

Prove: isTest

Con "isTest": true in settings tutto il batch gira nella sandbox: non si spende credito e i documenti sono segnati come prove. Il batch prende un elemento della dotazione di prova per documento dalla stessa riserva delle singole chiamate di prova, tutto o niente, ed è limitato a pochi elementi per batch (oggi il predefinito è 5). Un batch di prova oltre il limite è BULK_ITEM_LIMIT_EXCEEDED. Gli elementi di prova vengono dopo il lavoro di produzione.

Organizzazioni dataless

Se la tua organizzazione compone dataless, un batch bulk conserva comunque i suoi documenti per la tua normale conservazione — un batch risponde senza byte, quindi li scarichi dopo — e la risposta porta l'avviso DOCUMENT_STORED_FOR_BULK (2203). I dati che hai inviato non vengono registrati; il payload di ogni elemento viene cancellato quando l'elemento finisce.

Limiti

Questi sono i valori predefiniti attuali. Sono valori di lavoro e possono cambiare; quelli che valgono per la tua organizzazione possono essere più bassi, mai più alti. Una richiesta è rifiutata per intero, senza riservare nulla, quando ne supera uno.

LimitePredefinitoRifiutato con
Elementi in un batch in linea500BULK_ITEM_LIMIT_EXCEEDED
Elementi in un file caricato2.000BULK_ITEM_LIMIT_EXCEEDED
Dimensione di un corpo in linea / di un file caricato10 MiB / 25 MB (nessuna richiesta può essere più grande)JOB_TOO_LARGE / PAYLOAD_TOO_LARGE
Elementi in un batch isTest5BULK_ITEM_LIMIT_EXCEEDED
Job in esecuzione contemporanea2BULK_CONCURRENCY_LIMIT_REACHED
Elementi in attesa nei tuoi job20.000BULK_CONCURRENCY_LIMIT_REACHED
Invii al minuto6BULK_CONCURRENCY_LIMIT_REACHED
File caricati non ancora usati5BULK_CONCURRENCY_LIMIT_REACHED

Il limite effettivo di elementi è il più basso tra quello che chiedi in options.maxItems, il limite della tua organizzazione e quello della piattaforma; details.requestedItems e details.allowedItems dicono di quanto eri oltre. BULK_CONCURRENCY_LIMIT_REACHED è da ritentare e porta Retry-After: details.what dice quale limite era. Un job ancora in esecuzione sei ore dopo l'ammissione fa scadere gli elementi rimasti (BULK_JOB_TIMED_OUT, non addebitati). Gli elementi si compongono uno dopo l'altro e condividono la capacità con le richieste di tutti gli altri, quindi un batch grande è questione di minuti, non di secondi; la piattaforma mette in pausa un job invece di farlo fallire quando è occupata. Se il bulk è spento per tutto il servizio, un nuovo batch è rifiutato con SERVICE_PAUSED.

Ambiti

Un batch di composizione richiede bulk:submit e documents:compose; un batch di firma bulk:submit e signatures:ses; un batch di flussi bulk:submit e flow:*. Il primo autorizza a eseguire un batch, il secondo l'operazione al suo interno, e un rifiuto (TOKEN_SCOPE_NOT_ALLOWED, 403) nomina il primo ambito mancante in details.missingScopes. Il gruppo di ambiti bulk è: bulk:submit per inviare, caricare, annullare e ritentare, bulk:read per leggere job, elementi e il pacchetto dei risultati (che richiede anche documents:download), o bulk:* per entrambi. Spuntare bulk:submit non spunta per te l'ambito dell'operazione: spuntali entrambi nella pagina Chiavi API. I token emessi prima che esistesse il bulk non hanno questi ambiti; emetti un nuovo token con gli ambiti spuntati. Il job o il file di un'altra organizzazione risponde 404, esattamente come uno che non esiste.

Nella console

Un batch è un elenco di singole chiamate, e la console lo mostra così. Ogni documento creato da un batch di composizione è una riga di Documenti e ogni busta inviata da un batch di firma è una riga di Firme, segnata Batch con un link al suo batch; il filtro sopra ogni elenco mostra tutte le righe, solo le singole chiamate o solo i batch. Un batch avviato con una chiave API c'è senza dover configurare nulla (Documenti, poi Batch, su /tenant/batches). I risultati di un batch si conservano per il periodo di conservazione; dopo, i suoi documenti sono ancora in Documenti, ma non più segnati.

La pagina del batch mostra stato, tipo, quanti elementi sono fatti, falliti, annullati e in attesa, una barra di avanzamento, e i crediti riservati, usati e restituiti (le stesse cifre di output.credits; un batch di prova lo dice e non mostra credito). Ogni elemento porta al suo documento o alla sua richiesta di firma, e uno fallito mostra il suo codice di errore stabile, il numero e il messaggio. Chiunque veda Documenti può leggere la pagina e scaricare lo ZIP dei risultati. Un coordinatore può anche ritentare gli elementi falliti (solo quelli da ritentare, come fa l'API), annullare un batch in corso (quello che non era iniziato si ferma e il suo credito torna) e rimandare il webhook di completamento; ognuna delle tre cose è registrata nel registro delle attività con il nome della persona.

Non ancora disponibile

  • Niente sigillo, marca temporale o password su un documento o una busta in blocco: si addebitano o si conservano a cose fatte e non si possono riservare in anticipo (manda quelli uno alla volta).
  • Niente AES o QES, né in un batch né singolarmente (SIGNATURE_LEVEL_UNAVAILABLE).
  • Un link di download firmato per tutto il pacchetto: lo ZIP si scarica con la tua chiave; un link si crea per documento.