TikiPay logo TikiPayPayment Automation
Home Pricing Demo Sandbox API Documentation Transaction Verification API Compatibility Apps & Plugins About TikiPay Blog FAQ Terms & Conditions Privacy Policy
TIKIPAY DEVELOPER PLATFORM

Create invoices & verify payment status

Use TikiPay from your backend to create hosted payment sessions, redirect customers, receive callbacks and verify the final payment status before fulfillment.

Base URLhttp://payment.tikipay.in
Create EndpointPOST /api/payment/create
Verify EndpointPOST /api/payment/verify
Preferred AuthAPI-KEY
5-MINUTE SETUP

Quick Start

1Buy/activate a planChoose the plan that matches your websites and automation requirements.
2Create a BrandDashboard → Brands → Create Brand, then copy the Brand API Key.
3Set API Base URLUse the payment/API host where your TikiPay payment script is installed.
4Create paymentCall Create from your backend and save the returned invoice_id.
5Redirect customerOpen the returned payment_url in the browser.
6Verify before deliveryCall Verify from your backend and fulfill only when status is COMPLETED.

Minimal cURL example

REQUEST
curl -X POST "http://payment.tikipay.in/api/payment/create" \ -H "Content-Type: application/json" \ -H "API-KEY: YOUR_BRAND_API_KEY" \ -d '{ "cus_name": "John Doe", "cus_email": "john@example.com", "amount": 1200, "success_url": "https://merchant.example/payment/success", "cancel_url": "https://merchant.example/payment/cancel", "webhook_url": "https://merchant.example/api/tikipay/webhook", "metadata": {"order_id":"ORDER-1001"} }'
BASIC TO ADVANCED

Complete Payment Integration Flow

Follow this sequence from the first local order to final fulfillment. Every step is arranged vertically so developers can read and implement the integration without horizontal scrolling.

01
Create your local order firstGenerate your own order ID in your database and keep the order in PENDING. Do not mark it paid yet.
02
Call TikiPay Create from your backendSend amount, customer details, success/cancel URLs, webhook URL and your order reference in metadata. Authenticate with the Brand API Key.
03
Save the returned invoice IDStore invoice_id against your local order. This is the safest reference to use when you verify later.
04
Redirect the customer to payment_urlThe customer completes payment on the hosted TikiPay checkout page. Your API key must never be exposed in this browser redirect.
05
Receive return URL and/or webhookThe browser return is useful for customer experience. The webhook is useful for automation. Neither should be your only source of truth.
06
Call Verify from your backendSend invoice_id or transaction_id to TikiPay Verify using the Brand API Key. This is the authoritative backend check.
07
Handle COMPLETED / PENDING / ERRORCOMPLETED = fulfill once. PENDING = keep open and re-check later. ERROR = do not fulfill.
08
Make fulfillment idempotentStore the TikiPay invoice/transaction reference. If a webhook or return is repeated, the same order must never be delivered twice.
09
Log and reconcileKeep the invoice ID, transaction ID, payment method, amount, status and your local order reference for support, refunds and reconciliation.
Recommended architecture Browser/mobile app -> Your backend -> TikiPay API. The Brand API Key stays on your backend. The customer only receives the hosted payment URL.
CREDENTIALS

Brand API Key vs Device Key

WEBSITE / SERVER

Brand API Key

Use this key on your website/server for Create, Verify and compatible payment API routes. Create it from Dashboard → Brands.

API-KEY: YOUR_BRAND_API_KEY
MOBILE / SMS CONNECTOR

Device Key

Use this key only for the TikiPay device/SMS connector that forwards eligible payment information into your TikiPay account. Do not use a Device Key as the website payment API key.

Device Key → Dashboard → Devices
Keep secrets server-sideNever put a Brand API Key in browser JavaScript, public HTML, Git repositories or an Android APK. Browser/mobile clients should call your backend; your backend calls TikiPay.
PAYMENT API

Create Invoice

Create a hosted payment session from your server. Save the returned invoice_id, then redirect your customer to payment_url.

POST http://payment.tikipay.in/api/payment/create
AuthenticationAPI-KEY: YOUR_BRAND_API_KEY
Content Typeapplication/json
Store locallySave the returned invoice_id with your order.

Request fields

FieldTypeRequiredDescription
amountnumberYesPayment amount. Must be greater than 0 and within the configured limit.
success_urlURLYesBrowser return URL after checkout.
cus_namestringRecommendedCustomer name.
cus_emailstringRecommendedCustomer email.
cancel_urlURLRecommendedCancel/failure destination. If omitted, TikiPay can fall back to the success URL.
webhook_urlURLRecommendedYour server callback endpoint for payment automation.
metadataobjectNoYour own references such as order_id, user_id or product_id.
return_typeGET/POSTNoOptional return style for compatible checkout routes.

