Zum Inhalt springen

Entwickler

API-Referenz

Mit der REST-API von mapps.one kannst du aus deinem eigenen Code, deiner CI-Pipeline oder deiner Integration heraus Apps erstellen und aktualisieren, Store-Links verwalten, Store-Metadaten importieren, Analysen lesen, QR-Codes generieren und Webhooks abonnieren. Die API ist im Studio-Plan verfügbar.

Basis-URL

https://mapps.one/api/v1

Alle Anfragen verwenden HTTPS. Sende Request-Bodys als JSON mit Content-Type: application/json und sende immer Accept: application/json, damit auch Fehler als JSON zurückkommen.

Authentifizierung

Erstelle ein Token im Dashboard unter Entwickler. Workspace-Owner und Admins können das tun. Gib dem Token einen Namen, etwa „GitHub Actions“, und wähle seine Berechtigungen. Das Token wird nur einmal angezeigt. Speichere es daher sofort in deinem Secret-Manager.

Tokens gehören zum Workspace, nicht zu einer Person. Sie funktionieren also weiter, wenn jemand das Team verlässt. Sie laufen nicht ab. Widerrufe ein Token auf derselben Seite, wenn du es nicht mehr brauchst oder wenn es möglicherweise in falsche Hände geraten ist.

Sende das Token als Bearer-Token:

curl https://mapps.one/api/v1/workspace \
  -H "Authorization: Bearer $MAPPS_TOKEN" \
  -H "Accept: application/json"

Berechtigungen

BerechtigungErlaubt
apps:readApps auflisten und lesen, QR-Codes herunterladen
apps:writeApps erstellen, aktualisieren und löschen, Store-Links ersetzen, Store-Metadaten importieren
analytics:readApp-Analysen lesen
webhooks:manageWebhook-Abos auflisten, erstellen und löschen

GET /workspace und GET /events funktionieren mit jedem gültigen Token. Gib jeder Integration nur die Berechtigungen, die sie braucht.

Konventionen

  • IDs sind 26 Zeichen lange ULIDs in Kleinbuchstaben, etwa 01j8b2k6r3xq9v7m4n5p0s1t2w. Apps werden über ihre id angesprochen, nicht über den Slug. Eine Änderung des Slugs bricht deine Integration also nie.
  • Zeitstempel sind ISO 8601 in UTC, etwa 2026-09-14T08:12:44+00:00.
  • Antworten verpacken das Ergebnis in einem data-Schlüssel.
  • Store-Schlüssel sind app_store, google_play, app_gallery, microsoft_store und web.
  • Plattform-Schlüssel sind ios, android, huawei, windows, macos und other. Ziel-Schlüssel sind die Store-Schlüssel plus landing.

Rate-Limits

Jeder Workspace kann 120 Anfragen pro Minute stellen, geteilt zwischen all seinen Tokens. Jede Antwort enthält die Header X-RateLimit-Limit und X-RateLimit-Remaining. Überschreitest du das Limit, antwortet die API mit 429 Too Many Requests und einem Retry-After-Header mit der Anzahl der Sekunden, die du warten musst.

Fehler

Fehler liefern einen JSON-Body mit einer menschenlesbaren message. Manche Fehler enthalten zusätzlich einen maschinenlesbaren code, und Validierungsfehler listen Probleme pro Feld in errors auf.

StatusWann
401Das Token fehlt, ist ungültig oder wurde widerrufen. {"message": "Unauthenticated."}
402Der Plan des Workspace enthält keinen API-Zugriff. Code plan_required.
403Das Token hat nicht die Berechtigung, die dieser Endpunkt braucht. {"message": "Invalid ability provided."}
404Die App oder das Abo existiert nicht oder gehört zu einem anderen Workspace.
422Die Validierung ist fehlgeschlagen, oder die Anfrage konnte nicht abgeschlossen werden. Zum Beispiel Code metadata_unavailable.
429Rate-Limit überschritten. Warte die Anzahl an Sekunden ab, die in Retry-After steht.
5xxAuf unserer Seite ist etwas schiefgelaufen. Versuche es mit exponentiellem Backoff erneut.
HTTP/2 402
{
  "message": "API access requires the Studio plan.",
  "code": "plan_required"
}
HTTP/2 422
{
  "message": "This link is already taken.",
  "errors": {
    "slug": ["This link is already taken."]
  }
}

