Aller au contenu

Développeurs

Référence de l'API

L'API REST de mapps.one vous permet de créer et de mettre à jour des applications, de gérer les liens de store, d'importer les métadonnées des stores, de consulter les statistiques, de générer des codes QR et de vous abonner à des webhooks depuis votre propre code, votre pipeline de CI ou votre intégration. L'API est disponible avec le forfait Studio.

URL de base

https://mapps.one/api/v1

Toutes les requêtes utilisent HTTPS. Envoyez les corps de requête en JSON avec Content-Type: application/json, et envoyez toujours Accept: application/json pour que les erreurs soient elles aussi renvoyées en JSON.

Authentification

Créez un jeton dans le tableau de bord, sous Développeurs. Les propriétaires et les administrateurs de l'espace de travail peuvent le faire. Donnez un nom au jeton, comme « GitHub Actions », et choisissez ses permissions. Le jeton n'est affiché qu'une seule fois, conservez-le donc immédiatement dans votre gestionnaire de secrets.

Les jetons appartiennent à l'espace de travail, et non à une personne : ils continuent donc de fonctionner lorsque quelqu'un quitte l'équipe. Ils n'expirent pas. Révoquez un jeton depuis la même page lorsque vous n'en avez plus besoin, ou s'il a pu fuiter.

Envoyez le jeton comme jeton Bearer :

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

Permissions

PermissionAutorise
apps:readLister et lire les applications, télécharger les codes QR
apps:writeCréer, mettre à jour et supprimer des applications, remplacer les liens de store, importer les métadonnées des stores
analytics:readLire les statistiques des applications
webhooks:manageLister, créer et supprimer des abonnements webhook

GET /workspace et GET /events fonctionnent avec n'importe quel jeton valide. N'accordez à chaque intégration que les permissions dont elle a besoin.

Conventions

  • Les identifiants sont des ULID de 26 caractères en minuscules, comme 01j8b2k6r3xq9v7m4n5p0s1t2w. Les applications sont désignées par leur id, et non par leur slug : renommer un slug ne casse donc jamais votre intégration.
  • Les horodatages sont au format ISO 8601 en UTC, comme 2026-09-14T08:12:44+00:00.
  • Les réponses encapsulent le résultat dans une clé data.
  • Les clés de store sont app_store, google_play, app_gallery, microsoft_store et web.
  • Les clés de plateforme sont ios, android, huawei, windows, macos et other. Les clés de destination sont les clés de store, plus landing.

Limites de débit

Chaque espace de travail peut effectuer 120 requêtes par minute, partagées entre tous ses jetons. Chaque réponse inclut les en-têtes X-RateLimit-Limit et X-RateLimit-Remaining. Lorsque vous dépassez la limite, l'API répond 429 Too Many Requests avec un en-tête Retry-After qui indique le nombre de secondes à attendre.

Erreurs

Les erreurs renvoient un corps JSON avec un message lisible par un humain. Certaines erreurs incluent aussi un code lisible par une machine, et les erreurs de validation listent les problèmes par champ dans errors.

StatutQuand
401Le jeton est absent, non valide ou révoqué. {"message": "Unauthenticated."}
402Le forfait de l'espace de travail n'inclut pas l'accès à l'API. Code plan_required.
403Le jeton n'a pas la permission requise par ce point de terminaison. {"message": "Invalid ability provided."}
404L'application ou l'abonnement n'existe pas, ou appartient à un autre espace de travail.
422La validation a échoué, ou la requête n'a pas pu aboutir. Par exemple, code metadata_unavailable.
429Limite de débit dépassée. Attendez le nombre de secondes indiqué dans Retry-After.
5xxUn problème est survenu de notre côté. Réessayez avec un backoff exponentiel.
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."]
  }
}

Points de terminaison

