Newsletter
Contributor? to access more tools

API Reference

v1

The Aroma Phyto Studio API provides programmatic access to data. All endpoints use the base URL https://aroma-phyto-studio.com/api/v1.

Authentication

All endpoints except /resolve require an API key. Pass it in the API-Key header with every request.

Generate and manage your keys at API Keys.

Header Value
API-Key aps_{role}_...

API keys use the format: aps_{role}_ followed by 56 hexadecimal characters. The role prefix indicates the access level: dbm (database manager) or view (viewer).

If your key has been disabled or revoked by an administrator, or your account has been suspended, the API returns 403 with a machine-readable code field (key_disabled, key_revoked, or account_suspended) instead of 401.

Example request
curl -H "API-Key: aps_view_a1b2c3..." \
  https://aroma-phyto-studio.com/api/v1/species
Error: missing or invalid key (401)
{
  "error": "Unauthorized",
  "message": "Invalid or missing API key"
}
Error: key disabled (403)
{
  "error": "Forbidden",
  "message": "API key is disabled",
  "code": "key_disabled"
}
Error: key revoked (403)
{
  "error": "Forbidden",
  "message": "API key has been revoked",
  "code": "key_revoked"
}
Error: account suspended (403)
{
  "error": "Forbidden",
  "message": "Account is suspended",
  "code": "account_suspended"
}

Rate Limits

All authenticated requests are rate-limited to 60 requests per minute per API key. Rate limit status is returned in response headers.

Header Description
X-RateLimit-Limit Maximum requests per minute.
X-RateLimit-Remaining Requests remaining in current window.
X-RateLimit-Reset Unix timestamp when the window resets.
Retry-After Seconds to wait (only present when limit exceeded).
Rate limit exceeded (429)
{
  "error": "Rate limit exceeded. Maximum 60 requests per minute. Try again in 43 seconds."
}

Errors

The API uses standard HTTP status codes. Errors return a JSON object with an error field.

Status Meaning
200 OK
201 Created
400 Bad Request — invalid input or missing fields.
401 Unauthorized — missing or invalid API key.
403 Forbidden — insufficient permissions, API key disabled/revoked, or account suspended.
404 Not Found.
405 Method Not Allowed.
409 Conflict — duplicate resource.
422 Unprocessable Entity — semantic error.
429 Too Many Requests — rate limit exceeded.
500 Internal Server Error.
Error response format
{
  "error": "Species not found",
  "status": 404
}
Forbidden — insufficient permissions (403)
{
  "error": "Forbidden: You do not have permission to access this resource",
  "status": 403
}
Key disabled (403)
{
  "error": "Forbidden",
  "message": "API key is disabled",
  "code": "key_disabled"
}
Account suspended (403)
{
  "error": "Forbidden",
  "message": "Account is suspended",
  "code": "account_suspended"
}

Resolve

Resolve any APS-ID to its entity data, canonical URL, and localized URLs. This is the only public endpoint — no API key required.

GET /resolve/{aps_id} #

Resolve an APS-ID

Resolve any APS-ID (species, extract, molecule...) to full entity data, metadata summary, canonical and localized URLs.

Access: Public — no API key required

Parameters

Name Type In Description
aps_id required string path APS identifier. Format: APS-{LETTER}{6 digits}{check digit}. Example: APS-M0000785
locale string query Locale for canonical URL. Supported: en_US, fr_FR, nl_BE.
Default: en_US

Responses

200 APS-ID resolved successfully.
Field Type Description
status string "success"
aps_id string The resolved APS-ID.
entity_type string Entity type: species, molecule, extract, genus, blend, publication, brand, product, isomer.
canonical_url string Canonical URL for the entity.
localized_urls object Locale-keyed URLs (en_US, fr_FR, nl_BE).
metadata object Basic entity metadata (varies by entity type).
schema_org string Schema.org fragment URL.
400 Invalid APS-ID format.
404 APS-ID not found.
422 Check digit validation failed.
cURL
curl https://aroma-phyto-studio.com/api/v1/resolve/APS-S0000123
Response
{
  "status": "success",
  "aps_id": "APS-S0000123",
  "entity_type": "species",
  "canonical_url": "https://aroma-phyto-studio.com/studio/species/lavandula-angustifolia/",
  "localized_urls": {
    "en_US": "https://aroma-phyto-studio.com/studio/species/lavandula-angustifolia/",
    "fr_FR": "https://aroma-phyto-studio.com/studio/fr/species/lavandula-angustifolia/",
    "nl_BE": "https://aroma-phyto-studio.com/studio/nl/species/lavandula-angustifolia/"
  },
  "metadata": {
    "name": "Lavandula angustifolia",
    "common_name": "Common Lavender",
    "genus": "Lavandula",
    "family": "Lamiaceae"
  },
  "schema_org": "https://aroma-phyto-studio.com/studio/species/lavandula-angustifolia/#species"
}
POST /resolve #

