본문으로 건너뛰기

개발자

API 레퍼런스

mapps.one REST API를 사용하면 자체 코드, CI 파이프라인 또는 연동 서비스에서 앱을 만들고 업데이트하고, 스토어 링크를 관리하고, 스토어 메타데이터를 가져오고, 분석을 읽고, QR 코드를 생성하고, 웹훅을 구독할 수 있어요. API는 Studio 플랜에서 사용할 수 있어요.

기본 URL

https://mapps.one/api/v1

모든 요청은 HTTPS를 사용해요. 요청 본문은 Content-Type: application/json 헤더와 함께 JSON으로 보내고, 오류도 JSON으로 반환되도록 항상 Accept: application/json 헤더를 보내세요.

인증

대시보드의 개발자 메뉴에서 토큰을 만드세요. 워크스페이스 소유자와 관리자가 이 작업을 할 수 있어요. 토큰에 "GitHub Actions" 같은 이름을 지정하고 권한을 선택하세요. 토큰은 한 번만 표시되므로 바로 시크릿 관리 도구에 보관하세요.

토큰은 개인이 아닌 워크스페이스에 속하므로, 누군가 팀을 떠나도 계속 작동해요. 토큰은 만료되지 않아요. 더 이상 필요 없거나 유출되었을 가능성이 있다면 같은 페이지에서 토큰을 폐기하세요.

토큰은 Bearer 토큰으로 보내세요.

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

권한

권한허용되는 작업
apps:read앱 목록 조회 및 읽기, QR 코드 다운로드
apps:write앱 만들기, 업데이트 및 삭제, 스토어 링크 교체, 스토어 메타데이터 가져오기
analytics:read앱 분석 읽기
webhooks:manage웹훅 구독 목록 조회, 만들기 및 삭제

GET /workspace 엔드포인트와 GET /events 엔드포인트는 유효한 토큰이라면 어떤 토큰으로도 사용할 수 있어요. 각 연동 서비스에는 필요한 권한만 부여하세요.

규칙

  • ID는 01j8b2k6r3xq9v7m4n5p0s1t2w 값처럼 26자의 소문자 ULID예요. 앱은 링크 주소(슬러그)가 아닌 id 값으로 지정하므로, 링크 주소를 바꿔도 연동이 깨지지 않아요.
  • 타임스탬프는 2026-09-14T08:12:44+00:00 값처럼 UTC 기준 ISO 8601 형식이에요.
  • 응답은 결과를 data 키로 감싸요.
  • 스토어 키는 app_store, google_play, app_gallery, microsoft_store, web 값이에요.
  • 플랫폼 키는 ios, android, huawei, windows, macos, other 값이에요. 이동 대상 키는 스토어 키에 landing 값을 더한 것이에요.

요청 한도

각 워크스페이스는 분당 120개의 요청을 보낼 수 있으며, 이 한도는 워크스페이스의 모든 토큰이 함께 사용해요. 모든 응답에는 X-RateLimit-Limit 헤더와 X-RateLimit-Remaining 헤더가 포함돼요. 한도를 넘으면 API가 429 Too Many Requests 상태와 함께, 기다려야 할 초 수를 담은 Retry-After 헤더로 응답해요.

오류

오류는 사람이 읽을 수 있는 message 필드가 담긴 JSON 본문을 반환해요. 일부 오류에는 기계가 읽을 수 있는 code 필드도 포함되며, 유효성 검사 오류는 errors 필드에 필드별 문제를 나열해요.

상태발생 조건
401토큰이 없거나, 유효하지 않거나, 폐기되었어요. {"message": "Unauthenticated."}
402워크스페이스 플랜에 API 접근이 포함되지 않아요. 코드 plan_required.
403토큰에 이 엔드포인트에 필요한 권한이 없어요. {"message": "Invalid ability provided."}
404앱이나 구독이 존재하지 않거나 다른 워크스페이스에 속해 있어요.
422유효성 검사에 실패했거나 요청을 완료할 수 없어요. 예: 코드 metadata_unavailable.
429요청 한도를 초과했어요. Retry-After 헤더에 표시된 초 수만큼 기다리세요.
5xx저희 쪽에서 문제가 발생했어요. 지수 백오프로 재시도하세요.
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."]
  }
}

엔드포인트