Méthode et cheminPermissionDescription
GET /workspacen'importe laquelleEspace de travail, forfait, utilisation et jeton actuel
GET /eventsn'importe laquelleTypes d'événements webhook
GET /appsapps:readLister les applications
POST /appsapps:writeCréer une application
GET /apps/{id}apps:readRécupérer une application
PATCH /apps/{id}apps:writeMettre à jour une application
DELETE /apps/{id}apps:writeSupprimer une application
PUT /apps/{id}/linksapps:writeDéfinir ou supprimer des liens de store
POST /apps/{id}/metadataapps:writeImporter les détails depuis la fiche store
GET /apps/{id}/analyticsanalytics:readTotaux, série quotidienne et répartitions
GET /apps/{id}/qrapps:readImage du code QR
GET /webhookswebhooks:manageLister les abonnements webhook
POST /webhookswebhooks:manageCréer un abonnement webhook
DELETE /webhooks/{id}webhooks:manageSupprimer un abonnement webhook

L'objet application

ChampTypeDescription
idchaîneULID de l'application
namechaîneNom de l'application
slugchaîneLe chemin du lien intelligent : mapps.one/{slug}
statuschaînelive, paused ou suspended
tagline, descriptionchaîne ou nullTextes de la page
categorychaîne ou nullUne clé de catégorie, comme health-fitness ou productivity
page_themechaîneclean, midnight ou vivid
accent_colorchaîne ou nullCouleur hexadécimale, comme #16a34a
developerobjetname, website et email
social_linksobjetProfils sociaux renseignés, indexés par réseau : x, instagram, tiktok, youtube, facebook, linkedin, threads, github, discord, reddit
featurestableauÉléments de la liste de fonctionnalités, avec icon, title et description
listed_in_explorebooléenIndique si l'application apparaît dans Explorer
utm_passthroughbooléenIndique si les balises UTM sont transmises aux stores
redirect_rulesobjetDestination par plateforme, avec les valeurs par défaut renseignées
icon_urlchaîne ou nullURL publique de l'icône
ratingobjet ou nullvalue et count issus du store
urlsobjetURL publiques : smart_link, landing_page, qr_svg, qr_png, privacy_policy, terms. Les URL légales renvoient 404 tant que le document n'est pas publié.
linksobjetLiens de store indexés par store, chacun avec url, status (unverified, verified ou invalid) et verified_at. Inclus dans les réponses qui portent sur une seule application.
screenshotstableauCaptures d'écran avec url, width et height. Incluses après une importation des métadonnées.
created_at, updated_atchaîneHorodatages ISO 8601

Récupérer une application

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"
  }
}

Lister les applications

Renvoie les applications de l'espace de travail. Les résultats sont paginés : suivez links.next, ou passez ?page=2, jusqu'à ce qu'il vaille null.

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
  }
}

Les objets application sont abrégés dans cet exemple. Chaque élément contient l'ensemble des champs.

Créer une application

ChampObligatoireDescription
nameOuiNom de l'application, jusqu'à 120 caractères
slugNonDe 3 à 40 lettres minuscules, chiffres et tirets simples. S'il est omis, un slug disponible est généré à partir du nom.
linksNonLiens de store indexés par store, au même format que dans Définir les liens de store

Vous pouvez aussi envoyer n'importe lequel des champs listés dans Mettre à jour une application.

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"
    }
  }'

La réponse est 201 Created, avec le nouvel objet application. Les liens de store sont enregistrés sous forme canonique, avec le statut unverified jusqu'à la fin de la vérification en arrière-plan. Pour renseigner l'icône, les captures d'écran et la description, appelez ensuite Importer les métadonnées du store.

Mettre à jour une application

Envoyez uniquement les champs que vous souhaitez modifier.

ChampType
namechaîne
slugchaîne. Le modifier casse immédiatement l'ancien lien.
tagline, descriptionchaîne ou null
categoryclé de catégorie ou null
page_themeclean, midnight ou vivid
accent_color#rrggbb ou null
utm_passthrough, listed_in_explorebooléen
redirect_rulesobjet associant une clé de plateforme à une clé de destination
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" }
  }'

La réponse est l'objet application mis à jour.

Supprimer une application

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

La réponse est 204 No Content. La suppression est définitive : le lien intelligent, la page de destination, les documents légaux, les médias et les statistiques de l'application sont supprimés.

PUT /apps/{id}/links accepte un objet links indexé par store :

  • une URL ajoute ou remplace le lien de ce store,
  • null ou une chaîne vide le supprime,
  • les stores que vous omettez ne sont pas modifiés.

