Easy Invoice

repository·master·Indexed 41 days ago

https://github.com/dashweb-bv/easyinvoice

A Node.js tool and REST API for programmatically creating professional PDF invoices with server-side calculations. Supports TypeScript, CommonJS, and ES modules, requiring Node.js 22.14+. Features include the `createInvoice` method for generating PDFs via temporary URLs or base64 strings, and `saveInvoice` for local file storage.

Tokens
6.2K
Snippets
16
Records
27
Agent score
51%

What's inside Easy Invoice

  1. Install easyinvoice via npm

    master

    Install the easyinvoice package using your preferred package manager. Requires Node.js 22.14+. The package includes TypeScript types and supports CommonJS and tree-shakeable ES modules. Note that the npm package is backend-only and requires an internet connection to contact the hosted API.

    npm install easyinvoice
  2. Migrate from version 3 to version 4

    master

    Version 4 introduces several breaking changes to improve security and modernise the API:

    • Backend-only focus: Browser/CDN entry points and PDF rendering/printing helpers (download, print, render, etc.) have been removed to prevent leaking API keys. Use a server-side environment.
    • API Changes: Replace new EasyInvoice().createInvoice(data) with the top-level createInvoice(data) or easyinvoice.createInvoice(data).
    • Async/Await: Replace callbacks with await or .then()/.catch().
    • Error Handling: Use EasyInvoiceError. Access the response body via error.body and the HTTP status via error.status.
    • Runtime: Node.js 22.14+ is required.
    • Output Change: In v4.0.0–v4.0.4, base64 was the default. In the revised v4, the default is URL metadata. To keep using base64, pass { output: "base64" } or switch to saveInvoice() for file writing.
  3. Access the Easy Invoice API via REST

    master

    You can use the Easy Invoice service without an npm package by making a POST request to the v3 HTTP endpoint. The request body must be a JSON object with an outer data property.

    Endpoint: https://api.easyinvoice.cloud/v3/free/invoices (for free access) or use Authorization: Bearer <your-api-key> for account access.

    Response: The API returns a JSON object containing data.pdfUrl, data.expiresAt, and data.calculations. The PDF download URL is temporary and typically expires within five minutes.

    curl --fail-with-body https://api.easyinvoice.cloud/v3/free/invoices \
      -H 'Content-Type: application/json' \
      --data-binary @- <<EOF
    {
      "data": {
        "mode": "development",
        "sender": { "company": "Sample Corp" },
        "client": { "company": "Client Corp" },
        "information": { "number": "2026.0001", "date": "09/11/2026", "dueDate": "09/25/2026" },
        "products": [{ "quantity": 2, "description": "Consulting", "taxRate": 8.25, "price": 75 }],
        "settings": { "currency": "USD", "locale": "en-US", "format": "Letter" }
      }
    }
    EOF
  4. Understand API-calculated totals in InvoiceCalculations

    master

    The API returns a InvoiceCalculations object so that the client can display rounded amounts without performing its own math. This ensures the client-side display matches the official invoice.

    Structure:

    • subtotal: Combined product amount excluding tax.
    • total: Combined product amount including tax.
    • tax: A TaxCalculations object (a Record<number, number>) where keys are tax rates and values are the total tax amount for that rate (e.g., { "8.25": 16.5 }).
    • products: An array of ProductCalculations for each line item, providing the subtotal, tax, and total for that specific item.
  5. Use Easy Invoice in CommonJS environments

    master

    For server-side Node.js applications using CommonJS, you can require the easyinvoice package. The client provides a stateless createInvoice() method that returns a Promise resolving to the invoice result or rejecting with an EasyInvoiceError.

    Note: This entrypoint uses the synchronous require(esm) feature available in Node.js 22.14+.

    import easyinvoice = require("easyinvoice");
    
    easyinvoice.createInvoice()
      .then((result) => console.log(result))
      .catch((error) => console.error(error));
  6. Handle EasyInvoiceError and request failures

    master

    Requests may fail due to HTTP errors, network issues, or invalid arguments.

    • Invalid Arguments: Throws a TypeError locally before any network request is made.
    • API/HTTP Errors: Throws an EasyInvoiceError. You can inspect error.status (e.g., 429 for rate limiting) and error.body (the parsed JSON or plain text response from the server).
    • Network Failures: status will be undefined, and the underlying cause is exposed via error.cause.
    • Timeouts: Both createInvoice (including the download for base64) and saveInvoice have a 30-second deadline.
    import { createInvoice, EasyInvoiceError } from "easyinvoice";
    
    try {
      await createInvoice(data);
    } catch (error) {
      if (error instanceof EasyInvoiceError && error.status === 429) {
        // Back off and retry later.
      }
      throw error;
    }
  7. Create an invoice with easyinvoice

    master

    Use createInvoice to send invoice data to the hosted API and saveInvoice to save the resulting PDF locally.

    Important:

    • Set "type": "module" in your package.json if using TypeScript/ESM.
    • Use mode: "development" to add an EXAMPLE watermark.
    • For production, omit mode or set it to "production".
    • Provide an apiKey in the data object (or via a Bearer header) for account access; otherwise, it uses free access.
    import easyinvoice, { type InvoiceData } from "easyinvoice";
    
    const data: InvoiceData = {
      mode: "development",
      sender: {
        company: "Sample Corp",
        address: "123 Main Street",
        zip: "78701",
        city: "Austin, TX",
        country: "United States",
      },
      client: {
        company: "Client Corp",
        address: "456 Oak Avenue",
        zip: "75201",
        city: "Dallas, TX",
        country: "United States",
      },
      information: {
        number: "2026.0001",
        date: "09/11/2026",
        dueDate: "09/25/2026",
      },
      products: [
        {
          quantity: 2,
          description: "Consulting",
          taxRate: 8.25,
          price: 75,
        },
      ],
      bottomNotice: "Please pay within 14 days.",
      settings: { currency: "USD", locale: "en-US", format: "Letter" },
    };
    
    const apiKey = process.env.EASYINVOICE_API_KEY;
    if (apiKey) data.apiKey = apiKey;
    
    easyinvoice
      .createInvoice(data)
      .then((result) => easyinvoice.saveInvoice(result, "invoice.pdf"))
      .catch((error) => console.error(error));
  8. Create multiple invoices concurrently

    master

    The client is stateless. Each call to createInvoice is independent and counts against your service limits. You can use Promise.all to trigger multiple creations simultaneously.

    const invoices = await Promise.all([
      easyinvoice.createInvoice(firstInvoice),
      easyinvoice.createInvoice(secondInvoice),
    ]);
  9. Get base64 encoded PDF output

    master

    By default, createInvoice returns a temporary URL. To receive the PDF as a base64-encoded string instead, pass { output: "base64" } in the options object. This will cause the client to download and encode the PDF locally, returning a CreateInvoiceBase64Result which contains a pdf field instead of pdfUrl and expiresAt.

    const result = await easyinvoice.createInvoice(data, { output: "base64" });
    // result.pdf contains the base64-encoded PDF.
  10. Use the easyinvoice API

    master

    The easyinvoice package provides two primary methods for managing invoices:

    1. createInvoice(data?: InvoiceData): Sends invoice data to the server. Returns a Promise<CreateInvoiceResult> containing metadata and server-side calculations. Note: This method does not download the PDF file itself; it returns a temporary URL.
    2. saveInvoice(result, filename): Streams an existing PDF from a CreateInvoiceResult to disk. This is more efficient than manual downloading as it avoids buffering or base64 conversion.

    Important: Download URLs expire after five minutes. Do not use them as permanent links or log their signed query strings.

    // Create an invoice (returns metadata and a temporary URL)
    const result = await createInvoice(data);
    
    // Save the invoice to a file (streams the PDF to disk)
    await saveInvoice(result, 'path/to/invoice.pdf');
  11. Configure createInvoice output format

    master

    When calling createInvoice, you can control how the resulting PDF is delivered using the options parameter.

    OptionTypeDescription
    output'url' (default)Returns a CreateInvoiceResult containing a pdfUrl and expiresAt timestamp.
    output'base64'Downloads the PDF and returns a CreateInvoiceBase64Result containing a pdf field with the base64-encoded string.

    Example: Requesting Base64 output

    const result = await createInvoice(data, { output: 'base64' });
    console.log(result.pdf); // The base64 string
  12. Understand createInvoice return values

    master

    The createInvoice() method returns an object that includes both metadata for the download and server-side calculations.

    Default Output (URL mode):

    • result.pdfUrl: Temporary signed PDF URL.
    • result.expiresAt: URL expiry as an ISO 8601 timestamp.

    Base64 Output ({ output: "base64" }):

    • result.pdf: The base64-encoded PDF string.

    Calculations (Available in both modes):

    • result.calculations.products: Array of per-product subtotal, tax, and total.
    • result.calculations.tax: Object mapping each tax rate to its total tax amount.
    • result.calculations.subtotal: Combined amount excluding tax.
    • result.calculations.total: Combined amount including tax.