# Overview

Leverage the power of Swish's API to create powerful integrations with your favourite tools and services.

The Swish API allows you to read and write information across your store's Swish profiles. You can do things like read a Wishlist, add new items, and much more.

This section describes how to use the Swish API and its resources. If you have any questions or issues, please contact the [Swish Support](mailto:support@swish.app).

## API Endpoint

The latest Swish API can be accessed using the `https://swish.app/api/2025-04` endpoint.

## API Reference

<table data-card-size="large" data-view="cards"><thead><tr><th data-card-target data-type="content-ref"></th><th></th><th data-hidden data-card-cover data-type="files"></th></tr></thead><tbody><tr><td><a href="/pages/He5CegA8imaj6aBcK7P2">/pages/He5CegA8imaj6aBcK7P2</a></td><td>Learn more about the endpoints you can use from Swish's REST API.</td><td><a href="/files/ETHeM1zFf6IQ77z2OLYj">/files/ETHeM1zFf6IQ77z2OLYj</a></td></tr></tbody></table>

## Authentication & Rate Limits

<table data-card-size="large" data-view="cards"><thead><tr><th data-card-target data-type="content-ref"></th><th></th><th data-hidden data-card-cover data-type="files"></th></tr></thead><tbody><tr><td><a href="/pages/rSek5jM1lDWEnjUdyBHb">/pages/rSek5jM1lDWEnjUdyBHb</a></td><td>Create an API access token and authenticate your API requests.</td><td><a href="/files/LdGlyKN7qN4wKp4Flh1T">/files/LdGlyKN7qN4wKp4Flh1T</a></td></tr><tr><td><a href="/pages/h33NpKIfbswC8ClMWpp2">/pages/h33NpKIfbswC8ClMWpp2</a></td><td>Understand how API requests are rate limited.</td><td><a href="/files/Igi3eh8xJ7PP3VHkgAP8">/files/Igi3eh8xJ7PP3VHkgAP8</a></td></tr></tbody></table>

## Errors & Pagination

<table data-card-size="large" data-view="cards"><thead><tr><th data-card-target data-type="content-ref"></th><th></th><th data-hidden data-card-cover data-type="files"></th></tr></thead><tbody><tr><td><a href="/pages/w8FYizTrs9FP0Pu7ZPoU">/pages/w8FYizTrs9FP0Pu7ZPoU</a></td><td>Learn about API errors, how they're structured and how to handle them.</td><td><a href="/files/wjgSYrOT4UorQBuFap1a">/files/wjgSYrOT4UorQBuFap1a</a></td></tr><tr><td><a href="/pages/rNPXmcfsIwqoA7v00Feb">/pages/rNPXmcfsIwqoA7v00Feb</a></td><td>Paginate through API list results.</td><td><a href="/files/NbjO6LmFWYAg8MIlyLAB">/files/NbjO6LmFWYAg8MIlyLAB</a></td></tr></tbody></table>

## Client Libraries

<table data-card-size="large" data-view="cards"><thead><tr><th data-type="content-ref"></th><th></th><th data-hidden data-card-cover data-type="files"></th></tr></thead><tbody><tr><td><a href="/pages/RScXcuiSt9P5Vw1sQ7RZ">/pages/RScXcuiSt9P5Vw1sQ7RZ</a></td><td>Use our libraries to interact with the API.</td><td><a href="/files/vSBSYR4QcvVDA1KsuZci">/files/vSBSYR4QcvVDA1KsuZci</a></td></tr></tbody></table>


# Authentication

The Swish API uses access tokens to authenticate requests.

{% hint style="info" %}
Please [contact our support](mailto:support@swish.app) team to request an admin token.
{% endhint %}

