Coral Tracker API

v1.0 — REST API Documentation

Overview

The Coral Tracker API lets you programmatically manage your coral inventory. Use it to integrate with e-commerce platforms, build custom dashboards, or sync data with mobile apps.

REST
JSON over HTTPS
5
Endpoints
Free
To get started

Base URL

https://api.coral-tracker.com/api/v1

Authentication

All requests must include your API key in the X-API-Key header. API keys start with ctk_.

Keep your key secret. Never expose it in client-side code, public repos, or URLs. If compromised, delete it and create a new one.

# Test your API key curl -H "X-API-Key: ctk_your_key_here" \ https://api.coral-tracker.com/api/v1/corals
const response = await fetch('https://api.coral-tracker.com/api/v1/corals', { headers: { 'X-API-Key': 'ctk_your_key_here', 'Accept': 'application/json' } }); const data = await response.json(); console.log(data);
<?php $ch = curl_init('https://api.coral-tracker.com/api/v1/corals'); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ 'X-API-Key: ctk_your_key_here', 'Accept: application/json', ], ]); $response = curl_exec($ch); $data = json_decode($response, true); print_r($data);
import requests response = requests.get( 'https://api.coral-tracker.com/api/v1/corals', headers={'X-API-Key': 'ctk_your_key_here'} ) data = response.json() print(data)

Rate Limiting

Requests are rate-limited per organization. Check the response headers to monitor your usage:

Header Description
X-RateLimit-LimitMax requests per minute
X-RateLimit-RemainingRequests left in current window
X-RateLimit-ResetUnix timestamp when the window resets
Retry-AfterSeconds to wait (only on 429 responses)

Plans & Access

Free

$0

  • 1 API key (read-only)
  • 60 req/min
  • 10 corals
POPULAR

Premium

€4.99/mo

  • 5 API keys (read + write)
  • 120 req/min
  • Unlimited corals

Enterprise

€14.99/mo

  • Unlimited keys (full access)
  • 300 req/min
  • Webhooks
GET

/corals

Retrieve a paginated list of corals for your organization.

Query Parameters

ParamTypeDefaultDescription
per_pageinteger20Items per page (max 100)
pageinteger1Page number
for_salestringSet to true to only get corals marked for sale
typestringFilter by type: SPS, LPS, Soft, NPS, Anemone, Zoa, Other
searchstringSearch by name or species
curl -H "X-API-Key: ctk_your_key" \ "https://api.coral-tracker.com/api/v1/corals?for_sale=true&per_page=10"
const res = await fetch('https://api.coral-tracker.com/api/v1/corals?for_sale=true&per_page=10', { headers: { 'X-API-Key': 'ctk_your_key' } }); const { data, meta } = await res.json(); console.log(`Page ${meta.current_page} of ${meta.last_page}`);
$response = file_get_contents( 'https://api.coral-tracker.com/api/v1/corals?for_sale=true', false, stream_context_create(['http' => [ 'header' => "X-API-Key: ctk_your_key\r\nAccept: application/json" ]]) ); $data = json_decode($response, true);
response = requests.get( 'https://api.coral-tracker.com/api/v1/corals', headers={'X-API-Key': 'ctk_your_key'}, params={'for_sale': 'true', 'per_page': 10} ) corals = response.json()['data']

Example Response

{ "data": [ { "id": 1, "name": "Blue Acropora", "species": "Acropora millepora", "type": "SPS", "price_when_added": 49.99, "current_frag_count": 25, "health_status": "excellent", "is_for_sale": true, "image_url": "https://...", "gallery_urls": ["https://...", "https://..."], "images": [ { "id": 1, "image_url": "https://...", "is_primary": true } ] } ], "meta": { "current_page": 1, "per_page": 10, "total": 42, "last_page": 5 } }
GET

/corals/{id}

Retrieve a specific coral with its full update history and images.

curl -H "X-API-Key: ctk_your_key" \ https://api.coral-tracker.com/api/v1/corals/1
const res = await fetch('https://api.coral-tracker.com/api/v1/corals/1', { headers: { 'X-API-Key': 'ctk_your_key' } }); const coral = (await res.json()).data;
$ch = curl_init('https://api.coral-tracker.com/api/v1/corals/1'); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ['X-API-Key: ctk_your_key'], ]); $coral = json_decode(curl_exec($ch), true)['data'];
POST

/corals

write permission

Create a new coral entry in your inventory.

