API Documentation

Everything you need to integrate: authentication, every endpoint with parameters and example responses, ready-to-paste code in five languages, error handling, and the points system.

base URL
https://v1.api.my.id

Quick start

Two endpoints are free and need no key at all β€” try one right now, then create an account for the rest.

1

Call a free endpoint

Holidays and prayer times work without any key.

2

Get an API key

Create a free account β€” your first key is issued instantly. 5,000 free hits/month per account.

3

Send it as a Bearer token

Authorization: Bearer <key> on every protected call.

TRY IT β€” NO KEY NEEDED
# National holidays 2026 (17 holidays + 8 collective leave days)
curl "https://v1.api.my.id/holidays?year=2026"

# Prayer times for Jakarta, today
curl "https://v1.api.my.id/sholat?city=jakarta"
GET A KEY
# 1. Create an account. Your first key is issued instantly.
curl -X POST "https://v1.api.my.id/auth/register" \
  -H "Content-Type: application/json" \
  -d '{"name": "Nama Anda", "email": "anda@perusahaan.com", "password": "min-8-karakter"}'

# β†’ {"data": {"api_key": "myid_live_…", "session_token": "…", "monthly_quota": 5000}}
# Store this api_key β€” it is shown only once.

# 2. Need another key later? Use the login session, not an API key.
curl -X POST "https://v1.api.my.id/keys/register" \
  -H "Authorization: Session $SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"label": "produksi"}'
There are no anonymous keys: issuing one needs a login session. Points, quota and subscriptions all live on the account, so every key you hold spends from the same balance β€” and revoking a key never costs you points."> Key terikat ke akun. Tidak ada key anonim: menerbitkan key butuh sesi login. Poin, kuota, dan langganan menempel di akun, jadi semua key Anda memakai saldo yang sama β€” dan mencabut key tidak pernah menghanguskan poin.">Keys belong to accounts. There are no anonymous keys: issuing one needs a login session. Points, quota and subscriptions all live on the account, so every key you hold spends from the same balance β€” and revoking a key never costs you points.

Authentication

Send your key on every protected endpoint. Two header forms are accepted β€” use whichever your HTTP client makes easiest.

Authorization: Bearer myid_live_a1b2c3d4…
# or
X-API-Key: myid_live_a1b2c3d4…
Anyone with the key can spend your points and quota. Never ship it in frontend JavaScript or a mobile app β€” proxy the call through your own backend instead."> Simpan key di sisi server. Siapa pun yang memegang key bisa memakai poin dan kuota Anda. Jangan pernah menaruhnya di JavaScript frontend atau aplikasi mobile β€” proxy panggilannya lewat backend Anda sendiri.">Keep your key server-side. Anyone with the key can spend your points and quota. Never ship it in frontend JavaScript or a mobile app β€” proxy the call through your own backend instead.

Errors, limits & points

Every response uses the same envelope. Errors always carry a human-readable message you can log or surface.

// sukses
{ "status": "success", "code": 200, "data": … }

// error
{ "status": "error", "code": 401, "message": "A valid API key is required…" }
CodeMeaningWhat to do
200SuccessRead the data field.
201Key createdStore the api_key β€” shown once.
400Bad requestA required parameter is missing or malformed.
401No/invalid keyCheck the Authorization header.
402Not enough pointsTop up: POST /billing/topup. The error tells you needed vs balance.
404Not foundUnknown endpoint, city, or resource.
422Unprocessablee.g. coordinates outside Indonesia, private IP.
429Quota exceeded5,000 free hits/month used. Subscribe for more.
501Not configured / reservedThe product needs an external provider β€” see the message.
502Upstream failedRetry. Points are auto-refunded on AI endpoints.

Rate limits

Every key gets 5,000 free hits per month across metered endpoints. Each response carries your usage so you can back off before hitting the wall:

X-RateLimit-Limit: 5000
X-RateLimit-Used: 128

How points work

AI endpoints are pay-per-use, billed in points. 1 IDR = 1 point. Points are deducted only on a successful hit and automatically refunded if the upstream call fails.

EndpointCost
POST /ocr/ktp150 poin
POST /ocr/sim300 poin
POST /cv/extract300 poin
POST /image/remove-bg300 poin
POST /articles/generate1.300 poin

Endpoint reference

πŸ“…

National Holidays

Free

Indonesian national holidays and joint-leave days per the official SKB decree. Free, no API key needed.

GET /holidays βœ“ No key needed Try it β†’

