MyMolecules Docs

Core API

Decode API

Available

Decode turns everyday food input into structured food items, normalized gram quantities and one molecular total per compound for the whole meal. It is the base layer for products that need to understand what a person ate beyond calories and macros.

Endpoint

POST/functions/v1/decode

Contract

Send mymolecules-api-version with 2026-07-10 to use the documented response contract.

{
  "data": {},
  "meta": {
    "request_id": "req_...",
    "api_version": "2026-07-10"
  }
}

Headers

Request

  • x-api-key required - Server-side API key for your integration.
  • mymolecules-api-version required 2026-07-10 - Use the latest stable API version: 2026-07-10.
  • Content-Type required application/json - Required for JSON request bodies.

Response

  • x-request-id required - Request identifier. Log this value when contacting support.
  • mymolecules-api-version required 2026-07-10 - The API contract version used for the response.
  • x-quota-limit optional - Monthly quota limit for the current API key.
  • x-quota-remaining optional - Unreserved monthly quota remaining.
  • x-quota-reset optional - Timestamp when the monthly quota resets.
  • x-operational-ratelimit-limit optional - Current operational rate limit when available.
  • x-operational-ratelimit-remaining optional - Remaining operational requests when available.
  • retry-after optional - Seconds to wait before retrying, only when the server provides a meaningful delay.

Inputs

  • Required input_mode: unstructured or structured
  • Unstructured input with foodText, foodImage, foodVoice, foodImageRemaining or attachments; media fields accept data URLs or HTTP(S) URLs
  • Structured input with 1–25 items; each item requires canonical_name, a positive numeric quantity and unit (mg, g or kg). brand and attributes are optional.

Returns

  • 202 queued response with job_id and status_url
  • Status response with queued, processing, completed or failed
  • Completed food_detected result with normalized items and meal-wide molecular totals
  • Completed no_food_detected result with an empty items array when the input contains no food

Async pattern

Create the job with POST, then poll the same endpoint with job_id until the status is completed or failed.

  • Poll parameter: job_id
  • Status values: queued, processing, completed, failed

Error codes

  • missing_api_key
  • invalid_api_key
  • scope_not_allowed
  • quota_exceeded
  • rate_limited
  • invalid_json
  • invalid_request
  • method_not_allowed
  • unsupported_api_version
  • job_not_found
  • backlog_high
  • service_unavailable
  • internal_error
  • input_too_large
  • invalid_compound_identifier
  • compound_not_allowed_for_decode_scope
  • decode_input_mode_not_allowed
  • decode_scope_not_configured
  • structured_items_limit_exceeded
  • food_name_too_long
  • food_attributes_limit_exceeded
  • food_attribute_too_long
  • invalid_food_quantity
  • food_quantity_exceeded
  • food_text_too_long
  • attachments_limit_exceeded
  • image_inputs_limit_exceeded
  • audio_inputs_limit_exceeded
  • unsupported_attachment_type
  • image_too_large
  • audio_too_large
  • inline_media_total_exceeded
  • media_total_exceeded
  • audio_duration_exceeded
  • audio_duration_unavailable

Request details

  • Use exactly one input mode. Structured requests use items; unstructured requests use food text, images, voice or attachments.
  • Structured items are not rewritten by the language model. Output item_id values are 1-based request-local positions; quantity_g is the normalized amount in grams.
  • Describe textual remaining information in foodText. Use foodImageRemaining only for a separate photo of what remained.
  • Decode derives the output tier from the API key. Do not send decode_profile. Send input_mode as structured or unstructured; the key must permit that mode.
  • The edge:decode scope grants access to Decode. Each key has one content tier: macros returns classified macros, micros includes macros and classified micros, and molecular permits any existing compound identifier. A permitted compound is returned only when the selected food or its evidence donors provide evidence for it.
  • Optional compound_identifier_ids (positive integers or numeric strings) and compound_identifier_names (exact, case-sensitive catalog names) narrow the result. Both arrays are combined and deduplicated; an empty array does not filter. If your key also has access to Decode Compound ID, use it to resolve a name before filtering.
  • Without a filter, the lower tiers use their complete configured classification; Molecular uses all available direct and donor evidence. A filter never expands the key tier.
  • foodText is limited to 1,500 characters; structured requests accept at most 25 items. Large media requests have separate size and attachment limits.

