Autentikasi Client App
Autentikasi yang disarankan adalah HMAC per request. Integrasi legacy dengan
X-Secret-Key masih bisa dipakai sementara selama mode migrasi
belum dimatikan.
Header utama
X-App-ID: project_a_prod
X-Timestamp: 1760832000
X-Payment-Signature: <hmac_signature>
Content-Type: application/json
Accept: application/json
String yang ditandatangani
{HTTP_METHOD}
{REQUEST_PATH}
{APP_ID}
{UNIX_TIMESTAMP}
{SHA256_RAW_BODY}
Contoh pembentukan signature
$rawBody = json_encode($payload, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
$bodyHash = hash('sha256', $rawBody);
$stringToSign = implode("\n", [
'POST',
'/api/v1/charge',
'project_a_prod',
$timestamp,
$bodyHash,
]);
$signature = hash_hmac('sha256', $stringToSign, $secretKey);
GET /projects/me
Dipakai untuk memverifikasi identitas project yang sedang terhubung sekaligus membaca readiness integrasi tenant.
Header request
X-App-ID: project_a_prod
X-Timestamp: 1760832000
X-Payment-Signature: <hmac_signature>
Accept: application/json
Contoh request cURL
curl --request GET \
--url https://payment.naeva.id/api/v1/projects/me \
--header "Accept: application/json" \
--header "X-App-ID: project_a_prod" \
--header "X-Timestamp: 1760832000" \
--header "X-Payment-Signature: <signature>"
Example response 200
{
"data": {
"app_id": "project_a_prod",
"project_name": "Project A",
"default_callback_url": "https://client-app.example.com/payment/callback",
"is_active": true,
"authentication": {
"mode": "hmac_signature",
"signature_algorithm": "sha256",
"timestamp_tolerance_seconds": 300,
"request_headers": {
"app_id": "X-App-ID",
"timestamp": "X-Timestamp",
"signature": "X-Payment-Signature"
},
"legacy_secret_header": {
"enabled": true,
"header": "X-Secret-Key"
}
},
"integration": {
"base_url": "https://payment.naeva.id/api/v1",
"environment": "production",
"currency": "IDR",
"endpoints": {
"charge": "/api/v1/charge",
"project_profile": "/api/v1/projects/me",
"transaction_lookup": "/api/v1/transactions/lookup",
"transaction_detail": "/api/v1/transactions/{gatewayOrderId}",
"callback_history": "/api/v1/transactions/{gatewayOrderId}/callback-history"
}
},
"callback": {
"default_url": "https://client-app.example.com/payment/callback",
"retry": {
"queue": "payment-callbacks",
"timeout_seconds": 10,
"max_attempts": 3,
"backoff_seconds": [60, 300, 900]
},
"delivery_headers": {
"app_id": "X-Payment-App-Id",
"event": "X-Payment-Event",
"attempt": "X-Payment-Attempt",
"timestamp": "X-Payment-Timestamp",
"delivery_id": "X-Payment-Delivery-Id",
"signature": "X-Payment-Signature"
},
"signature": {
"algorithm": "sha256",
"uses_project_secret_key": true
}
},
"readiness": {
"status": "ready",
"can_charge": true,
"has_default_callback_url": true,
"checks": [
{
"name": "project_active",
"passed": true,
"message": "Project aktif dan dapat mengakses API tenant."
},
{
"name": "default_callback_url_configured",
"passed": true,
"message": "Default callback URL sudah terpasang."
},
{
"name": "hmac_signature_auth_ready",
"passed": true,
"message": "Gunakan HMAC signature untuk integrasi tenant yang disarankan."
}
]
}
}
}
POST /charge
Endpoint utama untuk membuat transaksi baru dan mendapatkan token Snap Midtrans.
Header request
X-App-ID: project_a_prod
X-Timestamp: 1760832000
X-Payment-Signature: <hmac_signature>
Content-Type: application/json
Accept: application/json
Example request body
{
"order_id": "INV-PROJECTA-2026-001",
"gross_amount": 150000,
"currency": "IDR",
"customer_details": {
"first_name": "Budi",
"last_name": "Santoso",
"email": "[email protected]",
"phone": "081234567890"
},
"item_details": [
{
"id": "SKU-INV-001",
"price": 150000,
"quantity": 1,
"name": "Invoice Payment"
}
],
"custom_callback_url": "https://client-app.example.com/api/payment/notification",
"metadata": {
"invoice_id": 1001,
"source": "project-a"
}
}
Contoh request cURL
curl --request POST \
--url https://payment.naeva.id/api/v1/charge \
--header "Accept: application/json" \
--header "Content-Type: application/json" \
--header "X-App-ID: project_a_prod" \
--header "X-Timestamp: 1760832000" \
--header "X-Payment-Signature: <signature>" \
--data '{
"order_id": "INV-PROJECTA-2026-001",
"gross_amount": 150000,
"currency": "IDR",
"customer_details": {
"first_name": "Budi",
"last_name": "Santoso",
"email": "[email protected]",
"phone": "081234567890"
},
"item_details": [
{
"id": "SKU-INV-001",
"price": 150000,
"quantity": 1,
"name": "Invoice Payment"
}
],
"custom_callback_url": "https://client-app.example.com/api/payment/notification",
"metadata": {
"invoice_id": 1001,
"source": "project-a"
}
}'
Example response 201
{
"status": "success",
"project": {
"app_id": "project_a_prod",
"name": "Project A"
},
"order_id": "INV-PROJECTA-2026-001",
"gateway_order_id": "PROJECT-A-PROD-01JY3G0T2T8V40Q0V4K2QJ8G45",
"token": "snap-token-xyz",
"redirect_url": "https://app.midtrans.com/snap/v2/vtweb/snap-token-xyz"
}
Field penting
order_idwajib dan merepresentasikan ID order dari client app.gross_amountwajib, integer, minimal 1.customer_detailswajib, minimal berisifirst_name.custom_callback_urlopsional untuk override callback URL default project.expires_atopsional dan harus berupa waktu setelah saat ini.
GET /transactions/lookup
Dipakai untuk mencari transaksi memakai client_order_id, gateway_order_id, atau mode auto.
Header request
X-App-ID: project_a_prod
X-Timestamp: 1760832000
X-Payment-Signature: <hmac_signature>
Accept: application/json
Query parameter
identifierwajib, nilai yang ingin dicari.byopsional, nilaiauto,gateway_order_id, atauclient_order_id.
Contoh request cURL
curl --request GET \
--url "https://payment.naeva.id/api/v1/transactions/lookup?identifier=INV-LOOKUP-001&by=client_order_id" \
--header "Accept: application/json" \
--header "X-App-ID: project_a_prod" \
--header "X-Timestamp: 1760832000" \
--header "X-Payment-Signature: <signature>"
Example response 200
{
"data": {
"gateway_order_id": "PROJECTLOOKUP-01JABC1234567890",
"order_id": "INV-LOOKUP-001",
"amount": 123000,
"currency": "IDR",
"status": "pending",
"callback_status": "queued",
"payment_type": "bank_transfer",
"redirect_url": "https://midtrans.test/snap/lookup-001",
"callback_url": "https://client-app.example.com/api/payment/callback",
"metadata": {
"invoice_id": 7001
},
"customer_details": {
"first_name": "Lookup User",
"email": "[email protected]"
},
"timestamps": {
"created_at": "2026-06-20 02:30:00",
"updated_at": "2026-06-20 02:30:00",
"paid_at": null,
"expires_at": null,
"last_webhook_at": "2026-06-20 02:29:00"
},
"latest_webhook": {
"status": "pending",
"processing_status": "processed",
"is_signature_valid": true,
"received_at": "2026-06-20 02:29:00",
"processed_at": "2026-06-20 02:29:00"
},
"latest_callback": {
"attempt": 1,
"event_type": "payment.status.updated",
"callback_url": "https://client-app.example.com/api/payment/callback",
"success": false,
"response_status_code": 500,
"error_message": "HTTP 500",
"delivery_id": "delivery-lookup-001",
"next_retry_at": "2026-06-20 02:31:00",
"dispatched_at": "2026-06-20 02:30:30",
"responded_at": "2026-06-20 02:30:31"
}
}
}
GET yang memakai query string, path yang ditandatangani
harus mencakup query string persis seperti request akhir. Contoh:
/api/v1/transactions/lookup?identifier=INV-LOOKUP-001&by=client_order_id
GET /transactions/{gateway_order_id}
Dipakai untuk mengambil detail transaksi lengkap berdasarkan gateway order id yang dibuat oleh layanan payment.
Header request
X-App-ID: project_a_prod
X-Timestamp: 1760832000
X-Payment-Signature: <hmac_signature>
Accept: application/json
Parameter path
gateway_order_idwajib, ID transaksi internal yang dikembalikan saat endpointPOST /chargeberhasil.
Contoh request cURL
curl --request GET \
--url "https://payment.naeva.id/api/v1/transactions/PROJECT-A-PROD-01JY3G0T2T8V40Q0V4K2QJ8G45" \
--header "Accept: application/json" \
--header "X-App-ID: project_a_prod" \
--header "X-Timestamp: 1760832000" \
--header "X-Payment-Signature: <signature>"
Example response 200
{
"data": {
"gateway_order_id": "PROJECT-A-PROD-01JY3G0T2T8V40Q0V4K2QJ8G45",
"order_id": "INV-PROJECTA-2026-001",
"amount": 150000,
"currency": "IDR",
"status": "pending",
"callback_status": "queued",
"payment_type": "bank_transfer",
"redirect_url": "https://app.midtrans.com/snap/v2/vtweb/snap-token-xyz",
"callback_url": "https://client-app.example.com/api/payment/notification",
"metadata": {
"invoice_id": 1001
},
"customer_details": {
"first_name": "Budi"
},
"timestamps": {
"created_at": "2026-06-20 02:25:00",
"updated_at": "2026-06-20 02:30:00",
"paid_at": null,
"expires_at": null,
"last_webhook_at": "2026-06-20 02:29:00"
},
"latest_webhook": {
"status": "pending",
"processing_status": "processed",
"is_signature_valid": true,
"received_at": "2026-06-20 02:29:00",
"processed_at": "2026-06-20 02:29:00"
},
"latest_callback": {
"attempt": 1,
"event_type": "payment.status.updated",
"callback_url": "https://client-app.example.com/api/payment/notification",
"success": false,
"response_status_code": 500,
"error_message": "HTTP 500",
"delivery_id": "delivery-001",
"next_retry_at": "2026-06-20 02:31:00",
"dispatched_at": "2026-06-20 02:30:30",
"responded_at": "2026-06-20 02:30:31"
}
}
}
GET /transactions/{gateway_order_id}/callback-history
Dipakai untuk audit seluruh riwayat delivery callback per transaksi, termasuk retry terbaru.
Header request
X-App-ID: project_a_prod
X-Timestamp: 1760832000
X-Payment-Signature: <hmac_signature>
Accept: application/json
Query parameter
limitopsional, integer 1-20, default5.
Contoh request cURL
curl --request GET \
--url "https://payment.naeva.id/api/v1/transactions/PROJECT-A-PROD-01JY3G0T2T8V40Q0V4K2QJ8G45/callback-history?limit=5" \
--header "Accept: application/json" \
--header "X-App-ID: project_a_prod" \
--header "X-Timestamp: 1760832000" \
--header "X-Payment-Signature: <signature>"
Example response 200
{
"data": {
"gateway_order_id": "PROJECTHISTORY-01JABC1234567890",
"order_id": "INV-HISTORY-001",
"callback_status": "queued",
"history": [
{
"attempt": 3,
"event_type": "payment.status.updated",
"callback_url": "https://client-app.example.com/api/payment/callback",
"success": true,
"response_status_code": 200,
"error_message": null,
"delivery_id": "delivery-003",
"next_retry_at": null,
"dispatched_at": "2026-06-20 02:29:00",
"responded_at": "2026-06-20 02:29:01"
},
{
"attempt": 2,
"event_type": "payment.status.updated",
"callback_url": "https://client-app.example.com/api/payment/callback",
"success": false,
"response_status_code": 502,
"error_message": "HTTP 502",
"delivery_id": "delivery-002",
"next_retry_at": "2026-06-20 02:35:00",
"dispatched_at": "2026-06-20 02:28:00",
"responded_at": "2026-06-20 02:28:01"
}
]
}
}
Webhook Midtrans
Endpoint POST /api/v1/callback/midtrans digunakan oleh Midtrans.
Endpoint ini memverifikasi signature webhook, mencari transaksi internal, memperbarui status, lalu
menjadwalkan callback async ke project asal.
Notification URL = https://payment.naeva.id/api/v1/callback/midtrans
dan
Finish Redirect URL = https://payment.naeva.id/midtrans/finish.
Contoh payload webhook dari Midtrans
{
"transaction_time": "2026-06-20 14:15:13",
"transaction_status": "settlement",
"transaction_id": "513f1f01-c9da-474c-9fc9-d5c64364b709",
"status_message": "midtrans payment notification",
"status_code": "200",
"signature_key": "<midtrans_signature>",
"settlement_time": "2026-06-20 14:16:13",
"payment_type": "gopay",
"order_id": "PROJECT-A-PROD-01JY3G0T2T8V40Q0V4K2QJ8G45",
"merchant_id": "M351033033",
"gross_amount": "150000.00",
"fraud_status": "accept",
"currency": "IDR"
}
Example response invalid signature
{
"message": "Invalid signature."
}
Example response reachability check
{
"ok": true,
"message": "Midtrans notification endpoint is reachable."
}
Example response accepted
{
"status": "accepted"
}
Example response ignored test notification
{
"ok": true,
"message": "Midtrans notification endpoint is reachable.",
"ignored": true
}
Callback untuk Sistem Anda
Bagian ini ditulis untuk pengguna layanan payment.naeva.id, yaitu tim
yang ingin menghubungkan sistem mereka ke callback dari service payment.
Yang perlu Anda siapkan
- Buat endpoint
POSTdi server Anda, misalnyahttps://client-app.example.com/api/payment/callback. - Simpan
App IDdanSecret Keyproject Anda dari dashboard. - Isi
default_callback_urlpada project, atau kirimcustom_callback_urlsaat membuat charge. - Pastikan endpoint Anda bisa menerima request JSON dan membalas HTTP
2xxsaat sukses.
Jika Anda mengirim custom_callback_url saat POST /charge,
maka callback transaksi itu akan dikirim ke URL tersebut. Jika tidak, callback akan dikirim ke
default_callback_url project Anda.
Header yang akan diterima sistem Anda
User-Agent: Naeva-Payment-Callback/1.0
X-Payment-App-Id: project_a_prod
X-Payment-Event: payment.status.updated
X-Payment-Attempt: 2
X-Payment-Timestamp: 1760832000
X-Payment-Delivery-Id: delivery-002
X-Payment-Signature: <hmac_sha256_payload_signature>
Content-Type: application/json
Accept: application/json
Contoh endpoint yang harus Anda siapkan
POST https://client-app.example.com/api/payment/callback
Contoh request yang akan diterima saat Test Callback URL
Saat Anda menekan tombol Test Callback URL di dashboard project, endpoint Anda
akan menerima request seperti ini:
POST /api/payment/callback HTTP/1.1
Host: client-app.example.com
User-Agent: Naeva-Payment-Callback/1.0
X-Payment-App-Id: APP-FI4YVWSGZHXN
X-Payment-Event: payment.callback.test
X-Payment-Attempt: 1
X-Payment-Timestamp: 1760860800
X-Payment-Delivery-Id: 7d9d1f42-4d4c-4a47-a5e7-9f4050cc91d0
X-Payment-Signature: a13bcceff73a921a3e709ff52b9148f1944067ef81e7b40a320c388953ed875e
Content-Type: application/json
Accept: application/json
Content-Length: 278
{"test":true,"event":"payment.callback.test","message":"This is a callback connectivity test from payment.naeva.id","app_id":"APP-FI4YVWSGZHXN","project_name":"LevelUP adsPRO","callback_url":"https://client-app.example.com/api/payment/callback","sent_at":"2026-06-20 15:00:00"}
Raw body yang harus Anda verifikasi saat Test Callback URL
Signature dihitung dari body mentah ini. Endpoint Anda harus memverifikasi body apa adanya tanpa tambahan spasi atau format ulang.
{"test":true,"event":"payment.callback.test","message":"This is a callback connectivity test from payment.naeva.id","app_id":"APP-FI4YVWSGZHXN","project_name":"LevelUP adsPRO","callback_url":"https://client-app.example.com/api/payment/callback","sent_at":"2026-06-20 15:00:00"}
Contoh request status transaksi yang akan diterima sistem Anda
Ketika status pembayaran berubah, endpoint Anda akan menerima request seperti ini:
POST /api/payment/callback HTTP/1.1
Host: client-app.example.com
User-Agent: Naeva-Payment-Callback/1.0
X-Payment-App-Id: APP-FI4YVWSGZHXN
X-Payment-Event: payment.status.updated
X-Payment-Attempt: 2
X-Payment-Timestamp: 1760859000
X-Payment-Delivery-Id: delivery-002
X-Payment-Signature: d52b708685994945aac1213abb8b22b973ff1ffcd3e76f32f92fac387f2f32b1
Content-Type: application/json
Accept: application/json
Content-Length: 284
{"order_id":"INV-PROJECTA-2026-001","gateway_order_id":"PROJECT-A-PROD-01JY3G0T2T8V40Q0V4K2QJ8G45","transaction_status":"settlement","payment_type":"bank_transfer","gross_amount":150000,"transaction_time":"2026-06-20 14:30:00","metadata":{"invoice_id":1001,"source":"project-a"}}
Raw body status transaksi yang harus Anda verifikasi
{"order_id":"INV-PROJECTA-2026-001","gateway_order_id":"PROJECT-A-PROD-01JY3G0T2T8V40Q0V4K2QJ8G45","transaction_status":"settlement","payment_type":"bank_transfer","gross_amount":150000,"transaction_time":"2026-06-20 14:30:00","metadata":{"invoice_id":1001,"source":"project-a"}}
Cara verifikasi signature di sistem Anda
Gunakan Secret Key project Anda untuk menghitung HMAC dari raw body
request yang diterima.
$rawBody = $request->getContent();
$expectedSignature = hash_hmac('sha256', $rawBody, $projectSecretKey);
$receivedSignature = (string) $request->header('X-Payment-Signature');
if (! hash_equals($expectedSignature, $receivedSignature)) {
abort(401, 'Signature callback payment tidak valid.');
}
Penyebab umum test callback gagal
- Signature dihitung dari array yang sudah diparse lalu di-encode ulang.
- Menggunakan secret key yang bukan milik project yang aktif.
- Endpoint Anda tidak merespons HTTP
2xx. - Endpoint Anda memblokir request dari server
payment.naeva.id.
Response yang harus dikembalikan endpoint Anda
Jika callback berhasil diproses di sistem Anda, balas dengan HTTP 200 atau
status 2xx lain.
{
"received": true,
"message": "Callback diterima."
}
2xx atau timeout, callback akan dianggap
gagal dan akan dijadwalkan ulang otomatis dengan backoff 60, 300, lalu 900 detik.
Status dan Error
Status transaksi
pendingsettlementfailedexpiredcancelledrefunded
Status callback
pendingqueuedsuccessfailedskipped
Error umum
| HTTP | Code | Message | Arti |
|---|---|---|---|
| 401 | missing_project_app_id |
Missing project authentication app id header. |
Header X-App-ID tidak dikirim. |
| 401 | missing_project_hmac_headers |
Missing project HMAC authentication headers. |
Header HMAC tidak lengkap. |
| 401 | invalid_project_timestamp |
Invalid or expired project request timestamp. |
Timestamp di luar toleransi. |
| 401 | invalid_project_signature |
Invalid project request signature. |
Signature HMAC tidak cocok. |
| 401 | invalid_project_credentials |
Invalid project credentials. |
app_id atau secret tidak valid. |
| 403 | project_inactive |
Project is inactive. |
Project ditemukan tetapi sedang nonaktif. |
| 409 | order_id_conflict |
Order ID sudah pernah digunakan dengan payload yang berbeda. |
Charge duplikat dikirim dengan payload berbeda. |
| 404 | resource_not_found |
Resource not found. |
Resource transaksi tidak ditemukan pada project aktif. |
| 404 | endpoint_not_found |
Endpoint not found. |
Route API tenant tidak tersedia. |
| 403 | - | Invalid signature. |
Signature webhook Midtrans tidak valid. |
| 422 | validation_failed |
The given data was invalid. |
Payload request tidak lolos validasi. |
Contoh cURL
Create charge
curl --request POST \
--url https://payment.naeva.id/api/v1/charge \
--header "Accept: application/json" \
--header "Content-Type: application/json" \
--header "X-App-ID: project_a_prod" \
--header "X-Timestamp: 1760832000" \
--header "X-Payment-Signature: <signature>" \
--data '{
"order_id": "INV-PROJECTA-2026-001",
"gross_amount": 150000,
"customer_details": {
"first_name": "Budi",
"email": "[email protected]"
}
}'
Project profile
curl --request GET \
--url https://payment.naeva.id/api/v1/projects/me \
--header "Accept: application/json" \
--header "X-App-ID: project_a_prod" \
--header "X-Timestamp: 1760832000" \
--header "X-Payment-Signature: <signature>"
Transaction lookup
curl --request GET \
--url "https://payment.naeva.id/api/v1/transactions/lookup?identifier=INV-LOOKUP-001&by=client_order_id" \
--header "Accept: application/json" \
--header "X-App-ID: project_a_prod" \
--header "X-Timestamp: 1760832000" \
--header "X-Payment-Signature: <signature>"
Callback history
curl --request GET \
--url "https://payment.naeva.id/api/v1/transactions/PROJECT-A-PROD-01JY3G0T2T8V40Q0V4K2QJ8G45/callback-history?limit=5" \
--header "Accept: application/json" \
--header "X-App-ID: project_a_prod" \
--header "X-Timestamp: 1760832000" \
--header "X-Payment-Signature: <signature>"