VUZDevelopers

Quickstart

API key to your first signed, VAT-compliant document in 5 minutes.

By the end of this guide you'll have:

  1. ✅ Created a sandbox API key with the right scopes
  2. ✅ Created a client
  3. ✅ Created and finalized a tax_invoice_receipt document
  4. ✅ Previewed the generated PDF

Total reading time: 5 minutes. The whole walkthrough runs against the sandbox (https://sandbox-api.vuz.co.il) — a real, isolated environment with its own database, so nothing you do here creates a real document, sends a real message, or charges anyone. Going live at the end is a two-line change.

מעדיפ/ה עברית? יש מדריך זהה בעברית — קוד ותשובות ה-API נשארים באנגלית בכל השפות.

Step 1 — Create a sandbox API key

API keys are created from the VUZ dashboard, not the API itself (creating a key requires a logged-in dashboard session — you can't mint a key with a key). Go to Settings → Integrations → API Keys → "Sandbox key" — this mirrors your business into the isolated sandbox database and mints a key that works only on https://sandbox-api.vuz.co.il. It's the same endpoint your browser calls:

POST https://api.vuz.co.il/api/v1/api-keys/sandbox
Authorization: Bearer <your dashboard JWT>
X-Business-Id: <your business id>

The response includes the raw key once:

{
  "businessId": "b6b0b8b0-...",
  "rawKey": "vuz_ab12cdef3456789012345678901234567890abcdef12",
  "keyPrefix": "vuz_ab12",
  "environment": "sandbox",
  "created": true
}

The sandbox key is minted with the full canonical scope set, so every walkthrough call below just works. Store rawKey securely — it is never shown again. Every request from here on sends it as X-Api-Key. Note the key's string looks the same in both environments (vuz_...) — isolation comes from the completely separate sandbox database, not the prefix (see Auth → API keys).

When you later create a production key (Settings → Integrations → API Keys → Generate), you choose its scopes yourself — use the canonical scope strings, not the short legacy names shown on some older screens (read, write, documents). The routes below check for an exact string match against documents:write, documents:finalize, clients:write, etc. — see Auth → Scopes for the full list of canonical scopes.

Step 2 — Create a client

curl -X POST https://sandbox-api.vuz.co.il/api/v1/clients \
  -H "X-Api-Key: vuz_ab12cdef3456789012345678901234567890abcdef12" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Dana Cohen",
    "email": "dana@example.com"
  }'
const res = await fetch('https://sandbox-api.vuz.co.il/api/v1/clients', {
  method: 'POST',
  headers: {
    'X-Api-Key': process.env.VUZ_API_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ name: 'Dana Cohen', email: 'dana@example.com' }),
});
const client = await res.json();
console.log('Client ID:', client.id);
import os, requests

res = requests.post(
    'https://sandbox-api.vuz.co.il/api/v1/clients',
    headers={'X-Api-Key': os.environ['VUZ_API_KEY']},
    json={'name': 'Dana Cohen', 'email': 'dana@example.com'},
)
client = res.json()
print('Client ID:', client['id'])
<?php
$ch = curl_init('https://sandbox-api.vuz.co.il/api/v1/clients');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => ['X-Api-Key: ' . getenv('VUZ_API_KEY'), 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => json_encode(['name' => 'Dana Cohen', 'email' => 'dana@example.com']),
]);
$client = json_decode(curl_exec($ch), true);
echo 'Client ID: ' . $client['id'];

No X-Business-Id header — the API key itself is bound to your business (see Concepts → Business).

Response (trimmed):

{
  "id": "9b2f6b2e-2e1e-4b7e-9f1e-1e2e3e4e5e6e",
  "name": "Dana Cohen",
  "email": "dana@example.com",
  "type": "private"
}

Step 3 — Issue a document

The VAT rate below (17%) is illustrative. Your business's real rate lives on GET /businesses/current (vatRate field) — read it before computing lineVatTotal for real traffic. The server re-computes and rejects the request (±0.01 tolerance) if your totals don't match.

curl -X POST https://sandbox-api.vuz.co.il/api/v1/documents \
  -H "X-Api-Key: vuz_ab12cdef3456789012345678901234567890abcdef12" \
  -H "Content-Type: application/json" \
  -d '{
    "clientId": "9b2f6b2e-2e1e-4b7e-9f1e-1e2e3e4e5e6e",
    "docType": "tax_invoice_receipt",
    "issueDate": "2026-07-01",
    "vatMode": "exclusive",
    "items": [
      {
        "description": "Consulting - 2 hours",
        "quantity": 2,
        "unitPrice": 150,
        "vatApplicable": true,
        "vatRate": 17,
        "lineSubTotal": 300,
        "lineVatTotal": 51,
        "lineGrandTotal": 351
      }
    ],
    "subTotal": 300,
    "vatTotal": 51,
    "grandTotal": 351
  }'

Response — a DRAFT document (no document number yet; VUZ assigns one on finalize):

{
  "id": "205bd0d9-0c71-419f-989e-d5b2b790fe85",
  "docType": "tax_invoice_receipt",
  "status": "draft",
  "issueDate": "2026-07-01",
  "clientId": "9b2f6b2e-2e1e-4b7e-9f1e-1e2e3e4e5e6e",
  "subTotal": "300.00",
  "vatTotal": "51.00",
  "grandTotal": "351.00",
  "currency": "ILS"
}

Step 4 — Finalize it

POST /documents creates a DRAFT. Finalizing is a separate call (and a separate scope, documents:finalize) — it assigns the sequential document number, generates the signed PDF, and — where required — requests an allocation number from the Tax Authority:

curl -X POST https://sandbox-api.vuz.co.il/api/v1/documents/205bd0d9-0c71-419f-989e-d5b2b790fe85/finalize \
  -H "X-Api-Key: vuz_ab12cdef3456789012345678901234567890abcdef12"

The document comes back as ISSUED, numbered, and immutable. See Concepts → Documents for the full DRAFT → ISSUED lifecycle and which document types apply per business type.

In the sandbox nothing legally binding happens: Tax Authority calls go to the Authority's own test environment, and the PDF is watermarked "SANDBOX — NOT A LEGAL DOCUMENT". In production this same call produces a real, signed, legally final document — that's the point.

Step 5 — Preview the PDF

curl "https://sandbox-api.vuz.co.il/api/v1/documents/205bd0d9-0c71-419f-989e-d5b2b790fe85/pdf/preview" \
  -H "X-Api-Key: vuz_ab12cdef3456789012345678901234567890abcdef12" \
  -o preview.pdf

Returns Content-Type: application/pdf. Draft documents render with a DRAFT watermark; pass ?draft=false once the document is finalized. ?language=he|en controls the PDF language (defaults to he).

Going live

Two changes:

  1. Create a production key: Settings → Integrations → API Keys → Generate, granting only the scopes you actually use.
  2. Swap the base URL to https://api.vuz.co.il/api/v1.

A sandbox key never works on production (and vice versa) — the environments have fully separate databases, and every response tells you who answered via the X-Vuz-Environment: live|sandbox header.

You did it 🎉

On this page