Softlemon API Documentation
  • Merchant API
  • Partner API
  • Guides
API basics
    API ConventionsEnvironmentsError HandlingRate LimitsSCA and PSD2SupportChangelog
Integration flows
    Accept a Card PaymentAuthorize Now, Capture LaterRefund a PaymentCharge a Returning CustomerAccept an Alternative PaymentPaysafecard via Skrill: Customer JourneySet Up WebhooksIntegrate as a Partner
Reference
    Merchant Transaction WebhooksTransaction StatusesDuplicate Payment Protection
Integration flows

Accept an Alternative Payment

This guide covers hosted redirect payments through payment sessions, using Paysafecard (psc) as the payment method. The customer completes the payment on the provider's hosted page instead of entering details on your site, so no card or voucher data ever touches your integration.

Creating a session also creates a linked transaction. The transaction follows the standard transaction lifecycle and emits the standard webhook events, so payment sessions plug into the same confirmation machinery as card payments.

For a walkthrough of the Paysafecard flow party by party, with a diagram, see Paysafecard via Skrill: Customer Journey.

Before you start

  • You need an API key. Send it on every request as Authorization: Bearer {YOUR_API_KEY}.
  • All examples use the sandbox base URL https://api.sandbox.softlemons.com.
  • Redirect payments and the specific payment method must be enabled for your account. Requests for a method that is not enabled fail with ERR_PAYMENT_METHOD_NOT_ENABLED. Contact support to get a method enabled.
  • Each method is only available in certain countries, and the provider risk-checks the customer's IP. Send customer.country_code and customer.ip_address on every session. See Availability below.
  • Send customer.email too. For Paysafecard, Skrill uses it to take the customer straight to paysafecard's page instead of showing its own checkout form first.
  • You need two browser URLs on your site: a success URL and a cancel URL for the customer's return.
  • Amounts are major units in requests (25.00) and minor units in responses (2500). See conventions.
  • Never send card fields. A session request carrying card, token, CVV or voucher data is rejected with HTTP 422 regardless of where the field appears in the payload.

Step 1: Create a payment session

Call POST /api/v1/payment-sessions with the amount, a unique reference, the payment method and your return URLs:

curl https://api.sandbox.softlemons.com/api/v1/payment-sessions \ --request POST \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer {YOUR_API_KEY}' \ --data '{ "amount": 25, "currency": "EUR", "reference": "DEP-2048", "payment_method": "psc", "customer": { "first_name": "Jane", "last_name": "Doe", "email": "jane@example.com", "country_code": "GB", "ip_address": "198.51.100.5", "merchant_customer_id": "player-981" }, "customer_reference": "player-981", "success_url": "https://merchant.example.com/deposit/complete", "cancel_url": "https://merchant.example.com/deposit/cancelled" }'
JSON
{ "success": true, "message": "Payment session created", "code": "", "data": { "payment_session": { "payment_session_id": "ps_01J8FYK3ZQ4T9RB2M6XD5A7CWE", "transaction_id": 4512, "merchant_id": 123, "merchant_reference": "DEP-2048", "provider": "skrill", "payment_method": "psc", "status": "pending_redirect", "amount": 2500, "amount_formatted": "25.00", "currency": "EUR", "checkout_url": "https://pay.skrill.com/?sid=a1b2c3d4e5", "return_url": "https://merchant.example.com/deposit/complete", "cancel_url": "https://merchant.example.com/deposit/cancelled", "provider_session_id": "a1b2c3d4e5", "provider_transaction_id": null, "customer_reference": "player-981", "expires_at": "2026-08-08T10:30:00.000000Z", "finalised_at": null, "created_at": "2026-08-08T10:15:00.000000Z", "updated_at": "2026-08-08T10:15:00.000000Z" } } }

The response gives you everything the flow needs:

  • payment_session_id identifies the session in later status calls.
  • checkout_url is the provider's hosted page for this payment. Send the customer there in Step 2.
  • transaction_id is the linked transaction. Webhook events reference it.
  • expires_at is 15 minutes after creation. An unfinished session expires at that point.
  • The request field success_url comes back as return_url on the session.

The reference must be unique and duplicate protection applies. Reusing a reference that has an active session or transaction returns HTTP 409.

Partner API keys create sessions on behalf of a linked merchant by adding merchant_id to the body, with the same rules as partner card payments.

