Payment Links

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/links integrations 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 keyBehavior
Live keyOperates on live data
Test keyOperates 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"
      }
    }
  ]
}
CodeDescription
invalid_request_bodyThe request body is malformed or a field fails validation.
invalid_query_parametersA query parameter is invalid.
parameter_requiredA required path parameter is missing.
not_foundThe requested resource does not exist.
restriction_violationThe request violates a configured restriction, such as a completed session limit.
unauthorizedAuthentication credentials are missing or invalid.
internal_server_errorAn unexpected server-side error occurred.

Payment Link object

FieldTypeDescription
idstringUnique identifier for the payment link.
amountintegerAmount in cents. The value always represents two decimal places, so PHP 500.00 is 50000.
currencystringThree-letter ISO currency code, such as PHP.
descriptionstringCustomer-facing description for the payment link.
remarksstringInternal remarks that are not shown to customers.
statusstringManagement state of the payment link. Possible values are active and archived.
livemodebooleanReturns true for live transactions and false for test transactions.
urlstringShareable URL to send to your customer.
reference_numberstringShort unique reference included in the payment link URL.
metadataobjectCustom key-value data for your integration.
restrictionsobjectUsage restrictions, such as completed session limits.
restrictions.completed_sessions.countintegerNumber of completed payments for the payment link.
restrictions.completed_sessions.limitintegerMaximum number of completed payments allowed for the payment link.
created_atstringISO 8601 timestamp for when the payment link was created.
updated_atstringISO 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 LinksPayment Links
POST /v1/linksPOST /v1/payment_links
GET /v1/links/:idGET /v1/payment_links/:id
POST /v1/links/:id/archivePATCH /v1/payment_links/:id with { "archive": true }
POST /v1/links/:id/unarchivePATCH /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.attributes wrapper. Fields are now top-level.
  • Add currency. This field is required and must be an uppercase three-letter ISO currency code, such as PHP.
  • Set amount to at least 100 cents, which represents PHP 1.00. Legacy Links only required an amount greater than 0.

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

AttributeLegacy LinksPayment LinksNotes
Response structure{ id, type, attributes: { ... } }Flat { id, amount, ... }Remove the attributes wrapper from your parser.
statusunpaid or paidactive or archivedThese represent different concepts. See Status semantics.
archivedBoolean field in attributesNot presentCheck whether status is archived instead.
checkout_urlReturned directly in the create responseurlReplace checkout_url with url in your integration.
paymentsIncluded as an array in the link responseAvailable through GET /v1/payment_links/:id/paymentsFetch payments separately when needed.
created_at / updated_atUnix timestamp as an integerISO 8601 stringUpdate your date parsing logic.
fee, tax_amount, taxesPresent in the legacy responseNot included in the payment link responseUse individual payment records for payment-level amounts.
metadataNot supportedSupportedUse metadata for your own string key-value reference data.
restrictionNot supportedSupportedUse 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.

StatusDescription
activeThe payment link is open and can accept payments.
archivedThe 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.