---
title: "Create a Payment Source"
method: POST
path: "/2024-09/payment_sources"
tags: ["Payment Sources"]
---

# Create a Payment Source

`POST /2024-09/payment_sources`

## Request

- Base URL: `https://public-api.easyship.com`
- URL: `https://public-api.easyship.com/2024-09/payment_sources`
- Auth: HTTP bearer

Create a payment sources.

Easyship won't hold the details of your credit card. We use `stripe token` to attach the credit card to your easyship account on Stripe.
Please upload your credit card to stripe via Stripe Token JS.

Example:
<details>
  <summary>Stripe Token JS Example</summary>

  ```html
  <script src="https://js.stripe.com/v3/"></script>
  <script>
    // Retrieve Easyship stripe publishable api key through `GET /2024-09/account/stripe`
    var stripe = Stripe('stripe_publishable_api_key');

    // Create an instance of Elements.
    // https://stripe.com/docs/js/elements_object/create_element?type=card
    var elements = stripe.elements();

    // Create a CardElement
    var card = elements.create('card')

    // Create your token from the CardElement data
    // https://stripe.com/docs/js/tokens/create_token?type=cardElement
    stripe.createToken(card).then(function (result) {
      if (result.error) {
        // error handling
      } else {
        // You would receive the `stripe token` with prefix `tok_`.
        // `POST /2024-09/payment_sources` here to attach your card to Easyship
        var token = result.token;
      }
    });
  </script>
  ```

</details>

When the credit card needs 3DS (with response status code 202), proceed with the next step found in `POST /2024-09/payment_sources/confirm`.

If the payment source type is bank account, you'll receive a status code 202, indicating the need to submit the bank account information.
Easyship won't hold the details of your bank account. We use `setup intent` to attach the bank account to your easyship account on Stripe.

Note: A bank account payment source is only available for US companies.

Example:
<details>
  <summary>Stripe Bank Account JS Example</summary>

  ```html
    <script>
      // Retrieve Easyship stripe publishable api key through `GET /2024-09/account/stripe`
      const stripe = Stripe('stripe_publishable_api_key');

      // Use the form that already exists on the web page.
      const paymentMethodForm = document.getElementById('payment-method-form');

      paymentMethodForm.addEventListener('submit', (ev) => {
        ev.preventDefault();
        const accountHolderNameField = document.getElementById('account-holder-name');
        const emailField = document.getElementById('email-field');

        // Retrieve the client secret from POST /2024-09/payment_sources.
        const clientSecretField = document.getElementById('client-secret-field');

        // Calling this method will open the dialog to submit bank account information.
        stripe.collectBankAccountForSetup({
          clientSecret: clientSecretField.value,
          params: {
            payment_method_type: 'us_bank_account',
            payment_method_data: {
              billing_details: {
                name: accountHolderNameField.value,
                email: emailField.value,
              },
            },
          }
        })
        .then(({setupIntent, error}) => {
          if (error) {
            console.error(error.message);
          } else {
            // POST /2024-09/payment_sources/confirm to finalize the bank account payment source at Easyship
          }
        });
      });
    </script>
  ```

</details>

Once the bank account information has been submitted successfully, proceed with the next step found in `POST /2024-09/payment_sources/confirm`.


Required authorization scope: `public.payment_source:write`

## Request body

- union
  - PaymentSourceCreateCard
    - `type` 'card', required: Type of the payment source
    - `verify_3ds` boolean: Force 3DS validation. If 3DS is required, a Stripe Client Secret will be provided for confirmation. The confirmation must be handled with [Stripe JS](https://docs.stripe.com/js/setup_intents/handle_next_action). This behavior will be enforced in the upcoming API version.
    - `stripe_token` string, required: Token generated via stripe js.
    - `holder` object
      - `name` string: Card holder's name. This will only be applicable if the name was not assigned during token generation.
  - PaymentSourceCreateBankAccount
    - `type` 'bank_account', required: Type of the payment source

## Response `201`

payment source successfully created

- PaymentSourceSingle: Payment source details
  - `payment_source` PaymentSource
    - `id` string, uuid: Payment source id in Easyship
    - `third_party_source_id` string: Third party payment source id
    - `payment_method_type` 'card' | 'bank_account'
    - `bank_account` object
      - `bank_name` string: Bank name
      - `holder_name` string: Account holder name
      - `last_four_digits` string: Last four digits of bank account number
      - `routing_number` string: Routing number
      - `is_verified` boolean: Whether the bank account is verified by Stripe
    - `card` object
      - `brand` string: Credit card brand
      - `expiration_year` string: The expiration year of the card
      - `expiration_month` string: The expiration month of the card
      - `last_four_digits` string: Last four digits of credit card
      - `holder_name` string, nullable: Card holder name
  - `meta` Meta
    - `request_id` string: An unique ID represent the request.

## Other responses

- `202`: action required
- `422`: credit card has expired

## Changes

- **2026-11-03** `b47b54b748a7`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/easyship/apis/easyship-public-api/changes/2024-09/payment_sources/post.md)

---

[API](https://skmtc.dev/easyship/apis/easyship-public-api.md) - [All operations](https://skmtc.dev/easyship/apis/easyship-public-api/llms.txt) - [OpenAPI document](https://skmtc.dev/easyship/apis/easyship-public-api/revisions/b47b54b748a7?raw)