Bulk resolve APS-IDs

Resolve multiple APS-IDs in a single request. Maximum 50 IDs per request. Public — no API key required.

Access: Public — no API key required

Parameters

Name Type In Description
aps_ids required array body Array of APS-ID strings to resolve.
locale string query Locale for canonical URLs. Supported: en_US, fr_FR, nl_BE.
Default: en_US

Responses

200 Bulk resolve completed.
Field Type Description
results object APS-ID keyed object of resolved entities.
resolved integer Number of successfully resolved IDs.
not_found array APS-IDs that were not found.
invalid array APS-IDs with invalid format or check digit.
400 Invalid request (missing aps_ids, empty array, or exceeds limit).
cURL
curl -X POST https://aroma-phyto-studio.com/api/v1/resolve \
  -H "Content-Type: application/json" \
  -d '{"aps_ids": ["APS-S0000123", "APS-E0000594"]}'
Response
{
  "results": {
    "APS-S0000123": {
      "status": "success",
      "aps_id": "APS-S0000123",
      "entity_type": "species",
      "canonical_url": "https://aroma-phyto-studio.com/studio/species/lavandula-angustifolia/",
      "metadata": { "name": "Lavandula angustifolia" }
    },
    "APS-E0000594": {
      "status": "success",
      "aps_id": "APS-E0000594",
      "entity_type": "extract",
      "canonical_url": "https://aroma-phyto-studio.com/studio/extract/he-lavandula-angustifolia/",
      "metadata": { "name": "Lavandula angustifolia essential oil" }
    }
  },
  "resolved": 2,
  "not_found": [],
  "invalid": []
}

Families

Botanical families (e.g. Lamiaceae, Apiaceae). Read-only.

GET /families #

List all families

Retrieve a paginated list of botanical families with genus count and optional text search.

Access: Authenticated — all roles

Parameters

Name Type In Description
lang string query Language code for translations (e.g. en_US, fr_FR).
q string query Text search (min 2 chars). Matches family name. Searching "alpha" also matches "α" and vice versa.
page integer query Page number (1-based).
Default: 1
per_page integer query Items per page (max 100).
Default: 25

Responses

200 Families list retrieved.
Field Type Description
families array Array of family objects.
language string Active language code.
count integer Number of items in this page.
pagination object Pagination metadata (page, per_page, total, total_pages).
401 Missing or invalid API key.
cURL
curl -H "API-Key: YOUR_API_KEY" \
  https://aroma-phyto-studio.com/api/v1/families?lang=en_US
Response
{
  "families": [
    {
      "family_id": 3,
      "family_name": "Lamiaceae",
      "display_order": 0,
      "data_source": "POWO",
      "created_at": "2025-01-10T08:15:00Z",
      "updated_at": "2025-02-18T11:30:00Z",
      "notes": null,
      "genus_count": 12
    }
  ],
  "language": "en_US",
  "count": 1,
  "pagination": {
    "page": 1,
    "per_page": 25,
    "total": 48,
    "total_pages": 2
  }
}
GET /families/{id} #

Get a family

Retrieve a single family by its numeric ID, including genus count.

Access: Authenticated — all roles

Parameters

Name Type In Description
id required integer path Family ID.
lang string query Language code for translations.

Responses

200 Family retrieved.
Field Type Description
family object Family object.
language string Active language code.
404 Family not found.
cURL
curl -H "API-Key: YOUR_API_KEY" \
  https://aroma-phyto-studio.com/api/v1/families/3
