Skip to content
Status

Create a payment

POSThttps://app.shuttleglobal.com/c/api/instances/{instance_key}/payments

POST
/payments

Create a new payment. The payment can be immediate or scheduled, one-time or recurring. Unless rejected prior to processing, the API request will succeed and return a payment object in a SUCCESS or DECLINE status.

Media typeapplication/json
object
payment
required
object

Payment details object

object
currency
required
string
e.g. "GBP"

The currency in ISO format (e.g., USD)

amount
string
e.g. "100.00"

The payment amount as a string without commas, using ‘.’ as decimal separator. Required in the standard case. Optional when charges is provided — if omitted, it is derived from the sum of charges[].amount; if supplied, it must equal that sum.

alt_key
string
e.g. "order_123"

Your unique reference for the payment (e.g., order id). URL friendly string, max 64 chars (a-z0-9_-)

description
string
e.g. "Invoice 1234"

Descriptive text for the payment

nonce
string

Unique string to prevent duplicate submissions within 24 hours

action
string · enum
default "PAYMENT"

Payment action type

Allowed values: PAYMENT AUTH
source
string · enum
default "ECOMMERCE"

Source of the payment

Allowed values: MOTO ECOMMERCE RECURRING
success_url
string · uri
e.g. "https://www.myhost.com/success"

URL to redirect on successful 3D secure completion

cancel_url
string · uri
e.g. "https://www.myhost.com/cancel"

URL to redirect on 3D secure cancellation

payment_method
One of:

ID of existing payment method

account
One of:

ID of existing account

frequency
string · enum
default "ONEOFF"
e.g. "MONTHLY"

Payment frequency for recurring payments. Cannot be used together with charges; to use scheduled charges, omit frequency or set it to ONEOFF.

Allowed values: ONEOFF WEEKLY FORTNIGHTLY BIMONTHLY MONTHLY QUARTERLY BIANNUALLY ANNUALLY
occurrences
integer
e.g. 12

Number of payments for recurring payments (blank = forever)

start_date
string · date-time

When to take first payment for recurring payments (up to 365 days future)

start_days
integer · max 31

Days from now for first recurring payment (up to 31 days)

scheduled_date
string · date-time

When to process one-time payment (up to 365 days future)

scheduled_days
integer · max 31

Days from now for one-time payment (up to 31 days)

charges
Array<object>
Example
[
{
"alt_key": "INSTALMENT_1",
"amount": "100.00",
"due": "now"
},
{
"alt_key": "INSTALMENT_2",
"amount": "50.00",
"due": "2026-06-01T09:00:00Z"
},
{
"alt_key": "INSTALMENT_3",
"amount": "50.00",
"due": "2026-07-01T09:00:00Z"
}
]

Explicit schedule of charges for the contract. Use this when charge amounts or due dates vary between charges (e.g., instalment plans with irregular amounts or dates). All charges are created upfront at contract creation.

When each charge is taken:

  • due: "now" or a past timestamp (within the last 24 hours) — taken synchronously as part of contract creation. If the charge declines, contract creation fails and no contract is created.
  • due set to a future timestamp — taken asynchronously by the scheduler on the due date. The contract is created regardless of the outcome of that later payment.

To have the first charge run asynchronously, set its due to a future timestamp (even a few minutes ahead).

Constraints:

  • Cannot be combined with frequency (must be omitted or ONEOFF).
  • Not supported with action: AUTH.
  • Each charge’s due cannot be more than 24 hours in the past.
  • The top-level amount is optional when charges is provided. If you do provide amount, it must equal the sum of charges[].amount.

A single charge on an explicitly scheduled contract. Each charge carries its own amount and due date, allowing schedules with varying amounts and irregular dates.

object
alt_key
string
e.g. "INSTALMENT_1"

Optional — your unique reference for this charge (e.g., instalment number or invoice line id). URL friendly string, max 64 chars (a-z0-9_-)

amount
required
string
e.g. "100.00"

The charge amount as a string without commas, using ‘.’ as decimal separator. Must be greater than zero.

due
required
string
e.g. "2026-06-01T09:00:00Z"

