Skip to content

API Usage Examples

This document provides practical examples of common API usage scenarios using various tools like cURL, JavaScript, and Go.

Authentication Flow

1. Register a New User

cURL Example:

Terminal window
curl -X POST http://localhost:3000/api/v1/auth/register \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]",
"password": "securepassword123",
"first_name": "John",
"last_name": "Doe"
}'

JavaScript Example (Fetch API):

fetch('http://localhost:3000/api/v1/auth/register', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
password: 'securepassword123',
first_name: 'John',
last_name: 'Doe'
}),
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));

Go Example:

package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
)
func main() {
// Create request body
requestBody, err := json.Marshal(map[string]string{
"email": "[email protected]",
"password": "securepassword123",
"first_name": "John",
"last_name": "Doe",
})
if err != nil {
fmt.Println("Error creating request body:", err)
return
}
// Make the request
resp, err := http.Post(
"http://localhost:3000/api/v1/auth/register",
"application/json",
bytes.NewBuffer(requestBody),
)
if err != nil {
fmt.Println("Error making request:", err)
return
}
defer resp.Body.Close()
// Parse the response
var result map[string]interface{}
json.NewDecoder(resp.Body).Decode(&result)
fmt.Println("Response:", result)
}

2. Verify Email

After registration, the user will receive a verification token. Use this to verify their email:

cURL Example:

Terminal window
curl -X POST http://localhost:3000/api/v1/auth/verify-email \
-H "Content-Type: application/json" \
-d '{
"token": "verification-token-received-via-email"
}'

3. Login

cURL Example:

Terminal window
curl -X POST http://localhost:3000/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]",
"password": "securepassword123"
}'

Response:

{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "bearer",
"expires_in": 900
}

JavaScript Example (Fetch API):

fetch('http://localhost:3000/api/v1/auth/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
password: 'securepassword123'
}),
})
.then(response => response.json())
.then(data => {
// Store tokens in localStorage or securely in memory
localStorage.setItem('access_token', data.access_token);
localStorage.setItem('refresh_token', data.refresh_token);
console.log('Authentication successful:', data);
})
.catch(error => console.error('Error:', error));

Go Example:

package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
)
func main() {
// Create request body
requestBody, err := json.Marshal(map[string]string{
"email": "[email protected]",
"password": "securepassword123",
})
if err != nil {
fmt.Println("Error creating request body:", err)
return
}
// Make the request
resp, err := http.Post(
"http://localhost:3000/api/v1/auth/login",
"application/json",
bytes.NewBuffer(requestBody),
)
if err != nil {
fmt.Println("Error making request:", err)
return
}
defer resp.Body.Close()
// Parse the response
var result map[string]interface{}
json.NewDecoder(resp.Body).Decode(&result)
fmt.Println("Access Token:", result["access_token"])
fmt.Println("Refresh Token:", result["refresh_token"])
}

4. Refresh Token

When the access token expires, use the refresh token to get a new pair:

cURL Example:

Terminal window
curl -X POST http://localhost:3000/api/v1/auth/refresh \
-H "Content-Type: application/json" \
-d '{
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}'

JavaScript Example:

fetch('http://localhost:3000/api/v1/auth/refresh', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
refresh_token: localStorage.getItem('refresh_token')
}),
})
.then(response => response.json())
.then(data => {
// Update tokens in storage
localStorage.setItem('access_token', data.access_token);
localStorage.setItem('refresh_token', data.refresh_token);
console.log('Tokens refreshed successfully');
})
.catch(error => console.error('Error refreshing tokens:', error));

5. Logout

cURL Example:

Terminal window
curl -X POST http://localhost:3000/api/v1/auth/logout \
-H "Content-Type: application/json" \
-d '{
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}'

JavaScript Example:

fetch('http://localhost:3000/api/v1/auth/logout', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
refresh_token: localStorage.getItem('refresh_token')
}),
})
.then(response => {
if (response.ok) {
// Clear tokens from storage
localStorage.removeItem('access_token');
localStorage.removeItem('refresh_token');
console.log('Logged out successfully');
} else {
console.error('Logout failed');
}
})
.catch(error => console.error('Error during logout:', error));

User Management

1. Get Current User Profile

cURL Example:

Terminal window
curl -X GET http://localhost:3000/api/v1/users/me \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

JavaScript Example:

fetch('http://localhost:3000/api/v1/users/me', {
method: 'GET',
headers: {
'Authorization': `Bearer ${localStorage.getItem('access_token')}`,
},
})
.then(response => response.json())
.then(data => console.log('User profile:', data))
.catch(error => console.error('Error fetching profile:', error));

2. Update User Profile

cURL Example:

Terminal window
curl -X PUT http://localhost:3000/api/v1/users/me \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
-H "Content-Type: application/json" \
-d '{
"first_name": "Updated",
"last_name": "Name"
}'

JavaScript Example:

fetch('http://localhost:3000/api/v1/users/me', {
method: 'PUT',
headers: {
'Authorization': `Bearer ${localStorage.getItem('access_token')}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
first_name: 'Updated',
last_name: 'Name'
}),
})
.then(response => response.json())
.then(data => console.log('Updated profile:', data))
.catch(error => console.error('Error updating profile:', error));

3. List All Users (Admin Only)

cURL Example:

Terminal window
curl -X GET "http://localhost:3000/api/v1/users?page=1&per_page=20" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

JavaScript Example:

fetch('http://localhost:3000/api/v1/users?page=1&per_page=20', {
method: 'GET',
headers: {
'Authorization': `Bearer ${localStorage.getItem('access_token')}`,
},
})
.then(response => response.json())
.then(data => console.log('Users list:', data))
.catch(error => console.error('Error fetching users:', error));

API Key Management

1. Create an API Key

cURL Example:

Terminal window
curl -X POST http://localhost:3000/api/v1/api-keys \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
-H "Content-Type: application/json" \
-d '{
"name": "My Service API Key",
"expires_at": "2025-12-31T23:59:59Z"
}'

Response:

{
"id": "8a7b6c5d-4e3f-2a1b-0c9d-8e7f6a5b4c3d",
"user_id": "5f8d0d55-8b96-4536-8c34-781a9a3e9a9b",
"name": "My Service API Key",
"key": "sk-Avery1LongRandomAPIKeyStringThatShouldBeStoredSafely",
"prefix": "sk-Avery",
"is_active": true,
"expires_at": "2025-12-31T23:59:59Z",
"created_at": "2023-06-01T12:34:56Z",
"updated_at": "2023-06-01T12:34:56Z"
}

Important: The full API key (key field) is only returned once when creating the key. Store it securely as you won’t be able to retrieve it later.

2. List Your API Keys

cURL Example:

Terminal window
curl -X GET http://localhost:3000/api/v1/api-keys \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

3. Add Permissions to API Key

cURL Example:

Terminal window
curl -X POST http://localhost:3000/api/v1/api-keys/8a7b6c5d-4e3f-2a1b-0c9d-8e7f6a5b4c3d/permissions \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
-H "Content-Type: application/json" \
-d '{
"permission_id": "5f8d0d55-8b96-4536-8c34-781a9a3e9a9b"
}'

4. Using an API Key for Authentication

Instead of using JWT tokens, you can authenticate with an API key:

cURL Example:

Terminal window
curl -X GET http://localhost:3000/api/v1/users/me \
-H "X-API-Key: sk-Avery1LongRandomAPIKeyStringThatShouldBeStoredSafely"

JavaScript Example:

fetch('http://localhost:3000/api/v1/users/me', {
method: 'GET',
headers: {
'X-API-Key': 'sk-Avery1LongRandomAPIKeyStringThatShouldBeStoredSafely',
},
})
.then(response => response.json())
.then(data => console.log('User profile:', data))
.catch(error => console.error('Error fetching profile:', error));

Role and Permission Management

1. List All Roles

cURL Example:

Terminal window
curl -X GET http://localhost:3000/api/v1/roles \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

2. Create a New Role (Admin Only)

cURL Example:

Terminal window
curl -X POST http://localhost:3000/api/v1/roles \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
-H "Content-Type: application/json" \
-d '{
"name": "editor",
"description": "Can edit content but not manage users"
}'

3. Add Permission to Role (Admin Only)

cURL Example:

Terminal window
curl -X POST http://localhost:3000/api/v1/roles/8a7b6c5d-4e3f-2a1b-0c9d-8e7f6a5b4c3d/permissions \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
-H "Content-Type: application/json" \
-d '{
"permission_id": "5f8d0d55-8b96-4536-8c34-781a9a3e9a9b"
}'

4. Assign Role to User (Admin Only)

cURL Example:

Terminal window
curl -X POST http://localhost:3000/api/v1/users/8a7b6c5d-4e3f-2a1b-0c9d-8e7f6a5b4c3d/roles \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
-H "Content-Type: application/json" \
-d '{
"role_id": "5f8d0d55-8b96-4536-8c34-781a9a3e9a9b"
}'

Error Handling Examples

1. Validation Error

Request:

Terminal window
curl -X POST http://localhost:3000/api/v1/auth/register \
-H "Content-Type: application/json" \
-d '{
"email": "invalid-email",
"password": "short",
"first_name": "John",
"last_name": "Doe"
}'

Response:

{
"error": "Validation failed",
"fields": {
"email": "must be a valid email address",
"password": "must be at least 8 characters long"
}
}

2. Authentication Error

Request:

Terminal window
curl -X GET http://localhost:3000/api/v1/users/me

Response:

{
"error": "Unauthorized: missing authentication token",
"status": 401
}

3. Rate Limiting Error

When rate limits are exceeded:

Response:

{
"error": "Rate limit exceeded",
"status": 429
}

Helper Utilities

JavaScript Authentication Utility

Here’s a simple JavaScript utility for handling authentication:

auth.js
class AuthService {
constructor(apiUrl) {
this.apiUrl = apiUrl;
this.accessToken = localStorage.getItem('access_token');
this.refreshToken = localStorage.getItem('refresh_token');
}
isAuthenticated() {
return !!this.accessToken;
}
async login(email, password) {
const response = await fetch(`${this.apiUrl}/auth/login`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ email, password }),
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.error || 'Login failed');
}
const data = await response.json();
this.accessToken = data.access_token;
this.refreshToken = data.refresh_token;
localStorage.setItem('access_token', this.accessToken);
localStorage.setItem('refresh_token', this.refreshToken);
return data;
}
async logout() {
if (!this.refreshToken) return;
try {
await fetch(`${this.apiUrl}/auth/logout`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ refresh_token: this.refreshToken }),
});
} catch (error) {
console.error('Logout error:', error);
} finally {
// Clear tokens regardless of logout success
this.accessToken = null;
this.refreshToken = null;
localStorage.removeItem('access_token');
localStorage.removeItem('refresh_token');
}
}
async refreshAccessToken() {
if (!this.refreshToken) throw new Error('No refresh token available');
const response = await fetch(`${this.apiUrl}/auth/refresh`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ refresh_token: this.refreshToken }),
});
if (!response.ok) {
// If refresh fails, log out
this.logout();
throw new Error('Failed to refresh token');
}
const data = await response.json();
this.accessToken = data.access_token;
this.refreshToken = data.refresh_token;
localStorage.setItem('access_token', this.accessToken);
localStorage.setItem('refresh_token', this.refreshToken);
return data;
}
async fetchWithAuth(url, options = {}) {
const headers = {
...options.headers,
'Authorization': `Bearer ${this.accessToken}`,
};
let response = await fetch(url, { ...options, headers });
// If unauthorized, try to refresh token and retry the request
if (response.status === 401 && this.refreshToken) {
try {
await this.refreshAccessToken();
// Update headers with new token
headers.Authorization = `Bearer ${this.accessToken}`;
// Retry the request
response = await fetch(url, { ...options, headers });
} catch (error) {
console.error('Token refresh failed:', error);
throw error;
}
}
return response;
}
}
// Usage:
const auth = new AuthService('http://localhost:3000/api/v1');
async function loginUser(email, password) {
try {
await auth.login(email, password);
console.log('Login successful');
} catch (error) {
console.error('Login failed:', error);
}
}
async function getUserProfile() {
try {
const response = await auth.fetchWithAuth(`${auth.apiUrl}/users/me`);
if (!response.ok) throw new Error('Failed to get profile');
const profile = await response.json();
console.log('User profile:', profile);
return profile;
} catch (error) {
console.error('Error fetching profile:', error);
}
}

Go Client Example

Here’s a simple Go client for the API:

package main
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"net/http"
)
// AuthClient represents a client for the auth API
type AuthClient struct {
BaseURL string
AccessToken string
RefreshToken string
HTTPClient *http.Client
}
// NewAuthClient creates a new auth client
func NewAuthClient(baseURL string) *AuthClient {
return &AuthClient{
BaseURL: baseURL,
HTTPClient: &http.Client{},
}
}
// TokenResponse represents the response from login and refresh endpoints
type TokenResponse struct {
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
ExpiresIn int `json:"expires_in"`
}
// Login authenticates a user
func (c *AuthClient) Login(email, password string) error {
// Create request body
requestBody, err := json.Marshal(map[string]string{
"email": email,
"password": password,
})
if err != nil {
return err
}
// Make the request
resp, err := c.HTTPClient.Post(
c.BaseURL+"/auth/login",
"application/json",
bytes.NewBuffer(requestBody),
)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
var errorResp map[string]interface{}
json.NewDecoder(resp.Body).Decode(&errorResp)
return fmt.Errorf("login failed: %v", errorResp["error"])
}
// Parse the response
var tokenResp TokenResponse
if err := json.NewDecoder(resp.Body).Decode(&tokenResp); err != nil {
return err
}
// Save tokens
c.AccessToken = tokenResp.AccessToken
c.RefreshToken = tokenResp.RefreshToken
return nil
}
// AuthenticatedRequest makes an authenticated request
func (c *AuthClient) AuthenticatedRequest(method, path string, body interface{}) (*http.Response, error) {
if c.AccessToken == "" {
return nil, errors.New("not authenticated")
}
var bodyReader *bytes.Buffer
if body != nil {
bodyData, err := json.Marshal(body)
if err != nil {
return nil, err
}
bodyReader = bytes.NewBuffer(bodyData)
}
// Create request
req, err := http.NewRequest(method, c.BaseURL+path, bodyReader)
if err != nil {
return nil, err
}
// Set headers
req.Header.Set("Authorization", "Bearer "+c.AccessToken)
if body != nil {
req.Header.Set("Content-Type", "application/json")
}
// Make the request
resp, err := c.HTTPClient.Do(req)
if err != nil {
return nil, err
}
// If unauthorized, try to refresh token
if resp.StatusCode == http.StatusUnauthorized && c.RefreshToken != "" {
resp.Body.Close() // Close the 401 response
// Try to refresh token
err = c.RefreshToken()
if err != nil {
return nil, fmt.Errorf("token refresh failed: %w", err)
}
// Retry the request with new token
req.Header.Set("Authorization", "Bearer "+c.AccessToken)
return c.HTTPClient.Do(req)
}
return resp, nil
}
// RefreshToken refreshes the access token
func (c *AuthClient) RefreshTokens() error {
if c.RefreshToken == "" {
return errors.New("no refresh token available")
}
// Create request body
requestBody, err := json.Marshal(map[string]string{
"refresh_token": c.RefreshToken,
})
if err != nil {
return err
}
// Make the request
resp, err := c.HTTPClient.Post(
c.BaseURL+"/auth/refresh",
"application/json",
bytes.NewBuffer(requestBody),
)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
// Clear tokens on refresh failure
c.AccessToken = ""
c.RefreshToken = ""
var errorResp map[string]interface{}
json.NewDecoder(resp.Body).Decode(&errorResp)
return fmt.Errorf("token refresh failed: %v", errorResp["error"])
}
// Parse the response
var tokenResp TokenResponse
if err := json.NewDecoder(resp.Body).Decode(&tokenResp); err != nil {
return err
}
// Save new tokens
c.AccessToken = tokenResp.AccessToken
c.RefreshToken = tokenResp.RefreshToken
return nil
}
// GetUserProfile gets the current user's profile
func (c *AuthClient) GetUserProfile() (map[string]interface{}, error) {
resp, err := c.AuthenticatedRequest("GET", "/users/me", nil)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
var errorResp map[string]interface{}
json.NewDecoder(resp.Body).Decode(&errorResp)
return nil, fmt.Errorf("failed to get profile: %v", errorResp["error"])
}
var profile map[string]interface{}
if err := json.NewDecoder(resp.Body).Decode(&profile); err != nil {
return nil, err
}
return profile, nil
}
// Usage example
func main() {
client := NewAuthClient("http://localhost:3000/api/v1")
// Login
err := client.Login("[email protected]", "securepassword123")
if err != nil {
fmt.Println("Login error:", err)
return
}
// Get profile
profile, err := client.GetUserProfile()
if err != nil {
fmt.Println("Error getting profile:", err)
return
}
fmt.Println("User profile:", profile)
}