Response
{
  "family": {
    "family_id": 3,
    "family_name": "Lamiaceae",
    "display_order": 0,
    "data_source": "POWO",
    "created_at": "2025-01-10T08:15:00Z",
    "updated_at": "2025-02-18T11:30:00Z",
    "notes": null,
    "genus_count": 12
  },
  "language": "en_US"
}

Genera

Botanical genera with family relationship and species count. Read-only.

GET /genera #

List all genera

Retrieve a paginated list of genera with optional family filtering and text search.

Access: Authenticated ��� all roles

Parameters

Name Type In Description
lang string query Language code for translations (e.g. en_US, fr_FR).
family_id integer query Filter by family ID.
q string query Text search (min 2 chars). Matches genus name and APS-ID. Searching "alpha" also matches "α" and vice versa.
page integer query Page number (1-based).
Default: 1
per_page integer query Items per page (max 100).
Default: 25

Responses

200 Genera list retrieved.
Field Type Description
genera array Array of genus objects.
language string Active language code.
count integer Number of items in this page.
pagination object Pagination metadata (page, per_page, total, total_pages).
401 Missing or invalid API key.
cURL
curl -H "API-Key: YOUR_API_KEY" \
  https://aroma-phyto-studio.com/api/v1/genera?family_id=3&lang=en_US
Response
{
  "genera": [
    {
      "genus_id": 5,
      "aps_id": "APS-G0000054",
      "family_id": 3,
      "genus_name": "Lavandula",
      "display_order": 0,
      "data_source": "POWO",
      "created_at": "2025-01-10T08:15:00Z",
      "updated_at": "2025-02-18T11:30:00Z",
      "notes": null,
      "family_name": "Lamiaceae",
      "species_count": 8
    }
  ],
  "language": "en_US",
  "count": 1,
  "pagination": {
    "page": 1,
    "per_page": 25,
    "total": 120,
    "total_pages": 5
  }
}
GET /genera/{id} #

Get a genus

Retrieve a single genus by its numeric ID, including family name and species count.

Access: Authenticated — all roles

Parameters

Name Type In Description
id required integer path Genus ID.
lang string query Language code for translations.

Responses

200 Genus retrieved.
Field Type Description
genus object Genus object.
language string Active language code.
404 Genus not found.
cURL
curl -H "API-Key: YOUR_API_KEY" \
  https://aroma-phyto-studio.com/api/v1/genera/5
Response
{
  "genus": {
    "genus_id": 5,
    "aps_id": "APS-G0000054",
    "family_id": 3,
    "genus_name": "Lavandula",
    "display_order": 0,
    "data_source": "POWO",
    "created_at": "2025-01-10T08:15:00Z",
    "updated_at": "2025-02-18T11:30:00Z",
    "notes": null,
    "family_name": "Lamiaceae",
    "species_count": 8
  },
  "language": "en_US"
}

Species

Botanical species with genus and family relationships. Read-only.

GET /species #

List all species

Retrieve a paginated list of species with optional genus and family filtering.

Access: Authenticated — all roles

Parameters

Name Type In Description
lang string query Language code for translations (e.g. en_US, fr_FR).
genus_id integer query Filter by genus ID.
family_id integer query Filter by family ID.
aps_id string query Filter by exact APS-ID (e.g. APS-S0000123).
q string query Text search (min 2 chars). Matches species name, genus name, common name, and APS-ID. Searching "alpha" also matches "α" and vice versa.
page integer query Page number (1-based).
Default: 1
per_page integer query Items per page (max 100).
Default: 25

Responses

200 Species list retrieved.
Field Type Description
species array Array of species objects.
language string Active language code.
count integer Number of items in this page.
pagination object Pagination metadata (page, per_page, total, total_pages).
401 Missing or invalid API key.
cURL
curl -H "API-Key: YOUR_API_KEY" \
  https://aroma-phyto-studio.com/api/v1/species?lang=en_US&per_page=10
Response
{
  "species": [
    {
      "species_id": 42,
      "genus_id": 5,
      "species_name": "Lavandula angustifolia",
      "aps_id": "APS-S0000123",
      "display_order": 0,
      "created_at": "2025-01-10T08:15:00Z",
      "updated_at": "2025-02-18T11:30:00Z",
      "genus_name": "Lavandula",
      "family_id": 3,
      "family_name": "Lamiaceae"
    }
  ],
  "language": "en_US",
  "count": 1,
  "pagination": {
    "page": 1,
    "per_page": 10,
    "total": 342,
    "total_pages": 35
  }
}
GET /species/{id} #

