Zum Hauptinhalt springen
Getly

Befehlsmenü

Zu einer Seite springen oder den Katalog durchsuchen

API

API-Dokumentation

Vollständige Referenz für die Getly Developer-API v1

Authentifizierung

Alle API-Anfragen müssen deinen API-Schlüssel im Authorization-Header mit dem Bearer-Token-Schema enthalten.

HTTP header
Authorization: Bearer gk_your_api_key_here

Verfügbare Scopes

API-Schlüssel sind auf einen bestimmten Shop beschränkt und haben granulare Berechtigungen. Erstelle Schlüssel unter /dashboard/developer/keys.

read:productswrite:productsread:ordersread:storewrite:storeread:analyticswebhooks:manageread:postswrite:postsread:couponswrite:couponsread:licenseswrite:licensescheckout:createread:billingwrite:billing

Rate-Limits

API-Anfragen sind auf 100 requests per minute pro API-Schlüssel begrenzt. Bei Überschreitung erhältst du eine 429-Antwort - bitte kurz warten und erneut versuchen.

Plane deine Integrationen so, dass du innerhalb dieser Limits bleibst. Wo möglich Batch-Operationen verwenden und Antworten auf deiner Seite cachen.

Fehlerbehandlung

Alle API-Antworten folgen einem konsistenten Format. Fehler enthalten eine beschreibende Nachricht.

application/json
// Success
{ "success": true, "data": { ... } }

// Error
{
  "success": false,
  "error": "Description of what went wrong",
  "errorDetail": {
    "code": "validation_failed",   // stable, safe to branch on
    "message": "price must be a positive integer in cents",
    "hint": "Fix the field named in `param` and retry the same request.",
    "param": "price",              // omitted when no single field is at fault
    "docsUrl": "https://www.getly.store/developers/docs#errors"
  }
}

HTTP-Statuscodes

200 - Erfolg

201 - Erstellt

400 - Bad Request (ungültige Eingabe)

401 - Unauthorized (fehlender/ungültiger API-Schlüssel)

403 - Forbidden (fehlender Scope oder keine eigene Ressource)

404 - Nicht gefunden

500 - Interner Serverfehler

Endpunkte

Basis-URL: https://www.getly.store. Alle Preise sind in Cent (z. B. 1999 = 19,99 $).

GET/api/v1/productsread:products

Produkte deines Shops auflisten

bash
curl -X GET "https://www.getly.store/api/v1/products?page=1&limit=20" \
  -H "Authorization: Bearer gk_your_api_key"
Antwort · application/json
{
  "success": true,
  "data": [
    {
      "id": "uuid",
      "name": "Premium Icon Pack",
      "slug": "premium-icon-pack-abc123",
      "price": 1999,
      "status": "active",
      "category": { "id": "uuid", "name": "Design", "slug": "design" },
      "images": [{ "url": "...", "altText": "..." }]
    }
  ],
  "total": 42,
  "page": 1,
  "limit": 20,
  "hasMore": true
}
POST/api/v1/productswrite:products

Ein neues Produkt in deinem Shop erstellen

bash
curl -X POST "https://www.getly.store/api/v1/products" \
  -H "Authorization: Bearer gk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "My New Product",
    "description": "A great digital product",
    "price": 29.99,
    "categoryId": "uuid",
    "status": "active",
    "tags": ["design", "icons"],
    "images": [{ "url": "https://cdn.getly.store/...png", "altText": "cover" }],
    "files": [{ "fileUrl": "https://cdn.getly.store/files/.../abc.zip", "fileName": "pack.zip", "fileSize": 10485760, "fileType": "application/zip" }]
  }'
Antwort · application/json
{
  "success": true,
  "data": {
    "id": "uuid",
    "name": "My New Product",
    "slug": "my-new-product-abc123",
    "price": 2999,
    "status": "active",
    "createdAt": "2025-01-15T10:30:00Z"
  }
}
GET/api/v1/products/:idread:products

Produktdetails anhand der ID abrufen

bash
curl -X GET "https://www.getly.store/api/v1/products/{id}" \
  -H "Authorization: Bearer gk_your_api_key"
