


# How to use
1. install npm package using npm, pnpm or yarn
```bash
npm install @airwallex/node-sdk@beta
// or
pnpm install @airwallex/node-sdk@beta
// or
yarn add @airwallex/node-sdk@beta
```

2. initialize Airwallex instance
```ts
import { Airwallex } from '@airwallex/awx-node-sdk';
  const airwallex = new Airwallex({
    clientId: 'YOUR CLIENT ID',
    apiKey: 'YOUR API KEY',
    env: 'demo', // can be 'demo' or 'prod'
  });
```

3. call the endpoint
```ts
  // for example, if you want to get cards and handle the error
    const cards = await airwallex.issuing.cards.getCards({ card_status: 'ACTIVE' }).catch(error => {
      if (error instanceof ApiError) {
        console.log('Error: ', error);
      } else {
        throw new Error('Unknown error: ' + error);
      }
    });

  // for example, if you want to create a card
  const card = await airwallex.issuing.cards.createCard(
    {
      "authorization_controls": {
        "allowed_merchant_categories": ["7531"],
        "allowed_transaction_count": "SINGLE",
        "transaction_limits": {
          "cash_withdrawal_limits": [
            {
              "amount": 1000,
              "interval": "PER_TRANSACTION"
            }
          ],
          "currency": "USD",
          "limits": [
            {
              "amount": 1000,
              "interval": "PER_TRANSACTION"
            }
          ]
        }
      },
      "created_by": "John Smith",
      "form_factor": "VIRTUAL",
      "note": "API SDK Test",
      "request_id": generateRequestId(),
      "cardholder_id": "ef2ba01c-50a2-44e9-ae06-6114d92a9b63",
      "is_personalized": false,
      "program": {
          "purpose": "COMMERCIAL"
      }
    }
  );

  # for example, if you want to use a custom header and timeout
  const card = await airwallex.issuing.cards.createCard(
    {
      "authorization_controls": {
        "allowed_merchant_categories": ["7531"],
        "allowed_transaction_count": "SINGLE",
        "transaction_limits": {
          "cash_withdrawal_limits": [
            {
              "amount": 1000,
              "interval": "PER_TRANSACTION"
            }
          ],
          "currency": "USD",
          "limits": [
            { 
              "amount": 1000,
              "interval": "PER_TRANSACTION"
            }
          ]
        }
      },
      ...
    },
    {
      headers: {
          'x-on-behalf-of': 'account_id'
      },
      timeout: 10000
    },
  );

  // for example, if you want to call a undocumented/experimental endpoint
  const cards = await airwallex.get('/api/v1/issuing/cards', {
      params: {
          card_status: 'ACTIVE'
      },
      headers: {
          'x-on-behalf-of': 'account_id'
      },
      timeout: 10000
  }).catch(error => {
      if (error instanceof ApiError) {
          console.log('Error: ', error);
      } else {
          throw new Error('Unknown error: ' + error);
      }
  });
```

# Versioning

SDK versions follows semantic versioning.

Major version: Follows the existing Platform APIs Versioning for backwards incompatible changes.

Minor version: Follows the existing Platform APIs Versioning for backwards compatible changes.

Patch version: Reserved for bug fixes and changes that do not introduce changes to the API.

The SDK is in Beta. The version format is '<Major>.<Minor>.<Patch>-beta.<beta version number>' like 1.0.0-beta.1.

Airwallex Client APIs are currently version controlled using a date-based format, only creating new versions whenever backward incompatible changes are released.

For SDK 1.0.0-beta.1, it supports API version 2025-02-14 and has limited support for later API versions.

During Beta, we expect to release a new version of the SDK alongside new Client API versions or patch fixes.

# Available options for creating airwallex instance

| Option          | Required | Type    | Description                        |Default  |
|-----------------|----------|---------|------------------------------------|---------
| clientId        | Yes      | string  | Can be obtained from webapp        | /       |
| apiKey          | Yes      | string  | Can be obtained from webapp        | /       |
| env             | Yes      | string  | 'demo' / 'prod'                    | demo    |
| timeout         | No       | number  | Timeout for HTTP requests (ms)     | 30000   |
| enableTelemetry | No       | boolean | Enable telemetry for HTTP requests | true    |
| retry           | No       | number  | Number of retries for HTTP requests| 1       |
| retryDelay      | No       | number  | Base delay between retries (ms)    | 300     |

# Error Handling

The SDK provides several error types to help you handle different kinds of errors that might occur during API calls.

## Error Types

| Error Type | HTTP Status | Description | When It Occurs |
|------------|-------------|-------------|---------------|
| `ApiError` | Any | Base error class for all API-related errors | Parent class for all specific error types |
| `NetworkError` | N/A | Network connectivity issues | When the client can't connect to the server (e.g., network down, DNS failure) |
| `TimeoutError` | N/A | Request timeout | When the request takes too long to complete |
| `AuthenticationError` | 401 | Authentication failed | Invalid or expired credentials |
| `AuthorizationError` | 403 | Authorization failed | Valid credentials but insufficient permissions |
| `NotFoundError` | 404 | Resource not found | When the requested resource doesn't exist |
| `ValidationError` | 400 | Request validation failed | Invalid request parameters or payload |
| `RateLimitError` | 429 | Rate limit exceeded | Too many requests in a short time period |
| `ServerError` | 500+ | Server-side error | Internal server error or service unavailable |

## Error Properties

All error instances include the following properties:

- `message`: Human-readable error message
- `name`: The name of the error type (e.g., "ValidationError")
- `status`: HTTP status code (when applicable)
- `data`: Additional error details from the API response
- `headers`: Response headers

## Retryable Errors

The SDK automatically retries requests for errors that are considered retryable:
- `TimeoutError`
- `NetworkError`

You can configure retry behavior when initializing the client.

# example use cases

There's some example scripts under ./examples.

## The steps to run these scripts:
1. Set up the env variables for the corresponding client ID and API key in .env. Consult the account manager if there're permission issues.

2. Install ts-node or npx.

3. Run the script like `ts-node ./examples/pa.ts` or `npx node ./examples/pa.ts`.

For ./examples/pa.ts, it runs the use case for [Guest User Checkout](https://www.airwallex.com/docs/payments__native-api__guest-user-checkout).

The operations in the script:
1. Get the customer list
2. Create a new customer
3. Get the payment intent list
4. Create a payment intent for the new customer
5. Confirm the payment intent

The output looks like:

```bash

Customers: {
  has_more: false,
  items: [
    {
      id: 'custom_id',
      request_id: '992d802a-d0c9-42ae-ae74-20959bcb0b0b',
      merchant_customer_id: 'merchant_customer_id',
      email: 'john@example.com',
      phone_number: '',
      created_at: '2025-03-26T22:16:40+0000',
      updated_at: '2025-03-26T22:16:40+0000'
    },
    ...
  ]
}
Customer created: {
  id: 'new_customer_id',
  request_id: 'c3a8463a-5a0d-46bf-97d3-bc676e1a972d',
  merchant_customer_id: 'a_merchant_customer_id',
  email: 'john@example.com',
  phone_number: '',
  client_secret: 'xxxxxxxx',
  created_at: '2025-03-26T22:19:00+0000',
  updated_at: '2025-03-26T22:19:00+0000'
}
Payment Intents: {
  has_more: true,
  items: [
    {
      latest_payment_attempt: [Object],
      id: 'int_hkdmfsn96h5unqewweg',
      request_id: '341d2a4b-58fb-40c2-9533-457fb3c387ad',
      amount: 100,
      currency: 'USD',
      merchant_order_id: '5e7925f4-42e3-44b1-9a20-79254aef48dd',
      descriptor: 'Pa Test',
      status: 'SUCCEEDED',
      captured_amount: 100,
      created_at: '2025-03-26T22:16:41+0000',
      updated_at: '2025-03-26T22:16:42+0000'
    },
    ...
  ]
}
Payment Intent created: {
  id: 'payment_intent_id',
  request_id: '8109f8b2-1bbe-4f22-ae94-874c3daf156c',
  amount: 100,
  currency: 'USD',
  merchant_order_id: 'merchant_order_id',
  descriptor: 'Pa Test',
  status: 'REQUIRES_PAYMENT_METHOD',
  captured_amount: 0,
  created_at: '2025-03-26T22:19:00+0000',
  updated_at: '2025-03-26T22:19:00+0000',
  client_secret: 'xxxxxxx',
  original_amount: 100,
  original_currency: 'USD'
}
Payment Intent confirmed: {
  latest_payment_attempt: {
    id: 'attempt_id',
    amount: 100,
    currency: 'USD',
    payment_method: { type: 'card', card: [Object] },
    merchant_order_id: 'merchant_order_id',
    payment_intent_id: 'payment_intent_id',
    status: 'AUTHORIZED',
    provider_transaction_id: 'provider_transaction_id',
    payment_method_transaction_id: 'payment_method_transaction_id',
    provider_original_response_code: '00',
    authorization_code: 'xxxxxx',
    captured_amount: 0,
    refunded_amount: 0,
    created_at: '2025-03-26T22:19:01+0000',
    updated_at: '2025-03-26T22:19:02+0000',
    settle_via: 'airwallex',
    authentication_data: {
      ds_data: [Object],
      fraud_data: [Object],
      avs_result: 'not_attempted',
      cvc_result: 'matched',
      cvc_code: 'M'
    },
    payment_method_options: { card: [Object] }
  },
  id: 'payment_intent_id',
  request_id: '7f278406-285d-48a3-bb10-8a28766f2fc3',
  amount: 100,
  currency: 'USD',
  merchant_order_id: 'merchant_order_id',
  descriptor: 'Pa Test',
  status: 'SUCCEEDED',
  captured_amount: 100,
  created_at: '2025-03-26T22:19:00+0000',
  updated_at: '2025-03-26T22:19:02+0000',
  original_amount: 100,
  original_currency: 'USD'
}

```
