HomeDocsAPI

REST API v1

Integriere time2invoice mit deiner Buchhaltungssoftware, Automatisierungs-Tools oder eigenen Anwendungen. Die API gibt dir vollen Zugriff auf Rechnungen, Kunden, Zeiterfassung und EÜR-Berichte.

https://good-roadrunner-663.convex.site/api/v1/
Nur Pro-Plan

Authentifizierung

Alle API-Anfragen müssen mit einem API-Key authentifiziert werden. Erstelle einen Key unter Einstellungen → API-Zugang.

Sende den Key im Authorization-Header:

curl
curl -H "Authorization: Bearer t2i_deinApiKey..." \
  https://good-roadrunner-663.convex.site/api/v1/invoices
JavaScript (fetch)
const response = await fetch("https://good-roadrunner-663.convex.site/api/v1/invoices", {
  headers: {
    "Authorization": "Bearer t2i_deinApiKey...",
    "Content-Type": "application/json"
  }
});

const { data, meta, error } = await response.json();

⚠️ Sicherheitshinweis: API-Keys haben vollen Zugriff auf deinen Account. Teile sie niemals öffentlich und verwende sie nur in Server-seitigem Code, niemals im Frontend.

Rate Limiting

Die API erlaubt 100 Anfragen pro Minute pro API-Key. Bei Überschreitung erhältst du einen 429-Status.

HeaderBeschreibung
X-RateLimit-LimitMaximale Anfragen pro Fenster (100)
X-RateLimit-RemainingVerbleibende Anfragen
Retry-AfterSekunden bis zum nächsten Fenster

Response-Format

Alle Antworten folgen einem konsistenten JSON-Format:

Erfolg
{
  "data": { ... },
  "meta": { "total": 42 },
  "error": null
}
Fehler
{
  "data": null,
  "meta": null,
  "error": "Invalid or expired API key. Pro plan required."
}

Invoices (Rechnungen)

GET/api/v1/invoices

Alle Rechnungen auflisten. Optional nach Status filtern.

Query-Parameter

statusstring"draft" | "sent" | "paid"

Response

{
  "data": [
    {
      "_id": "jd7x...",
      "invoiceNumber": "FR-2026-001",
      "customerId": "k3f9...",
      "invoiceDate": 1735689600000,
      "netAmount": 2400,
      "status": "sent",
      "activityType": "freiberuflich",
      "taxRate": 0,
      "taxAmount": 0,
      "grossAmount": 2400,
      "createdAt": 1735689600000
    }
  ],
  "meta": { "total": 1 },
  "error": null
}
POST/api/v1/invoices

Neue Rechnung erstellen (Status: draft).

Request Body (JSON)

customerIdstringrequiredKunden-ID
invoiceNumberstringrequiredz.B. "FR-2026-002"
invoiceDatenumberrequiredUnix-Timestamp (ms)
periodStartnumberrequiredLeistungszeitraum Start
periodEndnumberrequiredLeistungszeitraum Ende
netAmountnumberrequiredNettobetrag in Euro
notesstringAnmerkungen
taxRatenumberUSt-Satz (0 = Kleinunternehmer)
taxAmountnumberUSt-Betrag
grossAmountnumberBruttobetrag
activityTypestring"freiberuflich" | "gewerblich"

Response

{
  "data": { "id": "jd7x..." },
  "meta": { "created": true },
  "error": null
}

Customers (Kunden)

GET/api/v1/customers

Alle aktiven Kunden auflisten.

Response

{
  "data": [
    {
      "_id": "k3f9...",
      "name": "Acme GmbH",
      "email": "info@acme.de",
      "address": "Musterstr. 1, 10115 Berlin",
      "hourlyRate": 90,
      "isActive": true,
      "activityType": "freiberuflich"
    }
  ],
  "meta": { "total": 1 },
  "error": null
}
POST/api/v1/customers

Neuen Kunden erstellen.

Request Body (JSON)

namestringrequiredKundenname
hourlyRatenumberrequiredStundensatz in Euro
emailstringE-Mail-Adresse
addressstringAnschrift
taxNumberstringSteuernummer des Kunden
ustIdstringUSt-IdNr. des Kunden
activityTypestring"freiberuflich" | "gewerblich"

Response

{
  "data": { "id": "k3f9..." },
  "meta": { "created": true },
  "error": null
}

Time Entries (Zeiteinträge)

GET/api/v1/time-entries

Zeiteinträge auflisten. Optional nach Zeitraum filtern.

Query-Parameter

fromstringStartdatum (ISO 8601, z.B. 2026-01-01)
tostringEnddatum (ISO 8601)

Response

{
  "data": [
    {
      "_id": "te42...",
      "projectId": "p1x7...",
      "customerId": "k3f9...",
      "startTime": 1735689600000,
      "endTime": 1735700400000,
      "durationMinutes": 180,
      "description": "UI-Entwicklung Login-Page",
      "isRunning": false
    }
  ],
  "meta": { "total": 1 },
  "error": null
}
POST/api/v1/time-entries

Neuen Zeiteintrag erstellen (abgeschlossen, kein laufender Timer).