API requests are authenticated using the [Bearer Auth scheme](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication#authentication_schemes). To authenticate a request, provide the token in the `Authorization` header of the request:

```sh
curl -H "Authorization: Bearer <your_access_token>" https://swish.app/api/2025-04/items
```

{% hint style="warning" %}
Please be sure to keep your API access tokens secure! Do not share them in emails, chat messages, client-side code or publicly accessible sites.

If you have accidentally shared an API access token publicly, you must [contact our support](mailto:support@swish.app) team immediately.
{% endhint %}

## Swish API access scopes

API access tokens can be scoped to a Shopify customer, a temporary session, or all store data when using an admin token.

### Admin token

All third-party integrations require an admin token. This token can be use to access and manage all resources with the Swish API. They must be used in a **secure environment** and **should never be shared**.

An admin token can be used to [create profile tokens](/swish-api/api-reference/profiles#profiles-token) with limited access. These tokens can be shared with a client and may be stored there as well.&#x20;

{% hint style="warning" %}
Profile tokens expire after one day and need to be replaced with a new token when that happens.
{% endhint %}

#### Load user data with admin token

Using an admin token allows you to impersonate a customer or session with the `Profile` header. This technique lets you access user data without generating a personal token for them. Ensure this method is only applied in secure environments, such as on a server.

```sh
curl -L \
  --url 'https://swish.app/api/2025-04/items' \
  --header 'Authorization: Bearer JWT' \
  --header 'Profile: gid://shopify/Customer/1234567890'
```

### Customer token

A customer token is specific to an individual Shopify customer account. It can be shared with a client authenticated as a signed-in customer. These tokens may be stored in the client's local storage for the duration of their session. Ensure secure storage with restricted access is used for token management.

```sh
curl -L \
  --request POST \
  --url 'https://swish.app/api/2025-04/profiles/token' \
  --header 'Authorization: Bearer <your admin token>' \
  --header 'Content-Type: application/json' \
  --data '{
    "customer": "gid://shopify/Customer/1234567890"
  }'
```

### Session token

Session tokens function similarly to customer tokens, but they are intended for visitors who haven't signed in yet. These tokens provide access to Swish features without requiring a user to sign in. When you create a new token without specifying a profile, the API will automatically generate a new session for you.

```sh
curl -L \
  --request POST \
  --url 'https://swish.app/api/2025-04/profiles/token' \
  --header 'Authorization: Bearer <your admin token>' \
  --header 'Content-Type: application/json'
```

When a customer logs in, replace their session token with a customer token. To link the previous session to the new customer session, provide the the customer and session IDs when creating the customer token.

```sh
curl -L \
  --request POST \
  --url 'https://swish.app/api/2025-04/profiles/token' \
  --header 'Authorization: Bearer <your admin token>' \
  --header 'Content-Type: application/json' \
  --data '{
    "customer": "gid://shopify/Customer/1234567890",
    "session": "gid://swish/Session/ebe9347c-6d2c-4d94-8542-d3a7e6e5ccd7"
  }'
```


# Rate limits

Different types of API methods are subject to different rate limits.

The response's HTTP headers are the authoritative source for the current number of API calls available to you or your app at any given time. The returned HTTP headers of any API request show your current rate limit status, as described below.

| Header name             | Description                                                                                                            |
| ----------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| `X-RateLimit-Limit`     | The maximum number of requests you're permitted to make in the current rate limit window.                              |
| `X-RateLimit-Remaining` | The number of requests remaining in the current rate limit window.                                                     |
| `X-RateLimit-Reset`     | The time at which the current rate limit window resets in [UTC epoch seconds](http://en.wikipedia.org/wiki/Unix_time). |


# Pagination

Some endpoints return paginated results. The formatting of a paginated result is always:

```json
{
  "pageInfo": {
    "next": "...",
    "previous": "..."
  },
  "data": []
}
```

The object `pageInfo` will be omitted if there are no next and previous pages.

The `pageInfo.next` or `pageInfo.previous` value can be added to the query parameters of the original query under the `page` key in order to get the next or previous page. The values can be omitted, which indicates that there is no next or previous page respectively.

## Example

You make a `GET` request to a paginated endpoint `/items`, and receive the following response:

```json
{
  "pageInfo": {
    "next": "next-page-cursor"
  },
  "data": []
}
```

In order to get the next page of results, you would take the cursor from `pageInfo.next` in the response body, and provide it as the value of the `page` key in a query to the same endpoint. The full path including query parameters of your request to get the next page of the listing is:

```
/items?page=next-page-cursor
```


# Errors

Swish uses conventional [HTTP response status codes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status) to indicate the success or failure of an API request. As a general rule:

* Status codes in the **`2xx`** range indicate success.
* Status codes in the **`4xx`** range indicate incorrect or incomplete parameters (e.g. a required parameter was omitted).
* Status codes in the **`5xx`** range indicate an error with Swish's servers.

Swish also outputs an error response formatted in JSON:

```json
{
  "error": {
    "message": "Item with ID 123 not found.",​
    "error": "Not Found",
    "statusCode": 404,​
    "requestId": "123e4567-e89b-12d3-a456-426614174000"
  }
}
```


# API Reference

The Swish API provides developers with a powerful and flexible way to interact with Swish's platform programmatically. It offers endpoints to manage content and integrate Swish functionalities into external applications.

This API is RESTful and supports standard HTTP methods like `GET`, `POST`, `PATCH`, and `DELETE`.

{% hint style="success" %}
Use our [Postman Collection](https://www.postman.com/swish-dot-app/swish/collection/xvr9qb7/swish-api-2025-04) to explore the API.
{% endhint %}


# Items

An Item in Swish belongs to a List and references a Shopify product/variant.

{% openapi src="<https://swish.app/api/2025-04/.well-known/openapi>" path="/items" method="get" %}
<https://swish.app/api/2025-04/.well-known/openapi>
{% endopenapi %}

{% openapi src="<https://swish.app/api/2025-04/.well-known/openapi>" path="/items" method="post" %}
<https://swish.app/api/2025-04/.well-known/openapi>
{% endopenapi %}

{% openapi src="<https://swish.app/api/2025-04/.well-known/openapi>" path="/items" method="delete" %}
<https://swish.app/api/2025-04/.well-known/openapi>
{% endopenapi %}

{% openapi src="<https://swish.app/api/2025-04/.well-known/openapi>" path="/items/{itemId}" method="patch" %}
<https://swish.app/api/2025-04/.well-known/openapi>
{% endopenapi %}

{% openapi src="<https://swish.app/api/2025-04/.well-known/openapi>" path="/items/{itemId}" method="delete" %}
<https://swish.app/api/2025-04/.well-known/openapi>
{% endopenapi %}

{% openapi src="<https://swish.app/api/2025-04/.well-known/openapi>" path="/items/{itemId}" method="get" %}
<https://swish.app/api/2025-04/.well-known/openapi>
{% endopenapi %}

{% openapi src="<https://swish.app/api/2025-04/.well-known/openapi>" path="/items/{itemId}/lists" method="put" %}
<https://swish.app/api/2025-04/.well-known/openapi>
{% endopenapi %}


# Lists

A List in Swish belongs to a Profile and contains Items.

{% openapi src="<https://swish.app/api/2025-04/.well-known/openapi>" path="/lists" method="get" %}
<https://swish.app/api/2025-04/.well-known/openapi>
{% endopenapi %}

{% openapi src="<https://swish.app/api/2025-04/.well-known/openapi>" path="/lists" method="post" %}
<https://swish.app/api/2025-04/.well-known/openapi>
{% endopenapi %}

{% openapi src="<https://swish.app/api/2025-04/.well-known/openapi>" path="/lists/{listId}" method="get" %}
<https://swish.app/api/2025-04/.well-known/openapi>
{% endopenapi %}

{% openapi src="<https://swish.app/api/2025-04/.well-known/openapi>" path="/lists/{listId}" method="patch" %}
<https://swish.app/api/2025-04/.well-known/openapi>
{% endopenapi %}

{% openapi src="<https://swish.app/api/2025-04/.well-known/openapi>" path="/lists/{listId}" method="delete" %}
<https://swish.app/api/2025-04/.well-known/openapi>
{% endopenapi %}

{% openapi src="<https://swish.app/api/2025-04/.well-known/openapi>" path="/lists/{listId}/items/order" method="put" %}
<https://swish.app/api/2025-04/.well-known/openapi>
{% endopenapi %}


# Profiles

A Swish profile is the entity to which Items and Lists belong.

{% openapi src="<https://swish.app/api/2025-04/.well-known/openapi>" path="/profiles/identify" method="post" %}
<https://swish.app/api/2025-04/.well-known/openapi>
{% endopenapi %}

{% openapi src="<https://swish.app/api/2025-04/.well-known/openapi>" path="/profiles/token" method="post" %}
<https://swish.app/api/2025-04/.well-known/openapi>
{% endopenapi %}


# API Client

Lightweight JS client for the Swish REST API.

The Swish API Client provides type-save methods for developers to interact with the API.&#x20;

{% hint style="warning" %}
When integrating Swish into a browser environment, using the [Browser library](/libraries/browser) is recommended.
{% endhint %}

## Requirements

This packages works in all JS environments were the [fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) is available.

## Installation

```sh
npm install @swishapp/api-client
```

## Usage

```typescript
import { createApiClient } from "@swishapp/api-client";

const swish = createApiClient({
  authToken: "your-api-auth-token"
});

const { data } = await swish.items.list();
```

## Reference

### Items

{% hint style="success" %}
For more details, refer to the [Items API reference](/swish-api/api-reference/items).
{% endhint %}

#### List all items

```typescript
const { data, error } = await swish.items.list();
```

#### List all items (pagination)

```typescript
const { data, error } = await swish.items.list({
  page: "page-cursor",
  limit: 20,
});
```

#### List all items (search query)

```typescript
const { data, error } = await swish.items.list({
  query: "product:123",
});
```

#### Create new item

```typescript
const { data, error } = await swish.items.create({ 
  productId: 123, variantId: 456, quantity: 1,
});
```

#### Delete multiple items

<pre class="language-typescript"><code class="lang-typescript"><strong>const { error } = await swish.items.delete([
</strong>  "item-id-1",
  "item-id-2",
]);
</code></pre>

#### Find item by ID

```typescript
const { data, error } = await swish.items.findById("item-id");
```

#### Update item by ID

```typescript
const { data, error } = await swish.items.updateById("item-id", {
  variantId: 456,
});
```

#### Delete item by ID

```typescript
const { error } = await swish.items.deleteById("item-id");
```

### Lists

{% hint style="success" %}
For more details, refer to the [Lists API reference](/swish-api/api-reference/lists).
{% endhint %}

#### List all lists

```typescript
const { data, error } = await swish.lists.list();
```

#### Create new list

```typescript
const { data, error } = await swish.lists.create({
  name: "Favourites",
});
```

#### Find list by ID

```typescript
const { data, error } = await swish.lists.findById("list-id");
```

#### Find list by ID (items sorted in custom order)

```typescript
const { data, error } = await swish.lists.findById("list-id", {
  sort: "customer"
});
```

#### Update list by ID

```typescript
const { data, error } = await swish.lists.updateById("list-id", {
  name: "New list name",
});
```

#### Delete list by ID

```typescript
const { error } = await swish.lists.deleteById("list-id");
```

#### Set  custom item order

```typescript
const { data, error } = await swish.lists.orderItems("list-id", {
  itemIds: ["item-id-2", "item-id-1"],
});
```

### Profiles

{% hint style="success" %}
For more details, refer to the [Profiles API reference](/swish-api/api-reference/profiles).
{% endhint %}

#### Create new token

```typescript
const { data, error } = await swish.profiles.createToken({
  customer: "gid://shopify/Customer/1234567",
})
```


# Browser

JS library to integrate Swish into a browser environment.

JavaScript library for integrating Swish on a Shopify web store (themes and headless stacks).

## Requirements

This library depends on the following browser APIs.

* [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)
* [Service Worker API](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API)
* [Web Workers API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API)

### Swish App Proxy

The Swish browser library requires a proxy service that operates on the same domain as the store. This service facilitates the loading of additional resources and ensures secure communication with the Swish API. The app proxy is automatically provided once the app has been installed.

If your store has it's own server (e.g. headless stack), then you will need to implement the proxy first. Please use the [Node.js library](/libraries/node.js) to implement the app proxy.

## Installation

To load the Swish app, you can either activate the Swish embed through your theme editor or install it via NPM. We recommend using the app embed for most scenarios. For headless stacks, NPM is necessary.

## Usage

```typescript
import { swishApp } from "/apps/wishlist/assets/swish.js";

const swish = await swishApp({
  proxy: {
    baseUrl: "/apps/wishlist"
  }
});

const { data } = await swish.api.items.list();
```

### Reference

#### Swish API

All Swish API functions can be accessed and are automatically scoped to the current user.&#x20;

```typescript
const { data } = await swish.api.items.list();
```

{% hint style="success" %}
Please refer to the [Swish API Client](/libraries/api-client) docs for a comprehensive list of available functions.
{% endhint %}

#### Swish UI Components

{% hint style="danger" %}
This feature is still under development!
{% endhint %}

To accelerate development, consider using our built-in UI components. These components follow a general design language and allow for some customisation. For a completely tailored user experience, creating your own UI components is recommended.

Our components load only when needed, enabling you to blend custom UI elements with our standard components without impacting your page speed.

<pre class="language-typescript"><code class="lang-typescript"><strong>await swish.ui.showSignIn({
</strong>  returnTo: window.location.pathname
});
</code></pre>


# Node.js

JS library to integrate Swish on a Node.js server.

## Swish app proxy for Node.js

The Swish browser library requires a proxy service that operates on the same domain as the store. This service facilitates the loading of additional resources and ensures secure communication with the Swish API.

### Installation

```sh
npm i @swishapp/node
```

### Usage

The example below is for Remix and needs to be adjusted for other frameworks.

```js
import { ActionFunction, LoaderFunction } from "@remix-run/node";
import { createProxy, MemoryStorage } from "@swishapp/node";

const swishProxy = createProxy({
  basePath: "/swish", // Needs to match the route path
  authToken: process.env.SWISH_API_TOKEN,
  storage: new MemoryStorage(), // Use MemoryStorage for development only!
  authenticate: async (request) => {
    // Authenticate the request and return customer id or null
    // Throw an error if the request cannot be authenticted
    return null;
  },
  onError: (error) => {
    console.error(error);
  },
});

export const loader: LoaderFunction = async ({ request }) =>
  swishProxy.forward(request);

export const action: ActionFunction = async ({ request }) =>
  swishProxy.forward(request);
```

The Swish app for browsers won't work on the server. Use it as a client only script!

```ts
// The proxy also serves the Swish brwoser app
import { createApp } from "/swish/assets/swish.js"; // Assuming the proxy runs on /swish

const swish = await createApp({
  proxy: {
    baseUrl: "/swish", // Use proxy route path
  },
});
```


# React

JS library to integrate Swish into a React project.

{% hint style="danger" %}
The REACT library is coming soon!
{% endhint %}

## Requirements

This package requires React 18 or newer.