Endpunkte

Methode und PfadBerechtigungBeschreibung
GET /workspacebeliebigWorkspace, Plan, Nutzung und das aktuelle Token
GET /eventsbeliebigWebhook-Ereignistypen
GET /appsapps:readApps auflisten
POST /appsapps:writeApp erstellen
GET /apps/{id}apps:readApp abrufen
PATCH /apps/{id}apps:writeApp aktualisieren
DELETE /apps/{id}apps:writeApp löschen
PUT /apps/{id}/linksapps:writeStore-Links festlegen oder entfernen
POST /apps/{id}/metadataapps:writeDetails aus dem Store-Eintrag importieren
GET /apps/{id}/analyticsanalytics:readSummen, Tagesreihe und Aufschlüsselungen
GET /apps/{id}/qrapps:readQR-Code-Bild
GET /webhookswebhooks:manageWebhook-Abos auflisten
POST /webhookswebhooks:manageWebhook-Abo erstellen
DELETE /webhooks/{id}webhooks:manageWebhook-Abo löschen

Das App-Objekt

FeldTypBeschreibung
idstringULID der App
namestringApp-Name
slugstringDer Pfad des Smart Links: mapps.one/{slug}
statusstringlive, paused oder suspended
tagline, descriptionstring oder nullSeitentext
categorystring oder nullEin Kategorie-Schlüssel, etwa health-fitness oder productivity
page_themestringclean, midnight oder vivid
accent_colorstring oder nullHex-Farbe, etwa #16a34a
developerobjectname, website und email
social_linksobjectAusgefüllte Social-Media-Profile, nach Netzwerk geschlüsselt: x, instagram, tiktok, youtube, facebook, linkedin, threads, github, discord, reddit
featuresarrayFunktionseinträge mit icon, title und description
listed_in_explorebooleanOb die App in Entdecken erscheint
utm_passthroughbooleanOb UTM-Tags an die Stores weitergegeben werden
redirect_rulesobjectZiel pro Plattform, mit ausgefüllten Standardwerten
icon_urlstring oder nullÖffentliche URL des Icons
ratingobject oder nullvalue und count aus dem Store
urlsobjectÖffentliche URLs: smart_link, landing_page, qr_svg, qr_png, privacy_policy, terms. Die URLs der Rechtstexte liefern 404, bis das Dokument veröffentlicht ist.
linksobjectStore-Links, nach Store geschlüsselt, jeweils mit url, status (unverified, verified oder invalid) und verified_at. In Antworten zu einer einzelnen App enthalten.
screenshotsarrayScreenshots mit url, width und height. Nach einem Metadaten-Import enthalten.
created_at, updated_atstringZeitstempel nach ISO 8601

App abrufen