When this charge is due. Accepts either the literal string "now", or an ISO 8601 timestamp.

  • "now" or a past timestamp (within the last 24 hours) — taken synchronously during contract creation. A decline blocks the whole contract creation.
  • Future timestamp — taken asynchronously by the scheduler on the due date. The contract is created regardless of that later payment’s outcome.

A timestamp more than 24 hours in the past is rejected.

gateway
string

Gateway ID to process the payment through. If not specified, the default gateway will be used

save_card
boolean

Whether to save the card for future use

force_payment_method
boolean

Force creation of a new payment method even if a matching one already exists

contract
string

Contract ID for one-time payment on existing contract

legal_entity
string

Legal entity ID or code processing the payment

event_date
string · date-time

Event date associated with the payment

metadata
object
e.g. { "order_id": "12345", "customer_reference": "CUS-001"}

Custom key-value pairs that will be stored on the contract

object
key
additional properties
string
shipping
object

Shipping address for the order

object
country
string

Country code

line1
string

Address line 1

line2
string

Address line 2

line3
string

Address line 3

line4
string

City / Town

line5
string

Postcode / ZIP

line6
string

State / Region

line_items
Array<object>
Example
[
{
"sku": "SHOE-10-BLK",
"name": "Running shoes",
"quantity": 2,
"unit_price": 20,
"total_amount": 40,
"total_tax": 4
},
{
"sku": "SHIPPING",
"name": "Standard delivery",
"quantity": 1,
"unit_price": 4.99,
"total_amount": 4.99,
"total_tax": 0
}
]

The order basket. Optional, but required by BNPL providers and by some acquirers to qualify for Level 2 / Level 3 interchange rates on commercial cards. Include every line that makes up the payment amount, including shipping and tax lines.

A single line in the order basket.

Line items are optional, but supplying them unlocks several things depending on the gateway and payment method in use:

  • Level 2 / Level 3 interchange data for commercial and purchasing cards — required by some acquirers to qualify for lower interchange rates.
  • Buy Now Pay Later — BNPL providers require a basket before they will underwrite the order.
  • Express checkout / wallets — the basket is shown in the wallet sheet.
  • Fraud screening — basket contents are passed to the fraud provider.

Amounts and units

All monetary values are in major currency units (e.g. 29.99, not 2999) and should be sent as JSON numbers, not strings. unit_price and total_amount are gross — they include the tax reported in total_tax.

How the line total is derived

Most gateways treat the difference between the extended price and the line total as a discount:

discount = (quantity x unit_price) - total_amount

So for a line with no discount, set total_amount to quantity x unit_price. Where a gateway accepts an explicit discount, total_discount is used instead.

Consistency with the payment amount

Shuttle does not reject a basket that fails to add up to the payment amount, but gateways may. Where the basket totals less than the payment amount, some gateways (PayPal, for example) add a balancing “Miscellaneous” line automatically. Send a complete basket wherever possible, including shipping and tax lines.

Where line items are used for Level 2 / Level 3 interchange data, the card networks require the breakdown to reconcile exactly — sum(total_amount) must equal the payment amount. Where it does not (a part payment, an instalment, an amount override, a discount that is not itemised), the interchange data is simply not sent and the payment goes through unchanged. Line items never cause a payment to fail.

Not every field reaches every gateway. Fields are mapped to whatever the target gateway supports and silently dropped otherwise. name, quantity, unit_price and total_amount are the fields understood everywhere, so populate at least those.

object
name
string
e.g. "Running shoes"

Display name of the item. Shown to the customer in wallet sheets and BNPL baskets, and used as the item description for Level 2/3 data. Some gateways truncate this aggressively (Authorize.Net to 31 characters, Fat Zebra to 40), so keep it short.

sku
string
e.g. "SHOE-10-BLK"

Your product code / SKU for the item.

PayPal only: a line item whose sku is shipping, handling or insurance (case-insensitive) is removed from the basket and its total_amount is reported in the corresponding PayPal order breakdown field instead of as a basket line.

description
string
e.g. "Black running shoes, UK size 10"

Longer description of the item, where name is not enough. Only used by gateways that accept a separate description field; those gateways fall back to name when this is omitted.

quantity
number
e.g. 2