All holidays for a year (2025 & 2026).

QUERY PARAMETERS
year int optional Year. Defaults to the current year.
CURL
curl "https://v1.api.my.id/holidays?year=2026"
EXAMPLE RESPONSE
{
  "status": "success",
  "code": 200,
  "year": 2026,
  "count": 25,
  "data": [
    {
      "date": "2026-08-17",
      "day": "Senin",
      "name": "Hari Kemerdekaan Republik Indonesia",
      "type": "national",
      "is_national": true,
      "is_cuti_bersama": false
    }
  ]
}
GET /holidays/upcoming βœ“ No key needed Try it β†’

Upcoming holidays from today.

QUERY PARAMETERS
limit int optional 1–20. Default 5.
CURL
curl "https://v1.api.my.id/holidays/upcoming?limit=3"
GET /holidays/check βœ“ No key needed Try it β†’

Check whether a given date is a holiday.

QUERY PARAMETERS
date string required Format YYYY-MM-DD.
CURL
curl "https://v1.api.my.id/holidays/check?date=2026-08-17"
EXAMPLE RESPONSE
{
  "status": "success",
  "code": 200,
  "data": {
    "date": "2026-08-17",
    "is_holiday": true,
    "holidays": [ { "name": "Hari Kemerdekaan Republik Indonesia", "type": "national", … } ]
  }
}
πŸ•Œ

Prayer Times

Free

Daily prayer times computed with the standard solar-position algorithm (Kemenag angles: Fajr βˆ’20Β°, Isha βˆ’18Β°, +2 min ihtiyat). Free, no API key needed.

GET /sholat βœ“ No key needed Try it β†’

Prayer schedule for a city and date.

QUERY PARAMETERS
city string required City slug, e.g. jakarta. See /sholat/cities.
date string optional YYYY-MM-DD. Defaults to today.
CURL
curl "https://v1.api.my.id/sholat?city=jakarta&date=2026-07-09"
EXAMPLE RESPONSE
{
  "status": "success",
  "code": 200,
  "data": {
    "city": { "slug": "jakarta", "name": "Jakarta", "lat": -6.2088, "lng": 106.8456 },
    "date": "2026-07-09",
    "timezone": "WIB",
    "gmt_offset": "+7",
    "jadwal": {
      "imsak": "04:31", "subuh": "04:41", "terbit": "06:04", "dhuha": "06:28",
      "dzuhur": "12:00", "ashar": "15:20", "maghrib": "17:53", "isya": "19:06"
    }
  }
}
GET /sholat/cities βœ“ No key needed Try it β†’

The 54 supported cities (WIB/WITA/WIT).

CURL
curl "https://v1.api.my.id/sholat/cities"
πŸ”‘

Accounts & API Keys

Free

Create an account, then issue an API key. Every key belongs to an account β€” there are no anonymous keys. The session is a myid_session cookie on .api.my.id, so one sign-in covers the whole site. A key is shown only once β€” store it safely.

POST /auth/register βœ“ No key needed Try it β†’

Create an account. Returns your first API key and starts a session.

REQUEST BODY
{ "name": "Nama Anda", "email": "anda@perusahaan.com", "password": "min-8-karakter" }
CURL
curl -X POST "https://v1.api.my.id/auth/register" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Nama Anda", "email": "anda@perusahaan.com", "password": "min-8-karakter" }'
EXAMPLE RESPONSE
{
  "status": "success",
  "code": 201,
  "message": "Account created. Store this API key safely β€” it is shown only once.",
  "data": {
    "user": { "id": 1, "name": "Nama Anda", "email": "anda@perusahaan.com" },
    "api_key": "myid_live_a1b2c3d4e5f6…",
    "key_hint": "myid_live_a1b2…",
    "monthly_quota": 5000,
    "session_token": "…",
    "expires_at": "2026-08-11T00:00:00Z"
  }
}
POST /auth/login βœ“ No key needed Try it β†’

Sign in. Sets the session cookie (and returns a session_token for non-browser clients).

REQUEST BODY
{ "email": "anda@perusahaan.com", "password": "…" }
CURL
curl -X POST "https://v1.api.my.id/auth/login" \
  -H "Content-Type: application/json" \
  -d '{ "email": "anda@perusahaan.com", "password": "…" }'
EXAMPLE RESPONSE
{
  "status": "success",
  "code": 200,
  "message": "Signed in.",
  "data": { "user": { "id": 1, "email": "anda@perusahaan.com" }, "expires_at": "…" }
}
GET /auth/me πŸ‘€ Login required Try it β†’

