DonutworkHelp Center
Api ReferenceRicavi e partner
Documentazione Donutwork

Importare charge esterne

Importa pagamenti già incassati da un altro sistema, con commissioni partner, eventi e retry idempotenti.

Importare charge esterne

Usa questo endpoint quando un altro sistema ha già incassato il pagamento e Donutwork deve registrarlo come charge pagata. Conserva importi, imposte e date originali e attiva il normale flusso di commissioni partner ed eventi. Non contatta gateway e non richiede un metodo di pagamento sul cliente.

Per un nuovo pagamento da incassare tramite Donutwork usa invece la creazione di charge una tantum. Le charge importate sono transazioni one-shot indipendenti: non creano né rinnovano un abbonamento.

Endpoint e prerequisiti

POST https://api.hub.donutwork.com/2026-02-01/customers/CUSTOMER_ID/charges/import.json
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json

L'endpoint supporta anche la versione 2024-08-01. Usa URL e chiave API dell'ambiente corretto; non inviare una chiave di sviluppo alla produzione. Per configurare la chiave consulta autenticazione.

  • La chiave API server-side deve avere charges:write; per rileggere il risultato serve charges:read.
  • CUSTOMER_ID deve essere l'ID esadecimale di 24 caratteri di un cliente esistente nella company della chiave. La company deriva dalla chiave, non dal JSON.
  • Ogni riga deve indicare un profilo fiscale della stessa company. Puoi selezionarlo con GET /taxes.json e taxes:read: consulta profili fiscali.
  • currency deve coincidere con la valuta aziendale configurata nel Partner Portal. Senza configurazione valutaria sono ammesse soltanto importazioni in EUR per clienti senza partner.
  • Se il cliente ha un partner, partner e gruppo commissionale devono essere validi e la configurazione valutaria aziendale deve essere persistita. Il server ricava il partner dal cliente.

Corpo della richiesta

Salva questo esempio in charge-import.json. Sostituisci l'ID fiscale di esempio con un profilo della tua company e usa le date effettive di creazione e pagamento della transazione esterna. Gli ID e i riferimenti della guida sono esempi.

{
  "charge": {
    "source": "external-billing",
    "external_id": "transaction-123",
    "created_at": "2026-10-20T10:00:00Z",
    "paid_at": "2026-10-20T10:05:00Z",
    "currency": "EUR",
    "total": "122.00",
    "services": [
      {
        "name": "Consulenza incassata esternamente",
        "amount": "100.00",
        "taxAmount": "22.00",
        "taxProfile": "67248941cbe2b1ff8b099a6d"
      }
    ]
  }
}

Invialo da un backend affidabile o da una shell in cui DONUTWORK_API_KEY sia già disponibile:

curl -i -X POST \
  'https://api.hub.donutwork.com/2026-02-01/customers/CUSTOMER_ID/charges/import.json' \
  -H "Authorization: Bearer $DONUTWORK_API_KEY" \
  -H 'Content-Type: application/json' \
  --data-binary @charge-import.json

Il body deve contenere soltanto l'oggetto charge e non può superare 64 KiB. Tutti i campi seguenti sono obbligatori.

CampoTipoContratto
charge.sourcestringNome stabile del sistema sorgente, massimo 80 byte UTF-8. Mantieni lo stesso valore nei retry.
charge.external_idstringID stabile della transazione nella sorgente, massimo 200 byte UTF-8. La coppia con source è univoca nell'intera company, anche tra clienti diversi.
charge.created_atstringData originale di creazione della charge, ISO 8601 con timezone, per esempio 2026-10-20T10:00:00Z.
charge.paid_atstringData originale di incasso nello stesso formato; non può precedere created_at.
charge.currencystringCodice valuta di tre lettere corrispondente alla valuta aziendale.
charge.totalnumber oppure stringa decimaleTotale lordo positivo, uguale alla somma esatta di imponibili e imposte di tutte le righe.
charge.servicesarrayDa 1 a 100 oggetti riga.
charge.services[].namestringDescrizione non vuota della riga, massimo 250 byte UTF-8.
charge.services[].amountnumber oppure stringa decimaleImponibile positivo, imposte escluse.
charge.services[].taxAmountnumber oppure stringa decimaleImposta già applicata esternamente; è ammesso zero.
charge.services[].taxProfilestringID esadecimale di 24 caratteri di un profilo fiscale esistente nella company.

Gli importi sono in unità principali della valuta, con punto decimale, massimo due decimali e otto cifre intere. Per esempio, "100.00" indica cento unità della valuta: non inviare 10000 per rappresentare lo stesso importo in centesimi. Il server conserva taxAmount senza ricalcolare l'imposta storica usando la percentuale corrente del profilo fiscale.

Le date devono essere valide, non precedenti all'epoca Unix, non future e con timezone; sono ammessi fino a tre decimali di secondo. Vengono normalizzate in UTC. Le stringhe vengono ripulite dagli spazi iniziali e finali e non possono contenere caratteri di controllo.

I campi sconosciuti vengono rifiutati con 422. Non includere company_id, customer_id, partner_id, status, instruction, capture o invoice: il cliente deriva dall'URL, il partner dal cliente e le charge importate sono sempre già pagate. I metadati fattura si possono associare separatamente dopo l'importazione.

Risposte e retry

