Orders API SEPA Integration Guide

DOCSbeta

Last updated: Sept 24th, 12:39am

Step 1: Create an order

Use the buyer information you captured from your user interface to create an order.

Sample request

API endpoint used: Create order

    1curl -v -X POST https://api-m.sandbox.paypal.com/v2/checkout/orders \
    2-H "Content-Type: application/json" \
    3-H "Authorization: Bearer <Access-Token>" \
    4-d '{
    5 "intent": "CAPTURE",
    6 "purchase_units": [
    7 {
    8 "amount": {
    9 "currency_code": "EUR",
    10 "value": "1.00"
    11 }
    12 }
    13 ]
    14 }'

    Modify the code

    After you copy the code in the sample request, modify the following:

    • Access-Token - Your access token.
    • intent - To use SEPA Direct Debit, this parameter must be set to CAPTURE as it is in this sample code.
    • purchase_units: amount - Pass the amount of the order and EUR as currency code.
    • (Optional) Change or add other parameters in the Create order request body to create an order that reflects the actual order details.
    • (Optional) soft_descriptor is supported in create order. See soft descriptor section for reference.
      1curl -v -X POST https://api-m.sandbox.paypal.com/v2/checkout/orders \
      2-H "Content-Type: application/json" \
      3-H "Authorization: Bearer <Access-Token>" \
      4-d '{
      5 "intent": "CAPTURE",
      6 "purchase_units": [
      7 {
      8 "soft_descriptor": "mycompany * myproduct",
      9 "amount": {
      10 "currency_code": "EUR",
      11 "value": "100.00"
      12 }
      13 }
      14 ]
      15 }'

      Step result

      A successful request results in the following:

      • A return status code of HTTP 201 Created.
      • A JSON response body that contains the order ID. You'll use the order ID in the next step.

      Sample response

        1{
        2 "id": "5O190127TN364715T",
        3 "status": "CREATED",
        4 "links": [
        5 {
        6 "href": "https://api-m.paypal.com/v2/checkout/orders/5O190127TN364715T",
        7 "rel": "self",
        8 "method": "GET"
        9 },
        10 {
        11 "href": "https://api-m.paypal.com/v2/checkout/orders/5O190127TN364715T/capture",
        12 "rel": "capture",
        13 "method": "POST"
        14 },
        15 {
        16 "href": "https://www.paypal.com/checkoutnow?token=5O190127TN364715T",
        17 "rel": "approve",
        18 "method": "GET"
        19 },
        20 {
        21 "href": "https://api-m.paypal.com/v2/checkout/orders/5O190127TN364715T",
        22 "rel": "update",
        23 "method": "PATCH"
        24 },
        25 {
        26 "href": "https://api-m.paypal.com/v2/checkout/orders/5O190127TN364715T/confirm-payment-source",
        27 "rel": "confirm",
        28 "method": "POST"
        29 }
        30 ]
        31}

        Step 2: Specify SEPA Direct Debit as the payment method

        To specify SEPA Direct Debit as the payment method the buyer selected in your user interface, confirm the payment source for the order.

        Sample request

        Limited release API endpoint used: Confirm payment source

          1curl -v -X POST https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T/confirm-payment-source \
          2-H "Content-Type: application/json" \
          3-H "Authorization: Bearer <Access-Token>" \
          4-d '{
          5 "payment_source": {
          6 "bank": {
          7 "sepa_debit": {
          8 "iban": "DE92612623452402508108",
          9 "account_holder_name": "John Doe",
          10 "billing_address": {
          11 "address_line_1": "Kantstraße 64",
          12 "address_line_2": "#100",
          13 "admin_area_1": "Freistaat Sachsen",
          14 "admin_area_2": "Annaberg-buchholz",
          15 "postal_code": "09456",
          16 "country_code": "DE"
          17 },
          18 "attributes": {
          19 "mandate": {
          20 "type": "RECURRENT"
          21 },
          22 "customer": {
          23 "id": "jd120252fg4dm"
          24 }
          25 },
          26 "experience_context": {
          27 "locale": "en-DE",
          28 "return_url": "https://example.com/return",
          29 "cancel_url": "https://example.com/cancel"
          30 }
          31 }
          32 }
          33 }
          34}'

          Modify the code

          After you copy the code in the sample request, modify the following:

          • Access-Token - Your access token.
          • Order ID - In the URI for the API call, replace the sample ID with your order ID. In the sample, the order ID is 5O190127TN364715T.
          • payment_source.bank.sepa_debit - Specify SEPA Direct Debit as payment method and provide required fields.
            • iban - buyer's IBAN
            • account_holder_name - buyer's account holder name
            • billing_address - buyer's full billing address
            • attributes - buyer's order attributes
              • mandate.type - ONE_OFF for one-time payment and RECURRENT if you want to store token and use it for future payments.
              • customer.id - unique customer identifier in your system
            • experience_context - Specify the preferred language for returned errors, the URL the buyer is returned to after approving the purchase with their selected payment method, and the URL the buyer is returned to after canceling an approval with their selected payment method. The return_url and cancel_url are mandatory fields, this integration requires you specify them to handle the handoff from the payment method back to your site. You can use the cancel_url to redirect buyers when an error occurs while they're on the payment method's site, so make sure your cancel URL works for that situation as well as an actual cancellation by the buyer.

          Step result

          A successful request results in the following:

          • A return status code of HTTP 200 OK.
          • A JSON response body that contains order details and HATEOAS links. You'll use the payer-action redirect in the next step. See also: HATEOAS links.

          Sample response

            1{
            2 "id": "5O190127TN364715T",
            3 "intent": "CAPTURE",
            4 "status": "PAYER_ACTION_REQUIRED",
            5 "payment_source": {
            6 "bank": {
            7 "sepa_debit": {
            8 "iban_last_chars": "8108",
            9 "account_holder_name": "John Doe",
            10 "attributes": {
            11 "token": {
            12 "id": "JB7L5VQ477TD6D4A",
            13 "type": "BANK_REFERENCE_TOKEN"
            14 }
            15 }
            16 }
            17 }
            18 },
            19 "links": [
            20 {
            21 "href": "https://api-m.paypal.com/v2/checkout/orders/5O190127TN364715T",
            22 "rel": "self",
            23 "method": "GET"
            24 },
            25 {
            26 "href": "https://www.paypal.com/directdebit/mandate/authorize?cart_id=5O190127TN364715T&auth_code=C21_A.AAfdTmGCivnRO87AS8Z1Ut_Qp_ffrhsHTTcC15wQBuRd4yh75bE5_Qu82DMCm8y9pGY012yPL6bqzDOcJEzGdiaV6Tk8cA&locale.x=de-DE",
            27 "rel": "payer-action",
            28 "method": "GET"
            29 }
            30 ]
            31}

            Step 3: Redirect buyer to the mandate approval website

            In your user interface, attach the payer-action redirect returned in the Confirm payment source call to a button that sends the buyer to the page that allow to approve the mandate.

            In the sample, the redirect is: "https://www.paypal.com/directdebit/mandate/authorize?cart_id=5O190127TN364715T&auth_code=C21_A.AAfdTmGCivnRO87AS8Z1Ut_Qp_ffrhsHTTcC15wQBuRd4yh75bE5_Qu82DMCm8y9pGY012yPL6bqzDOcJEzGdiaV6Tk8cA&locale.x=de-DE".

            Step result

            A successful approval results in the following:

            • The order status changes to APPROVED.

            Step 4: Capture payment for the order

            After status of an order changed to APPROVED it is ready to be captured.

            Sample request

            API endpoint used: Capture payment for order

              1curl -v -X POST https://api-m.sandbox.paypal.com/v2/checkout/orders/84745544P6340640G/capture \
              2 -H "Content-Type: application/json" \
              3 -H "Authorization: Bearer Access-Token" \
              4 -H "PayPal-Request-Id: 123e4567-e89b-12d3-a456-426655440040"

              Modify the code

              After you copy the code in the sample request, modify the following:

              • Access-Token - Your access token.
              • Order ID - In the URI for the API call, replace the sample ID with the order ID returned by the create order or confirm-payment-source call.
              • PayPal-RequestId - Replace the sample ID with a unique ID you generate. This ID helps prevent duplicate captures in the event that the API call is disrupted. See also: API idempotency.

              Step result

              A successful request results in the following:

              • A return status code of HTTP 201 Created.
              • The order status changes to COMPLETED for instant and PENDING for delayed payment.
              • A JSON response body that contains details for the captured payment. Use the ID returned if you need to refund the transaction in the future.

              Sample response

                1{
                2 "id": "5O190127TN364715T",
                3 "status": "COMPLETED",
                4 "payment_source": {
                5 "bank": {
                6 "sepa_debit": {
                7 "iban_last_chars": "8108",
                8 "account_holder_name": "John Doe",
                9 "attributes": {
                10 "token": {
                11 "id": "JB7L5VQ477TD6D4A",
                12 "type": "BANK_REFERENCE_TOKEN"
                13 }
                14 }
                15 }
                16 }
                17 },
                18 "purchase_units": [
                19 {
                20 "reference_id": "default",
                21 "payments": {
                22 "captures": [
                23 {
                24 "id": "3C679366HH908993F",
                25 "status": "COMPLETED",
                26 "amount": {
                27 "currency_code": "EUR",
                28 "value": "100.00"
                29 },
                30 "seller_protection": {
                31 "status": "NOT_ELIGIBLE"
                32 },
                33 "final_capture": true,
                34 "seller_receivable_breakdown": {
                35 "gross_amount": {
                36 "currency_code": "EUR",
                37 "value": "100.00"
                38 },
                39 "paypal_fee": {
                40 "currency_code": "EUR",
                41 "value": "3.00"
                42 },
                43 "net_amount": {
                44 "currency_code": "EUR",
                45 "value": "97.00"
                46 }
                47 },
                48 "create_time": "2021-06-21T21:10:39Z",
                49 "update_time": "2021-06-21T21:10:39Z",
                50 "links": [
                51 {
                52 "href": "https://api-m.paypal.com/v2/payments/captures/3C679366HH908993F",
                53 "rel": "self",
                54 "method": "GET"
                55 },
                56 {
                57 "href": "https://api-m.paypal.com/v2/payments/captures/3C679366HH908993F/refund",
                58 "rel": "refund",
                59 "method": "POST"
                60 }
                61 ]
                62 }
                63 ]
                64 }
                65 }
                66 ]
                67}

                Step 5: Notify buyer of success

                After a successful capture, notify the buyer of a successful transaction. You can:

                • Display a confirmation page on your site
                • Send a confirmation email

                Step 6: Capture order using token for recurrent payments

                When you pass mandate type of RECURRENT for confirm-payment-source, you receive token as a response. You can use it to process recurring payments.

                Sample request

                API endpoint used: Capture payment for order

                  1curl -v -X POST https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T/capture \
                  2-H "Content-Type: application/json" \
                  3-H "Authorization: Bearer <Access-Token>" \
                  4-H "PayPal-Request-Id: 123e4567-e89b-12d3-a456-426655440040" \
                  5-d '{
                  6 "payment_source": {
                  7 "bank": {
                  8 "sepa_debit": {
                  9 "bank_reference_token": "JB7L5VQ477TD6D4A",
                  10 "experience_context": {
                  11 "locale": "en-GB",
                  12 "return_url": "https://example.com/return",
                  13 "cancel_url": "https://example.com/cancel"
                  14 }
                  15 }
                  16 }
                  17 }
                  18}'

                  Modify the code

                  After you copy the code in the sample request, modify the following:

                  • Access-Token - Your access token.
                  • Order ID - In the URI for the API call, replace the sample ID with the order ID returned by the create order or confirm-payment-source call.
                  • PayPal-RequestId - Replace the sample ID with a unique ID you generate. This ID helps prevent duplicate captures in the event that the API call is disrupted. See also: API idempotency.
                  • payment_source.bank.sepa_debit.bank_reference_token - Token that was returned from confirm-payment-source call when passing RECURRENT mandate type.

                  Step result

                  A successful request results in the following:

                  • A return status code of HTTP 201 Created.
                  • The order status changes to COMPLETED for instant and PENDING for delayed payment.
                  • A JSON response body that contains details for the captured payment. Use the ID returned if you need to refund the transaction in the future.

                  Sample response

                    1{
                    2 "id": "5O190127TN364715T",
                    3 "status": "COMPLETED",
                    4 "payment_source": {
                    5 "bank": {
                    6 "sepa_debit": {
                    7 "iban_last_chars": "8108",
                    8 "account_holder_name": "John Doe"
                    9 }
                    10 }
                    11 },
                    12 "purchase_units": [
                    13 {
                    14 "reference_id": "default",
                    15 "payments": {
                    16 "captures": [
                    17 {
                    18 "id": "3C679366HH908993F",
                    19 "status": "COMPLETED",
                    20 "amount": {
                    21 "currency_code": "EUR",
                    22 "value": "100.00"
                    23 },
                    24 "seller_protection": {
                    25 "status": "NOT_ELIGIBLE"
                    26 },
                    27 "final_capture": true,
                    28 "seller_receivable_breakdown": {
                    29 "gross_amount": {
                    30 "currency_code": "EUR",
                    31 "value": "100.00"
                    32 },
                    33 "paypal_fee": {
                    34 "currency_code": "EUR",
                    35 "value": "3.00"
                    36 },
                    37 "net_amount": {
                    38 "currency_code": "EUR",
                    39 "value": "97.00"
                    40 }
                    41 },
                    42 "create_time": "2021-06-21T21:10:39Z",
                    43 "update_time": "2021-06-21T21:10:39Z",
                    44 "links": [
                    45 {
                    46 "href": "https://api-m.paypal.com/v2/payments/captures/3C679366HH908993F",
                    47 "rel": "self",
                    48 "method": "GET"
                    49 },
                    50 {
                    51 "href": "https://api-m.paypal.com/v2/payments/captures/3C679366HH908993F/refund",
                    52 "rel": "refund",
                    53 "method": "POST"
                    54 }
                    55 ]
                    56 }
                    57 ]
                    58 }
                    59 }
                    60 ]
                    61}

                    Next steps

                    • Test and go live - Test your integration and use the simulation server to run success and failure scenarios.
                    • Negative testing - Perform negative testing of common error conditions.

                    Common Errors

                    Reason Code Description What you should do
                    CURRENCY_NOT_SUPPORTED_FOR_BANK The payment_source does not support the currency of the Order. For ACH debit, only USD is supported and for SEPA debit, only EUR is supported. You provided different currency than EUR. You need to change currency to EUR.
                    IBAN_COUNTRY_NOT_SUPPORTED Country code of issuer bank for the provided IBAN is not supported for SEPA debit payments. You provided IBAN from a country that is not supported for SEPA Direct Debit payments. You need to provide different account.
                    INVALID_IBAN IBAN provided is not a valid bank account number. You provided IBAN that is not valid - either in length or its schema. Make sure that you provide IBAN as provided in the ISO specification.
                    NOT_ENABLED_FOR_BANK_PROCESSING The API Caller account is not setup to be able to process bank payments. Please contact your PayPal account manager. Configuration of your account is incorrect for this integration. You need to contact PayPal account manager for support.
                    ONLY_ONE_BANK_SOURCE_ALLOWED More than one payment method within the bank payment object is not supported. You provided more that one payment_source in the request or multiple payment_source.bank accounts. This integration accepts only one form of payment source.
                    SETUP_ERROR_FOR_BANK The API Caller account setup, for bank payments, is incomplete or incorrect. Please contact your PayPal account manager. Configuration of your account is incorrect for this integration. You need to contact PayPal account manager for support.
                    IDENTIFIER_NOT_FOUND Specified identifier was not found. Please verify the correct identifier was used and try the request again. Identifier provided in the request is malformed. Make sure that the correct bank_reference_token identifier is used and it is the same as the one from the response of confirm-payment-source.

                    If you accept cookies, we’ll use them to improve and customize your experience and enable our partners to show you personalized PayPal ads when you visit other sites. Manage cookies and learn more