NutriPatrol API
NutriPatrol is the Open Food Facts moderation backend — it takes tickets and flags on products and images and exposes them to the moderation front end. Serves its own OpenAPI 3.1 document from the live host.
NutriPatrol is the Open Food Facts moderation backend — it takes tickets and flags on products and images and exposes them to the moderation front end. Serves its own OpenAPI 3.1 document from the live host.
Every API here is available over the APIs.io API and to AI agents over MCP.
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
find_apisBrowse and filter every API in the catalog.get_api_artifactsOne API's artifacts, grouped by type.get_openapiThe primary OpenAPI for this API.find_similar_apisAPIs that look like this one.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.curl "https://apis.io/api/v1/apis/open-food-facts-nutripatrol"
curl "https://apis.io/api/v1/apis?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.
{"openapi":"3.1.0","info":{"title":"nutripatrol","description":"\nThe nutripatrol API is used to report and manage issues with products and images on [Open Food Facts](https://world.openfoodfacts.org/), Open Prices, Open Pet Food Facts, Open Beauty Facts.\nWe call a report a \"**flag**\" and a report will be associated with a \"**ticket**\" if it does not exist for this product or image. Otherwise it will be associated with the existing ticket.\n\n## Flags\n\nA flag containes the following main fields:\n- `barcode`: Barcode of the product, if the flag is about a product or a product image. In case of a search issue, this field is null.\n\n- `type`: Type of the issue. It can be `product`, `image` or `search`.\n- `url`: URL of the product or of the flagged image.\n- `user_id`: Open Food Facts User ID of the flagger.\n- `source`: Source of the flag. It can be a user from the mobile app, the web or a flag generated automatically by robotoff.\n- `confidence`: Confidence score of the model that generated the flag, this field should only be provided by Robotoff.\n- `image_id`: ID of the flagged image, if the ticket type is `image`.\n- `flavor`: Flavor (project) associated with the ticket.\n- `reason`: Reason for flagging provided by the user. For images, it can be `inappropriate`, `human`, `beauty` or `other`\n\n`image_to_delete_spam` or `image_to_delete_face`. For products it can be `product_to_delete`. The field is optional.\n- `comment`: Comment provided by the user during flagging. This is a free text field.\n\n## Tickets\nAutomatically created when a flag is created and no ticket exists for the product or image.\n\nA ticket containes the following main fields:\n- `barcode`: Barcode of the product, if the ticket is about a product or a product image. In case of a search issue, this field is null.\n\n- `type`: Type of the issue. It can be `product`, `image` or `search`.\n- `url`: URL of the product or of the flagged image.\n- `status`: Status of the ticket. It can be `open` or `closed`.\n- `image_id`: ID of the flagged image, if the ticket type is `image`.\n- `flavor`: Flavor (project) associated with the ticket.\n\n\n","contact":{"name":"The Open Food Facts team","url":"https://world.openfoodfacts.org/","email":"contact@openfoodfacts.org"},"license":{"name":" AGPL-3.0","url":"https://www.gnu.org/licenses/agpl-3.0.en.html"},"version":"0.1.0"},"paths":{"/":{"get":{"summary":"Main Page","operationId":"main_page__get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/robots.txt":{"get":{"summary":"Robots Txt","operationId":"robots_txt_robots_txt_get","responses":{"200":{"description":"Successful Response","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/api/v1/flags":{"get":{"summary":"Get Flags","description":"Get all flags.\n\nThis function is used to get all flags.","operationId":"get_flags_api_v1_flags_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetFlagsResponse"}}}}}},"post":{"summary":"Create Flag","description":"Create a flag for a product.\n\nThis function is used to create a flag for a product or an image.\nA flag is a request for a product or an image to be reviewed.\nA flag is associated with a ticket.\nA ticket is created if it does not exist for this product or image.\nA ticket can be associated with multiple flags.","operationId":"create_flag_api_v1_flags_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlagCreate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Flag"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/flags/{flag_id}":{"get":{"summary":"Get Flag","description":"Get a flag by ID.\n\nThis function is used to get a flag by its ID.","operationId":"get_flag_api_v1_flags__flag_id__get","parameters":[{"name":"flag_id","in":"path","required":true,"schema":{"type":"integer","title":"Flag Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Flag"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/tickets":{"get":{"summary":"Get Tickets","description":"Get all tickets.\n\nThis function is used to get all tickets with status open.","operationId":"get_tickets_api_v1_tickets_get","parameters":[{"name":"barcode","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Barcode"}},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/TicketStatus"},{"type":"null"}],"title":"Status"}},{"name":"type_","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/IssueType"},{"type":"null"}],"title":"Type "}},{"name":"reason","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"$ref":"#/components/schemas/ReasonType"}},{"type":"null"}],"title":"Reason"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","default":10,"title":"Page Size"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTicketsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/tickets/{ticket_id}":{"get":{"summary":"Get Ticket","description":"Get a ticket by ID.\n\nThis function is used to get a ticket by its ID.","operationId":"get_ticket_api_v1_tickets__ticket_id__get","parameters":[{"name":"ticket_id","in":"path","required":true,"schema":{"type":"integer","title":"Ticket Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/flags/batch":{"post":{"summary":"Get Flags By Ticket Batch","description":"Get all flags for tickets by IDs.\n\nThis function is used to get all flags for tickets by there IDs.","operationId":"get_flags_by_ticket_batch_api_v1_flags_batch_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlagsByTicketIdRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/tickets/{ticket_id}/status":{"put":{"summary":"Update Ticket Status","description":"Update the status of a ticket by ID.\n\nThis function is used to update the status of a ticket by its ID.","operationId":"update_ticket_status_api_v1_tickets__ticket_id__status_put","parameters":[{"name":"ticket_id","in":"path","required":true,"schema":{"type":"integer","title":"Ticket Id"}},{"name":"status","in":"query","required":true,"schema":{"$ref":"#/components/schemas/TicketStatus"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ticket"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/stats":{"get":{"summary":"Get Stats","description":"Get number of tickets by status for the last n days.\n\nArgs:\n n_days (int): The number of days from which to fetch ticket data.\n Default is 31 days.","operationId":"get_stats_api_v1_stats_get","parameters":[{"name":"n_days","in":"query","required":false,"schema":{"type":"integer","default":31,"title":"N Days"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/status":{"get":{"summary":"Status","description":"Health check endpoint.","operationId":"status_api_v1_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusResponse"}}}}}}}},"components":{"schemas":{"Flag":{"properties":{"barcode":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Barcode","description":"Barcode of the product, if the flag is about a product or a product image. In case of a search issue, this field is null."},"type":{"$ref":"#/components/schemas/IssueType","description":"Type of the issue"},"url":{"type":"string","title":"Url","description":"URL of the product or of the flagged image"},"user_id":{"type":"string","title":"User Id","description":"Open Food Facts User ID of the flagger"},"source":{"$ref":"#/components/schemas/SourceType","description":"Source of the flag. It can be a user from the mobile app, the web or a flag generated automatically by robotoff."},"confidence":{"anyOf":[{"type":"number","maximum":1.0,"minimum":0.0},{"type":"null"}],"title":"Confidence","description":"Confidence score of the model that generated the flag, this field should only be provided by Robotoff."},"image_id":{"anyOf":[{"type":"string","minLength":1},{"type":"null"}],"title":"Image Id","description":"ID of the flagged image","examples":["1","front_fr"]},"flavor":{"$ref":"#/components/schemas/Flavor","description":"Flavor (project) associated with the ticket"},"reason":{"anyOf":[{"type":"string","minLength":1},{"type":"null"}],"title":"Reason","description":"Reason for flagging provided by the user. The field is optional."},"comment":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Comment","description":"Comment provided by the user during flagging. This is a free text field."},"created_at":{"type":"string","format":"date-time","title":"Created At","description":"Creation datetime of the flag"},"id":{"type":"integer","title":"Id","description":"ID of the flag"},"ticket_id":{"type":"integer","title":"Ticket Id","description":"ID of the ticket associated with the flag"},"device_id":{"type":"string","title":"Device Id","description":"Device ID of the flagger"}},"type":"object","required":["type","url","user_id","source","flavor","id","ticket_id","device_id"],"title":"Flag"},"FlagCreate":{"properties":{"barcode":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Barcode","description":"Barcode of the product, if the flag is about a product or a product image. In case of a search issue, this field is null."},"type":{"$ref":"#/components/schemas/IssueType","description":"Type of the issue"},"url":{"type":"string","title":"Url","description":"URL of the product or of the flagged image"},"user_id":{"type":"string","title":"User Id","description":"Open Food Facts User ID of the flagger"},"source":{"$ref":"#/components/schemas/SourceType","description":"Source of the flag. It can be a user from the mobile app, the web or a flag generated automatically by robotoff."},"confidence":{"anyOf":[{"type":"number","maximum":1.0,"minimum":0.0},{"type":"null"}],"title":"Confidence","description":"Confidence score of the model that generated the flag, this field should only be provided by Robotoff."},"image_id":{"anyOf":[{"type":"string","minLength":1},{"type":"null"}],"title":"Image Id","description":"ID of the flagged image","examples":["1","front_fr"]},"flavor":{"$ref":"#/components/schemas/Flavor","description":"Flavor (project) associated with the ticket"},"reason":{"anyOf":[{"type":"string","minLength":1},{"type":"null"}],"title":"Reason","description":"Reason for flagging provided by the user. The field is optional."},"comment":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Comment","description":"Comment provided by the user during flagging. This is a free text field."},"created_at":{"type":"string","format":"date-time","title":"Created At","description":"Creation datetime of the flag"}},"type":"object","required":["type","url","user_id","source","flavor"],"title":"FlagCreate"},"FlagsByTicketIdRequest":{"properties":{"ticket_ids":{"items":{"type":"integer"},"type":"array","title":"Ticket Ids"}},"type":"object","required":["ticket_ids"],"title":"FlagsByTicketIdRequest"},"Flavor":{"type":"string","enum":["off","obf","opff","opf","off-pro"],"title":"Flavor","description":"Flavor is used to refer to a specific Open*Facts project:\n\n- Open Food Facts\n- Open Beauty Facts\n- Open Pet Food Facts\n- Open Product Facts\n- Open Food Facts (Pro plateform)"},"GetFlagsResponse":{"properties":{"flags":{"items":{"$ref":"#/components/schemas/Flag"},"type":"array","title":"Flags"}},"type":"object","required":["flags"],"title":"GetFlagsResponse"},"GetTicketsResponse":{"properties":{"tickets":{"items":{"$ref":"#/components/schemas/Ticket"},"type":"array","title":"Tickets"},"max_page":{"type":"integer","title":"Max Page"}},"type":"object","required":["tickets","max_page"],"title":"GetTicketsResponse","description":"Response model for get_tickets endpoint."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"IssueType":{"type":"string","enum":["product","image","search"],"title":"IssueType","description":"Type of the flag/ticket."},"ReasonType":{"type":"string","enum":["inappropriate","human","beauty","other"],"title":"ReasonType","description":"Type of the reason for flagging."},"SourceType":{"type":"string","enum":["mobile","web","robotoff"],"title":"SourceType"},"StatsResponse":{"properties":{"total_tickets":{"type":"integer","title":"Total Tickets","description":"Total number of tickets in the database"},"tickets_by_status":{"additionalProperties":true,"type":"object","title":"Tickets By Status","description":"A dictionary with ticket status as keys and the count of tickets as values"},"tickets_by_flavor":{"additionalProperties":true,"type":"object","title":"Tickets By Flavor","description":"A dictionary with ticket flavor as keys and the count of tickets as values"},"tickets_by_type":{"additionalProperties":true,"type":"object","title":"Tickets By Type","description":"A dictionary with ticket type as keys and the count of tickets as values"},"n_days":{"type":"integer","title":"N Days","description":"The number of days for which the data is fetched"},"start_date":{"type":"string","title":"Start Date","description":"The start date of the data range in ISO format"},"end_date":{"type":"string","title":"End Date","description":"The end date of the data range in ISO format"}},"type":"object","required":["total_tickets","tickets_by_status","tickets_by_flavor","tickets_by_type","n_days","start_date","end_date"],"title":"StatsResponse","description":"Response model for get_stats endpoint."},"StatusResponse":{"properties":{"status":{"type":"string","title":"Status","description":"Health status of the API"}},"type":"object","required":["status"],"title":"StatusResponse"},"Ticket":{"properties":{"barcode":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Barcode","description":"Barcode of the product, if the ticket is about a product or a product image. In case of a search issue, this field is null."},"type":{"$ref":"#/components/schemas/IssueType","description":"Type of the issue"},"url":{"type":"string","title":"Url","description":"URL of the product or of the flagged image"},"status":{"$ref":"#/components/schemas/TicketStatus","description":"Status of the ticket","default":"open"},"image_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Image Id","description":"ID of the flagged image, if the ticket type is `image`","examples":["1","front_fr"]},"flavor":{"$ref":"#/components/schemas/Flavor","description":"Flavor (project) associated with the ticket"},"created_at":{"type":"string","format":"date-time","title":"Created At","description":"Creation datetime of the ticket"},"id":{"type":"integer","title":"Id","description":"ID of the ticket"}},"type":"object","required":["type","url","flavor","id"],"title":"Ticket"},"TicketStatus":{"type":"string","enum":["open","closed"],"title":"TicketStatus"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}}}