Create Pay Link
Create a new payment link with specific validity modes.
POST
https://dev.mytpe.app/api/v2/mytpe-pay/links/storeCreates a new payment link for a Mytpe Pay instance.
Authentication: API Key (X-API-KEY + X-API-SECRET headers)
This API requires authentication via X-API-KEY and X-API-SECRET headers.
Constraint: Link Types & Modes
It is critical to understand the relationship between type and payment_mode.
- Dynamic Links: You set a fixed price that the customer must pay. These support all 3 modes (
reusable,one_shot,limited). - Static Links: The customer enters the amount (e.g., Donation). These are always Reusable. You cannot set them to
one_shotorlimited.
Validation Rule
If you send type: "static", the system will ignore any payment_mode or max_payments values you provide. These parameters are only respected when type is dynamic.
Validity & Modes (Dynamic Only)
For Dynamic links, you can define the lifecycle:
reusable(Default): The link never expires. Ideal for e-commerce products.one_shot: The link accepts exactly 1 payment and auto-closes. Ideal for specific invoices.limited: The link accepts a quota defined bymax_payments. Ideal for event tickets.
Body Parameters
Prop
Type
Example Request
const form = new FormData();
form.append('mytpe_pay_id', 'mytpe_pay_xyz789');
form.append('title', 'Limited Offer Product');
form.append('details', 'A special limited edition product.');
form.append('type', 'dynamic');
form.append('amount', '5000.00');
form.append('slug', 'limited-offer');
form.append('payment_mode', 'limited');
form.append('max_payments', '50');
form.append('metadata[internal_id]', 'PROD_123');
form.append('logo', document.querySelector('#logo').files[0]);
const response = await fetch('https://dev.mytpe.app/api/v2/mytpe-pay/links/store', {
method: 'POST',
headers: {
'X-API-KEY': 'your_api_key',
'X-API-SECRET': 'your_api_secret',
},
body: form,
});
const data = await response.json();
console.log(data);interface PayLinkResponse {
success: boolean;
message: string;
data: {
id: string;
title: string;
slug: string;
type: string;
amount: string;
status: string;
payment_mode: string;
max_payments: number | null;
payment_link: string;
payment_status: string;
};
}
const form = new FormData();
form.append('mytpe_pay_id', 'mytpe_pay_xyz789');
form.append('title', 'Limited Offer Product');
form.append('details', 'A special limited edition product.');
form.append('type', 'dynamic');
form.append('amount', '5000.00');
form.append('slug', 'limited-offer');
form.append('payment_mode', 'limited');
form.append('max_payments', '50');
form.append('metadata[internal_id]', 'PROD_123');
const fileInput = document.querySelector<HTMLInputElement>('#logo');
if (fileInput?.files?.[0]) {
form.append('logo', fileInput.files[0]);
}
const response = await fetch('https://dev.mytpe.app/api/v2/mytpe-pay/links/store', {
method: 'POST',
headers: {
'X-API-KEY': 'your_api_key',
'X-API-SECRET': 'your_api_secret',
},
body: form,
});
const data: PayLinkResponse = await response.json();
console.log(data);import requests
url = 'https://dev.mytpe.app/api/v2/mytpe-pay/links/store'
headers = {
'X-API-KEY': 'your_api_key',
'X-API-SECRET': 'your_api_secret',
}
payload = {
'mytpe_pay_id': 'mytpe_pay_xyz789',
'title': 'Limited Offer Product',
'details': 'A special limited edition product.',
'type': 'dynamic',
'amount': '5000.00',
'slug': 'limited-offer',
'payment_mode': 'limited',
'max_payments': '50',
'metadata[internal_id]': 'PROD_123',
}
files = {
'logo': ('logo.png', open('/path/to/logo.png', 'rb'), 'image/png'),
}
response = requests.post(url, headers=headers, data=payload, files=files)
data = response.json()
print(data)use Illuminate\Support\Facades\Http;
$response = Http::withHeaders([
'X-API-KEY' => 'your_api_key',
'X-API-SECRET' => 'your_api_secret',
])
->attach('logo', file_get_contents('/path/to/logo.png'), 'logo.png')
->post('https://dev.mytpe.app/api/v2/mytpe-pay/links/store', [
'mytpe_pay_id' => 'mytpe_pay_xyz789',
'title' => 'Limited Offer Product',
'details' => 'A special limited edition product.',
'type' => 'dynamic',
'amount' => '5000.00',
'slug' => 'limited-offer',
'payment_mode' => 'limited',
'max_payments' => 50,
'metadata' => ['internal_id' => 'PROD_123'],
]);
$data = $response->json();<?php
$curl = curl_init();
$boundary = uniqid();
$delimiter = '-------------' . $boundary;
$postData = '';
$fields = [
'mytpe_pay_id' => 'mytpe_pay_xyz789',
'title' => 'Limited Offer Product',
'details' => 'A special limited edition product.',
'type' => 'dynamic',
'amount' => '5000.00',
'slug' => 'limited-offer',
'payment_mode' => 'limited',
'max_payments' => '50',
'metadata[internal_id]' => 'PROD_123',
];
foreach ($fields as $name => $value) {
$postData .= "--{$delimiter}\r\n";
$postData .= "Content-Disposition: form-data; name=\"{$name}\"\r\n\r\n";
$postData .= "{$value}\r\n";
}
$postData .= "--{$delimiter}\r\n";
$postData .= "Content-Disposition: form-data; name=\"logo\"; filename=\"logo.png\"\r\n";
$postData .= "Content-Type: image/png\r\n\r\n";
$postData .= file_get_contents('/path/to/logo.png') . "\r\n";
$postData .= "--{$delimiter}--\r\n";
curl_setopt_array($curl, [
CURLOPT_URL => 'https://dev.mytpe.app/api/v2/mytpe-pay/links/store',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => $postData,
CURLOPT_HTTPHEADER => [
'X-API-KEY: your_api_key',
'X-API-SECRET: your_api_secret',
'Content-Type: multipart/form-data; boundary=' . $delimiter,
],
]);
$response = curl_exec($curl);
curl_close($curl);
echo $response;const axios = require('axios');
const FormData = require('form-data');
const fs = require('fs');
const form = new FormData();
form.append('mytpe_pay_id', 'mytpe_pay_xyz789');
form.append('title', 'Limited Offer Product');
form.append('details', 'A special limited edition product.');
form.append('type', 'dynamic');
form.append('amount', '5000.00');
form.append('slug', 'limited-offer');
form.append('payment_mode', 'limited');
form.append('max_payments', '50');
form.append('metadata[internal_id]', 'PROD_123');
form.append('logo', fs.createReadStream('/path/to/logo.png'));
axios.post('https://dev.mytpe.app/api/v2/mytpe-pay/links/store', form, {
headers: {
...form.getHeaders(),
'X-API-KEY': 'your_api_key',
'X-API-SECRET': 'your_api_secret',
},
})
.then(response => console.log(response.data))
.catch(error => console.error(error.response?.data));Example Success Response (201 Created)
201 Created
{
"success": true,
"message": "Pay link created successfully",
"data": {
"mytpe_pay_id": "instance-001",
"title": "Demo Product",
"details": "A detailed description of the demo product.",
"slug": "demo-product",
"type": "dynamic",
"amount": "2500.00",
"status": "active",
"logo": null,
"payment_mode": "reusable",
"max_payments": null,
"successful_payments_count": 0,
"metadata": {
"internal_reference": "REF-123"
},
"id": "link-demo-123",
"updated_at": "2026-01-17T10:00:00.000Z",
"created_at": "2026-01-17T10:00:00.000Z",
"payment_link": "https://frontdev.mytpe.app/pay/demo-product",
"payment_status": "active",
"remaining_payments": null
}
}Understanding payment_status
Newly created links will have one of these payment_status values:
active: Reusable or limited links ready to accept paymentsawaiting_payment: One-shot links waiting for their first payment
The payment_status field automatically updates based on payment activity and helps you track the payment state of each link.
Error Responses
422 Validation Error
{
"message": "The given data was invalid.",
"errors": {
"slug": ["The slug has already been taken."],
"amount": ["The amount field is required when type is dynamic."]
}
}