Get a species

Retrieve a single species by its numeric ID.

Access: Authenticated — all roles

Parameters

Name Type In Description
id required integer path Species ID.
lang string query Language code for translations.

Responses

200 Species retrieved.
Field Type Description
species object Species object.
language string Active language code.
404 Species not found.
cURL
curl -H "API-Key: YOUR_API_KEY" \
  https://aroma-phyto-studio.com/api/v1/species/42
Response
{
  "species": {
    "species_id": 42,
    "genus_id": 5,
    "species_name": "Lavandula angustifolia",
    "aps_id": "APS-S0000123",
    "display_order": 0,
    "created_at": "2025-01-10T08:15:00Z",
    "updated_at": "2025-02-18T11:30:00Z",
    "genus_name": "Lavandula",
    "family_id": 3,
    "family_name": "Lamiaceae"
  },
  "language": "en_US"
}

Extracts

Plant extracts (essential oils, hydrosols, etc.) with species, plant part, and chemotype relationships. Read-only.

GET /extracts #

List all extracts

Retrieve a paginated list of extracts with optional filtering by species, genus, plant part, chemotype, extract type, or olfactory family.

Access: Authenticated — all roles

Parameters

Name Type In Description
lang string query Language code for translations.
species_id integer query Filter by species ID.
genus_id integer query Filter by genus ID.
family_id integer query Filter by family ID.
aps_id string query Filter by exact APS-ID (e.g. APS-E0000594).
plant_part_id integer query Filter by plant part ID.
chemotype_id integer query Filter by chemotype ID.
extract_type_id integer query Filter by extract type ID.
olfactory_family_id integer query Filter by olfactory family ID.
q string query Text search (min 2 chars). Matches extract name, species name, genus name, and APS-ID. Searching "alpha" also matches "α" and vice versa.
page integer query Page number.
Default: 1
per_page integer query Items per page (max 100).
Default: 25

Responses

200 Extracts list retrieved.
Field Type Description
extracts array Array of extract objects.
language string Active language code.
count integer Number of items in this page.
pagination object Pagination metadata.
401 Missing or invalid API key.
cURL
curl -H "API-Key: YOUR_API_KEY" \
  https://aroma-phyto-studio.com/api/v1/extracts?plant_part_id=1&per_page=10
Response
{
  "extracts": [
    {
      "extract_id": 15,
      "aps_id": "APS-E0000047",
      "species_id": 42,
      "chemotype_id": 3,
      "plant_part_id": 1,
      "extract_type_id": 2,
      "olfactory_family_id": 4,
      "rating": 8.5,
      "display_order": 0,
      "created_at": "2025-01-05T09:20:00Z",
      "updated_at": "2025-02-16T13:45:00Z",
      "common_extract_name": "Lavender Essential Oil",
      "species_name": "Lavandula angustifolia",
      "genus_id": 5,
      "genus_name": "Lavandula",
      "family_id": 3,
      "family_name": "Lamiaceae",
      "chemotype_name": "Linalyl Acetate",
      "plant_part_name": "Flower",
      "extract_type_name": "Essential Oil",
      "extract_type_short_name": "EO",
      "olfactory_family_name": "Herbaceous"
    }
  ],
  "language": "en_US",
  "count": 1,
  "pagination": {
    "page": 1,
    "per_page": 10,
    "total": 287,
    "total_pages": 29
  }
}
GET /extracts/{id} #

Get an extract

Retrieve a single extract by its numeric ID.

Access: Authenticated — all roles

Parameters

Name Type In Description
id required integer path Extract ID.
lang string query Language code for translations.

Responses

200 Extract retrieved.
Field Type Description
extract object Extract object.
language string Active language code.
404 Extract not found.
cURL
curl -H "API-Key: YOUR_API_KEY" \
  https://aroma-phyto-studio.com/api/v1/extracts/15
Response
{
  "extract": {
    "extract_id": 15,
    "aps_id": "APS-E0000047",
    "species_id": 42,
    "chemotype_id": 3,
    "plant_part_id": 1,
    "extract_type_id": 2,
    "olfactory_family_id": 4,
    "rating": 8.5,
    "common_extract_name": "Lavender Essential Oil",
    "species_name": "Lavandula angustifolia",
    "genus_name": "Lavandula",
    "family_name": "Lamiaceae",
    "chemotype_name": "Linalyl Acetate",
    "plant_part_name": "Flower",
    "extract_type_name": "Essential Oil",
    "extract_type_short_name": "EO",
    "olfactory_family_name": "Herbaceous"
  },
  "language": "en_US"
}

Languages

Available languages for i18n translations. Read-only.

GET /languages #

List all languages

Retrieve all languages. Optionally filter by active status.

Access: Authenticated — all roles

Parameters

Name Type In Description
active boolean query Filter by active status (1 or true for active only).

Responses

200 Languages list retrieved.
Field Type Description
languages array Array of language objects.
count integer Number of languages.
cURL
curl -H "API-Key: YOUR_API_KEY" \
  https://aroma-phyto-studio.com/api/v1/languages?active=1
Response
{
  "languages": [
    {
      "language_code": "en_US",
      "language_name": "English (United States)",
      "is_default": true,
      "active": true,
      "display_order": 0,
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-02-20T14:22:00Z"
    },
    {
      "language_code": "fr_FR",
      "language_name": "French (France)",
      "is_default": false,
      "active": true,
      "display_order": 1,
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-02-20T14:22:00Z"
    }
  ],
  "count": 2
}
GET /languages/{code} #

Get a language

Retrieve a single language by its language code.

Access: Authenticated — all roles

Parameters

Name Type In Description
code required string path Language code (e.g. en_US, fr_FR).

Responses

200 Language retrieved.
Field Type Description
language object Language object.
404 Language not found.
cURL
curl -H "API-Key: YOUR_API_KEY" \
  https://aroma-phyto-studio.com/api/v1/languages/en_US
Response
{
  "language": {
    "language_code": "en_US",
    "language_name": "English (United States)",
    "is_default": true,
    "active": true,
    "display_order": 0,
    "created_at": "2025-01-15T10:30:00Z",
    "updated_at": "2025-02-20T14:22:00Z"
  }
}

Plant Parts

Reference data: plant parts used in extracts (e.g. Flower, Leaf, Root). Read-only.

GET /plant-parts #

List all plant parts

Retrieve all plant parts with optional language translation.

Access: Authenticated — all roles

Parameters

Name Type In Description
lang string query Language code for translations.

Responses

200 Plant parts list retrieved.
Field Type Description
plant_parts array Array of plant part objects.
language string Active language code.
count integer Number of items.
cURL
curl -H "API-Key: YOUR_API_KEY" \
  https://aroma-phyto-studio.com/api/v1/plant-parts
Response
{
  "plant_parts": [
    {
      "plant_part_id": 1,
      "display_order": 0,
      "created_at": "2025-01-01T00:00:00Z",
      "updated_at": "2025-01-01T00:00:00Z",
      "plant_part_name": "Flower"
    },
    {
      "plant_part_id": 2,
      "display_order": 1,
      "created_at": "2025-01-01T00:00:00Z",
      "updated_at": "2025-01-01T00:00:00Z",
      "plant_part_name": "Leaf"
    }
  ],
  "language": "en_US",
  "count": 2
}
GET /plant-parts/{id} #

Get a plant part

Retrieve a single plant part by ID.

Access: Authenticated — all roles

Parameters

Name Type In Description
id required integer path Plant part ID.
lang string query Language code for translations.

Responses

200 Plant part retrieved.
Field Type Description
plant_part object Plant part object.
language string Active language code.
404 Plant part not found.
cURL
curl -H "API-Key: YOUR_API_KEY" \
  https://aroma-phyto-studio.com/api/v1/plant-parts/1
Response
{
  "plant_part": {
    "plant_part_id": 1,
    "display_order": 0,
    "created_at": "2025-01-01T00:00:00Z",
    "updated_at": "2025-01-01T00:00:00Z",
    "plant_part_name": "Flower"
  },
  "language": "en_US"
}

Chemotypes

Reference data: chemotype classifications for extracts. Read-only.

GET /chemotypes #

List all chemotypes

