How to Auth @ ShipBob

Summary

ShipBob authenticates using the OAuth 2.0 flow. Basically this means that as an app you 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 said 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. These 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 https://acme.co/shipbobintegrationtest

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 id for operations pertaining to 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.
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: https://web.shipbob.com/app/Merchant/#/SignUp. The demo period does not expire and you can effectively use this as a sandbox to test API calls for your application to your own user account.

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

GET https://auth.shipbob.com/connect/authorize

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 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. Recommended if you know the user’s store name on your platform. If not provided, the user will be prompted to provide their own name or choose one from a drop down of options. recommended

NOTE: these parameters must be url encoded, particularly redirect_uri.

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

GET https://auth.shipbob.com/connect/authorize?
   client_id=MyCoolClient&
   scope=products_read channels_read offline_access&
   redirect_uri=https%3A%2F%2Fwww.myapp.com%2Fintegrate%2Fshipbob%2Fcallback

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 actually granted by the user, space separated. May be a subset of scopes requested by the app unless all scopes are marked as “required”

By default, we will call the following:

https://www.myapp.com/integrate/shipbob/callback#
   code=some_access_code&
   id_token=some_open_id_token&
   state=provided_state&
   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:

POST https://www.myapp.com/integrate/shipbob/callback
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) 

code={}
&id_token={}
&scope=openid+fulfillments_read+orders_read+offline_access
&state=810675d6-3453-471f-a435-841a5e6e82c5
&session_state=jRPAPm_BKQNRgJn9etH7qUJvbVSaglQNgXG-2tuyPqA.8c935b46eb19fab4210f546bfc11c31e

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 make a request for an access token that allows you to actually make API calls. You will have to POST to the following endpoint:

POST https://auth.shipbob.com/connect/token

redirect_uri=https%3A%2F%2Fwww.myapp.com%2Fintegrate%2Fshipbob%2Fcallback
&client_id=MyCoolApp
&client_secret=someSecret
&code=code_from_step_3
&grant_type=authorization_code

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 also 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:

POST https://auth.shipbob.com/connect/token

redirect_uri=https%3A%2F%2Fwww.myapp.com%2Fintegrate%2Fshipbob%2Fcallback
&client_id=MyCoolApp
&client_secret=someSecret
&refresh_token=token_provided_from_first_authorization
&grant_type=refresh_token

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.

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 own channel.

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

GET https://api.shipbob.com/1.0/channel

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.