Number of units of this item.

unit_of_measure
string
e.g. "each"

Unit that quantity is expressed in — for example each, hours, metres. Used in Level 3 interchange data, where the card networks require it. Alphanumeric, maximum 12 characters; a longer or malformed value is replaced with each, as is an absent one.

unit_price
number
e.g. 20

Gross price of a single unit, in major currency units, including tax.

total_amount
number
e.g. 40

Gross total for the line, in major currency units, including tax and after any discount. See the discount formula above.

total_tax
number
e.g. 4

Tax included in total_amount for this line, in major currency units. Send 0 for a tax-free line rather than omitting the field — several gateways sum this across the basket to report an order-level tax total.

total_discount
number
e.g. 0

Explicit discount applied to this line, in major currency units. Only used by gateways that accept a discount amount per line (CyberSource, Worldpay). Other gateways derive the discount from (quantity x unit_price) - total_amount.

Express the discount this way rather than as a negative line item. A negative line is not forwarded as Level 2/3 data.

tax_rate
number
e.g. 0.2

Tax rate applied to this line, passed through unchanged. Only used by gateways that accept an explicit rate (currently CyberSource, which expects a decimal fraction — 0.2 for 20%). Where it is omitted, gateways that need a rate derive one from total_tax and total_amount.

discount_rate
number

Discount rate applied to this line, passed through unchanged. Only used by gateways that accept an explicit rate (currently CyberSource).

item_url
string · uri
e.g. "https://example.com/products/shoe-10-blk"

HTTPS URL of the product page for this item. Displayed by BNPL providers (Klarna, Affirm) in the basket they present to the customer.

image_url
string · uri
e.g. "https://example.com/images/shoe-10-blk.jpg"

HTTPS URL of a product image for this item. Displayed by BNPL providers (Klarna, Affirm) in the basket they present to the customer.

hotel_data
object

Hotel-specific data passed through to the payment gateway

object
key
additional properties
any

Payment created

Media typeapplication/json
object
payment
object

Payment details

object
id
string
e.g. "pay_11842_10000"

Payment identifier

alt_key
string
e.g. "1234"

Your supplied payment reference

description
string
e.g. "Invoice 1234"

Payment description

source
string · enum
e.g. "MOTO"

Payment source

Allowed values: MOTO ECOMMERCE RECURRING
action
string · enum
e.g. "PAYMENT"

Payment action type

Allowed values: PAYMENT REFUND AUTH CAPTURE VOID
status
string · enum
e.g. "SUCCESS"

The status of the payment:

  • SUCCESS - The payment was approved
  • PENDING - The payment is still in progress
  • DECLINED - The payment was declined
  • REQAUTH - The payment requires authorization step (e.g. 3D secure)
  • INVALID_PAYMENT_METHOD - Invalid payment method used
  • UNRESOLVED - No conclusive approval/decline received
  • UNATTRIBUTED - Success but internal recording issue
Allowed values: SUCCESS PENDING DECLINED REQAUTH INVALID_PAYMENT_METHOD UNRESOLVED UNATTRIBUTED
gateway_status
string
e.g. "APPROVED"

Category or error message from the gateway

gateway_reference
string
e.g. "ch_1GVaEEFi2CnH4uN3ouw69fw3"

Gateway’s identifier for the transaction

authorisation_code
string
e.g. "pi_1GVaEEFi2CnH4uN355ZdZvk5 (TEST)"

Authorization code from the gateway

reference
string
e.g. "REF-00010000"

Customer-facing reference (e.g., BOLT-123445)

amount
string
e.g. "100"

Payment amount

balance
string
e.g. "100"

Payment amount less any refunds

currency
string
e.g. "GBP"

Payment currency in ISO format

resolved
string · date-time

When the payment was resolved

sub_status
string · enum
e.g. "CUSTOMER_ACTION_REQUIRED"

Sub-status of the payment, present when the gateway is waiting for someone to act. CUSTOMER_ACTION_REQUIRED means the customer still has something to do - e.g. a bank transfer or Multibanco payment stays PENDING until they make the transfer or pay the voucher. MERCHANT_ACTION_REQUIRED is reserved for future use. Omitted and NO_ACTION_REQUIRED mean the same thing.

