---
updatedAt: 2026-09-28T17:56:35.000Z
agentTools:
  projectIndex: https://docs.trybadge.com/llms.txt
---

# Getting Started For Platforms

Based on organizational requirements, you may want to create separate Workspaces for each of your customers. In the Badge Platform, Workspaces provide data isolation. If you want to keep your customers' data separate we recommend using a new workspace for each of your customers. If you would prefer using a single workspace you can continue with the normal [SDK setup](https://docs.trybadge.com/docs/sdk).

<Callout icon="⚠️" theme="warn">
  ### Organization API Required

  In order to follow this guide you will need access to the Organization API.

  Please contact sales to request access.
</Callout>

# Creating Workspaces

A workspace on the Badge platform acts as a data container, keeping data isolated. Steps in this guide should be repeated for each of your customers.

## Create a Workspace

When you are granted organization access, you will receive an API token that can be used to create workspaces. This token is needed to access the [create workspace API](https://docs.trybadge.com/reference/workspacecreate).

Use the [Badge API](https://docs.trybadge.com/reference/workspacecreate) to make a workspace for each of your customers:

```http HTTP
POST https://api.trybadge.com/v0/workspaces HTTP/1.1
Accept: application/json
Authorization: Bearer ORGANIZATION_TOKEN
Content-Type: application/json

{
  "companyInfo": {
    "address": [
      "123 Faker St",
      "Arkadelphia, Arkansas 71923"
    ],
    "name": "ACME Group, Inc.",
    "supportEmail": "acme-support@example.com"
  },
  "name": "ACME",
  "timezone": "America/New_York"
}
```

```json Response
{
  "apiKey": "34238uQcwhUT"
}
```

Save the value returned in `apiKey` for future api calls

## Create a Google Wallet Issuer

In order to issue passes in Google Wallet, Google requires that you have an issuer linked to a Google Pay Merchant Account account. While it is possible to reuse the same Google Wallet Issuer for each workspace, Badge recommends creating a new issuer for each workspace.

<Callout icon="ℹ️" theme="info">
  ### Google Pay Merchant Account

  <Anchor target="_blank" href="https://pay.google.com/business/console/">Create a Google Pay Merchant Account</Anchor> if you do not already one.
</Callout>

<Callout icon="ℹ️" theme="info">
  ### Programatic Google Issuer Creation

  You need to request access to be able to programatically create issuers, for up to date instructions follow <Anchor target="_blank" href="https://developers.google.com/wallet/retail/gift-cards/resources/create-issuer-accounts-programmatically">Google's Documentation</Anchor>​.
</Callout>

### Credentials

Google Wallet is authenticated using Google OAuth and Service Accounts. You will need to create a Google Service Account to access the create issuer API. Once the service account is invited to one of your Google Wallet Merchant Accounts, it will be able to create issuers.

### Service Account Email

Use the [Badge API](https://docs.trybadge.com/reference/TODO) to get the service account email for your workspace:

```sh
curl --request GET \
     --url https://api.trybadge.com/v0/workspace/googleWalletServiceAccount \
     --header 'accept: application/json' \
     --header 'authorization: Bearer your-workspace-api-key'
```

### Create Issuer

```shell sh
curl -X POST \
  "https://walletobjects.googleapis.com/walletobjects/v1/issuer" \
  -H "Authorization: Bearer $(gcloud auth print-access-token)" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "YOUR_ISSUER_NAME",
    "contactInfo": {
      "email": "YOUR_ISSUER_EMAIL"
    }
  }'
```

Record the returned `issuerId`.

### Invite Service Account

```shell sh
curl -X PUT \
 "https://walletobjects.googleapis.com/walletobjects/v1/permissions/YOUR_ISSUER_ID" \
  -H "Authorization: Bearer $(gcloud auth print-access-token)" \
  -H "Content-Type: application/json" \
  -d '{
    "issuerId": "YOUR_ISSUER_ID",
    "permissions": [
      {
        "emailAddress": "me@example.com",
        "role": "OWNER"
      },
      {
        "emailAddress": "BADGE_SERVICE_ACCOUNT_EMAIL",
        "role": "OWNER"
      }
    ]
  }'
```

We recommend inviting Badge as an `OWNER` so that the Badge platform can automatically request quota increases from Google.

### Add your Google Wallet Issuer to your Badge Workspace

Use the [Badge API](https://docs.trybadge.com/reference/TODO) to add this issuer to your Badge workspace:

```sh
curl --request POST \
    --url https://api.trybadge.com/v0/googleIssuers \
    --header 'accept: application/json' \
    --header 'authorization: Bearer your-workspace-api-key' \
    --header 'content-type: application/JSON' \
    --data   '{"identifier": "ISSUER_ID"}'
```

## Create an Apple Pass Type Identifier

In order to issue passes in Apple Wallet, Apple requires that you have an Apple Developer Program account. The Apple Developer Program is a paid subscription that enables distribution of apps and passes.

<Callout icon="ℹ️" theme="info">
  ### Apple Developer Program

  [Enroll in the Apple Developer Program](https://developer.apple.com/programs/enroll/) if you do not already have an account.
</Callout>

Once enrolled, follow the steps below so that you may begin issuing passes on the Badge platform.

In order to give your customers a seamless experience you can automate creation of Pass Type Identifiers through the Apple Appstore Connect API. Unfortunately, Apple does not allow use of this API by third parties but we have created some straight-forward API endpoints to help you integrate the two systems.

<Callout icon="❔" theme="default">
  ### Would a library you can install to manage this be useful to you?

  Reach out to us in the chat and let us know what language and frameworks you are using!
</Callout>

### API Credentials

In order to use the Appstore Connect API you need to [get an API key from Apple](https://developer.apple.com/documentation/appstoreconnectapi/creating-api-keys-for-app-store-connect-api) :

* In the Apple Developer Portal, navigate to [**Users & Accounts** > **Integrations**](https://appstoreconnect.apple.com/access/integrations/api)

* If you do not already have access click **Request Access**

  <Image src="https://files.readme.io/67886bcc1d1e5329684f0e5c51f4bd60e07f89a9efc65160f79c0d67bfb10aac-Screenshot_2024-10-24_at_4.59.05_PM.png" align="center" />

* Once you have been granted access click **Generate API Key**

  <Image src="https://files.readme.io/fab1f6d5659bfb73e7717af311131ecead0c41dc1565c884891b731056cd6b7c-Screenshot_2024-10-28_at_15.43.08.png" align="center" />

* Enter a **Name** and select **Admin** under **Access**, then click **Generate**

  <Image src="https://files.readme.io/32c090190d2e941ab5213206098fb745d34749f05570d0e2c57a036fc785f7c7-Screenshot_2024-10-28_at_15.43.28.png" align="left" width="400px" wrap={true} />

* Make note of your key's identifiers and download the API Key

  <Image src="https://files.readme.io/cfee9211864f104424023e16aa19dc5ef71d6f6a58f7983752f823b1877bb965-Screenshot_2024-10-28_at_15.43.43.png" align="center" />

### Signing a Request for the Apple Appstore Connect API

To make requests to the App Store Connect API you must [generate tokens](https://developer.apple.com/documentation/appstoreconnectapi/generating-tokens-for-api-requests). Below is an example of how to generate a token using the API Key created in the previous step:

```typescript
import * as jwt from "jsonwebtoken";

export function generateAppStoreConnectToken(
  issuerId: string,
  apiKeyId: string,
  privateKey: string,
): string {
  const tokenExpiryMs = Date.now() + TOKEN_VALIDITY_MS;

  const payload = {
    iss: issuerId,
    exp: Math.round(tokenExpiryMs / 1000),
    aud: "appstoreconnect-v1",
  };

  return jwt.sign(payload, privateKey, {
    algorithm: "ES256",
    header: {
      alg: "ES256",
      kid: apiKeyId,
      typ: "JWT",
    },
  });
}

const TOKEN_VALIDITY_MS = 5 * 60 * 1000; // 5 minutes
```

```typescript
import {readFileSync} from "node:fs";

const token = generateAppStoreConnectToken(
  "3a2cca66-5e32-47a5-8580-defd5405d2f1",
  "5TB6WHLRAK",
  readFileSync("/path/to/key/AuthKey_5TB6WHLRAK.p8", "utf8"),
);
```

### Create an Apple Pass Type Identifier

If there is already an identifier created that you want to use you can skip this step.

Use the [App Store Connect API](https://developer.apple.com/documentation/appstoreconnectapi) to create a Pass Type Identifier:

```http
POST https://api.appstoreconnect.apple.com/v1/passTypeIds HTTP/1.1
Accept: application/json
Authorization: Bearer YOUR_APPLE_TOKEN
Content-Type: application/json

{
  "data": {
    "type": "passTypeIds",
    "attributes": {
      "name": "My Loyalty Pass",
      "identifier": "pass.com.example.loyalty"
    }
  }
}
```

```json Response
HTTP/1.1 200 OK
Content-Type: application/json

{
  "data": {
    "id": "N9UBABTV8T"
  }
}
```

Store `data.id` for the next step.

### Get a Certificate Signing Request from Badge

Issuing a pass requires a signing certificate. Before you can generate a signing certificate, you need a certificate signing request (CSR).

Use the [Badge API](https://docs.trybadge.com/reference/applecertificatesigningrequestcreate) to create a CSR file:

```http
POST https://api.trybadge.com/v0/workspace/appleCertificateSigningRequests HTTP/1.1
Accept: application/x-pem-file
Authorization: Bearer WORKSPACE_API_KEY
```

```http Response
HTTP/1.1 200 OK
Content-Type: application/x-pem-file

RAW CERTIFICATE DATA
```

Use the response body of this request in the next step.

### Upload the Certificate Signing Request to Apple

Use the [App Store Connect API](https://developer.apple.com/documentation/appstoreconnectapi) to create a certificate:

```http
POST https://api.appstoreconnect.apple.com/v1/certificates HTTP/1.1
Accept: application/json
Authorization: Bearer YOUR_APPLE_TOKEN
Content-Type: application/json

{  
  "data": {  
    "type": "certificates",  
    "attributes": {  
      "csrContent": "RAW CERTIFICATE DATA FROM PREVIOUS STEP",  
      "certificateType": "PASS_TYPE_ID"  
    },  
    "relationships": {  
      "passTypeId": {  
        "data": {  
          "type": "passTypeIds",  
          "id": "N9UBABTV8T FROM CREATE PASS TYPE IDENTIFIER"
        }  
      }  
    }  
  }  
}
```

If you have an identifier with NFC entitlement and you want to create NFC passes, use `PASS_TYPE_ID_WITH_NFC` in `certificateType`.

```json Response
HTTP/1.1 200 OK
Content-Type: application/json

{
  "data": {
    "id": "SHCF2PMQCT",
    "attributes": {
      "certificateContent": "BASE64 ENCODED CERTIFICATE",
    }
  }
}
```

Use the data in `data.attributes.certificateContent` in the next step.

### Upload Signed Certificate to Badge

Now that you have a certificate, the final step is to upload it to your Badge workspace.

Use the [Badge API](https://docs.trybadge.com/reference/applecertificateupload) to upload the certificate to your Badge workspace:

```http
POST  https://api.trybadge.com/v0/workspace/appleCertificates HTTP/1.1
Accept: application/json
Authorization: Bearer WORKSPACE_API_KEY
Content-Type: application/pkix-cert

BASE64 DATA FROM PREVIOUS STEP
```

```json Response
HTTP/1.1 200 OK
Content-Type: application/json

{
  "passTypeIdentifier": "pass.com.example.loyalty"
}
```

You've completed the Apple Certificate Upload process.

## Create a Template

To get started, use the [Badge API](https://docs.trybadge.com/reference/passtemplatecreate)  to create a new template for your customer:

```http
POST https://api.trybadge.com/v0/passTemplates HTTP/1.1
Accept: application/json
Content-Type: application/json

{
  "passType": "LOYALTY",
  "revision": {
    "description": "User facing name",
    "logoUri": "https://example.com/logo.png",
    "backgroundColorHex": "#000000",
    "textColorHex": "#FFFFFF"
  },
  "publish": true,
  "name": "Test",
  "applePassTypeIdentifier": "pass.com.example.pass"
}
```

```json Response
HTTP/1.1 200 OK
Content-Type: application/json

{
  "template": {
    "id": "2e0f7fa5-80db-492d-a5fe-d22eab5a6ef2"
  }
}
```

Store the returned `template.id` as you will need it later when creating passes.

## Creating Passes

If you are not ready to create passes you can skip this step.

Use the [Badge API](https://docs.trybadge.com/reference/userpassupsert)  to create or update a pass:

```http
POST api.trybadge.com/v0/rpc/userPassUpsert HTTP/1.1
Accept: application/json
Authorization: Bearer API_KEY
Content-Type: application/json

{
  "passTemplateId": "2e0f7fa5-80db-492d-a5fe-d22eab5a6ef2",
  "user":{
    "id": "66565"
  },
  "pass":{
    "id": "88787"
  }
}
```

`pass.id` can be omitted if you are only creating one pass per user.

```json Response
HTTP/1.1 200 OK
Content-Type: application/json

{
  "pass": {
    "downloadUrl": "https://example.com/download?id=123&token=123"
  }
}
```

The returned `pass.downloadUrl` can be used to distribute passes.

## Update the Template

If you need to make any additional changes to the template you can use the [Badge API to create a template revision](https://docs.trybadge.com/reference/passtemplaterevisioncreate) .

# SDK Setup

Continue with the normal [SDK setup](https://docs.trybadge.com/docs/sdk).