Products API
Products (Produkte) ermöglichen es Ihnen, wiederverwendbare Produkte und Dienstleistungen zu verwalten. Products können in Rechnungen und Offerten verwendet werden, um Positionen schnell zu erfassen.
Product-Objekt
{
"data": {
"id": 42,
"company_id": 123,
"user_id": 456,
"name": "Webdesign Paket Standard",
"description": "Webdesign Paket inkl. 5 Seiten, Responsive Design, SEO-Optimierung",
"price": 3500.00,
"formatted_price": "CHF 3,500.00",
"unit": "Paket",
"archived": false,
"created_at": "2023-06-04T15:23:12.000000Z",
"updated_at": "2025-01-14T10:45:00.000000Z"
}
}Attribute
| Feld | Typ | Beschreibung |
|---|---|---|
id | integer | Eindeutige Product-ID |
company_id | integer | ID der zugehörigen Firma |
user_id | integer | ID des Benutzers, der das Product erstellt hat |
name | string | Name des Produkts (erforderlich) |
description | string|null | Detaillierte Beschreibung |
price | decimal|null | Standardpreis |
formatted_price | string|null | Formatierter Preis mit Währung |
unit | string|null | Einheit (z.B. "Stunde", "Stück", "Paket", "m²") |
archived | boolean | Ob das Product archiviert ist |
created_at | datetime | Erstellungsdatum |
updated_at | datetime | Datum der letzten Aktualisierung |
Endpoints
Alle Products auflisten
GET /companies/{company}/productsRuft eine paginierte Liste aller Products der Firma ab.
Parameter
| Parameter | Typ | Standard | Beschreibung |
|---|---|---|---|
page | integer | 1 | Seitennummer |
per_page | integer | 15 | Anzahl Products pro Seite (max. 100) |
filter[name] | string | - | Filtern nach Name (Teilübereinstimmung) |
filter[archived] | boolean | - | Filtern nach Archivierungsstatus (exakte Übereinstimmung) |
filter[id] | integer | - | Filtern nach spezifischer Product-ID (exakte Übereinstimmung) |
sort | string | - | Sortierung: name, -name, price, -price |
Response
{
"data": [
{
"id": 42,
"company_id": 123,
"user_id": 456,
"name": "Webdesign Paket Standard",
"description": "Webdesign Paket inkl. 5 Seiten, Responsive Design, SEO-Optimierung",
"price": 3500.00,
"formatted_price": "CHF 3,500.00",
"unit": "Paket",
"archived": false,
"created_at": "2023-06-04T15:23:12.000000Z",
"updated_at": "2025-01-14T10:45:00.000000Z"
},
{
"id": 43,
"company_id": 123,
"user_id": 456,
"name": "Beratungsstunde",
"description": "Technische Beratung zu Software-Architektur",
"price": 150.00,
"formatted_price": "CHF 150.00",
"unit": "Stunde",
"archived": false,
"created_at": "2023-06-05T09:15:00.000000Z",
"updated_at": "2025-01-14T10:45:00.000000Z"
}
],
"links": {
"first": "https://app.milkee.ch/api/v2/companies/123/products?page=1",
"last": "https://app.milkee.ch/api/v2/companies/123/products?page=3",
"prev": null,
"next": "https://app.milkee.ch/api/v2/companies/123/products?page=2"
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 3,
"path": "https://app.milkee.ch/api/v2/companies/123/products",
"per_page": 15,
"to": 15,
"total": 42
}
}Beispiele
# Alle Products abrufen
curl -H "Authorization: Bearer 1|abcdef123456789..." \
"https://app.milkee.ch/api/v2/companies/123/products"
# Suche nach Namen (Teilübereinstimmung)
curl -H "Authorization: Bearer 1|abcdef123456789..." \
"https://app.milkee.ch/api/v2/companies/123/products?filter[name]=Webdesign"
# Nur aktive Products
curl -H "Authorization: Bearer 1|abcdef123456789..." \
"https://app.milkee.ch/api/v2/companies/123/products?filter[archived]=false"
# Sortiert nach Preis absteigend
curl -H "Authorization: Bearer 1|abcdef123456789..." \
"https://app.milkee.ch/api/v2/companies/123/products?sort=-price"
# Sortiert nach Name aufsteigend
curl -H "Authorization: Bearer 1|abcdef123456789..." \
"https://app.milkee.ch/api/v2/companies/123/products?sort=name"Neues Product erstellen
POST /companies/{company}/productsErstellt ein neues Product für die angegebene Firma.
Request Body
{
"name": "Webdesign Paket Standard",
"description": "Webdesign Paket inkl. 5 Seiten, Responsive Design, SEO-Optimierung",
"price": 3500.00,
"unit": "Paket"
}Validierung
| Feld | Regeln |
|---|---|
name | required, string, max:255 |
description | nullable, string |
price | nullable, numeric, min:0, max:999999.99 |
unit | nullable, string, max:255 |
Response
HTTP/1.1 200 OK
Content-Type: application/json
{
"data": {
"id": 42,
"company_id": 123,
"user_id": 456,
"name": "Webdesign Paket Standard",
"description": "Webdesign Paket inkl. 5 Seiten, Responsive Design, SEO-Optimierung",
"price": 3500.00,
"formatted_price": "CHF 3,500.00",
"unit": "Paket",
"archived": false,
"created_at": "2025-01-14T14:22:00.000000Z",
"updated_at": "2025-01-14T14:22:00.000000Z"
}
}Beispiele
# Einfaches Product erstellen
curl -X POST \
-H "Authorization: Bearer 1|abcdef123456789..." \
-H "Content-Type: application/json" \
-d '{
"name": "Webdesign Paket Standard",
"price": 3500.00,
"unit": "Paket"
}' \
"https://app.milkee.ch/api/v2/companies/123/products"
# Product mit Beschreibung
curl -X POST \
-H "Authorization: Bearer 1|abcdef123456789..." \
-H "Content-Type: application/json" \
-d '{
"name": "Beratungsstunde",
"description": "Technische Beratung zu Software-Architektur",
"price": 150.00,
"unit": "Stunde"
}' \
"https://app.milkee.ch/api/v2/companies/123/products"
# Dienstleistung ohne Preis (wird bei Verwendung individuell festgelegt)
curl -X POST \
-H "Authorization: Bearer 1|abcdef123456789..." \
-H "Content-Type: application/json" \
-d '{
"name": "Individuelles Projekt",
"description": "Preis wird projektspezifisch festgelegt"
}' \
"https://app.milkee.ch/api/v2/companies/123/products"Einzelnes Product abrufen
GET /companies/{company}/products/{product}Ruft die Details eines spezifischen Products ab.
Parameter
| Parameter | Typ | Beschreibung |
|---|---|---|
company | integer | Firmen-ID |
product | integer | Product-ID |
Response
{
"data": {
"id": 42,
"company_id": 123,
"user_id": 456,
"name": "Webdesign Paket Standard",
"description": "Webdesign Paket inkl. 5 Seiten, Responsive Design, SEO-Optimierung",
"price": 3500.00,
"formatted_price": "CHF 3,500.00",
"unit": "Paket",
"archived": false,
"created_at": "2023-06-04T15:23:12.000000Z",
"updated_at": "2025-01-14T10:45:00.000000Z"
}
}Beispiel
curl -H "Authorization: Bearer 1|abcdef123456789..." \
"https://app.milkee.ch/api/v2/companies/123/products/42"Product aktualisieren
PUT /companies/{company}/products/{product}Aktualisiert ein bestehendes Product.
Request Body
{
"name": "Webdesign Paket Standard (aktualisiert)",
"description": "Webdesign Paket inkl. 5 Seiten, Responsive Design, SEO-Optimierung, Social Media Integration",
"price": 3750.00,
"unit": "Paket",
"archived": false
}Validierung
| Feld | Regeln |
|---|---|
name | sometimes, required, string, max:255 |
description | nullable, string |
price | nullable, numeric, min:0, max:999999.99 |
unit | nullable, string, max:255 |
archived | sometimes, boolean |
Teilweise Updates
Alle Felder sind optional. Sie können nur die Felder übermitteln, die geändert werden sollen.
Response
{
"data": {
"id": 42,
"company_id": 123,
"user_id": 456,
"name": "Webdesign Paket Standard (aktualisiert)",
"description": "Webdesign Paket inkl. 5 Seiten, Responsive Design, SEO-Optimierung, Social Media Integration",
"price": 3750.00,
"formatted_price": "CHF 3,750.00",
"unit": "Paket",
"archived": false,
"created_at": "2023-06-04T15:23:12.000000Z",
"updated_at": "2025-01-14T15:45:00.000000Z"
}
}Beispiele
# Preis aktualisieren
curl -X PUT \
-H "Authorization: Bearer 1|abcdef123456789..." \
-H "Content-Type: application/json" \
-d '{
"price": 3750.00
}' \
"https://app.milkee.ch/api/v2/companies/123/products/42"
# Product archivieren
curl -X PUT \
-H "Authorization: Bearer 1|abcdef123456789..." \
-H "Content-Type: application/json" \
-d '{
"archived": true
}' \
"https://app.milkee.ch/api/v2/companies/123/products/42"
# Name und Beschreibung aktualisieren
curl -X PUT \
-H "Authorization: Bearer 1|abcdef123456789..." \
-H "Content-Type: application/json" \
-d '{
"name": "Webdesign Paket Premium",
"description": "Erweitertes Paket mit 10 Seiten und zusätzlichen Features"
}' \
"https://app.milkee.ch/api/v2/companies/123/products/42"Product löschen
DELETE /companies/{company}/products/{product}Löscht ein bestehendes Product unwiderruflich.
Vorsicht beim Löschen
Products die bereits in Rechnungen oder Offerten verwendet wurden, sollten archiviert statt gelöscht werden, um die Datenintegrität zu wahren.
Response
HTTP/1.1 204 No ContentBeispiel
curl -X DELETE \
-H "Authorization: Bearer 1|abcdef123456789..." \
"https://app.milkee.ch/api/v2/companies/123/products/42"Anzahl Products abrufen
GET /companies/{company}/products/countRuft die Gesamtanzahl der Products der Firma ab.
Response
42Einfacher Integer-Wert
Dieser Endpoint gibt direkt einen Integer-Wert zurück, nicht als JSON-Objekt.
Beispiel
curl -H "Authorization: Bearer 1|abcdef123456789..." \
"https://app.milkee.ch/api/v2/companies/123/products/count"Fehlerbehandlung
Häufige Fehler
404 Not Found
{
"message": "No query results for model [App\\Models\\Product] 999"
}Ursache: Product mit der angegebenen ID existiert nicht oder gehört nicht zur angegebenen Firma.
422 Validation Error
{
"message": "The given data was invalid.",
"errors": {
"name": [
"Name für Produkt fehlt."
],
"price": [
"Preis muss eine Zahl sein.",
"Preis darf maximal 999999.99 sein."
]
}
}Häufige Validierungsfehler:
name.required: Name ist erforderlichname.max: Name zu lang (maximal 255 Zeichen)price.numeric: Preis muss numerisch seinprice.min: Preis muss mindestens 0 seinprice.max: Preis darf maximal 999,999.99 seinunit.max: Einheit zu lang (maximal 255 Zeichen)archived.boolean: archived muss true oder false sein
Best Practices
Product-Kategorisierung mit Namenskonventionen
Verwenden Sie Präfixe im Product-Namen für bessere Organisation. Empfohlene Konventionen:
- [Service] für Dienstleistungen (z.B. "[Service] Beratungsstunde")
- [Paket] für Produktpakete (z.B. "[Paket] Webdesign Standard")
- [Produkt] für physische Produkte (z.B. "[Produkt] Lizenz Software XY")
Preislisten-Verwaltung
Filtern Sie nach archived=false und sortieren Sie nach name, um aktuelle Preislisten zu erstellen. Gruppieren Sie Products nach Kategorien (basierend auf Präfixen) für strukturierte Anzeige.
Archivierung statt Löschung
Archivieren Sie Products statt sie zu löschen, um die Datenintegrität in bestehenden Rechnungen und Offerten zu wahren. Verwenden Sie filter[archived]=false in Auswahl-Listen, um nur aktive Products anzuzeigen.
Bulk-Preisanpassungen
Für Preisanpassungen mehrerer Products: Rufen Sie die Products ab, berechnen Sie die neuen Preise (z.B. +5% Erhöhung), runden Sie auf 2 Nachkommastellen und aktualisieren Sie jedes Product einzeln mit PUT.
Einheiten standardisieren
Verwenden Sie standardisierte Einheiten für Konsistenz:
- Zeit: Stunde, Tag, Woche, Monat
- Menge: Stück, Paket, Set
- Fläche: m², m³
Product-Suche mit Autocomplete
Implementieren Sie effiziente Suche mit filter[name] (mindestens 2 Zeichen), begrenzen Sie auf 10 Ergebnisse (per_page=10) und verwenden Sie Debouncing (z.B. 300ms) für bessere Performance.
Nächste Schritte
- Invoices API - Rechnungen mit Products erstellen
- Proposals API - Offerten mit Products erstellen
- Code-Beispiele ansehen
- Webhooks einrichten