The signed-in account, with its keys and points balance.

CURL
curl "https://v1.api.my.id/auth/me" \
  -H "Authorization: Session $SESSION_TOKEN"
EXAMPLE RESPONSE
{
  "status": "success",
  "code": 200,
  "data": {
    "user": { "id": 1, "name": "Nama Anda", "email": "anda@perusahaan.com" },
    "keys": [{ "id": 7, "key_hint": "myid_live_a1b2…", "points": 0 }],
    "points": 0,
    "monthly_quota": 5000
  }
}
POST /auth/logout πŸ‘€ Login required Try it β†’

Sign out and destroy the session.

CURL
curl -X POST "https://v1.api.my.id/auth/logout" \
  -H "Authorization: Session $SESSION_TOKEN"
POST /keys/register πŸ‘€ Login required Try it β†’

Issue a new API key for the signed-in account. Requires a login session β€” max 10 active keys.

REQUEST BODY
{ "label": "Playground" }
CURL
curl -X POST "https://v1.api.my.id/keys/register" \
  -H "Authorization: Session $SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "label": "Playground" }'
EXAMPLE RESPONSE
{
  "status": "success",
  "code": 201,
  "message": "Store this key safely β€” it is shown only once.",
  "data": {
    "api_key": "myid_live_a1b2c3d4e5f6…",
    "key_hint": "myid_live_a1b2…",
    "label": "Playground",
    "monthly_quota": 5000
  }
}
POST /auth/password πŸ‘€ Login required Try it β†’

Change your password. Every other session is signed out.

REQUEST BODY
{ "current_password": "…", "new_password": "min-8-karakter" }
CURL
curl -X POST "https://v1.api.my.id/auth/password" \
  -H "Authorization: Session $SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "current_password": "…", "new_password": "min-8-karakter" }'
EXAMPLE RESPONSE
{ "status": "success", "code": 200, "message": "Password changed. Every other session has been signed out." }
POST /auth/profile πŸ‘€ Login required Try it β†’

Change your display name. Email is immutable β€” it identifies the account.

REQUEST BODY
{ "name": "Nama Baru" }
CURL
curl -X POST "https://v1.api.my.id/auth/profile" \
  -H "Authorization: Session $SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Nama Baru" }'
POST /auth/logout-all πŸ‘€ Login required Try it β†’

Sign out every other device. This session stays active.

CURL
curl -X POST "https://v1.api.my.id/auth/logout-all" \
  -H "Authorization: Session $SESSION_TOKEN"
DELETE /keys/{id} πŸ‘€ Login required Try it β†’

Revoke one of your account’s keys.

QUERY PARAMETERS
id int required Key id (from /auth/me).
CURL
curl -X DELETE "https://v1.api.my.id/keys/7" \
  -H "Authorization: Session $SESSION_TOKEN"
GET /keys/me πŸ”‘ API key required Try it β†’

Key info: this month’s usage, points balance, active subscriptions.

CURL
curl "https://v1.api.my.id/keys/me" \
  -H "Authorization: Bearer $API_KEY"
EXAMPLE RESPONSE
{
  "status": "success",
  "code": 200,
  "data": {
    "key_hint": "myid_live_a1b2…",
    "month": "2026-07",
    "quota": 5000,
    "used_this_month": 128,
    "remaining": 4872,
    "points": 50000,
    "active_subscriptions": [
      { "product_id": "wilayah-indonesia", "tier": "Pro", "monthly_quota": 25000, "expires_at": "2026-08-09T…" }
    ],
    "by_endpoint": [ { "endpoint": "wilayah/provinces", "hits": 40 } ]
  }
}
πŸ—ΊοΈ

Indonesia Regions

Subscription

Complete Indonesian administrative data: 34 provinces, 514 regencies, 7,215 districts, 80,534 villages (Kemendagri codes). All endpoints support pagination.

GET /wilayah/provinces πŸ”‘ API key required Try it β†’

All provinces.

QUERY PARAMETERS
page int optional Default 1.
per_page int optional 1–500. Default 100.
CURL
curl "https://v1.api.my.id/wilayah/provinces" \
  -H "Authorization: Bearer $API_KEY"
EXAMPLE RESPONSE
{
  "status": "success",
  "code": 200,
  "page": 1, "per_page": 100, "total": 34, "total_pages": 1, "count": 34,
  "data": [ { "code": "32", "name": "JAWA BARAT" } ]
}
GET /wilayah/regencies πŸ”‘ API key required Try it β†’

