The API uses API keys for authentication. API keys provide secure, programmatic access to R4 platform features without requiring user credentials.
An API key consists of two parts:
{accessKey}.{secret}
rk_abc123def456)ghijklmnopqrstuvwxyz1234567890abcdef)The full API key looks like:
rk_abc123def456.ghijklmnopqrstuvwxyz1234567890abcdef
Note: The API key will be scoped to the currently selected tenant. Make sure you're in the correct tenant before creating the key.
The preferred method is to pass your API key in the X-API-Key header:
curl -X GET "https://r4.dev/api/v1/machine/domain-manager/dns-records?domain=example.com" \
-H "X-API-Key: rk_abc123def456.ghijklmnopqrstuvwxyz1234567890abcdef"You can also use the Authorization header with the ApiKey scheme:
curl -X GET "https://r4.dev/api/v1/machine/domain-manager/dns-records?domain=example.com" \
-H "Authorization: ApiKey rk_abc123def456.ghijklmnopqrstuvwxyz1234567890abcdef"API keys have the following characteristics:
| Property | Description |
|---|---|
| Tenant Scope | Keys are scoped to a specific tenant within your organization |
| Resource Access | Keys can only access resources within their assigned tenant |
| User Permissions | Keys inherit permissions from the user who created them |
| Audit Trail | All actions are logged with the API key ID for auditing |
When you create an API key, it is associated with:
This ensures fine-grained access control. For example, if you have multiple tenants (e.g., "Production" and "Development"), you can create separate API keys for each, limiting what automated systems can access.
Add your API key to .gitignore and use environment variables:
# .gitignore
.env
.env.local# .env
R4_API_KEY=rk_abc123def456.ghijklmnopqrstuvwxyz1234567890abcdefStore API keys in environment variables, not in code:
import os
API_KEY = os.environ.get("R4_API_KEY")const API_KEY = process.env.R4_API_KEYCreate separate API keys for:
This allows you to rotate or revoke keys independently.
Regularly review API key usage in the R4 dashboard:
If an API key is compromised or no longer needed:
Archived keys are immediately invalidated and cannot be used for authentication.
import os
import requests
class R4Client:
def __init__(self, api_key: str = None):
self.api_key = api_key or os.environ.get("R4_API_KEY")
self.base_url = "https://r4.dev/api/v1/machine"
def _headers(self):
return {"X-API-Key": self.api_key}
def get_dns_records(self, domain: str):
response = requests.get(
f"{self.base_url}/domain-manager/dns-records",
params={"domain": domain},
headers=self._headers()
)
response.raise_for_status()
return response.json()
# Usage
client = R4Client()
records = client.get_dns_records("example.com")class R4Client {
private apiKey: string
private baseUrl = 'https://r4.dev/api/v1/machine'
constructor(apiKey?: string) {
this.apiKey = apiKey || process.env.R4_API_KEY!
}
private headers() {
return { 'X-API-Key': this.apiKey }
}
async getDnsRecords(domain: string) {
const response = await fetch(
`${this.baseUrl}/domain-manager/dns-records?domain=${encodeURIComponent(domain)}`,
{ headers: this.headers() },
)
if (!response.ok) {
throw new Error(`API error: ${response.status}`)
}
return response.json()
}
}
// Usage
const client = new R4Client()
const records = await client.getDnsRecords('example.com')#!/bin/bash
# Set your API key (use environment variable in production)
export R4_API_KEY="rk_abc123def456.ghijklmnopqrstuvwxyz1234567890abcdef"
# Get DNS records
curl -X GET "https://r4.dev/api/v1/machine/domain-manager/dns-records?domain=example.com" \
-H "X-API-Key: $R4_API_KEY" \
-H "Content-Type: application/json"If you receive a 401 error:
{
"error": {
"code": "unauthorized",
"message": "Invalid or missing API key"
}
}Check the following:
X-API-Key (not X-Api-Key or x-api-key){accessKey}.{secret} with a period separatorIf you receive a 403 error, the API key is valid but doesn't have access to the requested resource. This typically means the resource belongs to a different organization.
If you're having trouble with API authentication: