# Getting started

ShopBase enables you to create powerful e-commerce solutions for a variety of scenarios, including integrating your service into the ShopBase admin, build a ShopBase app & themes.

### Welcome to the ShopBase partner program! <a href="#create-a-shopbase-partner-account" id="create-a-shopbase-partner-account"></a>

Please follow our instructions below to get started.&#x20;

### Apply to become a ShopBase Partner <a href="#apply-shopbase-partner" id="apply-shopbase-partner"></a>

By joining the ShopBase partner program, you can create a development store (unlimited free-trial access with test payment gateway only), so you can freely test your products.&#x20;

You can register to become a ShopBase Partner by submitting [this form](https://shopbase.typeform.com/to/yeYflB), using the email you have just signed up for the regular store. We'll email you once your request is approved.

After being approved, you will have access to the [Partner Dashboard](https://accounts.shopbase.com/partners) and you can use your development store without submitting payment details. From your Partner Dashboard, you can manage the apps and themes that you build on ShopBase.

![](/files/-MiyNUXAq8EMtVbxZuW5)

## Build an app

Build apps for ShopBase merchants. See our ShopBase apps [Getting Started guide](/build-an-app/making-your-first-request) to get up-and-running quickly and make your first calls to the API.

## Build a theme

Build themes for ShopBase merchants. See our ShopBase themes [Getting Started guide](/build-a-theme/getting-started).


# Making your first request

This guide describes the basic steps for getting started with ShopBase's API. You can create your development stores to test your apps, themes, and other integrations that you build.

{% hint style="info" %}
The first step in building an app for ShopBase is to join the ShopBase Partner Program by [creating a partner account](/#create-a-shopify-partner-account).&#x20;
{% endhint %}

### Generate API credentials from the ShopBase admin <a href="#generate-api-credentials-from-the-shopify-admin" id="generate-api-credentials-from-the-shopify-admin"></a>

When you make an API call, you need to include API credentials to authenticate it. You can quickly generate API credentials by creating a private app from your development store's ShopBase admin. When you create the private app, ShopBase creates an API key and password, which you can include in API calls to the development store.

{% hint style="info" %}
To learn more about public and private apps, see [Authentication](/build-an-app/making-your-first-request/authentication).
{% endhint %}

**Steps:**

1. From your ShopBase admin, go to **Apps**.
2. Click **Manage private apps**.
3. Click **Create a new private app**.
4. In the **App details** section, enter a name for your app, and an emergency developer email.
5. In the **Admin API** section, select the areas of your store that you want the app to access.
6. Click **Save**.

After you save the app's details, the **Admin API** section shows the app's API key and password.

**Caution**

Treat the API key and password like you would any other password since whoever has access to these credentials has full API access to the store.

### Making your first request <a href="#making-your-first-request" id="making-your-first-request"></a>

You can use the API key and password that you generated for [basic HTTP authorization](https://en.wikipedia.org/wiki/Basic_access_authentication) of your first request. The URL format for basic authorization is as follows:

```
https://{username}:{password}@{shop}.onshopbase.com/admin/{resource}.json
```

* `{username}` — The API key that you generated
* `{password}` — The API password
* `{shop}` - The name that you entered for your development store
* `{resource}` — A resource endpoint from the [REST admin API](https://developers.shopbase.com/build-an-app-tutorial/rest-admin-api-reference)

A URL with real values looks like this:

```
https://38b3692b6b48a9712b8d909c46e6208d:c2dc0abbdef5825da69ee1647962ce2d@example.onshopbase.com/admin/products.json
```

The following curl request retrieves information by using the Shop resource and the `/admin/shop.json`endpoint:

```
curl -X GET https://{username}:{password}@{shop}.onshopbase.com/admin/shop.json -H 'Content-Type: application/json'
```

Substitute your own values, and then run the curl command from the command line to retrieve information from your development store.

### Sample App

You can use SampleApp from this [github repo](https://github.com/Beeketing/sbase-sampleapp) as a reference for understanding authentication flow of a ShopBase app and how to call ShopBase APIs with public app.<br>


# Authentication

Before it can interact with the ShopBase API, your app must provide the necessary authentication credentials in each HTTP request that it makes to ShopBase.

The way to provide these credentials depends on the type of app that you're developing. ShopBase supports two different types of apps: public apps and private apps.

### Public apps <a href="#public-apps" id="public-apps"></a>

A public app can interact with the ShopBase API on behalf of multiple stores, as long as the app has been granted explicit permission by each merchant who installs it.

You can [create a public app](/build-an-app/making-your-first-request/authentication/public-apps) from your [Partner Dashboard](https://accounts.shopbase.com/partners).

### Private apps <a href="#private-apps" id="private-apps"></a>

Private apps can interact with the ShopBase API on behalf of only one particular store. These apps authenticate with ShopBase through basic HTTP authentication. The required credentials must be generated from the ShopBase admin of the store that you want to connect with your app.

&#x20;To learn more about how authentication works for private apps, see [*Private authentication*](/build-an-app/making-your-first-request/authentication/private-apps).


# Public apps

A public ShopBase app can interact with the ShopBase API on behalf of multiple stores.

To authenticate with ShopBase using a public app, you'll need to generate the credentials from your Partner Dashboard and then use them to implement [OAuth](/build-an-app/making-your-first-request/authentication/oauth).

### Generate credentials from your Partner Dashboard

You can create a public application from your [Partner Dashboard](https://accounts.shopbase.com/partners).

To create an app:

1. Once you are ShopBase's partner, and you own a store, you could see **Manage public apps** from your profile menu. Click **Manage public apps** to go to your Partner Dashboard.
2. From your Partner Dashboard, click **Apps** > **Create app**.
3. Provide an app name and URL where you will place authentication url of your app.
4. Click **Create app**. You are directed to your app's overview page, where you can view the API key and API secret that you will need for OAuth.

![Create public app screen](/files/-Lc1xavBelpOQ65dsgHG)

### Manage Access From App to ShopBase

The Access Token is the primary method for your application to authenticate with the ShopBase system. To enhance connection security and reduce potential risks, we have implemented additional security layers.

Starting from May 21, 2025, 100% of API requests to ShopBase must comply with the following security layers:

* Mandatory Layer: Token Secret
* Optional Layer: Whitelisted IPs

#### Token Secret

The Token Secret is a confidential string that must be included in every request from your application to ShopBase. It must be passed in the HTTP header named `X-ShopBase-Token-Secret` .

To generate a Token Secret, go to Access Control >> Generate new secret.

<figure><img src="/files/l8Uv360afJCvNFRlNlHy" alt=""><figcaption><p>Generate new secret</p></figcaption></figure>

After clicking Generate, a new Secret will be created and displayed immediately. For security reasons, you must store it yourself — just like how you would store a password. We will permanently hide the secret right after you click Close.

<figure><img src="/files/Q3TZmpWYvDoPu9vuT7fv" alt=""><figcaption><p>Copy new secret</p></figcaption></figure>

You can create and manage up to 3 Token Secrets at the same time. The Switch button allows you to enable or disable the active status of each secret individually, and the Delete button will permanently remove it.

<figure><img src="/files/Z5pLChQZ9KAVNm0VWoa8" alt=""><figcaption><p>Manage list secret</p></figcaption></figure>

#### Whitelisted IPs

Whitelisted IP is an advanced security layer that allows you to configure specific IP addresses or IP ranges permitted to send requests from your application to ShopBase. This layer is not mandatory; however, we recommend using it to restrict access to trusted sources.

<figure><img src="/files/6QgKdsCuLLtCH6ohnDWn" alt=""><figcaption></figcaption></figure>

**Note**: Changes made in the Access Control section are not applied immediately. They will be synchronized with the system within up to **15 minutes**.

### Make authenticated requests <a href="#make-authenticated-requests" id="make-authenticated-requests"></a>

Public apps authenticate to ShopBase by including the `X-ShopBase-Access-Token` and  `X-ShopBase-Token-Secret` header fields in each HTTP request to the ShopBase API. This access token is obtained through an OAuth handshake. To learn more about how OAuth works, see [*OAuth*](/build-an-app/making-your-first-request/authentication/oauth).


# Private apps

Private apps can interact with the ShopBase API on behalf of only one particular store. These apps authenticate with ShopBase through basic HTTP authentication. The required credentials must be generated from the ShopBase admin of the store that you want to connect with your app.

{% hint style="info" %}
&#x20;The [ShopBase API License and Terms of Use](https://pages.shopbase.com/api-terms) governs your access to and use of the ShopBase API. Make sure you're familiar with these terms before you create an app.
{% endhint %}

### On this page

* [Generate credentials from the ShopBase admin](https://developers.shopbase.com/build-an-app-tutorial/making-your-first-request/authentication/private-apps#generate-credentials-from-the-shopify-admin)
* [Make authenticated requests](https://developers.shopbase.com/build-an-app-tutorial/making-your-first-request/authentication/private-apps#make-authenticated-requests)

### Generate credentials from the ShopBase admin <a href="#generate-credentials-from-the-shopify-admin" id="generate-credentials-from-the-shopify-admin"></a>

Before you can authenticate a private app to ShopBase, you need to generate the required credentials from the ShopBase admin of the store that you want to connect with your application. If you don't have a ShopBase store, then you can [create a development store](https://developers.shopbase.com/build-an-app-tutorial/making-your-first-request#create-a-development-store).

After you've provisioned a development store, log in and then generate the required credentials from the **development store admin**:

1. From your ShopBase admin, go to **Apps**.
2. Click **Manage private apps**, near the bottom of the page.
3. Click **Create a new private app**.
4. In the **App details** section, enter a name for the private app and a contact email address.

   ShopBase uses the email address to contact the developer if there is an issue with the private app, such as when an API change might break it.
5. In the **Admin API** section, select the areas of your store that you want the app to be able to access.
6. Click **Save**.

You'll see your API key and password in the **Admin API** section. You can use these credentials to make authenticated requests to the ShopBase store that uses your application.

{% hint style="info" %}
Treat the API key and password like you would any other password, because whoever has access to these credentials has full API access to the store.
{% endhint %}

### Make authenticated requests <a href="#make-authenticated-requests" id="make-authenticated-requests"></a>

A private app can make authenticated requests to the ShopBase Admin REST API using basic authentication or by including its ShopBase access token in the request header.

#### Basic authentication <a href="#basic-authentication" id="basic-authentication"></a>

Private apps can authenticate through basic HTTP authentication by using their Admin API key and password as a username and password. You can generate these credentials from the ShopBase admin of the store that you want to connect with your app.

Some HTTP clients support basic authentication by prepending `username:password@` to the hostname in the URL. For example:

```
GET https://4478eb7ac138a136852babd861956c19:3e5a6edec71eab039422c6444d02659d@johns-apparel.onshopbase.com/admin/shop.json
```

If your HTTP client doesn't support basic authentication using this method, then you can provide the credentials in the `Authorization` header field instead:

1. Join the API key and password with a single colon (`:`).
2. Encode the resulting string in base64 representation.
3. Prepend the base64-encoded string with `Basic` and a space:

   ```
   Authorization: Basic 
   NDQ3OGViN2FjMTM4YTEzNjg1MmJhYmQ4NjE5NTZjMTk6M2U1YTZlZGVjNzFlYWIwMzk0MjJjNjQ0NGQwMjY1OWQ=
   ```


# OAuth

Your app cannot read ShopBase data without authenticating first. It must get permission from a user before gaining access to any of the resources in the REST API.

This guide walks you through the authorization process, described in greater detail by the [OAuth 2.0 specification](https://tools.ietf.org/html/rfc6749).

### Terminology <a href="#terminology" id="terminology"></a>

Before learning more about the details of the authorization process, make sure that you're familiar with some of the key terms used in this guide:

* **Client**: Any app that wants access to a shop's data. A user must grant permission before the client can access any data.
* **API**: ShopBase's REST API, which the client can use to read and modify shop data.
* **User**: A ShopBase account holder, usually a merchant. The user gives permission to a client to access shop data through the REST API.

### The OAuth flow <a href="#the-oauth-flow" id="the-oauth-flow"></a>

ShopBase uses OAuth 2.0's [authorization code grant flow](https://tools.ietf.org/html/rfc6749#section-4.1) to issue access tokens on behalf of users.

1. The merchant makes a request to install the app.
2. The app redirects to ShopBase to load the OAuth grant screen and requests the required scopes.
3. ShopBase displays a prompt to receive authorization and prompts the merchant to login if required.
4. The merchant consents to the scopes and is redirected to the `redirect_uri`.
5. The app makes an access token request to ShopBase including the `client_id`, `client_secret`, and `code`.
6. ShopBase returns the access token and requested scopes.
7. The app uses the token to make requests to the ShopBase API.
8. ShopBase returns the requested data.

![](/files/-LkMsEqv1ca_i2l5q_WB)

### Step 1: Get client credentials

You need to [retrieve an API key and secret key](/build-an-app/making-your-first-request/authentication/public-apps) to identify the client during the authorization process.

### Step 2: Ask for permission <a href="#step-2-ask-for-permission" id="step-2-ask-for-permission"></a>

After the user clicks an install link, your app receives a GET request on the app URL path specified in the Partner Dashboard. Requests to this route from a user that is logged into the ShopBase App Store include the `shop`, `timestamp`, and `hmac` query parameters. If your install link doesn't originate from the ShopBase App Store, then you need to provide the `shop`parameter yourself or implement other handling to get the user's shop.

{% hint style="info" %}
&#x20;You need to verify the authenticity of these requests via the provided HMAC. For more information, see *Verification*.
{% endhint %}

To show the prompt, redirect the user to the following URL with the query parameters defined below:

```
https://{shop}.onshopbase.com/admin/oauth/authorize?client_id={api_key}&scope={scopes}&redirect_uri={redirect_uri}
```

* `{shop}`: The name of the user's shop.
* `{api_key}`: The app's API Key.
* `{scopes}`: A comma-separated list of scopes. For example, to write orders and read customers, use `scope=write_orders,read_customers`. Any permission to write a resource includes the permission to read it.
* `{redirect_uri}`: The URL to which a user is redirected after authorizing the client. The complete URL specified here must be added to your app as a whitelisted redirection URL, as defined in the Partner Dashboard.

### Step 3: Confirm installation <a href="#step-3-confirm-installation" id="step-3-confirm-installation"></a>

When the user clicks the **Install** button in the prompt, they're redirected to the client server as specified above. The `authorization_code` is passed in the confirmation redirect.

```
https://example.org/some/redirect/uri?code={authorization_code}&hmac=da9d83c171400a41f8db91a950508985&timestamp=1409617544&shop={hostname}
```

Before you continue, make sure your app performs the following security checks. If any of the checks fails, your app must reject the request with an error, and must not continue.

* The `hmac` is valid. The HMAC is signed by ShopBase as explained below, in [*Verification*](https://help.shopify.com/en/api/getting-started/authentication/oauth#verification).
* The `hostname` parameter [is a valid hostname](https://en.wikipedia.org/wiki/Hostname#Restrictions_on_valid_host_names), ends with `onshopbase.com`, and does not contain characters other than letters (a-z), numbers (0-9), dots, and hyphens.

If all security checks pass, then you can exchange the access code for a permanent access token by sending a request to the shop's `access_token` endpoint:

```
POST https://{shop}.onshopbase.com/admin/oauth/access_token.json
```

In your request, `{shop}` is the name of the user's shop and the following parameters must be provided in the request body:

* `client_id`: The API key for the app, as defined in the Partner Dashboard.
* `client_secret`: The API secret key for the app, as defined in the Partner Dashboard.
* `code`: The authorization code provided in the redirect.

The server responds with an access token:

```
{
  "access_token": "f85632530bf277ec9ac6f649fc327f17",
  "scope": "write_orders,read_customers"
}
```

The following values are returned:

* `access_token`: An API access token that can be used to access the shop's data as long as the client is installed. Clients should store the token somewhere to make authenticated requests for a shop's data.
* `scope`: The list of access scopes that were granted to the application and are associated with the access token. Due to the nature of OAuth, it's always possible for a merchant to change the requested scope in the URL during the authorize phase, so the application should ensure that all required scopes are granted before using the access token. If you requested both the read and write access scopes for a resource, then check only for the write access scope. The read access scope is omitted because it's implied by the write access scope. For example, if your request included `scope=read_orders,write_orders`, then check only for the `write_orders` scope.

If [online access mode](https://help.shopify.com/en/api/getting-started/authentication/oauth/api-access-modes) is requested, then the server responds with an access token and additional data:

```
{
  "access_token": "f85632530bf277ec9ac6f649fc327f17",
  "scope": "write_orders,read_customers",
  "expires_in": 86399,
  "associated_user_scope": "write_orders",
  "associated_user": {
    "id": 902541635,
    "first_name": "John",
    "last_name": "Smith",
    "email": "john@example.com",
    "email_verified": true,
    "account_owner": true,
    "locale": "en",
    "collaborator": false
  }
}
```

The following values are returned:

* `expires_in`: The number of seconds until the access token expires.
* `associated_user_scope`: The list of access scopes that were granted to the app and are available for this access token, given the user's permissions.
* `associated_user`: Information about the user who completed the OAuth authorization flow.

{% hint style="warning" %}
The `email` field in this response appears regardless of the email verification status. If you're using emails as an identification source, then make sure that the `email_verified`field is also true. You can use the `id` field to uniquely identify a single user.
{% endhint %}

### Step 4: Making authenticated requests <a href="#step-4-making-authenticated-requests" id="step-4-making-authenticated-requests"></a>

After the client has obtained an API access token, it can make authenticated requests to the REST API. These requests must include the following headers:

* `X-ShopBase-Access-Token`: {access\_token}
* `X-ShopBase-Token-Secret`: {token\_secret}

Starting from May 21, 2025, the `X-ShopBase-Token-Secret` header is required for all API requests. For details on how to generate and manage your Token Secret, please refer to the [Manage Access from App to ShopBase section](https://developers.shopbase.com/build-an-app/making-your-first-request/authentication/public-apps#manage-access-from-app-to-shopbase).

### Update OAuth scopes <a href="#update-oauth-scopes" id="update-oauth-scopes"></a>

After the user has agreed to install your app, you might want to change the granted scope. For example, you might want to request additional scopes if your integration requires access to other API endpoints.

To change scopes, redirect your users to the [app authorization link](https://help.shopify.com/en/api/getting-started/authentication/oauth#step-2-ask-for-permission) and request authorization of new permissions:

```
https://{shop}.onshopbase.com/admin/oauth/authorize
```

In the URL, `{shop}` is the users `myshopbase` domain and the `oauth/authorize` link includes the required parameters.

### Verification <a href="#verification" id="verification"></a>

Every request or redirect from ShopBase to the client server includes an `hmac` parameter that can be used to verify the authenticity of the request from ShopBase. For each request, you must remove the `hmac` entry from the query string and process it through an HMAC-SHA256 hash function.

By way of example, consider the following query string:

```
code=0907a61c0c8d55e99db179b68161bc00&hmac=700e2dadb827fcc8609e9d5ce208b2e9cdaab9df07390d2cbca10d7c328fc4bf&shop=some-shop.onshopbase.com&timestamp=1337178173
```

{% hint style="warning" %}
This query string is merely an example, and the request parameters provided by ShopBase could be subject to change. Your verification strategy should not depend on the parameters in the example above.
{% endhint %}

#### Remove the HMAC <a href="#remove-the-hmac" id="remove-the-hmac"></a>

To remove the `hmac`, you can transform the query string to a map, remove the `hmac` key-value pair, and then lexicographically concatenate your map back to a query string. This leaves the remaining parameters from the example query string:

```
code=0907a61c0c8d55e99db179b68161bc00&shop=some-shop.onshopbase.com&timestamp=1337178173
```

#### Process through the hash function <a href="#process-through-the-hash-function" id="process-through-the-hash-function"></a>

You can process the string through an HMAC-SHA256 hash function using the secret key. The message is authentic if the generated hex digest is equal to the value of the `hmac` parameter.

You can view [SampleApp example](https://bitbucket.org/brodev/sbase-sampleapp/src/72b8c49a65221bdf7dcd39d85bca853effd66847/backend/controllers/auth.js#lines-16) or below example in Ruby code.

**Ruby Example:**

```ruby
digest = OpenSSL::Digest.new('sha256') 
secret = "YOUR_APP_SECRET_KEY" 
message = "code=0907a61c0c8d55e99db179b68161bc00&shop=some-shop.onshopbase.com&timestamp=1337178173"

digest = OpenSSL::HMAC.hexdigest(digest, secret, message) ActiveSupport::SecurityUtils.secure_compare(digest, "700e2dadb827fcc8609e9d5ce208b2e9cdaab9df07390d2cbca10d7c328fc4bf")
```

Note: The HMAC verification procedure for OAuth is different from the procedure for verifying webhooks. To learn more about HMAC verification for webhooks, see [*Using webhooks*](/build-an-app/making-your-first-request/using-webhooks).


# API access scopes

Part of the authorization process requires specifying which parts of a shop's data the client would like access to. Clients can ask for any of the authenticated/unauthenticated access scopes listed:

&#x20;You can check your granted access scopes for an app via the AccessScope resource.

### Authenticated access scopes <a href="#authenticated-access-scopes" id="authenticated-access-scopes"></a>

Authenticated access scopes control access to resources in the REST Admin API and the GraphQL Admin API. Authenticated access is intended for interacting with a store on behalf of the merchant to perform actions such as creating products and managing discount codes.

* `read_themes`, `write_themes`\
  Access to Asset and Theme.
* `read_products`, `write_products`\
  Access to Product, Product Variant, Product Image, and Product Custom Collection.
* `read_product_listings`

  Access to Product Listing, and Collection Listing.
* `read_inventory`, `write_inventory`

  Access to Inventory Level and Inventory Item.
* `read_customers`, `write_customers`\
  Access to Customer Detail and Customer Group.
* `read_orders`, `write_orders`\
  Access to Order, Transaction and Fulfillment.
* `read_fulfillments`, `write_fulfillments`

  Access to Fulfillment Service.
* `read_script_tags`, `write_script_tags`\
  Access to Script Tag.
* `read_content`, `write_content`

  Access to Page and Redirect.
* `read_fulfillments`, `write_fulfillments`\
  Access to Fulfillment Service.
* `read_shipping`, `write_shipping`\
  Access to Carrier Service, Shipping Rate, Country and Province.
* `read_checkouts`, `write_checkouts`\
  Access to Checkouts.
* `read_price_rules`, `write_price_rules`\
  Access to Price Rules.
* `read_analytics`

  Access to Analytics.


# Rest API References

The REST Admin API lets you build apps and other integrations for the ShopBase admin.

For full details of our Admin Rest API, please visit [ShopBase API Docs](https://api-doc.shopbase.com)

### Frequent Asked API Questions

#### Product API

**Create a Product**

Create a simple product:

```
POST: /admin/products.json
{
   "product": {
   	"title": "Simple product title"
   }
}
```

Create a product with multiple product variants and multiple options:

```
POST: /admin/products.json
{
    "product": {
        "title": "Simple product title",
        "variants": [
            {
                "option1": "Black",
                "option2": "Small",
                "price": "19.99",
                "sku": "sku-189234-123-12-1",
                "compare_at_price": "21.99"
            },
            {
                "option1": "Red",
                "option2": "Large",
                "price": "19.99",
                "sku": "sku-189234-123-12-2",
                "compare_at_price": "21.99"
            },
            {
                "option1": "Red",
                "option2": "Medium",
                "price": "19.99",
                "sku": "sku-189234-123-12-3",
                "compare_at_price": "21.99"
            }
        ],
        "options": [
            {
                "values": [
                    "Black",
                    "Red",
                    "Purple"
                ],
                "name": "Color"
            },
            {
                "values": [
                    "Small",
                    "Medium",
                    "Large"
                ],
                "name": "Size"
            }
        ],
        "images": [
            {
                "metafields": [],
                "src": "https://example.com/image-src-url-001.jpg",
                "alt": "some-alt-text-01"
            },
            {
                "metafields": [],
                "src": "https://example.com/image-src-url-002.jpg",
                "alt": "some-alt-text-02"
            }
        ]
    }
}
```

**Update Product:**

Update product title:

```
PUT admin/products/${product_id}.json
{
  "product": {
    "id": ${product_id},
    "title": "New product title"
  }
}
```

Update product by adding new product images:

```
PUT admin/products/${product_id}.json
{
  "product": {
    "id": ${product_id},
    "images": [
      {
        "src": "https://example.com/new-product-image-001.jpg"
      }
    ]
  }
}
```

Update product by reordering product images:

```
PUT admin/products/${product_id}.json
{
  "product": {
    "id": ${product_id},
    "images": [
      {
        "id": ${product_image_id_01},
        "position": 2
      },
      {
        "id": ${product_image_id_02},
        "position": 1
      }
    ]
  }
}
```

Show/hide product:

```
# Show product
PUT admin/products/${product_id}.json
{
  "product": {
    "id": ${product_id},
    "published": true
  }
}

# Hide product
PUT admin/products/${product_id}.json
{
  "product": {
    "id": ${product_id},
    "published": false
  }
}
```

#### Product variant API

Add a new variant with an image for a product:

```
POST: /admin/products/${product_id}/variants.json
{
  "variant": {
    "option1": "Purple",
    "option2": "Small",
    "image_id": ${product_image_id},
    "price": "19.99",
    "sku": "sku-189234-123-12-4",
    "compare_at_price": "21.99"
  }
}
```

Update product variant - Add an existing image to an existing variant:

```
PUT: /admin/variants/${variant_id}.json
{
  "variant": {
    "id": ${variant_id},
    "image_id": ${product_image_id},
    "product_id": ${productID}
  }
}
```

Update product variant - Update price:

```
PUT: /admin/variants/${variant_id}.json
{
  "variant": {
    "id": ${variant_id},
    "price": 3.99,
    "product_id": ${productID}
  }
}
```

#### Product image API

Create new product image for a product with image attachment:

```
POST: /admin/products/${product_id}/images.json
{
  "image": {
    "attachment": "Data endcode Base64 of image",
    "filename": "image.jpg"
  }
}
```

Create a new product image for a product with an image URL:

```
POST: /admin/products/${product_id}/images.json
{
  "image": {
    "src": "https://example.com/image.jpg"
  }
}
```

Create a new product image for a product and make it as the main image:

```
POST: /admin/products/${product_id}/images.json
{
  "image": {
    "src": "https://example.com/image.jpg",
    "position": 1
  }
}
```

Create a new product image for a product and assign it for product variants:

```
POST: /admin/products/${product_id}/images.json
{
  "image": {
    "src": "https://example.com/image.jpg",
    "variant_ids": [
      ${variant_1_id},
      ${variant_2_id}
    ]
  }
}
```

Update product image: assign it for product variants:

```
PUT: /admin/products/${product_id}/images/${image_id}.json
{
  "image": {
    "id": ${image_id},
    "variant_ids": [
      ${variant_1_id},
      ${variant_2_id}
    ]
  }
}
```


# Rate limits

### About REST Admin API rate limits <a href="#general-api-rate-limits" id="general-api-rate-limits"></a>

The ShopBase REST Admin API applies rate limits to the API requests that it receives. Every request is subject to throttling under the general limits.

Limits are calculated using the leaky [bucket algorithm](https://developers.shopbase.com/build-an-app-tutorial/rest-admin-api-reference/rest-admin-api-rate-limits#general-api-rate-limits-1). All requests that are made after rate limits have been exceeded are throttled and an HTTP `429 Too Many Requests` error is returned. Requests succeed again after enough requests have emptied out of the bucket. You can see the current state of the throttle for a shop by using the [rate limits header.](https://developers.shopbase.com/build-an-app-tutorial/rest-admin-api-reference/rest-admin-api-rate-limits#rate-limits-header)

### General API rate limits <a href="#general-api-rate-limits" id="general-api-rate-limits"></a>

The rate limits are designed to allow your app to make unlimited requests at a steady rate over time while also having the capacity to make infrequent bursts. The rate limits use a [leaky bucket](https://en.wikipedia.org/wiki/Leaky_bucket) algorithm. The *bucket size* and *leak rate* properties determine the API's burst behavior and request rate.

The default settings are as follows:

* **Bucket size**: `30`
* **Leak rate**: `2/second`

If the bucket size is exceeded, then an HTTP `429 Too Many Requests` error is returned. The bucket empties at a leak rate of two requests per second. To avoid being throttled, you can build your app to average two requests per second. The throttle is a pass or fail operation. If there is available capacity in your bucket, then the request is executed without queueing or processing delays. Otherwise, the request is throttled.

There is an additional rate limit for GET requests. When the value of the `page` parameter results in an offset of over 100,000 of the requested resource, a `429 Too Many Requests` error is returned. For example, a request to `GET /admin/collects.json?limit=250&page=401` would generate an offset of 100,250 (250 x 401 = 100,250) and return a 429 response.

### Rate limits header <a href="#rate-limits-header" id="rate-limits-header"></a>

You can check how many requests you've already made using the ShopBase `X-Sb-Shop-Api-Call-Limit` header that was sent in response to your API request. This header lists how many requests you've made for a particular shop. For example:

```
X-Sb-Shop-Api-Call-Limit: 22/30
```

In this example, `22` is the current request count and `30` is the bucket size. The request count decreases according to the leak rate over time. For example, if the header displays `29/30` requests, then after a wait period of ten seconds, the header displays `9/30` requests.


# Using webhooks

### About webhooks <a href="#about-webhooks" id="about-webhooks"></a>

Webhooks are a useful tool for apps that want to execute code after a specific event occurs on a shop, for example, after a customer creates a cart on the storefront, or a merchant creates a new product in the ShopBase admin.

Instead of having your app periodically poll a shop for a specific event, you can register a webhook for the event and create an HTTP endpoint as your webhook receiver. Whenever the event occurs, a webhook is sent to the endpoint. This approach uses less API requests, making it easier to stay within API call limits while building more robust apps. Webhook event data can be stored as JSON or XML.

Common webhook use cases include the following:

* Sending notifications to IM clients and pagers
* Collecting data for data-warehousing
* Integrating with accounting software
* Filtering order items and informing shipping companies about orders
* Removing customer data from a database for app uninstalls

### Configuring webhooks <a href="#configuring-webhooks" id="configuring-webhooks"></a>

You can configure a webhook using the API or in the ShopBase admin (later).

#### Configure a webhook using the API <a href="#configure-a-webhook-using-the-api" id="configure-a-webhook-using-the-api"></a>

You can configure a webhook by making a HTTP POST request to the [Webhook resource](https://api-doc.shopbase.com/#tag/sbase-webhook-api) in the REST Admin API.

After you've created a webhook, you're presented with a secret to validate its integrity. You can also [test](https://help.shopify.com/en/api/getting-started/webhooks#testing-webhooks-configured-using-the-shopify-admin) it.

### Testing webhooks

When testing webhooks, you can run a local server or use a publicly available service such as [Beeceptor](https://beeceptor.com/). If you decide to run a server locally, then you need to make it publicly available using a service such as [**Pagekite**](https://pagekite.net/) or [**ngrok**](https://ngrok.com/). The following URLS do not work as endpoints for webhooks:

* Localhost
* Any URL ending in the word "internal". For example, `thisshop.com/internal`
* Domains like `www.example.com`
* ShopBase domains such as `shopbase.com` and `onshopbase.com`

### Creating an endpoint for webhooks <a href="#creating-an-endpoint-for-webhooks" id="creating-an-endpoint-for-webhooks"></a>

Your endpoint must be an HTTPS webhook address with a valid SSL certificate that can correctly process event notifications as described below. You can also implement verification to make sure webhook requests originate from ShopBase.

#### Payloads <a href="#payloads" id="payloads"></a>

Payloads contain a JSON or XML object with the data for the webhook event. The contents and structure of each payload varies depending on the [subscribed event](/build-an-app/making-your-first-request/using-webhooks/webhook-events-and-topics).

#### Receiving a webhook <a href="#receiving-a-webhook" id="receiving-a-webhook"></a>

After you register a webhook URL, ShopBase issues a HTTP POST request to the URL specified every time that event occurs. The request's POST parameters contain XML/JSON data relevant to the event that triggered the request.

ShopBase verifies SSL certificates when delivering payloads to HTTPS webhook addresses. Make sure your server is correctly configured to support HTTPS with a valid SSL certificate.

#### Responding to a webhook <a href="#responding-to-a-webhook" id="responding-to-a-webhook"></a>

Your webhook acknowledges that it received data by sending a 200 OK response. Any response outside of the 200 range, including 3XX HTTP redirection codes, indicates that you did not receive the webhook. ShopBase does not follow redirects for webhook notifications and considers them to be an error response.

**Frequency**

ShopBase has implemented a five second timeout period and a retry period for subscriptions. ShopBase waits five seconds for a response to each request to a webhook. If there is no response, or an error is returned, then ShopBase retries the connection 19 times over the next 48 hours. A webhook is deleted if there are 19 consecutive failures.

{% hint style="info" %}
If the webhook subscription was created through the API, then notifications about pending deletions are sent to the support email associated with the app. If the webhook was created using ShopBase admin, then notifications are sent to the store owner's email address.
{% endhint %}

To avoid timeouts and errors, consider deferring app processing until after the webhook response has been successfully sent.

### Verifying webhooks

Webhooks created through the API by a ShopBase App are verified by calculating a digital signature. Each webhook request includes a [base64-encoded](https://tools.ietf.org/html/rfc4648#section-4) **X-ShopBase-Hmac-SHA256** header, which is generated using the app's shared secret along with the data sent in the request.

Webhooks created through the ShopBase admin are verified using the secret displayed in the **Webhooks** section of the **Notifications** page.

To verify that the request came from ShopBase, compute the HMAC digest according to the following algorithm and compare it to the value in the **X-ShopBase-Hmac-SHA256** header. If they match, then you can be sure that the webhook was sent from ShopBase.

{% hint style="info" %}
If you're using a Rack based framework such as Ruby on Rails or Sinatra, then the header you are looking for is HTTP\_X\_SHOPBASE\_HMAC\_SHA256.
{% endhint %}

You can follow [SampleApp code to verify webhook hmac](https://bitbucket.org/brodev/sbase-sampleapp/src/101857456d2898e2ff249daee30ef893f96ac8a5/backend/controllers/orders.js#lines-85:96) or below example uses PHP to verify a webhook request:

```php
<?php

define('SHOPBASE_APP_SECRET', 'my_shared_secret');

function verify_webhook($data, $hmac_header) {
  $calculated_hmac = base64_encode(hash_hmac('sha256', $data, SHOPBASE_APP_SECRET, true));
  return hash_equals($hmac_header, $calculated_hmac);
}


$hmac_header = $_SERVER['HTTP_X_SHOPBASE_HMAC_SHA256'];
$data = file_get_contents('php://input');
$verified = verify_webhook($data, $hmac_header);
error_log('Webhook verified: '.var_export($verified, true)); //check error.log to see the result
```

### Best practices <a href="#best-practices" id="best-practices"></a>

In the event that your app goes offline for an extended period of time, you can recover your webhooks by re-registering your webhooks and importing the missing data.

#### Re-registering webhooks <a href="#re-registering-webhooks" id="re-registering-webhooks"></a>

To re-register the webhooks, consult the app's code that initially registered the webhooks. You can add a check that fetches all the existing webhooks and only registers the ones that you need.

#### Importing missing data <a href="#importing-missing-data" id="importing-missing-data"></a>

To import the missing data, you can fetch data from the outage period and feed it into your webhook processing code.

{% hint style="info" %}
Your app should not rely solely on receiving data from ShopBase webhooks. Since webhook delivery is not always guaranteed, you should implement reconciliation jobs to periodically fetch data from ShopBase. Most query endpoints support both the `created_at_min` and `updated_at_min` filter parameters. These filters can be used to build a job that fetches all resources that have been created or updated since the last time the job ran.
{% endhint %}


# Webhook events and topics

### List of supported webhook events and topics

| Events           | Topic                                                                                                                                                            |
| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Cart             | `carts/create, carts/update`                                                                                                                                     |
| Checkout         | <p><code>checkouts/create, checkouts/update</code></p><p><code>checkouts/delete</code></p>                                                                       |
| Collection       | <p><code>collections/create, collections/update</code></p><p><code>customers/delete</code></p>                                                                   |
| Fulfillment      | `fulfillments/create, fulfillments/update`                                                                                                                       |
| Order            | <p><code>orders/cancelled, orders/create, orders/fulfilled, orders/paid, orders/partially\_fulfilled, orders/updated</code></p><p><code>orders/delete</code></p> |
| OrderTransaction | `order_transactions/create`                                                                                                                                      |
| Product          | <p><code>products/create, products/update</code></p><p><code>products/delete</code></p>                                                                          |
| Refund           | `refunds/create`                                                                                                                                                 |
| Shop             | `app/uninstalled, shop/update`                                                                                                                                   |
| Theme            | <p><code>themes/create, themes/publish, themes/update</code></p><p><code>themes/delete</code></p>                                                                |


# Response status codes

When ShopBase receives a request to an API endpoint, a number of different HTTP status codes can be returned in the response depending on the original request.

| Code                      | Explain                                                                                                                                                                                                                                                                                                                                                                         |
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 200 OK                    | The request was successfully processed by ShopBase.                                                                                                                                                                                                                                                                                                                             |
| 201 Created               | The request has been fulfilled and a new resource has been created.                                                                                                                                                                                                                                                                                                             |
| 202 Accepted              | The request has been accepted, but not yet processed.                                                                                                                                                                                                                                                                                                                           |
| 303 See Other             | The response to the request can be found under a different URI in the `Location`header and can be retrieved using a GET method on that resource.                                                                                                                                                                                                                                |
| 400 Bad Request           | <p>The request was not understood by the server, generally due to bad syntax or because the <code>Content-Type</code> header was not correctly set to <code>application/json</code>.</p><p>This status is also returned when the request provides an invalid <code>code</code> parameter during the <a href="/pages/-Lbh6_ie9A2klA0fYeS7">OAuth</a> token exchange process.</p> |
| 401 Unauthorized          | The necessary [authentication credentials](/build-an-app/making-your-first-request/authentication) are not present in the request or are incorrect.                                                                                                                                                                                                                             |
| 402 Payment Required      | The requested shop is currently frozen.                                                                                                                                                                                                                                                                                                                                         |
| 403 Forbidden             | The server is refusing to respond to the request. This is generally because you have not [requested the appropriate scope](/build-an-app/making-your-first-request/authentication/api-access-scopes) for this action.                                                                                                                                                           |
| 404 Not Found             | The requested resource was not found but could be available again in the future.                                                                                                                                                                                                                                                                                                |
| 406 Not Acceptable        | The requested resource is only capable of generating content not acceptable according to the Accept headers sent in the request.                                                                                                                                                                                                                                                |
| 422 Unprocessable Entity  | The request body was well-formed but contains semantical errors. The response body will provide more details in the `errors` or `error` parameters.                                                                                                                                                                                                                             |
| 423 Locked                | The requested shop is currently locked.                                                                                                                                                                                                                                                                                                                                         |
| 429 Too Many Requests     | The request was not accepted because the application has exceeded the rate limit. See the API Call Limit documentation for a breakdown of ShopBase's rate-limiting mechanism.                                                                                                                                                                                                   |
| 500 Internal Server Error | An internal error occurred in ShopBase. Please contact our support so that ShopBase staff can investigate.                                                                                                                                                                                                                                                                      |
| 501 Not Implemented       | The requested endpoint is not available on that particular shop, e.g. requesting access to a Plus-specific API on a non-Plus shop. This response may also indicate that this endpoint is reserved for future use.                                                                                                                                                               |
| 503 Service Unavailable   | The server is currently unavailable. Check the status page for reported service outages.                                                                                                                                                                                                                                                                                        |
| 504 Gateway Timeout       | The request could not complete in time. Try breaking it down in multiple smaller requests.                                                                                                                                                                                                                                                                                      |


# How to submit an app to ShopBase App Store

Kindly make sure your app is fully tested and works before submitting it. The App Approval team will tests all apps before publishing them to the ShopBase App Store.

## How to submit an app to ShopBase App Store

{% hint style="info" %}
&#x20;Prior to submitting your app, make sure that your emergency developer contact information is up to date in your Partner organization settings.
{% endhint %}

When you want to submit your app to be public on [ShopBase App Store](http://apps.shopbase.com), in App detail page, click the **Submit App Store listing** button.

![](/files/-LhofW6Jcb7-g6FA0v5F)

n the App listing submission page, please follow the instruction to fill in the needed information.&#x20;

![](/files/-Lhofg-ediEEG0nqUO6z)

You can save without submitting by click **Save** button on the bar appearing when you change something.\
When all things are set, click **Submit listing** button. Please note that after the submission, you can not change the information until we have made the decision of approving your app or not. When your app is approved, it will be shown on [ShopBase App Store](http://apps.shopbase.com) then your customers can install your app.

## **How to install an app and get an access token**

Once your app is reviewed and published, it should be listed on App store page <https://apps.shopbase.com>, and shop owner should be able to install that app to their store by clicking on **Add App** button.

![](/files/-Ljzn31dHuG_MrdgSpWb)

After the user adds an app to their store, the following steps will be done:

1. ShopBase will send a request to app URL with basic information like what shop is installing.
2. App redirect user to `https://<shop_domain>.onshopbase.com/admin/oauth/authorize` and following parameters are required
   1. **client\_id** (API Key)
   2. **scope**: list of available scopes, separated by comma
   3. **redirect\_uri**: must be one of the whitelist uri list
3. Shop owner will be asked for permission approval
4. ShopBase processes and send back request to your `redirect_uri` with authorize code
5. App send a POST request to `https://<shop_domain>.onshopbase.com/admin/oauth/access_token.json` with payload including
   1. **client\_id**
   2. **client\_secret**
   3. **Code**
6. ShopBase responds a JSON with 2 information
   1. **access\_token**
   2. **Scope**
7. App use that access token for accessing public admin APIs

![](/files/-LjznrkOsWCqnhpm516g)

<br>


# Getting your app approved

### App requirements and guidelines <a href="#app-requirements-and-guidelines" id="app-requirements-and-guidelines"></a>

All [public apps](/build-an-app/making-your-first-request/authentication/public-apps) must meet the following basic criteria. These requirements are the same for [private apps](/build-an-app/making-your-first-request/authentication/private-apps).

* The app solves a problem for merchants, either by adding new functionality to Sho, or by creating a faster, easier, or more efficient way to do something that already exists within ShopBase
* It uses the ShopBase API and makes sure that all data it collects provides real value to a merchant's business.
* It requires minimal interaction between the app's developer and the merchants who are using it. The app should use programming logic and ShopBase data to automate its functions.

All public apps must meet [general app requirements](https://shopify.dev/concepts/app-store/getting-your-app-approved/app-requirements#general-requirements-for-all-apps). Certain app configurations are subject to [additional requirements](https://shopify.dev/concepts/app-store/getting-your-app-approved/app-requirements#specific-requirements-for-certain-app-configurations).


# App requirements

The following requirements are used at ShopBase to review all apps.

## **Prohibited and restricted app configurations**

1. **Apps that act as a payment gateway, or apps that modify an existing payment gateway** - Our Hosted Payment SDK will be designed to let payment processors integrate with the ShopBase checkout soon.&#x20;
2. **Apps that are pieces of standalone software that need to be downloaded to a computer** - The ShopBase App Store's distribution method is through the use of web applications. There currently isn't an infrastructure to distribute any other type of app safely and securely to our merchants.
3. **Apps that make little or no use of ShopBase's APIs** - Apps submitting to the ShopBase App Store must make efficient use of ShopBase APIs in order to function. This is to make the merchant experience better by using direct shop data and mitigate user error.
4. **Apps that process payments outside of ShopBase's checkout** - ShopBase can't guarantee the safety or security of an order that has been placed through an offsite or third party checkout.
5. **Multiple apps with overlapping functionality created by the same partner** - If you want to list more than one app on the ShopBase App Store, then each app must be clearly different from other apps that you've already listed. In some cases, you can combine multiple apps into one.&#x20;
6. **Apps that offer capital loans** - These types of services are difficult to effectively monitor on an ongoing basis in a manner that ensures merchants are protected from unsound lending practices. In order to protect merchants from unintended risk, apps that lend capital to merchants are not able to be distributed through the ShopBase App Store.

## App listing

The app listing is your calling card - it helps merchants find your app and understand how it can help them run their businesses. Your listing explains the features, user interface, and functionality of your app. Your listing should clearly communicate functionality and pricing so that merchants can quickly understand the benefits of your app.

## Installation and setup

These requirements make sure that merchants can quickly set up and start using your app. The installation requirements describe the correct flows for authentication, app install charges, and any sign-up steps (if required). These requirements make sure that you provide merchants with the guidance they need when they start learning to use your app.

## Functionality and quality

For your app to be successful, it should offer a consistent and positive experience for the merchants who use it. The following functionality and quality requirements apply to the core features of your app, such as its user interface, performance, and billing.

## Security and merchant risk

Security is a critical part of any web-based business because online apps can be exposed or compromised in many different ways. Before you submit your app, you need to make sure that it's secure so that the merchants who use it won't be at risk.

## Data and user privacy

Depending on the purpose of your app, it might need to manage and store customer data. Make sure that your app meets the current best practices (and in some cases, the legal requirements) that protect customer data and user privacy.

## &#x20;Support

After you submit your app, you need to support the merchants who use it. There are different ways to do this, such as answering merchant inquiries promptly and publishing detailed help documentation, or providing instructive in-app context and support so that merchants can quickly get the help they need when they use your app.


# Testing your app

Before you submit your app for review, you need to test it on a development store to check for any bugs or errors

## Best practices for testing your app

When testing your app, think about what it might look like through the eyes of ShopBase merchants of varying skill levels. You should make sure you have accounted for any issues that might occur when a merchant installs your app in their store. Here are some suggestions of what to look for when you test your app:

* Make sure that the installation process is easy to understand and execute
* Make sure that your app can appropriately handle issues like 404s, unexpected inputs, and heavy user traffic.
* If your app interacts with or adds something to a merchant’s online store, then test your app with several different ShopBase-made themes.
* After you’ve installed your app on a development store, make sure you can uninstall and reinstall that app on the same shop.

## Installing an app on a development store

When a merchant installs your app, it must first authenticate with the merchant’s shop using OAuth. You can test this by installing your app on a development store. If you don’t have a development store, then you can create one in the partner dashboard.


# Submitting your app

After you’ve tested your app and ensured that it's production-ready, you can submit it for approval.

{% hint style="warning" %}
Make sure you thoroughly [test your app](/build-an-app/getting-your-app-approved/testing-your-app) before submitting it. If we discover a bug that prevents us from being able to review the functionality of your app, then it will be rejected.
{% endhint %}

Before you submit your app, check the following things:

* Make sure that the app meets our [requirements](/build-an-app/getting-your-app-approved/app-requirements). This helps to speed up your app’s review.
* Make sure that your app is appropriately documented, keeping in mind that many of your users might not be digitally literate. Try to create a guide that caters to all levels of experience. If your app requires the setup of an external service to function, then include this within your documentation.


# The review process

## Contact throughout the review process

During the review process, we’ll contact you at the Partner email. To ensure you receive our emails, add <noreply@shopbase.com> to your allowed sender list in your email service provider’s settings.

## What to expect from ShopBase when you submit your app

When you submit your app for approval, you will receive an email titled **Thank you for submitting \[your app name] to ShopBase**. This submission confirmation email will include some frequently asked questions and your expected review date. When you receive this email, this means that your app is **Pending Review**.

## How does the review process work?

Your app must pass two stages: the review stage and the conversation stage. During these stages, your app also passes through different states: Submitted, Draft, In Review, and Live. You can see these states in your app listing dashboard.

![A diagram that shows how the app passes through the different states.](https://shopify.dev/assets/api/getting-your-app-approved/review-process-diagram.png)

When you submit your public app for screening, it moves into the **review stage**. You receive an email titled **Thank you for submitting \[your app name] to ShopBase**. When you receive this email, your app is marked as **Submitted** in your app listing dashboard.

If your app submission requires major changes, then it will be rejected. You receive an email titled **Important: \[Your app name] app review has been rejected** that outlines the required changes you need to make before re-submitting the app for review. When you receive this email, your app is marked as **Draft** in your app listing dashboard. After you've made these changes to your app, you can resubmit your updated app through the Partner dashboard, at which point it will be screened as a new submission.

If your app submission requires minor changes, then it moves to the **conversation stage**. You receive an email titled **Important: \[Your app name] requires updates** that outline the remaining changes you need to make. When you receive this email, your app is marked as **In Review** in your app listing dashboard. After you've updated your app, you can reply to that email so that your app can be reviewed again.

\
After you’ve made any necessary major changes to your app, and those changes have been reviewed, your app moves into the **conversation stage**. In this stage, you can communicate with us about your app through ZenDesk. We’ll also communicate the next steps for approval.

We’ll approve the app when we've made sure it meets all the ShopBase App Store requirements. You receive an email titled **\[Your app name] has been approved on ShopBase** when your app has been approved. On receiving this email, your app is marked as **Live** in your app listing dashboard, and your app will appear on the ShopBase


# Getting started building themes

This guide describes the basic steps for getting started to build a theme for ShopBase.

{% hint style="info" %}
The first step in building a theme for ShopBase is to join the ShopBase Partner Program by [creating a partner account](/#create-a-shopify-partner-account).&#x20;
{% endhint %}

After you create a partner account, check out the following tools and resources to help you get started:

* [A GitHub account to store your theme code ](https://github.com/)
* [Theme development resources](/build-a-theme/theme-development-resources)
* [How to submit a theme to ShopBase Theme Store](/build-a-theme/how-to-submit-a-theme-to-shopbase-theme-store)

### Create a new theme from ShopBase Partner Admin <a href="#generate-api-credentials-from-the-shopify-admin" id="generate-api-credentials-from-the-shopify-admin"></a>

**Steps:**

1. Create a new empty Github repo (public or private) and remember its' url (eg: <https://github.com/ShopBaseCom/starter-theme>).
2. From your ShopBase Partner Admin, go to **Public Themes**.
3. Click **Create Theme**
4. Give your theme a name
5. In the **Theme details** section, write your theme description and 2 thumbnails of Desktop and Mobile.
6. In the **Connect to repository** section, enter the repository URL where you store your theme code.
7. Hit **Save**.

### Develop the theme in local environment <a href="#generate-api-credentials-from-the-shopify-admin" id="generate-api-credentials-from-the-shopify-admin"></a>

**Steps:**

1. Create a new theme repo on your local machine using our [Theme CLI](/build-a-theme/theme-development-resources) tool.
2. [Connect your store & start developing](/build-a-theme/theme-development-resources/connect-to-your-store-and-start-developing).

### How submit your theme to Theme Store

**Steps:**

1. From theme detail page, click **Create new version**
2. Enter the description of this version. For eg. *Submit the first time*
3. Hit **Save as draft** or **Submit for Review** \
   (Only Submit when you make sure your theme is fully tested and works)
4. Select the store that you want to install the theme version to test.


# Theme development resources

### ShopBase Theme CLI Overview

ShopBase Theme CLI helps you develop themes for ShopBase easily.

### How to install ShopBase Theme CLI

Node Version Requirement\
ShopBase Theme CLI requires Node.js version 10.13.0 or above. You can manage multiple versions of Node on the same machine with [nvm](https://github.com/nvm-sh/nvm) or nvm-windows

To install the new package, use one of the following commands. You need administrator privileges to execute these unless npm was installed on your system through a Node.js version manager (e.g. n or nvm).

```
npm install -g @shopbase-theme/cli
# OR
yarn global add @shopbase-theme/cli
```

### Starter theme

The quickest way to get up and running with a workspace for building themes is to use the official [starter theme](https://github.com/ShopBaseCom/starter-theme-test)

To get started, you need to log in to your Partner account (make sure you request to create partner account here)

```
shopbase-theme auth:login
```

After authenticated by using your email & password, you can use the following command to create a new theme.

```
shopbase-theme create new-theme
```

Note: **new-theme** is a handle of a theme, you may change theme name in [ShopBase Partner Dashboard](https://partners.shopbase.com)

All source code is cloned from [starter-theme](https://github.com/ShopBaseCom/starter-theme-test) repo. We recommend starting with this starter theme.

To view all available command, use the help command

```
shopbase-theme help
```


# Connect to your store & start developing

### Connect to your store

You can add the development theme to any store which your authenticated account has access to. Navigate the directory of a theme & use the following command to add &#x20;

```bash
shopbase-theme connect 
```

Note: to test the development theme in your store, that theme need to be built successfully . &#x20;

### Start developing

From the root of your theme project, run:

```bash
shopbase-theme serve
```

This command starts a development server. You will be able to see and interact with your new site in a development environment — local (on your computer, not published to the internet).

You can also specify a path that point to your theme project:

```bash
shopbase-theme serve ~/home/theme/example
```


# Theme structure

### Theme structure

```
src
   assets [1]
   config [2]
   layouts [3]
   sections [4]
   blocks [5]
   pages [6]
   templates [7]
   plugin.js [8]
   index.js [9]
.editorconfig: [10]
.env: [11]
.eslintrc.js [12]
.gitignore [13]
.prettierrc.js [14]
package.json [15]
```

1. It contains all the assets used in the theme, including images and stylesheets files.
2. It Contains theme editor configuration, including schema and default data.
3. It contains theme layout templates.
4. It contain all theme sections, which are reusable modules of content that can be customized and re-ordered by users of the theme.
5. Custom reusable components that can be referenced in any page templates.
6. Theme templates for core pages.
7. There might be cases where you need a different markup for the same page. For example, you might want a sidebar on one product page but not in another. The workaround for this is to create alternate templates.
8. Defines routes component. Each route component should map to a template in the pages folder.
9. Since themes also function as plugins, this is a required file in order to use this theme as a plugin.
10. ShopBase will use the environment variables declared in this file to connect to your ShopBase store.

{% hint style="info" %}
**Required files and folders**: src/assets/styles/style.scss, src/config, src/index.js, .eslintrc.js, .prettierrc.js, .package.json
{% endhint %}


# Theme object, methods, and props

#### Object

```
$shop
    $shop.name
        Returns the shop's name.
    $shop.email
		Returns the shop's email.
	$shop.enabled_currencies
		Returns the list of currency objects that the store accepts.
```

#### Methods

```
Routes
	$routeToPath(path)
	$routeToHome()
	$routeToCollections()
	$routeToCollection(collection)
	$routeToProductWithAttribute(name, type)
	$routeToProduct(product)
	$routeToProductWithCollection(collection, product)
	$routeToCart()
	$routeToMyAccount()
	$routeTopage()

Navigate
	$navigateToAccount()
	$navigateToCheckout()

Theme editor
	$getPageSettings(page)
	$getThemeSettings()
	$getForceSettings()
	$getFixedSettings(section)

Menu
	$getMenu(handle)

Device
	$getDevice()
	$isMobile()
	$isTablet()
	$isDesktop()

Storage
	$getStorage(key)
	$setStorage(key, value)

Other
	$resizeImage(url = '', height = '', width = '', crop = '', scale = '')
	$changeCurrency(code)
	$toggleOverlay(state)
```

#### Page component props

**Home**

| Prop                | Type  | Description |
| ------------------- | ----- | ----------- |
| featuredProducts    | Array |             |
| featuredCollections | Array |             |
| collectionList      | Array |             |

**Product**

| **Prop**               | Type     | Description |
| ---------------------- | -------- | ----------- |
| product                | Object   |             |
| variant                | Object   |             |
| description            | String   |             |
| availableOptions       | Array    |             |
| currentOption          | Object   |             |
| unavailableVariant     | Boolean  |             |
| unavailableOptionItems | Object   |             |
| pages                  | Array    |             |
| cartFormId             | String   |             |
| isPageFetching         | Boolean  |             |
| isDisabledAddCart      | Boolean  |             |
| isActiveOptionItem     | Function |             |
| isCartItemAdded        | Boolean  |             |
| uploadProcess          | Object   |             |
| uploadAccept           | String   |             |
| validateProperties     | Object   |             |
| onChangeOption         | Function |             |
| onChangeQuantity       | Function |             |
| onChangeCustomOption   | Function |             |
| onAddToCart            | Function |             |


# Theme editor

You can use the settings\_schema.json file to configure the theme settings that merchants can access using the theme editor. A merchant accesses the editor by clicking Customize from the Themes page of their ShopBase admin

#### File format

The settings\_schema.json file contains the definitions for your theme settings, grouped into sections according to the setting type.\
The grouping of the settings in settings\_schema.json is reflected in the theme editor.

#### There are two categories of theme setting:

* **Section settings:** These control the settings that can be configured by merchants.
* **Sidebar settings:** These are not configurable by the merchant. They control informational elements (headers and paragraphs), which you can use to add detail and clarity to the theme editor sidebar.

#### Current supported setting types:

**Input** (text, number, url, textarea)

```
{
	"id": "",
	"type": "input",
	"default": "",
	"placeholder": "",
	"maxLength": 100
}
```

Example:

```
{
	"id": "input",
	"type": "input",
	"placeholder": "Placeholder"
}
```

**Image picker**

```
{
	"id": "",
	"type": "image_picker",
	"info": ""
}
```

Example:

```
{
	"id": "logo",
	"type": "image_picker",
	"info": "Upload a logo"
}
```

**Radio**

```
{
	"id": "",
	"type": "radio",
	"default": 0,
	"options": []
}
```

Example:

```
{
	"id": "radio",
	"type": "radio",
	"default": 1,
	"options": [
		{
			"label": "Radio 1",
			"value": 1
		}
	],
}
```

#### Sections

**Supported Types**: image\_picker, text, number, url, textarea, select, checkbox, radio, slider, help\_text, label, heading, text\_editor, collection, product, page, link, menu, video

```
{
	"icon": "",
	"label": "",
	"sections": [
		{
			"elements": [
			]
		},
		{
			"children": {
				"default": [],
				"elements": []
			},
			"label": "content",
			"max_items": 5,
			"options": {
				"btnAdd": "Add slideshow",
				"btnDelete": "Remove content",
				"heading": "Slideshow",
				"id": "title"
			}
		}
	]
}
```

Example:

```
{
  "icon": "image-multiple",
  "label": "Slideshow",
  "sections": [
    {
      "elements": [
        {
          "default": "fade_in",
          "id": "text_animation",
          "label": "Text animation",
          "options": [
            {
              "label": "None",
              "value": "none"
            },
            {
              "label": "Fade in",
              "value": "fade_in"
            },
            {
              "label": "Fade up",
              "value": "fade_up"
            },
            {
              "label": "Fade down",
              "value": "fade_down"
            }
          ],
          "type": "select"
        },
        {
          "default": "slide",
          "id": "gallery_transition",
          "label": "Gallery transition",
          "options": [
            {
              "label": "Fade",
              "value": "fade"
            },
            {
              "label": "Slide",
              "value": "slide"
            }
          ],
          "type": "select"
        },
        {
          "default": 6,
          "id": "change_slides_every",
          "label": "Change slides every",
          "max": 12,
          "min": 4,
          "type": "slider",
          "unit": "sec"
        },
        {
          "default": 30,
          "id": "opacity",
          "label": "Opacity",
          "max": 100,
          "min": 0,
          "type": "slider",
          "unit": "%"
        }
      ],
      "label": "setting"
    },
    {
      "children": {
        "default": [],
        "elements": [
          {
            "id": "background_image",
            "info": "1600x1000px recommended",
            "label": "Background image",
            "type": "image_picker"
          },
          {
            "id": "alt_text",
            "label": "Alt text",
            "placeholder": "Describe image to improve SEO",
            "type": "text"
          },
          {
            "default": "Introducing The",
            "id": "preheading",
            "label": "Preheading",
            "type": "textarea"
          },
          {
            "default": "Roller Shop Base Theme",
            "id": "heading",
            "label": "Heading",
            "type": "text"
          },
          {
            "default": "Exclusively From Shop Base",
            "id": "subheading",
            "label": "Subheading",
            "type": "textarea"
          },
          {
            "default": "centre",
            "id": "text_position",
            "label": "Text position",
            "options": [
              {
                "label": "Centre",
                "value": "centre"
              },
              {
                "label": "Right",
                "value": "right"
              },
              {
                "label": "Left",
                "value": "left"
              }
            ],
            "type": "select"
          },
          {
            "default": "centre",
            "id": "text_alignment",
            "label": "Text alignment",
            "options": [
              {
                "label": "Centre",
                "value": "centre"
              },
              {
                "label": "Right",
                "value": "right"
              },
              {
                "label": "Left",
                "value": "left"
              }
            ],
            "type": "select"
          },
          {
            "default": "Shop Men",
            "id": "first_button_label",
            "label": "First button label",
            "type": "text"
          },
          {
            "id": "first_button_link",
            "label": "First button link",
            "placeholder": "Paste a link or search",
            "type": "link"
          },
          {
            "default": false,
            "id": "highlight_first_button_link",
            "label": "Highlight first button label",
            "type": "checkbox"
          },
          {
            "default": "Shop Women",
            "id": "second_button_label",
            "label": "Second button label",
            "type": "text"
          },
          {
            "id": "second_button_link",
            "label": "Second button link",
            "placeholder": "Paste a link or search",
            "type": "link"
          },
          {
            "default": true,
            "id": "highlight_second_button_link",
            "label": "Highlight second button label",
            "type": "checkbox"
          }
        ],
        "label": "Slideshow"
      },
      "label": "content",
      "options": {
        "btnAdd": "Add slideshow",
        "btnDelete": "Remove content",
        "heading": "Slideshow",
        "id": "title"
      }
    }
  ]
}
```

#### Sidebar settings

**Supported types**: image\_picker, text, number, url, textarea, select, color, checkbox, radio, slider, help\_text, label, heading

```
{
    "schema": [
    ],
    "type": ""
}
```

Example:

```
{
  "schema": [
    {
      "content": "Currency",
      "warning": "",
      "info": "",
      "type": "heading"
    },
    {
      "default": true,
      "id": "enable_conversion",
      "label": "Enable currency conversion",
      "type": "checkbox"
    },
    {
      "label": "Even though prices are displayed in different currencies, orders will still be processed in your store's currency.",
      "type": "help_text"
    },
    {
      "default": "without",
      "id": "format_type",
      "label": "Format",
      "options": [
        {
          "label": "Without currency ($10)",
          "value": "without"
        },
        {
          "label": "With currency ($10 USD)",
          "value": "with"
        }
      ],
      "type": "select"
    },
    {
      "default": "USD CAD AUD GBP EUR JPY",
      "id": "support_currencies",
      "label": "Supported currencies",
      "type": "text"
    },
    {
      "content": "Use the country's ISO currency code. Separate your currency codes with a space.",
      "type": "help_text"
    },
    {
      "content": "Please note that the store currency always appears as an option on your store.",
      "type": "help_text"
    }
  ],
  "type": "currency"
}
```


# How to update configure for theme editor

You can override your settings schema at anytime using this command:

```bash
shopbase-theme sync
```

**Options**:

| Option           | Description                                                                                                               |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------- |
| --override       | Override settings schema & settings data for every shops that are currently using this theme. (default: true)             |
| --override-store | Override settings schema & settings data only for specified shops (example: theme1.onshopbase.com, theme2.onshopbase.com) |


# How to submit a theme to ShopBase Theme Store

Kindly make sure your theme is fully tested and works before submitting it. The Theme Approval team will tests all themes before publishing them to the ShopBase Theme Store.

When you want to submit your theme to be public on ShopBase Theme Store, in Theme version detail page, click **Submit for Review** button.

![](/files/-LrhqelFxBxe_2n3m6hc)

### **Statuses of a theme version:**

* **Waiting for Review:** When a new version is submitted & waiting for ShopBase to review.\
  *It usually takes 3 \~ 5 business days to review your submission.*
* **Submission Canceled:** When theme developer click Cancel submission. \
  *After Submitting for Review, the theme developer can cancel the request to continue editing and resubmit any time later on.*
* **Submission Rejected:** When the submission is rejected by the reviewer.\
  You can edit, update your code and resubmit to solve all the problems we listed. The rejection reasons will be sent to your email.
* **Pending Developer Released:** When the build is successfully & ready to release to store
* **Release Canceled:** When the developer cancels the version from Pending Developer Release status. *Then, the developer can edit and resubmit later.*
* **Released to Theme Store:** When the theme is released to the store. \
  *Merchants can add the theme to their store and use it.*

{% hint style="info" %}
You can create only one version at a moment. It means that you cannot create a theme version when there is a previous version that has not been approved.
{% endhint %}


# Storefront SDK

You can use ShopBase Storefront SDK to access shop data, listen to shop events like add to cart, update cart quantity, etc.

This is list of exposed events and actions for 3rd party apps. It provides the ability to interact with shop data, functions. For example, retrieving products, collections, carts, etc.

{% hint style="info" %}
ShopBase Storefront leverage latest technology to provide a fast shopping experience for buyers, we uses single page app stack (VueJS, VueX) on ShopBase Storefront so make sure you listen to page change events and update your apps accordingly.
{% endhint %}

### Ready

**Specify a function to execute when the SDK is fully loaded.**

```javascript
window.sbsdk.ready(function() {
    console.log('ready');
});
```

### Get content

**Get page context**

```javascript
window.sbsdk.page.getContext() // { type: 'product', payload: { id: 1 }}
```

**Get current product**

```
window.sbsdk.product.current() // { id: 1000000003239458, title: "T-shirt" }
```

**Get cart**

```javascript
window.sbsdk.cart.get() // { token: '', items: [], subtotal_price: 0, total_price: 0 }
```

**Get user**

```javascript
window.sbsdk.user.get() // { id: 1 }
```

**Get order**

```javascript
window.sbsdk.checkout.getOrder() // { id: 1, items: [{ product_id: 1, product_title: 'T-shirt', variant_id: 1, variant_title: 'Black/M' }], email: 'john.doe@gmail.com' }
```

### Events <a href="#markdown-header-events" id="markdown-header-events"></a>

**Listen page load**

This event will be fired when the current page is starting to load

```javascript
window.sbsdk.page.onLoad(function() {
  console.log('Page loaded')
})
```

**Listen page context update**

```javascript
window.sbsdk.page.onContextUpdate(function(context) {
  console.log(context)
})
```

**Listen add to cart**

```javascript
window.sbsdk.cart.onAdd(function(payload) {
  console.log('Add item', payload) // { variant_id: 1, qty: 1 }
})
```

**Listen cart update**

```javascript
// Update an item
window.sbsdk.cart.onAdd(function(payload) {
  console.log('Update item', payload) // { variant_id: 1, qty: 1 }
})

// Update multiple items
window.sbsdk.cart.onUpdate(function(payload) {
  console.log('Update items', payload) // [ { variant_id: 1, qty: 1 }, { variant_id: 2, qty: 5 } ]
})
```

**Listen remove cart item**

```javascript
window.sbsdk.cart.onRemove(function(payload) {
  console.log('Remove item', payload) // { variant_id: 1 }
})
```

**Listen an user authorized**

```javascript
window.sbsdk.user.onAuthorized(function(user) {
  console.log('User', user) // { id: 1 }
})
```

**Listen an user unauthorized**

```javascript
window.sbsdk.user.onUnauthorized(function() {
  // Do something
})
```

**Listen order completed**

This event is fired when the current order has been completed

```javascript
window.sbsdk.checkout.onCompleteOrder(function(payload) {
	// do something
})
```

#### Actions <a href="#markdown-header-actions" id="markdown-header-actions"></a>

**Add to cart**

Add a product with variant id `123456` into cart.

```javascript
window.sbsdk.cart.add(123456, 1).then(function(response) {
  console.log('Added', response) // { success: true }
}).catch(function(e) {
  console.log('Error', e)
})
```

**Update cart item**

Update quantity of an existing product with variant id `123456` in cart.

```javascript
window.sbsdk.cart.update(123456, 2).then(function(response) {
  console.log('Updated', response) // { success: true }
}).catch(function(e) {
  console.log('Error', e)
})
```

**Update cart items**

```javascript
window.sbsdk.cart.updateMultiple({ 123456: 1, 123457: 2}).then(function(response) {
  console.log('Updated', response) // { success: true }
}).catch(function(e) {
  console.log('Error', e)
})
```

**Remove cart item**

```javascript
window.sbsdk.cart.remove(123456).then(function(response) {
  console.log('Removed', response) // { success: true }
}).catch(function(e) {
  console.log('Error', e)
})
```

**Clear all items in cart**

```javascript
window.sbsdk.cart.clear().then(function(response) {
  console.log('Cleared', response) // { success: true }
}).catch(function(e) {
  console.log('Error', e)
})
```

**Add a discount code**

```javascript
window.sbsdk.checkout.addDiscount('10OFF').then(function(response) {
  console.log('Added', response) // { success: true }
}).catch(function(e) {
  console.log('Error', e)
})
```

**Remove a discount code**

```javascript
window.sbsdk.checkout.removeDiscount('10OFF').then(function(response) {
  console.log('Removed', response) // { success: true }
}).catch(function(e) {
  console.log('Error', e)
})
```

#### Navigate to sign in <a href="#markdown-header-navigate-to-sign-in" id="markdown-header-navigate-to-sign-in"></a>

```javascript
window.sbsdk.user.navigateSignIn()
```

#### Navigate to sign up <a href="#markdown-header-navigate-to-sign-up" id="markdown-header-navigate-to-sign-up"></a>

```javascript
window.sbsdk.user.navigateSignUp()
```

#### Navigate to checkout <a href="#markdown-header-navigate-to-checkout" id="markdown-header-navigate-to-checkout"></a>

```javascript
window.sbsdk.checkout.navigateCheckout()
```


# Debug apps with Postman

> [**Postman**](https://www.postman.com/) is an application that lets you send HTTP requests to ShopBase API endpoints. It can be a useful tool for getting started with the ShopBase API or for debugging your apps.

## Get your ShopBase API credentials

To make authorized requests to the ShopBase API from Postman, you need to [generate private API credentials](https://developers.shopbase.com/build-an-app-tutorial/making-your-first-request/authentication/private-apps#generate-credentials-from-the-shopify-admin)

{% hint style="info" %}
The scopes you grant when generating your API credentials will give Postman the equivalent permissions. Proceed with caution when granting write access.
{% endhint %}

**Step 1:** To generate private API credentials, create a private app:

{% hint style="warning" %}
Consider skipping this part if you are already familiar with the content.
{% endhint %}

![](https://i.imgur.com/w7do5MP.gif)

**Step 2:** Send your API Credentials into Postman's New Tab :

1. Click `+` to create a new tab.&#x20;
2. Click **Authorization**.
3. From the **Type** drop-down menu, select **Basic auth**.   &#x20;
4. In the **Username** and **Password** fields, enter your store's private API key and password respectively.

![](https://i.imgur.com/0dDdZfD.gif)

{% hint style="danger" %}

#### CAUTION

Don't enter the shared secret in place of the API password
{% endhint %}

After you've authenticated your request, you need to specify the applicable HTTP method and API endpoint URL before you can send it. For example, you can use Postman to retrieve your store information:

1. From the request method drop-down menu, select **GET**.
2. Enter the store API endpoint, where `<store-names>` is the name of your store:

   ```
   https://{store-names}.onshopbase.com/admin/shop.json
   ```

![](https://i.imgur.com/jnjz3FA.png)

&#x20;   3.Click **Send.**

If the request was formatted correctly, then the store information is returned:

```
{
  "shop": {
    "id": 4159229,
    "name": "John's Apparel",
    "email": "johns-apparel@gmail.com",
    "domain": "johns-apparel.com",
    "created_at": "2014-03-27T17:52:33-04:00",
    "province": "Ontario",
    "country": "CA",
    "address1": "150 Elgin St.",
    "zip": "K2P1L4",
...
  }
}
```

### Add API credentials to an endpoint URL

Instead of entering your credentials in the **Authorization** section of Postman, you can paste a URL that includes your API key and password directly into the URL bar. The format of the URL is as follows, where `<store-name>` is the domain of your store:

```
https://apikey:password@<store-name>.onshopbase.com/admin/shop.json
```

When you click **Send**, the data is returned to Postman in the body of the response.

## Generate code snippet for API support

Whenever you need support with your API call, you can contact our support team and send us the CURL request using the below instruction.

{% hint style="warning" %}
Please create a new private app or generate a new private key once the support process is done to ensure the security of your app.
{% endhint %}

1. Create the API request with Postman (Step 2: **Send your API Credentials into Postman's New Tab** in **Get your ShopBase  API credentials**)
2. Select **Code** (**\</>**) button on the top right.
3. Select **cURL** (Code Generation Settings).   &#x20;
4. Use the copy button and send the code to ShopBase Support.

![](/files/-MWTSQcO2s6V6NUGClqR)

## Creating Postman collections

After you've successfully sent an API request with Postman, you can save it into a **collection**. Collections group together related API calls and are a great way to organize your work in Postman.

To save an API request to a collection:

1. In the tab for the API call you've just sent, click the arrow next to **Save**.
2. Click **Save As**, then enter a **Request name**. You can also enter an optional description for the request.
3. Click **Create collection**.
4. Enter a name for your collection, then click the checkmark.
5. Select the name of your collection.
6. Click **Save to (Name of your collection)**.

You can access your saved collections from the **Collections** tab in the sidebar.

{% hint style="info" %}

#### TIP

Looking for a quick start? You can find details about all supported APIs in the [Admin API reference](https://api-doc.shopbase.com/).&#x20;
{% endhint %}

## Adding calls to Postman collections

After you've created a collection, you can add calls to help organize your API calls. For this example, you'll add a call that posts a product to your store.

To create a call and add it to your collection:

1. Click `+` to open a new tab.
2. From the **Type** drop-down menu, select **Basic Auth**.
3. In the **Username** and **Password** fields, enter your store's private API key and password respectively.
4. From the API actions drop-down menu, select **POST**.
5. Enter the API endpoint for adding a product, where `<@store_url>` is the URL of your store:
6. Click **Body**.
7. Select **raw**, then in the drop-down menu, select **JSON (application/json)**.
8. In your browser, go to the [Product reference](https://api-doc.shopbase.com/#operation/create-a-product)
9. Scroll down to the **Create a new product** POST call and copy the JSON of the IPod Nano - White, 8GB product.
10. Paste the JSON in the **Body** of your Postman request.

![](https://i.imgur.com/gSDvHnj.png)

&#x20;  11\. Click **Send**. If the request is properly formatted, then the product response JSON will be returned to Postman.

{% hint style="info" %}

#### NOTE

Shopbase prevents HTTP Basic Auth POST requests that have cookies, which can cause POST calls to fail. If your POST call fails, then you should try [clearing your cookies](https://www.getpostman.com/docs/v6/postman/sending_api_requests/cookies).&#x20;

Also note that the request headers automatically update to include **Content-Type:application/json**:&#x20;
{% endhint %}

![](https://i.imgur.com/OtqbhUg.png)

![](https://i.imgur.com/NN1O9PZ.gif)

&#x20;  12\. After the call has sent successfully, click the arrow next to **Save**.\
&#x20;  13\. Select the name of your collection.   \
&#x20;  14\. Click **Save to (Name of your collection)**.

You can add as many API calls to a collection as you want. You can access your saved collections from the **Collections** tab in the sidebar.

![](/files/-MPab1b30QEdHH0lne64)

## Next steps

Browse the [Postman documentation](https://www.getpostman.com/docs/collections) to learn about collections and other features in more detail. You can also use Postman to help you [build a public ShopBase app](https://developers.shopbase.com/build-an-app-tutorial/making-your-first-request/authentication#public-apps).


# Manage orders and shipping

* Manage order with the REST Admin API
* Edit an existing order with the Admin API
* Manage fulfillments with Fulfillment and FulfillmentService resources
* Get a country field using Admin API


# Manage orders with the REST Admin API

You can use the REST Admin API to create orders and transactions to validate your app's behavior.

### Tip

{% hint style="info" %}
You can create test orders without using the API by using [Shopbase Test Gateway](https://help.shopbase.com/en/article/how-to-place-a-test-order-draft-order-t1zaoe/)
{% endhint %}

## Before you begin

To best understand this guide, you can familiarize yourself with the concepts of [orders](/tutorial/manage-orders-and-shipping/manage-orders-with-the-rest-admin-api/order) and [transactions](/tutorial/manage-orders-and-shipping/manage-orders-with-the-rest-admin-api/transaction).&#x20;

**Transactions** are associated to orders and occur each time there is an exchange of money. Transactions are processed by payment providers, and involve the transfer of money from the issuer account (the customer's credit card) to the acquirer (the merchant's bank account). For more information, see [*Getting paid*](https://help.shopbase.com/en/article/understand-shopbase-payments-1a9ypn6/#3-c-getting-paid-with-shopbase-payments).

### Access scopes

To use the Admin API to edit orders, your app needs to request the `write_order_edits` access scope for a ShopBase store. For more information on requesting access scopes when your app is installed, see [OAuth](https://developers.shopbase.com/build-an-app/making-your-first-request/authentication/oauth). To make things easy for you, we have also included a guideline on [sending request with Postman](https://developers.shopbase.com/test-and-debug-app/test-and-debug-app).

## Create an order

To test orders, create an order with an authorization transaction by sending a POST request to the [Order](https://api-doc.shopbase.com/#tag/Order) resource:

**POST** `https://shop-name.onshopbase.com/admin/orders.json`

```
{
   "order":{
      "email":" ",
      "financial_status":"pending",
      "line_items":[
         {
            "title":"Big Brown Bear Boots",
            "price":100,
            "grams":"1300",
            "quantity":2
         }
      ]
   }
}
```

#### SAMPLE RESPOND:

```
{
   "orders":[
      {
         "id": 5549662,
         "currency":"USD",
         "customer":{
            "accepts_marketing":false,
            "average_spent":0,
            "default_address":null,
            "email":" ",
            "first_name":"",
            "id":49231780,
            "last_name":"",
            "last_order_at":0,
            "last_order_id":0,
            "last_order_name":"",
            "note":"",
            "orders_count":0,
            "phone":"",
            "state":"disabled",
            "tags":"",
            "tax_exempt":false,
            "total_spent":0,
            "updated_at":"2020-12-15T05:09:48+00:00",
            "verified_email":false
         },
         "customer_locale":"",
         "discount_applications":null,
         "discount_code":null,
         "draft_order_number":0,
         "email":" ",
         "financial_status":"pending",
         "fulfillment_status":"",
         ...
      }
   ]
}
```

To be more specific, we can take a look at how we can use Postman to create this order

**STEP 1:** **Create your Shopbase's API Credentials by following the** [**tutorial here**](https://developers.shopbase.com/test-and-debug-app/test-and-debug-app#get-your-shopbase-api-credentials)**.**

![](https://i.imgur.com/w7do5MP.gif)

**STEP 2:  Send the POST Request with Postman**&#x20;

![](/files/-MPakoGDqzmK1rPt5Fhv)

**STEP 3: Save this request into a collection and extract the Order ID as a variable**&#x20;

![](/files/-MPaoTlgT_p4UfuU_4BD)

```
let response = pm.response.json()
pm.globals.set("order_id", response.order.id)
```

![](/files/-MPaoiGf5vgb4yn4Cp-l)

{% hint style="info" %}
After editing the collection's authorization property,  you do not have to manually set your **Shopbase's API Credentials** anymore. By default, all newly created requests will be set to the **"inherit auth from parent"** option
{% endhint %}

## Create the transaction for an order

After creating an order, the returned Order object includes an ID. You can use the order ID to create a transaction.

**POST** `https://shop-name.onshopbase.com/admin/orders/{order_id}/transactions.json`

```
{
   "transactions":[
      {
         "kind":"authorization",
         "status":"success",
         "amount":200
      }
   ]
}
```

After you create the transaction, you can then use the order ID to get its transactions and transaction IDs. To retrieve the transactions, send a GET request to the [Order Transaction](https://app.gitbook.com/wMG9G8F3QgSwfS2CYAgJTg).

**GET** `https://shop-name.onshopbase.com/admin/orders/{order_id}/transactions.json`

```
{
   "transactions":[
      {
         "amount":0,
         "application_fee":0,
         "authorization":"",
         "conversion_rate":0,
         "created_at":"2020-12-16T10:45:05+00:00",
         "currency":"USD",
         "currency_exchange_adjustment":null,
         "device_id":0,
         "error_code":"",
         "gateway":"",
         "id":10624938,
         "kind":"",
         "location_id":0,
         "message":"",
         "order_id":5557905,
         "origin_error_code":"",
         "parent_id":0,
         "payment_details":null,
         "payment_method_id":0,
         "processed_at":"",
         "receipt":null,
         "shop_id":10124799,
         "source_name":"",
         "staff_id":0,
         "status":"",
         "test":false,
         "transaction_amount":0,
         "transaction_currency":"",
         "updated_at":"2020-12-16T10:45:05+00:00"
      }
   ]
}
```

Let's also look at how this request is handled by using Postman:

**STEP 1: Use the same API Credential from the above instruction to create a new POST Request. Set \`{{order\_id}}\` parameter in the request url as below:**

![](/files/-MPare9hs8Gt1qughs6-)

&#x20;**STEP 2: Save the request call into a collection for future's use.**

![](/files/-MParfoHTrQs-7SQ4_ui)


# Transaction

Transactions are created for every order that results in an exchange of money.

![](https://i.imgur.com/JCO5TTz.png)

There are five types of transactions:

* **Authorization**: An amount reserved against the cardholder's funding source. Money does not change hands until the authorization is captured.
* **Capture**: A transfer of the money that was reserved during the authorization stage.
* **Void**: A cancellation of a pending authorization or capture.
* **Refund**: A partial or full return of captured funds to the cardholder. A refund can happen only after a capture is processed.

Refund transactions must be created by using the [Refund resource](https://api-doc.shopbase.com/#tag/Refund).

### Note

An order can have no more than 100 transactions associated with it.

## What you can do with Transaction

The Shopbase API lets you do the following with the Transaction resource. More detailed versions of these general actions is [available here](https://api-doc.shopbase.com/#tag/Transaction).


# Order

An order is a customer's completed request to purchase one or more products from a shop. An order is created when a customer completes the checkout process, during which time they provide an email address or phone number, billing address and payment information.

![](https://i.imgur.com/fEu5yME.png)

Orders can be created through the API, but no payment information will be collected, and no transaction performed. You can mark the order with any payment status.

You can also allow merchants to create orders manually by using the [DraftOrder resource](https://help.shopbase.com/en/article/how-to-place-a-test-order-draft-order-t1zaoe/).

## What you can do with Order

The Shopbase API lets you do the following with the Order resource. More detailed versions of these general actions is [available here.](https://api-doc.shopbase.com/#tag/Order)


# Edit an existing order with the Admin API

Apps can edit any order created by a Shopbase channel (for example, POS, online store, or draft orders) or any orders the app created through the API.

This guide explains how to use the Admin API to edit an existing order. For example, you might **add new items to a customer’s order** or **alter the quantity of line items**.

### Types of edits to an order

You can make the following edits to an order:

* Adjust quantity of a line item
* Add new custom line items
* Delete an order
* Cancel an order
* Open-Close a closed order

### Access scopes

To use the Admin API to edit orders, your app needs to request the `write_order_edits` access scope for a Shopbase store. For more information on requesting access scopes when your app is installed, see [OAuth](https://developers.shopbase.com/build-an-app-tutorial/making-your-first-request/authentication/oauth).

### Begin order editing

#### Retrieves a specific order

In **Manage orders with the Rest Admin API**, we learned how to create a new order and get its ID for future use. If you need to retrieve all the information related to a specific order, then do the following steps

Step 1: Send a GET method to this request URL

**GET** <https://shop-name.onshopbase.com/admin/orders/{{order-id}}.json>

![](https://i.imgur.com/3TcBLF5.gif)

{% hint style="info" %}
We have already learned how to get your API credential in [the test and debug post](https://developers.shopbase.com/test-and-debug-app/test-and-debug-app#get-your-shopbase-api-credentials).
{% endhint %}

Step 2: Save the request method for later use with Postman:

![](https://i.imgur.com/8JXlFic.gif)

Step 3: Get the first line item's id properties for later adjustment.

![](https://i.imgur.com/8xrxKWG.gif)

```javascript
let response = pm.response.json()
if (response.order.line_items[0].length > 0) pm.globals.set("line_item_id", response.order.line_items[0].id)
```

#### Adjust quantity of a line item.

You can adjust the quantity of a line item to an order by passing the item id:

**PUT** `https://shop-name.onshopbase.com/admin/orders/{order_id}/adjust.json`

**SAMPLE**

```
{
  "is_send_email": true,
  "line_items": [
    { "id": {{line_item_id}},
      "name": "New Item",
      "properties": "Color",
      "quantity": 15,
      "require_shipping": true,
      "restock": true,
      "variant_id": 0
    }
  ],
  "reason": "Need more quantity"
}
```

See the request in action with Postman:

![](/files/-MPbFtzzeUueOVKSHlIb)

```javascript
let response = pm.response.json()

if (response.order.line_items[0].length > 0) {
   pm.globals.set("line_item_id", response.order.line_items[0].id)
}
```

{% hint style="info" %}
It is always beneficial to save the request in the same collection we have been using for later use.&#x20;
{% endhint %}

#### Add new custom line items

You can adjust the quantity of a line item to an order by passing:

**PUT** `https://shop-name.onshopbase.com/admin/orders/{order_id}/adjust.json`

**SAMPLE**

```
{
  "is_send_email": true,
  "line_items": [
    {
      "id": 0,
      "is_custom": true,
      "name": "string",
      "price": 20,
      "properties": "string",
      "quantity": 10,
      "require_shipping": true,
      "restock": true,
      "variant_id": 0
    }
  ],
  "reason": "We need more item"
}
```

{% hint style="info" %}
To create a new line item without modifying a pre-existed one, set the line item's id and variant's id to zero.&#x20;
{% endhint %}

### Delete an order

Deleting an order is truly simple. You can remove an existing order by passing:

**DELETE** `https://shop-name.onshopbase.com/admin/orders/{order_id}.json`

### Cancel an order

**POST** `https://shop-name.onshopbase.com/admin/orders/{order_id}/cancel.json`

SAMPLE

```
{
  "amount": "20",
  "currency": "USD",
  "email": true,
  "reason": "customer",
  "refund": {},
  "restock": true
}
```

{% hint style="info" %}
Make sure you already has a set payment method before cancelling the order. For instruction on creating a payment method using Shopbase Api, read [here](https://api-doc.shopbase.com/#operation/create-a-payment-method)
{% endhint %}

### Open-Close a closed order

To open or close an order, pass the following POST method:

**POST**

```
https://shop-name.onshopbase.com/admin/orders/{order_id}/open.json
```


# Manage fulfillments with Fulfillment and FulfillmentService resources

This guide explains how to use the Fulfillment and FulfillmentService resources to create and complete fulfillments. You can use these resources either separately or in tandem, depending on your use case.

## Fulfillment resources

Before you create fulfillments, it's helpful to understand some of the different fulfillment-related resources:

* **Order**: Contains information about an order, including an array of the line items that were purchased. Line items contain important fulfillment information, such as the associated variant, the quantity purchased, and the fulfillment status.
* **Location**: Represents a geographical location where a line item can be fulfilled. A fulfillment service always has its own location, and variants managed by the fulfillment service should always be fulfilled from that location.
* **Fulfillment**: Represents a shipment of one or more items in an order. It includes the line item that the fulfillment applies to its tracking information, and the location of the fulfillment.
* **FulfillmentService:** Represents a third-party warehousing service that prepares and ships orders on behalf of the store owner. Each fulfillment service is associated with its own location. When you create a fulfillment service, a new location is automatically created and associated with it.

## Create a fulfillment

The following steps walk through the process of identifying a line item in an order that needs to be fulfilled and then creating a fulfillment.

* [Step 1: Query the order to see its line items](/tutorial/manage-orders-and-shipping/manage-fulfillments-with-fulfillment-and-fulfillmentservice-resources#step-1-query-the-order-to-see-its-line-items)
* [Step 2 Query the variant for its inventory item](/tutorial/manage-orders-and-shipping/manage-fulfillments-with-fulfillment-and-fulfillmentservice-resources#step-2-query-the-variant-for-its-inventory-item-optional)
* [Step 3: Create the fulfillment](/tutorial/manage-orders-and-shipping/manage-fulfillments-with-fulfillment-and-fulfillmentservice-resources#step-3-create-the-fulfillment)
* [Step 4: Complete the fulfillment](/tutorial/manage-orders-and-shipping/manage-fulfillments-with-fulfillment-and-fulfillmentservice-resources#step-4-complete-a-fulfillment)

{% hint style="info" %}

#### Tip

Each order includes line items that may be stocked at one or more locations. This means that when you create a fulfillment, you need to specify where you are fulfilling. This helps ShopBase effectively manage inventory for the shop owner.
{% endhint %}

### Step 1 Query the order to see its line items

To get started, retrieve the line items of the order that you want to create fulfillment for.

**GET** `https://shop-name.onshopbase.com/admin/orders/{order_id}.json`

**Response**

```
{
...
  "line_items":[
         {
            "applied_discount":null,
            "custom":true,
            "discount_allocations":[
               {

               }
            ],
            "discount_amount":0,
            "fulfillable_quantity":2,
            "fulfillment_id":0,
            "fulfillment_service":"shopbase",
            "fulfillment_status":"",
            "gift_card":false,
            "id":7256864,
            "image_src":"",
            "line_item_discount_amount":0,
            "line_item_discount_price":0,
            "line_item_price":200,
            "line_item_price_after_discount":100,
            "line_item_price_before_discount":200,
            "line_item_weight":0,
            "name":"Big Brown Bear Boots",
            "price":100,
            "product_id":0,
            "properties":null,
            "quantity":2,
            "raw_price":100,
            "raw_weight":0,
            "requires_shipping":true,
            "sku":"",
            "tax_amount":6,
            "variant_id":1000000125465789,
            ...
      }
    ],
    "fulfillments": [],
  }
}
```

For more detail, read through the instruction in this link.

Remember to include this code in the test tab for the GET Request:&#x20;

```javascript
let response = pm.response.json()
if (response.order.line_items[0].length > 0){
 pm.globals.set("variant_id", response.order.line_items[0].variant_id) 
  }
```

### Step 2: Query the variant for its inventory item (optional)

After you've queried the order's line items, you can use variant IDs to find the specific variants that are associated with the inventory item that you want to fulfill.

If an order contains line items without product or variant IDs, then those items can be fulfilled using any of the shop's locations.

**GET** `https://shop-name.onshopbase.com/admin/variants/{{variant_id}}.json`

**SAMPLE RESPONSE**

```
{
   "variant":{
      "barcode":"9 788073 400972",
      "compare_at_price":200,
      "cost_per_item":0,
      "created_at":"2020-12-16T19:22:07+00:00",
      "fulfillment_service":"shopbase",
      "grams":0,
      "id":1000003658118088,
      "image_id":434522,
      "inventory_management":"shopbase",
      "inventory_policy":"string",
      "inventory_quantity":100,
      "is_default":true,
      "option1":"IPOD2008PINK",
      "option2":"",
      "option3":"",
      "position":1,
      "presentment_prices":[
         {
            "compare_at_price":{
               "amount":"200",
               "currency_code":"USD"
            },
            "price":{
               "amount":"100",
               "currency_code":"USD"
            }
         }
      ],
      "price":100,
      "product_id":1000000125465789,
      "requires_shipping":true,
      "sku":"string",
      "taxable":true,
      "title":"IPod Nano - 8GB",
      "updated_at":"2020-12-16T19:22:07+00:00",
      "weight":12,
      "weight_unit":"lb"
   }
}
```

### Step 3: Create the fulfillment

To create a fulfillment, pass this following request URL, and set the line\_items id to the line\_items id above.

**POST** `https://shop-name.onshopbase.com/admin/orders/{order_id}/fulfillments.json`

```
{
   "fulfillment":{
      "line_items":[
         {
            "id":7256864,
            "quantity":12
         }
      ],
      "service":"shopbase",
      "tracking_company":"Other",
      "tracking_number":"123123123",
      "tracking_url":"https://t.17track.net/en#nums=123123123"
   }
}
```

**RESPONSE SAMPLE**

```
{
   "fulfillment":{
      "created_at":"2020-12-17T10:31:02+00:00",
      "detected_tracking_company":"",
      "first_tracking_step_at":0,
      "id":11685344,
      "last_crawled_at":0,
      "last_mile_tracking_company":"",
      "last_mile_tracking_number":"",
      "last_tracking_step_at":0,
      "line_items":[
         {
            "applied_discount":null,
            "compare_at_price":0,
            "custom":true,
            "discount_allocations":[
               {
                  "amount":0,
                  "discount_application_index":0
               }
            ],
            "discount_amount":0,
            "fulfillable_quantity":0,
            "fulfillment_id":0,
            "fulfillment_service":"shopbase",
            "fulfillment_status":"fulfilled",
            "gift_card":false,
            "has_custom_options":false,
            "id":7256864,
            "image_src":"",
            "item_discount_price":0,
            "line_item_discount_amount":0,
            "line_item_discount_price":0,
            "line_item_price":0,
            "line_item_price_after_discount":0,
            "line_item_price_before_discount":0,
            "line_item_price_with_explicit_discount":0,
            "line_item_weight":0,
            "metadata":{
               "is_post_purchase":false,
               "source":null
            },
            "name":"Big Brown Bear Boots",
            "not_explicit_discount_price":0,
            "order_id":5577110,
            "price":100,
            "product_id":0,
            "product_type":"",
            "properties":null,
            "quantity":2,
            "raw_price":100,
            "raw_weight":0,
            "refunded_quantity":0,
            "removed_quantity":0,
            "requires_shipping":true,
            "sku":"",
            "tags":"",
            "tax_amount":0,
            "tax_lines":null,
            "tax_rate":0,
            "taxable":true,
            "tip_payment_gateway":"",
            "tip_payment_method":"",
            "title":"Big Brown Bear Boots",
            "total_discount":0,
            "total_item_discount_price":0,
            "total_line_with_discount_price":0,
            "total_tax_amount":0,
            "variant_id":0,
            "variant_options":"",
            "variant_title":"Big Brown Bear Boots",
            "vendor":"",
            "weight":0,
            "weight_unit":""
         }
      ],
      "name":"#1001.1",
      "notify_customer":false,
      "order_id":5577110,
      "send_delay_mail":false,
      "service":"shopbase",
      "shipment_status":"",
      "status":"success",
      "tracking_company":"Other",
      "tracking_number":"123123123",
      "tracking_numbers":[
         "123123123"
      ],
      "tracking_steps":{         
      },
      "tracking_url":"https://t.17track.net/en#nums=123123123",
      "tracking_urls":[
         "https://t.17track.net/en#nums=123123123"
      ],
      "updated_at":"2020-12-17T10:31:02+00:00",
      "variant_inventory_management":"shopbase"
   }
}
```

### Step 4: Complete a fulfillment

In this final step, we already got the fulfillment id (11685344) and the related order. All that is left to be done is sending a POST method to this request URL:

**POST**&#x20;

```
https://shop-name.onshopbase.com/admin/orders/{order_id:\[0-9\]+}/fulfillments/{fulfillment_id:\[0-9\]+}/complete.json
```

{% hint style="info" %}
**NOTE:**&#x20;

If you are using a ShopBase store without fulfillment services, the fulfillment status will be automatically set to **fulfilled**. Therefore, the complete fulfillment API only applies to **orders created from Fulfillment Services like Printhub or Ali Dropship Connector**.&#x20;
{% endhint %}


# Get a country field using Admin API

This guide explains how to use the Admin API to return a country field collected during checkout.

## Access scopes

To use the Admin API to access the information collected in the checkout, your app needs to request the `read_order` access scope for a ShopBase store. For more information on requesting access scopes when your app is installed, see [API Access Scopes](https://developers.shopbase.com/build-an-app-tutorial/making-your-first-request/authentication/api-access-scopes)

## Collect a country field on the checkout

For this tutorial, you'll set the address of your shop to Brazil (since Brazilian merchants are required to collect a tax ID for government invoicing) and then complete checkout from your storefront:

1. Set the address of your shop to Brazil. Remember to change your address back when you've completed the tutorial.

![](https://i.imgur.com/GSMwVOq.gif)

1. From your storefront, add a product to your cart and then complete a checkout.
2. Complete the checkout.

## Get the country field for an order

To get the client country code, use the ShopBase Admin API to retrieve the order.

**GET** `https://shop-name.onshopbase.com/admin/orders/{order_id}.json`

**SAMPLE RESPONSE**

```
{
   "order":{
        ...     
      "additional_information":null,
      "allow_refund":false,
      "client_country_code":"BR",
      ...
      "total_line_items_discount":0,
      "total_line_items_price":200,
      "total_price":200,
      "total_quantity":2,
      "total_tax":0,
      "total_weight":0,
      "total_weight_in_gram":0,
      "transaction_id":0,
      ...
   }
}
```

## Additional information

For additional information on editing orders, refer to the [Admin API reference](http://api-doc.shopbase.com/).


# How to create your payment gateway on ShopBase

Kindly make sure your gateway is fully tested and works before integrating it. The ShopBase Approval team will tests all gateways before publishing them to ShopBase merchants.

Payment gateway developers are permitted to integrate a payment gateway with ShopBase.&#x20;

The payment gateway integrated may be made available to merchants privately. Or, if approved by ShopBase, it may be listed in the public list of ShopBase’s payment gateways, and be made available to customers of all shops in its supported countries.&#x20;

## How to integrate your hosted payment gateway with ShopBase

A. [Become a ShopBase Partner](https://www.shopbase.com/partners)

B. Create your payment gateway and submit a request-for-review form

C. Get your ShopBase payment key

D. Make your payment gateway available to you privately, or to your selected merchants, or all ShopBase customers

## **A. Become a ShopBase Partner**

* To sign up for a ShopBase Partner account, click [here](https://accounts.shopbase.com/sign-up?partner=true\&utm_source=direct\&utm_medium=&_ga=2.73488794.987642730.1609063010-933522684.1605874012).
* To get more information about ShopBase Partner Program, click [here](https://help.shopbase.com/en/article/walkthrough-of-the-shopbase-partner-program-rzkrxz/).&#x20;

## **B. Create your payment gateway**

Take the following steps to create your payment gateway with ShopBase:

1\. Log in to the [Partner Dashboard](https://partners.shopbase.com/).

2\. Click **Gateways.**

![](/files/-MS6g54-PwTF3_5zQ7tG)

3\. Click **Create new gateway.**

4\. Enter your gateway name and click **Create**.&#x20;

![](/files/-MS6g88Na7tylIt8R4aZ)

5\. Fill out the registration form, including different fields as follows:

#### Gateway information

| **Field**         | **Explanation**                                                                                                                                    |
| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| Gateway name      | This will appear in the payment settings and on the checkout page as a payment option.                                                             |
| Gateway website   | This URL will be provided to the merchant within the payment settings and will also be used to review your service.                                |
| Gateway category  | This will define how your gateway receives methods and display under the payment settings.                                                         |
| Checkout flow     | This will specify how your gateway processes transactions: using embedded iframe on ShopBase checkout page or redirecting to payment gateway page. |
| Gateway logo      | This will appear on the checkout page.                                                                                                             |
| Help document URL | This URL will be provided to the merchant within the payment settings and will also be used to review your service.                                |
| Description       | This will give your users a brief description of your service.                                                                                     |

#### Gateway redirect/embedded settings

| **Field**              | **Explanation**                                                                                                                                                                 |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Redirect URL           | The customer will be redirected to this address at checkout. This URL must properly handle the request values that will be sent                                                 |
| Embedded Iframe URL    | This will be embedded to checkout step                                                                                                                                          |
| Field label            | <p>The naming convention used to describe the login credentials for your gateway.</p><p>Maximum 70 characters. Only alphabet and numeric characters are allowed.</p>            |
| Field name             | <p>The parameters used to connect the login credentials from ShopBase to your gateway. </p><p>Maximum 120 characters. Alphabet, numeric and special characters are allowed.</p> |
| Credentials validation | This URL will be used to validate your Field name and Field label to make sure they work fine.                                                                                  |

#### Gateway order management

| **Field**                  | **Explanation**                                                                                                                                                                                                             |
| -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Capture payments URL       | When a payment capture is triggered, ShopBase will send the Request Values to your Capture URL.                                                                                                                             |
| Refund payments URL        | When a merchant clicks on the Refund item button from the ShopBase dashboard, the Request Values will be sent to your Refund URL.                                                                                           |
| Void payments URL          | When a merchant clicks on the Cancel order button from the ShopBase dashboard, the Request Values will be sent to your Void URL.                                                                                            |
| Payment information URL    | This URL will be used to retrieve information about a transaction. Payment Provider needs to return the corresponding information with x\_transaction\_type (authorization, capture, refund or void) requested by ShopBase. |
| Gateway credential webhook | This will be used to receive notification from ShopBase. ShopBase will trigger notification any time a merchant updates his/her gateway credentials on ShopBase dashboard.                                                  |
| Update Authorization URL   | This will be used when a post-purchase authorization is triggered                                                                                                                                                           |

#### **Currency**

| **Field**          | **Explanation**                                  |
| ------------------ | ------------------------------------------------ |
| Currency supported | Supported currencies for your merchant accounts. |

![](/files/-MS6DA_wgpytx00e_o3S)

**Note:**

* **Payment gateway name:** The gateway name filled in the registration form will be displayed on merchants’ dashboard and customers’ checkout page. The gateway name can’t be changed after being submitted to ShopBase for review.
* **Payment gateway logo:** Upload the logo that meets the following criteria:
  * It is a high-resolution raster image (e.g. PNG or SVG).
  * It comes with a transparent background.
  * It contains small yet easy-to-read texts.&#x20;

6\. After filling out the registration form successfully, you can perform one of the following actions:

* Make your payment gateway available for you privately
* Make your payment gateway available for your selected merchants
* Request a public listing for your payment gateway

## **C. Get ShopBase payment key**

![List of ShopBase Payments keys](/files/-MS69-XbhAkHbOvSoSJA)

ShopBase payment key will be generated after your payment gateway is successfully created.

To find your gateway key, click one gateway and choose the tab **ShopBase payment key**.

To get more detailed instructions, visit [here](https://developers.shopbase.com/integrate-a-payment-gateway/technical-specifications).

## **D. Make your payment gateway available to you privately, or to your selected merchants, or all ShopBase customers**

1\. Make your payment gateway available to you privately

* Once your payment gateway has been successfully created, it will be listed in the Gateway list and can be used by your customers only.
* To make any change to your gateway, click its name.

2\. Make your payment gateway available to selected merchants

* Click the icon [![image-1611052610276.png](https://docs-files.bgroupltd.com/uploads/images/gallery/2021-01/scaled-1680-/lR3U4qhVX7GaUIun-image-1611052610276.png)](https://docs-files.bgroupltd.com/uploads/images/gallery/2021-01/lR3U4qhVX7GaUIun-image-1611052610276.png)to share the install link with the ShopBase merchants that you are connected to on your own network

![](/files/-MS6gL0GtIM43Is-ICvo)

**Disclaimer:**

* ShopBase takes no responsibility for any issues that may arise when customers check out their orders using the payment gateway that isn’t publicly listed on the ShopBase’s payment gateways list.

3\. Request for a public listing for your payment gateway&#x20;

* You must submit a request to ShopBase if you want us to list your payment gateway publicly to all shops in your supported countries.
* To do so, click the Submit **for review** button.
* Your request will be processed by ShopBase within 3-5 days from its receipt.
  * If approved by ShopBase, your payment gateway will be made available to all shops on ShopBase in your supported countries.
  * If rejected by ShopBase, your payment gateway will require further modification to meet the criteria set out by ShopBase.
* After processing, ShopBase will send you the result via email.


# Technical Specifications

## 1. Integration solutions

### 1.1 Hosted Payment Page?

* In the most basic terms, a hosted payment page (also known as External Checkout, Third-Party Checkout, External Payment Page or Checkout page) is one of the most common ways to accept online payments.
* **It is a third-party checkout web form that handles electronic transactions (payments made with credit and debit cards).**
* In exchange for a small transaction fee, these Hosted Checkout Pages will take care of the entire transaction process: payment information collection, sensitive data protection, and transaction security.

![](/files/-MS69OhKQpDXyDA6sR_c)

### 1.2 Embedded Checkout?

Embedded checkout gives the shopper the seamless appearance of staying on your site while they make payment.

![](/files/-MS69_Mzgn2zu43jXD3f)

The checkout page is embedded in your website using an HTML `<iframe>` tag. This tag creates a frame in your web page and then the checkout page is embedded within that frame.

### 1.3 Get ShopBase Payment Key

{% embed url="<https://partners.shopbase.com/payment-gateways>" %}

**After Create Gateway**

<figure><img src="/files/RV6dms8Ryar56vMvH0sw" alt=""><figcaption></figcaption></figure>

Click ***Test***

<figure><img src="/files/hWMljaAhgsVEA6l9TvVa" alt=""><figcaption><p>ShopBase Payment Key</p></figcaption></figure>

## 2. FLOW

### 2.1 Integration Flow

![](/files/-MS69jRriD_VZDslC3HC)

* ShopBase partner will receive ShopBase Payment key after successfully registering Payment integration.
* Partner's payment provider will use ShopBase Payment key for signing mechanism when send/receive requests to/from ShopBase
* To start using the Payment Provider, merchants have to register with Payment Gateway and take Gateway's credentials. Merchants should enter those credentials to ShopBase payment settings.
* Checkout flow:&#x20;
  * ShopBase sends a request to endpoints of Payment Provider according to ShopBase format and Shopbase signing mechanism.
  * After taking the request, the Payment Provider can ask ShopBase to get Gateway's credentials and then send Gateway's requests to Gateway's format and Gateway's authenticate mechanism.

### 2.2 Sequence Diagram

#### **2.2.1 Hosted Payment Page**

![](/files/-MS69yBAYwRKjFnY7mR3)

1. First, the buyer needs to fulfill the information: shipping address, billing information, shipping method... and choose your provider as the payment method. When the buyer clicks the Place Order button, ShopBase submits to the [Redirect API](https://docs.ocg.to/books/shopbase-project-info/page/integrated-payment-checkout-flow/4417#bkmrk-2.1-request-values) with the POST method and the `x-www-form-urlencoded` format.
2. Your provider performs a signature validation to ensure that the request is sent from ShopBase. Your provider displays on the checkout page and lets buyers confirm their payment.
3. Your provider redirects to `x_url_complete` with GET method and all required parameters. ShopBase will validate the data and create the Order.
4. ShopBase will redirect to the Thank-you page to inform the buyer that the payment is complete.
5. Your provider needs to make a POST request to `x_url_callback`. It informs ShopBase that the payment has completed with the same response parameters as when it was redirected. It also ensures that the Order will be created even if the buyer goes offline before being redirected to ShopBase.
6. ShopBase records the payment and responses with a 200 HTTP status to the provider.

#### **2.2.2 Embeded Checkout**

![](/files/-MS6A4Am6r0SUt78EBQH)

1. First, the buyer needs to fulfill the information: shipping address, billing information, shipping method... and choose your provider as the payment method. ShopBase will embed your `Iframe Url` to block Payment method on the checkout page.
2. Your iframe should display the card element (or whatever element), so the buyer can interact with it.
3. When the buyer provides card details and clicks Place Order, ShopBase will post a message into the iframe with [request values](#request-values).
4. Your iframe should request your provider server to confirm payment and obtain gateway authorization reference
5. Your iframe post message to ShopBase with required [response values](#response-values).
6. ShopBase will request to ShopBase server to verify payment status with your provider server, then create an Order.
7. ShopBase server displays the order information to the client with the Thank you page to indicate that the order has been paid successfully.
8. We suggest your provider make a POST request to `x_url_callback`. It informs ShopBase that the payment has completed with the same response parameters when posting the message on iframe. It also ensures that the Order will be created even if the buyer loses the connection before the ShopBase Server receives the payment information.

#### **2.2.3 Post-Purchase**

**What is post-purchase?**&#x20;

To help merchants who want to motivate customers after they bought something from the store. ShopBase designed a feature called Post-Purchase. This feature can re-engage customers who just complete a purchase and catch them on the site when they are most likely to buy or to comply with other requests.

**How to implement it?**

Almost, has the same normal flow, but still has some differences.

After the first purchase is completed, we will send a new authorization with x\_reference has the same value with the first authorization and `x_post_purchase` is true. These have some different ways to process Post-Purchase, it depends on the flow which you choose for implementation.

* For **Hosted payment page** flow, we will redirect the customer to Gateway payment page, and use **Redirect API** with the same `x_reference` and `x_post_purchase` is true.
* For ​**Embedded checkout** flow, we will send `update-authorization` request use Order management API ​with the same `x_reference` and `x_post_purchase`  is `true`.

At this step, the gateway needs to capture this second authorization and return a new transaction id. And note that, ShopBase only accepts the `update-authorization` once within 10 minutes after the first authorization. Authorization cannot be updated twice​.

## 3. API reference

[**Link Postman**<br>](https://www.postman.com/warped-meteor-302495/workspace/shopbase/collection/16061299-c34173f3-40af-487c-bf80-d3aea05e13d4)**:**<https://www.postman.com/warped-meteor-302495/workspace/shopbase/collection/16061299-c34173f3-40af-487c-bf80-d3aea05e13d4>

### 3.1 Redirect API + Iframe postMessage

It is used in the checkout flow to redirect to a hosted checkout page or embed an iframe in an embedded checkout page.&#x20;

#### **Request values**

| Key                                                                                                                      | Type                                                           | Example                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |                                                                                                                 |
| ------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| `x_account_id` **Required.**                                                                                             | ascii string                                                   | 10023456                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  | ShopBase payment account ID, for getting Gateway Credentials.                                                   |
| `x_amount` **Required.**                                                                                                 | decimal                                                        | 89.99                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |                                                                                                                 |
| `x_currency` **Required.**                                                                                               | [iso-4217](https://en.wikipedia.org/wiki/ISO_4217)             | USD                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |                                                                                                                 |
| `x_reference` **Required.**                                                                                              | ascii string                                                   | 19783                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     | Unique token for current checkout (checkout token)                                                              |
| `x_shop_name` **Required.**                                                                                              | unicode string                                                 | Widgets Inc                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               | To display shop name on Hosted checkout page                                                                    |
| `x_test` **Required.**                                                                                                   | true/false                                                     | true                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      | Indicates whether or not this request should be processed in test mode (if supported).                          |
| `x_url_callback` **Required.**                                                                                           | url                                                            |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           | URL to which a callback notification should be sent asynchronously.                                             |
| <p><code>x\_url\_cancel</code> <strong>Required.</strong></p><p><strong>Note:</strong></p><p>Optional with iframe</p>    | url                                                            |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           | URL to which customer must be redirected when they wish to quit payment flow and return to the merchant's site. |
| <p><code>x\_url\_complete</code> <strong>Required.</strong></p><p><strong>Note:</strong></p><p>Optional with iframe</p>  | url                                                            |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           | URL to which customer must be redirected upon successfully completing payment flow.                             |
| `x_post_purchase`                                                                                                        | true/false                                                     | false                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     | Indicates whether or not this request is for making post purchase.                                              |
| `x_purchase_items`                                                                                                       | nested                                                         | <p>\[<br>  {<br>    "name": "Shirt",<br>    "quantity": 2,<br>    "price": 10,<br>    "url": "<a href="https://q-payment-test.onshopbase.com/products/shirt-1"><https://q-payment-test.onshopbase.com/products/shirt-1></a>",<br>    "image": "<a href="https://img.btdmp.com/10243/10243285/products/1636621679424.jpg"><https://img.btdmp.com/10243/10243285/products/1636621679424.jpg></a>",<br>    "options": \[<br>      {<br>        "label": "Size",<br>        "value": "L"<br>      },<br>      {<br>        "label": "Color",<br>        "value": "Red"<br>      }<br>    ]<br>  }</p><p>]</p> | To display purchase items on Hosted checkout page                                                               |
| `x_customer_billing_address1`                                                                                            | unicode string                                                 | 241 Spadina Ave                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |                                                                                                                 |
| `x_customer_billing_address2`                                                                                            | unicode string                                                 |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |                                                                                                                 |
| `x_customer_billing_city`                                                                                                | unicode string                                                 | Toronto                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |                                                                                                                 |
| `x_customer_billing_company`                                                                                             | unicode string                                                 | ShopBase                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |                                                                                                                 |
| `x_customer_billing_country`                                                                                             | [iso-3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1) | CA                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |                                                                                                                 |
| `x_customer_billing_phone`                                                                                               | unicode string                                                 | +1-613-987-6543                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |                                                                                                                 |
| `x_customer_billing_state`                                                                                               | unicode string                                                 | ON                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |                                                                                                                 |
| `x_customer_billing_zip`                                                                                                 | unicode string                                                 | M5T 3A8                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |                                                                                                                 |
| `x_customer_email`                                                                                                       | unicode string                                                 | <boris.slobodin@example.com>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |                                                                                                                 |
| `x_customer_first_name`                                                                                                  | unicode string                                                 | Boris                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |                                                                                                                 |
| `x_customer_last_name`                                                                                                   | unicode string                                                 | Slobodin                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |                                                                                                                 |
| `x_customer_phone`                                                                                                       | unicode string                                                 | +1-613-987-6543                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |                                                                                                                 |
| `x_customer_shipping_address1`                                                                                           | unicode string                                                 | 241 Spadina Ave                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |                                                                                                                 |
| `x_customer_shipping_address2`                                                                                           | unicode string                                                 |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |                                                                                                                 |
| `x_customer_shipping_city`                                                                                               | unicode string                                                 | Toronto                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |                                                                                                                 |
| `x_customer_shipping_company`                                                                                            | unicode string                                                 | ShopBase                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |                                                                                                                 |
| `x_customer_shipping_country`                                                                                            | [iso-3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1) | CA                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |                                                                                                                 |
| `x_customer_shipping_first_name`                                                                                         | unicode string                                                 | Boris                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |                                                                                                                 |
| `x_customer_shipping_last_name`                                                                                          | unicode string                                                 | Slobodin                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |                                                                                                                 |
| `x_customer_shipping_phone`                                                                                              | unicode string                                                 | +1-416-123-4567                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |                                                                                                                 |
| `x_customer_shipping_state`                                                                                              | unicode string                                                 | ON                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |                                                                                                                 |
| `x_customer_shipping_zip`                                                                                                | unicode string                                                 | M5T 3A8                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |                                                                                                                 |
| <p><code>x\_intent</code> <strong>Required.</strong></p><p><strong>Note:</strong></p><p>Require if using iframe flow</p> | fixed choice                                                   | authorize                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 | Possible values: `authorize`                                                                                    |

#### **Response values**

| Key                                 | Type                                                      | Example                                | Note                                                              |
| ----------------------------------- | --------------------------------------------------------- | -------------------------------------- | ----------------------------------------------------------------- |
| `x_account_id` **Required.**        | ascii string                                              | 10023456                               | ShopBase payment account ID, for getting Gateway Credentials.     |
| `x_amount` **Required.**            | decimal                                                   | 89.99                                  | Echo request's `x_amount`                                         |
| `x_currency` **Required.**          | [iso-4217](https://en.wikipedia.org/wiki/ISO_4217)        | USD                                    | Echo request's `x_currency`                                       |
| `x_gateway_reference` **Required.** | unicode string                                            | 123                                    | Unique reference for payment issued by the payment processor.     |
| `x_reference` **Required.**         | ascii string                                              | 19783                                  | Echo request's `x_reference`                                      |
| `x_transaction_type` **Required.**  | fixed choice                                              | authorization                          | The valid values are `authorization`, `capture`, `refund`, `void` |
| `x_result` **Required.**            | fixed choice                                              | completed                              | Valid values are `completed`, `failed`                            |
| `x_test` **Required.**              | true/false                                                | true                                   | Echo request's `x_test`                                           |
| `x_timestamp` **Required.**         | [iso-8601](https://en.wikipedia.org/wiki/ISO_8601) in UTC | 2014-03-24T12:15:41Z                   | Time of transaction completion. UTC Time: YYYY-MM-DDTHH:MM:SSZ    |
| `x_message`                         | ascii string                                              | Billing address could not be verified. | A custom error message displayed to the customer.                 |
| `x_error_code`                      | ascii string                                              | ACCOUNT\_RESTRICTED                    | An error code to be log on ShopBase                               |

**Custom iframe message**

The following messages can be posted from the iframe to the ShopBase window to modify the iframe container.&#x20;

| Key                      | Type         | Example        |                                        |
| ------------------------ | ------------ | -------------- | -------------------------------------- |
| `x_intent` **Required.** | fixed choice | iframe\_update | Update the iframe of the payment block |
| `x_iframe_height`        | number       | 100            | Resize iframe height to 100px          |

### 3.2 Order management API

* These are endpoints used to perform actions such as capture, refund, void order.
* In the **Embedded checkout** flow, the Payment provider needs to provide more update-authorization endpoint to use in **ShopBase's Post-Purchase** feature.

**Note:**&#x20;

* Only accept the update-authorization once within 10 minutes after the first authorization. An authorization cannot be updated twice.&#x20;

**Request values**

| Key                                 | Type                                               | Example                    |                                                                                        |
| ----------------------------------- | -------------------------------------------------- | -------------------------- | -------------------------------------------------------------------------------------- |
| `x_account_id` **Required.**        | ascii string                                       | 10023456                   | ShopBase payment account ID, for getting Gateway Credentials                           |
| `x_amount`                          | decimal                                            | 89.99                      |                                                                                        |
| `x_currency`                        | [iso-4217](https://en.wikipedia.org/wiki/ISO_4217) | USD                        |                                                                                        |
| `x_reference` **Required.**         | integer                                            | 19783                      | ShopBase order id                                                                      |
| `x_gateway_reference` **Required.** | ascii string                                       | 450789469                  | Unique reference for payment issued by the payment processor.                          |
| `x_test` **Required.**              | true/false                                         | true                       | Indicates whether or not this request should be processed in test mode (if supported). |
| `x_url_callback` **Required.**      | url                                                |                            | URL to which a callback notification should be sent asynchronously.                    |
| `x_transaction_type` **Required.**  | fixed choice                                       | capture                    | The valid values are `update-authorization`, `capture`, `refund`, `void`               |
| `x_invoice`                         | unicode string                                     | #123                       | Only available on request type = `capture`                                             |
| `x_refund_reason`                   | unicode string                                     | admin refunded $150.00 USD | Only available on request type = `refund`                                              |

**Response values**&#x20;

<table data-header-hidden><thead><tr><th width="212">Key</th><th>Type</th><th>Example</th><th>Note</th></tr></thead><tbody><tr><td>Key</td><td>Type</td><td>Example</td><td>Note</td></tr><tr><td><code>x_gateway_reference</code> <strong>Required.</strong></td><td>unicode string</td><td>123</td><td>Unique reference for payment issued by the payment processor.</td></tr><tr><td><code>x_reference</code> <strong>Required.</strong></td><td>ascii string</td><td>19783</td><td>Echo request's <code>x_reference</code></td></tr><tr><td><code>x_transaction_type</code> <strong>Required.</strong></td><td>fixed choice</td><td>capture</td><td>The valid values are <code>authorize</code>, <strong><code>capture</code></strong>, <strong><code>void</code></strong>, and <strong><code>refund</code></strong>.</td></tr><tr><td><code>x_result</code> <strong>Required.</strong></td><td>fixed choice</td><td>completed</td><td>Valid values are <code>completed</code> or <code>failed</code></td></tr><tr><td><code>x_timestamp</code> <strong>Required.</strong></td><td><a href="https://en.wikipedia.org/wiki/ISO_8601">iso-8601</a> in UTC</td><td>2014-03-24T12:15:41Z</td><td>Time of transaction completion. UTC Time: YYYY-MM-DDTHH:MM:SSZ</td></tr><tr><td><code>x_message</code></td><td>ascii string</td><td>Billing address could not be verified.</td><td>A custom error message displayed to the customer.</td></tr><tr><td><code>x_error_code</code></td><td>ascii string</td><td>ACCOUNT_RESTRICTED</td><td>An error code to be log on ShopBase</td></tr></tbody></table>

### 3.3 Get transaction info API

This API is the endpoint to retrieve information on one transaction. Payment Provider needs to provide information in accordance with  `x_transaction_type` (authorization, capture, refund or void) that ShopBase requests.

**Request values**

| Key                                 | Type         | Example   |                                                                                        |
| ----------------------------------- | ------------ | --------- | -------------------------------------------------------------------------------------- |
| `x_account_id` **Required.**        | ascii string | 10023456  | ShopBase payment account ID, for getting Gateway Credentials.                          |
| `x_reference` **Required.**         | ascii string | 19783     | Checkout token or order id depends on `x_transaction_type`                             |
| `x_gateway_reference` **Required.** | ascii string | 450789469 | Unique reference for payment issued by the payment processor.                          |
| `x_test` **Required.**              | true/false   | true      | Indicates whether or not this request should be processed in test mode (if supported). |
| `x_transaction_type` **Required.**  | fixed choice | capture   | The valid values are `authorization`, `capture`, `refund`, `void`                      |
| `x_result` **Required.**            | fixed choice | completed | Valid values are `completed`, `failed`                                                 |

**Response values**&#x20;

Same as ​Redirect API Response value

### 3.4 Check Credentials API

The API is the endpoint to check the legitimacy of one set of gateway credentials (it can be used to make transactions and refund transactions). ShopBase will use this endpoint whenever the merchants activate your payment in the ShopBase dashboard.

**Request values**

| Key                                   | Type | Example |                                                       |
| ------------------------------------- | ---- | ------- | ----------------------------------------------------- |
| `x_gateway_credentials` **Required.** | json |         | The json object contains Payment Gateway credentials. |

**Response values**&#x20;

| Key                      | Type         | Example |                                                              |
| ------------------------ | ------------ | ------- | ------------------------------------------------------------ |
| `x_result` **Required.** | fixed choice | valid   | The valid values are **valid**, **invalid**, **restricted**. |

### 3.5 Get Gateway Credentials

It provides gateway's credentials for your provider.

**Endpoint:** [**https://api.shopbase.com/api/checkout/payment-credential.json**](https://api.shopbase.com/api/checkout/payment-credential.json)

**Request values**

| Key                          | Type         | Example  |                                                               |
| ---------------------------- | ------------ | -------- | ------------------------------------------------------------- |
| `x_account_id` **Required.** | ascii string | 10023456 | ShopBase payment account ID, for getting Gateway Credentials. |

**Response values**

| Key                                   | Type         | Example            |                                                       |
| ------------------------------------- | ------------ | ------------------ | ----------------------------------------------------- |
| `x_gateway_credentials` **Required.** | json         |                    | The json object contains Payment Gateway credentials. |
| `x_message`                           | ascii string | Invalid signature  | A custom readale error message.                       |
| `x_error_code`                        | ascii string | invalid\_signature | An error code                                         |

### 3.6 Asynchronous callback

* It makes certain that all orders can be completed, even If your gateway and customer connection is disconnected. You can get the callback URL in `x_url_callback` param.
* In the **Embedded checkout** flow, If **ShopBase's Post-Purchase** feature is active, please note that will require a new transaction for second authorization.

**Request values**

| Key                                 | Type                                                      | Example                                | Note                                                              |
| ----------------------------------- | --------------------------------------------------------- | -------------------------------------- | ----------------------------------------------------------------- |
| `x_account_id` **Required.**        | string                                                    | 10023456                               | ShopBase payment account ID, for getting Gateway Credentials.     |
| `x_amount` **Required.**            | decimal                                                   | 89.99                                  | Echo request's `x_amount`                                         |
| `x_currency` **Required.**          | [iso-4217](https://en.wikipedia.org/wiki/ISO_4217)        | USD                                    | Echo request's `x_currency`                                       |
| `x_gateway_reference` **Required.** | ascii string                                              | 123                                    | Unique reference for payment issued by the payment processor.     |
| `x_reference` **Required.**         | ascii string                                              | 19783                                  | Echo request's `x_reference`                                      |
| `x_transaction_type` **Required.**  | fixed choice                                              | authorization                          | The valid values are `authorization`, `capture`, `refund`, `void` |
| `x_result` **Required.**            | fixed choice                                              | completed                              | Valid values are `completed`, `failed`                            |
| `x_test` **Required.**              | true/false                                                | true                                   | Echo request's `x_test`                                           |
| `x_timestamp` **Required.**         | [iso-8601](https://en.wikipedia.org/wiki/ISO_8601) in UTC | 2014-03-24T12:15:41Z                   | Time of transaction completion. UTC Time: YYYY-MM-DDTHH:MM:SSZ    |
| `x_message`                         | ascii string                                              | Billing address could not be verified. | A custom error message displayed to the customer.                 |
| `x_error_code`                      | ascii string                                              | ACCOUNT\_RESTRICTED                    | An error code to be log on ShopBase                               |

**Response**

If request success, Shopbase will return HTTP status 200. Otherwise, you should retry later with a delay time.

### 3.7 Signing mechanism

All requests and responses must be signed/verified using [**HMAC-SHA256**](https://en.wikipedia.org/wiki/Hash-based_message_authentication_code), where:&#x20;

* `key` is[ ShopBase Payment Key](#id-1.3-get-shopbase-payment-key). If Provider uses more than 1 ShopBase Payment Key, ShopBase always uses the older one (compared by activated date).&#x20;

<figure><img src="/files/S9VmixgEV8eSpW3Mi9Y3" alt=""><figcaption><p>ShopBase Payment Key</p></figcaption></figure>

* `message` is a string of all key-value pairs that start with `x_` prefix, sorted alphabetically and concatenated without separators.

**Note:**&#x20;

* The result codes must be hex-encoded and passed as the value of `x_signature`. Make sure to use case-insensitive comparison when verifying the provided `x_signature` values.

Assuming your HMAC key is `iU44RWxeik`, the signing mechanisms would look like this:

```
key = 'iU44RWxeik'
fields = {x_account_id: '10023456', x_amount: 89.99, x_currency: 'USD', x_gateway_reference: '123', x_reference: "19783", x_result: "completed", x_test: "true",  x_timestamp: '2014-03-24T12:15:41Z'}
=> {:x_account_id=>"10023456", :x_amount=>89.99, :x_currency=>"USD", :x_gateway_reference=>"123", :x_reference=>"19783", :x_result=>"completed", :x_test=>"true", :x_timestamp=>"2014-03-24T12:15:41Z"}
message = fields.sort.join
=> "x_account_id10023456x_amount89.99x_currencyUSDx_gateway_reference123x_reference19783x_resultcompletedx_testtruex_timestamp2014-03-24T12:15:41Z"
OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), key, message)
=> "49d3166063b4d881b50af0b4648c1244bfa9890a53ed6bce6d2386404b610777"

"x_signature=49d3166063b4d881b50af0b4648c1244bfa9890a53ed6bce6d2386404b610777"
```

Signature will be sent in HTTP header `X-Signature` of request.

### 3.8 Error codes

|   | **Error codes**         | **Description**                                                                                                                                      |
| - | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| 1 | card\_declined          | Card declined by any reasons (anti-fraud, declined by bank..)                                                                                        |
| 2 | processing\_error       | An error occurred while processing the card. Try again later or with a different payment method.                                                     |
| 3 | call\_issuer            | The card has been declined for an unknown reason. The customer needs to contact their card issuer for more information.                              |
| 4 | pick\_up\_card          | The customer's card issuer has declined the transaction and requested that the card be retained as the card may have been reported as lost or stolen |
| 5 | invalid\_signature      |                                                                                                                                                      |
| 6 | account\_restricted     |                                                                                                                                                      |
| 7 | account\_invalid        |                                                                                                                                                      |
| 8 | payment\_not\_supported | Does not support this payment for some reason.                                                                                                       |
| 9 | missing\_param          | Missing "x" params                                                                                                                                   |

### 3.9 Other notes

* HTTP 200 indicates successful receipt of a callback by ShopBase. Otherwise, up to 5 retries with an interval of at least 60 seconds are recommended.
* In case the merchant performs the capture/refund/void action from the payment provider dashboard, POST a callback asynchronously to ShopBase payment callback URL to notify ShopBase for syncing the order status.
* ShopBase ignores duplicate requests.
* Here are two git examples for reference
  * Dummy: [ https://github.com/ShopBaseCom/demo-intergrated-gateway](< https://github.com/ShopBaseCom/demo-intergrated-gateway>)
  * &#x20;Full integrated gateway demo: <https://github.com/ShopBaseCom/asiabill-sdk> &#x20;

## 4. Testing (for ShopBase simulator)

|   | **Transaction amount** | **Description**                |
| - | ---------------------- | ------------------------------ |
| 1 | 99.00\~99.99           | processing\_error when capture |
| 2 | 101.00\~101.99         | processing\_error when refund  |

|   | **Credit card number** | **Description** |
| - | ---------------------- | --------------- |
| 1 | 4242 4242 4242 4242    | Payment success |
| 2 | Other                  | card\_declined  |

|   | **Account ID**      | **Description**                              |
| - | ------------------- | -------------------------------------------- |
| 1 | invalid             | Will be invalid when validate credentials    |
| 2 | restricted          | Will be restricted when validate credentials |
| 3 | restricted\_payment | Will be restricted when authorize payment    |

## 5. Technical requirements

### Security

* ShopBase always double-validate all request calls between 2 sides: validate request payload + signature, and validate real data (using payment information from the **Get Payment Info API**​ to compare). All the data should be validated:&#x20;
  * `x_reference` should similar to checkout token and order id of ShopBase
  * `x_amount` of transaction should matches with the amount of ShopBase&#x20;
  * `x_result` should be completed
  * `x_test`, `x_account_id` should match with ShopBase's request
* ShopBase payment key, Gateway's credentials are private and hidden in all APIs.
* Messages posted via iFrame need to be defined protocol + host + port strictly to ensure no other parties can eavesdrop. When Payment Provider received the messages via iFrame, you also need to check the origin of the requests to ensure they are sent from ShopBase.

### Stability

* When handling requests from payment providers, ShopBase will have a process lock to avoid duplicating requests.
* All the requests to payment providers will be logged by ShopBase (i.e. request, response, error rate, error code) to trace back the problems and statistics.

### Usability

* Embedded iframe needs to share the same style with ShopBase and support responsive.
* You need to ensure rendering speed, API process speed.