Regencies/cities within a province.

QUERY PARAMETERS
province string required Province code, e.g. 32.
CURL
curl "https://v1.api.my.id/wilayah/regencies?province=32" \
  -H "Authorization: Bearer $API_KEY"
GET /wilayah/districts πŸ”‘ API key required Try it β†’

Districts within a regency.

QUERY PARAMETERS
regency string required Regency code, e.g. 3204.
CURL
curl "https://v1.api.my.id/wilayah/districts?regency=3204" \
  -H "Authorization: Bearer $API_KEY"
GET /wilayah/villages πŸ”‘ API key required Try it β†’

Villages within a district.

QUERY PARAMETERS
district string required District code, e.g. 3204010.
CURL
curl "https://v1.api.my.id/wilayah/villages?district=3204010" \
  -H "Authorization: Bearer $API_KEY"
GET /wilayah/search πŸ”‘ API key required Try it β†’

Search region names across all levels at once.

QUERY PARAMETERS
q string required Minimum 3 characters.
limit int optional 1–100. Default 25.
CURL
curl "https://v1.api.my.id/wilayah/search?q=menteng" \
  -H "Authorization: Bearer $API_KEY"
EXAMPLE RESPONSE
{
  "status": "success", "code": 200, "query": "menteng", "count": 3,
  "data": [
    { "code": "3173020", "name": "MENTENG", "level": "district", "parent_code": "3173" },
    { "code": "3171090001", "name": "MENTENG DALAM", "level": "village", "parent_code": "3171090" }
  ]
}
🏫

Facility Data

Subscription

Schools (215,333 β€” Dapodik), universities (4,759 β€” PDDikti), and hospitals (3,116 β€” SIRS Kemenkes). All support pagination and filters.

GET /schools πŸ”‘ API key required Try it β†’

Search schools nationwide, including GPS coordinates.

QUERY PARAMETERS
q string optional Search by school name.
npsn string optional Look up by NPSN.
bentuk string optional SD, SMP, SMA, SMK, SLB…
status string optional N (public) or S (private).
province string optional Dapodik province code.
regency string optional Dapodik regency code.
CURL
curl "https://v1.api.my.id/schools?q=SMA Negeri 1&bentuk=SMA&status=N" \
  -H "Authorization: Bearer $API_KEY"
EXAMPLE RESPONSE
{
  "status": "success", "code": 200, "total": 749, "count": 1,
  "source": "Dapodik/Kemdikbud",
  "data": [
    {
      "npsn": "20106343", "name": "SMA NEGERI 1 CIAWIGEBANG", "bentuk": "SMA", "status": "N",
      "province": "Jawa Barat", "regency": "Kab. Kuningan", "district": "Ciawigebang",
      "address": "Jl. Siliwangi No. 1", "lat": -6.974, "lng": 108.5894
    }
  ]
}
GET /universities πŸ”‘ API key required Try it β†’

Higher-education institutions (universities, institutes, polytechnics, colleges, academies).

QUERY PARAMETERS
q string optional Search by campus name.
type string optional Universitas / Institut / Politeknik / Sekolah Tinggi / Akademi.
lldikti int optional LLDikti region 1–16.
CURL
curl "https://v1.api.my.id/universities?q=institut teknologi" \
  -H "Authorization: Bearer $API_KEY"
GET /hospitals πŸ”‘ API key required Try it β†’

Hospitals nationwide with region names.

QUERY PARAMETERS
q string optional Search by hospital name.
type string optional RSUD, RS Umum, RS Jiwa, RS Ibu dan Anak…
province string optional Kemendagri province code, e.g. 32.
regency string optional Regency code.
CURL
curl "https://v1.api.my.id/hospitals?type=RS Jiwa&province=32" \
  -H "Authorization: Bearer $API_KEY"
🌐

Rates, Geo & IP

Subscription

Real-time currency rates, reverse geocoding, and IP geolocation.

GET /rates πŸ”‘ API key required Try it β†’

Rates for 160+ currencies, with optional conversion.

QUERY PARAMETERS
base string optional 3-letter code. Default USD.
to string optional Filter currencies, comma-separated.
amount number optional Convert an amount (needs a single ?to).
CURL
curl "https://v1.api.my.id/rates?base=USD&to=IDR&amount=100" \
  -H "Authorization: Bearer $API_KEY"
