API Authentication
Detailed guide to authenticating with the SearchAF API using OAuth tokens and API keys.
Authentication Methods
SearchAF supports two authentication methods:
- OAuth 2.0 with JWT tokens - For user-authenticated requests
- API Keys - For programmatic, project-specific access
OAuth 2.0 Authentication
Supported Providers
SearchAF integrates with popular OAuth providers:
- Google - Gmail and Google Workspace accounts
- GitHub - Developer accounts
- Shopify - Store owner accounts
OAuth Flow
Step 1: Initiate Login
Redirect users to the OAuth login endpoint:
GET /auth/oauth/{provider}/login?redirect_uri={your_callback_url}
Parameters:
provider- One of:google,github,shopifyredirect_uri- Your application callback URL
Example:
const provider = 'google';
const redirectUri = encodeURIComponent('https://myapp.com/auth/callback');
const loginUrl = `https://searchaf-api.antfly.io/auth/oauth/${provider}/login?redirect_uri=${redirectUri}`;
// Redirect user to loginUrl
window.location.href = loginUrl;
Step 2: User Authorizes
The user authenticates with the OAuth provider and grants permissions.
Step 3: Handle Callback
SearchAF redirects back to your application with an authorization code:
GET https://myapp.com/auth/callback?code={auth_code}&state={state}
Step 4: Exchange Code for Tokens
The callback endpoint automatically exchanges the code for JWT tokens and redirects with the tokens.
Token Response:
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"user": {
"id": "usr_abc123",
"email": "user@example.com",
"display_name": "John Doe"
}
}
Using JWT Tokens
Include the access token in the Authorization header:
curl https://searchaf-api.antfly.io/api/v1/users/me \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
Token Expiration
Access tokens expire after 1 hour (3600 seconds). Use the refresh token to obtain a new access token.
Refreshing Tokens
When your access token expires:
POST /auth/refresh
Content-Type: application/json
{
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
Response:
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600
}
Token Storage
Best Practices:
- Store tokens securely (encrypted storage, secure cookies)
- Never expose tokens in URLs or logs
- Implement token rotation on refresh
- Clear tokens on logout
API Key Authentication
API keys provide project-specific authentication for programmatic access.
Key Types
- Read-Only - Query and search operations only
- Read-Write - Full CRUD operations
Creating an API Key
- Navigate to your project settings
- Click "Create API Key"
- Configure the key:
POST /api/v1/projects/{project_id}/api-keys
Content-Type: application/json
Authorization: Bearer {jwt_token}
{
"name": "Production Key",
"type": "read_write",
"expires_at": "2025-12-31T23:59:59Z"
}
Response:
{
"id": "key_abc123",
"key": "sk_live_abc123def456...",
"name": "Production Key",
"type": "read_write",
"created_at": "2025-01-15T10:30:00Z",
"expires_at": "2025-12-31T23:59:59Z"
}
Important: The key value is only shown once. Store it securely.
Using API Keys
Include the API key in the X-API-Key header:
curl https://searchaf-api.antfly.io/api/v1/projects/{project_id}/search \
-H "X-API-Key: sk_live_abc123def456..." \
-H "Content-Type: application/json" \
-d '{"query": "blue shoes"}'
Key Management
List Keys
GET /api/v1/projects/{project_id}/api-keys
Authorization: Bearer {jwt_token}
Revoke Key
DELETE /api/v1/projects/{project_id}/api-keys/{key_id}
Authorization: Bearer {jwt_token}
Key Security
Best Practices:
- Use read-only keys when write access isn't needed
- Set expiration dates on all keys
- Rotate keys regularly
- Never commit keys to version control
- Use environment variables for key storage
- Implement key rotation before expiration
Security Considerations
HTTPS Only
All API requests must use HTTPS. HTTP requests will be rejected.
Rate Limiting
Both authentication methods are subject to rate limiting:
- OAuth: 10 requests per minute per IP
- API Keys: Based on subscription tier
IP Whitelisting
Enterprise plans can restrict API key usage to specific IP addresses.
Scope and Permissions
- OAuth tokens inherit user permissions
- API keys are scoped to specific projects
- Both respect RBAC rules
Error Responses
Invalid Token
{
"type": "https://searchaf-api.antfly.io/errors/unauthorized",
"title": "Unauthorized",
"status": 401,
"detail": "Invalid or expired access token"
}
Invalid API Key
{
"type": "https://searchaf-api.antfly.io/errors/unauthorized",
"title": "Unauthorized",
"status": 401,
"detail": "Invalid API key"
}
Insufficient Permissions
{
"type": "https://searchaf-api.antfly.io/errors/forbidden",
"title": "Forbidden",
"status": 403,
"detail": "Insufficient permissions for this operation"
}
Example Implementations
JavaScript/TypeScript
class SearchAFClient {
private apiKey: string;
private baseUrl = 'https://searchaf-api.antfly.io/api/v1';
constructor(apiKey: string) {
this.apiKey = apiKey;
}
async search(projectId: string, query: string) {
const response = await fetch(
`${this.baseUrl}/projects/${projectId}/search`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': this.apiKey,
},
body: JSON.stringify({ query }),
}
);
if (!response.ok) {
throw new Error(`API error: ${response.statusText}`);
}
return response.json();
}
}
// Usage
const client = new SearchAFClient('sk_live_...');
const results = await client.search('proj_123', 'blue shoes');
Python
import requests
class SearchAFClient:
def __init__(self, api_key):
self.api_key = api_key
self.base_url = 'https://searchaf-api.antfly.io/api/v1'
def search(self, project_id, query):
url = f'{self.base_url}/projects/{project_id}/search'
headers = {
'Content-Type': 'application/json',
'X-API-Key': self.api_key,
}
data = {'query': query}
response = requests.post(url, json=data, headers=headers)
response.raise_for_status()
return response.json()
# Usage
client = SearchAFClient('sk_live_...')
results = client.search('proj_123', 'blue shoes')
Next Steps
- API Endpoints - Explore all available endpoints
- Projects - Create your first project
- Usage & Analytics - Monitor API usage