Antwort · application/json
{
  "success": true,
  "data": {
    "id": "uuid",
    "name": "Premium Icon Pack",
    "price": 1999,
    "images": [...],
    "files": [...],
    "reviews": [...]
  }
}
PATCH/api/v1/products/:idwrite:products

Ein bestehendes Produkt aktualisieren

bash
curl -X PATCH "https://www.getly.store/api/v1/products/{id}" \
  -H "Authorization: Bearer gk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Updated Name", "price": 39.99 }'
Antwort · application/json
{
  "success": true,
  "data": { "id": "uuid", "name": "Updated Name", "price": 3999 }
}
DELETE/api/v1/products/:idwrite:products

Produkt archivieren (Soft-Delete). Es wird nicht mehr öffentlich gelistet; bestehende Bestellungen und Downloads funktionieren weiter.

bash
curl -X DELETE "https://www.getly.store/api/v1/products/{id}" \
  -H "Authorization: Bearer gk_your_api_key"
Antwort · application/json
{
  "success": true,
  "data": { "id": "uuid", "status": "archived" },
  "message": "Product archived"
}
POST/api/v1/products/:id/fileswrite:products

Eine herunterladbare Datei an ein Produkt anhängen. Für kleine Dateien Multipart verwenden, für Dateien bis 2 GB den Presign-Unterpfad + direkten R2-PUT. Du kannst auch ein files[]-Array an POST /api/v1/products übergeben, um die Datei direkt beim Erstellen anzuhängen.

bash
# Direct upload (multipart) - best for files under ~4MB:
curl -X POST "https://www.getly.store/api/v1/products/{id}/files" \
  -H "Authorization: Bearer gk_your_api_key" \
  -F "file=@/path/to/your-file.zip"

# Large files (up to 2GB) - 3 steps:
# 1) get a presigned upload URL
curl -X POST "https://www.getly.store/api/v1/products/{id}/files/presign" \
  -H "Authorization: Bearer gk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{ "fileName": "pack.zip", "fileSize": 524288000, "fileType": "application/zip" }'
# 2) PUT the bytes straight to R2 (use the returned uploadUrl)
curl -X PUT "<uploadUrl>" --data-binary "@/path/to/pack.zip" \
  -H "Content-Length: 524288000"
# 3) attach the uploaded object (use the returned fileUrl)
curl -X POST "https://www.getly.store/api/v1/products/{id}/files" \
  -H "Authorization: Bearer gk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{ "fileUrl": "<fileUrl>", "fileName": "pack.zip", "fileSize": 524288000, "fileType": "application/zip" }'
Antwort · application/json
{
  "success": true,
  "data": {
    "id": "uuid",
    "fileName": "pack.zip",
    "fileUrl": "https://cdn.getly.store/files/.../abc.zip",
    "fileSize": 524288000,
    "fileType": "application/zip",
    "version": "1.0",
    "isLatest": true,
    "createdAt": "2026-06-02T10:30:00Z"
  }
}
POST/api/v1/uploads/images/presignwrite:products

Signierte URL zum Hochladen eines Produktbilds anfordern (max. 10 MB; png, jpeg, webp, gif, avif). Ohne Bild kann ein Produkt nicht live gehen.

bash
# Images are uploaded in 3 steps - there is no direct multipart route.
# 1) ask for a presigned URL (max 10MB; png, jpeg, webp, gif or avif)
curl -X POST "https://www.getly.store/api/v1/uploads/images/presign" \
  -H "Authorization: Bearer gk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{ "fileName": "cover.png", "fileSize": 184320, "contentType": "image/png" }'

# 2) PUT the raw bytes to the returned uploadUrl (expires in 1h).
#    Content-Length MUST equal the fileSize you declared.
curl -X PUT "<uploadUrl>" --data-binary "@/path/to/cover.png" \
  -H "Content-Type: image/png" -H "Content-Length: 184320"

# 3) reference the returned publicUrl when you create or update the product.
#    An image is REQUIRED before a product can go live.
curl -X PATCH "https://www.getly.store/api/v1/products/{id}" \
  -H "Authorization: Bearer gk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{ "images": ["<publicUrl>"] }'