Two customer fields deserve special care:

  • customer.country_code is the customer's country. It is checked against the method's availability before anything is sent to the provider (see Availability).
  • customer.ip_address is the customer's IP address as your server saw it, IPv4 or IPv6. Your call to this API is server-to-server, so without this field the provider only ever sees the IP of your server. Pass the value you actually observed and never a substitute: it is your attestation about the customer, and the provider uses it for its risk decision.

Step 2: Redirect the customer

Send the customer's browser to checkout_url. This is a full page redirect, not an iframe. The customer confirms the payment on the provider's page, for Paysafecard by entering their voucher PIN there.

The session stays pending_redirect while the customer is on the hosted page. It only changes when the provider reports back: pending_provider if the provider says the payment is still in progress, otherwise straight to paid, failed or cancelled. If the customer does not finish within 15 minutes the session becomes expired and you need to create a new one.

Step 3: Handle the browser return

After the hosted page the provider sends the customer back through the gateway, which immediately redirects the browser to your success_url or cancel_url with three query parameters appended:

TEXT
https://merchant.example.com/deposit/complete?payment_session_id=ps_01J8FYK3ZQ4T9RB2M6XD5A7CWE&reference=DEP-2048&status=pending_redirect

Treat this landing as navigation only. It tells you which session the customer came back from, never whether money moved. Confirmation of the provider's outcome can arrive before or after the browser does, so render a waiting state and resolve it in Step 4. Customers who close the tab never hit your return URL at all and the outcome still arrives by webhook.

Step 4: Confirm the outcome

The reliable signal is the webhook on the linked transaction. When the provider confirms the payment the session becomes paid and its transaction becomes captured, which delivers transaction.captured to your webhook endpoint. A failed payment delivers transaction.failed and an abandoned or expired session delivers transaction.cancelled.

To resolve a waiting page or reconcile on demand, poll the session:

curl https://api.sandbox.softlemons.com/api/v1/payment-sessions/ps_01J8FYK3ZQ4T9RB2M6XD5A7CWE \ --header 'Authorization: Bearer {YOUR_API_KEY}'
JSON
{ "success": true, "message": "Payment session retrieved", "code": "", "data": { "payment_session": { "payment_session_id": "ps_01J8FYK3ZQ4T9RB2M6XD5A7CWE", "transaction_id": 4512, "merchant_id": 123, "merchant_reference": "DEP-2048", "provider": "skrill", "payment_method": "psc", "status": "paid", "amount": 2500, "amount_formatted": "25.00", "currency": "EUR", "checkout_url": "https://pay.skrill.com/?sid=a1b2c3d4e5", "return_url": "https://merchant.example.com/deposit/complete", "cancel_url": "https://merchant.example.com/deposit/cancelled", "provider_session_id": "a1b2c3d4e5", "provider_transaction_id": "2649912345", "customer_reference": "player-981", "expires_at": "2026-08-08T10:30:00.000000Z", "finalised_at": "2026-08-08T10:18:42.000000Z", "created_at": "2026-08-08T10:15:00.000000Z", "updated_at": "2026-08-08T10:18:42.000000Z" } } }

Credit the customer only when the session is paid or the transaction.captured webhook arrives. The full session lifecycle (created, pending_redirect, pending_provider, paid, failed, cancelled, chargeback, expired) is documented in the statuses reference.

Availability

Alternative payment methods are not available everywhere. Two checks decide whether a session can be opened:

  1. Country. Each method has a list of countries it can serve. For Paysafecard (psc) that is paysafecard's published availability (most of Europe plus, among others, Australia, Canada, Mexico, New Zealand, the United Kingdom and the United States; not, for example, South Africa or Costa Rica). Your account may carry a narrower list. The check runs on customer.country_code before the provider is contacted, and a country the method does not serve is refused with HTTP 400 ERR_PAYMENT_METHOD_NOT_AVAILABLE_IN_COUNTRY. Nothing is created and the reference stays free. If you do not send customer.country_code the check is skipped and the provider decides on its hosted page.
  2. Provider risk rules on the customer's IP. The provider risk-checks the IP it receives as the customer's device IP. That IP is customer.ip_address when you send it, and the IP of the server calling this API when you do not. A server in a country the method does not serve therefore gets every payment refused unless it forwards the real customer IP. When the provider declines to open the checkout, the session fails with HTTP 400 ERR_PROVIDER_REJECTED, the message carries the provider's reason (for example The transaction has been blocked), the linked transaction is failed with the same status_reason, and the reference is released.

