Use the Payment Links API to create and manage shareable checkout links that customers can use to pay for a specific order, customer, or transaction.
Payment Links are the successor to the legacy Links API (/v1/links), which is being deprecated. Use /v1/payment_links for new integrations.
Migrate existing
/v1/linksintegrations to/v1/payment_links. The legacy Links API will be deprecated soon. See Migration from legacy Links before updating your integration.
Authentication
Authenticate protected endpoints with HTTP Basic Auth. Use your secret API key as the username and leave the password empty.
Authorization: Basic <base64(secret_key:)>The request mode is determined by the API key you use:
| API key | Behavior |
|---|---|
| Live key | Operates on live data |
| Test key | Operates on test data |
For test mode behavior and a sample Payment Links test flow, see Testing Payment Links.
Response format
Success responses
Successful single-resource responses return a data object.
{
"data": {
"id": "link_yfHsXPm8bhSg6ceMhjxCTQ61",
"amount": 50000,
"currency": "PHP",
"description": "My product",
"status": "active",
"livemode": true,
"url": "https://pm.link/yourbusiness/3VEi9Ub",
"reference_number": "3VEi9Ub",
"metadata": {},
"created_at": "2026-05-21T08:00:00Z",
"updated_at": "2026-05-21T08:00:00Z"
}
}List endpoints return a data array. Some list responses may also include pagination metadata.
{
"data": [
{
"id": "link_yfHsXPm8bhSg6ceMhjxCTQ61",
"amount": 50000,
"currency": "PHP",
"description": "My product",
"status": "active",
"livemode": true,
"url": "https://pm.link/yourbusiness/3VEi9Ub",
"reference_number": "3VEi9Ub",
"metadata": {},
"created_at": "2026-05-21T08:00:00Z",
"updated_at": "2026-05-21T08:00:00Z"
}
],
"has_more": false
}Error responses
Error responses return an errors array with a machine-readable code and a human-readable detail.
{
"errors": [
{
"code": "invalid_request_body",
"detail": "amount is required",
"source": {
"pointer": "/amount"
}
}
]
}| Code | Description |
|---|---|
invalid_request_body | The request body is malformed or a field fails validation. |
invalid_query_parameters | A query parameter is invalid. |
parameter_required | A required path parameter is missing. |
not_found | The requested resource does not exist. |
restriction_violation | The request violates a configured restriction, such as a completed session limit. |
unauthorized | Authentication credentials are missing or invalid. |
internal_server_error | An unexpected server-side error occurred. |
Payment Link object
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier for the payment link. |
amount | integer | Amount in cents. The value always represents two decimal places, so PHP 500.00 is 50000. |
currency | string | Three-letter ISO currency code, such as PHP. |
description | string | Customer-facing description for the payment link. |
remarks | string | Internal remarks that are not shown to customers. |
status | string | Management state of the payment link. Possible values are active and archived. |
livemode | boolean | Returns true for live transactions and false for test transactions. |
url | string | Shareable URL to send to your customer. |
reference_number | string | Short unique reference included in the payment link URL. |
metadata | object | Custom key-value data for your integration. |
restrictions | object | Usage restrictions, such as completed session limits. |
restrictions.completed_sessions.count | integer | Number of completed payments for the payment link. |
restrictions.completed_sessions.limit | integer | Maximum number of completed payments allowed for the payment link. |
created_at | string | ISO 8601 timestamp for when the payment link was created. |
updated_at | string | ISO 8601 timestamp for when the payment link was last updated. |
Migration from legacy Links
The /v1/links endpoints are deprecated. Use the following Payment Links endpoints when migrating your integration.
Endpoint mapping
| Legacy Links | Payment Links |
|---|---|
POST /v1/links | POST /v1/payment_links |
GET /v1/links/:id | GET /v1/payment_links/:id |
POST /v1/links/:id/archive | PATCH /v1/payment_links/:id with { "archive": true } |
POST /v1/links/:id/unarchive | PATCH /v1/payment_links/:id with { "archive": false } |
Request body changes
Legacy Links used a nested data.attributes wrapper when creating a link.
{
"data": {
"attributes": {
"amount": 50000,
"description": "My product",
"remarks": "Internal note"
}
}
}Payment Links uses top-level request fields.
{
"amount": 50000,
"currency": "PHP",
"description": "My product",
"remarks": "Internal note"
}Key changes:
- Remove the
data.attributeswrapper. Fields are now top-level. - Add
currency. This field is required and must be an uppercase three-letter ISO currency code, such asPHP. - Set
amountto at least100cents, which represents PHP 1.00. Legacy Links only required an amount greater than0.
Response body changes
Payment Links returns a flatter response structure. Legacy Links returned most resource fields inside data.attributes.
{
"data": {
"id": "link_SEiPNhj6CRXGn98QbwWJJjGj",
"type": "link",
"attributes": {
"amount": 50000,
"archived": false,
"currency": "PHP",
"description": "My product",
"livemode": true,
"fee": 0,
"status": "unpaid",
"checkout_url": "https://pm.link/yourbusiness/XAhvWsK",
"reference_number": "XAhvWsK",
"payments": [],
"created_at": 1748822400,
"updated_at": 1748822400
}
}
}{
"data": {
"id": "link_yfHsXPm8bhSg6ceMhjxCTQ61",
"amount": 50000,
"currency": "PHP",
"description": "My product",
"status": "active",
"livemode": true,
"url": "https://pm.link/yourbusiness/3VEi9Ub",
"reference_number": "3VEi9Ub",
"metadata": {},
"created_at": "2026-05-21T08:00:00Z",
"updated_at": "2026-05-21T08:00:00Z"
}
}Notable field differences
| Attribute | Legacy Links | Payment Links | Notes |
|---|---|---|---|
| Response structure | { id, type, attributes: { ... } } | Flat { id, amount, ... } | Remove the attributes wrapper from your parser. |
status | unpaid or paid | active or archived | These represent different concepts. See Status semantics. |
archived | Boolean field in attributes | Not present | Check whether status is archived instead. |
checkout_url | Returned directly in the create response | url | Replace checkout_url with url in your integration. |
payments | Included as an array in the link response | Available through GET /v1/payment_links/:id/payments | Fetch payments separately when needed. |
created_at / updated_at | Unix timestamp as an integer | ISO 8601 string | Update your date parsing logic. |
fee, tax_amount, taxes | Present in the legacy response | Not included in the payment link response | Use individual payment records for payment-level amounts. |
metadata | Not supported | Supported | Use metadata for your own string key-value reference data. |
restriction | Not supported | Supported | Use restrictions to limit how many times a payment link can be paid. |
Status semantics
Legacy Links used status to represent the payment state, such as unpaid or paid. Payment Links uses status to represent the management state of the link itself.
| Status | Description |
|---|---|
active | The payment link is open and can accept payments. |
archived | The payment link has been manually deactivated. |
To check whether a Payment Link has been paid, call GET /v1/payment_links/:id/payments and inspect the payment records. PayMongo also sends a link.payment.paid event to your configured webhook endpoint after a successful payment.