EXAMPLE RESPONSE
{
  "status": "success", "code": 200, "count": 1,
  "data": {
    "base": "USD",
    "updated_at": "Thu, 09 Jul 2026 00:02:32 +0000",
    "rates": { "IDR": 18058.21 },
    "converted": 1805821.08
  }
}
GET /geocode/reverse πŸ”‘ API key required Try it β†’

Coordinates β†’ nearest city (city-level accuracy).

QUERY PARAMETERS
lat number required Latitude (Indonesian territory).
lng number required Longitude.
CURL
curl "https://v1.api.my.id/geocode/reverse?lat=-6.95&lng=107.60" \
  -H "Authorization: Bearer $API_KEY"
GET /ip/{ip} πŸ”‘ API key required Try it β†’

Locate an IP address. Use /ip/me for the caller’s IP.

CURL
curl "https://v1.api.my.id/ip/8.8.8.8" \
  -H "Authorization: Bearer $API_KEY"
EXAMPLE RESPONSE
{
  "status": "success", "code": 200,
  "data": {
    "ip": "8.8.8.8", "country": "United States", "city": "Mountain View",
    "lat": 37.386, "lng": -122.084, "timezone": "America/Los_Angeles",
    "asn": 15169, "isp": "Google LLC"
  }
}
πŸ“¦

Shipping Cost

Subscription

Courier rates for any route in Indonesia. You pass the same wilayah codes you already use in the Wilayah API β€” no provider-specific ids to learn. Weight is rounded up per kilogram, exactly the way couriers bill.

POST /shipping/cost πŸ”‘ API key required Try it β†’

Rates for every courier service on a route.

QUERY PARAMETERS
origin string required Origin district code (7 digits) β€” from GET /wilayah/districts.
destination string required Destination district code.
weight int required Weight in grams. Rounded up per kg.
courier string optional Courier code(s), comma-separated. Default: jne,jnt,sicepat.
REQUEST BODY
{ "origin": "3173020", "destination": "5103020", "weight": 1240, "courier": "jne,jnt" }
CURL
curl -X POST "https://v1.api.my.id/shipping/cost" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "origin": "3173020", "destination": "5103020", "weight": 1240, "courier": "jne,jnt" }'
EXAMPLE RESPONSE
{
  "status": "success",
  "code": 200,
  "origin": { "code": "3173020", "name": "Menteng" },
  "destination": { "code": "5103020", "name": "Kuta" },
  "weight_grams": 1240,
  "billed_weight": { "kg": 2, "note": "couriers bill per started kilogram, so the weight is rounded up" },
  "data": [
    { "courier": "jne", "service": "REG", "description": "Reguler", "cost": 19000, "etd": "2 day" },
    { "courier": "jne", "service": "YES", "description": "Express", "cost": 38000, "etd": "1 day" }
  ]
}
GET /shipping/couriers πŸ”‘ API key required Try it β†’

The courier codes the cost endpoint accepts.

CURL
curl "https://v1.api.my.id/shipping/couriers" \
  -H "Authorization: Bearer $API_KEY"
EXAMPLE RESPONSE
{ "status": "success", "code": 200, "count": 9, "data": ["jne","pos","tiki","sicepat","jnt","ninja","anteraja","wahana","lion"] }
πŸ€–

AI: OCR, CV & Articles

Pay Per Use

AI-powered endpoints. Charged in points per successful hit β€” points are only deducted on success, and auto-refunded if the upstream call fails.

POST /ocr/ktp πŸ”‘ API key required 150 points/hit Try it β†’

Extract KTP (ID card) data into structured JSON.

REQUEST BODY
// multipart: field "image"  β€”  atau JSON:
{ "image": "<base64>", "media_type": "image/jpeg" }
CURL
curl -X POST "https://v1.api.my.id/ocr/ktp" \
  -H "Authorization: Bearer $API_KEY"
EXAMPLE RESPONSE
{
  "status": "success", "code": 200,
  "model": "claude-opus-4-8", "document": "ktp", "points_charged": 150,
  "data": {
    "nik": "3204xxxxxxxxxxxx", "nama": "BUDI SANTOSO",
    "tempat_lahir": "BANDUNG", "tanggal_lahir": "17-08-1990",
    "jenis_kelamin": "LAKI-LAKI", "alamat": "JL. MERDEKA NO. 1",
    "kecamatan": "COBLONG", "agama": "ISLAM",
    "confidence": "high"
  }
}
POST /ocr/sim πŸ”‘ API key required 300 points/hit Try it β†’