Request examples

Choose your backend language. These examples all create the same TikiPay payment session. JavaScript examples are intended for a trusted server runtime - never expose the Brand API Key in public browser code.

curl -X POST "http://payment.tikipay.in/api/payment/create" \ -H "Content-Type: application/json" \ -H "API-KEY: YOUR_BRAND_API_KEY" \ -d '{ "cus_name": "John Doe", "cus_email": "john@example.com", "amount": 1200, "success_url": "https://merchant.example/payment/success", "cancel_url": "https://merchant.example/payment/cancel", "webhook_url": "https://merchant.example/api/tikipay/webhook", "metadata": { "order_id": "ORDER-1001" } }'
const response = await fetch("http://payment.tikipay.in/api/payment/create", { method: "POST", headers: { "Content-Type": "application/json", "API-KEY": process.env.TIKIPAY_API_KEY }, body: JSON.stringify({ cus_name: "John Doe", cus_email: "john@example.com", amount: 1200, success_url: "https://merchant.example/payment/success", cancel_url: "https://merchant.example/payment/cancel", webhook_url: "https://merchant.example/api/tikipay/webhook", metadata: { order_id: "ORDER-1001" } })
});
const data = await response.json();
if (!response.ok || !data.payment_url) { throw new Error(data.message || "Unable to create payment");
}
console.log(data.invoice_id);
console.log(data.payment_url);
<?php
$payload = [ "cus_name" => "John Doe", "cus_email" => "john@example.com", "amount" => 1200, "success_url" => "https://merchant.example/payment/success", "cancel_url" => "https://merchant.example/payment/cancel", "webhook_url" => "https://merchant.example/api/tikipay/webhook", "metadata" => [ "order_id" => "ORDER-1001" ]
];
$ch = curl_init("http://payment.tikipay.in/api/payment/create");
curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ "Content-Type: application/json", "API-KEY: YOUR_BRAND_API_KEY" ], CURLOPT_POSTFIELDS => json_encode($payload)
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$data = json_decode($response, true);
if ($httpCode >= 400 || empty($data["payment_url"])) { throw new RuntimeException($data["message"] ?? "Unable to create payment");
}
$invoiceId = $data["invoice_id"];
$paymentUrl = $data["payment_url"];
<?php
use Illuminate\Support\Facades\Http;
$response = Http::withHeaders([ "API-KEY" => config("services.tikipay.key"),
])->acceptJson()->post("http://payment.tikipay.in/api/payment/create", [ "cus_name" => "John Doe", "cus_email" => "john@example.com", "amount" => 1200, "success_url" => route("payment.success"), "cancel_url" => route("payment.cancel"), "webhook_url" => route("tikipay.webhook"), "metadata" => [ "order_id" => "ORDER-1001" ],
]);
$response->throw();
$invoiceId = $response->json("invoice_id");
$paymentUrl = $response->json("payment_url");
return redirect()->away($paymentUrl);
import os
import requests
payload = { "cus_name": "John Doe", "cus_email": "john@example.com", "amount": 1200, "success_url": "https://merchant.example/payment/success", "cancel_url": "https://merchant.example/payment/cancel", "webhook_url": "https://merchant.example/api/tikipay/webhook", "metadata": { "order_id": "ORDER-1001" }
}
response = requests.post( "http://payment.tikipay.in/api/payment/create", headers={ "Content-Type": "application/json", "API-KEY": os.environ["TIKIPAY_API_KEY"] }, json=payload, timeout=20
)
response.raise_for_status()
data = response.json()
invoice_id = data["invoice_id"]
payment_url = data["payment_url"]
const https = require("https");
const payload = JSON.stringify({ cus_name: "John Doe", cus_email: "john@example.com", amount: 1200, success_url: "https://merchant.example/payment/success", cancel_url: "https://merchant.example/payment/cancel", webhook_url: "https://merchant.example/api/tikipay/webhook", metadata: { order_id: "ORDER-1001" }
});
const url = new URL("http://payment.tikipay.in/api/payment/create");
const req = https.request({ hostname: url.hostname, path: url.pathname, method: "POST", headers: { "Content-Type": "application/json", "Content-Length": Buffer.byteLength(payload), "API-KEY": process.env.TIKIPAY_API_KEY }
}, (res) => { let body = ""; res.on("data", chunk => body += chunk); res.on("end", () => { const data = JSON.parse(body); if (res.statusCode >= 400 || !data.payment_url) { throw new Error(data.message || "Unable to create payment"); } console.log(data.invoice_id); console.log(data.payment_url); });
});
req.on("error", console.error);
req.write(payload);
req.end();
SUCCESS RESPONSE
{ "status": 1, "message": "Payment Link", "payment_url": "http://payment.tikipay.in/api/execute/SESSION_ID", "invoice_id": "SESSION_ID"
}
Next step: redirect the customerAfter you save invoice_id, send the browser to payment_url. When the customer returns, verify from your backend before fulfilling the order.
BACKEND CHECK

