Quick start
Two endpoints are free and need no key at all β try one right now, then create an account for the rest.
Call a free endpoint
Holidays and prayer times work without any key.
Get an API key
Create a free account β your first key is issued instantly. 5,000 free hits/month per account.
Send it as a Bearer token
Authorization: Bearer <key> on every protected call.
# 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"
# 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"}'
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β¦
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β¦" }
| Code | Meaning | What to do |
|---|---|---|
| 200 | Success | Read the data field. |
| 201 | Key created | Store the api_key β shown once. |
| 400 | Bad request | A required parameter is missing or malformed. |
| 401 | No/invalid key | Check the Authorization header. |
| 402 | Not enough points | Top up: POST /billing/topup. The error tells you needed vs balance. |
| 404 | Not found | Unknown endpoint, city, or resource. |
| 422 | Unprocessable | e.g. coordinates outside Indonesia, private IP. |
| 429 | Quota exceeded | 5,000 free hits/month used. Subscribe for more. |
| 501 | Not configured / reserved | The product needs an external provider β see the message. |
| 502 | Upstream failed | Retry. 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.
| Endpoint | Cost |
|---|---|
| POST /ocr/ktp | 150 poin |
| POST /ocr/sim | 300 poin |
| POST /cv/extract | 300 poin |
| POST /image/remove-bg | 300 poin |
| POST /articles/generate | 1.300 poin |
Endpoint reference
National Holidays
FreeIndonesian national holidays and joint-leave days per the official SKB decree. Free, no API key needed.
All holidays for a year (2025 & 2026).
| year | int | optional | Year. Defaults to the current year. |
curl "https://v1.api.my.id/holidays?year=2026"
{
"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
}
]
}
Upcoming holidays from today.
| limit | int | optional | 1β20. Default 5. |
curl "https://v1.api.my.id/holidays/upcoming?limit=3"
Check whether a given date is a holiday.
| date | string | required | Format YYYY-MM-DD. |
curl "https://v1.api.my.id/holidays/check?date=2026-08-17"
{
"status": "success",
"code": 200,
"data": {
"date": "2026-08-17",
"is_holiday": true,
"holidays": [ { "name": "Hari Kemerdekaan Republik Indonesia", "type": "national", β¦ } ]
}
}
Prayer Times
FreeDaily prayer times computed with the standard solar-position algorithm (Kemenag angles: Fajr β20Β°, Isha β18Β°, +2 min ihtiyat). Free, no API key needed.
Prayer schedule for a city and date.
| city | string | required | City slug, e.g. jakarta. See /sholat/cities. |
| date | string | optional | YYYY-MM-DD. Defaults to today. |
curl "https://v1.api.my.id/sholat?city=jakarta&date=2026-07-09"
{
"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"
}
}
}
The 54 supported cities (WIB/WITA/WIT).
curl "https://v1.api.my.id/sholat/cities"
Accounts & API Keys
FreeCreate 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.
Create an account. Returns your first API key and starts a session.
{ "name": "Nama Anda", "email": "anda@perusahaan.com", "password": "min-8-karakter" }
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" }'
{
"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"
}
}
Sign in. Sets the session cookie (and returns a session_token for non-browser clients).
{ "email": "anda@perusahaan.com", "password": "β¦" }
curl -X POST "https://v1.api.my.id/auth/login" \
-H "Content-Type: application/json" \
-d '{ "email": "anda@perusahaan.com", "password": "β¦" }'
{
"status": "success",
"code": 200,
"message": "Signed in.",
"data": { "user": { "id": 1, "email": "anda@perusahaan.com" }, "expires_at": "β¦" }
}
The signed-in account, with its keys and points balance.
curl "https://v1.api.my.id/auth/me" \ -H "Authorization: Session $SESSION_TOKEN"
{
"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
}
}
Sign out and destroy the session.
curl -X POST "https://v1.api.my.id/auth/logout" \ -H "Authorization: Session $SESSION_TOKEN"
Issue a new API key for the signed-in account. Requires a login session β max 10 active keys.
{ "label": "Playground" }
curl -X POST "https://v1.api.my.id/keys/register" \
-H "Authorization: Session $SESSION_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "label": "Playground" }'
{
"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
}
}
Change your password. Every other session is signed out.
{ "current_password": "β¦", "new_password": "min-8-karakter" }
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" }'
{ "status": "success", "code": 200, "message": "Password changed. Every other session has been signed out." }
Change your display name. Email is immutable β it identifies the account.
{ "name": "Nama Baru" }
curl -X POST "https://v1.api.my.id/auth/profile" \
-H "Authorization: Session $SESSION_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "name": "Nama Baru" }'
Sign out every other device. This session stays active.
curl -X POST "https://v1.api.my.id/auth/logout-all" \ -H "Authorization: Session $SESSION_TOKEN"
Revoke one of your accountβs keys.
| id | int | required | Key id (from /auth/me). |
curl -X DELETE "https://v1.api.my.id/keys/7" \ -H "Authorization: Session $SESSION_TOKEN"
Key info: this monthβs usage, points balance, active subscriptions.
curl "https://v1.api.my.id/keys/me" \ -H "Authorization: Bearer $API_KEY"
{
"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
SubscriptionComplete Indonesian administrative data: 34 provinces, 514 regencies, 7,215 districts, 80,534 villages (Kemendagri codes). All endpoints support pagination.
All provinces.
| page | int | optional | Default 1. |
| per_page | int | optional | 1β500. Default 100. |
curl "https://v1.api.my.id/wilayah/provinces" \ -H "Authorization: Bearer $API_KEY"
{
"status": "success",
"code": 200,
"page": 1, "per_page": 100, "total": 34, "total_pages": 1, "count": 34,
"data": [ { "code": "32", "name": "JAWA BARAT" } ]
}
Regencies/cities within a province.
| province | string | required | Province code, e.g. 32. |
curl "https://v1.api.my.id/wilayah/regencies?province=32" \ -H "Authorization: Bearer $API_KEY"
Districts within a regency.
| regency | string | required | Regency code, e.g. 3204. |
curl "https://v1.api.my.id/wilayah/districts?regency=3204" \ -H "Authorization: Bearer $API_KEY"
Villages within a district.
| district | string | required | District code, e.g. 3204010. |
curl "https://v1.api.my.id/wilayah/villages?district=3204010" \ -H "Authorization: Bearer $API_KEY"
Search region names across all levels at once.
| q | string | required | Minimum 3 characters. |
| limit | int | optional | 1β100. Default 25. |
curl "https://v1.api.my.id/wilayah/search?q=menteng" \ -H "Authorization: Bearer $API_KEY"
{
"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
SubscriptionSchools (215,333 β Dapodik), universities (4,759 β PDDikti), and hospitals (3,116 β SIRS Kemenkes). All support pagination and filters.
Search schools nationwide, including GPS coordinates.
| 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 "https://v1.api.my.id/schools?q=SMA Negeri 1&bentuk=SMA&status=N" \ -H "Authorization: Bearer $API_KEY"
{
"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
}
]
}
Higher-education institutions (universities, institutes, polytechnics, colleges, academies).
| q | string | optional | Search by campus name. |
| type | string | optional | Universitas / Institut / Politeknik / Sekolah Tinggi / Akademi. |
| lldikti | int | optional | LLDikti region 1β16. |
curl "https://v1.api.my.id/universities?q=institut teknologi" \ -H "Authorization: Bearer $API_KEY"
Hospitals nationwide with region names.
| 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 "https://v1.api.my.id/hospitals?type=RS Jiwa&province=32" \ -H "Authorization: Bearer $API_KEY"
Rates, Geo & IP
SubscriptionReal-time currency rates, reverse geocoding, and IP geolocation.
Rates for 160+ currencies, with optional conversion.
| 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 "https://v1.api.my.id/rates?base=USD&to=IDR&amount=100" \ -H "Authorization: Bearer $API_KEY"
{
"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
}
}
Coordinates β nearest city (city-level accuracy).
| lat | number | required | Latitude (Indonesian territory). |
| lng | number | required | Longitude. |
curl "https://v1.api.my.id/geocode/reverse?lat=-6.95&lng=107.60" \ -H "Authorization: Bearer $API_KEY"
Locate an IP address. Use /ip/me for the callerβs IP.
curl "https://v1.api.my.id/ip/8.8.8.8" \ -H "Authorization: Bearer $API_KEY"
{
"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
SubscriptionCourier 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.
Rates for every courier service on a route.
| 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. |
{ "origin": "3173020", "destination": "5103020", "weight": 1240, "courier": "jne,jnt" }
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" }'
{
"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" }
]
}
The courier codes the cost endpoint accepts.
curl "https://v1.api.my.id/shipping/couriers" \ -H "Authorization: Bearer $API_KEY"
{ "status": "success", "code": 200, "count": 9, "data": ["jne","pos","tiki","sicepat","jnt","ninja","anteraja","wahana","lion"] }
AI: OCR, CV & Articles
Pay Per UseAI-powered endpoints. Charged in points per successful hit β points are only deducted on success, and auto-refunded if the upstream call fails.
Extract KTP (ID card) data into structured JSON.
// multipart: field "image" β atau JSON:
{ "image": "<base64>", "media_type": "image/jpeg" }
curl -X POST "https://v1.api.my.id/ocr/ktp" \ -H "Authorization: Bearer $API_KEY"
{
"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"
}
}
Extract driver-license data (new & 6-line legacy formats).
// multipart: field "image" β atau JSON base64
curl -X POST "https://v1.api.my.id/ocr/sim" \ -H "Authorization: Bearer $API_KEY"
Parse a resume (PDF/image/text) into structured JSON.
// multipart: field "file" (PDF atau gambar)
// atau JSON: { "text": "<isi CV>" }
curl -X POST "https://v1.api.my.id/cv/extract" \ -H "Authorization: Bearer $API_KEY"
{
"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"]
}
}
Generate an SEO-friendly article in Markdown.
{
"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 -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 }'
{
"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
}
}
Remove an image background β transparent PNG.
| model | string | optional | u2net (default), u2netp, silueta, isnet-general-use. |
| format | string | optional | binary β raw PNG. Default JSON base64. |
// multipart: field "image" (maks 10 MB)
curl -X POST "https://v1.api.my.id/image/remove-bg?model=u2net&format=binary" \ -H "Authorization: Bearer $API_KEY"
Billing & Points
SubscriptionTop up points and buy subscriptions via Midtrans. 1 IDR = 1 point. Points power the AI endpoints above.
Payment gateway status (used by the frontend).
curl "https://v1.api.my.id/billing/config"
Create a points top-up transaction. Returns a snap_token for the payment popup.
{ "amount": 100000 } // IDR, 10.000 β 10.000.000
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'
{
"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
}
}
Buy a product subscription (30 days).
{ "product_id": "wilayah-indonesia", "tier": "Pro" }
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" }'
Your order history.
curl "https://v1.api.my.id/billing/orders" \ -H "Authorization: Bearer $API_KEY"