🚀 TemanQRIS API Documentation

RESTful API untuk mengkonversi QRIS statis menjadi QRIS dinamis dengan nominal custom, fee, dan payment link yang bisa di-share.

Base URL: https://temanqris.com/api/qris
🔔
NEW in v1.2: Webhook & Callback!

Terima notifikasi real-time saat status pembayaran berubah. Lihat dokumentasi →

Authentication

Semua API endpoint memerlukan autentikasi. Gunakan API Key yang bisa Anda dapatkan dari Dashboard Settings.

API Key

Gunakan API Key untuk semua request ke TemanQRIS API.

X-API-Key: YOUR_API_KEY
Keamanan API Key
Jangan pernah expose API Key di frontend atau commit ke repository. Gunakan environment variables.

Quick Start

Tiga langkah untuk mulai menggunakan TemanQRIS API:

1

Upload QRIS Statis

Upload gambar atau string QRIS statis Anda (sekali saja)

2

Generate QRIS Dinamis

Buat QRIS dengan nominal kapan saja

3

Share atau Embed

Gunakan payment link atau embed widget

Rate Limits

Batas request harian berdasarkan tier akun:

Tier Daily Limit Stored QRIS Features
Free 50 requests/day 1 QRIS Basic features
Premium 1000 requests/day Unlimited* All features + Priority support
Gunakan endpoint GET /api/qris/usage untuk monitoring penggunaan API real-time.

Upload Static QRIS

Upload QRIS statis Anda. Ini hanya perlu dilakukan SEKALI saja.

Penting!

Upload QRIS statis hanya diperlukan sekali saat pertama kali setup. Setelah berhasil upload, Anda bisa langsung menggunakan endpoint /generate untuk membuat QRIS dinamis tanpa perlu upload ulang. Gunakan endpoint /my-qris untuk mengecek apakah Anda sudah pernah upload QRIS.

POST /upload Upload QRIS image or string (one-time only)

Option 1: Upload Image

Upload file gambar QRIS (jpg, png, webp)

# Upload image file
curl -X POST https://temanqris.com/api/qris/upload \
  -H "X-API-Key: YOUR_API_KEY" \
  -F "qris_image=@/path/to/qris.png"

Option 2: Upload String

Jika sudah punya QRIS string (hasil decode)

# Upload QRIS string
curl -X POST https://temanqris.com/api/qris/upload \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "qris_string": "00020101021126670016COM.NOBUBANK.WWW..."
  }'

Response

200 OK
{
  "message": "QRIS uploaded successfully",
  "qris_string": "00020101021126...",
  "merchant": {
    "name": "TOKO EXAMPLE",
    "city": "JAKARTA"
  }
}

Check QRIS Status

Cek apakah Anda sudah pernah upload QRIS statis. Gunakan sebelum memanggil /upload untuk menghindari upload yang tidak perlu.

GET /my-qris Check if QRIS has been uploaded

Request

# Check QRIS status
curl -X GET https://temanqris.com/api/qris/my-qris \
  -H "X-API-Key: YOUR_API_KEY"

Response (QRIS exists)

200 OK
{
  "success": true,
  "has_qris": true,
  "qris": {
    "id": 123,
    "qris_string": "00020101021126...",
    "merchant_name": "TOKO EXAMPLE",
    "merchant_city": "JAKARTA",
    "created_at": "2024-01-15T10:30:00Z",
    "updated_at": "2024-01-15T10:30:00Z"
  }
}

Response (No QRIS yet)

200 OK
{
  "success": true,
  "has_qris": false,
  "message": "No QRIS found. Please upload your static QRIS first (only needed once)."
}

Generate Dynamic QRIS

Endpoint utama untuk membuat QRIS dinamis dengan nominal transaksi.

POST /generate Generate QRIS with amount

Request Body

Field Type Description
amount number required Nominal transaksi (contoh: 50000)
fee_type string optional "rupiah" atau "percent"
fee_value number optional Nilai fee yang ditambahkan
qris_id number optional ID QRIS spesifik (jika punya multiple)
order_id string optional ID unik order Anda (max 30 chars). Auto-generate jika kosong.
webhook_url string optional URL untuk menerima notifikasi webhook saat status berubah.
callback_url string optional URL redirect customer setelah klik "Sudah Bayar".

Example Request

