Loading...

Introduction

This API reference describes the REST API you can use to detect and identify wildlife in images. The API accepts image uploads via HTTP and returns detection results with bounding boxes, confidence scores, and taxonomic classification.


Authentication

The Animal Detect API uses API keys for authentication. Create and manage API keys in your account settings.

Remember that your API key is a secret! Do not share it with others or expose it in client-side code (browsers, apps). API keys should be securely loaded from an environment variable or key management service on the server.

API keys should be provided via HTTP Bearer authentication.

Authorization: Bearer ANIMAL_DETECT_API_KEY

Detect Animals

POST https://www.animaldetect.com/api/v1/detect

Analyzes an image for wildlife presence. Returns bounding boxes, confidence scores, species labels, and taxonomic classification for each detected animal.

Request body

ParameterTypeRequiredDescription
imagefile or stringRequiredImage file (JPG, PNG, WebP, BMP) or base64-encoded string. Maximum 5MB.
countrystringOptionalISO Alpha-2/3 country code or full name. Improves species identification accuracy.
thresholdnumberOptionalConfidence threshold between 0.01 and 0.99. Defaults to 0.2.

The API accepts multipart/form-data for file uploads or application/json with base64-encoded images.

Example request

curl -X POST "https://www.animaldetect.com/api/v1/detect" \
  -H "Authorization: Bearer YOUR_API_KEY_HERE" \
  -F "image=@/path/to/wildlife_image.jpg" \
  -F "country=USA" \
  -F "threshold=0.2"
import requests

files = {'image': ('wildlife1.jpg', open('wildlife1.jpg', 'rb'), 'image/jpeg')}
data = {}
# Optional parameters
# data['country'] = 'USA'   # OPTIONAL: Country code or name
# data['threshold'] = '0.5' # OPTIONAL: Confidence threshold (0.01-0.99)
headers = {
    'Authorization': 'Bearer YOUR_API_KEY_HERE'
}

response = requests.post('https://www.animaldetect.com/api/v1/detect', 
                        files=files, data=data, headers=headers)
result = response.json()
print(result)
import fs from 'fs'
import path from 'path'
import FormData from 'form-data'
import fetch from 'node-fetch'
import { fileURLToPath } from 'url'

const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)

const imagePath = path.join(__dirname, 'wildlife1.jpg')

const formData = new FormData()
formData.append('image', fs.createReadStream(imagePath))

// Optional parameters
// formData.append('country', 'USA') // OPTIONAL: Country code or name
// formData.append('threshold', '0.2') // OPTIONAL: Confidence threshold (0.01-0.99)

const response = await fetch('https://www.animaldetect.com/api/v1/detect', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY_HERE',
    ...formData.getHeaders()
  },
  body: formData
})

const result = await response.json()
console.log(JSON.stringify(result, null, 2)) // pretty print the result
import Foundation

// ============================================================================
// CONFIGURATION - Update these values for your use case
// ============================================================================

let apiKey = "YOUR_API_KEY_HERE"
let apiUrl = "https://www.animaldetect.com/api/v1/detect"

// Image file path (relative to script location)
let imageFileName = "wildlife1.jpg"

// OPTIONAL parameters (uncomment to use)
let country: String? = nil  // e.g., "USA" or nil
let threshold: String? = nil  // e.g., "0.2" (0.01-0.99) or nil

func appendFormField(to body: inout Data, boundary: String, name: String, value: String) {
    body.append("--\(boundary)\r\n".data(using: .utf8)!)
    body.append("Content-Disposition: form-data; name=\"\(name)\"\r\n\r\n".data(using: .utf8)!)
    body.append(value.data(using: .utf8)!)
    body.append("\r\n".data(using: .utf8)!)
}

func appendImageFile(to body: inout Data, boundary: String, imageData: Data, filename: String) {
    body.append("--\(boundary)\r\n".data(using: .utf8)!)
    body.append("Content-Disposition: form-data; name=\"image\"; filename=\"\(filename)\"\r\n".data(using: .utf8)!)
    body.append("Content-Type: image/jpeg\r\n\r\n".data(using: .utf8)!)
    body.append(imageData)
    body.append("\r\n".data(using: .utf8)!)
}