Access: Authenticated — all roles

Parameters

Name Type In Description
lang string query Language code for translations.

Responses

200 Chemotypes list retrieved.
Field Type Description
chemotypes array Array of chemotype objects.
language string Active language code.
count integer Number of items.
cURL
curl -H "API-Key: YOUR_API_KEY" \
  https://aroma-phyto-studio.com/api/v1/chemotypes
Response
{
  "chemotypes": [
    {
      "chemotype_id": 1,
      "display_order": 0,
      "created_at": "2025-01-01T00:00:00Z",
      "updated_at": "2025-01-01T00:00:00Z",
      "chemotype_name": "Linalool"
    }
  ],
  "language": "en_US",
  "count": 1
}
GET /chemotypes/{id} #

Get a chemotype

Access: Authenticated — all roles

Parameters

Name Type In Description
id required integer path Chemotype ID.
lang string query Language code for translations.

Responses

200 Chemotype retrieved.
404 Chemotype not found.
cURL
curl -H "API-Key: YOUR_API_KEY" \
  https://aroma-phyto-studio.com/api/v1/chemotypes/1
Response
{
  "chemotype": {
    "chemotype_id": 1,
    "display_order": 0,
    "created_at": "2025-01-01T00:00:00Z",
    "updated_at": "2025-01-01T00:00:00Z",
    "chemotype_name": "Linalool"
  },
  "language": "en_US"
}

Extract Types

Reference data: types of plant extracts (Essential Oil, Hydrosol, etc.). Read-only.

GET /extract-types #

List all extract types

Access: Authenticated — all roles

Parameters

Name Type In Description
lang string query Language code for translations.

Responses

200 Extract types list retrieved.
Field Type Description
extract_types array Array of extract type objects.
language string Active language code.
count integer Number of items.
cURL
curl -H "API-Key: YOUR_API_KEY" \
  https://aroma-phyto-studio.com/api/v1/extract-types
Response
{
  "extract_types": [
    {
      "extract_type_id": 1,
      "is_carrier_oil": false,
      "is_default": true,
      "iso_reference": null,
      "display_order": 0,
      "extract_type_name": "Essential Oil",
      "extract_type_short_name": "EO"
    }
  ],
  "language": "en_US",
  "count": 1
}
GET /extract-types/{id} #

Get an extract type

Access: Authenticated — all roles

Parameters

Name Type In Description
id required integer path Extract type ID.
lang string query Language code for translations.

Responses

200 Extract type retrieved.
404 Extract type not found.
cURL
curl -H "API-Key: YOUR_API_KEY" \
  https://aroma-phyto-studio.com/api/v1/extract-types/1
Response
{
  "extract_type": {
    "extract_type_id": 1,
    "is_carrier_oil": false,
    "is_default": true,
    "iso_reference": null,
    "display_order": 0,
    "extract_type_name": "Essential Oil",
    "extract_type_short_name": "EO"
  },
  "language": "en_US"
}

Olfactory Families

Reference data: olfactory family classifications for extracts. Read-only.

GET /olfactory-families #

List all olfactory families

Access: Authenticated — all roles

Parameters

Name Type In Description
lang string query Language code for translations.

Responses

200 Olfactory families list retrieved.
Field Type Description
olfactory_families array Array of olfactory family objects.
language string Active language code.
count integer Number of items.
cURL
curl -H "API-Key: YOUR_API_KEY" \
  https://aroma-phyto-studio.com/api/v1/olfactory-families
Response
{
  "olfactory_families": [
    {
      "olfactory_family_id": 1,
      "display_order": 0,
      "family_name": "Herbaceous"
    }
  ],
  "language": "en_US",
  "count": 1
}
GET /olfactory-families/{id} #

Get an olfactory family

Access: Authenticated — all roles

Parameters

Name Type In Description
id required integer path Olfactory family ID.
lang string query Language code for translations.

Responses

200 Olfactory family retrieved.
404 Olfactory family not found.
cURL
curl -H "API-Key: YOUR_API_KEY" \
  https://aroma-phyto-studio.com/api/v1/olfactory-families/1
Response
{
  "olfactory_family": {
    "olfactory_family_id": 1,
    "display_order": 0,
    "family_name": "Herbaceous"
  },
  "language": "en_US"
}