Antwort · application/json
{
  "success": true,
  "data": {
    "uploadUrl": "https://<bucket>.r2.cloudflarestorage.com/...",
    "publicUrl": "https://cdn.getly.store/images/.../abc.png",
    "expiresIn": 3600
  }
}
GET/api/v1/products/:id/keysread:products

Den eigenen Lizenzschlüssel-Pool eines Produkts auflisten: Zähler (verfügbar/vergeben/wartend) und eine maskierte, paginierte Liste. Der Klartext-Schlüssel wird nie zurückgegeben.

bash
curl -X GET "https://www.getly.store/api/v1/products/{id}/keys?limit=50&offset=0" \
  -H "Authorization: Bearer gk_your_api_key"
Antwort · application/json
{
  "success": true,
  "data": {
    "keyPoolEnabled": true,
    "keyPoolLowThreshold": 5,
    "counts": { "available": 12, "issued": 40, "waiting": 0 },
    "keys": [
      { "id": "uuid", "masked": "ABCD…WXYZ", "status": "available", "issuedAt": null, "orderItemId": null, "refunded": false }
    ],
    "limit": 50,
    "offset": 0,
    "total": 52
  }
}
POST/api/v1/products/:id/keyswrite:products

Eigene Schlüssel, Gutscheincodes oder eindeutige URLs in den Pool eines Produkts einfügen, ein Element pro Array-Eintrag. Duplikate und leere Zeilen werden gemeldet statt stillschweigend verworfen; wartende Käufer erhalten sofort einen Schlüssel.

bash
curl -X POST "https://www.getly.store/api/v1/products/{id}/keys" \
  -H "Authorization: Bearer gk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{ "keys": ["ABCD-1234-EFGH-5678", "IJKL-9012-MNOP-3456"] }'
Antwort · application/json
{
  "success": true,
  "data": {
    "added": 2,
    "duplicates": 0,
    "duplicatesInInput": 0,
    "tooLong": 0,
    "blank": 0,
    "filled": 1
  }
}
DELETE/api/v1/products/:id/keys/:keyIdwrite:products

Einen unverkauften Schlüssel aus dem Pool entfernen. Ein vergebener Schlüssel ist ein Verkaufsnachweis und kann nicht entfernt werden - 409 key_not_available.

bash
curl -X DELETE "https://www.getly.store/api/v1/products/{id}/keys/{keyId}" \
  -H "Authorization: Bearer gk_your_api_key"
Antwort · application/json
{
  "success": true,
  "data": { "id": "uuid", "removed": true }
}
GET/api/v1/ordersread:orders

Bestellungen mit Artikeln aus deinem Shop auflisten

bash
curl -X GET "https://www.getly.store/api/v1/orders?page=1&limit=20" \
  -H "Authorization: Bearer gk_your_api_key"
Antwort · application/json
{
  "success": true,
  "data": [
    {
      "id": "uuid",
      "orderId": "uuid",
      "price": 2999,
      "order": { "status": "completed", "buyer": { "name": "John" } },
      "product": { "name": "Premium Pack" }
    }
  ],
  "total": 156,
  "page": 1
}
GET/api/v1/orders/:idread:orders

Bestelldetails abrufen (nur Artikel aus deinem Shop)

bash
curl -X GET "https://www.getly.store/api/v1/orders/{id}" \
  -H "Authorization: Bearer gk_your_api_key"
Antwort · application/json
{
  "success": true,
  "data": {
    "id": "uuid",
    "status": "completed",
    "total": 5999,
    "buyer": { "name": "John", "email": "[email protected]" },
    "items": [...]
  }
}
GET/api/v1/storeread:store

Deine Shop-Informationen abrufen

bash
curl -X GET "https://www.getly.store/api/v1/store" \
  -H "Authorization: Bearer gk_your_api_key"
Antwort · application/json
{
  "success": true,
  "data": {
    "id": "uuid",
    "name": "My Store",
    "slug": "my-store",
    "description": "...",
    "totalSales": 250,
    "totalRevenue": 450000,
    "badges": [...]
  }
}
PATCH/api/v1/storewrite:store