To avoid surprises, always send both customer.country_code and customer.ip_address, and offer the customer another method when you receive either code. Neither check creates a provider payment, so they are safe to hit as often as your checkout needs.

Ask before you show a method

GET /api/v1/payment-methods answers the same questions ahead of time so your checkout only shows methods that can actually be opened. Pass the customer's country and the payment currency; partner keys add merchant_id.

curl 'https://api.sandbox.softlemons.com/api/v1/payment-methods?country=GB&currency=EUR' \ --header 'Authorization: Bearer {YOUR_API_KEY}'
JSON
{ "success": true, "message": "Payment methods retrieved", "code": "", "data": { "merchant_id": 123, "country": "GB", "currency": "EUR", "payment_methods": [ { "payment_method": "psc", "label": "Paysafecard", "provider": "paycent", "available": true, "unavailable_reasons": [], "supported_countries": ["AR", "AT", "AU", "BE", "BG", "CA", "HR", "CY", "CZ", "DK", "EE", "FI", "FR", "GE", "DE", "GI", "GR", "HU", "IS", "IE", "IT", "KW", "LV", "LI", "LT", "LU", "MT", "MX", "MD", "ME", "NL", "NZ", "NO", "PY", "PE", "PL", "PT", "RO", "SA", "SK", "SI", "ES", "SE", "CH", "TR", "AE", "GB", "US", "UY"], "supported_currencies": ["EUR", "GBP", "USD"] }, { "payment_method": "ideal", "label": "iDEAL", "provider": "paycent", "available": false, "unavailable_reasons": ["country_not_supported"], "supported_countries": ["NL"], "supported_currencies": ["EUR"] } ] } }

Each row is a redirect method enabled for the account. supported_countries and supported_currencies are the restrictions in force for it (an empty list means no restriction is known), and when you pass filters available tells you whether a session for that customer would be accepted, with unavailable_reasons being one or more of country_not_supported, currency_not_supported and provider_not_offering. A method that is available: false here would be refused by POST /api/v1/payment-sessions with the matching error. The endpoint reads configuration and the provider's published catalogue only; it never opens a provider payment, so call it per checkout if you like. It is advisory: the session create still runs the full provider checks, and card payments are not listed because they are governed by your acquirer routing rather than by this list.

Errors you should handle

ResponseMeaningWhat to do
400 ERR_PAYMENT_METHOD_NOT_ENABLEDThe method or currency is not enabled for the merchant.Offer a different payment method or contact support about enablement.
400 ERR_PAYMENT_METHOD_NOT_AVAILABLE_IN_COUNTRYThe method is not available for customer.country_code. Checked before the provider is called; nothing is created.Offer a different payment method for that country. See Availability.
400 ERR_PROVIDER_REJECTEDThe provider refused to open the payment for this customer (risk or availability rules, typically the customer's country or IP). message carries the provider's reason. The session and transaction are marked failed and the reference is released.Make sure you send the real customer.ip_address and customer.country_code. Do not retry the same data blindly; offer another method.
409 ERR_DUPLICATEA session or transaction with this reference already exists.Fetch the existing session instead of retrying. See duplicate protection.
422 ERR_VALIDATION_FAILEDA field failed validation. This includes any request carrying card, token, CVV or voucher data, and a customer.ip_address that is not a valid IP.Fix the request. Card data never belongs in a redirect session.
429 ERR_RATE_LIMITEDToo many requests.Back off and retry. See rate limits.
502 ERR_GATEWAY_ERRORThe provider could not prepare the hosted session. The session and its transaction are marked failed.Create a new session to retry.

Full details for every code are in the error catalogue.

Last modified on September 7, 2026
Charge a Returning CustomerPaysafecard via Skrill: Customer Journey
On this page
  • Before you start
  • Step 1: Create a payment session
  • Step 2: Redirect the customer
  • Step 3: Handle the browser return
  • Step 4: Confirm the outcome
  • Availability
    • Ask before you show a method
  • Errors you should handle
JSON
JSON
JSON