


# Individual Account

## Overview

This guide will help you authenticate with the iglooworks API using OAuth 2.0 Client Credentials flow. You'll learn how to obtain access tokens and make your first API calls.

## Prerequisites

- An iglooworks account
- Basic understanding of REST APIs and OAuth 2.0

## Authentication

### OAuth 2.0 Client Credentials Flow

The iglooworks API uses OAuth 2.0 Client Credentials flow for authentication. This flow is designed for server-to-server communication where your application acts on its own behalf.

**Reference**: [OAuth 2.0 RFC 6749, section 4.4](https://www.rfc-editor.org/rfc/rfc6749#section-4.4)

### Authentication Flow Diagram

The following diagram illustrates the complete authentication process:

```mermaid
sequenceDiagram
    participant App as Your Application
    participant Auth as Auth Server
    participant DB as Your Database
    participant API as iglooworks API

    Note over App, Auth: 1. Authentication
    App->>Auth: POST /oauth2/token<br/>scope='iglooworksapi/algopin-onetime'
    Auth->>App: access_token, expires_in, token_type
    App->>DB: Store token + calculated expiry

    Note over App, API: 2. API Usage
    App->>API: Create One-Time PIN<br/>Authorization: Bearer {token}
    API->>App: pin, pinId, success

    Note over App, API: 3. New Token (24h later)
    App->>Auth: POST /oauth2/token (client_credentials)
    Auth->>App: new access_token
    App->>DB: Update stored token
```

### Step 1: Obtain Your API Credentials

1. Contact BD to obtain your api credentials

### Step 2: Encode Your Credentials

Your credentials must be Base64 encoded before use:

1. Concatenate your Client ID and Client Secret with a colon: `client_id:client_secret`
2. Base64 encode the result: `Base64Encode(client_id:client_secret)`

**Example:**

```javascript
const clientId = "your_client_id_here";
const clientSecret = "your_client_secret_here";
const credentials = btoa(`${clientId}:${clientSecret}`);
// Result: "eW91cl9jbGllbnRfaWRfaGVyZTp5b3VyX2NsaWVudF9zZWNyZXRfaGVyZQ=="
```

```python
import base64

client_id = "your_client_id_here"
client_secret = "your_client_secret_here"
credentials = base64.b64encode(f"{client_id}:{client_secret}".encode()).decode()
# Result: "eW91cl9jbGllbnRfaWRfaGVyZTp5b3VyX2NsaWVudF9zZWNyZXRfaGVyZQ=="
```

```go
package main

import (
    "encoding/base64"
    "fmt"
)

func main() {
    clientId := "your_client_id_here"
    clientSecret := "your_client_secret_here"
    credentials := base64.StdEncoding.EncodeToString([]byte(clientId + ":" + clientSecret))
    // Result: "eW91cl9jbGllbnRfaWRfaGVyZTp5b3VyX2NsaWVudF9zZWNyZXRfaGVyZQ=="
}
```

```bash
# Using command substitution to encode credentials
CLIENT_ID="your_client_id_here"
CLIENT_SECRET="your_client_secret_here"
CREDENTIALS=$(echo -n "${CLIENT_ID}:${CLIENT_SECRET}" | base64)
echo $CREDENTIALS
# Result: "eW91cl9jbGllbnRfaWRfaGVyZTp5b3VyX2NsaWVudF9zZWNyZXRfaGVyZQ=="
```

This encoded string will be used in the Authorization header as `Basic {credentials}`.

### Step 3: Request an Access Token

Make a POST request to the token endpoint with your encoded credentials.

**Endpoint:** `POST https://auth.iglooworks.co/oauth2/token`

#### Required Headers


| Header          | Value                               | Description                            |
| ----------------- | ------------------------------------- | ---------------------------------------- |
| `Authorization` | `Basic {credentials}`               | Your Base64 encoded client credentials |
| `Content-Type`  | `application/x-www-form-urlencoded` | Required for form data                 |

#### Required Parameters


| Parameter    | Value                | Description          |
| -------------- | ---------------------- | ---------------------- |
| `grant_type` | `client_credentials` | OAuth 2.0 grant type |

#### Optional Parameters


| Parameter | Description                                                                   |
| ----------- | ------------------------------------------------------------------------------- |
| `scope`   | Space-separated list of permissions. If omitted, all permissions are granted. |

#### Available Scopes


| Scope                                                | Description                                  |
| ------------------------------------------------------ | ---------------------------------------------- |
| `iglooworksapi/create-custom-pin-permanent-job`      | Create a job for a permanent custom PIN      |
| `iglooworksapi/create-custom-pin-duration-job`       | Create a job for a duration-based custom PIN |
| `iglooworksapi/create-custom-pin-onetime-job`        | Create a job for a one-time custom PIN       |
| `iglooworksapi/unlock-bridge-proxied-job`            | Unlock devices via bridge                    |
| `iglooworksapi/lock-bridge-proxied-job`              | Lock devices via bridge                      |
| `iglooworksapi/create-pin-bridge-proxied-job`        | Create custom PINs via bridge                |
| `iglooworksapi/delete-pin-bridge-proxied-job`        | Delete custom PINs via bridge                |
| `iglooworksapi/delete-pin-job`                       | Delete a PIN access or revoke an eKey                 |
| `iglooworksapi/get-devices`                          | Retrieve device list                         |
| `iglooworksapi/get-job-status`                       | Get the status of a specific job             |
| `iglooworksapi/get-master-pin`                       | Get a device's admin key               |
| `iglooworksapi/get-properties`                       | Retrieve property list                       |
| `iglooworksapi/get-access`                           | Get access records          |
| `iglooworksapi/get-battery-level-bridge-proxied-job` | Get battery levels via bridge                |
| `iglooworksapi/get-device-status-bridge-proxied-job` | Get device status via bridge                 |
| `iglooworksapi/get-activity-logs-bridge-proxied-job` | Get activity logs via bridge                 |
| `iglooworksapi/create-ekey-access`                   | Create eKey access                           |
| `iglooworksapi/store-device-activity`                | Store device activity                        |
| `iglooworksapi/get-device-activity`                  | Get device activity                          |
| `iglooworksapi/get-jobs`                             | Get a list of jobs                           |
| `iglooworksapi/get-job-detail`                       | Get the details of a specific job            |
| `iglooworksapi/update-job-status`                    | Update the status of a job                   |
| `iglooworksapi/algopin-permanent`                    | Create permanent access AlgoPINs             |
| `iglooworksapi/algopin-daily`                        | Create a daily AlgoPIN                       |
| `iglooworksapi/algopin-hourly`                       | Create an hourly AlgoPIN                     |
| `iglooworksapi/algopin-onetime`                      | Create a one-time AlgoPIN                    |
| `iglooworksapi/get-departments`                      | Retrieve department list                     |
| `iglooworksapi/get-account-detail`                   | Get account detail                           |

#### Example Requests

**Request all permissions:**

```bash
curl --request POST \
  --url https://auth.iglooworks.co/oauth2/token \
  --header 'Authorization: Basic {your_encoded_credentials}' \
  --header 'Content-Type: application/x-www-form-urlencoded' \
  --data grant_type=client_credentials
```

```javascript
const clientId = "your_client_id_here";
const clientSecret = "your_client_secret_here";
const encodedCredentials = btoa(`${clientId}:${clientSecret}`);

const params = new URLSearchParams({
  grant_type: 'client_credentials'
});

const response = await fetch('https://auth.iglooworks.co/oauth2/token', {
  method: 'POST',
  headers: {
    'Authorization': `Basic ${encodedCredentials}`,
    'Content-Type': 'application/x-www-form-urlencoded'
  },
  body: params
});
```

```go
package main

import (
    "encoding/base64"
    "net/http"
    "net/url"
    "strings"
)

func main() {
    // Encode credentials
    clientId := "your_client_id_here"
    clientSecret := "your_client_secret_here"
    encodedCredentials := base64.StdEncoding.EncodeToString([]byte(clientId + ":" + clientSecret))

    // Prepare form data
    data := url.Values{}
    data.Set("grant_type", "client_credentials")

    // Create request
    req, _ := http.NewRequest("POST", "https://auth.iglooworks.co/oauth2/token", strings.NewReader(data.Encode()))
    req.Header.Set("Authorization", "Basic "+encodedCredentials)
    req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

    // Make the request
    client := &http.Client{}
    response, _ := client.Do(req)
}
```

```python
import requests
import base64

# Encode credentials
client_id = "your_client_id_here"
client_secret = "your_client_secret_here"
encoded_credentials = base64.b64encode(f"{client_id}:{client_secret}".encode()).decode()

# Make the request
response = requests.post(
    'https://auth.iglooworks.co/oauth2/token',
    headers={
        'Authorization': f'Basic {encoded_credentials}',
        'Content-Type': 'application/x-www-form-urlencoded'
    },
    data={
        'grant_type': 'client_credentials',
    }
)
```

**Request specific permissions:**

```bash
curl --request POST \
  --url https://auth.iglooworks.co/oauth2/token \
  --header 'Authorization: Basic {your_encoded_credentials}' \
  --header 'Content-Type: application/x-www-form-urlencoded' \
  --data grant_type=client_credentials \
  --data 'scope=iglooworksapi/algopin-onetime iglooworksapi/get-devices'
```

```javascript
const clientId = "your_client_id_here";
const clientSecret = "your_client_secret_here";
const encodedCredentials = btoa(`${clientId}:${clientSecret}`);

const params = new URLSearchParams({
  grant_type: 'client_credentials',
  scope: 'iglooworksapi/algopin-onetime iglooworksapi/get-devices'
});

const response = await fetch('https://auth.iglooworks.co/oauth2/token', {
  method: 'POST',
  headers: {
    'Authorization': `Basic ${encodedCredentials}`,
    'Content-Type': 'application/x-www-form-urlencoded'
  },
  body: params
});
```

```go
package main

import (
    "encoding/base64"
    "net/http"
    "net/url"
    "strings"
)

func main() {
    // Encode credentials
    clientId := "your_client_id_here"
    clientSecret := "your_client_secret_here"
    encodedCredentials := base64.StdEncoding.EncodeToString([]byte(clientId + ":" + clientSecret))

    // Prepare form data
    data := url.Values{}
    data.Set("grant_type", "client_credentials")
    data.Set("scope", "iglooworksapi/algopin-onetime iglooworksapi/get-devices")

    // Create request
    req, _ := http.NewRequest("POST", "https://auth.iglooworks.co/oauth2/token", strings.NewReader(data.Encode()))
    req.Header.Set("Authorization", "Basic "+encodedCredentials)
    req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

    // Make the request
    client := &http.Client{}
    response, _ := client.Do(req)
}
```

```python
import requests
import base64

# Encode credentials
client_id = "your_client_id_here"
client_secret = "your_client_secret_here"
encoded_credentials = base64.b64encode(f"{client_id}:{client_secret}".encode()).decode()

# Make the request
response = requests.post(
    'https://auth.iglooworks.co/oauth2/token',
    headers={
        'Authorization': f'Basic {encoded_credentials}',
        'Content-Type': 'application/x-www-form-urlencoded'
    },
    data={
        'grant_type': 'client_credentials',
        'scope': 'iglooworksapi/algopin-onetime iglooworksapi/get-devices'
    }
)
```

### Successful Response

When authentication succeeds, you'll receive a JSON response with your access token:

```json
{
  "access_token": "eyJraWQiOiJKc.....",
  "expires_in": 86400,
  "token_type": "Bearer"
}
```


| Field          | Description                                  |
| ---------------- | ---------------------------------------------- |
| `access_token` | JWT token for API authentication             |
| `expires_in`   | Token lifetime in seconds (86400 = 24 hours) |
| `token_type`   | Always "Bearer"                              |

## Token Management

Access tokens expire after 24 hours. Client credentials issue no refresh token, so when a token expires, reauthenticate by requesting a new access token with the same call.

### Best Practices

- Store tokens securely
- Calculate expiry time: `current_time + expires_in`
- Request a new token shortly before the current one expires

## Implementation

### Using Your Token

Include your access token in API requests:

```bash
curl --request GET \
  --url https://api.igloohome.co/works/devices \
  --header 'Authorization: Bearer {your_access_token}'
```

### Example 1: One-Time PIN Access

For applications that only need to create one-time access pins, limit your scope for better security:

```bash
curl --request POST \
  --url https://auth.iglooworks.co/oauth2/token \
  --header 'Authorization: Basic {credentials}' \
  --header 'Content-Type: application/x-www-form-urlencoded' \
  --data grant_type=client_credentials \
  --data 'scope=iglooworksapi/algopin-onetime'
```

> **Note:** Attempting to create permanent pins with a one-time scope token will result in `403 Forbidden`.

### Example 2: Device Management Application

For applications that need full device control and monitoring:

```bash
curl --request POST \
  --url https://auth.iglooworks.co/oauth2/token \
  --header 'Authorization: Basic {credentials}' \
  --header 'Content-Type: application/x-www-form-urlencoded' \
  --data grant_type=client_credentials \
  --data 'scope=iglooworksapi/get-devices iglooworksapi/lock-bridge-proxied-job iglooworksapi/unlock-bridge-proxied-job iglooworksapi/get-device-status-bridge-proxied-job'
```

### Example 3: Property Management System

For comprehensive property management requiring all PIN types and device control:

```bash
curl --request POST \
  --url https://auth.iglooworks.co/oauth2/token \
  --header 'Authorization: Basic {credentials}' \
  --header 'Content-Type: application/x-www-form-urlencoded' \
  --data grant_type=client_credentials \
  --data 'scope=iglooworksapi/algopin-permanent iglooworksapi/algopin-onetime iglooworksapi/algopin-daily iglooworksapi/algopin-hourly iglooworksapi/get-devices iglooworksapi/lock-bridge-proxied-job iglooworksapi/unlock-bridge-proxied-job'
```

## Quick Start Checklist

### Before You Begin

- Contact BD to obtain your API credentials

### Implementation Steps

- Base64 encode your Client ID and Client Secret
- Request an access token with `grant_type=client_credentials` and the scopes your application needs
- Call the API with the `Authorization: Bearer {access_token}` header
- Reauthenticate when the token expires, 24 hours after issue

### Testing Your Integration

- Request a token and confirm the response includes `access_token` and `expires_in`
- Call `GET https://api.igloohome.co/works/devices` and confirm a 200 response

## Troubleshooting

### Error Responses


When authentication fails, you'll receive an error response:

```json
{
  "error": "error_type"
}
```

### Common Errors


| Error Code        | Cause                                          | Solution                                    |
| ------------------- | ------------------------------------------------ | --------------------------------------------- |
| `invalid_request` | Missing required parameter (e.g.,`grant_type`) | Include all required parameters             |
| `invalid_client`  | Invalid Client ID or Secret                    | Verify credentials with the iglooworks team |
| `invalid_scope`   | Requested scope doesn't exist                  | Check available scopes list                 |

### Status Codes

**401 Unauthorized:**

- Verify Base64 encoding is correct
- Check Client ID and Secret are valid

**400 Bad Request:**

- Verify `grant_type=client_credentials` is included
- Check Content-Type header is set correctly
- Validate scope parameter format

**402 Payment Required (on API calls):**

- The account's iglooworks API trial has ended, or its billing grace period has expired. Check the account's billing status.