Shop-Name, Beschreibung, Website, socialLinks aktualisieren

bash
curl -X PATCH "https://www.getly.store/api/v1/store" \
  -H "Authorization: Bearer gk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{ "description": "Updated store description" }'
Antwort · application/json
{
  "success": true,
  "data": { "id": "uuid", "name": "My Store", "description": "Updated store description" }
}
GET/api/v1/analyticsread:analytics

Verkaufsanalysen für deinen Shop abrufen

bash
curl -X GET "https://www.getly.store/api/v1/analytics" \
  -H "Authorization: Bearer gk_your_api_key"
Antwort · application/json
{
  "success": true,
  "data": {
    "totalSales": 250,
    "totalRevenue": 450000,
    "monthlySales": 42,
    "monthlyRevenue": 75000,
    "averageOrderValue": 1800,
    "productCount": 15,
    "totalDownloads": 1200,
    "salesByMonth": [
      { "month": "2025-01", "sales": 38, "revenue": 68000 }
    ]
  }
}
GET/api/v1/webhook-endpointswebhooks:manage

Webhook-Endpunkte für deinen Shop auflisten

bash
curl -X GET "https://www.getly.store/api/v1/webhook-endpoints" \
  -H "Authorization: Bearer gk_your_api_key"
Antwort · application/json
{
  "success": true,
  "data": {
    "items": [
      {
        "id": "uuid",
        "url": "https://example.com/webhooks",
        "events": ["sale.completed"],
        "isActive": true
      }
    ],
    "nextCursor": null
  }
}
POST/api/v1/webhook-endpointswebhooks:manage

Einen neuen Webhook-Endpunkt registrieren

bash
curl -X POST "https://www.getly.store/api/v1/webhook-endpoints" \
  -H "Authorization: Bearer gk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/webhooks",
    "events": ["sale.completed", "product.updated"]
  }'
Antwort · application/json
{
  "success": true,
  "data": {
    "id": "uuid",
    "url": "https://example.com/webhooks",
    "events": ["sale.completed", "product.updated"],
    "secret": "abcdef1234567890..."
  }
}
POST/api/v1/billing/planswrite:billing

Einen wiederkehrenden Plan für dein EIGENES Produkt anlegen (Getly Billing). amount in ganzen Cent (min. 50), intervalUnit day/week/month/year, intervalCount 1–52. Erfordert einen genehmigten Billing-Antrag - bis dahin 403 billing_not_approved. GET listet Pläne; GET/PATCH /{id} liest und bearbeitet einen.

bash
curl -X POST "https://www.getly.store/api/v1/billing/plans" \
  -H "Authorization: Bearer gk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Pro", "amount": 1900, "intervalUnit": "month", "externalId": "pro-monthly" }'
Antwort · application/json
{
  "success": true,
  "data": {
    "id": "uuid",
    "name": "Pro",
    "amount": 1900,
    "currency": "usd",
    "interval": { "unit": "month", "count": 1 },
    "externalId": "pro-monthly",
    "isActive": true
  }
}
POST/api/v1/billing/checkoutwrite:billing

Eine gehostete Abo-Seite für einen Kunden erzeugen, 24 Stunden gültig. customerRef ist deine eigene Kunden-ID und kommt auf jedem billing.*-Webhook als externalCustomerRef zurück. Der Kunde zahlt per Karte (verlängert sich von selbst) oder Krypto (jeweils ein Zeitraum).

bash
curl -X POST "https://www.getly.store/api/v1/billing/checkout" \
  -H "Authorization: Bearer gk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{ "planId": "uuid", "customerRef": "user_8841",
        "successUrl": "https://your-app.com/welcome",
        "cancelUrl": "https://your-app.com/pricing" }'
Antwort · application/json
{
  "success": true,
  "data": {
    "url": "https://www.getly.store/billing/subscribe/uuid?t=…",
    "expiresAt": "2026-09-09T09:00:00.000Z"
  }
}
GET/api/v1/billing/subscriptions/{id}read:billing

