Skip to main content
The RABOT Partner API uses OAuth 2.0 for authentication (see RFC 7649). Using the OAuth client credentials flow, you can obtain an access token from the RABOT authentication server.

Automating OAuth 2.0 Token Management

This guide shows you how to implement automated token management in your RABOT Partner API integration, ensuring your scripts maintain uninterrupted access without manual intervention.

Token Lifecycle

Key Points:
  • Tokens expire after ~1 hour (3599 seconds)
  • No refresh tokens - re-authenticate with client credentials when expired
  • Proactive token renewal recommended (don’t wait for 401 errors)

Token Request

Use your client credentials to obtain an access token:
replace CLIENT_ID and CLIENT_SECRET with the credentials you received from Rabot Charge. See Partner setup
Example API request
curl -L "auth.rabot-charge.de/connect/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "client_id={{CLIENT_ID}}" \
-d "client_secret={{CLIENT_SECRET}}" \
-d "grant_type=client_credentials" \
-d "scope=api:partner"

Scopes

You need to specify, which scopes you want to include in the token by specifying them in scope parameter.
Multiple Scopes: Separate multiple scopes with spaces, e.g., api:partner create:orders
The following scopes are available for Whitelabel Partners:
ScopeDescription
api:partnerpermission to access Partner API, required for all API requests
create:orderspermission to create orders
role:finance-reportingpermission to access customer and contract data, limited to finance reporting related information
role:customer-supportpermission to access customer and contract data, limited to customer support related information (includes role: finance-reporting)
role:applicationpermission to access all customer and contract data (includes role: finance-reporting and role:customer-support )
The following scopes are available for HEMS / 3rd Party Partners:
ScopeDescription
api:partnerpermission to access Partner API, required for all API requests
In order to access further customer or contract specific information e.g. Working Price via the metrics endpoint, you will need to integrate the 3rd Party Authorization flow.Once the RABOT customer has authorized the data exchange between our platforms, you will be able to access all endpoint under the /customers path.
The following scopes are available for Sales Affilliate Partners:
ScopeDescription
api:partnerpermission to access Partner API, required for all API requests
create:orderspermission to create orders
role:finance-reportingpermission to access customer and contract data, limited to finance reporting related information
To use scopes, you need to have them assigned to your API client by RABOT administrators. If you feel you should have a scope, that you don’t have, please contact our Integration Management team.

Token Response

If successful, the authentication server responds with a HTTP/200 status code, and the response body contains a structure with the access token
{
  "access_token": "eyJhbGciOiJS....QnkY36d_ac",
  "token_type": "Bearer",
  "expires_in": 3599
}
In all requests to the partner API, include the access token as Bearer token in the HTTP authorization header:
Example API request
curl -L "https://api.rabot-charge.de/partner/v1/tariffs" \
-H "Authorization: Bearer eyJhbGciOiJS....QnkY36d_ac"
Note that the token only has a limited life time; when the life time has expired, you will need to request a new token from the authentication server.

Best Practices

1. Proactive Token Renewal

Don’t wait for tokens to expire - renew them proactively:
# Good: Check before each request
def ensure_valid_token(self):
    if datetime.now() >= self.token_expires_at:
        self.authenticate()

# Better: Renew 5 minutes before expiry
def ensure_valid_token(self):
    buffer = timedelta(minutes=5)
    if datetime.now() >= (self.token_expires_at - buffer):
        self.authenticate()

2. Secure Credential Storage

Never hardcode credentials in your source code or commit them to version control.
Recommended approaches:
# Environment variables (development/production)
import os
client = RabotAPIClient(
    client_id=os.environ['RABOT_CLIENT_ID'],
    client_secret=os.environ['RABOT_CLIENT_SECRET']
)

# Configuration file (with restricted permissions)
import json
with open('/secure/path/config.json') as f:
    config = json.load(f)
    client = RabotAPIClient(
        client_id=config['client_id'],
        client_secret=config['client_secret']
    )

# Secret management service (production)
# AWS Secrets Manager, Azure Key Vault, etc.

3. Error Handling

Always handle authentication errors gracefully:
def authenticate(self):
    try:
        response = requests.post(self.auth_url, data=data)
        response.raise_for_status()
        # ... process token
    except requests.exceptions.HTTPError as e:
        if e.response.status_code == 401:
            raise Exception("Invalid client credentials")
        elif e.response.status_code == 403:
            raise Exception("Insufficient scopes or permissions")
        else:
            raise Exception(f"Authentication failed: {e}")
    except requests.exceptions.RequestException as e:
        raise Exception(f"Network error during authentication: {e}")

4. Logging (Without Exposing Secrets)

Log authentication events, but never log tokens or credentials:
import logging

def authenticate(self):
    logging.info("Requesting new access token...")
    # ... get token
    logging.info(f"Token obtained, expires at {self.token_expires_at}")
    # DON'T LOG: logging.debug(f"Token: {self.access_token}")  ❌

5. Thread Safety (For Multi-threaded Applications)

If your application uses multiple threads, protect token operations:
import threading

class ThreadSafeRabotClient(RabotAPIClient):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._token_lock = threading.Lock()
    
    def _ensure_valid_token(self):
        with self._token_lock:
            if not self._is_token_valid():
                self._authenticate()

Common Issues & Solutions

Issue 1: “Invalid client credentials”

Cause: Incorrect client_id or client_secret Solution:
  • Verify credentials in your Partner setup
  • Check for typos or extra whitespace
  • Ensure you’re using the correct environment (staging vs. production)

Issue 2: “Insufficient scopes”

Cause: Requesting access to endpoints without the required scopes Solution:
  • Review available scopes for your partner type (Whitelabel, HEMS, Sales Affiliate)
  • Contact Integration Management to request additional scopes
  • Update your scope list in the authentication request

Issue 3: Frequent 401 errors

Cause: Token expiring between validation check and API request Solution:
# Add larger buffer time (e.g., 5 minutes instead of 1)
expires_in = token_data['expires_in'] - 300  # 5 min buffer

# Or validate token immediately before each request
def request(self, ...):
    self._ensure_valid_token()  # Check right before request
    # ... make API call

Issue 4: High authentication rate

Cause: Re-authenticating too frequently Solution:
  • Increase buffer time to avoid premature re-authentication
  • Cache tokens in memory (don’t re-authenticate for every request)
  • Check your expiry calculation logic
# Bad: Re-authenticates every request
def request(self):
    self.authenticate()  # ❌ Don't do this!
    # ... make request

# Good: Only re-authenticate when needed
def request(self):
    self.ensure_valid_token()  # ✓ Only if expired
    # ... make request

Testing Your Implementation

Manual Test

# Test authentication
curl -X POST "https://auth.rabot-charge.de/connect/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "client_secret=YOUR_CLIENT_SECRET" \
  -d "grant_type=client_credentials" \
  -d "scope=api:partner"

# Use the token
curl -X GET "https://api.rabot-charge.de/partner/v1/tariffs" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Testing Checklist

  • Initial authentication works
  • Token is used in API requests (Bearer header)
  • Token expiry is calculated correctly
  • Token is renewed before expiry (proactive)
  • 401 errors trigger re-authentication
  • Credentials are not hardcoded
  • Credentials are not logged
  • Error handling is robust
  • Multi-threaded access is safe (if applicable)