// Setup request
let url = URL(string: apiUrl)!
var request = URLRequest(url: url)
request.httpMethod = "POST"

let boundary = UUID().uuidString
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")

// Build multipart form data body
var body = Data()

// Get image file path
let scriptPath = URL(fileURLWithPath: #file).deletingLastPathComponent()
let imagePath = scriptPath.appendingPathComponent(imageFileName)

// Add required image file
if let imageData = try? Data(contentsOf: imagePath) {
    appendImageFile(to: &body, boundary: boundary, imageData: imageData, filename: imageFileName)
} else {
    print("Error: Could not load image file at \(imagePath.path)")
    exit(1)
}

// Add optional parameters
if let country = country {
    appendFormField(to: &body, boundary: boundary, name: "country", value: country)
}

if let threshold = threshold {
    appendFormField(to: &body, boundary: boundary, name: "threshold", value: threshold)
}

// Close multipart body
body.append("--\(boundary)--\r\n".data(using: .utf8)!)

request.httpBody = body

// Send request and wait for response
let semaphore = DispatchSemaphore(value: 0)
var resultData: Data?
var resultError: Error?

let task = URLSession.shared.dataTask(with: request) { data, response, error in
    if let error = error {
        resultError = error
        semaphore.signal()
        return
    }
    resultData = data
    semaphore.signal()
}

task.resume()
semaphore.wait()

// Handle response
if let error = resultError {
    print("Error: \(error)")
    exit(1)
}

guard let data = resultData,
      let json = try? JSONSerialization.jsonObject(with: data, options: []),
      let jsonData = try? JSONSerialization.data(withJSONObject: json, options: .prettyPrinted),
      let jsonString = String(data: jsonData, encoding: .utf8) else {
    print("Error: Failed to parse JSON response")
    exit(1)
}

print(jsonString) // pretty print the result

Example response

Returns a JSON object with annotations (detected animals) and info (processing metadata).

{
  "annotations": [
    {
      "id": 0,
      "bbox": [0.4127, 0.8261, 0.2027, 0.1727],
      "score": 0.9975,
      "label": "canine family",
      "taxonomy": {
        "id": "3184697f-51ad-4608-9a28-9edb5500159c",
        "class": "mammalia",
        "order": "carnivora",
        "family": "canidae",
        "genus": "",
        "species": ""
      }
    }
  ],
  "info": {
    "processing_time_ms": 123,
    "model_version": "v1.0",
    "country_processed": "USA",
    "threshold_applied": 0.2
  }
}

annotations

Array of detected animals. Empty if no animals found.

FieldTypeDescription
idintegerSequential detection ID starting from 0
bboxarrayBounding box [x, y, width, height] normalized to 0–1
scorenumberDetection confidence between 0 and 1
labelstringHuman-readable species or family name
taxonomyobjectFull taxonomic classification (class, order, family, genus, species)

info

Processing metadata.

FieldTypeDescription
processing_time_msintegerProcessing time in milliseconds
model_versionstringAI model version used for detection
country_processedstringNormalized country code that was applied
threshold_appliednumberConfidence threshold that was applied

Error Codes

API errors return a JSON object with an error message and code identifier.

HTTP StatusError CodeDescription
200Request successful
400INVALID_INPUTInvalid request parameters or image format
401INVALID_KEY_FORMATMissing or malformed API key
401KEY_NOT_FOUNDAPI key does not exist
401KEY_REVOKEDAPI key has been revoked
402QUOTA_EXCEEDEDData quota exhausted
413FILE_TOO_LARGEImage exceeds 5MB limit
429RATE_LIMITEDRate limit exceeded
500INTERNAL_ERRORInternal server error

Rate Limits

API usage is governed by your subscription plan. Each plan includes a data volume quota measured in gigabytes. When quota is exceeded, requests return 402.

Rate limiting is applied per API key. If you receive 429, implement exponential backoff in your retry logic.

For API support, contact support@animaldetect.com.