{"openapi":"3.1.0","info":{"title":"MANJI Gateway API","version":"0.2.0","description":"Merchant-owned QRIS monitoring. Payment detected tidak sama dengan Payment verified. Roles PENDING/USER tidak mengakses merchant. Provider resmi dinonaktifkan sampai disetujui."},"servers":[{"url":"https://api.manjifood.biz.id","description":"Origin konfigurasi; ketersediaan produksi harus diverifikasi setelah deployment"}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","description":"JWT pengguna atau credential mg_sbx_/mg_live_/md_. Kunci integrasi hanya pada server; Android menukar enrollment credential untuk token perangkat."}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"object","required":["code","message","request_id"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"request_id":{"type":"string","format":"uuid"}}}}}}},"paths":{"/api/v1/app/download":{"get":{"summary":"Unduh APK MANJI Gateway bertanda tangan","description":"307 ke /aplikasi/manji-gateway-release.apk pada origin yang sama. APK harus tersedia bersama laporan verifikasi signing yang cocok. Arsip unsigned tetap tersedia pada endpoint terpisah; katalog dan updater tidak diubah.","operationId":"get__api_v1_app_download","tags":["Aplikasi Android"],"security":[],"parameters":[],"responses":{"307":{"description":"Same-origin signed APK URL","headers":{"Location":{"schema":{"type":"string","const":"/aplikasi/manji-gateway-release.apk"}}}}}}},"/aplikasi/manji-gateway-release.apk":{"get":{"summary":"Berkas APK existing setelah signing","description":"APK yang ditandatangani tanpa rebuild. Laporan verifikasi dan SHA-256 berkas diperiksa sebelum pengiriman. 404 jika belum tersedia; 503 jika bukti verifikasi atau checksum gagal. Mendukung HEAD. Header X-Checksum-SHA256 dan X-APK-Certificate-SHA256 berisi checksum berkas dan fingerprint sertifikat.","operationId":"get__aplikasi_manji_gateway_release_apk","tags":["Aplikasi Android"],"security":[],"parameters":[],"responses":{"200":{"description":"Existing signed APK with a matching verification report and checksum","headers":{"X-Checksum-SHA256":{"schema":{"type":"string"}},"X-APK-Certificate-SHA256":{"schema":{"type":"string"}}},"content":{"application/vnd.android.package-archive":{"schema":{"type":"string","format":"binary"}}}},"404":{"description":"Signed APK or verification report not present"},"503":{"description":"Verification report or APK integrity check failed"}}}},"/api/v1/app/unsigned/download":{"get":{"summary":"Unduh arsip APK unsigned untuk pengembangan","description":"Berkas yang ada di web/aplikasi, disajikan tanpa modifikasi. Belum ditandatangani, tidak dapat dipasang langsung, bukan rilis produksi dan tidak masuk katalog updater. Header X-APK-Status: unsigned-not-installable. Tidak memerlukan Storage eksternal.","operationId":"get__api_v1_app_unsigned_download","tags":["Aplikasi Android"],"security":[],"parameters":[],"responses":{"200":{"description":"Existing unsigned development APK; not directly installable","headers":{"X-APK-Status":{"schema":{"type":"string","const":"unsigned-not-installable"}},"X-Checksum-SHA256":{"schema":{"type":"string"}}},"content":{"application/vnd.android.package-archive":{"schema":{"type":"string","format":"binary"}}}},"404":{"description":"APK not present in deployment"},"503":{"description":"APK cannot be read"}}}},"/v1/app/version":{"get":{"summary":"Versi APK resmi, kanal dan riwayat","description":"Publik. Default stable, beta opsional. available=false jika katalog kosong; 503 jika distribusi belum dikonfigurasi. Android membandingkan version_code lokal dan menolak downgrade. Riwayat maksimal 30 rilis aktif per kanal; object key privat tidak dikirim.","operationId":"get__v1_app_version","tags":["Aplikasi Android"],"security":[],"parameters":[{"in":"query","name":"channel","required":false,"schema":{"type":"string","enum":["stable","beta"],"default":"stable"}},{"in":"query","name":"history_limit","required":false,"schema":{"type":"integer","minimum":0,"maximum":30,"default":30},"description":"Android uses 0 for a lightweight update check."}],"responses":{"200":{"description":"Current approved app distribution catalog","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"available":{"type":"boolean"},"channel":{"type":"string","enum":["stable","beta"]},"distribution_environment":{"type":"string","enum":["production","test"]},"release":{"anyOf":[{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid"},"application_id":{"const":"id.biz.manjifood.gateway","type":"string"},"channel":{"type":"string","enum":["stable","beta"]},"version_code":{"type":"integer","minimum":1,"maximum":2100000000},"version_name":{"type":"string","pattern":"^[0-9]+\\.[0-9]+\\.[0-9]+(?:-[A-Za-z0-9.-]+)?$","maxLength":60},"released_at":{"type":"string","format":"date-time"},"min_sdk":{"type":"integer","minimum":26,"maximum":100},"target_sdk":{"type":"integer","minimum":26,"maximum":100},"size_bytes":{"type":"integer","minimum":1,"maximum":83886080},"sha256":{"type":"string","pattern":"^[a-f0-9]{64}$"},"signer_sha256":{"type":"string","pattern":"^[a-f0-9]{64}$"},"notes":{"type":"array","items":{"type":"string","minLength":1,"maxLength":1000},"minItems":1,"maxItems":20},"download_path":{"type":"string"},"screenshots":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"url":{"type":"string"},"caption":{"type":"string"},"width":{"type":"integer"},"height":{"type":"integer"}},"required":["url","caption","width","height"]}}},"required":["id","application_id","channel","version_code","version_name","released_at","min_sdk","target_sdk","size_bytes","sha256","signer_sha256","notes","download_path","screenshots"]},{"type":"null"}]},"history":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid"},"application_id":{"const":"id.biz.manjifood.gateway","type":"string"},"channel":{"type":"string","enum":["stable","beta"]},"version_code":{"type":"integer","minimum":1,"maximum":2100000000},"version_name":{"type":"string","pattern":"^[0-9]+\\.[0-9]+\\.[0-9]+(?:-[A-Za-z0-9.-]+)?$","maxLength":60},"released_at":{"type":"string","format":"date-time"},"min_sdk":{"type":"integer","minimum":26,"maximum":100},"target_sdk":{"type":"integer","minimum":26,"maximum":100},"size_bytes":{"type":"integer","minimum":1,"maximum":83886080},"sha256":{"type":"string","pattern":"^[a-f0-9]{64}$"},"signer_sha256":{"type":"string","pattern":"^[a-f0-9]{64}$"},"notes":{"type":"array","items":{"type":"string","minLength":1,"maxLength":1000},"minItems":1,"maxItems":20},"download_path":{"type":"string"},"screenshots":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"url":{"type":"string"},"caption":{"type":"string"},"width":{"type":"integer"},"height":{"type":"integer"}},"required":["url","caption","width","height"]}}},"required":["id","application_id","channel","version_code","version_name","released_at","min_sdk","target_sdk","size_bytes","sha256","signer_sha256","notes","download_path","screenshots"]}}},"required":["available","channel","distribution_environment","release","history"]}}}},"503":{"description":"Distribution not configured or metadata invalid"}}}},"/v1/app/latest/download":{"get":{"summary":"Mulai unduh APK resmi terbaru","description":"307 ke tiket backend 120 detik, terikat ID dan hash APK. Tidak ada debug/unsigned di produksi. 503 APP_RELEASE_UNAVAILABLE jika belum ada rilis. Ikuti Location pada origin HTTPS yang sama; final response application/vnd.android.package-archive dan X-Checksum-SHA256.","operationId":"get__v1_app_latest_download","tags":["Aplikasi Android"],"security":[],"parameters":[{"in":"query","name":"channel","required":false,"schema":{"type":"string","enum":["stable","beta"],"default":"stable"}}],"responses":{"307":{"description":"Temporary backend download ticket","headers":{"Location":{"schema":{"type":"string"}}}},"401":{"description":"Invalid/expired ticket"},"404":{"description":"Release unavailable/revoked"},"503":{"description":"Release/signing/storage not ready"}}}},"/v1/app/releases/{id}/download":{"get":{"summary":"Unduh versi tertentu dari riwayat","description":"307 tiket backend sementara; rilis yang ditarik ditolak. Signature, identitas paket dan kode versi tetap diperiksa Android.","operationId":"get__v1_app_releases__id__download","tags":["Aplikasi Android"],"security":[],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"307":{"description":"Temporary backend download ticket","headers":{"Location":{"schema":{"type":"string"}}}},"401":{"description":"Invalid/expired ticket"},"404":{"description":"Release unavailable/revoked"},"503":{"description":"Release/signing/storage not ready"}}}},"/v1/app/releases/{id}/file":{"get":{"summary":"Berkas APK terverifikasi melalui tiket","description":"Tiket wajib dari backend. 200 APK, 206 untuk Range tunggal bytes=start-end, 416 range tidak valid; 401 tiket palsu/kedaluwarsa, 404 rilis ditarik, 503 hash/storage gagal. Revokasi dan SHA-256 diperiksa sebelum byte disajikan.","operationId":"get__v1_app_releases__id__file","tags":["Aplikasi Android"],"security":[],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"}},{"in":"query","name":"ticket","required":true,"schema":{"type":"string","maxLength":1024}},{"in":"header","name":"Range","required":false,"schema":{"type":"string"},"example":"bytes=0-1023"}],"responses":{"200":{"description":"Integrity-checked private artifact","content":{"application/vnd.android.package-archive":{"schema":{"type":"string","format":"binary"}}}},"206":{"description":"Single byte range (APK only)"},"401":{"description":"Invalid/expired download ticket"},"404":{"description":"Release unavailable/revoked"},"416":{"description":"Invalid byte range"},"503":{"description":"Artifact unavailable or integrity check failed"}}}},"/v1/app/releases/{id}/screenshots/{index}":{"get":{"summary":"Cuplikan layar asli untuk rilis","description":"Gambar dari private storage yang lolos checksum; indeks 0–7. Tidak ada preview hasil rekayasa yang diklaim sebagai screenshot.","operationId":"get__v1_app_releases__id__screenshots__index_","tags":["Aplikasi Android"],"security":[],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"}},{"in":"path","name":"index","required":true,"schema":{"type":"integer","minimum":0,"maximum":7}}],"responses":{"200":{"description":"Integrity-checked private artifact","content":{"image/png":{"schema":{"type":"string","format":"binary"}}}},"206":{"description":"Single byte range (APK only)"},"401":{"description":"Invalid/expired download ticket"},"404":{"description":"Release unavailable/revoked"},"416":{"description":"Invalid byte range"},"503":{"description":"Artifact unavailable or integrity check failed"}}}},"/health":{"get":{"summary":"Kesehatan dan lingkungan backend","description":"","operationId":"get__health","tags":["Operasional"],"security":[],"parameters":[],"responses":{"200":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/auth/register":{"post":{"summary":"Daftar akun PENDING","description":"Role dari klien ditolak. Verifikasi email dan peninjauan admin diperlukan; tidak ada hak merchant/admin otomatis.","operationId":"post__v1_auth_register","tags":["Autentikasi"],"security":[],"parameters":[],"responses":{"202":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"email":{"type":"string","format":"email","maxLength":254},"password":{"type":"string","minLength":12,"maxLength":128},"display_name":{"type":"string","minLength":2,"maxLength":100}},"required":["email","password","display_name"]}}}}}},"/v1/auth/login":{"post":{"summary":"Login email/password","description":"","operationId":"post__v1_auth_login","tags":["Autentikasi"],"security":[],"parameters":[],"responses":{"200":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"email":{"type":"string","format":"email","maxLength":254},"password":{"type":"string","minLength":1,"maxLength":256},"device_name":{"type":"string","minLength":1,"maxLength":80}},"required":["password"]}}}}}},"/v1/auth/verify":{"post":{"summary":"Verifikasi tautan email/pemulihan","description":"","operationId":"post__v1_auth_verify","tags":["Autentikasi"],"security":[],"parameters":[],"responses":{"200":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"token_hash":{"type":"string","minLength":16,"maxLength":512},"type":{"type":"string","enum":["email","recovery"]}},"required":["token_hash","type"]}}}}}},"/v1/auth/refresh":{"post":{"summary":"Perbarui sesi pengguna","description":"Browser memakai cookie HttpOnly. Android mengirim refresh_token dari penyimpanan terenkripsi.","operationId":"post__v1_auth_refresh","tags":["Autentikasi"],"security":[],"parameters":[],"responses":{"200":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"refresh_token":{"type":"string"}},"required":[]}}}}}},"/v1/auth/reset-password":{"post":{"summary":"Minta pemulihan password","description":"","operationId":"post__v1_auth_reset_password","tags":["Autentikasi"],"security":[],"parameters":[],"responses":{"202":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"email":{"type":"string","format":"email"}},"required":["email"]}}}}}},"/v1/auth/resend-verification":{"post":{"summary":"Kirim ulang verifikasi","description":"","operationId":"post__v1_auth_resend_verification","tags":["Autentikasi"],"security":[],"parameters":[],"responses":{"202":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"email":{"type":"string","format":"email"}},"required":["email"]}}}}}},"/v1/auth/me":{"get":{"summary":"Profil, role, pengajuan dan membership","description":"","operationId":"get__v1_auth_me","tags":["Autentikasi"],"security":[{"bearer":[]}],"parameters":[],"responses":{"200":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/auth/logout":{"post":{"summary":"Logout aman dan cabut sesi","description":"","operationId":"post__v1_auth_logout","tags":["Autentikasi"],"security":[{"bearer":[]}],"parameters":[],"responses":{"200":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{},"required":[]}}}}}},"/v1/auth/password":{"post":{"summary":"Ubah password dan cabut sesi lain","description":"","operationId":"post__v1_auth_password","tags":["Autentikasi"],"security":[{"bearer":[]}],"parameters":[],"responses":{"200":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"password":{"type":"string","minLength":12,"maxLength":128}},"required":["password"]}}}}}},"/v1/auth/sessions":{"get":{"summary":"Daftar sesi akun","description":"","operationId":"get__v1_auth_sessions","tags":["Autentikasi"],"security":[{"bearer":[]}],"parameters":[],"responses":{"200":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/auth/sessions/{id}":{"delete":{"summary":"Cabut sesi akun","description":"","operationId":"delete__v1_auth_sessions__id_","tags":["Autentikasi"],"security":[{"bearer":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"}},{"in":"header","name":"Idempotency-Key","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}],"responses":{"200":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/merchant-applications":{"post":{"summary":"Ajukan akses merchant","description":"","operationId":"post__v1_merchant_applications","tags":["Akun"],"security":[{"bearer":[]}],"parameters":[{"in":"header","name":"Idempotency-Key","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}],"responses":{"201":{"description":"Created"},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"business_name":{"type":"string","minLength":2,"maxLength":120},"business_description":{"type":"string","minLength":10,"maxLength":1000},"phone":{"type":"string","pattern":"^\\+?[0-9]{8,16}$"}},"required":["business_name","business_description","phone"]}}}}}},"/v1/auth/device/enroll":{"post":{"summary":"Mulai enrollment perangkat","description":"Sesi MERCHANT atau key Layer A ENROLLMENT. Allowlist harus merupakan sumber yang disetujui admin; tantangan berlaku 5 menit.","operationId":"post__v1_auth_device_enroll","tags":["Perangkat"],"security":[{"bearer":[]}],"parameters":[{"in":"header","name":"Idempotency-Key","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}],"responses":{"200":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":80},"allowed_packages":{"type":"array","items":{"type":"string","minLength":3,"maxLength":180,"pattern":"^[A-Za-z][\\w]*(?:\\.[A-Za-z][\\w]*)+$"},"maxItems":5},"consent":{"const":true,"type":"boolean"},"empirically_verified":{"const":true,"type":"boolean"}},"required":["name","allowed_packages","consent","empirically_verified"]}}}}}},"/v1/auth/device/redeem":{"post":{"summary":"Tukar tantangan dengan token perangkat","description":"Identitas pengaju yang sama. Token perangkat berlaku 15 menit; credential enrollment tidak disimpan permanen di Android.","operationId":"post__v1_auth_device_redeem","tags":["Perangkat"],"security":[{"bearer":[]}],"parameters":[{"in":"header","name":"Idempotency-Key","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}],"responses":{"200":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"challenge_id":{"type":"string","format":"uuid"},"challenge":{"type":"string"}},"required":["challenge_id","challenge"]}}}}}},"/v1/devices/events":{"post":{"summary":"Kirim sinyal minimal UNTRUSTED","description":"Hanya token perangkatnya sendiri. Kandidat nominal/waktu tidak pernah menetapkan PAID atau mengirim payment.verified.","operationId":"post__v1_devices_events","tags":["Perangkat"],"security":[{"bearer":[]}],"parameters":[{"in":"header","name":"Idempotency-Key","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}],"responses":{"200":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"signal_id":{"type":"string","format":"uuid"},"device_id":{"type":"string","format":"uuid"},"source_package":{"type":"string","minLength":3,"maxLength":180,"pattern":"^[A-Za-z][\\w]*(?:\\.[A-Za-z][\\w]*)+$"},"amount_idr":{"anyOf":[{"type":"integer","minimum":1,"maximum":10000000},{"type":"null"}]},"posted_at":{"type":"string","format":"date-time"},"dedup_hash":{"type":"string","pattern":"^[a-f0-9]{64}$"},"source_type":{"const":"ANDROID_NOTIFICATION","type":"string"}},"required":["signal_id","device_id","source_package","amount_idr","posted_at","dedup_hash","source_type"]}}}}}},"/v1/devices/status":{"get":{"summary":"Status perangkat terautentikasi","description":"","operationId":"get__v1_devices_status","tags":["Perangkat"],"security":[{"bearer":[]}],"parameters":[],"responses":{"200":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/merchant/devices":{"get":{"summary":"Daftar perangkat merchant","description":"","operationId":"get__v1_merchant_devices","tags":["Perangkat"],"security":[{"bearer":[]}],"parameters":[],"responses":{"200":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/merchant/devices/{id}/revoke":{"post":{"summary":"Cabut perangkat","description":"","operationId":"post__v1_merchant_devices__id__revoke","tags":["Perangkat"],"security":[{"bearer":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"}},{"in":"header","name":"Idempotency-Key","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}],"responses":{"200":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{},"required":[]}}}}}},"/v1/merchant/devices/{id}/rotate":{"post":{"summary":"Rotasi token perangkat","description":"","operationId":"post__v1_merchant_devices__id__rotate","tags":["Perangkat"],"security":[{"bearer":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"}},{"in":"header","name":"Idempotency-Key","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}],"responses":{"200":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{},"required":[]}}}}}},"/v1/payments":{"post":{"summary":"Buat permintaan pembayaran","description":"Integer IDR 1–10.000.000, dapat dibatasi lebih rendah oleh konfigurasi sistem. STATIC_QRIS mempertahankan gambar asli. PROVIDER_DYNAMIC_QRIS mengembalikan 503 sampai provider resmi disetujui.","operationId":"post__v1_payments","tags":["Pembayaran"],"security":[{"bearer":[]}],"parameters":[{"in":"header","name":"Idempotency-Key","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}},{"in":"header","name":"X-Merchant-Id","required":false,"schema":{"type":"string","format":"uuid"},"description":"Pilihan membership untuk akun multi-merchant"}],"responses":{"201":{"description":"Created"},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"amount_idr":{"type":"integer","minimum":1,"maximum":10000000},"currency":{"const":"IDR","type":"string"},"qr_mode":{"type":"string","enum":["STATIC_QRIS","PROVIDER_DYNAMIC_QRIS"]},"external_reference":{"type":"string","minLength":1,"maxLength":120}},"required":["amount_idr"]}}}}},"get":{"summary":"Riwayat pembayaran berpaginasi","description":"","operationId":"get__v1_payments","tags":["Pembayaran"],"security":[{"bearer":[]}],"parameters":[{"in":"header","name":"X-Merchant-Id","required":false,"schema":{"type":"string","format":"uuid"},"description":"Pilihan membership untuk akun multi-merchant"},{"in":"query","name":"limit","required":false,"schema":{"type":"integer","minimum":1,"maximum":100}},{"in":"query","name":"cursor","required":false,"schema":{"type":"string","format":"uuid"}},{"in":"query","name":"status","required":false,"schema":{"type":"string","enum":["CREATED","PENDING","PAYMENT_DETECTED","VERIFYING","PAID","EXPIRED","FAILED","REVIEW_REQUIRED","REFUNDED","SIMULATED_PAID"]}},{"in":"query","name":"q","required":false,"schema":{"type":"string","maxLength":120}}],"responses":{"200":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/payments/{id}":{"get":{"summary":"Detail dan kronologi pembayaran","description":"","operationId":"get__v1_payments__id_","tags":["Pembayaran"],"security":[{"bearer":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"}},{"in":"header","name":"X-Merchant-Id","required":false,"schema":{"type":"string","format":"uuid"},"description":"Pilihan membership untuk akun multi-merchant"}],"responses":{"200":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/payments/{id}/status":{"get":{"summary":"Status pembayaran dari server","description":"","operationId":"get__v1_payments__id__status","tags":["Pembayaran"],"security":[{"bearer":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"}},{"in":"header","name":"X-Merchant-Id","required":false,"schema":{"type":"string","format":"uuid"},"description":"Pilihan membership untuk akun multi-merchant"}],"responses":{"200":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/payments/{id}/cancel":{"post":{"summary":"Batalkan tagihan belum terverifikasi","description":"Pembatalan dicatat sebagai FAILED dengan failure_reason=merchant_canceled. Tidak mengubah PAID.","operationId":"post__v1_payments__id__cancel","tags":["Pembayaran"],"security":[{"bearer":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"}},{"in":"header","name":"Idempotency-Key","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}},{"in":"header","name":"X-Merchant-Id","required":false,"schema":{"type":"string","format":"uuid"},"description":"Pilihan membership untuk akun multi-merchant"}],"responses":{"200":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{},"required":[]}}}}}},"/v1/merchant/profile":{"get":{"summary":"Profil dan konfigurasi merchant","description":"","operationId":"get__v1_merchant_profile","tags":["Merchant"],"security":[{"bearer":[]}],"parameters":[{"in":"header","name":"X-Merchant-Id","required":false,"schema":{"type":"string","format":"uuid"},"description":"Pilihan membership untuk akun multi-merchant"}],"responses":{"200":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/qr-sources":{"post":{"summary":"Daftarkan gambar QR merchant asli","description":"","operationId":"post__v1_qr_sources","tags":["Merchant"],"security":[{"bearer":[]}],"parameters":[{"in":"header","name":"Idempotency-Key","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}},{"in":"header","name":"X-Merchant-Id","required":false,"schema":{"type":"string","format":"uuid"},"description":"Pilihan membership untuk akun multi-merchant"}],"responses":{"201":{"description":"Created"},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"mime":{"type":"string","enum":["image/png","image/jpeg"]},"bytes_base64":{"type":"string","maxLength":950000},"ownership_confirmed":{"const":true,"type":"boolean"}},"required":["mime","bytes_base64","ownership_confirmed"]}}}}}},"/v1/qr-sources/{id}/image":{"get":{"summary":"Ambil gambar asli terautentikasi","description":"","operationId":"get__v1_qr_sources__id__image","tags":["Merchant"],"security":[{"bearer":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"}},{"in":"header","name":"X-Merchant-Id","required":false,"schema":{"type":"string","format":"uuid"},"description":"Pilihan membership untuk akun multi-merchant"}],"responses":{"200":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/merchant/api-keys":{"get":{"summary":"Daftar identifier tanpa secret","description":"","operationId":"get__v1_merchant_api_keys","tags":["Credential"],"security":[{"bearer":[]}],"parameters":[],"responses":{"200":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"summary":"Buat credential Layer A/B","description":"ENROLLMENT hanya devices:enroll. INTEGRATION untuk server website dengan scope pembayaran/webhook. Hanya verifier di-hash yang disimpan. Secret dihilangkan dari cache; retry penerbitan mengembalikan 409 SECRET_ALREADY_ISSUED, gunakan rotasi/enrollment ulang jika respons pertama hilang.","operationId":"post__v1_merchant_api_keys","tags":["Credential"],"security":[{"bearer":[]}],"parameters":[{"in":"header","name":"Idempotency-Key","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}],"responses":{"201":{"description":"Created"},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":80},"layer":{"type":"string","enum":["ENROLLMENT","INTEGRATION"]},"scopes":{"type":"array","items":{"type":"string","enum":["payments:read","payments:write","webhooks:manage","devices:enroll"]},"minItems":1,"maxItems":4},"expires_in_days":{"type":"integer","minimum":1,"maximum":90}},"required":["name","layer","scopes"]}}}}}},"/v1/merchant/api-keys/{id}":{"delete":{"summary":"Cabut credential","description":"","operationId":"delete__v1_merchant_api_keys__id_","tags":["Credential"],"security":[{"bearer":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"}},{"in":"header","name":"Idempotency-Key","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}],"responses":{"200":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/merchant/api-keys/{id}/rotate":{"post":{"summary":"Rotasi credential; secret sekali tampil","description":"","operationId":"post__v1_merchant_api_keys__id__rotate","tags":["Credential"],"security":[{"bearer":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"}},{"in":"header","name":"Idempotency-Key","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}],"responses":{"200":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{},"required":[]}}}}}},"/v1/webhooks/endpoints":{"post":{"summary":"Daftarkan penerima webhook","description":"Signing secret terpisah. HTTPS, allowlist host operator dan challenge verifikasi wajib.","operationId":"post__v1_webhooks_endpoints","tags":["Webhook"],"security":[{"bearer":[]}],"parameters":[{"in":"header","name":"Idempotency-Key","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}],"responses":{"201":{"description":"Created"},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"url":{"type":"string","format":"uri","maxLength":2048}},"required":["url"]}}}}},"get":{"summary":"Daftar penerima tanpa secret","description":"","operationId":"get__v1_webhooks_endpoints","tags":["Webhook"],"security":[{"bearer":[]}],"parameters":[],"responses":{"200":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/webhooks/endpoints/{id}":{"delete":{"summary":"Nonaktifkan penerima webhook","description":"","operationId":"delete__v1_webhooks_endpoints__id_","tags":["Webhook"],"security":[{"bearer":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"}},{"in":"header","name":"Idempotency-Key","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}],"responses":{"200":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/webhooks/endpoints/{id}/test":{"post":{"summary":"Kirim endpoint.test non-finansial","description":"","operationId":"post__v1_webhooks_endpoints__id__test","tags":["Webhook"],"security":[{"bearer":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"}},{"in":"header","name":"Idempotency-Key","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}],"responses":{"200":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{},"required":[]}}}}}},"/v1/webhooks/endpoints/{id}/rotate":{"post":{"summary":"Rotasi signing secret dan verifikasi ulang","description":"","operationId":"post__v1_webhooks_endpoints__id__rotate","tags":["Webhook"],"security":[{"bearer":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"}},{"in":"header","name":"Idempotency-Key","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}],"responses":{"200":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{},"required":[]}}}}}},"/v1/realtime/config":{"get":{"summary":"Konfigurasi Supabase Realtime terotorisasi","description":"JWT pengguna berumur pendek dan anon key publik, bukan service role. Subscribe manji_gateway.payment_requests dengan filter merchant_id. RLS tetap memeriksa role, status, sesi dan membership.","operationId":"get__v1_realtime_config","tags":["Realtime"],"security":[{"bearer":[]}],"parameters":[],"responses":{"200":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/overview":{"get":{"summary":"Operasional khusus ADMIN","description":"","operationId":"get__v1_admin_overview","tags":["Administrator"],"security":[{"bearer":[]}],"parameters":[],"responses":{"200":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/applications/{id}/review":{"post":{"summary":"Setujui/tolak pengajuan","description":"","operationId":"post__v1_admin_applications__id__review","tags":["Administrator"],"security":[{"bearer":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"}},{"in":"header","name":"Idempotency-Key","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}],"responses":{"200":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"action":{"type":"string","enum":["approve","reject"]},"note":{"type":"string","minLength":3,"maxLength":500}},"required":["action","note"]}}}}}},"/v1/admin/accounts/{id}/status":{"post":{"summary":"Suspend/aktifkan akun non-admin","description":"","operationId":"post__v1_admin_accounts__id__status","tags":["Administrator"],"security":[{"bearer":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"}},{"in":"header","name":"Idempotency-Key","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}],"responses":{"200":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"status":{"type":"string","enum":["ACTIVE","SUSPENDED"]}},"required":["status"]}}}}}},"/v1/admin/merchants/{id}/status":{"post":{"summary":"Suspend/aktifkan merchant","description":"","operationId":"post__v1_admin_merchants__id__status","tags":["Administrator"],"security":[{"bearer":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"}},{"in":"header","name":"Idempotency-Key","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}],"responses":{"200":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"status":{"type":"string","enum":["ACTIVE","SUSPENDED"]}},"required":["status"]}}}}}},"/v1/admin/configuration":{"post":{"summary":"Konfigurasi dan sumber notifikasi berizin","description":"","operationId":"post__v1_admin_configuration","tags":["Administrator"],"security":[{"bearer":[]}],"parameters":[{"in":"header","name":"Idempotency-Key","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}],"responses":{"200":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"registration_open":{"type":"boolean"},"max_amount_idr":{"type":"integer","minimum":1,"maximum":10000000},"signal_retention_days":{"type":"integer","minimum":1,"maximum":30},"notification_sources":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"package_name":{"type":"string","minLength":3,"maxLength":180,"pattern":"^[A-Za-z][\\w]*(?:\\.[A-Za-z][\\w]*)+$"},"evidence_note":{"type":"string","minLength":10,"maxLength":300},"reviewed_at":{"type":"string","format":"date-time"}},"required":["package_name","evidence_note","reviewed_at"]},"maxItems":20}},"required":["registration_open","max_amount_idr","signal_retention_days","notification_sources"]}}}}}},"/v1/admin/api-keys/{id}/revoke":{"post":{"summary":"Cabut credential merchant oleh ADMIN","description":"","operationId":"post__v1_admin_api_keys__id__revoke","tags":["Administrator"],"security":[{"bearer":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"}},{"in":"header","name":"Idempotency-Key","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}],"responses":{"200":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{},"required":[]}}}}}},"/v1/admin/devices/{id}/revoke":{"post":{"summary":"Cabut perangkat oleh ADMIN","description":"","operationId":"post__v1_admin_devices__id__revoke","tags":["Administrator"],"security":[{"bearer":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"}},{"in":"header","name":"Idempotency-Key","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}],"responses":{"200":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{},"required":[]}}}}}},"/v1/admin/merchants/{id}/enrollment-credential":{"post":{"summary":"Credential enrollment 15 menit dari ADMIN","description":"","operationId":"post__v1_admin_merchants__id__enrollment_credential","tags":["Administrator"],"security":[{"bearer":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"}},{"in":"header","name":"Idempotency-Key","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}],"responses":{"201":{"description":"Created"},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{},"required":[]}}}}}},"/v1/privacy/export":{"get":{"summary":"Ekspor snapshot merchant","description":"","operationId":"get__v1_privacy_export","tags":["Merchant"],"security":[{"bearer":[]}],"parameters":[{"in":"header","name":"X-Merchant-Id","required":false,"schema":{"type":"string","format":"uuid"},"description":"Pilihan membership untuk akun multi-merchant"}],"responses":{"200":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/privacy/signals":{"delete":{"summary":"Hapus sinyal minimal dan audit tindakan","description":"","operationId":"delete__v1_privacy_signals","tags":["Merchant"],"security":[{"bearer":[]}],"parameters":[{"in":"header","name":"Idempotency-Key","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}},{"in":"header","name":"X-Merchant-Id","required":false,"schema":{"type":"string","format":"uuid"},"description":"Pilihan membership untuk akun multi-merchant"}],"responses":{"200":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{},"required":[]}}}}}},"/v1/provider/webhook/official":{"post":{"summary":"Callback provider resmi — belum aktif","description":"Selalu 503 PROVIDER_NOT_ONBOARDED. Tidak ada algoritma GoPay atau akses provider yang dikarang.","operationId":"post__v1_provider_webhook_official","tags":["Provider"],"security":[],"parameters":[],"responses":{"200":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/sandbox/provider/webhook":{"post":{"summary":"Callback HMAC protokol sandbox lokal","description":"X-Mock-Signature = HMAC-SHA256(body mentah, MOCK_PROVIDER_SECRET). Bukan algoritma GoPay. Timestamp maksimal ±5 menit. Tidak dapat menetapkan PAID produksi.","operationId":"post__v1_sandbox_provider_webhook","tags":["Sandbox"],"security":[],"parameters":[],"responses":{"200":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"event_id":{"type":"string","format":"uuid"},"merchant_id":{"type":"string","format":"uuid"},"payment_id":{"type":"string","format":"uuid"},"transaction_id":{"type":"string","format":"uuid"},"amount_idr":{"type":"integer","minimum":1,"maximum":10000000},"currency":{"const":"IDR","type":"string"},"event_type":{"type":"string","enum":["settlement","refund"]},"environment":{"const":"sandbox","type":"string"},"timestamp":{"type":"integer"}},"required":["event_id","merchant_id","payment_id","transaction_id","amount_idr","currency","event_type","environment","timestamp"]}}}}}},"/v1/sandbox/confirm":{"post":{"summary":"Konfirmasi uji merchant lokal","description":"Sandbox saja, hasil SIMULATED_PAID atau REVIEW_REQUIRED. Tidak ada sukses finansial/receipt/speech nyata.","operationId":"post__v1_sandbox_confirm","tags":["Sandbox"],"security":[{"bearer":[]}],"parameters":[{"in":"header","name":"Idempotency-Key","required":true,"schema":{"type":"string","minLength":8,"maxLength":128}}],"responses":{"200":{"description":"Respons berhasil. Status finansial hanya berasal dari provider resmi."},"default":{"description":"Kesalahan terstruktur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"payment_id":{"type":"string","format":"uuid"}},"required":["payment_id"]}}}}}}}}