# Generate QRIS Rp 50.000 + fee Rp 1.000 with webhook
curl -X POST https://temanqris.com/api/qris/generate \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 50000,
    "fee_type": "rupiah",
    "fee_value": 1000,
    "order_id": "INV-2025-001",
    "webhook_url": "https://yoursite.com/webhook"
  }'

Response

200 OK
{
  "success": true,
  "qris": "00020101021226...",
  "qr_image": "data:image/png;base64,...",
  "amount": 50000,
  "fee": { "type": "rupiah", "value": 1000 },
  "expires_at": "2025-12-25T10:00:00.000Z",
  "payment_link": {
    "id": 456,
    "link_code": "BTN3EV2X",
    "order_id": "INV-2025-001",
    "url": "/p/BTN3EV2X",
    "amount": 50000,
    "merchant_name": "TOKO EXAMPLE",
    "webhook_url": "https://yoursite.com/webhook",
    "expires_at": "2025-12-26T10:00:00.000Z"
  }
}
Field qr_image berisi Base64 image yang bisa langsung ditampilkan dengan <img src="...">

Render QR Image

Generate gambar QR code dari string QRIS.

POST /render Render QR from string

Provide either qris_string or qris_data_id.

Option 1: Using String

curl -X POST https://temanqris.com/api/qris/render \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "qris_string": "00020101021126..."
  }'

Option 2: Using Saved ID

Jika sudah punya QRIS yang tersimpan (dari /my-qris), cukup kirim ID-nya.

curl -X POST https://temanqris.com/api/qris/render \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "qris_data_id": 123
  }'

Response

{
  "success": true,
  "qr_image": "data:image/png;base64,iVBOR..."
}

Check Order Status

Cek status pembayaran order/payment link via API. Berguna untuk integrasi backend-to-backend.

GET /orders/:orderId Check single order status

Request

# Check specific order by order_id
curl -X GET https://temanqris.com/api/qris/orders/ORD-ABC123 \
  -H "X-API-Key: YOUR_API_KEY"

Response

200 OK

Order Status Definitions

Status Description
pending Menunggu pembayaran dari customer.
awaiting_confirmation Pembayaran dikonfirmasi customer (widget), menunggu verifikasi.
Pembayaran berhasil dan terverifikasi.
expired Batas waktu pembayaran telah habis.
cancelled Order dibatalkan.
{
  "success": true,
  "order": {
    "order_id": "ORD-ABC123",
    "title": "Pembayaran Invoice #001",
    "amount": 50000,
    "total_amount": 51000,
    "status": "paid",
    "is_paid": true,
    "is_expired": false,
    "created_at": "2024-01-15T10:30:00Z",
    "paid_at": "2024-01-15T10:35:00Z"
  }
}
GET /orders List all orders with pagination

Query Parameters

Parameter Type Description
status string Filter by status: pending, paid, expired, cancelled
limit number Max results (default: 20)
offset number Offset for pagination

Request

# Get all paid orders
curl -X GET "https://temanqris.com/api/qris/orders?status=paid&limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

Response

200 OK
{
  "success": true,
  "orders": [
    {
      "order_id": "ORD-ABC123",
      "title": "Invoice #001",
      "amount": 50000,
      "status": "paid",
      "is_paid": true
    }
  ],
  "pagination": {
    "total": 25,
    "limit": 10,
    "offset": 0
  }
}

Verify Order (Merchant)

Verifikasi pembayaran order via API. Merchant bisa langsung mark order sebagai paid tanpa perlu buka dashboard.

💡 Use Case: Setelah customer klik "Sudah Bayar" (status = awaiting_confirmation), merchant bisa verifikasi via API dan otomatis update ke paid.
POST /orders/:orderId/verify Verify payment as paid

URL Parameter

Parameter Type Description
orderId string Required. Order ID Anda (e.g., INV-2025-001)

Request Body (optional)

Field Type Description
payer_name string optional Nama pembayar
payer_note string optional Catatan pembayaran

Request

# Verify order as paid
curl -X POST https://temanqris.com/api/qris/orders/INV-2025-001/verify \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "payer_name": "John Doe",
    "payer_note": "Pembayaran via OVO"
  }'

Response

200 OK
{
  "success": true,
  "message": "Payment verified successfully",
  "order": {
    "order_id": "INV-2025-001",
    "amount": 75000,
    "status": "paid",
    "paid_at": "2025-12-27T16:30:00.000Z",
    "confirmed_by": "api"
  }
}

Error Responses