Die Statusprüfung, die dein Backend vor der Zugangsvergabe macht. status: active, past_due (Kartenverlängerung fehlgeschlagen, der Zahlungsdienstleister versucht es erneut), canceled, expired (Krypto-Zeitraum abgelaufen). Behandle active und past_due bis currentPeriodEnd als berechtigt. Der Listen-Endpunkt filtert nach status, customerRef und planId.

bash
curl "https://www.getly.store/api/v1/billing/subscriptions/uuid" \
  -H "Authorization: Bearer gk_your_api_key"
Antwort · application/json
{
  "success": true,
  "data": {
    "id": "uuid",
    "customerRef": "user_8841",
    "status": "active",
    "paymentMethod": "stripe",
    "currentPeriodEnd": "2026-10-08T09:14:00.000Z",
    "cancelAtPeriodEnd": false,
    "plan": { "name": "Pro", "amount": 1900, "interval": { "unit": "month", "count": 1 } }
  }
}
POST/api/v1/billing/subscriptions/{id}/cancelwrite:billing

Verlängerung am Ende des bezahlten Zeitraums stoppen - nie ein sofortiger Abbruch. Du erhältst billing.subscription.canceled, wenn er endet (Karte), oder billing.subscription.expired (Krypto). 409 subscription_not_cancellable, wenn bereits beendet.

bash
curl -X POST "https://www.getly.store/api/v1/billing/subscriptions/uuid/cancel" \
  -H "Authorization: Bearer gk_your_api_key"
Antwort · application/json
{
  "success": true,
  "data": { "id": "uuid", "status": "active", "cancelAtPeriodEnd": true, "currentPeriodEnd": "2026-10-08T09:14:00.000Z" }
}

Getly Billing

Wiederkehrende Pläne für ein Produkt, das du selbst betreibst - ein SaaS, eine Community, ein Tool. Die Pläne leben in der API, die Abo-Seite auf getly.store, und dein Backend vergibt den Zugang über fünf Webhooks, die alle deine eigene Kundenreferenz tragen.

Zugang auf Antrag: nenne uns unter /dashboard/billing die Website und was du verkaufst. Bis zur Genehmigung antworten Schreibaufrufe mit 403 billing_not_approved, Leseaufrufe funktionieren.

  • billing.subscription.created
  • billing.subscription.renewed
  • billing.payment_failed
  • billing.subscription.canceled
  • billing.subscription.expired
So funktioniert Getly Billing

Eigene Lizenzschlüssel ausliefern

Ein Produkt kann die eigenen, vorbereiteten Schlüssel des Verkäufers ausgeben - Registrierungsschlüssel, Gutscheincodes oder eindeutige URLs - statt eines von Getly generierten. Getly gibt pro Verkauf den nächsten Schlüssel aus, zuerst eingefügt, zuerst verkauft, und blockiert einen Verkauf nie bei leerem Pool: der Käufer erfährt, dass der Schlüssel per E-Mail kommt, und erhält ihn, sobald mehr hinzugefügt werden.

  • Dashboard: Produkt bearbeiten → Schritt „Preis“ → „Meine eigenen Lizenzschlüssel ausliefern“ (der Pool braucht eine Produkt-ID, daher nicht beim Anlegen verfügbar). Ein Schlüssel pro Zeile, bis zu 5,000 pro Hinzufügen; schließt Getly-generierte Schlüssel für dasselbe Produkt aus.
  • API: GET/POST /api/v1/products/{id}/keys listet und fügt Schlüssel hinzu; DELETE /api/v1/products/{id}/keys/{keyId} entfernt einen unverkauften. keyPoolEnabled und keyPoolLowThreshold liegen am Produkt selbst, gesetzt über POST/PATCH /api/v1/products.

Lieber vom eigenen Server aus? Jedes sale.completed-Element trägt jetzt licenseKey - den für diese Position bereits vergebenen Schlüssel (aus dem Pool oder von Getly generiert) oder null, solange er noch aussteht - neben buyerEmail, sodass du ihn weiterleiten oder einen eigenen senden kannst.

Webhooks

