Developer API Authentication


ShipBob's Developer API allows 2 forms of authentication, depending on the use case: Personal Access Token (PAT) or OAuth 2.0.

  • If you're building a single-user custom integration, you can use the Personal Access Token (PAT) method. This generates a ready-to-use bearer-type token with full access to the merchant's account.

    • You can generate credentials from the ShipBob dashboard.

  • If you are building an integration or app that will be multi-user or listed on our App Store, you must use the OAuth flow.

    • You can request credentials by filling out the form here.

NOTE: All API authentication operates against the root user of the account. When requesting a PAT token or installing an OAuth app, you should do so against the root user.

Personal Access Token (PAT) Flow

When you request your first PAT, ShipBob automatically generates an application (called "SMA" or single-merchant application) and channel to house all your future PATs. You can request as many as you like, and revoke them at any time.

NOTE: These tokens do not expire, so be extremely cautious when sharing them.

Your PAT should automatically have read and write access to the entire ShipBob account.

To use your PAT, just provide the token as an Authorization header formatted like this:

bearer [your_api_token]

First you should use your PAT to hit the GET Channel endpoint, so you can use your channel ID in the headers of subsequent API calls. Your response will look like this:

"id": 56232,
"name": "Personal Access Token Thursday, March 19, 2020",
"application_name": "SMA",
"scopes": [
    "channels_read orders_read orders_write products_read products_write receiving_read receiving_write returns_read returns_write inventory_read"

OAuth Flow

To finish the authentication process, your app will have to do the following:

  1. Request a client ID and client secret.
  2. Request authorization from a ShipBob user.
  3. Retrieve an authorization code from a provided callback.
  4. Exchange the authorization code for an access token.
  5. Begin making API calls.

Step 0: Get Familiar with OAuth 2.0

At ShipBob, we use OAuth 2.0 for its robust security and relatively universal implementations.

If you’re not familiar, you can read more about working with OAuth’s hybrid flow here.

NOTE: If you want to use Postman or a similar tool to hit our API endpoints during testing, ensure that your redirect URL is set up EXACTLY as you entered when you requested access, and Postman is set up for OAuth 2.0

Step 1: Request a Client ID and Secret for your Application

Begin by filling out and submitting this form to request a client ID and secret. Once approved, we will email you the ID and secret, as well as your approved API scopes.

In addition to requesting scopes, you will need to provide us with a list of callback URIs. Please provide us with callback URIs that don't include a hash (fragments). URLs that include hashes (fragments) will result in errors. These URIs provided must exactly match any endpoint you will use as a callback when calling /connect/authorize. This means including any https:// prefix and appropriate slugs. For security reasons, please only use domains that you can control - e.g. if you are from ACME, Co you should use something like

You may request access for the following scopes:

Scope Description
orders_read Read information about a user’s orders.
orders_write Create and modify orders for a user.
products_read Read information about a user’s products (application SKUs).
products_write Create and modify products for a user.
fulfillments_read Read information about a user’s shipments and fulfillments.
inventory_read Read information about a user’s inventory (physical items).
channels_read Read channel to get the id for operations of other API calls. This is required.
receiving_read Read receiving is required to retrieve Warehouse Receiving Orders from the user account.
receiving_write Read receiving is required to create Warehouse Receiving Orders on behalf of the user account.
returns_read Required to retrieve Returns on behalf of the user account.
returns_write Required to create or modify Returns on behalf of the user account.
webhooks_read Read access to a user's webhooks is required to interact with the Webhooks API. Note: each webhooks topic will also be tied to the auth policy for the underlying resource (e.g. ordershipped is tied to ordersread).
webhooks_write Write access to create or delete webhook subscriptions on behalf of a user account.
locations_read Required to retrieve associated Locations from the user account.
offline_access Enable refresh token functionality when requesting tokens (bypass /connect/authorize after initial token grant).

Step 2: Request Permission to See User's Data

NOTE: if you do not yet have a ShipBob user in mind - you can sign up for a free demo account here: The demo period does not expire and you can effectively use this as a sandbox to test API calls for your application to your user account.

Once you have your client ID and secret, you can use them to get a user’s permission to access their account data. You start by making a request to the following endpoint:


The following query parameters are allowed for this endpoint:

Parameter Values Required?
client_id Client id provided by step 1. required
scope One or more scopes granted by step 1, space-separated. NOTE: if you want to take advantage of refresh tokens (aka offline access mode) you must additionally request the “offline_access” scope. required
redirect_uri The callback URI ShipBob will call after the user responds to the request for consent. Must match one of the provided values from step 1. required
response_mode If you include this query parameter with value form_post then we will make a POST request to your callback URL, instead of including the data as a fragment. optional
state Application-provided string to help prevent replay attacks. Echoed back to the application in the callback for validation. recommended
nonce A random string you can send and we will send it back within the token, to prevent replay attacks, code substitutions, etc. recommended
integration_name Name of the integration for this particular user. We recommend that you know the user’s store name on your platform. If not provided, the user will be prompted to provide their name or choose one from a drop-down of options. recommended

NOTE: These parameters must be URL encoded, particularly redirect_uri.

A very basic example call to our integrate endpoint will look like this:

   scope=products_read channels_read offline_access&

Step 3: Implement Your Callback URI

Now that you’ve made a call to the "integrate" endpoint, the granting of permission is entirely within the user’s hands. Whether they grant or not, your application must implement a GET endpoint with the following URI fragment parameters:

Parameter Value
error String; “access_denied” if the user selects deny. Not present if the user selects allow
state Echoed state string provided in step 2. Not present if the user selects deny
code Authorization code string used to request a token. Valid for 2 minutes and only works once. Not present if the user selects deny
scope The scopes granted by the user, space-separated. Maybe a subset of scopes requested by the app unless all scopes are marked as “required”

By default, we will call the following:
   scope=channels_read orders_read orders_write

NOTE: the data will return as a fragment, not a query string.

ShipBob will attempt to call this endpoint when the user completes the consent step.

If you use response_mode=form_post we will make a POST request to the callback URI, with the data contained in the body, something like this:

Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) 