Allowed values: NO_ACTION_REQUIRED CUSTOMER_ACTION_REQUIRED MERCHANT_ACTION_REQUIRED
sub_status_reason
string
e.g. "follow_bank_transfer_instructions"

Free-text description of the sub-status, e.g. follow_bank_transfer_instructions, follow_voucher_instructions or partially_funded. Descriptive only - not searchable.

target_date
string · date-time
e.g. "2020-04-13T00:00:00.000Z"

Intended payment date. Present only when the payment was created ahead of its target date because the payment method requires gateway advance notice (e.g. SEPA/BACS/GoCardless/Stripe ACH). This is the target date, not the settlement date, and is omitted for payment methods that charge on the due date.

settle_currency
string
e.g. "GBP"

Settlement currency if different from transaction currency

settle_gross_amount
string
e.g. "100"

Gross amount in settlement currency

settle_net_amount
string
e.g. "96.9"

Net amount in settlement currency after fees

settle_fee_amount
string
e.g. "3.1"

Processing fees in settlement currency

gateway
string
e.g. "gw_11842_10000"

Gateway used for processing

account
string
e.g. "acc_11842_10000"

Associated account ID

payment_method
string
e.g. "pm_11842_10000"

Payment method ID used

contract
string
e.g. "co_11842_10000"

Associated contract ID

channel
string
e.g. "ch_11842_10001"

Processing channel

initiative
string
e.g. "in_11842_10000"

Initiative ID

designation
string
e.g. "des_11842_10000"

Designation ID

legal_entity
string
e.g. "le_11842_10000"

Legal entity ID

created
string · date-time
e.g. "2020-04-08T09:29:48.000Z"

Creation timestamp

updated
string · date-time
e.g. "2020-04-08T09:29:52.000Z"

Last update timestamp

processed
string · date-time
e.g. "2020-04-08T09:29:51.000Z"

Processing timestamp

gateway_metadata
object

Gateway-specific data (varies by gateway)

object
payment_method_used_token
boolean
e.g. false

Whether a tokenized payment method was used

recurring
boolean
e.g. false

Whether this is a recurring payment

frequency
string · enum
e.g. "MONTHLY"

Frequency for recurring payments

Allowed values: ONEOFF WEEKLY FORTNIGHTLY BIMONTHLY MONTHLY QUARTERLY BIANNUALLY ANNUALLY
occurrences
integer
e.g. 12

Number of planned occurrences for recurring payments

browser_ip_address
string
e.g. "212.161.80.4"

IP address of the browser that initiated the payment

contract
object

Associated contract details

object
id
string
e.g. "co_11842_10000"

Contract identifier

account
string
e.g. "acc_11842_10000"

Associated account ID

alt_key
string
e.g. "1234"

Your reference for this contract

amount
string
e.g. "100"

Contract amount

currency
string
e.g. "GBP"

Contract currency

description
string
e.g. "Invoice 1234"

Contract description

status
string · enum
e.g. "COMPLETED"

Status of the contract

Allowed values: COMPLETED ACTIVE PENDING
recurring
boolean
e.g. false

Whether this is a recurring contract

payment_method
string
e.g. "pm_11842_10000"

Payment method ID used

created
string · date-time
e.g. "2020-04-08T09:29:48.000Z"

Creation timestamp

updated
string · date-time
e.g. "2020-04-08T09:29:52.000Z"

Last update timestamp

initiated
string · date-time
e.g. "2020-04-08T09:29:48.000Z"

Initiation timestamp

completed
string · date-time
e.g. "2020-04-08T09:29:52.000Z"

Completion timestamp

last_transaction
string
e.g. "tr_11842_10000"

The last transaction ID for this contract

frequency
string · enum

Frequency for recurring contracts

Allowed values: ONEOFF WEEKLY FORTNIGHTLY BIMONTHLY MONTHLY QUARTERLY BIANNUALLY ANNUALLY
occurrences
integer

Number of planned occurrences for recurring contracts

next_charge
string · date-time

Next scheduled charge date for recurring contracts

charge_count
integer

Number of charges processed for this contract

transaction
object