Extract driver-license data (new & 6-line legacy formats).

REQUEST BODY
// multipart: field "image"  β€”  atau JSON base64
CURL
curl -X POST "https://v1.api.my.id/ocr/sim" \
  -H "Authorization: Bearer $API_KEY"
POST /cv/extract πŸ”‘ API key required 300 points/hit Try it β†’

Parse a resume (PDF/image/text) into structured JSON.

REQUEST BODY
// multipart: field "file" (PDF atau gambar)
// atau JSON: { "text": "<isi CV>" }
CURL
curl -X POST "https://v1.api.my.id/cv/extract" \
  -H "Authorization: Bearer $API_KEY"
EXAMPLE RESPONSE
{
  "status": "success", "code": 200, "points_charged": 300,
  "data": {
    "name": "Siti Rahma", "email": "siti@example.com", "phone": "+62812…",
    "skills": ["Go", "PostgreSQL", "Docker"],
    "experience": [ { "company": "PT Maju", "title": "Backend Engineer", "start": "2022", "end": "2026", "description": "…" } ],
    "education": [ { "institution": "Institut Teknologi Bandung", "degree": "S1 Informatika", "year": "2021" } ],
    "certifications": [], "languages": ["Indonesia", "English"]
  }
}
POST /articles/generate πŸ”‘ API key required 1300 points/hit Try it β†’

Generate an SEO-friendly article in Markdown.

REQUEST BODY
{
  "topic": "Cara integrasi API cek ongkir",
  "language": "id",             // id | en
  "tone": "informatif",         // opsional
  "keywords": ["ongkir", "api"],// opsional, maks 10
  "words": 800                  // opsional, 300–2000
}
CURL
curl -X POST "https://v1.api.my.id/articles/generate" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "topic": "Cara integrasi API cek ongkir", "language": "id",             ,         , "api"],, maks 10 "words": 800                  , 300–2000 }'
EXAMPLE RESPONSE
{
  "status": "success", "code": 200, "points_charged": 1300,
  "data": {
    "article_markdown": "# Cara Integrasi API Cek Ongkir\n\n## Pendahuluan\n…",
    "meta_description": "Panduan lengkap integrasi API cek ongkir…",
    "word_count": 812
  }
}
POST /image/remove-bg πŸ”‘ API key required 300 points/hit Try it β†’

Remove an image background β†’ transparent PNG.

QUERY PARAMETERS
model string optional u2net (default), u2netp, silueta, isnet-general-use.
format string optional binary β†’ raw PNG. Default JSON base64.
REQUEST BODY
// multipart: field "image" (maks 10 MB)
CURL
curl -X POST "https://v1.api.my.id/image/remove-bg?model=u2net&format=binary" \
  -H "Authorization: Bearer $API_KEY"
πŸ’³

Billing & Points

Subscription

Top up points and buy subscriptions via Midtrans. 1 IDR = 1 point. Points power the AI endpoints above.

GET /billing/config βœ“ No key needed Try it β†’

Payment gateway status (used by the frontend).

CURL
curl "https://v1.api.my.id/billing/config"
POST /billing/topup πŸ”‘ API key required Try it β†’

Create a points top-up transaction. Returns a snap_token for the payment popup.

REQUEST BODY
{ "amount": 100000 }   // IDR, 10.000 – 10.000.000
CURL
curl -X POST "https://v1.api.my.id/billing/topup" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "amount": 100000 }   , 10.000 – 10.000.000'
EXAMPLE RESPONSE
{
  "status": "success", "code": 200,
  "data": {
    "order_id": "TOPUP-12-1752…",
    "snap_token": "66e4fa55-fdac-4ef9-91b5-…",
    "redirect_url": "https://app.sandbox.midtrans.com/snap/v2/vtweb/…",
    "amount": 100000, "points": 100000
  }
}
POST /billing/subscribe πŸ”‘ API key required Try it β†’

Buy a product subscription (30 days).

REQUEST BODY
{ "product_id": "wilayah-indonesia", "tier": "Pro" }
CURL
curl -X POST "https://v1.api.my.id/billing/subscribe" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "product_id": "wilayah-indonesia", "tier": "Pro" }'
GET /billing/orders πŸ”‘ API key required Try it β†’

Your order history.

CURL
curl "https://v1.api.my.id/billing/orders" \
  -H "Authorization: Bearer $API_KEY"