API Key Logs
curl --request GET \
--url https://api.thepurplebox.io/v1/api-keys/logs \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: <content-type>'import requests
url = "https://api.thepurplebox.io/v1/api-keys/logs"
headers = {
"Content-Type": "<content-type>",
"Authorization": "Bearer <token>"
}
response = requests.get(url, headers=headers)
print(response.text)const options = {
method: 'GET',
headers: {'Content-Type': '<content-type>', Authorization: 'Bearer <token>'}
};
fetch('https://api.thepurplebox.io/v1/api-keys/logs', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.thepurplebox.io/v1/api-keys/logs",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: <content-type>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.thepurplebox.io/v1/api-keys/logs"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Content-Type", "<content-type>")
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.thepurplebox.io/v1/api-keys/logs")
.header("Content-Type", "<content-type>")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.thepurplebox.io/v1/api-keys/logs")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Content-Type"] = '<content-type>'
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"status": 200,
"message": "api key logs retrieved successfully.",
"data": {
"data": [
{
"id": "xxxxx",
"api_key_id": 2,
"team_id": "xxxxx",
"endpoint": "/v1/send",
"method": "POST",
"status_code": 201,
"ip_address": "xxx.xxx.xxx.xxx",
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36",
"request_body": {
"to": "user@example.com",
"subject": "Welcome Email",
"body": "<redacted>"
},
"response_body": {
"status": 201,
"message": "email sent successfully"
},
"response_time": 245,
"error_message": null,
"created_at": "2025-11-21T14:30:15.123Z"
},
{
"id": "xxxxx",
"api_key_id": 2,
"team_id": "xxxxx",
"endpoint": "/v1/emails",
"method": "GET",
"status_code": 200,
"ip_address": "xxx.xxx.xxx.xxx",
"user_agent": "axios/1.6.0",
"request_body": null,
"response_body": {
"status": 200,
"message": "emails retrieved successfully"
},
"response_time": 89,
"error_message": null,
"created_at": "2025-11-21T14:25:42.456Z"
},
{
"id": "xxxxx",
"api_key_id": 2,
"team_id": "xxxxx",
"endpoint": "/v1/send",
"method": "POST",
"status_code": 429,
"ip_address": "xxx.xxx.xxx.xxx",
"user_agent": "node-fetch/2.6.1",
"request_body": {
"to": "user@example.com",
"subject": "Test Email",
"body": "<redacted>"
},
"response_body": {
"status": 429,
"message": "Rate limit exceeded. Please try again later."
},
"response_time": 12,
"error_message": "Rate limit exceeded",
"created_at": "2025-11-21T14:20:05.789Z"
},
{
"id": "xxxxx",
"api_key_id": 2,
"team_id": "xxxxx",
"endpoint": "smtp",
"method": "SMTP",
"status_code": 200,
"ip_address": "xxx.xxx.xxx.xxx",
"user_agent": "nodemailer/6.9.7",
"request_body": {
"to": "recipient@example.com",
"subject": "SMTP Test",
"body": "<redacted>"
},
"response_body": {
"status": 200,
"message": "Email sent via SMTP"
},
"response_time": 310,
"error_message": null,
"created_at": "2025-11-21T14:15:30.123Z"
},
{
"id": "xxxxx",
"api_key_id": 2,
"team_id": "xxxxx",
"endpoint": "/v1/domains",
"method": "POST",
"status_code": 201,
"ip_address": "xxx.xxx.xxx.xxx",
"user_agent": "curl/8.4.0",
"request_body": {
"value": "example.com"
},
"response_body": {
"status": 201,
"message": "domain added successfully"
},
"response_time": 156,
"error_message": null,
"created_at": "2025-11-21T14:10:22.789Z"
}
],
"pagination": {
"page": 1,
"total_records": 250,
"total_pages": 25,
"limit": 10
}
}
}
API Keys
API Key Logs
Retrieve activity logs for your API keys to monitor usage and track requests.
GET
/
v1
/
api-keys
/
logs
API Key Logs
curl --request GET \
--url https://api.thepurplebox.io/v1/api-keys/logs \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: <content-type>'import requests
url = "https://api.thepurplebox.io/v1/api-keys/logs"
headers = {
"Content-Type": "<content-type>",
"Authorization": "Bearer <token>"
}
response = requests.get(url, headers=headers)
print(response.text)const options = {
method: 'GET',
headers: {'Content-Type': '<content-type>', Authorization: 'Bearer <token>'}
};
fetch('https://api.thepurplebox.io/v1/api-keys/logs', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.thepurplebox.io/v1/api-keys/logs",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: <content-type>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.thepurplebox.io/v1/api-keys/logs"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Content-Type", "<content-type>")
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.thepurplebox.io/v1/api-keys/logs")
.header("Content-Type", "<content-type>")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.thepurplebox.io/v1/api-keys/logs")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Content-Type"] = '<content-type>'
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"status": 200,
"message": "api key logs retrieved successfully.",
"data": {
"data": [
{
"id": "xxxxx",
"api_key_id": 2,
"team_id": "xxxxx",
"endpoint": "/v1/send",
"method": "POST",
"status_code": 201,
"ip_address": "xxx.xxx.xxx.xxx",
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36",
"request_body": {
"to": "user@example.com",
"subject": "Welcome Email",
"body": "<redacted>"
},
"response_body": {
"status": 201,
"message": "email sent successfully"
},
"response_time": 245,
"error_message": null,
"created_at": "2025-11-21T14:30:15.123Z"
},
{
"id": "xxxxx",
"api_key_id": 2,
"team_id": "xxxxx",
"endpoint": "/v1/emails",
"method": "GET",
"status_code": 200,
"ip_address": "xxx.xxx.xxx.xxx",
"user_agent": "axios/1.6.0",
"request_body": null,
"response_body": {
"status": 200,
"message": "emails retrieved successfully"
},
"response_time": 89,
"error_message": null,
"created_at": "2025-11-21T14:25:42.456Z"
},
{
"id": "xxxxx",
"api_key_id": 2,
"team_id": "xxxxx",
"endpoint": "/v1/send",
"method": "POST",
"status_code": 429,
"ip_address": "xxx.xxx.xxx.xxx",
"user_agent": "node-fetch/2.6.1",
"request_body": {
"to": "user@example.com",
"subject": "Test Email",
"body": "<redacted>"
},
"response_body": {
"status": 429,
"message": "Rate limit exceeded. Please try again later."
},
"response_time": 12,
"error_message": "Rate limit exceeded",
"created_at": "2025-11-21T14:20:05.789Z"
},
{
"id": "xxxxx",
"api_key_id": 2,
"team_id": "xxxxx",
"endpoint": "smtp",
"method": "SMTP",
"status_code": 200,
"ip_address": "xxx.xxx.xxx.xxx",
"user_agent": "nodemailer/6.9.7",
"request_body": {
"to": "recipient@example.com",
"subject": "SMTP Test",
"body": "<redacted>"
},
"response_body": {
"status": 200,
"message": "Email sent via SMTP"
},
"response_time": 310,
"error_message": null,
"created_at": "2025-11-21T14:15:30.123Z"
},
{
"id": "xxxxx",
"api_key_id": 2,
"team_id": "xxxxx",
"endpoint": "/v1/domains",
"method": "POST",
"status_code": 201,
"ip_address": "xxx.xxx.xxx.xxx",
"user_agent": "curl/8.4.0",
"request_body": {
"value": "example.com"
},
"response_body": {
"status": 201,
"message": "domain added successfully"
},
"response_time": 156,
"error_message": null,
"created_at": "2025-11-21T14:10:22.789Z"
}
],
"pagination": {
"page": 1,
"total_records": 250,
"total_pages": 25,
"limit": 10
}
}
}
Headers
string
required
application/jsonQuery Parameters
number
Filter logs by a specific API key ID.
number
default:"1"
Page number for pagination.
number
default:"10"
Number of log entries to return per page.
string
Filter logs from this date onwards (ISO 8601 format, e.g.,
2025-11-01T00:00:00Z).string
Filter logs up to this date (ISO 8601 format, e.g.,
2025-11-30T23:59:59Z).number
Filter by HTTP status code (e.g.,
200, 429, 500).string
Filter by specific endpoint path (e.g.,
/v1/send, /v1/domains).Response
number
HTTP status code. Returns
200 when logs are retrieved successfully.string
A human-readable message describing the result of the operation.
object
Contains the paginated list of API key logs and pagination metadata.
Show properties
Show properties
array
Array of API key log entries.
Show properties
Show properties
string
Unique identifier for the log entry.
number
The ID of the API key used for this request.
string
The team ID that owns the API key.
string
The API endpoint that was called (e.g.,
/v1/send, /v1/emails, /v1/domains). For SMTP requests, this will be smtp.string
HTTP method used for the request. Possible values:
GET, POST, PUT, DELETE, PATCH. For SMTP requests, this will be SMTP.number
HTTP status code returned by the API (e.g.,
200, 201, 400, 429, 500).string
IP address from which the request originated.
string
User agent string from the client that made the request.
object | null
The request payload sent to the API. Sensitive data may be redacted. Null for GET requests.
object | null
The API response. May be truncated for large responses.
number
Time taken to process the request in milliseconds.
string | null
Error message if the request failed. Null for successful requests.
string
ISO 8601 timestamp when the request was made.
{
"status": 200,
"message": "api key logs retrieved successfully.",
"data": {
"data": [
{
"id": "xxxxx",
"api_key_id": 2,
"team_id": "xxxxx",
"endpoint": "/v1/send",
"method": "POST",
"status_code": 201,
"ip_address": "xxx.xxx.xxx.xxx",
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36",
"request_body": {
"to": "user@example.com",
"subject": "Welcome Email",
"body": "<redacted>"
},
"response_body": {
"status": 201,
"message": "email sent successfully"
},
"response_time": 245,
"error_message": null,
"created_at": "2025-11-21T14:30:15.123Z"
},
{
"id": "xxxxx",
"api_key_id": 2,
"team_id": "xxxxx",
"endpoint": "/v1/emails",
"method": "GET",
"status_code": 200,
"ip_address": "xxx.xxx.xxx.xxx",
"user_agent": "axios/1.6.0",
"request_body": null,
"response_body": {
"status": 200,
"message": "emails retrieved successfully"
},
"response_time": 89,
"error_message": null,
"created_at": "2025-11-21T14:25:42.456Z"
},
{
"id": "xxxxx",
"api_key_id": 2,
"team_id": "xxxxx",
"endpoint": "/v1/send",
"method": "POST",
"status_code": 429,
"ip_address": "xxx.xxx.xxx.xxx",
"user_agent": "node-fetch/2.6.1",
"request_body": {
"to": "user@example.com",
"subject": "Test Email",
"body": "<redacted>"
},
"response_body": {
"status": 429,
"message": "Rate limit exceeded. Please try again later."
},
"response_time": 12,
"error_message": "Rate limit exceeded",
"created_at": "2025-11-21T14:20:05.789Z"
},
{
"id": "xxxxx",
"api_key_id": 2,
"team_id": "xxxxx",
"endpoint": "smtp",
"method": "SMTP",
"status_code": 200,
"ip_address": "xxx.xxx.xxx.xxx",
"user_agent": "nodemailer/6.9.7",
"request_body": {
"to": "recipient@example.com",
"subject": "SMTP Test",
"body": "<redacted>"
},
"response_body": {
"status": 200,
"message": "Email sent via SMTP"
},
"response_time": 310,
"error_message": null,
"created_at": "2025-11-21T14:15:30.123Z"
},
{
"id": "xxxxx",
"api_key_id": 2,
"team_id": "xxxxx",
"endpoint": "/v1/domains",
"method": "POST",
"status_code": 201,
"ip_address": "xxx.xxx.xxx.xxx",
"user_agent": "curl/8.4.0",
"request_body": {
"value": "example.com"
},
"response_body": {
"status": 201,
"message": "domain added successfully"
},
"response_time": 156,
"error_message": null,
"created_at": "2025-11-21T14:10:22.789Z"
}
],
"pagination": {
"page": 1,
"total_records": 250,
"total_pages": 25,
"limit": 10
}
}
}
Use Cases
Monitor API Key Usage
Track how your API keys are being used across different endpoints:// Get all logs for a specific API key
const response = await fetch('https://api.thepurplebox.io/v1/api-keys/logs?api_key_id=2&limit=50', {
headers: {
'Authorization': 'Bearer YOUR_API_KEY'
}
});
const logs = await response.json();
console.log(`Total requests: ${logs.data.pagination.total_records}`);
Identify Rate Limit Issues
Find when and why rate limits are being hit:// Filter by 429 status codes
const response = await fetch('https://api.thepurplebox.io/v1/api-keys/logs?status_code=429', {
headers: {
'Authorization': 'Bearer YOUR_API_KEY'
}
});
const rateLimitErrors = await response.json();
rateLimitErrors.data.data.forEach(log => {
console.log(`Rate limit hit at ${log.created_at} on ${log.endpoint}`);
});
Audit Security
Monitor requests from unexpected IP addresses or locations:// Get recent logs and check IP addresses
const response = await fetch('https://api.thepurplebox.io/v1/api-keys/logs?limit=100', {
headers: {
'Authorization': 'Bearer YOUR_API_KEY'
}
});
const logs = await response.json();
const uniqueIPs = [...new Set(logs.data.data.map(log => log.ip_address))];
console.log('Requests from IPs:', uniqueIPs);
Debug Failed Requests
Investigate errors and failed API calls:// Filter by error status codes (4xx and 5xx)
const response = await fetch('https://api.thepurplebox.io/v1/api-keys/logs?start_date=2025-11-20T00:00:00Z', {
headers: {
'Authorization': 'Bearer YOUR_API_KEY'
}
});
const logs = await response.json();
const errors = logs.data.data.filter(log => log.status_code >= 400);
errors.forEach(log => {
console.log(`Error: ${log.status_code} - ${log.error_message}`);
console.log(`Endpoint: ${log.method} ${log.endpoint}`);
console.log(`Time: ${log.created_at}`);
});
Log Retention
API key logs are retained for:- Free Plan: 1 day
- Basic Plan: 3 days
- Other Plans: Check our pricing page for retention details
What Gets Logged
API key usage is logged for all operations, including:- REST API Requests: Any HTTP request to our API endpoints (
/v1/send,/v1/emails,/v1/domains, etc.) - SMTP Authentication: Emails sent via SMTP using your API key as the password
- All API Operations: Domain creation/verification, email retrieval, contact management, and any other API functionality
Privacy & Security
- Sensitive data in request/response bodies may be redacted
- IP addresses are logged for security purposes
- Logs are only accessible by team members with proper authentication
- All log data is encrypted at rest and in transit
⌘I