MANJIGATEWAY / APIOpenAPI 3.1

DOKUMENTASI INTEGRASI

Satu API, bukti yang jelas.

Integrasikan permintaan pembayaran di server website Anda. Notifikasi Android adalah UNTRUSTED; hanya provider resmi dapat memverifikasi settlement. Sandbox selalu berlabel SIMULATED_PAID.

Credential dengan tujuan berbeda

Layer A ENROLLMENT hanya untuk enrollment awal perangkat. Tukar tantangan melalui /v1/auth/device/enroll dan /v1/auth/device/redeem menjadi token perangkat 15 menit; hapus secret enrollment dari memori setelahnya.

Layer B INTEGRATION memakai identifier publik dan secret untuk server website. Gunakan scope payments:read/write atau webhooks:manage seperlunya. Secret hanya sekali ditampilkan, verifier di-hash, dapat dirotasi/dicabut.

Kontrak pembayaran

Integer IDR. STATIC_QRIS menampilkan QR asli dan mewajibkan input nominal oleh pembayar. PROVIDER_DYNAMIC_QRIS mengembalikan 503 sampai adapter resmi disetujui. Tidak ada modifikasi TLV/CRC.

Gunakan Idempotency-Key 8–128 karakter untuk mutation. Cache 24 jam tanpa secret. Replay penerbitan secret mengembalikan 409 SECRET_ALREADY_ISSUED; rotasi/enrollment ulang jika respons hilang. external_reference unik per merchant untuk deduplikasi pesanan jangka panjang. Riwayat menggunakan limit 1–100 dan cursor ID dari next_cursor.

Contoh integrasi server

curl -X POST "$MANJI_API_ORIGIN/v1/payments" \
  -H "Authorization: Bearer $MANJI_API_KEY" \
  -H 'Idempotency-Key: order-2026-unique-101' \
  -H 'Content-Type: application/json' \
  --data '{"amount_idr":25000,"currency":"IDR","qr_mode":"STATIC_QRIS","external_reference":"POS-101"}'

Verifikasi webhook

Signing secret berbeda dari API key. Hitung HMAC-SHA256 atas timestamp + '.' + body mentah. Periksa header X-Webhook-Timestamp (selisih ≤5 menit), X-Webhook-Signature, X-Delivery-Id; simpan event ID untuk deduplikasi. Retry mempertahankan delivery ID, maksimal 8 kali. HTTPS, DNS publik yang dipin dan allowlist host operator wajib.

import {createHmac, timingSafeEqual} from 'node:crypto';
const expected = createHmac('sha256', signingSecret).update(timestamp + '.' + rawBody).digest('hex');
if (!/^[0-9]{10,11}$/.test(timestamp) || !Number.isSafeInteger(Number(timestamp)) ||
    !/^[a-f0-9]{64}$/.test(signature) ||
    !timingSafeEqual(Buffer.from(expected), Buffer.from(signature)) ||
    Math.abs(Date.now()/1000 - Number(timestamp)) > 300) throw Error('reject');
// Validate timestamp as an integer, deduplicate delivery ID before fulfillment.
// endpoint.verification: return {challenge: event.data.challenge}.
// payment.detected is UNTRUSTED; payment.simulated is never fulfillment authority.

Hanya payment.verified pada produksi yang dapat menjadi dasar pemenuhan setelah memvalidasi merchant, nominal, currency dan reference. payment.refunded adalah event terpisah. Adapter resmi belum aktif pada implementasi ini.

Kesalahan dan batas permintaan

401: refresh/login/enrollment ulang. 403: role/scope/akun ditolak. 404: sumber daya tidak ada pada tenant. 409: state/idempotensi konflik. 429: hormati Retry-After. 503: konfigurasi/provider/dependensi belum siap. Batas default 120 request per menit per identitas; perangkat 60; auth 20. Gunakan rate limiter edge sebelum produksi.

{"error":{"code":"MERCHANT_REQUIRED","message":"Akun belum memiliki akses merchant","request_id":"uuid"}}

Referensi endpoint

GET/api/v1/app/download · Unduh APK MANJI Gateway bertanda tangan

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.

GET/aplikasi/manji-gateway-release.apk · Berkas APK existing setelah signing

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.

GET/api/v1/app/unsigned/download · Unduh arsip APK unsigned untuk pengembangan

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.

GET/v1/app/version · Versi APK resmi, kanal dan riwayat

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.

GET/v1/app/latest/download · Mulai unduh APK resmi terbaru

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.

