How to call our APIs

Authentication

Anonymous calls

Some of our functions can be invoked without an authentication token or with an empty one. We call these anonymous calls.

  • All read-only Loyalty API functions can be called anonymously, and will assume empty customer state.
  • All Blocks API blocks can be embedded anonymously, and will similarly assume an empty customer state.

JWT tokens

Bubblehouse authenticates uses via HS256 JWT tokens that you generate on your end, based on a shared secret set up in Bubblehouse API console.

If you have never used JWT, it's just a Base64-encoded JSON signed (in case of HS256 tokens) using HMAC-SHA256, with the shared secret as the HMAC key. API console will link you to JWT.io debugger, which allows to inspect, verify and create these tokens.

So, to reiterate:

  • Shared secrets are generated by Bubblehouse upon your request.

    You can have multiple shared secrets, perhaps for multiple environments or for secret rotation. A specific secret is selected based on Key ID field (kid) in JWT header

    Shared secrets do not expire. You can revoke them manually.

  • The actual tokens come from you. You can generate any number of tokens you want, with any supported JWT features.

Every JWT token presented to Bubblehouse needs to have:

  • kid (Key ID) field in the header specifying the particular shared secret used.
  • aud (Audience) set to BH.
  • sub (Subject) set to either a shop slug (my-shop), or a combination of shop slug and customer ID (my-shop/1234)

Additionally, you can set:

  • iat (Issued At) to have Bubblehouse reject a key before a certain time
  • exp (Expires At) to have Bubblehouse reject a key after a certain time
  • l (Level) to select admin-level or customer-level access for a given customer token

NOTE: if you do NOT include Expires At property, your tokens will never expire, and will remain valid until you revoke the corresponding shared secret. We recommend adding a reasonable expiration time and generate fresh tokens whenever needed.

3 kinds of tokens

The app supports three kinds of tokens:

  1. Shop tokens are for your backend servers, and allow acting on behalf of the shop owner.

    They MUST be kept private and cannot be exposed to your front-end code or mobile apps.

    We recommend giving these tokens a short expiration time (a few minutes), and generate a fresh one on every use.

  2. Customer tokens are for your frontend code and mobile apps, and allow acting on behalf of a single shop customer.

    In many cases, you should give these tokens a short expiration time (1 to 5 minutes is recommended).

  3. Admin customer tokens are a blend of the two above. These are for your backend servers and, perhaps, for admin-only frontend code. These allow to act on a given shop customer with full shop-level priviledges.

    These are generated similar to customer tokens, but annotated to give shop-level admin priviledges.

See the example tokens on the API console for the exact claims included in each kind.

Tokens cannot be generated in front-end JavaScript

There is absolutely no way to safely generate tokens in front-end JavaScript code. If you attempt to do this, you will allow any visitor of your store to make any changes to the entire store and to impersonate any customer or the administrator of your store.

Authenticating RPC API calls

RPC API calls accept the token via Authorization: Bearer <token> header.

Alternatively, you can pass the token via auth query param, but this is mainly intended for debugging purposes, mostly for making trivial GET calls by opening a URL in a web browser. You SHOULD NOT use this in production; Bubblehouse reserves the right to apply development rate limiting to such tokens.

Authenticating Blocks API calls

Blocks API calls accept the token via auth query param.

Generating tokens when using Shopify Hydrogen

As described above, you need to generate JWT tokens to access Bubblehouse APIs, and that needs to happen server-side.

Tokens cannot be generated in front-end JavaScript

It is worth repeating that there is no possible way to generate Bubblehouse tokens on the front-end side without compomising the security of the entire shop.

After authenticating a customer via Customer Account API, be sure to store their Shopify customer ID in your session data; you will need the customer ID to create Bubblehouse tokens. Then produce the token based on this customer ID, combined with the key ID, shared secret and shop slug from Bubblehouse API console. (See the example below.)

Example (Node.js)

Here's an example JavaScript function that generates valid Bubblehouse tokens:

function signBubblehouseToken(subject, keyId, keySecretInBase64, validityInSeconds) {
  let nowUnix = Math.floor(Date.now() / 1000)
  let header = {'typ': 'JWT', 'alg': 'HS256', 'kid': keyId}
  let payload = {'aud': 'BH', 'sub': subject, 'exp': nowUnix + validityInSeconds}
  let raw = Buffer.from(JSON.stringify(header)).toString('base64url') + '.' + Buffer.from(JSON.stringify(payload)).toString('base64url')
  let hmac = require('crypto').createHmac('sha256', Buffer.from(keySecretInBase64, 'base64'))
  hmac.update(raw)
  return raw + '.' + hmac.digest('base64url')
}

Customer token:

signBubblehouseToken('shopify-yourshop/123456789', '1b356cdffb010001', 'Idkau7WmFTRh1w+pX0Snp3EQA6pJ+h19qdb38ylwIyY', 3600)

Shop token:

signBubblehouseToken('shopify-yourshop', '1b356cdffb010001', 'Idkau7WmFTRh1w+pX0Snp3EQA6pJ+h19qdb38ylwIyY', 3600*24)

Example (PHP)

Here's an example PHP function that generates valid Bubblehouse tokens (using only standard PHP library with no dependencies):

<?php

function bubblehouse_token_sign($subject, $keyId, $keySecretInBase64, $validity_sec) {
    $raw = bubblehouse_base64url_encode(json_encode(['typ' => 'JWT', 'alg' => 'HS256', 'kid' => $keyId])) . '.' .
        bubblehouse_base64url_encode(json_encode(['aud' => 'BH', 'sub' => $subject, 'exp' => time() + $validity_sec]));
    return $raw . '.' . bubblehouse_base64url_encode(hash_hmac('sha256', $raw, base64_decode($keySecretInBase64), true));
}

function bubblehouse_base64url_encode($string) {
    return str_replace(['+','/','='], ['-','_',''], base64_encode($string));
}

Customer token:

echo bubblehouse_token_sign('shopify-yourshop/123456789', '1b356cdffb010001', 'Idkau7WmFTRh1w+pX0Snp3EQA6pJ+h19qdb38ylwIyY', 3600)

Shop token:

echo bubblehouse_token_sign('shopify-yourshop', '1b356cdffb010001', 'Idkau7WmFTRh1w+pX0Snp3EQA6pJ+h19qdb38ylwIyY', 3600*24)

Final word: Tokens cannot be generated in front-end JavaScript

You cannot safely generate tokens in frontend JavaScript code. It needs to happen server-side.

There is no possible way whatsoever to do that without allowing any visitor of your store to make any changes to the entire store and to impersonate any customer or any administrator.

Previous
Versioning