Desenvolvedores
Referência da API
A API REST do mapps.one permite criar e atualizar apps, gerenciar links da loja, importar metadados da loja, ler análises, gerar códigos QR e se inscrever em webhooks a partir do seu próprio código, pipeline de CI ou integração. A API está disponível no plano Studio.
URL base
https://mapps.one/api/v1
Todas as solicitações usam HTTPS. Envie os corpos das solicitações em JSON com Content-Type: application/json e sempre envie Accept: application/json para que os erros também sejam retornados em JSON.
Autenticação
Crie um token no painel, em Desenvolvedores. Proprietários e admins do espaço de trabalho podem fazer isso. Dê um nome ao token, como "GitHub Actions", e escolha as permissões dele. O token é exibido apenas uma vez, então guarde-o no seu gerenciador de segredos imediatamente.
Os tokens pertencem ao espaço de trabalho, não a uma pessoa, então continuam funcionando quando alguém sai da equipe. Eles não expiram. Revogue um token na mesma página quando não precisar mais dele ou se ele puder ter vazado.
Envie o token como bearer token:
curl https://mapps.one/api/v1/workspace \
-H "Authorization: Bearer $MAPPS_TOKEN" \
-H "Accept: application/json"
Permissões
| Permissão | Permite |
|---|---|
apps:read | Listar e ler apps, baixar códigos QR |
apps:write | Criar, atualizar e excluir apps, substituir links da loja, importar metadados da loja |
analytics:read | Ler as análises dos apps |
webhooks:manage | Listar, criar e excluir inscrições de webhook |
GET /workspace e GET /events funcionam com qualquer token válido. Dê a cada integração apenas as permissões de que ela precisa.
Convenções
- Os IDs são ULIDs de 26 caracteres em minúsculas, como
01j8b2k6r3xq9v7m4n5p0s1t2w. Os apps são identificados peloid, não pelo slug, então renomear um slug nunca quebra sua integração. - Os timestamps seguem a ISO 8601 em UTC, como
2026-09-14T08:12:44+00:00. - As respostas envolvem o resultado em uma chave
data. - As chaves de loja são
app_store,google_play,app_gallery,microsoft_storeeweb. - As chaves de plataforma são
ios,android,huawei,windows,macoseother. As chaves de destino são as chaves de loja maislanding.
Limites de taxa
Cada espaço de trabalho pode fazer 120 solicitações por minuto, compartilhadas entre todos os seus tokens. Toda resposta inclui os cabeçalhos X-RateLimit-Limit e X-RateLimit-Remaining. Quando você ultrapassa o limite, a API responde com 429 Too Many Requests e um cabeçalho Retry-After com o número de segundos que você deve aguardar.
Erros
Os erros retornam um corpo JSON com uma message legível por humanos. Alguns erros também incluem um code legível por máquinas, e os erros de validação listam os problemas por campo em errors.
| Status | Quando |
|---|---|
401 | O token está ausente, é inválido ou foi revogado. {"message": "Unauthenticated."} |
402 | O plano do espaço de trabalho não inclui acesso à API. Código plan_required. |
403 | O token não tem a permissão exigida por este endpoint. {"message": "Invalid ability provided."} |
404 | O app ou a inscrição não existe, ou pertence a outro espaço de trabalho. |
422 | A validação falhou ou a solicitação não pôde ser concluída. Por exemplo, código metadata_unavailable. |
429 | Limite de taxa excedido. Aguarde o número de segundos indicado em Retry-After. |
5xx | Algo deu errado do nosso lado. Tente novamente com backoff exponencial. |
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."]
}
}
Endpoints
| Método e caminho | Permissão | Descrição |
|---|---|---|
GET /workspace | qualquer | Espaço de trabalho, plano, uso e o token atual |
GET /events | qualquer | Tipos de evento de webhook |
GET /apps | apps:read | Listar apps |
POST /apps | apps:write | Criar um app |
GET /apps/{id} | apps:read | Obter um app |
PATCH /apps/{id} | apps:write | Atualizar um app |
DELETE /apps/{id} | apps:write | Excluir um app |
PUT /apps/{id}/links | apps:write | Definir ou remover links da loja |
POST /apps/{id}/metadata | apps:write | Importar detalhes da ficha da loja |
GET /apps/{id}/analytics | analytics:read | Totais, série diária e detalhamentos |
GET /apps/{id}/qr | apps:read | Imagem do código QR |
GET /webhooks | webhooks:manage | Listar inscrições de webhook |
POST /webhooks | webhooks:manage | Criar uma inscrição de webhook |
DELETE /webhooks/{id} | webhooks:manage | Excluir uma inscrição de webhook |
O objeto app
| Campo | Tipo | Descrição |
|---|---|---|
id | string | ULID do app |
name | string | Nome do app |
slug | string | O caminho do link inteligente: mapps.one/{slug} |
status | string | live, paused ou suspended |
tagline, description | string ou null | Textos da página |
category | string ou null | Uma chave de categoria, como health-fitness ou productivity |
page_theme | string | clean, midnight ou vivid |
accent_color | string ou null | Cor hexadecimal, como #16a34a |
developer | object | name, website e email |
social_links | object | Perfis sociais preenchidos, indexados por rede: x, instagram, tiktok, youtube, facebook, linkedin, threads, github, discord, reddit |
features | array | Itens de recurso com icon, title e description |
listed_in_explore | boolean | Se o app aparece no Explore |
utm_passthrough | boolean | Se as tags UTM são repassadas às lojas |
redirect_rules | object | Destino por plataforma, com os valores padrão preenchidos |
icon_url | string ou null | URL pública do ícone |
rating | object ou null | value e count da loja |
urls | object | URLs públicas: smart_link, landing_page, qr_svg, qr_png, privacy_policy, terms. As URLs jurídicas retornam 404 até que o documento seja publicado. |
links | object | Links da loja indexados por loja, cada um com url, status (unverified, verified ou invalid) e verified_at. Incluído nas respostas de um único app. |
screenshots | array | Capturas de tela com url, width e height. Incluído depois de uma importação de metadados. |
created_at, updated_at | string | Timestamps ISO 8601 |
Obter um app
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"
}
}
Listar apps
Retorna os apps do espaço de trabalho. Os resultados são paginados: siga links.next, ou passe ?page=2, até que ele seja 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
}
}
Os objetos app estão abreviados neste exemplo. Cada item tem o conjunto completo de campos.
Criar um app
| Campo | Obrigatório | Descrição |
|---|---|---|
name | Sim | Nome do app, com até 120 caracteres |
slug | Não | De 3 a 40 letras minúsculas, números e hifens simples. Quando omitido, um slug livre é gerado a partir do nome. |
links | Não | Links da loja indexados por loja, no mesmo formato de Definir links da loja |
Você também pode enviar qualquer um dos campos listados em Atualizar um app.
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"
}
}'
A resposta é 201 Created com o novo objeto app. Os links da loja são salvos na forma canônica com o status unverified até que a verificação em segundo plano termine. Para preencher o ícone, as capturas de tela e a descrição, chame Importar metadados da loja em seguida.
Atualizar um app
Envie apenas os campos que você quer alterar.
| Campo | Tipo |
|---|---|
name | string |
slug | string. Alterá-lo quebra o link antigo imediatamente. |
tagline, description | string ou null |
category | chave de categoria ou null |
page_theme | clean, midnight ou vivid |
accent_color | #rrggbb ou null |
utm_passthrough, listed_in_explore | boolean |
redirect_rules | objeto que associa chaves de plataforma a chaves de destino |
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" }
}'
A resposta é o objeto app atualizado.
Excluir um app
curl https://mapps.one/api/v1/apps/01j8b2k6r3xq9v7m4n5p0s1t2w \
-X DELETE \
-H "Authorization: Bearer $MAPPS_TOKEN" \
-H "Accept: application/json"
A resposta é 204 No Content. A exclusão é permanente: o link inteligente, a página de destino, os documentos jurídicos, as mídias e as análises do app são removidos.
Definir links da loja
PUT /apps/{id}/links recebe um objeto links indexado por loja:
- uma URL adiciona ou substitui o link dessa loja,
nullou uma string vazia remove o link,- as lojas que você não incluir não são alteradas.
Cada URL deve ser uma ficha válida da respectiva loja: um link apps.apple.com com um ID de app, um link play.google.com com um ID de pacote, e assim por diante. O link web pode ser qualquer endereço http ou https. As URLs podem ter até 1024 caracteres. Os links são salvos na forma canônica e verificados em segundo plano.
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
}
}'
A resposta é o objeto app, incluindo links. Um link inválido retorna 422:
{
"message": "This is not a valid Google Play link.",
"errors": {
"links.google_play": ["This is not a valid Google Play link."]
}
}
Importar metadados da loja
POST /apps/{id}/metadata lê a ficha da App Store, ou a ficha do Google Play quando não há um link da App Store legível, e importa os detalhes dela.
| Campo | Descrição |
|---|---|
overwrite | Opcional, padrão false. Quando false, apenas os campos vazios são preenchidos, e as capturas de tela só são adicionadas se o app não tiver nenhuma. Quando true, o nome, o ícone, os textos e as capturas de tela são substituídos. A avaliação e o preço são sempre atualizados. |
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 }'
A resposta é o objeto app, incluindo links e screenshots, e um webhook app.metadata_fetched é enviado. Se nenhuma ficha puder ser lida:
HTTP/2 422
{
"message": "The store listing could not be read. Add a valid App Store or Google Play link first.",
"code": "metadata_unavailable"
}
Análises
GET /apps/{id}/analytics aceita estes parâmetros de consulta:
| Parâmetro | Descrição |
|---|---|
range | 7d, 30d, 90d, 12m ou custom. Padrão 30d. |
from, to | Datas no formato YYYY-MM-DD, ambas incluídas, para range=custom. to não pode ser posterior a hoje. |
timezone | Um fuso horário IANA, como Europe/Istanbul, usado para os limites dos dias. Padrão 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é incluído etoé excluído. Ambos são instantes em UTC.clamped_to_planétruequando o período solicitado foi encurtado para caber no histórico do plano.dailyconta os cliques por data local, incluindo dias sem cliques.- Os detalhamentos listam até 10 valores, dos mais frequentes para os menos frequentes. Uma chave vazia
""significa desconhecido ou não definido. - As definições das métricas estão na página Análises.
Código QR
GET /apps/{id}/qr retorna uma imagem. Use format=svg (padrão) ou format=png, além das mesmas opções das URLs públicas de QR: fg, bg, margin, ecc, size, logo e download. Veja Códigos QR e kit de imprensa.
curl "https://mapps.one/api/v1/apps/01j8b2k6r3xq9v7m4n5p0s1t2w/qr?format=png&size=2048&ecc=Q" \
-H "Authorization: Bearer $MAPPS_TOKEN" \
-o habitly-qr.png
Espaço de trabalho
GET /workspace retorna o espaço de trabalho, os limites e recursos do plano, o uso atual e o token em uso. É uma boa primeira chamada para verificar se um token funciona.
{
"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"] }
}
}
Um limite null significa ilimitado.
Tipos de evento
GET /events lista os tipos de evento de webhook com uma descrição curta. As integrações podem usá-lo para montar um seletor de eventos.
{
"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." }
]
}
Inscrições de webhook
Crie inscrições de webhook a partir do código, por exemplo quando um usuário conecta sua integração, e exclua-as quando ele se desconectar. POST /webhooks recebe:
| Campo | Obrigatório | Descrição |
|---|---|---|
url | Sim | Uma URL https pública que recebe os eventos |
events | Sim | Um array de tipos de evento, ou ["*"] para todos os eventos |
description | Não | Até 160 caracteres, exibida no painel |
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"
}
}
O secret de assinatura só é retornado quando a inscrição é criada. Use-o para verificar assinaturas. Um espaço de trabalho Studio pode ter até 10 endpoints de webhook. Exclua uma inscrição com DELETE /webhooks/{id}, que retorna 204 No Content.
Exemplo: publicar uma versão beta pelo CI
Este script cria um app, adiciona o link do Google Play dele, importa a ficha e imprime o link inteligente. Ele precisa de curl, jq e de um token com 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'
Versionamento
Esta é a versão 1 da API. Podemos adicionar endpoints, campos e tipos de evento a qualquer momento, então ignore os campos que você não reconhecer. Mudanças incompatíveis serão lançadas como uma nova versão, com aviso prévio.