Chaque URL doit correspondre à une fiche valide de son store : un lien apps.apple.com avec un identifiant d'application, un lien play.google.com avec un identifiant de package, etc. Le lien web peut être n'importe quelle adresse http ou https. Les URL peuvent comporter jusqu'à 1024 caractères. Les liens sont enregistrés sous forme canonique et vérifiés en arrière-plan.

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
    }
  }'

La réponse est l'objet application, links compris. Un lien non valide renvoie 422 :

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

Importer les métadonnées du store

POST /apps/{id}/metadata lit la fiche App Store, ou la fiche Google Play s'il n'existe aucun lien App Store lisible, et importe ses détails.

ChampDescription
overwriteFacultatif, false par défaut. Avec la valeur false, seuls les champs vides sont remplis, et les captures d'écran ne sont ajoutées que si l'application n'en a aucune. Avec la valeur true, le nom, l'icône, les textes et les captures d'écran sont remplacés. La note et le prix sont toujours mis à jour.
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 }'

La réponse est l'objet application, links et screenshots compris, et un webhook app.metadata_fetched est envoyé. Si aucune fiche ne peut être lue :

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

Statistiques

GET /apps/{id}/analytics accepte ces paramètres de requête :

ParamètreDescription
range7d, 30d, 90d, 12m ou custom. Valeur par défaut : 30d.
from, toDates au format YYYY-MM-DD, toutes deux incluses, pour range=custom. to ne peut pas être postérieure à aujourd'hui.
timezoneUn fuseau horaire IANA, comme Europe/Istanbul, utilisé pour délimiter les jours. Valeur par défaut : 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 est inclus et to est exclu. Ce sont tous deux des instants UTC.
  • clamped_to_plan vaut true lorsque la plage demandée a été raccourcie à l'historique du forfait.
  • daily compte les clics par date locale, y compris les jours sans clic.
  • Les répartitions listent jusqu'à 10 valeurs, de la plus fréquente à la moins fréquente. Une clé vide "" signifie inconnue ou non définie.
  • Les définitions des métriques figurent sur la page Statistiques.

Code QR

GET /apps/{id}/qr renvoie une image. Utilisez format=svg (par défaut) ou format=png, ainsi que les mêmes options que pour les URL QR publiques : fg, bg, margin, ecc, size, logo et download. Consultez Codes QR et kit de presse.

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

Espace de travail

GET /workspace renvoie l'espace de travail, les limites et les fonctionnalités de son forfait, l'utilisation actuelle et le jeton utilisé. C'est un bon premier appel pour vérifier qu'un jeton fonctionne.

{
  "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"] }
  }
}

Une limite null signifie illimité.

Types d'événements

GET /events liste les types d'événements webhook avec une courte description. Les intégrations peuvent l'utiliser pour créer un sélecteur d'événements.

{
  "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." }
  ]
}

Abonnements webhook

Créez des abonnements webhook depuis votre code, par exemple lorsqu'un utilisateur connecte votre intégration, et supprimez-les lorsqu'il la déconnecte. POST /webhooks accepte :

ChampObligatoireDescription
urlOuiUne URL https publique qui reçoit les événements
eventsOuiUn tableau de types d'événements, ou ["*"] pour tous les événements
descriptionNonJusqu'à 160 caractères, affichée dans le tableau de bord
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"
  }
}

Le secret de signature n'est renvoyé qu'à la création de l'abonnement. Utilisez-le pour vérifier les signatures. Un espace de travail Studio peut avoir jusqu'à 10 points de terminaison de webhook. Supprimez un abonnement avec DELETE /webhooks/{id}, qui renvoie 204 No Content.

Exemple : publier une bêta depuis la CI

Ce script crée une application, ajoute son lien Google Play, importe la fiche et affiche le lien intelligent. Il nécessite curl, jq et un jeton disposant de la permission 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'

Gestion des versions

Il s'agit de la version 1 de l'API. Nous pouvons ajouter des points de terminaison, des champs et des types d'événements à tout moment, ignorez donc les champs que vous ne reconnaissez pas. Les changements incompatibles seront publiés dans une nouvelle version, avec un préavis.