Transaction details

object
id
string
e.g. "tr_11842_10000"

Transaction identifier

action
string · enum
e.g. "PAYMENT"

Transaction action type

Allowed values: PAYMENT REFUND AUTH CAPTURE VOID
source
string · enum
e.g. "MOTO"

Transaction source

Allowed values: MOTO ECOMMERCE RECURRING
status
string · enum
e.g. "SUCCESS"

Transaction status

Allowed values: SUCCESS PENDING DECLINED
gateway_status
string
e.g. "APPROVED"

Status reported by the gateway

sub_status
string · enum
e.g. "CUSTOMER_ACTION_REQUIRED"

Sub-status of the transaction, present when the gateway is waiting for someone to act. CUSTOMER_ACTION_REQUIRED means the customer still has something to do - e.g. a bank transfer or Multibanco payment stays PENDING until they make the transfer or pay the voucher. MERCHANT_ACTION_REQUIRED is reserved for future use. Omitted and NO_ACTION_REQUIRED mean the same thing.

Allowed values: NO_ACTION_REQUIRED CUSTOMER_ACTION_REQUIRED MERCHANT_ACTION_REQUIRED
sub_status_reason
string
e.g. "follow_bank_transfer_instructions"

Free-text description of the sub-status, e.g. follow_bank_transfer_instructions, follow_voucher_instructions or partially_funded. Descriptive only - not searchable.

gateway_reference
string
e.g. "ch_1GVaEEFi2CnH4uN3ouw69fw3"

Gateway’s transaction identifier

authorisation_code
string
e.g. "pi_1GVaEEFi2CnH4uN355ZdZvk5 (TEST)"

Authorization code from the gateway

reference
string
e.g. "REF-00010000"

Customer-facing reference

amount
string
e.g. "100"

Transaction amount

currency
string
e.g. "GBP"

Transaction currency

created
string · date-time
e.g. "2020-04-08T09:29:48.000Z"

Creation timestamp

updated
string · date-time
e.g. "2020-04-08T09:29:52.000Z"

Last update timestamp

processed
string · date-time
e.g. "2020-04-08T09:29:51.000Z"

Processing timestamp

resolved
string · date-time
e.g. "2020-04-08T09:29:51.000Z"

When the transaction was resolved

target_date
string · date-time
e.g. "2020-04-13T00:00:00.000Z"

Intended payment date. Present only when the transaction was created ahead of its target date because the payment method requires gateway advance notice (e.g. SEPA/BACS/GoCardless/Stripe ACH). This is the target date, not the settlement date, and is omitted for payment methods that charge on the due date.

id
string

Payment identifier (legacy format - use payment.id instead)

alt_key
string

Your supplied payment reference (legacy format - use payment.alt_key instead)

description
string

Payment description (legacy format - use payment.description instead)

source
string · enum

Payment source (legacy format - use payment.source instead)

Allowed values: MOTO ECOMMERCE RECURRING
action
string · enum

Payment action type (legacy format - use payment.action instead)

Allowed values: PAYMENT REFUND AUTH CAPTURE VOID
status
string · enum

Payment status (legacy format - use payment.status instead)

Allowed values: SUCCESS PENDING DECLINED REQAUTH INVALID_PAYMENT_METHOD UNRESOLVED UNATTRIBUTED

Bad request - invalid parameters

Media typeapplication/json

Every error has a code and a message. Some add more fields alongside them, with detail about the error.

object
code
string

The error code, for example VALIDATION_ERROR, INVALID, INVALID_REQUEST, UNAUTHORIZED, FORBIDDEN or NOT_FOUND. Program against this, not the message.

message
string

What went wrong, in words, for logs and support.

Unauthorized - invalid credentials

Media typeapplication/json

Every error has a code and a message. Some add more fields alongside them, with detail about the error.

object
code
string

The error code, for example VALIDATION_ERROR, INVALID, INVALID_REQUEST, UNAUTHORIZED, FORBIDDEN or NOT_FOUND. Program against this, not the message.

message
string

What went wrong, in words, for logs and support.

Example
{
"code": "UNAUTHORIZED",
"message": "Unauthorised"
}

Was this page helpful?