API/Write
<Back to API(Required reading)
WRITE API Documentation
Status Codes
If the edit was successful
{"status_verbose":"fields saved","status":1}
If there was an issue
Wrong password
HTML 200 code + an HTML page with a link to login
Authentification
- user_id
- password
WARNING: If the password is not correct, the API will currently "silently" fail, both for image addition and product data addition (will return HTML 200 code + an html page with a link to login - example )
Anonymous contribution
- It is possible for new products (no anonymous modification is possible though, for obvious reasons)
- It is possible for adding images (as many as you like)
- If you detect an error 200 (wrong password), please retry the query without user_id and password. That way the contribution will be accepted. Otherwise, the photo will get lost :(
Global account
If you want to avoid coding the detection of password errors, login stuff⌠you can create a global account for all your users.
You can create a global account to let the users of your app contribute. please name it YourApp_app or something like that, so that we can spot them easily. Better yet, introduce yourself on Slack :-)
Manipulating photos for a product
Understanding products and photos
- Photos are the primary source of Open Food Facts.
- We need good photos of the product, of its ingredients and nutrition table. (and for each language present on the packaging)
- Please encourage your users to add as many photos as possible, even if the product is already complete (in that case, don't set them as default photos for front, ingredients, and nutrition)
Upload behaviour
If you upload an image (eg for front), the first one will be shown, the others will be saved but not displayed. Useful if you want to let your users take additional images that are neither front, ingredients or nutrition (eg: recycling instructions, labelsâŚ)
Understanding photos for multilingual products
Multilingual products have several photos based on languages present on the packaging. Just suffix the lang code to our examples to get or add the relevant language(s).
Adding photos for a product
- Use the POST method on:
Test server: https://world.openfoodfacts.net/cgi/product_image_upload.pl
Live server: https://world.openfoodfacts.org/cgi/product_image_upload.pl
(remember to do tests on world.openfoodfacts.net - login and password: off )
Parameters
- code: the barcode
- imagefield: (front | ingredients | nutrition)
- imgupload_front : your image file if imagefield:front
- imgupload_ingredients: your image file if imagefield:ingredients
- imgupload_nutrition: your image file if imagefield:nutrition
Example
curl --user off:off --form "imgupload_front=@Tacitus.jpg" --form code=1212121212 --form imagefield=front --form user_id=tacite --form password=mypassword https://fr.openfoodfacts.net/cgi/product_image_upload.pl
Important
- Content-Disposition: form-data; name=âimgupload_frontâ; filename=âfront.pngâ
- There must be a HTTP header "Content-Type: multipart/form-data" in the HTTP POST request.
- The imageupload_(front|ingredients|nutrition) name, size and data needs to be encoded in the multipart/form-data format, usually your HTTP request library will do that for you.
- All parameters need to be passed as POST parameters, do not put some in the URL.
- 0048151623426 is a random barcode used only for demonstration purposes.
Getting a list of all available photos
You get a list of all available photos in the product JSON (both selected photos for all languages, and Raw photos (source images for the selected images and images that are not used)
Properties of a photo
- id = 5
- uploaded_t = 1474912158 (UNIX timestamp format)
- uploader = tacinte (contributor slug)
- sizes
100 "h":100, "w":75
- 400
"h":400, "w":300
- full
"w":3120, "h":4160
Properties of a selected photo
- nutrition_fr
- y1 = 151.8125
- normalize":"true",
- x2":"169.75",
- rev":"13",
- geometry":"1238x1238-527-1578"
- sizes
- 100
"h":100, "w":75
- 200
- 400
"h":400, "w":300
- full
"w":3120, "h":4160
- y2 = 270.8125
- x1 = 50.75
- angle = 0
- white_magic = false
- imgid = 4
"images":{ "front_fr":{ "y2":"340.8125", "x1":"67.75", "angle":"0", "imgid":"5", "white_magic":"false", "x2":"245.75", "normalize":"true", "y1":"13.8125", "rev":"10", "geometry":"1851x3401-704-143", "sizes":{ "400":{ "w":218, "h":400 }, "full":{ "h":3401, "w":1851 }, "100":{ "w":54, "h":100 }, "200":{ "h":200, "w":109 } } }, "2":{ "sizes":{ "400":{ "h":400, "w":300 }, "full":{ "h":4160, "w":3120 }, "100":{ "w":75, "h":100 } }, "uploaded_t":"1474912149", "uploader":"tacinte" }, "5":{ "uploaded_t":"1474912158", "uploader":"tacinte", "sizes":{ "100":{ "h":100, "w":75 }, "400":{ "h":400, "w":300 }, "full":{ "w":3120, "h":4160 } } }, "3":{ "uploaded_t":"1474912152", "uploader":"tacinte", "sizes":{ "full":{ "w":3120, "h":4160 }, "400":{ "h":400, "w":300 }, "100":{ "h":100, "w":75 } } }, "nutrition_fr":{ "y1":"151.8125", "normalize":"true", "x2":"169.75", "rev":"13", "geometry":"1238x1238-527-1578", "sizes":{ "full":{ "w":1238, "h":1238 }, "400":{ "h":400, "w":400 }, "100":{ "w":100, "h":100 }, "200":{ "w":200, "h":200 } }, "y2":"270.8125", "x1":"50.75", "angle":"0", "white_magic":"false", "imgid":"4" }, "4":{ "sizes":{ "400":{ "w":300, "h":400 }, "full":{ "h":4160, "w":3120 }, "100":{ "h":100, "w":75 } }, "uploader":"tacinte", "uploaded_t":"1474912154" }, "ingredients_fr":{ "y2":"248.8125", "x1":"82.75", "angle":"0", "white_magic":"false", "imgid":"3", "normalize":"true", "y1":"158.8125", "x2":"257.75", "rev":"12", "sizes":{ "full":{ "w":1820, "h":936 }, "400":{ "h":206, "w":400 }, "100":{ "h":51, "w":100 }, "200":{ "h":103, "w":200 } }, "geometry":"1820x936-860-1651" }, "1":{ "sizes":{ "full":{ "w":3120, "h":4160 }, "400":{ "h":400, "w":300 }, "100":{ "w":75, "h":100 } }, "uploaded_t":"1474912148", "uploader":"tacinte" } },
Adding a photo to the list of all available photos
Getting the current global photo
Setting a new current global photo
Getting the current ingredients photo
Setting a new current ingredients photo
Getting the current nutrition photo
Setting a new current nutrition photo
Choosing the product by barcode
code=
Values:
Selecting a photo
imgid=
Values:
Rotating a photo
Test server: https://world.openfoodfacts.net/cgi/product_image_rotate.pl
Live server: https://world.openfoodfacts.org/cgi/product_image_rotate.pl
Values and output
Parameters:
imgid = code = BARCODE angle = Angle of the rotation - 90° increments normalize = whether the source image should be normalized white_magic = whether the source image should be "white magic"'d ( background removal)
function update_image(imagefield) { $('#crop_' + imagefield).attr("src","/cgi/product_image_rotate.pl?code=" + code + "&imgid=" + imagefield_imgid[imagefield] + "&angle=" + angles[imagefield] + "&normalize=" + $("#normalize_" + imagefield).prop('checked') + "&white_magic=" + $("#white_magic_" + imagefield).prop('checked') ); $('div[id="cropbuttonmsg_' + imagefield +'"]').hide(); }
Removing background on a photo ("White magic")
This will work best on photos with a white background. Best use case is to let user try it and give up if the result is not satisfying.
white_magic=
Values:
Color correction on a photo ("Normalize")
normalize=
Values:
Cropping a photo
This implies applying operations to a source image (not only cropping, but all the others if applicable). We start from a source image (defined by a barcode and incremental id), apply cropping parameters (x1, y1, x2, y2), additional operations (white_magic, normalize)
Test server: https://world.openfoodfacts.net/cgi/product_image_crop.pl
Live server: https://world.openfoodfacts.org/cgi/product_image_crop.pl
Values
code=BARCODE id= angle= Angle of the rotation normalize = whether the source image should be normalized white_magic = whether the source image should be white magiced ( background removal) type = add action = display imgid = x1= the X origin of the crop y1=the Y origin of the crop x2=the X end of the crop y2=the Y end of the crop
Ignore me
$.post('/cgi/product_image_crop.pl', {code: code, id: imagefield , imgid: imgid, x1:selection.x, y1:selection.y, x2:selection.x + selection.width, y2:selection.y + selection.height, angle:angles[imagefield], normalize:$("#normalize_" + imagefield).prop('checked'), white_magic:$("#white_magic_" + imagefield).prop('checked') }, function(data) { imagefield_url[imagefield] = data.image.display_url; update_display(imagefield, false); $('div[id="cropbutton_' + imagefield +'"]').show(); $('div[id="cropbuttonmsg_' + imagefield +'"]').html(Lang.image_saved); $(document).foundation('equalizer', 'reflow'); }, 'json'); });
Performing OCR on a photo
We start from a source image (defined by barcode and id) as selected for ingredients. We ask Product Opener to process it (process_image=1). Product Opener returns a JSON. Processing is done using Tesseract (3 on preprod). The result is often cripped with errors. Take steps to avoid direct copy pasting into the ingredients field by your users.
Test server: https://world.openfoodfacts.net/cgi/ingredients.pl
Live server: https://world.openfoodfacts.net/cgi/ingredients.pl
Values and output
code=code id=imagefield process_image=1
This will return JSON
Ignore me
$.post('/cgi/ingredients.pl', { }, function(data) { if (data.status == 0) { $('div[id="ocrbuttondiv_' + imagefield +'"]').html(Lang.extracted_ingredients_ok); var ingredients_text_id = imagefield.replace("ingredients","ingredients_text"); $("#" + ingredients_text_id).val(data.ingredients_text_from_image); } else { $('div[id="ocrbuttondiv_' + imagefield +'"]').html(Lang.extracted_ingredients_nok); } $(document).foundation('equalizer', 'reflow'); }, 'json');
Posting a new product
- Do a GET request, otherwise you'll get
{âstatus_verboseâ: âno code or invalid codeâ,âstatusâ: 0}
- URL:
https://world.openfoodfacts.org/cgi/product_jqm2.pl
(Product post)(remember to do tests on world.openfoodfacts.net - login and password: off ) - URL for your tests :
https://world.openfoodfacts.net/cgi/product_jqm2.pl
Quick overview
- var foodfact = { barcode : '0048151623426', name : 'Product name', energy: 500, energy_unit: "kJ", weight: 282 };
- var postData = {
- code : foodfact.barcode,
- user_id : "mesinfosnutritionelles",
- password : "****",
- product_name : foodfact.name?foodfact.name:foodfact.shop_label,
- quantity : foodfact.weight?""+foodfact.weight+" g":undefined,
- stores : "Walmart",
- nutriment_energy :foodfact.energy,
- nutriment_energy_unit :foodfact.energy_unit,
- nutrition_data_per :"serving"
Status after save
- {"status_verbose":"fields saved","status":1}
Example
(remember to do tests on world.openfoodfacts.net - login and password: off)
Query 1 : Unauthentified query
https://world.openfoodfacts.net/cgi/product_jqm2.pl?code=0048151623426&product_name=Maryland%20Choc%20Chip&quantity=230g&brand=Golden%20Cookies&nutriment_energy=450&nutriment_energy_unit=kJ&nutrition_data_per=serving&ingredients_text=Fortified%20wheat%20flour%2C%20Chocolate%20chips%20%2825%25%29%2C%20Sugar%2C%20Palm%20oil%2C%20Golden%20syrup%2C%20Whey%20and%20whey%20derivatives%20%28Milk%29%2C%20Raising%20agents%2C%20Salt%2C%20Flavouring&traces=Milk%2C+Soya%2C+Nuts%2C+Wheat
Result 2
https://uk.openfoodfacts.net/product/0072417136160/maryland-choc-chip
Query 2 : Authentified query
https://world.openfoodfacts.org/cgi/product_jqm2.pl?code=0048151623426&user_id=usernameexample&password=*****&product_name=KIRI%20GOUTER%20280G%208%20PORTIONS&quantity=282%20g&stores=Intermarch%C3%A9&nutriment_energy=500&nutriment_energy_unit=kJ&nutrition_data_per=serving
Result 2
If credentials are correct
Standard success status, see above
If credentials are not correct
Will give you a responsive HTML login page.
See editing a product for details on fields
Posting several values for a field
When adding values, send to the field labels as comma separated values that are canonicalised and added to the _tags array
labels = "labelA, labelB"
Reading back, use labels_tags to get an array of labels
Editing an existing product
Posting additional photos
- Photos post on /cgi/product_image_upload.pl
- code: the barcode
- imagefield: (front | ingredients | nutrition)
Add more pictures without selecting them
- imagefield: (other)
Select the Front picture
- imgupload_front : your image file if imagefield:front
Select the Ingredients picture
- imgupload_ingredients: your image file if imagefield:ingredients
Select the Nutrition Facts picture
- imgupload_nutrition: your image file if imagefield:nutrition
Editing the product
Give the barcode
code=072417136160
Add the brand
brand=Heinz
Add the name
product_name=Maryland%20Choc%20Chip
Add the quantity
quantity=230g
Add the packager code
emb_codes_tag=EMB%2013330
Add the packaging type
packaging=Cardboard
Add the labels
labels=Vegan%2C%20Fat%20free
Add the Stores where bought
stores=Intermarch%C3%A9
Add the category
categories=Cookies
Add the best before date
expiration_date=
Add the link to the official webpage of the product
link=
Add the ingredients
ingredients_text=Fortified%20wheat%20flour%2C%20Chocolate%20chips%20%2825%25%29%2C%20Sugar%2C%20Palm%20oil%2C%20Golden%20syrup%2C%20Whey%20and%20whey%20derivatives%20%28Milk%29%2C%20Raising%20agents%2C%20Salt%2C%20Flavouring
Add ingredient traces
traces=Milk%2C+Soya%2C+Nuts%2C+Wheat
Add the main language
You can set the main language of the product.
lang=fr
(NOT LIVE YET) In the case of a multilingual product, you can specify the main language of the product, and you can then specify values and images for different languages by suffixing the language code to the other fields.
Add the nutrition facts
Indicate the absence of nutrition facts
no_nutriments : indicates if the nutrition facts are indicated on the food label
Add nutrition facts values, units and base
Define the basis for the values
nutrition_data_per=100g
OR
nutrition_data_per=serving
serving_size=38g
Input values and units
nutriment_energy=450
nutriment_energy_unit=kJ
Values
nutriment_energy nutriment_proteins nutriment_casein nutriment_serum-proteins nutriment_nucleotides nutriment_carbohydrates nutriment_sugars nutriment_sucrose nutriment_glucose nutriment_fructose nutriment_lactose nutriment_maltose nutriment_maltodextrins nutriment_starch nutriment_polyols nutriment_fat nutriment_saturated-fat nutriment_butyric-acid nutriment_caproic-acid nutriment_caprylic-acid nutriment_capric-acid nutriment_lauric-acid nutriment_myristic-acid nutriment_palmitic-acid nutriment_stearic-acid nutriment_arachidic-acid nutriment_behenic-acid nutriment_lignoceric-acid nutriment_cerotic-acid nutriment_montanic-acid nutriment_melissic-acid nutriment_monounsaturated-fat nutriment_polyunsaturated-fat nutriment_omega-3-fat nutriment_alpha-linolenic-acid nutriment_eicosapentaenoic-acid nutriment_docosahexaenoic-acid nutriment_omega-6-fat nutriment_linoleic-acid nutriment_arachidonic-acid nutriment_gamma-linolenic-acid nutriment_dihomo-gamma-linolenic-acid nutriment_omega-9-fat nutriment_oleic-acid nutriment_elaidic-acid nutriment_gondoic-acid nutriment_mead-acid nutriment_erucic-acid nutriment_nervonic-acid nutriment_trans-fat nutriment_cholesterol nutriment_fiber nutriment_sodium nutriment_alcohol : % vol of alcohol nutriment_vitamin-a nutriment_vitamin-d nutriment_vitamin-e nutriment_vitamin-k nutriment_vitamin-c nutriment_vitamin-b1 nutriment_vitamin-b2 nutriment_vitamin-pp nutriment_vitamin-b6 nutriment_vitamin-b9 nutriment_vitamin-b12 nutriment_biotin nutriment_pantothenic-acid nutriment_silica nutriment_bicarbonate nutriment_potassium nutriment_chloride nutriment_calcium nutriment_phosphorus nutriment_iron nutriment_magnesium nutriment_zinc nutriment_copper nutriment_manganese nutriment_fluoride nutriment_selenium nutriment_chromium nutriment_molybdenum nutriment_iodine nutriment_caffeine nutriment_taurine nutriment_ph : pH (no unit)
Units
nutriment_energy_unit nutriment_proteins_unit nutriment_casein_unit nutriment_serum-proteins_unit nutriment_nucleotides_unit nutriment_carbohydrates_unit nutriment_sugars_unit nutriment_sucrose_unit nutriment_glucose_unit nutriment_fructose_unit nutriment_lactose_unit nutriment_maltose_unit nutriment_maltodextrins_unit nutriment_starch_unit nutriment_polyols_unit nutriment_fat_unit nutriment_saturated-fat_unit nutriment_butyric-acid_unit nutriment_caproic-acid_unit nutriment_caprylic-acid_unit nutriment_capric-acid_unit nutriment_lauric-acid_unit nutriment_myristic-acid_unit nutriment_palmitic-acid_unit nutriment_stearic-acid_unit nutriment_arachidic-acid_unit nutriment_behenic-acid_unit nutriment_lignoceric-acid_unit nutriment_cerotic-acid_unit nutriment_montanic-acid_unit nutriment_melissic-acid_unit nutriment_monounsaturated-fat_unit nutriment_polyunsaturated-fat_unit nutriment_omega-3-fat_unit nutriment_alpha-linolenic-acid_unit nutriment_eicosapentaenoic-acid_unit nutriment_docosahexaenoic-acid_unit nutriment_omega-6-fat_unit nutriment_linoleic-acid_unit nutriment_arachidonic-acid_unit nutriment_gamma-linolenic-acid_unit nutriment_dihomo-gamma-linolenic-acid_unit nutriment_omega-9-fat_unit nutriment_oleic-acid_unit nutriment_elaidic-acid_unit nutriment_gondoic-acid_unit nutriment_mead-acid_unit nutriment_erucic-acid_unit nutriment_nervonic-acid_unit nutriment_trans-fat_unit nutriment_cholesterol_unit nutriment_fiber_unit nutriment_sodium_unit nutriment_alcohol_unit : % vol of alcohol nutriment_vitamin-a_unit nutriment_vitamin-d_unit nutriment_vitamin-e_unit nutriment_vitamin-k_unit nutriment_vitamin-c_unit nutriment_vitamin-b1_unit nutriment_vitamin-b2_unit nutriment_vitamin-pp_unit nutriment_vitamin-b6_unit nutriment_vitamin-b9_unit nutriment_vitamin-b12_unit nutriment_biotin_unit nutriment_pantothenic-acid_unit nutriment_silica_unit nutriment_bicarbonate_unit nutriment_potassium_unit nutriment_chloride_unit nutriment_calcium_unit nutriment_phosphorus_unit nutriment_iron_unit nutriment_magnesium_unit nutriment_zinc_unit nutriment_copper_unit nutriment_manganese_unit nutriment_fluoride_unit nutriment_selenium_unit nutriment_chromium_unit nutriment_molybdenum_unit nutriment_iodine_unit nutriment_caffeine_unit nutriment_taurine_unit nutriment_ph_unit : pH (no unit)
Adding the alcohol % of wine
12% wine
nutriment_unit=%25%20vol&nutriment_alcohol=12
Adding the carbon footprint
nutriment_carbon-footprint
nutriment_carbon-footprint_unit
Adding a comment to your edit
comment=Automated%20Edit