curl https://mapps.one/api/v1/apps/01j8b2k6r3xq9v7m4n5p0s1t2w \
  -H "Authorization: Bearer $MAPPS_TOKEN" \
  -H "Accept: application/json"
{
  "data": {
    "id": "01j8b2k6r3xq9v7m4n5p0s1t2w",
    "name": "Habitly",
    "slug": "habitly",
    "status": "live",
    "tagline": "Build habits that stick",
    "description": "Habitly helps you build small daily habits with gentle reminders and streaks.",
    "category": "health-fitness",
    "page_theme": "clean",
    "accent_color": "#16a34a",
    "developer": {
      "name": "Habitly Labs",
      "website": "https://habitly.app",
      "email": "hello@habitly.app"
    },
    "social_links": {
      "instagram": "https://instagram.com/habitly.app"
    },
    "features": [
      { "icon": "bell", "title": "Gentle reminders", "description": "Nudges at the time you choose." }
    ],
    "listed_in_explore": true,
    "utm_passthrough": true,
    "redirect_rules": {
      "ios": "app_store",
      "android": "google_play",
      "huawei": "app_gallery",
      "windows": "microsoft_store",
      "macos": "landing",
      "other": "landing"
    },
    "icon_url": "https://mapps.one/storage/apps/01j8b2k6r3xq9v7m4n5p0s1t2w/icon/icon.png",
    "rating": { "value": 4.8, "count": 12450 },
    "urls": {
      "smart_link": "https://mapps.one/habitly",
      "landing_page": "https://mapps.one/habitly/page",
      "qr_svg": "https://mapps.one/habitly/qr.svg",
      "qr_png": "https://mapps.one/habitly/qr.png",
      "privacy_policy": "https://mapps.one/habitly/privacy",
      "terms": "https://mapps.one/habitly/terms"
    },
    "links": {
      "app_store": {
        "url": "https://apps.apple.com/app/id1612345678",
        "status": "verified",
        "verified_at": "2026-09-14T08:12:44+00:00"
      },
      "google_play": {
        "url": "https://play.google.com/store/apps/details?id=com.habitly.app",
        "status": "verified",
        "verified_at": "2026-09-14T08:12:46+00:00"
      }
    },
    "created_at": "2026-09-01T11:20:03+00:00",
    "updated_at": "2026-09-14T08:12:46+00:00"
  }
}

Apps auflisten

Liefert die Apps im Workspace. Die Ergebnisse sind paginiert: Folge links.next oder übergib ?page=2, bis der Wert null ist.

curl "https://mapps.one/api/v1/apps?page=1" \
  -H "Authorization: Bearer $MAPPS_TOKEN" \
  -H "Accept: application/json"
{
  "data": [
    { "id": "01j8b2k6r3xq9v7m4n5p0s1t2w", "name": "Habitly", "slug": "habitly", "status": "live" },
    { "id": "01j8d5r2w9y6a3c0e7g4j1m8p5", "name": "Habitly Focus", "slug": "habitly-focus", "status": "paused" }
  ],
  "links": {
    "first": "https://mapps.one/api/v1/apps?page=1",
    "last": "https://mapps.one/api/v1/apps?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "last_page": 1,
    "per_page": 25,
    "total": 2
  }
}

Die App-Objekte sind in diesem Beispiel gekürzt. Jeder Eintrag enthält alle Felder.

App erstellen

FeldErforderlichBeschreibung
nameJaApp-Name, bis zu 120 Zeichen
slugNein3 bis 40 Kleinbuchstaben, Ziffern und einzelne Bindestriche. Ohne Angabe wird aus dem Namen ein freier Slug generiert.
linksNeinStore-Links, nach Store geschlüsselt, im selben Format wie bei Store-Links festlegen

Du kannst außerdem alle Felder senden, die unter App aktualisieren aufgeführt sind.

curl https://mapps.one/api/v1/apps \
  -X POST \
  -H "Authorization: Bearer $MAPPS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Habitly",
    "slug": "habitly",
    "links": {
      "app_store": "https://apps.apple.com/us/app/habitly/id1612345678",
      "google_play": "https://play.google.com/store/apps/details?id=com.habitly.app"
    }
  }'

Die Antwort ist 201 Created mit dem neuen App-Objekt. Store-Links werden in kanonischer Form mit dem Status unverified gespeichert, bis die Prüfung im Hintergrund abgeschlossen ist. Um Icon, Screenshots und Beschreibung auszufüllen, rufe als Nächstes Store-Metadaten importieren auf.

App aktualisieren

Sende nur die Felder, die du ändern möchtest.