메서드 및 경로권한설명
GET /workspace모두워크스페이스, 플랜, 사용량, 현재 토큰
GET /events모두웹훅 이벤트 유형
GET /appsapps:read앱 목록 조회
POST /appsapps:write앱 만들기
GET /apps/{id}apps:read앱 조회
PATCH /apps/{id}apps:write앱 업데이트
DELETE /apps/{id}apps:write앱 삭제
PUT /apps/{id}/linksapps:write스토어 링크 설정 또는 삭제
POST /apps/{id}/metadataapps:write스토어 등록 정보에서 정보 가져오기
GET /apps/{id}/analyticsanalytics:read합계, 일별 시계열, 세부 분석
GET /apps/{id}/qrapps:readQR 코드 이미지
GET /webhookswebhooks:manage웹훅 구독 목록 조회
POST /webhookswebhooks:manage웹훅 구독 만들기
DELETE /webhooks/{id}webhooks:manage웹훅 구독 삭제

앱 객체

필드유형설명
idstring앱의 ULID
namestring앱 이름
slugstring스마트 링크의 경로: mapps.one/{slug}
statusstringlive, paused 또는 suspended
tagline, descriptionstring 또는 null페이지 텍스트
categorystring 또는 nullhealth-fitness, productivity 같은 카테고리 키
page_themestringclean, midnight 또는 vivid
accent_colorstring 또는 null#16a34a 같은 16진수 색상
developerobjectname, website, email
social_linksobject입력된 소셜 프로필. 네트워크별 키로 구분돼요: x, instagram, tiktok, youtube, facebook, linkedin, threads, github, discord, reddit
featuresarrayicon, title, description 값을 가진 기능 항목
listed_in_exploreboolean앱이 둘러보기에 표시되는지 여부
utm_passthroughbooleanUTM 태그를 스토어로 전달하는지 여부
redirect_rulesobject플랫폼별 이동 대상(기본값이 채워져 있음)
icon_urlstring 또는 null아이콘의 공개 URL
ratingobject 또는 null스토어에서 가져온 value 및 count 값
urlsobject공개 URL: smart_link, landing_page, qr_svg, qr_png, privacy_policy, terms. 법률 문서 URL은 문서가 게시될 때까지 404를 반환해요.
linksobject스토어별 키로 구분된 스토어 링크. 각 링크에는 url, status(unverified, verified 또는 invalid), verified_at 값이 있어요. 단일 앱 응답에 포함돼요.
screenshotsarrayurl, width, height 값을 가진 스크린샷. 메타데이터를 가져온 후에 포함돼요.
created_at, updated_atstringISO 8601 타임스탬프

앱 조회하기

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

앱 목록 조회하기

워크스페이스의 앱을 반환해요. 결과는 페이지로 나뉘어 있어요. links.next 값이 null 값이 될 때까지 해당 링크를 따라가거나 ?page=2 파라미터를 전달하세요.

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

이 예시에서는 앱 객체를 줄여서 표시했어요. 실제로는 각 항목에 전체 필드가 포함돼요.

앱 만들기

필드필수설명
name예앱 이름, 최대 120자
slug아니요영문 소문자, 숫자, 단일 하이픈으로 된 3~40자. 생략하면 이름을 바탕으로 사용 가능한 링크 주소가 생성돼요.
links아니요스토어별 키로 구분된 스토어 링크. 형식은 스토어 링크 설정하기와 같아요.

앱 업데이트하기에 나열된 필드도 함께 보낼 수 있어요.

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

응답은 새 앱 객체와 함께 201 Created 상태로 반환돼요. 스토어 링크는 표준 형식으로 저장되며, 백그라운드 확인이 끝날 때까지 상태는 unverified 값이에요. 아이콘, 스크린샷, 설명을 채우려면 이어서 스토어 메타데이터 가져오기를 호출하세요.

앱 업데이트하기

변경할 필드만 보내세요.

필드유형
namestring
slugstring. 변경하면 이전 링크가 즉시 작동하지 않아요.
tagline, descriptionstring 또는 null
category카테고리 키 또는 null
page_themeclean, midnight 또는 vivid
accent_color#rrggbb 또는 null
utm_passthrough, listed_in_exploreboolean
redirect_rules플랫폼 키를 이동 대상 키에 매핑한 object
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" }
  }'

응답은 업데이트된 앱 객체예요.

앱 삭제하기

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

응답은 204 No Content 상태예요. 삭제는 되돌릴 수 없어요. 앱의 스마트 링크, 랜딩 페이지, 법률 문서, 미디어, 분석 데이터가 삭제돼요.

PUT /apps/{id}/links 엔드포인트는 스토어별 키로 구분된 links 객체를 받아요.

  • URL을 보내면 해당 스토어의 링크가 추가되거나 교체돼요.
  • null 값이나 빈 문자열을 보내면 링크가 삭제돼요.
  • 생략한 스토어는 변경되지 않아요.