Response details

  • POST returns HTTP 202 with job_id, queued status and status_url. It does not return the completed analysis. Poll GET /functions/v1/decode?job_id=... with the same API key until status is completed or failed.
  • Status polling always uses HTTP 200 for a found job, including status: failed. Its job error is separate from the HTTP error envelope; result is returned when available.
  • Every completed result has type: food_detected or type: no_food_detected. No-food is a completed domain result with result.items: [] and a null job error.
  • For food_detected, each input item has status matched or unresolved. molecular_analysis contains one row per compound for the entire meal, without an item_id. If an item has no evidence for a compound or is unresolved, its contribution is assumed zero for the displayed total and that compound has incomplete: true. This is not proof of actual zero.
  • measurement_value and measurement_value_min/max refer to the whole meal, not per 100 g. Interpret each number using its matching measurement_value_type and measurement_unit; null means no numeric value or bound. Min/max describe evidence spread or valid one-sided bounds, not confidence intervals.
  • Evidence types are quantified (one source point), calculated (derived or combined value), less_than, greater_than, trace and unquantified (present without a numeric amount). Do not treat trace or unquantified as zero.
  • provenance is interpolation if any included evidence was interpolated; otherwise it is source. Aggregated confidence is always null. references, references_min and references_max contain { id, citation } for the corresponding value or bound; incomplete totals have no min/max.
  • Use include_result=false or result=none on status requests when you only need the job state.

Operational notes

  • Requires x-api-key with edge:decode, one assigned content tier and at least one allowed input mode. A key may permit structured, unstructured or both.
  • Job status is restricted to the creating API key and its current Decode permissions. After a tier downgrade or input-mode revocation, affected earlier jobs are no longer readable.
  • An input_mode not permitted for the key returns 403 decode_input_mode_not_allowed before a job is created.
  • Malformed compound filters return 400 invalid_request with details.field. Unknown compound names or IDs return 422 invalid_compound_identifier.
  • If any existing requested compound is outside the API key tier, the complete request returns 403 compound_not_allowed_for_decode_scope.
  • Macro tiers return 503 decode_scope_not_configured until their compound classification is configured. Internal scope configuration faults return only 503 service_unavailable without configuration details.
  • 429 rate_limited is an operational limit; 429 backlog_high means Decode is overloaded; 429 quota_exceeded means the monthly quota is exhausted. Follow Retry-After only when present. A quota error is not a request to retry shortly.
  • Temporary dependency failures return 503 service_unavailable; unexpected server failures return 500 internal_error. A job hidden after a key downgrade returns 404 job_not_found.
  • Decode input size and count limits have specific error codes listed below; correct the request before retrying.
  • POST usage is counted; polling does not create another job. Rate-limit headers are returned when quota data is available.
  • Large media payloads should be sent only when needed; URLs or attachments are preferable for repeated workflows.

Examples

Request JSON

{
  "input_mode": "unstructured",
  "foodText": "200 g Greek yogurt",
  "compound_identifier_ids": [12057]
}

Structured request JSON

{
  "input_mode": "structured",
  "items": [
    {
      "canonical_name": "greek yogurt",
      "brand": null,
      "attributes": [],
      "quantity": 200,
      "unit": "g"
    }
  ],
  "compound_identifier_ids": [12057]
}

Accepted POST response (HTTP 202)

{
  "data": {
    "job_id": "8a93f4a0-2222-4a10-8c93-bca31ae9d48b",
    "status": "queued",
    "status_url": "https://api.mymolecules.de/functions/v1/decode?job_id=8a93f4a0-2222-4a10-8c93-bca31ae9d48b"
  },
  "meta": {
    "request_id": "req_...",
    "api_version": "2026-07-10"
  }
}

Completed poll response (HTTP 200)

{
  "data": {
    "job_id": "8a93f4a0-2222-4a10-8c93-bca31ae9d48b",
    "status": "completed",
    "result": {
      "type": "food_detected",
      "items": [
        {
          "item_id": 1,
          "canonical_name": "greek yogurt",
          "brand": null,
          "attributes": [],
          "quantity_g": 200,
          "status": "matched"
        }
      ],
      "molecular_analysis": [
        {
          "compound_identifier_id": 12057,
          "compound_identifier_name": "protein",
          "compound_identifier_value": "CHEBI_36080",
          "measurement_value": 20000,
          "measurement_value_min": 20000,
          "measurement_value_max": 20000,
          "measurement_value_type": "quantified",
          "measurement_value_min_type": "quantified",
          "measurement_value_max_type": "quantified",
          "measurement_unit": "mg",
          "provenance": "source",
          "confidence": null,
          "incomplete": false,
          "references": [{ "id": 42, "citation": "Example food composition source" }],
          "references_min": [{ "id": 42, "citation": "Example food composition source" }],
          "references_max": [{ "id": 42, "citation": "Example food composition source" }]
        }
      ]
    },
    "error": null
  },
  "meta": {
    "request_id": "req_...",
    "api_version": "2026-07-10"
  }
}

Code examples

curl -X POST 'https://api.mymolecules.de/functions/v1/decode' \
  -H "x-api-key: $MYMOLECULES_API_KEY" \
  -H 'mymolecules-api-version: 2026-07-10' \
  -H 'Content-Type: application/json' \
  --data '{  "input_mode": "unstructured",  "foodText": "200 g Greek yogurt",  "compound_identifier_ids": [12057]}'