DoConure

Esempi di codice: cURL, JavaScript, React, PHP, WordPress, Java, C#, Go, Ruby

La stessa chiamata in tutti i linguaggi più diffusi: genera un documento e salvalo come PDF. Ogni esempio invia "isTest": true, quindi è gratuito; togli quella riga quando sei pronto per un documento vero. Python e Salesforce (Apex) hanno pagine dedicate, e Make, Zapier e n8n sono spiegati senza codice.

L'indirizzo è https://app.doconure.com/api/v1/compose/documents/generate, la chiave va in Authorization: Bearer ..., e l'id del modello è quello indicato nella pagina del modello nella console. Ogni errore risponde con un code stabile e un message: fai le tue scelte in base al code, mai al messaggio (tutti i codici).

Tieni la chiave su un server. Non metterla mai in codice che gira in un browser, in un'app mobile o nel JavaScript di una pagina WordPress: chiunque apra la pagina può leggerla. Gli esempi React, Vue e WordPress qui sotto chiamano il tuo server, che custodisce la chiave.

cURL

curl -X POST https://app.doconure.com/api/v1/compose/documents/generate \
  -H "Authorization: Bearer $DOCONURE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"data": {"customer": {"name": "Acme Srl"}},
       "settings": {"templateId": "YOUR_TEMPLATE_ID", "isTest": true}}' \
  --output document.pdf

Su Windows cmd.exe non capisce gli apici singoli: metti il corpo in un file e usa -d @body.json, oppure usa PowerShell.

JavaScript e Node.js

import { writeFile } from "node:fs/promises";

const res = await fetch("https://app.doconure.com/api/v1/compose/documents/generate", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.DOCONURE_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    data: { customer: { name: "Acme Srl" } },
    settings: { templateId: "YOUR_TEMPLATE_ID", isTest: true },
  }),
});
if (!res.ok) {
  const err = await res.json();
  throw new Error(`${err.code}: ${err.message}`);
}
await writeFile("document.pdf", Buffer.from(await res.arrayBuffer()));

React, Next.js e Vue

Il browser non chiama mai DoConure direttamente. Chiama una route del tuo server, ed è la route a custodire la chiave. Route handler di Next.js (app/api/invoice/route.js):

export async function POST(request) {
  const data = await request.json();
  const res = await fetch("https://app.doconure.com/api/v1/compose/documents/generate", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.DOCONURE_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ data, settings: { templateId: "YOUR_TEMPLATE_ID" } }),
  });
  if (!res.ok) return Response.json(await res.json(), { status: res.status });
  return new Response(res.body, { headers: { "Content-Type": "application/pdf" } });
}

Il componente React che scarica il PDF:

export function DownloadInvoice({ invoice }) {
  async function download() {
    const res = await fetch("/api/invoice", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(invoice),
    });
    if (!res.ok) { alert((await res.json()).message); return; }
    const url = URL.createObjectURL(await res.blob());
    Object.assign(document.createElement("a"), { href: url, download: "invoice.pdf" }).click();
  }
  return <button onClick={download}>Download PDF</button>;
}

Vue, Svelte e Angular funzionano allo stesso modo: il front end chiama il tuo server, il tuo server chiama DoConure.

PHP

<?php
$body = json_encode([
    "data" => ["customer" => ["name" => "Acme Srl"]],
    "settings" => ["templateId" => "YOUR_TEMPLATE_ID", "isTest" => true],
]);
$ch = curl_init("https://app.doconure.com/api/v1/compose/documents/generate");
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => $body,
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer " . getenv("DOCONURE_API_KEY"),
        "Content-Type: application/json",
    ],
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 120,
]);
$pdf = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($status !== 200) {
    $err = json_decode($pdf, true);
    throw new RuntimeException($err["code"] . ": " . $err["message"]);
}
file_put_contents("document.pdf", $pdf);

Laravel e Symfony: la stessa chiamata con Http::withToken(...)->post(...) o HttpClient; il corpo e gli header non cambiano.

WordPress

In un plugin o nel functions.php del tema. Metti la chiave in wp-config.php (define('DOCONURE_API_KEY', '...');), mai in un articolo o nel JavaScript:

function doconure_pdf( array $data, string $template_id ) {
    $response = wp_remote_post(
        'https://app.doconure.com/api/v1/compose/documents/generate',
        [
            'timeout' => 120,
            'headers' => [
                'Authorization' => 'Bearer ' . DOCONURE_API_KEY,
                'Content-Type'  => 'application/json',
            ],
            'body'    => wp_json_encode( [
                'data'     => $data,
                'settings' => [ 'templateId' => $template_id, 'isTest' => true ],
            ] ),
        ]
    );
    if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {
        $err = json_decode( wp_remote_retrieve_body( $response ), true );
        return new WP_Error( $err['code'] ?? 'doconure_error', $err['message'] ?? 'Request failed' );
    }
    return wp_remote_retrieve_body( $response ); // the PDF bytes
}

WooCommerce: chiamala dall'action woocommerce_order_status_completed e allega il file all'email dell'ordine. Contact Form 7 e Gravity Forms: chiamala dal loro hook di invio del modulo.

Java

import java.net.URI;
import java.net.http.*;
import java.nio.file.*;

String body = """
    {"data": {"customer": {"name": "Acme Srl"}},
     "settings": {"templateId": "YOUR_TEMPLATE_ID", "isTest": true}}""";

HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://app.doconure.com/api/v1/compose/documents/generate"))
    .header("Authorization", "Bearer " + System.getenv("DOCONURE_API_KEY"))
    .header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString(body))
    .build();

HttpResponse<byte[]> response = HttpClient.newHttpClient()
    .send(request, HttpResponse.BodyHandlers.ofByteArray());
if (response.statusCode() != 200) {
    throw new IllegalStateException(new String(response.body()));  // JSON with code and message
}
Files.write(Path.of("document.pdf"), response.body());

Spring: lo stesso con RestClient o WebClient. Kotlin e Android usano lo stesso HttpClient, da un tuo servizio, non dall'app.

C# e .NET

using System.Net.Http.Headers;
using System.Text;

using var http = new HttpClient { Timeout = TimeSpan.FromSeconds(120) };
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
    "Bearer", Environment.GetEnvironmentVariable("DOCONURE_API_KEY"));

var body = """
    {"data": {"customer": {"name": "Acme Srl"}},
     "settings": {"templateId": "YOUR_TEMPLATE_ID", "isTest": true}}""";

var response = await http.PostAsync(
    "https://app.doconure.com/api/v1/compose/documents/generate",
    new StringContent(body, Encoding.UTF8, "application/json"));
if (!response.IsSuccessStatusCode)
    throw new InvalidOperationException(await response.Content.ReadAsStringAsync());
await File.WriteAllBytesAsync("document.pdf", await response.Content.ReadAsByteArrayAsync());

Per generare invece un client tipizzato, scarica /openapi.json e passalo a NSwag, Kiota o openapi-generator (qualsiasi linguaggio).

Go

body := `{"data": {"customer": {"name": "Acme Srl"}},
          "settings": {"templateId": "YOUR_TEMPLATE_ID", "isTest": true}}`
req, _ := http.NewRequest("POST",
    "https://app.doconure.com/api/v1/compose/documents/generate", strings.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("DOCONURE_API_KEY"))
req.Header.Set("Content-Type", "application/json")

res, err := (&http.Client{Timeout: 120 * time.Second}).Do(req)
if err != nil { log.Fatal(err) }
defer res.Body.Close()
out, _ := io.ReadAll(res.Body)
if res.StatusCode != 200 { log.Fatalf("%d: %s", res.StatusCode, out) }
os.WriteFile("document.pdf", out, 0o644)

Ruby e Rails

require "net/http"
require "json"

uri = URI("https://app.doconure.com/api/v1/compose/documents/generate")
request = Net::HTTP::Post.new(uri, "Content-Type" => "application/json",
                              "Authorization" => "Bearer #{ENV['DOCONURE_API_KEY']}")
request.body = { data: { customer: { name: "Acme Srl" } },
                 settings: { templateId: "YOUR_TEMPLATE_ID", isTest: true } }.to_json
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true, read_timeout: 120) { |h| h.request(request) }
raise response.body unless response.code == "200"   # JSON with code and message
File.binwrite("document.pdf", response.body)

Dove andare dopo