FeldTyp
namestring
slugstring. Eine Änderung macht den alten Link sofort ungültig.
tagline, descriptionstring oder null
categoryKategorie-Schlüssel oder null
page_themeclean, midnight oder vivid
accent_color#rrggbb oder null
utm_passthrough, listed_in_exploreboolean
redirect_rulesobject, das Plattform-Schlüssel auf Ziel-Schlüssel abbildet
curl https://mapps.one/api/v1/apps/01j8b2k6r3xq9v7m4n5p0s1t2w \
  -X PATCH \
  -H "Authorization: Bearer $MAPPS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "tagline": "Tiny habits, big changes",
    "redirect_rules": { "macos": "landing" }
  }'

Die Antwort ist das aktualisierte App-Objekt.

App löschen

curl https://mapps.one/api/v1/apps/01j8b2k6r3xq9v7m4n5p0s1t2w \
  -X DELETE \
  -H "Authorization: Bearer $MAPPS_TOKEN" \
  -H "Accept: application/json"

Die Antwort ist 204 No Content. Das Löschen ist endgültig: Smart Link, Landingpage, Rechtstexte, Medien und Analysen der App werden entfernt.

PUT /apps/{id}/links erwartet ein links-Objekt, nach Store geschlüsselt:

  • eine URL fügt den Link für diesen Store hinzu oder ersetzt ihn,
  • null oder ein leerer String entfernt ihn,
  • Stores, die du weglässt, bleiben unverändert.

Jede URL muss ein gültiger Eintrag im jeweiligen Store sein: ein apps.apple.com-Link mit App-ID, ein play.google.com-Link mit Paket-ID und so weiter. Der web-Link kann jede beliebige http- oder https-Adresse sein. URLs dürfen bis zu 1024 Zeichen lang sein. Links werden in kanonischer Form gespeichert und im Hintergrund geprüft.

curl https://mapps.one/api/v1/apps/01j8b2k6r3xq9v7m4n5p0s1t2w/links \
  -X PUT \
  -H "Authorization: Bearer $MAPPS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "links": {
      "app_gallery": "https://appgallery.huawei.com/app/C109876543",
      "web": null
    }
  }'

Die Antwort ist das App-Objekt einschließlich links. Ein ungültiger Link liefert 422:

{
  "message": "This is not a valid Google Play link.",
  "errors": {
    "links.google_play": ["This is not a valid Google Play link."]
  }
}

Store-Metadaten importieren

POST /apps/{id}/metadata liest den Eintrag im App Store oder, wenn es keinen lesbaren App-Store-Link gibt, den Eintrag bei Google Play und importiert seine Details.

FeldBeschreibung
overwriteOptional, Standard false. Bei false werden nur leere Felder ausgefüllt, und Screenshots werden nur hinzugefügt, wenn die App noch keine hat. Bei true werden Name, Icon, Texte und Screenshots ersetzt. Bewertung und Preis werden immer aktualisiert.
curl https://mapps.one/api/v1/apps/01j8b2k6r3xq9v7m4n5p0s1t2w/metadata \
  -X POST \
  -H "Authorization: Bearer $MAPPS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{ "overwrite": true }'

Die Antwort ist das App-Objekt einschließlich links und screenshots, und ein Webhook vom Typ app.metadata_fetched wird gesendet. Wenn kein Store-Eintrag gelesen werden kann:

HTTP/2 422
{
  "message": "The store listing could not be read. Add a valid App Store or Google Play link first.",
  "code": "metadata_unavailable"
}

Analysen

GET /apps/{id}/analytics akzeptiert diese Query-Parameter:

ParameterBeschreibung
range7d, 30d, 90d, 12m oder custom. Standard 30d.
from, toDatumsangaben im Format YYYY-MM-DD, beide einschließlich, für range=custom. to darf nicht später als heute sein.
timezoneEine IANA-Zeitzone, etwa Europe/Istanbul, die für die Tagesgrenzen verwendet wird. Standard UTC.
curl "https://mapps.one/api/v1/apps/01j8b2k6r3xq9v7m4n5p0s1t2w/analytics?range=7d&timezone=Europe/Istanbul" \
  -H "Authorization: Bearer $MAPPS_TOKEN" \
  -H "Accept: application/json"
{
  "data": {
    "app": { "id": "01j8b2k6r3xq9v7m4n5p0s1t2w", "slug": "habitly" },
    "range": {
      "key": "7d",
      "from": "2026-09-07T21:00:00+00:00",
      "to": "2026-09-14T21:00:00+00:00",
      "timezone": "Europe/Istanbul",
      "clamped_to_plan": false
    },
    "summary": {
      "clicks": 1284,
      "visitors": 902,
      "page_views": 356,
      "store_clicks": 141
    },
    "daily": {
      "2026-09-08": 152,
      "2026-09-09": 171,
      "2026-09-10": 168,
      "2026-09-11": 205,
      "2026-09-12": 214,
      "2026-09-13": 190,
      "2026-09-14": 184
    },
    "breakdowns": {
      "os": { "iOS": 702, "Android": 431, "Windows": 88, "macOS": 63 },
      "country": { "TR": 512, "US": 298, "": 236, "DE": 141, "GB": 97 },
      "source": { "instagram": 488, "direct": 402, "qr": 190, "google": 121, "x": 83 },
      "destination": { "app_store": 640, "google_play": 399, "landing": 214, "deep_link": 31 },
      "utm_campaign": { "": 796, "launch": 402, "newsletter-sep": 86 }
    }
  }
}
  • from ist eingeschlossen, to ist ausgeschlossen. Beide sind Zeitpunkte in UTC.
  • clamped_to_plan ist true, wenn der angefragte Zeitraum auf den Verlauf des Plans gekürzt wurde.
  • daily zählt Klicks pro lokalem Datum, einschließlich Tagen ohne Klicks.
  • Aufschlüsselungen listen bis zu 10 Werte, die häufigsten zuerst. Ein leerer Schlüssel "" bedeutet unbekannt oder nicht gesetzt.
  • Die Definitionen der Metriken findest du auf der Seite Analysen.

QR-Code

GET /apps/{id}/qr liefert ein Bild. Verwende format=svg (Standard) oder format=png sowie dieselben Optionen wie bei den öffentlichen QR-URLs: fg, bg, margin, ecc, size, logo und download. Siehe QR-Codes und Pressekit.

curl "https://mapps.one/api/v1/apps/01j8b2k6r3xq9v7m4n5p0s1t2w/qr?format=png&size=2048&ecc=Q" \
  -H "Authorization: Bearer $MAPPS_TOKEN" \
  -o habitly-qr.png

Workspace

GET /workspace liefert den Workspace, die Limits und Funktionen seines Plans, die aktuelle Nutzung und das verwendete Token. Das ist ein guter erster Aufruf, um zu prüfen, ob ein Token funktioniert.

{
  "data": {
    "id": "01j8a0f4c7d2e9h6k3m5n8q1r4",
    "name": "Habitly Labs",
    "plan": {
      "key": "studio",
      "name": "Studio",
      "limits": {
        "apps": null,
        "analytics_days": 730,
        "members": 10,
        "custom_domains": 25,
        "legal_locales": null,
        "screenshots": 10,
        "webhooks": 10
      },
      "features": ["remove_badge", "all_themes", "accent_color", "qr_logo", "legal_full", "deep_links", "press_kit", "analytics_export", "custom_domains", "team", "folders", "ab_testing", "api", "webhooks", "white_label"]
    },
    "usage": { "apps": 12, "custom_domains": 3, "members": 4 },
    "token": { "name": "GitHub Actions", "abilities": ["apps:read", "apps:write"] }
  }
}

Ein Limit von null bedeutet unbegrenzt.

Ereignistypen