As mentioned, the URI must match exactly one of the provided callback URIs from step 1. If the user selects allow, it’s highly recommended that you validate the response against a provided state string to prevent replay attacks.

Step 4: Get Your Access Token

Within the 2-minute expiration window of the authorization code, you can now request an access token that allows you to make API calls. You will have to POST to the following endpoint:


Which will return the following response:

  "access_token": "your_api_token",
  "expires_in: "3600",
  "token_type": "bearer"

If you request the offline_access scope, you will be provided with a refresh_token parameter. You can then use that to make a separate call to /connect/token with a body that looks like this:


NOTE: Access tokens are good for 1 hour before they expire. Request a refresh token before the access token expires. The refresh token is valid for 30 days.

When posting, make sure your Content-Type is application/x-www-form-urlencoded.

Congratulations! Now you can start making API calls. You’re going to want to do this first though...

Step 5: Get Your Channel ID

A channel is a specific installation of an application built by a vendor on top of our API – e.g. “Kevin’s Shopify Store #133432.”

Every call you make to a ShipBob API resource using a write scope must include the shipbob_channel_id header. The channel is used to identify where the data originally came from. By default, applications must also pass the shipbob_channel_id header when using a read scope for many ShipBob API resources and will only receive data from the channel passed in the header.

OAuth Applications that are granted multi-channel permissions will receive data from all channels that belong to a merchant when making a call to a ShipBob API resource using a read scope. However, multi-channel applications making a call to a ShipBob API resource using a write scope can only write on behalf of their channel.

But how do you get the Channel ID? By querying our Channels API. Using your shiny new token, make the following call:


This will respond with all of the channels that a user has authorized for your client:

    "id": 12345,
    "name": "integration_name_unique_to_user"

You must provide the access token generated in step 4 as an Authorization header formatted as bearer your_api_token as well as a content_type header of “application/json”. You can then use this channel_id in your headers for all subsequent API calls.

And that’s it! Now you can make ShipBob API calls to your heart’s content. Note that for now, API calls will be rate-limited to 150 requests per minute using a sliding window, and will be totaled per user, per application across calls to any of the ShipBob APIs.