Subscriptions

Update Subscription

Changed on

Updates the configuration of an existing subscription.

Modifiable Parameters:

  • Billing information (priceId, amount, interval, intervalCount, description, allowedPaymentMethods)
  • Customer details (contact information, billing/shipping addresses)
  • Subscription settings (cancelAtPeriodEnd, pauseAtPeriodEnd, skipIntervalCount)
  • Metadata (for your internal tracking)

Update Effects:

  • Amount changes apply to the next billing cycle
  • Interval changes apply from the next period, leaving the current one to run out
  • Setting prorate to true settles the price difference immediately instead, and an interval change then restarts the billing period from now
  • nextPaymentAt moves the next charge date on its own, leaving the price alone. With prorate it also settles the time that moves: later charges for it, earlier refunds it
  • Customer information updates take effect immediately
  • Setting cancelAtPeriodEnd to true will end the subscription after the current period
  • Setting pauseAtPeriodEnd to true will pause billing after the current period
  • Setting skipIntervalCount skips billing for the specified number of intervals without changing subscription status

Switching price:

  • A new priceId replaces amount, interval and intervalCount with the price's values. The price must be active and in the subscription's currency
  • On a PENDING subscription the switch also replaces the trial with the price's trial
  • The switch follows the same rules as a manual change: it applies from the next period, or settles at once with prorate
  • Without priceId, changing amount, interval or intervalCount removes priceId and productId

Note: The currency cannot be changed once a subscription is created. To change it, cancel the subscription and create a new one.

put/subscriptions/{id}

Request

Request body

priceIdstring uuid

The price the subscription bills.

The subscription copies the price's values when it is created or switched to the price. A later change to the price never changes the subscription.

amountinteger

Amount intended to be collected by this payment. A positive integer representing how much to charge in the smallest currency unit (e.g., 100 cents to charge 1.00 USD).

interval'minute' | 'hour' | 'day' | 'week' | 'month' | 'quarter' | 'year'

Subscription interval. The minute and hour intervals are only available in test mode.

intervalCountinteger

Number of intervals between subscription payments.

allowedPaymentMethodsstring[]

List of payment methods allowed for subscriptions.

descriptionstring

An arbitrary string attached to the subscription. Often useful for displaying to users.

customerIdstring uuid

The customer this subscription belongs to.

Linking a subscription to a customer turns on renewal failover: when a renewal is declined by the issuing bank, MONEI retries it against up to two of the customer's other saved payment methods within the same attempt, before the subscription goes PAST_DUE. One declined renewal can therefore produce up to three charge attempts on different cards. If one succeeds the subscription continues and moves to that payment method.

trialPeriodEndnumber

The end date of the trial period. Measured in seconds since the Unix epoch.

callbackUrlstring

The URL will be called each time subscription status changes. You will receive a subscription object in the body of the request.

paymentCallbackUrlstring

The URL will be called each time subscription creates a new payments. You will receive the payment object in the body of the request.

pauseAtPeriodEndboolean

If true, the subscription will be paused at the end of the current period.

cancelAtPeriodEndboolean

If true, the subscription will be canceled at the end of the current period.

pauseIntervalCountinteger

Number of intervals when subscription will be paused before it activates again.

skipIntervalCountinteger

The number of intervals during which the subscription billing cycle will be skipped without altering the subscription status. This is useful when payment for a specific period is received through different methods.

prorateboolean

Settle the price difference immediately when you change amount, interval, intervalCount or nextPaymentAt mid-period. Unused time is credited at the current price. An amount change charges the remaining time at the new price and keeps the billing period. An interval or intervalCount change charges the full new price and restarts the period from now. A nextPaymentAt change charges the time from now until the new date and moves the period end to it, so a later date charges and an earlier one refunds.

A positive difference is charged to the saved payment method. A negative difference is refunded against the payments that funded the current period, newest money first: the charge taken by the most recent prorated change in this period, then the payment that renewed it. A refund those together cannot cover is rejected before any of it moves, so a change is either settled in full or not at all. The same rule applies to the preview, which returns the same rejection rather than quoting a settlement the update would refuse.

A billing period can be prorated more than once. Two limits apply:

  • While a settlement is in flight the next one is rejected, and the guard has one-second granularity, so a repeat inside the same second as the previous change is rejected too. Retry after at least a second.
  • A period whose length no longer matches the plan's interval cannot be prorated at all until the next renewal restores it. A nextPaymentAt change resizes the period by definition, and an interval or intervalCount change without prorate leaves the old period in place under the new interval. Either one closes the period to further prorated changes, because the credit and the charge are both fractions of the stored period and would divide by a length the price was never set against.