GET /events listet die Webhook-Ereignistypen mit einer kurzen Beschreibung auf. Integrationen können damit eine Ereignisauswahl aufbauen.

{
  "data": [
    { "type": "app.created", "description": "An app was added to the workspace." },
    { "type": "app.updated", "description": "App details, links or page settings changed." },
    { "type": "app.deleted", "description": "An app was deleted." },
    { "type": "app.status_changed", "description": "An app went live, was paused or was suspended." },
    { "type": "app.metadata_fetched", "description": "Store metadata was imported for an app." },
    { "type": "legal.published", "description": "A privacy policy or terms document was published." },
    { "type": "domain.verified", "description": "A custom domain was verified." },
    { "type": "link.clicked", "description": "Every smart link click. High volume." },
    { "type": "analytics.daily_summary", "description": "Yesterday's click totals for each app, sent once a day." }
  ]
}

Webhook-Abos

Erstelle Webhook-Abos per Code, zum Beispiel wenn ein Nutzer deine Integration verbindet, und lösche sie, wenn er die Verbindung trennt. POST /webhooks erwartet:

FeldErforderlichBeschreibung
urlJaEine öffentliche https-URL, die die Ereignisse empfängt
eventsJaEin Array von Ereignistypen oder ["*"] für alle Ereignisse
descriptionNeinBis zu 160 Zeichen, wird im Dashboard angezeigt
curl https://mapps.one/api/v1/webhooks \
  -X POST \
  -H "Authorization: Bearer $MAPPS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://hooks.zapier.com/hooks/catch/1234567/abcde12/",
    "events": ["link.clicked"],
    "description": "Zapier: clicks to Google Sheets"
  }'
HTTP/2 201
{
  "data": {
    "id": "01j8c1p4s7v0y3b6e9h2k5n8q1",
    "url": "https://hooks.zapier.com/hooks/catch/1234567/abcde12/",
    "events": ["link.clicked"],
    "description": "Zapier: clicks to Google Sheets",
    "is_active": true,
    "secret": "9f2c4e7a1b8d3f6e0a5c2b9d7e4f1a3c6b8d0e2f4a6c8e0b2d4f6a8c0e2b4d61",
    "created_at": "2026-09-14T10:05:12+00:00"
  }
}

Das secret zum Signieren wird nur beim Erstellen des Abos zurückgegeben. Verwende es, um Signaturen zu verifizieren. Ein Studio-Workspace kann bis zu 10 Webhook-Endpunkte haben. Lösche ein Abo mit DELETE /webhooks/{id}, was 204 No Content liefert.

Beispiel: Beta aus der CI veröffentlichen

Dieses Skript erstellt eine App, fügt ihren Google-Play-Link hinzu, importiert den Store-Eintrag und gibt den Smart Link aus. Es benötigt curl, jq und ein Token mit apps:write.

#!/usr/bin/env bash
set -euo pipefail

API="https://mapps.one/api/v1"
HEADERS=(-H "Authorization: Bearer $MAPPS_TOKEN" -H "Accept: application/json" -H "Content-Type: application/json")

APP_ID=$(curl -sf "${HEADERS[@]}" -X POST "$API/apps" \
  -d '{"name": "Habitly Beta", "slug": "habitly-beta"}' | jq -r '.data.id')

curl -sf "${HEADERS[@]}" -X PUT "$API/apps/$APP_ID/links" \
  -d '{"links": {"google_play": "https://play.google.com/store/apps/details?id=com.habitly.beta"}}' > /dev/null

curl -sf "${HEADERS[@]}" -X POST "$API/apps/$APP_ID/metadata" \
  -d '{"overwrite": true}' | jq -r '.data.urls.smart_link'

Versionierung

Dies ist Version 1 der API. Wir können jederzeit Endpunkte, Felder und Ereignistypen hinzufügen. Ignoriere daher Felder, die du nicht kennst. Inkompatible Änderungen erscheinen als neue Version und werden vorab angekündigt.