GET/v1/app/releases/{id}/download · Unduh versi tertentu dari riwayat

307 tiket backend sementara; rilis yang ditarik ditolak. Signature, identitas paket dan kode versi tetap diperiksa Android.

GET/v1/app/releases/{id}/file · Berkas APK terverifikasi melalui tiket

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.

GET/v1/app/releases/{id}/screenshots/{index} · Cuplikan layar asli untuk rilis

Gambar dari private storage yang lolos checksum; indeks 0–7. Tidak ada preview hasil rekayasa yang diklaim sebagai screenshot.

GET/health · Kesehatan dan lingkungan backend

POST/v1/auth/register · Daftar akun PENDING

Role dari klien ditolak. Verifikasi email dan peninjauan admin diperlukan; tidak ada hak merchant/admin otomatis.

{
  "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"
        ]
      }
    }
  }
}
POST/v1/auth/login · Login email/password

{
  "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"
        ]
      }
    }
  }
}
POST/v1/auth/verify · Verifikasi tautan email/pemulihan

{
  "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"
        ]
      }
    }
  }
}
POST/v1/auth/refresh · Perbarui sesi pengguna

Browser memakai cookie HttpOnly. Android mengirim refresh_token dari penyimpanan terenkripsi.

{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "refresh_token": {
            "type": "string"
          }
        },
        "required": []
      }
    }
  }
}
POST/v1/auth/reset-password · Minta pemulihan password

{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "email": {
            "type": "string",
            "format": "email"
          }
        },
        "required": [
          "email"
        ]
      }
    }
  }
}
POST/v1/auth/resend-verification · Kirim ulang verifikasi

{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "email": {
            "type": "string",
            "format": "email"
          }
        },
        "required": [
          "email"
        ]
      }
    }
  }
}
GET/v1/auth/me · Profil, role, pengajuan dan membership

POST/v1/auth/logout · Logout aman dan cabut sesi

{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "additionalProperties": false,
        "properties": {},
        "required": []
      }
    }
  }
}
POST/v1/auth/password · Ubah password dan cabut sesi lain

{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "password": {
            "type": "string",
            "minLength": 12,
            "maxLength": 128
          }
        },
        "required": [
          "password"
        ]
      }
    }
  }
}
GET/v1/auth/sessions · Daftar sesi akun

DELETE/v1/auth/sessions/{id} · Cabut sesi akun

POST/v1/merchant-applications · Ajukan akses merchant

{
  "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"
        ]
      }
    }
  }
}
POST/v1/auth/device/enroll · Mulai enrollment perangkat

Sesi MERCHANT atau key Layer A ENROLLMENT. Allowlist harus merupakan sumber yang disetujui admin; tantangan berlaku 5 menit.

{
  "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"
        ]
      }
    }
  }
}
POST/v1/auth/device/redeem · Tukar tantangan dengan token perangkat

Identitas pengaju yang sama. Token perangkat berlaku 15 menit; credential enrollment tidak disimpan permanen di Android.

{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "challenge_id": {
            "type": "string",
            "format": "uuid"
          },
          "challenge": {
            "type": "string"
          }
        },
        "required": [
          "challenge_id",
          "challenge"
        ]
      }
    }
  }
}
POST/v1/devices/events · Kirim sinyal minimal UNTRUSTED

Hanya token perangkatnya sendiri. Kandidat nominal/waktu tidak pernah menetapkan PAID atau mengirim payment.verified.

{
  "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"
        ]
      }
    }
  }
}
GET/v1/devices/status · Status perangkat terautentikasi

GET/v1/merchant/devices · Daftar perangkat merchant

POST/v1/merchant/devices/{id}/revoke · Cabut perangkat

{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "additionalProperties": false,
        "properties": {},
        "required": []
      }
    }
  }
}
POST/v1/merchant/devices/{id}/rotate · Rotasi token perangkat

{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "additionalProperties": false,
        "properties": {},
        "required": []
      }
    }
  }
}
POST/v1/payments · Buat permintaan pembayaran

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.

{
  "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/v1/payments · Riwayat pembayaran berpaginasi

GET/v1/payments/{id} · Detail dan kronologi pembayaran

GET/v1/payments/{id}/status · Status pembayaran dari server

POST/v1/payments/{id}/cancel · Batalkan tagihan belum terverifikasi

Pembatalan dicatat sebagai FAILED dengan failure_reason=merchant_canceled. Tidak mengubah PAID.

{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "additionalProperties": false,
        "properties": {},
        "required": []
      }
    }
  }
}
GET/v1/merchant/profile · Profil dan konfigurasi merchant