Request Body

FieldTypeRequiredDescription
namestringYesCoral name (max 255)
speciesstringNoScientific species name
purchased_atdateYesPurchase date (YYYY-MM-DD)
price_when_addednumberYesPurchase price
price_per_fragnumberYesPrice per frag
initial_frag_countintegerYesStarting frag count (min: 1)
current_frag_countintegerNoDefaults to initial count
notesstringNoAny notes
health_statusstringNoexcellent, good, fair, or poor (default: good)
curl -X POST https://api.coral-tracker.com/api/v1/corals \ -H "X-API-Key: ctk_your_key" \ -H "Content-Type: application/json" \ -d '{ "name": "Blue Acropora", "species": "Acropora millepora", "purchased_at": "2026-01-15", "price_when_added": 49.99, "price_per_frag": 5.00, "initial_frag_count": 10, "health_status": "good" }'
const res = await fetch('https://api.coral-tracker.com/api/v1/corals', { method: 'POST', headers: { 'X-API-Key': 'ctk_your_key', 'Content-Type': 'application/json' }, body: JSON.stringify({ name: 'Blue Acropora', species: 'Acropora millepora', purchased_at: '2026-01-15', price_when_added: 49.99, price_per_frag: 5.00, initial_frag_count: 10, health_status: 'good' }) }); const newCoral = (await res.json()).data;
$ch = curl_init('https://api.coral-tracker.com/api/v1/corals'); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_HTTPHEADER => [ 'X-API-Key: ctk_your_key', 'Content-Type: application/json', ], CURLOPT_POSTFIELDS => json_encode([ 'name' => 'Blue Acropora', 'species' => 'Acropora millepora', 'purchased_at' => '2026-01-15', 'price_when_added' => 49.99, 'price_per_frag' => 5.00, 'initial_frag_count' => 10, ]), ]); $result = json_decode(curl_exec($ch), true);
PUT

/corals/{id}

write permission

Update an existing coral. Only include the fields you want to change.

curl -X PUT https://api.coral-tracker.com/api/v1/corals/1 \ -H "X-API-Key: ctk_your_key" \ -H "Content-Type: application/json" \ -d '{"current_frag_count": 25, "health_status": "excellent"}'
const res = await fetch('https://api.coral-tracker.com/api/v1/corals/1', { method: 'PUT', headers: { 'X-API-Key': 'ctk_your_key', 'Content-Type': 'application/json' }, body: JSON.stringify({ current_frag_count: 25, health_status: 'excellent' }) });
$ch = curl_init('https://api.coral-tracker.com/api/v1/corals/1'); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => 'PUT', CURLOPT_HTTPHEADER => [ 'X-API-Key: ctk_your_key', 'Content-Type: application/json', ], CURLOPT_POSTFIELDS => json_encode([ 'current_frag_count' => 25, 'health_status' => 'excellent', ]), ]); $result = json_decode(curl_exec($ch), true);
DELETE

/corals/{id}

delete permission

Permanently delete a coral and all associated data.

Warning: This action is irreversible. The coral and all its update history will be permanently deleted.

curl -X DELETE https://api.coral-tracker.com/api/v1/corals/1 \ -H "X-API-Key: ctk_your_key"
await fetch('https://api.coral-tracker.com/api/v1/corals/1', { method: 'DELETE', headers: { 'X-API-Key': 'ctk_your_key' } });

Webhooks

Receive real-time HTTP notifications when events happen in your account. (Enterprise plan)

Available Events

coral.created coral.updated coral.deleted coral.update.created

Signature Verification

Each webhook includes headers for verification:

# Headers sent with each webhook X-Webhook-Signature: <hmac_sha256> X-Webhook-Timestamp: <unix_timestamp> X-Webhook-Event: coral.created # Verify with: signature = hmac_sha256(secret, timestamp + '.' + json_body)

Error Handling

All errors follow a consistent JSON format:

{ "error": "Validation failed", "message": "The provided data is invalid", "errors": { "name": ["The name field is required."] } }

HTTP Status Codes

CodeMeaningWhen
200OKRequest successful
201CreatedNew coral created
401UnauthorizedMissing or invalid API key
403ForbiddenAPI disabled or coral limit reached
404Not FoundCoral doesn't exist
422Validation ErrorInvalid request data
429Rate LimitedToo many requests
500Server ErrorSomething went wrong

Downloads & Tools