Verify Payment

Verify from your backend before you mark an order paid. You can send either invoice_id or transaction_id. The invoice ID returned by Create is the recommended reference.

POST http://payment.tikipay.in/api/payment/verify
Recommended lookupinvoice_id
Alternative lookuptransaction_id
Fulfill only whenstatus = COMPLETED

Request examples

curl -X POST "http://payment.tikipay.in/api/payment/verify" \ -H "Content-Type: application/json" \ -H "API-KEY: YOUR_BRAND_API_KEY" \ -d '{ "invoice_id": "SESSION_ID" }'
const response = await fetch("http://payment.tikipay.in/api/payment/verify", { method: "POST", headers: { "Content-Type": "application/json", "API-KEY": process.env.TIKIPAY_API_KEY }, body: JSON.stringify({ invoice_id: "SESSION_ID" })
});
const payment = await response.json();
if (!response.ok) { throw new Error(payment.message || "Verification failed");
}
if (payment.status === "COMPLETED") { // Mark the local order paid exactly once.
} else if (payment.status === "PENDING") { // Keep the local order open and retry later.
} else { // Do not fulfill.
}
<?php
$ch = curl_init("http://payment.tikipay.in/api/payment/verify");
curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ "Content-Type: application/json", "API-KEY: YOUR_BRAND_API_KEY" ], CURLOPT_POSTFIELDS => json_encode([ "invoice_id" => "SESSION_ID" ])
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$payment = json_decode($response, true);
if ($httpCode >= 400) { throw new RuntimeException($payment["message"] ?? "Verification failed");
}
if (($payment["status"] ?? "") === "COMPLETED") { // Mark order paid once.
}
<?php
use Illuminate\Support\Facades\Http;
$response = Http::withHeaders([ "API-KEY" => config("services.tikipay.key"),
])->acceptJson()->post("http://payment.tikipay.in/api/payment/verify", [ "invoice_id" => $order->tikipay_invoice_id,
]);
$response->throw();
$payment = $response->json();
if (($payment["status"] ?? null) === "COMPLETED") { DB::transaction(function () use ($order, $payment) { if (!$order->is_paid) { $order->update([ "is_paid" => true, "transaction_id" => $payment["transaction_id"] ?? null, ]); } });
}
import os
import requests
response = requests.post( "http://payment.tikipay.in/api/payment/verify", headers={ "Content-Type": "application/json", "API-KEY": os.environ["TIKIPAY_API_KEY"] }, json={ "invoice_id": "SESSION_ID" }, timeout=20
)
response.raise_for_status()
payment = response.json()
if payment["status"] == "COMPLETED": # Mark the local order paid exactly once. pass
elif payment["status"] == "PENDING": # Retry later. pass
else: # Do not fulfill. pass
const https = require("https");
const payload = JSON.stringify({ invoice_id: "SESSION_ID"
});
const url = new URL("http://payment.tikipay.in/api/payment/verify");
const req = https.request({ hostname: url.hostname, path: url.pathname, method: "POST", headers: { "Content-Type": "application/json", "Content-Length": Buffer.byteLength(payload), "API-KEY": process.env.TIKIPAY_API_KEY }
}, (res) => { let body = ""; res.on("data", chunk => body += chunk); res.on("end", () => { const payment = JSON.parse(body); if (payment.status === "COMPLETED") { // Mark the order paid exactly once. } });
});
req.on("error", console.error);
req.write(payload);
req.end();
SUCCESS RESPONSE
{ "cus_name": "John Doe", "cus_email": "john@example.com", "amount": 1200, "invoice_id": "SESSION_ID", "transaction_id": "TXN123456789", "metadata": { "order_id": "ORDER-1001" }, "payment_method": "bkash", "status": "COMPLETED"
}

How to decide what your website should do

COMPLETEDPayment verified. Mark your local order paid and fulfill exactly once.
PENDINGPayment is not final yet. Keep the order open and verify again later.
ERRORVerification failed or payment is not payable. Do not fulfill.
Never trust only the success URL A customer can open, refresh or manually revisit a return URL. Your backend Verify response is the authoritative check before fulfillment.
AUTOMATION

Webhook & Return Flow

Use the browser return for customer experience and the webhook for automation. Always finish by verifying the payment server-to-server.

01
Customer completes checkoutTikiPay processes the selected payment method.
02
TikiPay calls webhook_urlYour backend receives the payment notification if a webhook URL was supplied during Create.
03
Store the notificationUse invoice_id and transactionId/transaction_id to locate your local order.
04
Call VerifyDo not fulfill directly from webhook data. Verify the payment through the TikiPay Verify endpoint.
05
Fulfill onceOnly a verified COMPLETED payment should update the order as paid.

Native webhook payload

FORM POST
paymentMethod=bkash
transactionId=TXN123456789
paymentAmount=1200
paymentFee=0
invoice_id=SESSION_ID
status=COMPLETED

Example webhook handler (PHP)

WEBHOOK ENDPOINT
<?php
$invoiceId = $_POST["invoice_id"] ?? null;
if (!$invoiceId) { http_response_code(400); exit("Missing invoice_id");
}
/* * 1. Find the local order by the saved TikiPay invoice ID. * 2. Call TikiPay Verify from your backend. * 3. Fulfill only when Verify returns COMPLETED. * 4. Make the fulfillment idempotent. */
http_response_code(200);
echo "OK";
Webhooks can be retried Design your handler so duplicate webhook deliveries are safe. Store the invoice/transaction reference and never deliver the same order twice.
RESPONSE HANDLING

Status, HTTP Errors & Recovery

A production integration should handle both HTTP-level errors and payment-level statuses.

200Request processed

Read the JSON body. For Verify, inspect status before fulfillment.

400Invalid parameters

Check amount, required URL fields, invoice ID and request JSON.

401Invalid API key

Confirm the Brand API Key and the authentication header.

404Transaction not found

Check the invoice/transaction reference and make sure it belongs to the same TikiPay account.

500Server processing error

Do not fulfill. Log the response and retry safely when appropriate.

TIMEOUTUnknown final state

Do not assume failure or success. Re-run Verify using the saved invoice ID.

Recommended retry logic

Retry Verify for PENDING payments with a reasonable delay.
Use the same invoice ID when checking an existing payment; do not create a new invoice just to check status.
Log HTTP code, response body, invoice ID and local order ID for debugging.
Use database locking/unique constraints or another idempotency strategy before fulfillment.
MIGRATION-FRIENDLY

Existing Integration Compatibility

TikiPay accepts three API shapes. New integrations should use the Native API. Existing compatible integrations can keep their current field mapping and response parser.

NATIVERecommended
Create/api/payment/create
Verify/api/payment/verify
HeaderAPI-KEY
CHECKOUT V2Migration contract
Create/api/checkout-v2
Verify/api/verify-payment
KeyBrand API Key
V1 INVOICEMigration contract
Create/v1/payment/create
Verify/v1/payment/verify
KeyBrand API Key
What usually changes during migration?If the existing integration has a configurable API Base URL, point it to your TikiPay payment host once and paste the TikiPay Brand API Key. If its old API host is hard-coded, the host must be changed once; replacing an API key alone cannot send HTTP traffic to a different server.
Checkout v2 Createhttp://payment.tikipay.in/api/checkout-v2
Checkout v2 Verifyhttp://payment.tikipay.in/api/verify-payment
V1 Createhttp://payment.tikipay.in/v1/payment/create
V1 Verifyhttp://payment.tikipay.in/v1/payment/verify
API, APPS & PLUGINS

Apps, Plugins & Modules

View All Modules

Start with the TikiPay app or install a ready-made integration for your platform. The most commonly used packages are highlighted below; the full library includes SDKs, ecommerce, billing, CRM, SMM, LMS and automation modules.

GO LIVE

Production Checklist

Use HTTPS for merchant return/webhook URLs.
Keep the Brand API Key in encrypted settings or environment variables.
Verify payment from the backend before fulfillment.
Make callbacks idempotent and log invoice/transaction references.
Test completed, pending, cancelled and invalid-key cases.
Use Device Keys only for authorized TikiPay mobile/SMS connectors.
DEBUGGING

Troubleshooting

401 / Invalid API keyConfirm you copied the Brand API Key, not the Device Key, and that the Brand/plan is active.
No payment URLCheck API Base URL, HTTPS, amount, success_url and server outbound cURL/HTTP access.
Return says paid but order is pendingDo not trust browser text. Call Verify using the invoice_id and inspect the backend status.
Old integration does not connectCheck whether its API host is configurable. If the host is hard-coded, change it once or install a TikiPay module.