Request Body (JSON)

projectIdstringrequiredProjekt-ID
customerIdstringrequiredKunden-ID
startTimenumberrequiredStartzeit (Unix-Timestamp ms)
endTimenumberrequiredEndzeit (Unix-Timestamp ms)
descriptionstringBeschreibung der Tätigkeit

Response

{
  "data": { "id": "te42..." },
  "meta": { "created": true },
  "error": null
}

Projects (Projekte)

GET/api/v1/projects

Alle aktiven Projekte auflisten.

Response

{
  "data": [
    {
      "_id": "p1x7...",
      "name": "Website Redesign",
      "customerId": "k3f9...",
      "color": "#3b82f6",
      "isActive": true,
      "activityType": "freiberuflich"
    }
  ],
  "meta": { "total": 1 },
  "error": null
}

Reports (Berichte)

GET/api/v1/reports/eur

EÜR-Daten (Einnahme-Überschuss-Rechnung) für ein Jahr abrufen. Getrennt nach freiberuflich/gewerblich.

Query-Parameter

yearnumberJahr (z.B. 2026). Default: aktuelles Jahr

Response

{
  "data": {
    "year": 2026,
    "income": {
      "total": 48000,
      "byType": {
        "freiberuflich": 36000,
        "gewerblich": 12000
      },
      "invoiceCount": 24
    },
    "expenses": {
      "total": 8500,
      "count": 42
    },
    "profit": 39500
  },
  "meta": null,
  "error": null
}

Webhooks

Registriere Webhook-Endpoints unter Einstellungen → API-Zugang um Echtzeit-Benachrichtigungen zu erhalten.

Verfügbare Events

EventBeschreibungAuslöser
invoice.createdNeue Rechnung erstelltRechnung wird als Draft angelegt
invoice.sentRechnung versendetStatus wechselt zu 'sent'
invoice.paidZahlung eingegangenStatus wechselt zu 'paid'
invoice.reminder_sentMahnung versendetZahlungserinnerung/Mahnung per E-Mail verschickt
customer.createdNeuer Kunde angelegtKunde wird erstellt
expense.createdNeue Ausgabe erfasstAusgabe wird erstellt

Payload-Format

Webhook Payload
POST https://dein-server.de/webhook
Content-Type: application/json
X-T2I-Event: invoice.created
X-T2I-Signature: a1b2c3d4e5f6...

{
  "event": "invoice.created",
  "timestamp": "2026-01-15T10:30:00.000Z",
  "data": {
    "id": "jd7x...",
    "invoiceNumber": "FR-2026-003",
    "netAmount": 1800
  }
}

Signatur-Verifizierung

Jeder Webhook-Request enthält einen X-T2I-Signature-Header mit einer HMAC-SHA256 Signatur des Request-Bodys, erstellt mit deinem Webhook-Secret.

Node.js — Signatur verifizieren
import crypto from "crypto";

function verifyWebhookSignature(body, signature, secret) {
  const expected = crypto
    .createHmac("sha256", secret)
    .update(body, "utf-8")
    .digest("hex");

  return crypto.timingSafeEqual(
    Buffer.from(signature, "hex"),
    Buffer.from(expected, "hex")
  );
}

// In deinem Webhook-Handler:
app.post("/webhook", (req, res) => {
  const signature = req.headers["x-t2i-signature"];
  const isValid = verifyWebhookSignature(
    JSON.stringify(req.body),
    signature,
    "whsec_deinSecret..."
  );

  if (!isValid) {
    return res.status(401).send("Invalid signature");
  }

  const { event, data } = req.body;
  console.log(`Event: ${event}`, data);
  res.status(200).send("OK");
});

Fehlerbehandlung

StatusBedeutungLösung
400Ungültige AnfragePrüfe die Request-Parameter und den JSON-Body
401Nicht authentifiziertAuthorization-Header mit gültigem API-Key senden
403Zugriff verweigertAPI-Key ist abgelaufen oder Pro-Plan erforderlich
429Rate Limit überschrittenWarte und versuche es erneut (siehe Retry-After Header)
500ServerfehlerVersuche es erneut. Bei Wiederholung: Support kontaktieren

🚀 Quick Start

Komplett-Beispiel: Alle Rechnungen abrufen und den Gesamtumsatz berechnen.

JavaScript — Umsatz berechnen
const API_KEY = "t2i_deinApiKey...";
const BASE = "https://good-roadrunner-663.convex.site/api/v1";

async function getTotalRevenue() {
  const res = await fetch(`${BASE}/invoices?status=paid`, {
    headers: { "Authorization": `Bearer ${API_KEY}` }
  });

  const { data, error } = await res.json();
  if (error) throw new Error(error);

  const total = data.reduce((sum, inv) => sum + inv.netAmount, 0);
  console.log(`Gesamtumsatz (bezahlt): ${total.toFixed(2)} €`);
  console.log(`Anzahl Rechnungen: ${data.length}`);
  return total;
}

getTotalRevenue();

Fragen zur API? Schreib uns an support@time2invoice.de