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

# SDKs

> Install an official e-invoice.be SDK for TypeScript, Python, Ruby, PHP or Java and validate, create and send a document with typed calls.

e-invoice.be publishes SDKs for five languages. Each SDK is generated from the OpenAPI specification of the API and gives you typed requests, typed responses, automatic retries and error classes. You do not have to write HTTP calls.

All SDKs call the single API host `https://api.e-invoice.be`. The API key selects the mode: a key of a sandbox company makes the SDK run in test mode, and a key of a production company sends documents on the Peppol network. See [Test mode and sandbox companies](/environments).

## Available SDKs

| Language | Repository | Package | Minimum runtime | Release status |
| - | - | - | - | - |
| TypeScript and JavaScript | [e-invoice-ts](https://github.com/e-invoice-be/e-invoice-ts) | `e-invoice-api` (npm) | Node.js 20 LTS, TypeScript 4.9 | Version 1.x |
| Python | [e-invoice-py](https://github.com/e-invoice-be/e-invoice-py) | `e-invoice-api` (PyPI) | Python 3.9 | Version 1.x |
| Ruby | [e-invoice-rb](https://github.com/e-invoice-be/e-invoice-rb) | `e-invoice-api` (RubyGems) | Ruby 3.2.0 | Version 0.x, the interface can change |
| PHP | [e-invoice-php](https://github.com/e-invoice-be/e-invoice-php) | `e-invoice-be/e-invoice` (Composer, from the repository) | PHP 8.1.0 | Version 0.x, the interface can change |
| Java | [e-invoice-java](https://github.com/e-invoice-be/e-invoice-java) | `com.e_invoice.api:e-invoice-java` | Java 8 | Alpha |

The TypeScript SDK also runs in Deno 1.28.0 and later, Bun 1.0 and later, Cloudflare Workers and the Vercel Edge Runtime. The README of the repository has the full list.

## Install an SDK

<CodeGroup>
  ```bash TypeScript theme={null}
  npm install e-invoice-api
  ```

  ```bash Python theme={null}
  pip install e-invoice-api
  ```

  ```ruby Ruby theme={null}
  # Gemfile
  gem "e-invoice-api", "~> 0.33.0"
  ```

  ```json PHP theme={null}
  {
    "repositories": [
      {
        "type": "vcs",
        "url": "git@github.com:e-invoice-be/e-invoice-php.git"
      }
    ],
    "require": {
      "e-invoice-be/e-invoice": "dev-main"
    }
  }
  ```

  ```xml Java theme={null}
  <dependency>
    <groupId>com.e_invoice.api</groupId>
    <artifactId>e-invoice-java</artifactId>
    <version>0.1.0-alpha.12</version>
  </dependency>
  ```
</CodeGroup>

The Ruby and Java version numbers above are the versions in each README at the time of writing. Use the README of the repository to find the current version.

<Note>
  The PHP SDK is not on Packagist. Composer installs it from the GitHub repository, as the `repositories` entry in the sample shows.
</Note>

<Note>
  The Java coordinates above are the coordinates in the README of the Java SDK. At the time of writing (2026-10-01), the artifact `com.e_invoice.api:e-invoice-java` is not yet on Maven Central: `repo1.maven.org` returns `404` for it. If your build cannot find the artifact, see the README of the [repository](https://github.com/e-invoice-be/e-invoice-java) for the current status.
</Note>

## Authenticate

Each SDK reads the API key from the environment variable `E_INVOICE_API_KEY`. Do not put the key in your source code.

```bash theme={null}
export E_INVOICE_API_KEY="your-api-key"
```

To get an API key, see [Authentication](/authentication).

## Validate, create and send a document

The samples do the same operations in each language:

1. Create a client and read the account of the API key (`GET /api/me/`).
2. Validate the invoice JSON (`POST /api/validate/json`).
3. Create the document (`POST /api/documents/`). The document is in the `DRAFT` state.
4. Send the document (`POST /api/documents/{document_id}/send`).

<Note>
  Validation is not a separate mandatory call. `POST /api/documents/` rejects a payload that does not pass the same rules. Use `POST /api/validate/json` while you develop, because it returns all rule failures and the generated UBL.
</Note>

<Note>
  The samples use the vendor E-INVOICE BV (`BE1018265814`). Replace `vendor_name`, `vendor_tax_id` and `vendor_address` with the data of your own company. A sandbox company has an assigned VAT number, which you can read from the account response.
</Note>

<CodeGroup>
  ```typescript TypeScript theme={null}
  import EInvoice from 'e-invoice-api';

  // Reads the key from E_INVOICE_API_KEY
  const client = new EInvoice();

  const account = await client.me.retrieve();
  console.log(account.name);

  const invoice: EInvoice.DocumentCreateParams = {
    document_type: 'INVOICE',
    invoice_id: 'INV-2026-001',
    invoice_date: '2026-10-01',
    due_date: '2026-10-31',
    currency: 'EUR',
    vendor_name: 'E-INVOICE BV',
    vendor_tax_id: 'BE1018265814',
    vendor_address: 'Brusselsesteenweg 119/A, 1980 Zemst, Belgium',
    customer_name: 'OpenPeppol VZW',
    customer_tax_id: 'BE0848934496',
    customer_address: 'Robert Schumanplein 6 bus 5, 1040 Brussel, Belgium',
    items: [
      {
        description: 'Professional services',
        quantity: 10,
        unit: 'C62',
        unit_price: 100.0,
        amount: 1000.0,
        tax_rate: '21.00',
      },
    ],
  };

  const validation = await client.validate.validateJson(invoice);
  if (!validation.is_valid) {
    console.error(validation.issues);
    process.exit(1);
  }

  const document = await client.documents.create(invoice);
  console.log(document.id, document.state);

  const sent = await client.documents.send(document.id);
  console.log(sent.state);
  ```

  ```python Python theme={null}
  from e_invoice_api import EInvoice

  # Reads the key from E_INVOICE_API_KEY
  client = EInvoice()

  account = client.me.retrieve()
  print(account.name)

  invoice = {
      "document_type": "INVOICE",
      "invoice_id": "INV-2026-001",
      "invoice_date": "2026-10-01",
      "due_date": "2026-10-31",
      "currency": "EUR",
      "vendor_name": "E-INVOICE BV",
      "vendor_tax_id": "BE1018265814",
      "vendor_address": "Brusselsesteenweg 119/A, 1980 Zemst, BE",
      "customer_name": "OpenPeppol VZW",
      "customer_tax_id": "BE0848934496",
      "customer_address": "Robert Schumanplein 6 bus 5, 1040 Brussel, BE",
      "items": [
          {
              "description": "Professional services",
              "quantity": 10,
              "unit": "C62",
              "unit_price": 100.00,
              "amount": 1000.00,
              "tax_rate": "21.00",
          }
      ],
  }

  validation = client.validate.validate_json(**invoice)
  if not validation.is_valid:
      print(validation.issues)
      raise SystemExit(1)

  document = client.documents.create(**invoice)
  print(document.id, document.state)

  sent = client.documents.send(document.id)
  print(sent.state)
  ```

  ```ruby Ruby theme={null}
  require "bundler/setup"
  require "date"
  require "e_invoice_api"

  # Reads the key from E_INVOICE_API_KEY
  e_invoice = EInvoiceAPI::Client.new

  account = e_invoice.me.retrieve
  puts(account.name)

  invoice = {
    document_type: :INVOICE,
    invoice_id: "INV-2026-001",
    invoice_date: Date.new(2026, 10, 1),
    due_date: Date.new(2026, 10, 31),
    currency: :EUR,
    vendor_name: "E-INVOICE BV",
    vendor_tax_id: "BE1018265814",
    vendor_address: "Brusselsesteenweg 119/A, 1980 Zemst, BE",
    customer_name: "OpenPeppol VZW",
    customer_tax_id: "BE0848934496",
    customer_address: "Robert Schumanplein 6 bus 5, 1040 Brussel, BE",
    items: [
      {
        description: "Professional services",
        quantity: 10,
        unit: :C62,
        unit_price: 100.00,
        amount: 1000.00,
        tax_rate: "21.00"
      }
    ]
  }

  validation = e_invoice.validate.validate_json(**invoice)
  unless validation.is_valid
    puts(validation.issues)
    exit(1)
  end

  document = e_invoice.documents.create(**invoice)
  puts(document.id, document.state)

  sent = e_invoice.documents.send_(document.id)
  puts(sent.state)
  ```

  ```php PHP theme={null}
  <?php

  require __DIR__ . '/vendor/autoload.php';

  use EInvoiceAPI\Client;

  // Reads the key from E_INVOICE_API_KEY
  $client = new Client();

  $account = $client->me->retrieve();
  echo $account->name, PHP_EOL;

  $invoice = [
      'document_type' => 'INVOICE',
      'invoice_id' => 'INV-2026-001',
      'invoice_date' => '2026-10-01',
      'due_date' => '2026-10-31',
      'currency' => 'EUR',
      'vendor_name' => 'E-INVOICE BV',
      'vendor_tax_id' => 'BE1018265814',
      'vendor_address' => 'Brusselsesteenweg 119/A, 1980 Zemst, Belgium',
      'customer_name' => 'OpenPeppol VZW',
      'customer_tax_id' => 'BE0848934496',
      'customer_address' => 'Robert Schumanplein 6 bus 5, 1040 Brussel, Belgium',
      'items' => [
          [
              'description' => 'Professional services',
              'quantity' => 10,
              'unit' => 'C62',
              'unit_price' => 100.00,
              'amount' => 1000.00,
              'tax_rate' => '21.00',
          ],
      ],
  ];

  $validation = $client->validate->validateJson($invoice);
  if (!$validation->is_valid) {
      var_dump($validation->issues);
      exit(1);
  }

  $document = $client->documents->create($invoice);
  echo $document->id, PHP_EOL;

  $sent = $client->documents->send($document->id, []);
  var_dump($sent->state);
  ```

  ```java Java theme={null}
  import com.e_invoice.api.client.EInvoiceClient;
  import com.e_invoice.api.client.okhttp.EInvoiceOkHttpClient;
  import com.e_invoice.api.models.documents.CurrencyCode;
  import com.e_invoice.api.models.documents.DocumentCreate;
  import com.e_invoice.api.models.documents.DocumentResponse;
  import com.e_invoice.api.models.documents.DocumentType;
  import com.e_invoice.api.models.documents.UnitOfMeasureCode;
  import com.e_invoice.api.models.validate.UblDocumentValidation;
  import java.time.LocalDate;

  public class SendInvoice {
      public static void main(String[] args) {
          // Reads the key from E_INVOICE_API_KEY
          EInvoiceClient client = EInvoiceOkHttpClient.fromEnv();

          DocumentCreate invoice = DocumentCreate.builder()
              .documentType(DocumentType.INVOICE)
              .invoiceId("INV-2026-001")
              .invoiceDate(LocalDate.of(2026, 10, 1))
              .dueDate(LocalDate.of(2026, 10, 31))
              .currency(CurrencyCode.EUR)
              .vendorName("E-INVOICE BV")
              .vendorTaxId("BE1018265814")
              .vendorAddress("Brusselsesteenweg 119/A, 1980 Zemst, BE")
              .customerName("OpenPeppol VZW")
              .customerTaxId("BE0848934496")
              .customerAddress("Robert Schumanplein 6 bus 5, 1040 Brussel, BE")
              .addItem(DocumentCreate.Item.builder()
                  .description("Professional services")
                  .quantity(10.0)
                  .unit(UnitOfMeasureCode.C62)
                  .unitPrice(100.00)
                  .amount(1000.00)
                  .taxRate("21.00")
                  .build())
              .build();

          UblDocumentValidation validation = client.validate().validateJson(invoice);
          if (!validation.isValid()) {
              System.err.println(validation.issues());
              System.exit(1);
          }

          DocumentResponse document = client.documents().create(invoice);
          System.out.println(document.id());

          DocumentResponse sent = client.documents().send(document.id());
          System.out.println(sent.state());
      }
  }
  ```
</CodeGroup>

<Warning>
  The Java SDK is an alpha release. It does not have the account resource (`GET /api/me/`), thus the Java sample starts with the validation step.
</Warning>

The send call accepts the optional routing parameters `sender_peppol_scheme`, `sender_peppol_id`, `receiver_peppol_scheme`, `receiver_peppol_id` and `email`. In Java, the names are in camel case in `DocumentSendParams`. See [Create e-invoices](/guides/creating-invoices) for when to set them.

With a sandbox company, the send call does not use the Peppol network. See [Test mode and sandbox companies](/environments).

## Method names for each SDK

| Operation | TypeScript | Python | Ruby | PHP | Java |
| - | - | - | - | - | - |
| Get account | `client.me.retrieve()` | `client.me.retrieve()` | `me.retrieve` | `$client->me->retrieve()` | Not available |
| Validate JSON | `client.validate.validateJson()` | `client.validate.validate_json()` | `validate.validate_json` | `$client->validate->validateJson()` | `client.validate().validateJson()` |
| Create document | `client.documents.create()` | `client.documents.create()` | `documents.create` | `$client->documents->create()` | `client.documents().create()` |
| Send document | `client.documents.send()` | `client.documents.send()` | `documents.send_` | `$client->documents->send()` | `client.documents().send()` |

<Note>
  In Ruby, the send method has the name `send_` with an underscore at the end, because `send` is a method of each Ruby object.
</Note>

The TypeScript and Python repositories have a file `api.md` with the full list of methods.

## Versions and the OpenAPI specification

The API has one OpenAPI specification, which is version 1.1.0 at this time. Each SDK is generated from this specification, but each SDK has its own version number. An SDK version number does not agree with the version number of the specification.

* The TypeScript, Python and Java SDKs follow semantic versioning, with the exceptions that each README gives.
* The Ruby and PHP SDKs have major version `0`. Their README states that the interface can change at any time.
* A new endpoint can be in the API before it is in an SDK. The [API reference](/api-reference) always shows the current API. Each README shows how to call an endpoint that the SDK does not have yet.

## Report a problem

Report a problem with an SDK in the issues of its repository:

* [e-invoice-ts issues](https://github.com/e-invoice-be/e-invoice-ts/issues)
* [e-invoice-py issues](https://github.com/e-invoice-be/e-invoice-py/issues)
* [e-invoice-rb issues](https://github.com/e-invoice-be/e-invoice-rb/issues)
* [e-invoice-php issues](https://github.com/e-invoice-be/e-invoice-php/issues)
* [e-invoice-java issues](https://github.com/e-invoice-be/e-invoice-java/issues)

## Next Steps

<CardGroup cols={2}>
  <Card title="peppol CLI" icon="terminal" href="/cli">
    Validate, create and send documents from the command line
  </Card>

  <Card title="Create e-invoices" icon="file-invoice" href="/guides/creating-invoices">
    Learn the fields of an invoice
  </Card>

  <Card title="Errors and troubleshooting" icon="triangle-exclamation" href="/guides/errors">
    Handle the errors that the API returns
  </Card>

  <Card title="API reference" icon="code" href="/api-reference">
    See all endpoints and schemas
  </Card>
</CardGroup>