POST/v1/qr-sources · Daftarkan gambar QR merchant asli

{
  "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"
        ]
      }
    }
  }
}
GET/v1/qr-sources/{id}/image · Ambil gambar asli terautentikasi

GET/v1/merchant/api-keys · Daftar identifier tanpa secret

POST/v1/merchant/api-keys · Buat credential Layer A/B

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.

{
  "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"
        ]
      }
    }
  }
}
DELETE/v1/merchant/api-keys/{id} · Cabut credential

POST/v1/merchant/api-keys/{id}/rotate · Rotasi credential; secret sekali tampil

{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "additionalProperties": false,
        "properties": {},
        "required": []
      }
    }
  }
}
POST/v1/webhooks/endpoints · Daftarkan penerima webhook

Signing secret terpisah. HTTPS, allowlist host operator dan challenge verifikasi wajib.

{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048
          }
        },
        "required": [
          "url"
        ]
      }
    }
  }
}
GET/v1/webhooks/endpoints · Daftar penerima tanpa secret

DELETE/v1/webhooks/endpoints/{id} · Nonaktifkan penerima webhook

POST/v1/webhooks/endpoints/{id}/test · Kirim endpoint.test non-finansial

{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "additionalProperties": false,
        "properties": {},
        "required": []
      }
    }
  }
}
POST/v1/webhooks/endpoints/{id}/rotate · Rotasi signing secret dan verifikasi ulang

{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "additionalProperties": false,
        "properties": {},
        "required": []
      }
    }
  }
}
GET/v1/realtime/config · Konfigurasi Supabase Realtime terotorisasi

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.

GET/v1/admin/overview · Operasional khusus ADMIN

POST/v1/admin/applications/{id}/review · Setujui/tolak pengajuan

{
  "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"
        ]
      }
    }
  }
}
POST/v1/admin/accounts/{id}/status · Suspend/aktifkan akun non-admin

{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "ACTIVE",
              "SUSPENDED"
            ]
          }
        },
        "required": [
          "status"
        ]
      }
    }
  }
}
POST/v1/admin/merchants/{id}/status · Suspend/aktifkan merchant

{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "ACTIVE",
              "SUSPENDED"
            ]
          }
        },
        "required": [
          "status"
        ]
      }
    }
  }
}
POST/v1/admin/configuration · Konfigurasi dan sumber notifikasi berizin

{
  "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"
        ]
      }
    }
  }
}
POST/v1/admin/api-keys/{id}/revoke · Cabut credential merchant oleh ADMIN

{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "additionalProperties": false,
        "properties": {},
        "required": []
      }
    }
  }
}
POST/v1/admin/devices/{id}/revoke · Cabut perangkat oleh ADMIN

{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "additionalProperties": false,
        "properties": {},
        "required": []
      }
    }
  }
}
POST/v1/admin/merchants/{id}/enrollment-credential · Credential enrollment 15 menit dari ADMIN

{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "additionalProperties": false,
        "properties": {},
        "required": []
      }
    }
  }
}
GET/v1/privacy/export · Ekspor snapshot merchant

DELETE/v1/privacy/signals · Hapus sinyal minimal dan audit tindakan

{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "additionalProperties": false,
        "properties": {},
        "required": []
      }
    }
  }
}
POST/v1/provider/webhook/official · Callback provider resmi — belum aktif

Selalu 503 PROVIDER_NOT_ONBOARDED. Tidak ada algoritma GoPay atau akses provider yang dikarang.

POST/v1/sandbox/provider/webhook · Callback HMAC protokol sandbox lokal

X-Mock-Signature = HMAC-SHA256(body mentah, MOCK_PROVIDER_SECRET). Bukan algoritma GoPay. Timestamp maksimal ±5 menit. Tidak dapat menetapkan PAID produksi.

{
  "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"
        ]
      }
    }
  }
}
POST/v1/sandbox/confirm · Konfirmasi uji merchant lokal

Sandbox saja, hasil SIMULATED_PAID atau REVIEW_REQUIRED. Tidak ada sukses finansial/receipt/speech nyata.

{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "payment_id": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "payment_id"
        ]
      }
    }
  }
}

Scalar API Reference

Memuat Scalar…

Scalar disajikan dari paket lokal; tidak ada secret yang dipasang pada dokumentasi. Untuk pengujian bercredential, gunakan sandbox dan credential sementara dengan scope minimum.