Accepted on active and trialing subscriptions only. On a trialing subscription the fields change and no money moves, because there is no paid time to credit. Any other status is rejected.

You cannot combine prorate with trialPeriodEnd, cancelAtPeriodEnd, pauseAtPeriodEnd, pauseIntervalCount or skipIntervalCount.

On an active subscription, these are rejected too:

  • A subscription that pays with Bizum, or whose allowedPaymentMethods include it.
  • prorate without a change to amount, interval, intervalCount or nextPaymentAt, because there is nothing to settle.
  • An interval or intervalCount change while cancelAtPeriodEnd, pauseAtPeriodEnd or skipIntervalCount is pending. An amount change is accepted.
  • A change that would refund, when refunds are disabled for the account.

A nextPaymentAt change has its own rules:

  • Only on an active subscription. A prorated nextPaymentAt change is rejected on a trialing one, where nothing would settle, and on a past due one, which a plain change accepts.
  • Not together with interval or intervalCount. Those already restart the period from now, so the new period end would have two answers.
  • The charge is capped at 24 billing periods. A date far enough ahead to exceed that is rejected rather than charged.
  • The clearing value described on nextPaymentAt is accepted on an anchor move and on nothing else. Any other prorated change still rejects those fields outright.
nextPaymentAtinteger

The date when the next payment will be made. Measured in seconds since the Unix epoch.

Send it on an update to move the next charge without changing the price. The date must be in the future and no more than five years ahead, and the subscription must be active or past due with a live schedule. A trialing subscription moves with trialPeriodEnd instead, and a paused one has to be resumed first.

A pending skipIntervalCount, pauseIntervalCount, pauseAtPeriodEnd or cancelAtPeriodEnd blocks the change, because it would turn the charge at the new date into a skipped, paused or cancelled cycle instead of a payment. Clear it in the same request by sending 0, null or false for that field.

Moving the date on its own settles no money. Combine it with prorate to charge or refund the time that moves.

metadataMetadata

A set of key-value pairs that you can attach to a resource. This can be useful for storing additional information about the resource in a structured format.

Example request

{
  "priceId": "3c5a1f8e-2b7d-4e9a-9c41-7d2e6b0f5a13",
  "amount": 110,
  "interval": "month",
  "intervalCount": 1,
  "allowedPaymentMethods": [
    "card",
    "bizum"
  ],
  "description": "MoonMail Monthly Lite",
  "customerId": "a4e1d1dd-e0c2-4f7a-a2b1-2b0f1f9b6b1e",
  "customer": {
    "email": "john.doe@example.com",
    "name": "John Doe"
  },
  "billingDetails": {
    "name": "John Doe",
    "email": "john.doe@example.com",
    "address": {
      "country": "ES",
      "city": "Málaga",
      "line1": "Fake Street 123",
      "zip": "1234",
      "state": "Málaga"
    }
  },
  "shippingDetails": {
    "name": "John Doe",
    "email": "john.doe@example.com",
    "address": {
      "country": "ES",
      "city": "Málaga",
      "line1": "Fake Street 123",
      "zip": "1234",
      "state": "Málaga"
    }
  },
  "trialPeriodEnd": 1636366897,
  "callbackUrl": "https://example.com/subscriptions/callback",
  "paymentCallbackUrl": "https://example.com/payments/callback",
  "pauseIntervalCount": 1,
  "skipIntervalCount": 1,
  "retrySchedule": [
    {
      "interval": "day",
      "intervalCount": 1
    },
    {
      "interval": "day",
      "intervalCount": 3
    },
    {
      "interval": "week",
      "intervalCount": 1
    }
  ],
  "nextPaymentAt": 1636366897,
  "metadata": {
    "systemId": "12345"
  }
}

Response

A subscription object

idstring required

Unique identifier for the subscription.

amountinteger required

Amount intended to be collected by this payment. A positive integer representing how much to charge in the smallest currency unit (e.g., 100 cents to charge 1.00 USD).

currencystring

Three-letter ISO currency code, in uppercase. Must be a supported currency.

allowedPaymentMethodsstring[]

List of payment methods allowed for subscriptions.

descriptionstring

An arbitrary string attached to the subscription. Often useful for displaying to users.

