Skip to content

Authentication

This guide explains how to authenticate with the PinkCloudSync API.

Overview

PinkCloudSync uses a two-step authentication process1:

  1. Obtain an access token using your API key and secret
  2. Use the token to authenticate all subsequent API requests
sequenceDiagram
    participant Client
    participant API

    Client->>API: POST /auth/token<br/>(api_key, api_secret)
    API->>Client: access_token (JWT)

    Client->>API: GET /sync/sessions<br/>(Authorization: Bearer token)
    API->>Client: Response data

Prerequisites

Before you begin, make sure you have:

  • An active PinkCloudSync account
  • API key and secret (obtain from the console)
  • Basic knowledge of REST APIs
  • An installed tool for working with APIs (curl, Postman, or Python)

Step 1: Obtain Access Token

To get an access token, send a POST request to the /auth/token endpoint with your API credentials.

Request

1
2
3
4
5
6
curl -X POST https://api.pinkcloudsync.example/v1/auth/token \
  -H "Content-Type: application/json" \
  -d '{
    "api_key": "pk_live_abc123",
    "api_secret": "sk_live_xyz789"
  }'
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
import requests

url = "https://api.pinkcloudsync.example/v1/auth/token"

payload = {
    "api_key": "pk_live_abc123",
    "api_secret": "sk_live_xyz789"
}

response = requests.post(url, json=payload)

if response.status_code == 200:
    token_data = response.json()
    access_token = token_data["access_token"]
    print(f"Token obtained: {access_token[:20]}...")
else:
    print(f"Error: {response.status_code}")
    print(response.json())

Response

1
2
3
4
5
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyXzEyMyIsImV4cCI6MTY0MDk5NTIwMH0.signature",
  "token_type": "Bearer",
  "expires_in": 3600
}

Response Fields

Field Type Description
access_token string JWT token for authentication
token_type string Always "Bearer"
expires_in integer Token lifetime in seconds (3600 = 1 hour)

Token Expiration

Access tokens expire after 1 hour. You'll need to request a new token when the current one expires.

Step 2: Use the Token

Include the access token in the Authorization header of all API requests.

Header Format

1
Authorization: Bearer YOUR_ACCESS_TOKEN

Example Request

1
2
curl -X GET https://api.pinkcloudsync.example/v1/sync/sessions \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import requests

url = "https://api.pinkcloudsync.example/v1/sync/sessions"

headers = {
    "Authorization": f"Bearer {access_token}"
}

response = requests.get(url, headers=headers)
sessions = response.json()

print(f"Found {len(sessions['sessions'])} sessions")

Token Management

Storing Tokens

Store access tokens securely:

  • Never commit tokens to version control
  • Use environment variables or secure vaults
  • Encrypt tokens at rest if storing in a database
1
2
3
4
5
6
7
8
import os
from dotenv import load_dotenv

# Load from .env file
load_dotenv()

api_key = os.getenv("PINKCLOUDSYNC_API_KEY")
api_secret = os.getenv("PINKCLOUDSYNC_API_SECRET")
1
2
PINKCLOUDSYNC_API_KEY=pk_live_abc123
PINKCLOUDSYNC_API_SECRET=sk_live_xyz789

Token Refresh

Implement automatic token refresh to handle expiration:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import requests
from datetime import datetime, timedelta

class PinkCloudSyncClient:
    def __init__(self, api_key, api_secret):
        self.api_key = api_key
        self.api_secret = api_secret
        self.access_token = None
        self.token_expires_at = None
        self.base_url = "https://api.pinkcloudsync.example/v1"

    def get_token(self):
        """Obtain a new access token"""
        url = f"{self.base_url}/auth/token"
        payload = {
            "api_key": self.api_key,
            "api_secret": self.api_secret"
        }

        response = requests.post(url, json=payload)
        response.raise_for_status()

        data = response.json()
        self.access_token = data["access_token"]
        # Set expiration 5 minutes before actual expiry
        self.token_expires_at = datetime.now() + timedelta(
            seconds=data["expires_in"] - 300
        )

        return self.access_token

    def ensure_token(self):
        """Ensure we have a valid token"""
        if not self.access_token or datetime.now() >= self.token_expires_at:
            self.get_token()

    def make_request(self, method, endpoint, **kwargs):
        """Make an authenticated API request"""
        self.ensure_token()

        url = f"{self.base_url}{endpoint}"
        headers = kwargs.pop("headers", {})
        headers["Authorization"] = f"Bearer {self.access_token}"

        response = requests.request(method, url, headers=headers, **kwargs)
        return response

# Usage
client = PinkCloudSyncClient(
    api_key="pk_live_abc123",
    api_secret="sk_live_xyz789"
)

# Automatically handles token refresh
response = client.make_request("GET", "/sync/sessions")
sessions = response.json()

Error Handling

Common Authentication Errors

401 Unauthorized

Cause: Invalid API credentials or expired token

Solution: * Verify your API key and secret * Request a new token if expired * Check for typos in credentials

1
2
3
4
{
  "error": "invalid_credentials",
  "message": "Invalid API key or secret"
}

403 Forbidden

Cause: Valid credentials but insufficient permissions

Solution: * Check your API key permissions in the console * Ensure the key has the required scopes

1
2
3
4
{
  "error": "insufficient_permissions",
  "message": "API key does not have 'sync:write' permission"
}

Handling Errors in Code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import requests
from requests.exceptions import HTTPError

def get_access_token(api_key, api_secret):
    url = "https://api.pinkcloudsync.example/v1/auth/token"
    payload = {
        "api_key": api_key,
        "api_secret": api_secret
    }

    try:
        response = requests.post(url, json=payload)
        response.raise_for_status()
        return response.json()["access_token"]

    except HTTPError as e:
        if e.response.status_code == 401:
            print("Invalid credentials. Please check your API key and secret.")
        elif e.response.status_code == 429:
            print("Rate limit exceeded. Please wait before retrying.")
        else:
            print(f"HTTP error occurred: {e}")
        raise

    except Exception as e:
        print(f"An error occurred: {e}")
        raise

Security Best Practices

API Key Management

  1. Rotate keys regularly — create new keys every 90 days
  2. Use separate keys — different keys for development and production
  3. Limit permissions — grant only necessary permissions to each key
  4. Monitor usage — review API key usage logs regularly

Token Security

  1. Never log tokens — avoid logging access tokens in application logs
  2. Use HTTPS only — always use HTTPS for API requests
  3. Implement timeouts — set reasonable timeouts for API requests
  4. Handle errors gracefully — don't expose tokens in error messages

Security Warning

Never share your API secret or access tokens. Treat them like passwords.

API Key Permissions

Each API key can have the following permissions:

Permission Description
sync:read Read sync session information
sync:write Create and manage sync sessions
conflicts:read View conflicts
conflicts:write Resolve conflicts
admin Full access to all resources

Checking Permissions

You can check your current permissions by decoding the JWT token:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import jwt
import json

def decode_token(token):
    # Note: This doesn't verify the signature
    # Only use for inspecting your own tokens
    payload = jwt.decode(token, options={"verify_signature": False})
    print(json.dumps(payload, indent=2))
    return payload

# Example output
# {
#   "sub": "user_123",
#   "permissions": ["sync:read", "sync:write"],
#   "exp": 1640995200
# }

Next Steps


  1. The access token is a JWT (JSON Web Token) that contains encoded information about the user and their permissions.