FoodLens · CaloAI REST API
FoodLens API 문서
FoodLens(CaloAI) REST API는 음식 사진 한 장을 받아, 사진 속 음식마다 이름, 위치, 1회 제공량, 재료, 칼로리와 36종 영양소를 JSON으로 돌려주는 음식 이미지 인식 API입니다. 이 문서는 기능과 응답 구조를 소개합니다.
개요
CaloAI는 FoodLens 2.0 엔진입니다. 응답 형식은 FoodLens와 같고, 일부 필드(식품군 등)는 CaloAI에서만 채워집니다.
기능과 엔드포인트
경로는 서버 주소를 뺀 상대 경로입니다.
음식 인식 — 음식 사진(multipart/form-data)을 보내면 인식된 음식 목록을 돌려줍니다. 응답 보기
음식 정보 조회 — 음식 ID로 그 음식의 제공량과 영양 정보를 돌려줍니다. 응답 형식은 음식 인식 결과와 같습니다. 응답 보기
음식 검색 — 음식 이름으로 영양 DB(28만 개 이상)를 찾아, 간단 목록(ID·이름) 또는 상세 목록(제공량·칼로리 포함)을 돌려줍니다. 경로는 전체 명세서에서 안내합니다. 응답 보기
Android·iOS SDK
앱에 바로 붙이려면 REST API 대신 SDK를 쓸 수 있습니다. 카메라·결과·음식 검색 화면이 들어 있는 UI SDK와, 화면을 직접 만드는 Core SDK를 제공합니다. SDK 응답도 이 문서의 응답 형식과 같습니다.
공통 응답 형식
모든 응답은 application/json이며 아래 구조로 감싸져 있습니다.
| 필드 | 형식 | 설명 |
|---|---|---|
| success | Boolean | 처리 결과. 성공하면 true, 실패하면 false |
| code | String | 처리에 문제가 있을 때의 오류 코드. 예: server.error(서버 내부 오류). 성공하면 빈 문자열 |
| body | Array | 결과 목록. 음식 인식·정보 조회는 음식 객체, 검색은 검색 결과 객체 |
| path | String | 처리 경로 정보. 보통 빈 문자열 |
음식 인식 응답
사진 속 음식마다 body에 음식 객체가 하나씩 들어갑니다. 아래 예시는 새우 오일 파스타 한 접시를 인식한 결과입니다(값은 예시).
음식 객체
| 필드 | 형식 | 설명 |
|---|---|---|
| name | String | 기본 음식 이름. 예: Oil Pasta |
| fullName | String | 음식과 재료를 합친 이름. 예: Prawn Oil Pasta |
| position | Object | 사진 속 음식 위치(픽셀). xmin, xmax, ymin, ymax |
| candidates | Array | 음식 후보 목록. FoodLens는 5개, CaloAI는 1개를 돌려줍니다(옵션으로 여러 후보 요청 가능) |
| ingredients | Array | 재료 목록. name(재료 이름), gram(1회 제공량 기준 무게) |
후보(candidates) 객체
| 필드 | 형식 | 설명 |
|---|---|---|
| id | Number | 음식 ID. CaloAI는 -1 |
| manufacturer | String | 제조사(가공식품·프랜차이즈) |
| foodName | String | 기본 음식 이름 |
| fullFoodName | String | 음식과 재료를 합친 이름 |
| foodType | String | 음식 종류(주류 등) |
| servingSize | Number | 1회 제공량 |
| totalServingSize | Number | 총 내용량(값이 있을 때) |
| unit | String | 제공량 단위(g, ml) |
| counts | String | 제공 단위 이름. 예: plate(L) |
| countsDetail | Array | 단위 상세. countType은 serving(1회 제공량)과, 총 내용량이 다를 때 함께 오는 total. 각 항목에 servingSize, countsValue, counts, 보조 단위 subCountsValue·subCounts |
| ingredients | Array | 이 후보의 재료 목록 |
| energy … | Number | 칼로리와 영양소. 영양소 필드 참고 |
값이 없으면 숫자는 -1, 문자열은 빈 문자열로 옵니다.
응답 예시
{
"body": [
{
"name": "Oil Pasta",
"fullName": "Prawn Oil Pasta",
"position": { "xmin": 27, "xmax": 712, "ymin": 43, "ymax": 508 },
"candidates": [
{
"id": -1,
"manufacturer": "",
"foodName": "Oil Pasta",
"fullFoodName": "Prawn Oil Pasta",
"foodType": "",
"servingSize": 388.0,
"totalServingSize": 388.0,
"unit": "g",
"counts": "plate(L)",
"countsDetail": [
{ "countType": "serving", "servingSize": 388.0, "countsValue": 1.0, "counts": "plate(L)", "subCountsValue": -1.0, "subCounts": "" }
],
"ingredients": [
{ "name": "Noodles", "gram": 250.0 },
{ "name": "Prawn", "gram": 80.0 },
{ "name": "Oil", "gram": 50.0 },
{ "name": "Parmesan", "gram": 5.0 },
{ "name": "Salt", "gram": 2.5 },
{ "name": "Black pepper", "gram": 0.5 }
],
"energy": 872.21,
"carbohydrate": 68.36,
"protein": 25.46,
"fat": 51.9,
"totalSugars": 0.0,
"totalDietaryFiber": 0.0,
"calcium": 117.31,
"iron": 2.96,
"magnesium": 2.55,
"phosphorus": 220.11,
"potassium": 363.71,
"sodium": 1043.66,
"zinc": 0.21,
"selenium": 1.78,
"retinol": 12.75,
"betaCarotene": 5.54,
"vitaminA": 13.21,
"thiamin": 0.15,
"riboflavin": 0.1,
"niacin": 4.27,
"vitaminB6": 0.0,
"biotin": 0.05,
"totalFolate": 0.38,
"vitaminC": 0.8,
"vitaminD": 0.03,
"vitaminE": 40.68,
"vitaminK": 86.14,
"isoleucine": 74.42,
"leucine": 141.49,
"valine": 95.69,
"bcaa": 5.21,
"cholesterol": 5.3,
"saturatedFattyAcid": 6.26,
"epa": 0.0,
"dha": 0.0,
"omega3FattyAcid": 3.41,
"omega6FattyAcid": 17.07,
"transFattyAcid": 0.04,
"grainGroup": -1.0,
"proteinGroup": -1.0,
"vegetableGroup": -1.0,
"fruitGroup": -1.0,
"oilGroup": -1.0,
"sugarGroup": -1.0,
"dairyGroup": -1.0
}
],
"ingredients": [
{ "name": "Noodles", "gram": 250.0 },
{ "name": "Prawn", "gram": 80.0 },
{ "name": "Oil", "gram": 50.0 },
{ "name": "Parmesan", "gram": 5.0 },
{ "name": "Salt", "gram": 2.5 },
{ "name": "Black pepper", "gram": 0.5 }
]
}
],
"path": "",
"success": true,
"code": ""
}
영양소 필드
모든 영양소 값은 1회 제공량(servingSize) 기준입니다. 값이 없으면 -1이 옵니다.
| 필드 | 영양소 | 단위 |
|---|---|---|
| energy | 열량 | kcal |
| carbohydrate | 탄수화물 | g |
| protein | 단백질 | g |
| fat | 지방 | g |
| totalSugars | 당류 | g |
| totalDietaryFiber | 식이섬유 | g |
| saturatedFattyAcid | 포화지방 | g |
| transFattyAcid | 트랜스지방 | g |
| cholesterol | 콜레스테롤 | mg |
| sodium | 나트륨 | mg |
| calcium | 칼슘 | mg |
| iron | 철 | mg |
| magnesium | 마그네슘 | mg |
| phosphorus | 인 | mg |
| potassium | 칼륨 | mg |
| zinc | 아연 | mg |
| selenium | 셀레늄 | μg |
| vitaminA | 비타민A | μg |
| retinol | 레티놀 | μg |
| betaCarotene | 베타카로틴 | μg |
| thiamin | 티아민(비타민B1) | mg |
| riboflavin | 리보플라빈(비타민B2) | mg |
| niacin | 나이아신 | mg |
| vitaminB6 | 비타민B6 | mg |
| biotin | 비오틴 | μg |
| totalFolate | 엽산 | μg |
| vitaminC | 비타민C | mg |
| vitaminD | 비타민D | μg |
| vitaminE | 비타민E | mg |
| vitaminK | 비타민K | μg |
| isoleucine | 이소류신 | mg |
| leucine | 류신 | mg |
| valine | 발린 | mg |
| bcaa | BCAA(분지사슬아미노산) | mg |
| epa | EPA | mg |
| dha | DHA | mg |
| omega3FattyAcid | 오메가3 지방산 | g |
| omega6FattyAcid | 오메가6 지방산 | g |
| grainGroup … dairyGroup | 식품교환단위(곡류군·어육류군·채소군·과일군·지방군·당류군·우유군) | 단위. CaloAI만 제공 |
음식 정보 조회 응답
음식 ID로 조회하면 해당 음식 하나의 정보가 음식 인식과 같은 형식으로 옵니다. 사진이 없으므로 position은 모두 0, ingredients는 빈 목록입니다.
{
"body": [
{
"name": "Oil Pasta",
"fullName": "Prawn Oil Pasta",
"position": { "xmin": 0, "xmax": 0, "ymin": 0, "ymax": 0 },
"candidates": [
{
"id": -1,
"manufacturer": "",
"foodName": "Oil Pasta",
"fullFoodName": "Prawn Oil Pasta",
"foodType": "",
"servingSize": 388.0,
"totalServingSize": 0.0,
"unit": "g",
"counts": "plate(L)",
"countsDetail": [
{ "countType": "serving", "servingSize": 388.0, "countsValue": 1.0, "counts": "plate(L)", "subCountsValue": -1.0, "subCounts": "" }
],
"energy": 872.21,
"carbohydrate": 68.36,
"protein": 25.46,
"fat": 51.9,
"totalSugars": 0.0,
"totalDietaryFiber": 0.0,
"sodium": 1043.66,
"cholesterol": 5.3,
"saturatedFattyAcid": 6.26,
"transFattyAcid": 0.04,
"grainGroup": -1.0,
"proteinGroup": -1.0,
"vegetableGroup": -1.0,
"fruitGroup": -1.0,
"oilGroup": -1.0,
"sugarGroup": -1.0,
"dairyGroup": -1.0
}
],
"ingredients": []
}
],
"path": "",
"success": true,
"code": ""
}
예시에서는 지면상 일부 영양소만 보였습니다. 실제 응답에는 영양소 필드의 모든 항목이 옵니다.
음식 검색 응답
아래 결과의 음식 이름, ID, 값은 형식을 보여 주기 위한 예시입니다.
간단 목록
음식 ID와 이름, 제조사만 돌려줍니다. 고른 음식의 상세 정보는 음식 정보 조회로 가져옵니다.
{
"body": [
{ "id": 6699, "foodName": "Steamed Steak", "manufacturer": "" },
{ "id": 6702, "foodName": "Grilled Sirloin Steak", "manufacturer": "" },
{ "id": 789, "foodName": "Pork Chop Steak", "manufacturer": "" }
],
"success": true,
"code": ""
}
상세 목록
제공량과 칼로리, 제공 단위까지 함께 돌려줍니다. 숫자 값도 문자열로 옵니다.
{
"body": [
{ "id": 360021, "foodName": "연어", "manufacturer": "부경수산", "weight": "100g", "energy": "261.0", "countsValue": "1", "counts": "총 내용량", "subCountsValue": "", "subCounts": "" },
{ "id": 94911, "foodName": "연어초밥", "manufacturer": "", "weight": "180g", "energy": "287.5", "countsValue": "1", "counts": "인분", "subCountsValue": "6", "subCounts": "개" },
{ "id": 94912, "foodName": "연어감자조림", "manufacturer": "", "weight": "125g", "energy": "140.24", "countsValue": "1", "counts": "접시(중)", "subCountsValue": "", "subCounts": "" }
],
"success": true,
"code": ""
}
오류 응답
| HTTP 상태 | 의미 |
|---|---|
| 401 Unauthorized | 인증 정보가 없거나 맞지 않음 |
| 402 Payment Required | 호출 한도를 넘었거나 결제가 필요함 |
| 403 Forbidden | 계약에 포함되지 않은 기능을 호출함 |
| 404 Not Found | 없는 주소이거나 지원하지 않는 주소 |
| 406 Not Acceptable | 등록된 앱 정보와 맞지 않음 |
| 5xx Server Error | 예상하지 못한 서버 오류. 본문 code는 server.error |
값 계산 방법
- 재료 무게도 1회 제공량 기준입니다.
- 100g당 값 = 영양소 값 × 100 ÷
servingSize - 총 내용량 기준 값은
countsDetail에countType: "total"항목이 있을 때 그servingSize로 환산합니다. - 값이
-1이면 정보가 없는 것이므로 0으로 계산하지 마세요.
도입 절차
- 이메일 sales@doinglab.com 또는 전화 02-6959-5657로 도입을 문의합니다.
- 계약 후 API 키, 서버 주소, 요청 파라미터가 담긴 전체 명세서를 받습니다.
- 3개월 무료 테스트 기간(FoodLens 최대 3,000회 호출) 동안 개발과 검증을 진행합니다.
- 앱에 바로 붙이려면 Sample UI가 포함된 Android·iOS SDK를 쓸 수 있습니다. 설명서: Android · iOS
요금은 FoodLens 요금에서 볼 수 있습니다. 가입 없이 먼저 써 보려면 다이어트카메라 앱이나 푸드렌즈 카카오톡 채널에 음식 사진을 올려 보세요.
FoodLens API 도입 문의
서비스에 맞는 요금제와 전체 API 명세서를 안내해 드립니다. 모든 플랜에 3개월 무료 테스트가 포함됩니다.