각 URL은 해당 스토어의 유효한 등록 정보여야 해요. 예를 들어 앱 ID가 포함된 apps.apple.com 링크, 패키지 ID가 포함된 play.google.com 링크 등이에요. web 링크에는 http 또는 https 주소라면 무엇이든 사용할 수 있어요. URL은 최대 1024자까지 가능해요. 링크는 표준 형식으로 저장되고 백그라운드에서 확인돼요.

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

응답은 links 필드를 포함한 앱 객체예요. 유효하지 않은 링크는 422 상태를 반환해요.

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

스토어 메타데이터 가져오기

POST /apps/{id}/metadata 엔드포인트는 App Store 등록 정보를 읽고(읽을 수 있는 App Store 링크가 없으면 Google Play 등록 정보를 읽어요) 그 정보를 가져와요.

필드설명
overwrite선택 사항이며 기본값은 false 값이에요. false이면 비어 있는 필드만 채우고, 앱에 스크린샷이 없을 때만 스크린샷을 추가해요. true이면 이름, 아이콘, 텍스트, 스크린샷을 교체해요. 평점과 가격은 항상 업데이트돼요.
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 }'

응답은 links 필드와 screenshots 필드를 포함한 앱 객체이며, app.metadata_fetched 웹훅이 전송돼요. 읽을 수 있는 등록 정보가 없으면 다음과 같이 응답해요.

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

분석

GET /apps/{id}/analytics 엔드포인트는 다음 쿼리 파라미터를 받아요.

파라미터설명
range7d, 30d, 90d, 12m 또는 custom. 기본값은 30d 값이에요.
from, torange=custom 값과 함께 사용하는 YYYY-MM-DD 형식의 날짜(양쪽 모두 포함). to 값은 오늘보다 늦을 수 없어요.
timezone일 경계를 정하는 데 사용하는 IANA 시간대(예: Europe/Istanbul). 기본값은 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 값은 포함되고 to 값은 제외돼요. 둘 다 UTC 시점이에요.
  • 요청한 범위가 플랜의 기록 기간에 맞춰 짧아졌다면 clamped_to_plan 값은 true 값이에요.
  • daily 필드는 클릭이 없는 날을 포함해 현지 날짜별 클릭 수를 집계해요.
  • 세부 분석은 가장 빈도가 높은 값부터 최대 10개까지 나열해요. 빈 키 "" 값은 알 수 없거나 설정되지 않았다는 뜻이에요.
  • 지표 정의는 분석 페이지에 있어요.

QR 코드

GET /apps/{id}/qr 엔드포인트는 이미지를 반환해요. format=svg(기본값) 또는 format=png 값을 사용하고, 공개 QR URL과 같은 옵션인 fg, bg, margin, ecc, size, logo, download 값을 함께 사용할 수 있어요. QR 코드 및 프레스 키트를 참고하세요.

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

워크스페이스

GET /workspace 엔드포인트는 워크스페이스, 플랜 한도와 기능, 현재 사용량, 사용 중인 토큰을 반환해요. 토큰이 작동하는지 확인하는 첫 호출로 알맞아요.

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

한도가 null 값이면 무제한이라는 뜻이에요.

이벤트 유형

GET /events 엔드포인트는 웹훅 이벤트 유형을 짧은 설명과 함께 나열해요. 연동 서비스에서 이벤트 선택 화면을 만드는 데 사용할 수 있어요.

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

웹훅 구독

사용자가 연동 서비스를 연결할 때처럼 코드에서 웹훅 구독을 만들고, 사용자가 연결을 해제하면 구독을 삭제하세요. POST /webhooks 엔드포인트는 다음 필드를 받아요.

필드필수설명
url예이벤트를 받을 공개 https URL
events예이벤트 유형 배열 또는 모든 이벤트를 뜻하는 ["*"] 값
description아니요최대 160자이며 대시보드에 표시돼요
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"
  }
}

서명 secret 값은 구독을 만들 때만 반환돼요. 이 값으로 서명을 검증하세요. Studio 워크스페이스에는 최대 10개의 웹훅 엔드포인트를 만들 수 있어요. 구독은 DELETE /webhooks/{id} 요청으로 삭제하며, 이 요청은 204 No Content 상태를 반환해요.

예시: CI에서 베타 게시하기

이 스크립트는 앱을 만들고, Google Play 링크를 추가하고, 등록 정보를 가져온 다음 스마트 링크를 출력해요. curl, jq, 그리고 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'

버전 관리

이 문서는 API 버전 1을 다뤄요. 엔드포인트, 필드, 이벤트 유형은 언제든지 추가될 수 있으므로 알 수 없는 필드는 무시하세요. 호환성을 깨는 변경 사항은 사전 공지와 함께 새 버전으로 출시돼요.