La prima importazione completata restituisce 201 Created:

{
  "status": "success",
  "id": "CHARGE_ID",
  "created": true,
  "paid": true,
  "externally_managed": true
}

Conserva id insieme alla transazione sorgente. Un reinvio già completato con lo stesso payload normalizzato restituisce 200 OK, lo stesso id e created: false. Non serve l'header Idempotency-Key.

La chiave di idempotenza è company più source ed external_id. Il confronto del payload include cliente, entrambe le date, valuta, totale e righe nel loro ordine originale. Riutilizzare la chiave con contenuto diverso restituisce 409 e non aggiorna la transazione importata. Conserva il payload originale per i retry: dopo un timeout non generare nuove date o un altro ID esterno.

Stato HTTPSignificato e azione
200Importazione esistente restituita oppure importazione interrotta completata; riusa l'ID charge ricevuto.
201Nuova importazione completata.
400Body JSON assente o malformato.
401 / 403Autenticazione o autorizzazione fallita; controlla chiave, accesso alla company e charges:write.
404Cliente assente nella company autenticata.
409Contenuto diverso per la stessa transazione sorgente, oppure un'altra richiesta sta completando l'importazione. Distingui i casi dal messaggio di errore.
413Body oltre 64 KiB.
415Content type diverso da application/json.
422Campi, date, importi, valuta, profilo fiscale, partner/gruppo o totale non validi. Correggi l'input prima di riprovare.
429Limite richieste API raggiunto; segui le indicazioni di retry della risposta.
503Impossibile completare l'importazione, oppure configurazione valutaria partner mancante. Risolvi prima eventuali problemi di configurazione; altrimenti ripeti la stessa sorgente, ID esterno e payload con backoff.

Esempi dei due messaggi 409:

{"error":"source and external_id already used with different content"}
{"error":"Import is being finalized; retry the same payload"}

La charge può essere già stata salvata quando si verifica un'interruzione di rete o un 503. Ripetere la richiesta identica riprende il lavoro incompleto senza creare un'altra charge o commissione diretta. Un completamento concorrente risponde 409: riprova con backoff. Dopo l'interruzione di un processo può essere necessario attendere la scadenza del blocco di elaborazione di cinque minuti. Un recupero può restituire 200 anche se non hai ricevuto il 201 originale.

Commissioni, eventi e gestione esterna

Il partner del cliente viene fissato al primo inserimento. La commissione diretta usa l'imponibile della charge e le normali regole del gruppo partner; la data contabile segue paid_at. Le regole predefinite allo zero per cento possono non produrre una commissione positiva. Le commissioni referral eleggibili vengono elaborate in modo asincrono secondo la policy aziendale. Le regole dirette sono quelle disponibili al calcolo; la policy referral è quella efficace alla creazione della fee diretta. Importare pagamenti passati non ricostruisce configurazioni commissionali storiche né ricalcola fee esistenti.

Dopo il salvataggio della charge pagata e l'elaborazione della commissione diretta, Donutwork emette Charge.create e Charge.succeeded attraverso il normale flusso eventi. Workflow e webhook configurati possono quindi attivarsi anche per i pagamenti importati. L'importazione non invia una ricevuta email automatica e non contatta Stripe, PayPal o altri gateway.

Un reinvio già completato non genera un'altra commissione e non riemette questi eventi. La consegna usa le garanzie del dispatcher esistente: un crash tra invio e registrazione del completamento può ripetere un evento. Rendi idempotenti i consumer webhook usando tipo evento e ID charge e riconcilia lo stato corrente della charge. Consulta webhook.

Importi, date di pagamento e stato delle charge importate sono gestiti dalla sorgente esterna. I percorsi di capture e cambio stato manuale di Donutwork non possono incassarle, marcarle o rimborsarle. Questo endpoint di importazione non espone operazioni di aggiornamento, eliminazione o rimborso. Reinviare importi o date diversi per la stessa transazione restituisce 409; un altro ID esterno rappresenta un'altra transazione, non una correzione.

Leggere e riconoscere una charge importata

Rileggi l'ID restituito usando charges:read:

curl \
  'https://api.hub.donutwork.com/2026-02-01/customers/CUSTOMER_ID/charges/CHARGE_ID.json' \
  -H "Authorization: Bearer $DONUTWORK_API_KEY"

Tra i campi della risposta di dettaglio trovi:

{
  "id": "CHARGE_ID",
  "type": "one-shot",
  "status": "paid",
  "instruction": "external",
  "externally_managed": true,
  "paid_at": "2026-10-20T10:05:00+00:00",
  "metadata": {
    "paid": {
      "source": "external",
      "external_source": "external-billing",
      "external_id": "transaction-123",
      "currency": "EUR"
    }
  }
}

La lista charge aziendale supporta anche GET /charges.json?instruction=external. I riepiloghi includono instruction, externally_managed e la data originale di creazione; per i riferimenti esterni usa il dettaglio. Nel backoffice la scheda cliente mostra un badge di importazione con la sorgente nel tooltip.

Per associare numero, data, sorgente o link della fattura usa PUT /customers/{customerId}/charges/{chargeId}/invoice.json con charges:write. Vengono aggiornati soltanto i metadati fattura, senza modificare il pagamento esterno. Consulta sincronizzazione fatture.

On this page