accountIdstring required

MONEI Account identifier.

livemodeboolean required

Has the value true if the resource exists in live mode or the value false if the resource exists in test mode.

status'PENDING' | 'EXPIRED' | 'TRIALING' | 'ACTIVE' | 'PAST_DUE' | 'PAUSED' | 'CANCELED' required

The status of the subscription.

priceIdstring uuid

The price the subscription bills.

The subscription copies the price's values when it is created or switched to the price. A later change to the price never changes the subscription.

productIdstring uuid

The product of the subscription's price. MONEI sets it from priceId, and removes it together with priceId.

customerIdstring uuid

The customer this subscription belongs to.

Linking a subscription to a customer turns on renewal failover: when a renewal is declined by the issuing bank, MONEI retries it against up to two of the customer's other saved payment methods within the same attempt, before the subscription goes PAST_DUE. One declined renewal can therefore produce up to three charge attempts on different cards. If one succeeds the subscription continues and moves to that payment method.

interval'minute' | 'hour' | 'day' | 'week' | 'month' | 'quarter' | 'year' required

Subscription interval. The minute and hour intervals are only available in test mode.

intervalCountinteger required

Number of intervals between subscription payments.

pauseIntervalCountinteger

Number of intervals when subscription will be paused before it activates again.

skipIntervalCountinteger

The number of intervals during which the subscription billing cycle will be skipped without altering the subscription status. This is useful when payment for a specific period is received through different methods.

lastOrderIdstring

An order ID from your system. A unique identifier that can be used to reconcile the payment with your internal system. Up to 40 characters: ASCII letters, digits and _ @ . / # & + - (no spaces).

currentPeriodStartnumber

The start date of the current subscription period. Measured in seconds since the Unix epoch.

currentPeriodEndnumber

The end date of the current subscription period. Measured in seconds since the Unix epoch.

trialPeriodEndnumber

The end date of the trial period. Measured in seconds since the Unix epoch.

trialAmountinteger

Amount charged on each billing cycle during the trial period, as a positive integer in the smallest currency unit (e.g., 100 cents to charge 1.00 USD). Once the trial ends, the subscription's regular amount is charged. Use this to offer discounted introductory pricing. Can be combined with trialIntervalCount (charged each cycle for that many cycles) or with trialPeriodDays/trialPeriodEnd (charged once at activation, covering the subscription until the trial period ends).

trialIntervalCountinteger

Number of billing cycles charged at trialAmount before the regular amount applies, using the subscription's interval (e.g., interval of month with a trialIntervalCount of 3 charges the trialAmount for the first 3 months). Requires trialAmount and cannot be combined with trialPeriodDays or trialPeriodEnd. In responses, the value decrements after each trial payment and is removed once the trial ends.

nextPaymentAtinteger

The date when the next payment will be made. Measured in seconds since the Unix epoch.

Send it on an update to move the next charge without changing the price. The date must be in the future and no more than five years ahead, and the subscription must be active or past due with a live schedule. A trialing subscription moves with trialPeriodEnd instead, and a paused one has to be resumed first.

A pending skipIntervalCount, pauseIntervalCount, pauseAtPeriodEnd or cancelAtPeriodEnd blocks the change, because it would turn the charge at the new date into a skipped, paused or cancelled cycle instead of a payment. Clear it in the same request by sending 0, null or false for that field.

Moving the date on its own settles no money. Combine it with prorate to charge or refund the time that moves.

retryCountinteger

Number of retries left for the subscription.

cancelAtPeriodEndboolean

If true, the subscription will be canceled at the end of the current period.

pauseAtPeriodEndboolean

If true, the subscription will be paused at the end of the current period.

lastProrationAtinteger

The date of the most recent prorated change. A period can be prorated more than once, so this moves with each settlement rather than being set once per period.

sequenceIdstring

A permanent identifier that refers to the initial payment of a sequence of payments. This value needs to be sent in the path for RECURRING payments.

callbackUrlstring

The URL will be called each time subscription status changes. You will receive a subscription object in the body of the request.

paymentCallbackUrlstring

The URL will be called each time subscription creates a new payments. You will receive the payment object in the body of the request.

metadataMetadata

A set of key-value pairs that you can attach to a resource. This can be useful for storing additional information about the resource in a structured format.

createdAtinteger

Time at which the resource was created. Measured in seconds since the Unix epoch.

updatedAtinteger

