Apple Pay Recurring Payments (MPAN)
To process recurring payments with Apple Pay using MPAN (Multi-Use Payment Token), include the recurrenceMetadata object in the order creation within paymentDetails. If the data is sent in the order it will also be returned in the payment callback.
All information regarding accepted formats and descriptions of the new fields is in section 6. Field appendix.
General Validation Rules
recurrenceMetadata is optional, but if included:
intervalUnit,intervalCount,managementUrl, andsubscriptionare mandatory- If both
startDateandendDateare provided,startDatemust be ≤endDate managementUrlmust begin withhttps://
MPAN Creation
Important: If recurrenceMetadata is not included in the Apple Pay payment request, the system will attempt to create a DPAN (Dedicated Payment Account Number) instead of an MPAN.
Regarding recurrenceMetadata for Apple Pay and MPAN creation:
The information provided in the recurrenceMetadata fields is used SOLELY FOR DISPLAY PURPOSES within the Apple Pay interface and for tokenization.
THESE FIELDS DO NOT EXECUTE OR SCHEDULE PAYMENTS.
The recurring payment execution and scheduling must be managed separately through Revup's subscription system or your own recurring payment logic. The MPAN token created through this process can be used for subsequent payments, but the recurrence metadata itself does not trigger automatic billing.
| FIELD | TYPE | REQUIRED | MAX LENGHT / ENUM | VALIDATION RULES | NOTES |
|---|---|---|---|---|---|
| startDate | string | No | ISO-8601 UTC | Must be a valid ISO-8601 UTC string | Optional. If provided, must be ≤ endDate |
| endDate | string | No | ISO-8601 UTC | Must be a valid ISO-8601 UTC string and ≥ startDate | Optional. Can be omitted if subscription is indefinite |
| intervalUnit | string | Yes (if recurrenceMetadata) | "day", "week", "month", "year" | Must be one of the enumerated values | Defines frequency unit |
| intervalCount | integer | Yes (if recurrenceMetadata) | - | Must be ≥ 1 | Number of units per interval (e.g., every 1 month) |
| managementUrl | string | Yes (if recurrenceMetadata) | - | Must be valid HTTPS URL | Used to manage/cancel subscription. Must begin with https:// |
| FIELD | TYPE | REQUIRED | MAX LENGHT / ENUM | VALIDATION RULES | NOTES |
|---|---|---|---|---|---|
| amount | number | No | - | Must be ≥ 0 | Trial charge (typically 0.00) |
| currency | string | No | ISO 4217 (e.g., EUR, USD) | Must be valid ISO 4217 code | Matches payment currency |
| label | string | No | - | Optional descriptive label | e.g., "trial" |
| duration | integer | No | - | Must be ≥ 1 | Length of trial period |
| durationUnit | string | No | "day", "week", "month", "year" | Must be one of the enumerated values | Defines unit of trial duration (e.g., 7 days) |
| FIELD | TYPE | REQUIRED | MAX LENGHT / ENUM | VALIDATION RULES | NOTES |
|---|---|---|---|---|---|
| amount | number | Yes | - | Must be ≥ 0 | Charge per interval |
| currency | string | Yes | ISO 4217 (e.g., EUR, USD) | Must be valid ISO 4217 code | Matches system-supported currencies |
| label | string | Yes | - | Optional descriptive label | e.g., "Basic Plan", "Subscription" |
Additional General Validations
The recurrenceMetadata field is optional, but if it is included:
- intervalUnit, intervalCount, managementUrl, and subscription are required.
- If startDate and endDate are provided, then startDate must be less than or equal to (≤) endDate.
- managementUrl must begin with https://.
Request Body Example - Apple Pay with Recurrence Metadata
{
"money": {
"amount": 49,
"currency": "USD"
},
"concept": "Test concept",
"userInformation": {
"ip": "61.251.115.6",
"email": "qa@1eqa.net",
"country": "es",
"language": "es",
"phone": "666111222",
"billingAddress": {
"name": "Test",
"street": "Testing St.",
"city": "City",
"postcode": "01101",
"country": "US",
"state": "us-al"
},
"browserInformation": {
"userAgentHeader": "userAgent",
"acceptHeader": "accept",
"screenHeight": 1080,
"screenColorDepth": 24,
"enableJava": true,
"windowSize": "max",
"timeZone": 1,
"enableJavaScript": true,
"screenWidth": 720
}
},
"items": [
{
"name": "Test2",
"quantity": 1,
"unitPrice": 27.01,
"sku": "ABCD100",
"url": "https://www.test.com",
"category": "TestCategory",
"tax": 0.21
}
],
"generateToken": true,
"domain": "https://www.test.com",
"customTag": "custom",
"paymentDetails": {
"type": "credit_card_present",
"recurrenceMetadata": {
"startDate": "2026-01-01T15:00:00.000Z",
"intervalUnit": "month",
"intervalCount": 1,
"endDate": "2027-01-01T15:00:00.000Z",
"managementUrl": "https://www.test.com/es",
"trial": {
"amount": 20,
"currency": "USD",
"label": "Trial payment",
"duration": 7,
"durationUnit": "month"
},
"subscription": {
"amount": 20,
"currency": "USD",
"label": "Subscription"
}
}
},
"redirectUrl": {
"success": "https://api.qai.1eqa.net/callback/success",
"fail": "https://api.qai.1eqa.net/callback/failed",
"threeDSChallengeResult": "https://api.qai.1eqa.net/challenge?v=2&chll=done"
},
"purchaseId": "1763452974328",
"threeDSSupport": "no_3ds"
}
Subscrtion Module - Apple Pay Recurring Payments (MPAN)
If you already use the subscription order creation endpoint, you do not need to change the existing fields in your integration. To request MPAN, you must:
- continue sending the usual order and subscription information;
- add the
apmConfig.applePayobject; - explicitly set
tokenType: "MPAN"; - provide a URL where the customer can manage their subscription;
- create the order as a new operation without using stored-token fields.
Before you begin
Make sure you have:
- access to the Subscriptions API and a valid credential (
x-api-key); - Apple Pay configured for your business and enabled for the corresponding MPAN flow;
- an active subscription plan with the correct billing frequency;
- a public HTTPS URL for receiving subscription events;
- public HTTPS URLs for redirecting the customer after payment;
- a public HTTPS page where the customer can view or manage their subscription.
If the plan includes a trial period, configure it in the plan itself. Do not send the trial duration or renewal frequency in apmConfig; the platform obtains this information from the plan identified by planId.
Create a subscription with MPAN
Use the existing order creation endpoint:
POST /subscriptions
Content-Type: application/json
x-api-key: <your-api-key>
The base URL depends on the environment provided by Revup.
Complete request example
The following example keeps the standard order fields and adds the new MPAN configuration:
{
"planId": "00000000-0000-0000-0000-000000000001",
"eventSubscriptionUrl": "https://merchant.example/subscriptions/events",
"currency": "EUR",
"redirectUrl": {
"success": "https://merchant.example/payment/success",
"fail": "https://merchant.example/payment/failed",
"threeDSChallengeResult": "https://merchant.example/payment/challenge"
},
"userInformation": {
"ip": "203.0.113.10",
"email": "customer@example.com",
"country": "ES",
"language": "EN"
},
"concept": "Premium subscription",
"threeDSSupport": "no_3ds",
"domain": "https://merchant.example",
"customTag": "premium-subscription",
"description": "Premium subscription signup",
"apmConfig": {
"applePay": {
"tokenType": "MPAN",
"managementUrl": "https://merchant.example/account/subscription",
"trial": {
"label": "Trial period"
},
"subscription": {
"label": "Premium subscription"
}
}
}
}
Fields you already use
Existing fields keep their current behavior. For an MPAN integration, continue sending them according to your existing order creation contract.
| Field | What the merchant must do |
|---|---|
planId | Send the identifier of the plan being purchased. The plan defines the renewal frequency and trial period, if applicable. |
eventSubscriptionUrl | Send a public and stable URL where you can receive subscription events. |
currency | Send the transaction currency when applicable, using a three-letter ISO 4217 code such as EUR. |
redirectUrl.success | Specify where to redirect the customer after a successful payment. |
redirectUrl.fail | Specify where to redirect the customer after a failed payment. |
redirectUrl.threeDSChallengeResult | Keep the URL used to receive or continue the result of a 3DS challenge, when applicable. |
userInformation | Send the customer information required by your existing flow, such as IP address, email, country, and language. |
concept | Provide a recognizable description of the product or service being purchased. |
domain | Send your merchant domain. |
threeDSSupport | Keep the value used by your existing integration. |
customTag | Keep your internal reference or tag if you use one. |
description | Keep the transaction description if you use one. |
overwrite.initialAmount | Use it only when you need to override the first charge amount. |
This update does not change the validation or required status of these fields in your existing integration.
New MPAN fields
Add the following block to your existing request:
{
"apmConfig": {
"applePay": {
"tokenType": "MPAN",
"managementUrl": "https://merchant.example/account/subscription",
"trial": {
"label": "Trial period"
},
"subscription": {
"label": "Premium subscription"
}
}
}
}
| Field | Must you send it? | Description |
|---|---|---|
apmConfig | Yes, for this feature | Contains the alternative payment method configuration. |
apmConfig.applePay | Yes, for this feature | Contains the Apple Pay-specific configuration. |
apmConfig.applePay.tokenType | Yes | Send exactly MPAN. If omitted, the operation is treated as DPAN and MPAN is not enabled. |
apmConfig.applePay.managementUrl | Yes | Public HTTPS URL where the customer can view or manage their subscription. It must not be empty. |
apmConfig.applePay.trial.label | No | Text describing the trial-period charge. If omitted, Trial payment is used. |
apmConfig.applePay.subscription.label | No | Text describing the regular subscription charge. If omitted, Subscription is used. |
Label recommendations
- Use short text that customers can easily recognize.
- Clearly indicate when the first charge relates to a trial period.
- Use a subscription label consistent with the product name shown during checkout.
- Do not include amounts or dates in labels, as these values come from the plan and may change.
Subscription management page
managementUrl is required for MPAN. The merchant is responsible for keeping this URL available throughout the lifetime of the recurring agreement.
Recommendations:
- use HTTPS;
- direct the customer to the relevant subscription or to an area where it can be easily identified;
- allow the customer to view the subscription status and terms;
- provide the management actions relevant to your service, such as cancellation or plan changes;
- avoid temporary URLs, expired sessions, or URLs tied to a single device.
Example:
"managementUrl": "https://merchant.example/account/subscription"
Plans with a trial period
If the plan identified by planId includes a trial, the platform automatically uses:
- the trial duration configured in the plan;
- the renewal frequency configured in the plan;
- the amount and currency calculated for the first charge;
- the value sent in
trial.label, orTrial paymentif omitted; - the value sent in
subscription.label, orSubscriptionif omitted.
Do not manually send the trial duration, period unit, or renewal interval in apmConfig.
Override the initial amount
The existing overwrite.initialAmount field remains available:
{
"overwrite": {
"initialAmount": 10.00
}
}
- For a plan with a trial, the overridden amount applies to the initial trial charge. Renewals keep the regular amount calculated for the plan.
- For a plan without a trial, the overridden amount applies to the initial subscription charge.
Important restriction: do not use a stored token
MPAN is supported only when creating a new, non-tokenized subscription order.
Do not combine the MPAN configuration with the following token-based flow fields:
{
"tokenId": "...",
"parentTransactionId": "...",
"parentOrderId": "..."
}
If these fields are sent together with tokenType: "MPAN", the request is rejected.
Minimum example
If your integration already supplies the other standard fields, the minimum change is to add:
{
"planId": "00000000-0000-0000-0000-000000000001",
"eventSubscriptionUrl": "https://merchant.example/subscriptions/events",
"apmConfig": {
"applePay": {
"tokenType": "MPAN",
"managementUrl": "https://merchant.example/account/subscription"
}
}
}
In this case, the default labels are applied:
- trial:
Trial payment; - subscription:
Subscription.
curl example
curl --request POST \
--url 'https://<api-host>/<environment>/subscriptions' \
--header 'Content-Type: application/json' \
--header 'x-api-key: <your-api-key>' \
--data '{
"planId": "00000000-0000-0000-0000-000000000001",
"eventSubscriptionUrl": "https://merchant.example/subscriptions/events",
"currency": "EUR",
"concept": "Premium subscription",
"domain": "https://merchant.example",
"userInformation": {
"ip": "203.0.113.10",
"email": "customer@example.com",
"country": "ES",
"language": "EN"
},
"redirectUrl": {
"success": "https://merchant.example/payment/success",
"fail": "https://merchant.example/payment/failed"
},
"apmConfig": {
"applePay": {
"tokenType": "MPAN",
"managementUrl": "https://merchant.example/account/subscription",
"trial": {
"label": "Trial period"
},
"subscription": {
"label": "Premium subscription"
}
}
}
Successful response
An accepted request returns HTTP 200:
{
"orderId": "11111111-1111-1111-1111-111111111111",
"subscriptionId": "22222222-2222-2222-2222-222222222222"
}
Store both identifiers:
orderIdidentifies the created payment order;subscriptionIdidentifies the subscription and should be used for tracking and management.
Errors to review
Error responses use the following structure:
{
"error": {
"code": "0301",
"description": "Missing or invalid field: apmConfig.applePay.managementUrl"
}
}
| HTTP | Code | Meaning | How to resolve it |
|---|---|---|---|
400 | 0300 | The request does not match the expected format. | Review the JSON and the standard order creation fields. |
400 | 0301 | apmConfig.applePay.tokenType is invalid. | Send exactly MPAN and verify that you are not using tokenized-order fields. |
400 | 0301 | apmConfig.applePay.managementUrl is missing. | Add a non-empty management URL, preferably using HTTPS. |
400 | 0003 | No billing strategy was found for the plan. | Verify that planId belongs to a valid and correctly configured plan. |
400 | 0001 | The order already exists. | Do not repeat the same creation request. Use the identifiers from the original response or review your retry handling. |
Relevant error descriptions include:
Missing or invalid field: apmConfig.applePay.tokenType
Missing or invalid field: apmConfig.applePay.managementUrl
Integration checklist
Before going live, verify that:
- Apple Pay MPAN is enabled for your business.
- You use a valid credential for the correct environment.
- The
planIdexists and has the expected billing cycle and trial settings. - You keep all fields already required by your order creation integration.
- You add
apmConfig.applePay.tokenTypewith the valueMPAN. managementUrlis public, stable, and uses HTTPS.- You do not send
tokenId,parentTransactionId, orparentOrderId. - Your event and redirect URLs are accessible from the target environment.
- You have tested a plan with a trial, if your business uses trials.
- You have tested a plan without a trial.
- You store
orderIdandsubscriptionIdafter a successful response. - You handle retries without creating duplicate orders.
Compatibility with existing integrations
Integrations that do not send apmConfig.applePay continue to work as before.
Sending Apple Pay without tokenType, or sending tokenType: "DPAN", does not enable MPAN. To use this feature, the merchant must explicitly send:
{
"tokenType": "MPAN"
}