Webhooks ermöglichen es deiner Anwendung, Echtzeit-Benachrichtigungen zu erhalten, wenn Ereignisse in deinem Shop passieren. Registriere Endpunkte unter /dashboard/developer/webhooks oder über die API.

Ereignistypen

sale.completed - Ein Verkauf für eines deiner Produkte wurde abgeschlossen. Enthält die E-Mail des Käufers, damit du deinen eigenen Lizenzschlüssel senden kannst.

product.created - In deinem Shop wurde ein Produkt erstellt

product.updated - Ein Produkt in deinem Shop wurde aktualisiert

review.created - Eines deiner Produkte hat eine neue Bewertung erhalten

download.completed - Ein Käufer hat eines deiner Produkte heruntergeladen

refund.created - Ein Käufer hat eine Rückerstattung angefragt (die Entscheidung folgt als order.refunded)

order.refunded - Für eine deiner Bestellungen wurde eine Rückerstattung verbucht

dispute.created - Ein Käufer hat eine Reklamation eröffnet

dispute.resolved - Eine Reklamation wurde gelöst

checkout_link.completed - Ein Checkout-Link wurde bezahlt

license.activated - Ein Lizenzschlüssel wurde aktiviert

access.expiring - Ein zeitlich begrenzter Zugang läuft in 7 Tagen ab

access.expired - Ein zeitlich begrenzter Zugang ist abgelaufen

billing.subscription.created - Getly Billing: ein Kunde hat einen deiner Pläne abonniert

billing.subscription.renewed - Getly Billing: ein Abonnement wurde verlängert und bezahlt

billing.payment_failed - Getly Billing: eine Verlängerungszahlung ist fehlgeschlagen

billing.subscription.canceled - Getly Billing: ein Abonnement wurde gekündigt

billing.subscription.expired - Getly Billing: ein per Krypto bezahltes Abonnement ist unbezahlt abgelaufen

* - Alle Ereignisse abonnieren

Payload-Format

Jede Webhook-Zustellung sendet eine JSON-POST-Anfrage mit folgender Struktur:

POST · application/json
POST https://your-endpoint.com/webhooks
Content-Type: application/json
X-Getly-Signature: sha256=<hmac_hex>
X-Getly-Event: sale.completed

{
  "deliveryId": "uuid",
  "event": "sale.completed",
  "data": {
    "orderId": "uuid",
    "buyerId": "uuid",
    "buyerEmail": "[email protected]",
    "items": [
      {
        "orderItemId": "uuid",
        "productId": "uuid",
        "price": 2999,
        "sellerAmount": 2399,
        "isGift": false,
        "licenseKey": null
      }
    ],
    "total": 2999
  },
  "timestamp": "2026-09-23T10:30:00.000Z"
}

Signaturverifizierung

Jede Webhook-Zustellung enthält einen X-Getly-Signature-Header. Verifiziere die Signatur mit HMAC-SHA256 und deinem Webhook-Secret, um sicherzustellen, dass die Anfrage von Getly stammt.

node.js
const crypto = require('crypto');

function verifyWebhook(body, signature, secret) {
  const expected = 'sha256=' +
    crypto
      .createHmac('sha256', secret)
      .update(body)
      .digest('hex');

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

// In your webhook handler
app.post('/webhooks', (req, res) => {
  const signature = req.headers['x-getly-signature'];
  const isValid = verifyWebhook(
    JSON.stringify(req.body),
    signature,
    process.env.GETLY_WEBHOOK_SECRET
  );

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

  const { event, data } = req.body;
  // Handle the event...

  res.status(200).send('OK');
});

Retry-Richtlinie

Fehlgeschlagene Zustellungen (Nicht-2xx-Antwort oder Timeout) werden automatisch mit exponentiellem Backoff erneut versucht:

Versuch 1: Erneut nach 1 Minute

Versuch 2: Erneut nach 5 Minuten

Versuch 3: Erneut nach 30 Minuten

Versuch 4: Erneut nach 2 Stunden

Versuch 5: Aufgeben (Zustellung als fehlgeschlagen markiert)

Dein Endpunkt sollte innerhalb von 10 Sekunden antworten. Sende einen 2xx-Statuscode zur Empfangsbestätigung.