API Client
Learn how to authenticate and make requests to the Agin Cloud API using Bearer token authentication
What is an API Client?
An API client is any application or code that makes HTTP requests to interact with the Agin Cloud API. Unlike SDKs (Software Development Kits) that provide pre-built methods, you'll be making direct HTTP requests using your preferred HTTP client library.
Authentication Method
Agin Cloud uses Bearer token authentication. Your API key serves as the bearer token that you include in the Authorization header of every request.
Getting Your API Key
Before you can make requests to the Agin Cloud API, you need to obtain an API key.
Log in to Agin Cloud Dashboard
Navigate to https://agin.cloud and sign in with your credentials.
Access API Settings
From the dashboard, click on Settings in the sidebar, then select API Keys.
Generate New API Key
Click the Generate New Key button. You'll be prompted to:
- Provide a descriptive name for your key (e.g., "Production App", "Development")
- Select the appropriate permissions/scopes
- Set an expiration date (optional but recommended)
Save Your API Key
Important
Copy your API key immediately. For security reasons, you won't be able to see it again after closing this dialog.
Store your API key securely using environment variables or a secrets manager. Never commit API keys to version control.
API Key Format
Agin Cloud API keys follow this format:
agin_live_1234567890abcdefghijklmnopqrstuvwxyzagin_- Prefix identifying it as an Agin Cloud keylive_ortest_- Environment identifier- Random alphanumeric string - Your unique key
Setting Up Your Environment
Environment Variables
Create a .env file in your project root:
AGIN_API_KEY=agin_live_your_api_key_here
AGIN_API_URL=https://api.agin.cloud/v1Use agin_test_ keys for development and testing environments.
Add to .gitignore
Ensure your .env file is not committed to version control:
.env
.env.local
.env.*.localBearer Token Authentication
The Agin Cloud API uses Bearer token authentication. Your API key is used directly as the bearer token.
How It Works
Include your API key in the Authorization header of every request:
Authorization: Bearer agin_live_your_api_key_hereThis header must be included in all requests to the Agin Cloud API.
Making Requests
You can use any HTTP client library to make requests. Here are examples with popular options:
Using fetch (Built-in)
const response = await fetch('https://api.agin.cloud/v1/resources', {
method: 'GET',
headers: {
'Authorization': `Bearer ${process.env.AGIN_API_KEY}`,
'Content-Type': 'application/json',
},
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
console.log(data);const response = await fetch('https://api.agin.cloud/v1/resources', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.AGIN_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'My Resource',
type: 'compute',
config: {
cpu: 2,
memory: '4GB',
},
}),
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const resource = await response.json();
console.log('Created:', resource.id);const response = await fetch('https://api.agin.cloud/v1/resources/resource_123', {
method: 'PUT',
headers: {
'Authorization': `Bearer ${process.env.AGIN_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'Updated Name',
config: {
cpu: 4,
memory: '8GB',
},
}),
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const updated = await response.json();
console.log('Updated:', updated);const response = await fetch('https://api.agin.cloud/v1/resources/resource_123', {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${process.env.AGIN_API_KEY}`,
},
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
console.log('Deleted successfully');Using axios
First, install axios:
npm install axiosThen make requests:
import axios from 'axios';
const client = axios.create({
baseURL: 'https://api.agin.cloud/v1',
headers: {
'Authorization': `Bearer ${process.env.AGIN_API_KEY}`,
},
});
const response = await client.get('/resources');
console.log(response.data);import axios from 'axios';
const client = axios.create({
baseURL: 'https://api.agin.cloud/v1',
headers: {
'Authorization': `Bearer ${process.env.AGIN_API_KEY}`,
},
});
const response = await client.post('/resources', {
name: 'My Resource',
type: 'compute',
config: {
cpu: 2,
memory: '4GB',
},
});
console.log('Created:', response.data.id);const response = await client.put('/resources/resource_123', {
name: 'Updated Name',
config: {
cpu: 4,
memory: '8GB',
},
});
console.log('Updated:', response.data);const response = await client.delete('/resources/resource_123');
console.log('Deleted successfully');Creating a Reusable Client
Create a simple wrapper to avoid repeating authentication:
class AginClient {
private baseURL: string;
private apiKey: string;
constructor(apiKey: string, baseURL = 'https://api.agin.cloud/v1') {
this.baseURL = baseURL;
this.apiKey = apiKey;
}
private async request(
endpoint: string,
options: RequestInit = {}
) {
const url = `${this.baseURL}${endpoint}`;
const response = await fetch(url, {
...options,
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json',
...options.headers,
},
});
if (!response.ok) {
const error = await response.json().catch(() => ({}));
throw new Error(error.message || `HTTP ${response.status}`);
}
return response.json();
}
async get(endpoint: string) {
return this.request(endpoint, { method: 'GET' });
}
async post(endpoint: string, data: any) {
return this.request(endpoint, {
method: 'POST',
body: JSON.stringify(data),
});
}
async put(endpoint: string, data: any) {
return this.request(endpoint, {
method: 'PUT',
body: JSON.stringify(data),
});
}
async delete(endpoint: string) {
return this.request(endpoint, { method: 'DELETE' });
}
}
// Export configured instance
export const aginClient = new AginClient(
process.env.AGIN_API_KEY!
);Usage:
import { aginClient } from './lib/agin-client';
// GET request
const resources = await aginClient.get('/resources');
// POST request
const newResource = await aginClient.post('/resources', {
name: 'My Resource',
type: 'compute',
});
// PUT request
const updated = await aginClient.put('/resources/resource_123', {
name: 'Updated Name',
});
// DELETE request
await aginClient.delete('/resources/resource_123');Error Handling
Handle different HTTP status codes appropriately:
async function makeRequest() {
try {
const response = await fetch('https://api.agin.cloud/v1/resources', {
headers: {
'Authorization': `Bearer ${process.env.AGIN_API_KEY}`,
},
});
// Handle different status codes
switch (response.status) {
case 200:
case 201:
return await response.json();
case 400:
const validationError = await response.json();
console.error('Validation error:', validationError.errors);
throw new Error('Invalid request');
case 401:
console.error('Unauthorized: Check your API key');
throw new Error('Authentication failed');
case 403:
console.error('Forbidden: Insufficient permissions');
throw new Error('Access denied');
case 404:
console.error('Resource not found');
throw new Error('Not found');
case 429:
const retryAfter = response.headers.get('Retry-After');
console.error(`Rate limited. Retry after ${retryAfter} seconds`);
throw new Error('Rate limit exceeded');
case 500:
case 502:
case 503:
case 504:
console.error('Server error');
throw new Error('Server error');
default:
throw new Error(`Unexpected status: ${response.status}`);
}
} catch (error) {
console.error('Request failed:', error);
throw error;
}
}Framework Integration
Next.js App Router (API Route)
import { NextResponse } from 'next/server';
export async function GET(request: Request) {
try {
const response = await fetch('https://api.agin.cloud/v1/resources', {
headers: {
'Authorization': `Bearer ${process.env.AGIN_API_KEY}`,
'Content-Type': 'application/json',
},
// Important for server-side caching
next: { revalidate: 60 }, // Revalidate every 60 seconds
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
return NextResponse.json(data);
} catch (error) {
return NextResponse.json(
{ error: 'Failed to fetch resources' },
{ status: 500 }
);
}
}
export async function POST(request: Request) {
try {
const body = await request.json();
const response = await fetch('https://api.agin.cloud/v1/resources', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.AGIN_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
return NextResponse.json(data);
} catch (error) {
return NextResponse.json(
{ error: 'Failed to create resource' },
{ status: 500 }
);
}
}Next.js Server Component
async function getResources() {
const response = await fetch('https://api.agin.cloud/v1/resources', {
headers: {
'Authorization': `Bearer ${process.env.AGIN_API_KEY}`,
},
next: { revalidate: 3600 }, // Cache for 1 hour
});
if (!response.ok) {
throw new Error('Failed to fetch resources');
}
return response.json();
}
export default async function ResourcesPage() {
const resources = await getResources();
return (
<div>
<h1>Resources</h1>
<ul>
{resources.data.map((resource: any) => (
<li key={resource.id}>{resource.name}</li>
))}
</ul>
</div>
);
}React Client Component
'use client';
import { useEffect, useState } from 'react';
export function ResourcesList() {
const [resources, setResources] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
async function fetchResources() {
try {
// Call your API route, not Agin API directly
const response = await fetch('/api/resources');
if (!response.ok) {
throw new Error('Failed to fetch');
}
const data = await response.json();
setResources(data.data || []);
} catch (err) {
setError(err instanceof Error ? err.message : 'An error occurred');
} finally {
setLoading(false);
}
}
fetchResources();
}, []);
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error}</div>;
return (
<ul>
{resources.map((resource: any) => (
<li key={resource.id}>{resource.name}</li>
))}
</ul>
);
}Security Best Practice
Never expose your Agin API key in client-side code. Always make API calls from your backend (API routes, server components, or server functions) where environment variables are secure.
Express.js
import express from 'express';
const app = express();
app.use(express.json());
app.get('/api/resources', async (req, res) => {
try {
const response = await fetch('https://api.agin.cloud/v1/resources', {
headers: {
'Authorization': `Bearer ${process.env.AGIN_API_KEY}`,
},
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
res.json(data);
} catch (error) {
res.status(500).json({
error: 'Failed to fetch resources'
});
}
});
app.post('/api/resources', async (req, res) => {
try {
const response = await fetch('https://api.agin.cloud/v1/resources', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.AGIN_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(req.body),
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
res.json(data);
} catch (error) {
res.status(500).json({
error: 'Failed to create resource'
});
}
});
app.listen(3000, () => {
console.log('Server running on port 3000');
});Security Best Practices
1. Store API Keys Securely
# ✅ Good - Use environment variables
AGIN_API_KEY=agin_live_xxxxx// ❌ Bad - Never hardcode
const apiKey = 'agin_live_xxxxx';2. Use Different Keys for Different Environments
AGIN_API_KEY=agin_test_xxxxxAGIN_API_KEY=agin_live_xxxxx3. Never Expose Keys Client-Side
// ❌ Bad - API key exposed in browser
async function clientSideRequest() {
const response = await fetch('https://api.agin.cloud/v1/resources', {
headers: {
'Authorization': `Bearer ${process.env.NEXT_PUBLIC_AGIN_API_KEY}`, // ❌
},
});
}
// ✅ Good - Use API routes
async function clientSideRequest() {
const response = await fetch('/api/resources'); // ✅
}4. Implement Rate Limiting
Respect the API's rate limits and implement exponential backoff for retries.
5. Monitor API Usage
Log requests for debugging and monitoring:
const startTime = Date.now();
const response = await fetch(url, options);
const duration = Date.now() - startTime;
console.log(`API Request: ${method} ${url} - ${response.status} (${duration}ms)`);Rate Limits
Agin Cloud API has the following rate limits:
| Plan | Requests per Hour |
|---|---|
| Standard | 1,000 |
| Pro | 10,000 |
| Enterprise | Custom |
Handling Rate Limits
Check the response headers for rate limit information:
const response = await fetch(url, options);
console.log('Rate Limit:', response.headers.get('X-RateLimit-Limit'));
console.log('Remaining:', response.headers.get('X-RateLimit-Remaining'));
console.log('Reset:', response.headers.get('X-RateLimit-Reset'));
if (response.status === 429) {
const retryAfter = response.headers.get('Retry-After');
console.log(`Rate limited. Retry after ${retryAfter} seconds`);
}Troubleshooting
Authentication Failed (401)
Possible causes:
- Invalid API key
- Expired API key
- Missing Authorization header
- Using test key in production
Solution:
- Verify your API key is correct
- Ensure the Authorization header format is:
Bearer YOUR_API_KEY - Check you're using the right environment key
Forbidden (403)
Possible causes:
- Insufficient permissions for the operation
- API key doesn't have required scope
Solution:
- Check the permissions assigned to your API key
- Generate a new key with appropriate permissions
Not Found (404)
Possible causes:
- Incorrect endpoint URL
- Resource doesn't exist
- Typo in resource ID
Solution:
- Verify the endpoint URL
- Check the resource ID is correct
- Consult the API reference for correct endpoints
Rate Limit Exceeded (429)
Solution:
- Implement retry logic with exponential backoff
- Reduce request frequency
- Upgrade to a higher tier plan