404 Not Found
{
  "success": false,
  "error": "Order not found",
  "message": "No order found with order_id \"INV-999\" for your account."
}
400 Bad Request
{
  "success": false,
  "error": "Order already verified",
  "message": "This order has already been marked as paid."
}

Integration Flow

  1. Buat payment link via POST /api/qris/payment-link atau POST /api/qris/generate
  2. Share link ke customer
  3. Customer scan QRIS dan bayar
  4. Customer klik "Sudah Bayar" → status = awaiting_confirmation
  5. Terima webhook payment.awaiting_confirmation 🔔
  6. Cek status via GET /api/qris/orders/:orderId
  7. Verifikasi dana masuk di e-wallet/rekening
  8. Call POST /api/qris/orders/:orderId/verify → status = paid

Cancel Order

Batalkan order/payment link yang belum dibayar.

POST /orders/:orderId/cancel Cancel an order

Request

# Cancel an order
curl -X POST https://temanqris.com/api/qris/orders/INV-2025-001/cancel \
  -H "X-API-Key: YOUR_API_KEY"

Response

200 OK
{
  "success": true,
  "message": "Order cancelled successfully",
  "order": {
    "order_id": "INV-2025-001",
    "status": "cancelled"
  }
}

Error Responses

400 Bad Request
{
  "success": false,
  "error": "Cannot cancel paid order",
  "message": "This order has already been verified as paid and cannot be cancelled."
}

Webhooks

Terima notifikasi real-time saat status pembayaran berubah. Webhook dikirim ke URL yang Anda tentukan saat membuat payment link.

Event Types

Event Trigger Description
payment.awaiting_confirmation Customer klik "Sudah Bayar" Customer mengklaim sudah bayar, menunggu verifikasi Anda
payment.confirmed Merchant approve di Dashboard atau via API Pembayaran sudah diverifikasi dan dikonfirmasi (via POST /orders/:orderId/verify atau Dashboard)

Webhook Payload

{
  "event": "payment.awaiting_confirmation",
  "timestamp": "2025-12-27T16:00:00.000Z",
  "data": {
    "order_id": "INV-2025-001",
    "link_code": "ABC12345",
    "amount": 75000,
    "description": "Pembayaran Order #12345",
    "status": "awaiting_confirmation",
    "paid_at": null,
    "created_at": "2025-12-27T15:55:00.000Z"
  }
}

Webhook Headers

Header Description
X-TemanQRIS-Signature HMAC-SHA256 signature untuk verifikasi (format: sha256=...)
X-TemanQRIS-Event Nama event (e.g. payment.awaiting_confirmation)
X-TemanQRIS-Retry Nomor retry (jika sebelumnya gagal)

Verifikasi Signature (Node.js)

const crypto = require('crypto');

function verifyWebhook(payload, signature, secret) {
  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(JSON.stringify(payload))
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

// Contoh penggunaan di Express
app.post('/webhook', (req, res) => {
  const signature = req.headers['x-temanqris-signature'];
  const isValid = verifyWebhook(req.body, signature, 'YOUR_WEBHOOK_SECRET');

  if (!isValid) {
    return res.status(401).json({ error: 'Invalid signature' });
  }

  // Process webhook...
  if (req.body.event === 'payment.confirmed') {
    // Update order status di database Anda
  }

  res.json({ received: true });
});
Retry Policy: Jika webhook gagal (non-2xx response), kami akan retry hingga 3 kali dengan interval: 30 detik → 2 menit → 10 menit.

Customer Sudah Bayar (Public)

API publik untuk mencatat bahwa customer mengklaim sudah membayar. Status transaksi akan berubah menjadi awaiting_confirmation dan merchant perlu memverifikasi di dashboard.

⚠️ Ini BUKAN konfirmasi pembayaran!
Endpoint ini hanya mengubah status ke awaiting_confirmation. Merchant tetap harus verifikasi manual bahwa dana sudah masuk di e-wallet/rekening mereka.

🔓 Public API - Tidak Perlu API Key

Endpoint ini dipanggil dari frontend saat customer klik tombol "Sudah Bayar" di halaman pembayaran.

POST /api/pay/:link_code/confirm Customer claims payment done

URL Parameter

Parameter Type Description
link_code string Required. Kode payment link (e.g., ABC12345)

Request

# Customer confirms payment via link code
curl -X POST https://temanqris.com/api/pay/ABC12345/confirm \
  -H "Content-Type: application/json"

JavaScript Example

// Call from payment page after customer finishes paying
const linkCode = 'ABC12345';

fetch(`/api/pay/${linkCode}/confirm`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' }
})
.then(res => res.json())
.then(data => {
    if (data.success) {
        alert('Konfirmasi pembayaran berhasil!');
    }
});

Response

200 OK
{
  "success": true,
  "message": "Konfirmasi pembayaran berhasil dikirim",
  "order_id": "ORD-ABC12345XYZ",
  "status": "awaiting_confirmation"
}

Flow Explanation

  1. Customer membuka halaman pembayaran (/p/ABC12345)
  2. Customer scan QRIS dan melakukan pembayaran di e-wallet
  3. Customer klik tombol "Sudah Bayar"
  4. Frontend memanggil POST /api/pay/ABC12345/confirm
  5. Status berubah menjadi awaiting_confirmation (belum confirmed!)
  6. 🔔 Webhook dikirim ke URL yang di-configure (jika ada)
  7. 📩 Merchant menerima Email Notifikasi
  8. 🔗 Customer di-redirect ke callback_url (jika ada)
  9. Merchant verifikasi manual di dashboard atau e-wallet
  10. Setelah verifikasi, merchant approve via API atau Dashboard → status = paid

Error Response

404 Not Found
{
  "error": "Link pembayaran tidak ditemukan"
}

API Usage Statistics

Monitor penggunaan API dan sisa limit Anda.

GET /usage Get usage statistics
curl https://temanqris.com/api/qris/usage \
  -H "X-API-Key: YOUR_API_KEY"

Response

{
  "tier": "free",
  "daily_limit": 100,
  "usage": {
    "today": {
      "total": 15,
      "remaining": 85,
      "by_endpoint": [
        { "endpoint": "/qris/generate", "request_count": 10 },
        { "endpoint": "/qris/payment-link", "request_count": 5 }
      ]
    },
    "this_month": {
      "total": 250,
      "by_endpoint": [...]
    }
  }
}

Embed Widget (widget.js)

Pasang tombol pembayaran QRIS di website Anda dengan satu baris kode. Widget akan menampilkan modal pembayaran yang cantik dan responsif.

EMBED widget.js Embeddable payment button

Installation

Tambahkan kode ini di halaman website Anda:

<script 
  src="https://temanqris.com/widget.js" 
  data-merchant="YOUR_MERCHANT_ID"
></script>

💡 Mendapatkan Merchant ID: Login ke Dashboard → Widget untuk melihat Merchant ID Anda.

Result

Widget akan otomatis menampilkan tombol seperti ini:

Bayar dengan QRIS

Preview tombol widget

Widget Options

Kustomisasi widget sesuai kebutuhan Anda dengan data attributes:

Attribute Type Description
data-merchant string * Merchant ID Anda (wajib)
data-amount number Nominal tetap (jika tidak diisi, user bisa input sendiri)
data-button-text string Teks tombol (default: "Bayar dengan QRIS")
data-button-color string Warna tombol dalam hex (default: "#ff6b35")
data-description string Deskripsi pembayaran (opsional)
data-callback string (URL) Callback URL - Redirect browser customer setelah klik "Sudah Bayar". Query params: order_id, amount, status
data-webhook string (URL) 🔔 Webhook URL - Notifikasi server-to-server saat status berubah (untuk update database)

Full Example with Callback & Webhook

<script 
  src="https://temanqris.com/widget.js" 
  data-merchant="abc123xyz"
  data-amount="50000"
  data-button-text="Bayar Sekarang"
  data-button-color="#22c55e"
  data-description="Pembayaran Order #123"
  data-callback="https://yoursite.com/thank-you"
  data-webhook="https://yoursite.com/webhook"
></script>

🔗 Callback URL (data-callback): Customer di-redirect ke URL setelah klik "Sudah Bayar":
https://yoursite.com/thank-you?order_id=xxx&amount=50000&status=confirmed

🔔 Webhook URL (data-webhook): Server TemanQRIS akan mengirim POST request ke URL Anda dengan payload JSON:
{ "event": "payment.awaiting_confirmation", "order_id": "xxx", ... }
Lihat dokumentasi webhook untuk verifikasi signature.

⚠️ Catatan Keamanan: Jangan tampilkan Merchant ID di repositori publik. Widget ini aman digunakan di frontend karena pembayaran diproses via server TemanQRIS.