N payment.naeva.id Centralized payment gateway service
Dokumentasi API Publik

Dokumentasi integrasi `payment.naeva.id` untuk seluruh project internal Naeva.

Halaman ini dapat diakses publik untuk mempermudah integrasi antar-server. Seluruh contoh di bawah mengikuti implementasi yang aktif saat ini, termasuk autentikasi HMAC, readiness profile tenant, lookup transaksi fleksibel, callback history, webhook Midtrans, dan callback forwarding ke project asal.

Base URL https://payment.naeva.id/api/v1
Auth Utama HMAC per request dengan X-App-ID, X-Timestamp, dan X-Payment-Signature.
Callback Forwarding status pembayaran diproses async melalui queue, memiliki retry operasional, dan delivery metadata.

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);
Request timestamp harus berupa Unix timestamp dan saat ini diverifikasi dengan toleransi sekitar 300 detik terhadap waktu server.

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."
        }
      ]
    }
  }
}
Endpoint ini cocok dipanggil pertama kali saat provisioning integrasi baru, karena tenant bisa langsung membaca header auth, endpoint penting, retry callback, dan status readiness dari satu response.

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_id wajib dan merepresentasikan ID order dari client app.
  • gross_amount wajib, integer, minimal 1.
  • customer_details wajib, minimal berisi first_name.
  • custom_callback_url opsional untuk override callback URL default project.
  • expires_at opsional 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

  • identifier wajib, nilai yang ingin dicari.
  • by opsional, nilai auto, gateway_order_id, atau client_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"
    }
  }
}
Untuk request 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_id wajib, ID transaksi internal yang dikembalikan saat endpoint POST /charge berhasil.

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

  • limit opsional, integer 1-20, default 5.

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.

URL yang bisa dipakai pada konfigurasi Midtrans: 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 POST di server Anda, misalnya https://client-app.example.com/api/payment/callback.
  • Simpan App ID dan Secret Key project Anda dari dashboard.
  • Isi default_callback_url pada project, atau kirim custom_callback_url saat membuat charge.
  • Pastikan endpoint Anda bisa menerima request JSON dan membalas HTTP 2xx saat 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."
}
Jika endpoint Anda membalas non-2xx atau timeout, callback akan dianggap gagal dan akan dijadwalkan ulang otomatis dengan backoff 60, 300, lalu 900 detik.

Status dan Error

Status transaksi

  • pending
  • settlement
  • failed
  • expired
  • cancelled
  • refunded

Status callback

  • pending
  • queued
  • success
  • failed
  • skipped

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>"