Time at which the resource updated last time. Measured in seconds since the Unix epoch.

Example response

{
  "id": "575bcd84-09fc-4a6e-8c4c-f88b8eb90bfa",
  "amount": 110,
  "currency": "EUR",
  "allowedPaymentMethods": [
    "card",
    "bizum"
  ],
  "description": "MoonMail Monthly Lite",
  "accountId": "aa9333ba-82de-400c-9ae7-087b9f8d2242",
  "status": "PENDING",
  "priceId": "3c5a1f8e-2b7d-4e9a-9c41-7d2e6b0f5a13",
  "productId": "8f2c6d1a-4b3e-4f7a-9d2c-1e5b7a9c3f60",
  "customerId": "a4e1d1dd-e0c2-4f7a-a2b1-2b0f1f9b6b1e",
  "customer": {
    "email": "john.doe@example.com",
    "name": "John Doe"
  },
  "billingDetails": {
    "name": "John Doe",
    "email": "john.doe@example.com",
    "address": {
      "country": "ES",
      "city": "Málaga",
      "line1": "Fake Street 123",
      "zip": "1234",
      "state": "Málaga"
    }
  },
  "shippingDetails": {
    "name": "John Doe",
    "email": "john.doe@example.com",
    "address": {
      "country": "ES",
      "city": "Málaga",
      "line1": "Fake Street 123",
      "zip": "1234",
      "state": "Málaga"
    }
  },
  "interval": "month",
  "intervalCount": 1,
  "pauseIntervalCount": 1,
  "skipIntervalCount": 1,
  "lastOrderId": "14379133960355",
  "lastPayment": {
    "id": "af6029f80f5fc73a8ad2753eea0b1be0",
    "status": "PENDING",
    "statusCode": "E000",
    "statusMessage": "Transaction approved"
  },
  "paymentMethod": {
    "method": "card",
    "card": {
      "country": "ES",
      "brand": "visa",
      "type": "credit",
      "threeDSecureVersion": "2.1.0",
      "threeDSecureFlow": "CHALLENGE",
      "expiration": 2048544000,
      "last4": "0004",
      "fingerprint": "7f2afde1566286c5fb126bb7e79bef549755cce6033dc429013c46d1365ff0e9",
      "tokenizationMethod": "applePay",
      "cardholderName": "John Doe",
      "cardholderEmail": "email@example.com"
    }
  },
  "currentPeriodStart": 1636366897,
  "currentPeriodEnd": 1636366897,
  "trialPeriodEnd": 1636366897,
  "trialAmount": 100,
  "trialIntervalCount": 3,
  "nextPaymentAt": 1636366897,
  "retryCount": 1,
  "retrySchedule": [
    {
      "interval": "day",
      "intervalCount": 1
    },
    {
      "interval": "day",
      "intervalCount": 3
    },
    {
      "interval": "week",
      "intervalCount": 1
    }
  ],
  "lastProrationAt": 1636366897,
  "lastProration": {
    "credit": 500,
    "charge": 1200,
    "net": 700,
    "paymentId": "af6029f80f5fc73a8ad2753eea0b1be0"
  },
  "traceDetails": {
    "ip": "100.100.200.100",
    "countryCode": "ES",
    "lang": "es",
    "deviceType": "desktop",
    "browser": "Chrome",
    "browserVersion": "83.0.4103.116",
    "os": "Mac OS",
    "osVersion": "10.15.4",
    "source": "MONEI/PHP",
    "sourceVersion": "0.1.2",
    "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...",
    "browserAccept": "text/html,application/xhtml+xml,application/json",
    "browserColorDepth": "24",
    "browserScreenHeight": "1152",
    "browserScreenWidth": "2048",
    "browserTimezoneOffset": "-120",
    "userEmail": "user@example.com"
  },
  "sequenceId": "62b23b9f3627cc38b08ff471ccd313ad",
  "callbackUrl": "https://example.com/subscriptions/callback",
  "paymentCallbackUrl": "https://example.com/payments/callback",
  "metadata": {
    "systemId": "12345"
  },
  "createdAt": 1636366897,
  "updatedAt": 1636366897
}

Changes

    • info

      added the new optional request property

    • info

      added the optional property to the response with the status

    • info

      added the optional property to the response with the status

    • info

      added the new optional request property

    • info

      added the optional property to the response with the status

    • info

      the response's property pattern ^[a-zA-Z0-9_@./#&+-]{1,40}$ was added for the status