Authentication
All COALS API requests are authenticated with an API key passed in the HTTP Authorization header.
Getting an API Key
API keys are created and managed from your COALS dashboard. Each key can be given a name and scoped to specific services so you can issue minimal-privilege keys for each application.
Manage API KeysAuthorization Header
Pass your API key as a Bearer token in every request. The header is required on all endpoints — requests without it will receive a 401 response.
Header
Authorization: Bearer YOUR_API_KEY
Example Request
curl -X POST https://coals.ai/api/v1/simcoal/send \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "to": "+15550001234", "message": "Hello from COALS!" }'
// Using Guzzle $response = $client->post('https://coals.ai/api/v1/simcoal/send', [ 'headers' => ['Authorization' => 'Bearer YOUR_API_KEY'], 'json' => [ "to" => "+15550001234", "message" => "Hello from COALS!" ] ]); $data = json_decode($response->getBody(), true);
# Using requests import requests response = requests.post( "https://coals.ai/api/v1/simcoal/send", headers={"Authorization": "Bearer YOUR_API_KEY"}, json={ "to": "+15550001234", "message": "Hello from COALS!" } ) data = response.json()
# Using net/http require "net/http" require "json" uri = URI("https://coals.ai/api/v1/simcoal/send") req = Net::HTTP::Post.new(uri) req["Authorization"] = "Bearer YOUR_API_KEY" req["Content-Type"] = "application/json" req.body = '{ "to": "+15550001234", "message": "Hello from COALS!" }' res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) } data = JSON.parse(res.body)
// Using fetch (Node 18+) const response = await fetch("https://coals.ai/api/v1/simcoal/send", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json" }, body: JSON.stringify({ "to": "+15550001234", "message": "Hello from COALS!" }) }); const data = await response.json();
Scopes
When creating a key you select which scopes it is granted. A key will be rejected with 403 Forbidden if it attempts to call an endpoint outside its granted scopes.
SimCoal — SMS
simcoal:send
Send a single SMS message
simcoal:bulk
Send SMS to multiple recipients in one request
simcoal:read
Read delivery logs and account stats
ConvertaCoal — Files
convertacoal:convert
Submit a file conversion job
convertacoal:read
Read conversion logs and download converted files
GraphiCoal — Images
graphicoal:generate
Generate a new image from a text prompt
graphicoal:edit
Edit or inpaint an existing image
graphicoal:analyze
Analyze or describe an image
graphicoal:convert
Convert a raster image to SVG
graphicoal:read
Read generation history and gallery
graphicoal:delete
Delete images from your gallery
MagiCoal — Video
magicoal:generate
Submit image-to-video or text-to-video generation jobs
magicoal:read
Poll job status and read video history
Invalid or Missing Key
When a key is missing, malformed, revoked, or does not exist, the API returns 401 Unauthorized.
Response — 401
{
"success": false,
"error": {
"code": "UNAUTHORIZED",
"message": "Invalid or missing API key."
}
}
Rate limit headers on every response
Every API response includes X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers so you can monitor consumption in real time. See the Rate Limits page for details.