EDI 제약사 분류 / 이미지라벨링
처방전·EDI 사진 한 장이면 어느 제약사 약인지 색깔로 표시해 드립니다. 여러 제약사 약이 섞여 있어도 한눈에 구분되고, 제약사별로 일일이 나눠 정리하던 수작업이 사라집니다.
바로 실행
이미지를 올려 바로 실행해 결과를 확인하세요. (비로그인은 하루 실행 횟수 제한)
엔드포인트
POST https://marketapi.nadoo.ai/api/v1/hira-detect/detect인증
| 헤더 | 타입 | 필수 | 설명 |
|---|---|---|---|
x-api-key | string | 필수 | 대시보드에서 발급한 API 키 (pk_live_…) |
요청
요청 헤더
| 헤더 | 타입 | 필수 | 설명 |
|---|---|---|---|
Content-Type | string | 필수 | image/jpeg, image/png (바이너리) 또는 application/json |
Idempotency-Key | string | 선택 | 재시도 이중 과금 방지 (권장: UUID). 같은 키 + 같은 본문이면 재처리 없이 최초 결과를 반환하고, 같은 키로 다른 본문을 보내면 422. 키를 안 보내면 매 요청이 별건 처리됨. |
요청 본문 — (A) 바이너리
Content-Type: image/jpeg(또는 png)로 이미지 바이트를 그대로 전송합니다. (최대 25MB)
요청 본문 — (B) JSON
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
image | string | 택1 | base64 인코딩된 이미지 |
imageUrl | string(uri) | 택1 | 이미지 https URL (서버가 다운로드). image와 택일 |
쿼리 파라미터 (선택)
| 파라미터 | 타입 | 설명 |
|---|---|---|
labelSingle | boolean | ?labelSingle=1 이면 단일 제약사여도 색상 라벨 합성본(labeled)을 생성합니다. 기본값은 false — 단일 제약사는 라벨 없이 원본이 반환됩니다(기존 스펙). 멀티 제약사는 이 옵션과 무관하게 항상 라벨을 붙입니다. 좌표(items[].box)는 옵션과 무관하게 항상 반환되므로, 라벨을 직접 그릴 경우엔 이 옵션 없이도 좌표만으로 가능합니다. 바이너리·JSON·배치 모두 동일하게 지원합니다. |
응답 200 OK
| 필드 | 타입 | 설명 |
|---|---|---|
requestId | string | 요청 식별자 (idempotency 키와 동일) |
items | object[] | 검출된 약가코드별 결과 (아래 items 스키마) |
items[].code | string | 9자리 약가코드 |
items[].manufacturer | string | null | 제약사명 (미조회 시 null) |
items[].drugName | string | null | 의약품명 (미조회 시 null) |
items[].found | boolean | 마스터 조회 성공 여부 |
items[].box | object | 라벨 좌표 — original 이미지 기준 픽셀 {x,y,width,height}. 이 좌표로 라벨 편집 에디터를 구성 |
uniqueManufacturers | string[] | 검출된 제약사 목록 (중복 제거) |
width, height | number | original 이미지 크기(px) — 좌표 매핑 기준 |
tagged | boolean | labeled 라벨 합성본 존재 여부. 멀티 제약사면 true, 단일 제약사는 ?labelSingle=1 일 때만 true |
rotation | number | 자동 보정한 회전 각도 (0/90/180/270) |
unknownCodes | string[] | 검출됐으나 마스터 미조회된 코드 |
original | object | 원본(라벨 없는 보정본) 이미지 — 라벨 좌표의 기준·에디터 베이스 (mode/url/base64/contentType) |
labeled | object | null | 라벨 합성본 — 멀티 제약사, 또는 ?labelSingle=1 인 단일 제약사면 생성. 아니면 null |
output | object | 표시용(labeled 있으면 그것, 없으면 original) — 하위호환 |
output.mode | "gcs" | "inline" | gcs=서명 URL, inline=base64 직접 (original·labeled·output 공통) |
cost.krw | number | 이번 호출 과금액(원). 무료 처리 시 0 |
cost.free | boolean | 무료 제공량으로 처리됐는지 |
balanceKrw | number | 처리 후 잔액(원) |
응답 예시
{
"requestId": "3f9a1c2e-...",
"items": [
{ "code": "658107190", "manufacturer": "한풍제약 주식회사",
"drugName": "아제나정(아젤라스틴염산염)", "found": true,
"box": { "x": 198, "y": 689, "width": 101, "height": 24 } }
],
"uniqueManufacturers": ["한풍제약 주식회사"],
"width": 1600, "height": 881,
"tagged": false,
"rotation": 90,
"unknownCodes": [],
"original": { "mode": "gcs", "contentType": "image/jpeg",
"url": "https://storage.googleapis.com/cso-ai-results/original/...?X-..." },
"labeled": null,
"output": { "mode": "gcs", "url": "https://.../original/...?X-..." },
"cost": { "krw": 300, "free": false },
"balanceKrw": 49800
}original(라벨 없는 원본)을 캔버스에 깔고 items[].box 좌표(원본 픽셀 기준)로 사각형을 그리면, 제약사별 라벨을 확인·수정하는 에디터를 만들 수 있습니다. 좌표는 단일/멀티·labelSingle 여부와 무관하게 항상 반환됩니다. 서버가 합성한 미리보기 이미지가 필요하면 labeled(멀티 제약사, 또는 ?labelSingle=1 인 단일 제약사)를 쓰세요.위 예시는 단일 제약사 + 옵션 없음 — 기존 스펙대로 labeled: null, tagged: false 이고 output은 원본입니다. ?labelSingle=1을 붙이면 labeled가 합성되고 output이 라벨본, tagged: true가 됩니다.
에러 응답
본문: { "error": "<code>", ... }
| HTTP | error | 추가 필드 | 의미 |
|---|---|---|---|
| 401 | invalid_key | — | API 키 누락/무효 |
| 402 | insufficient_credit | freeUsed, freeQuota, applyUrl | 무료 소진 + 잔액 부족 |
| 404 | product_not_found | — | 없는/종료된 API |
| 413 | payload_too_large | maxBytes | 요청 본문 25MB 초과 |
| 500 | internal_error | — | 내부 오류 |
| 502 | processor_error | refunded | 처리 실패(이미지 해석 불가 포함), 과금분 자동 환불 |
// 402 예시
{ "error": "insufficient_credit", "freeUsed": 10, "freeQuota": 10,
"applyUrl": "https://market.nadoo.ai/dashboard/apply" }예시 (cURL)
curl -X POST https://marketapi.nadoo.ai/api/v1/hira-detect/detect \
-H "x-api-key: pk_live_xxxxxxxx" \
-H "Content-Type: image/jpeg" \
-H "Idempotency-Key: $(uuidgen)" \
--data-binary @처방전.jpg벌크 (다중 이미지)
여러 이미지를 한 요청으로 처리합니다(최대 50건, 제한 동시성). 항목별로 독립 과금되며(성공 300원/건, 실패 시 자동 환불), 부분 성공을 지원합니다. 대량은 imageUrls 사용을 권장합니다(요청 본문 25MB 제한).
요청 본문 (JSON)
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
images | string[] | 택1 | base64 인코딩 이미지 배열 |
imageUrls | string[] | 택1 | 이미지 https URL 배열 (대량 권장) |
응답 200 OK
| 필드 | 타입 | 설명 |
|---|---|---|
count / ok / failed | number | 요청·성공·실패 건수 |
totalCostKrw | number | 이번 배치 총 과금액(원) |
balanceKrw | number | 처리 후 잔액(원) |
results[] | object[] | 항목별 결과 — index·status(200/402/502) + 단건 응답 필드(items·output 등) |
예시 (cURL)
curl -X POST https://marketapi.nadoo.ai/api/v1/hira-detect/detect-batch \
-H "x-api-key: pk_live_xxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"imageUrls":["https://.../a.jpg","https://.../b.jpg"]}'대용량 업로드 (presigned, 권장)
base64는 요청 크기 한계(본문 25MB·원본 ~18MB)가 있어, 대용량·대량은 presigned 업로드가 안정적입니다(용량 무제한 — 이미지를 GCS로 직접 PUT). ① 업로드 URL 발급 → ② 이미지 PUT → ③ imageUrl 로 검출.
# ① 업로드 URL 발급
curl -X POST https://marketapi.nadoo.ai/api/v1/uploads \
-H "x-api-key: pk_live_xxxxxxxx" -H "Content-Type: application/json" \
-d '{"contentType":"image/jpeg"}'
# → { "uploadUrl": "https://storage.googleapis.com/...(서명)", "imageUrl": "https://.../key", "expiresIn": 900 }
# ② 이미지를 uploadUrl 로 PUT (같은 Content-Type)
curl -X PUT "<uploadUrl>" -H "Content-Type: image/jpeg" --data-binary @처방전.jpg
# ③ imageUrl 로 검출(단건·배치 공통)
curl -X POST https://marketapi.nadoo.ai/api/v1/hira-detect/detect -H "x-api-key: pk_live_xxxxxxxx" -H "Content-Type: application/json" \
-d '{"imageUrl":"<imageUrl>"}'| 필드 | 타입 | 설명 |
|---|---|---|
uploadUrl | string | 이미지를 PUT 할 서명 URL(만료 시간 내) |
imageUrl | string | 업로드 후 검출 요청의 imageUrl/imageUrls에 넣을 값 |
expiresIn | number | 서명 URL 유효 시간(초) |
비동기 대량
대량용(최대 500장). 접수 즉시 202로 jobId·pollUrl을 반환하고, 처리는 백그라운드(큐)에서 진행됩니다. 본문은 detect-batch와 동일(images/imageUrls — 대량은 presigned imageUrls 권장).
curl -X POST https://marketapi.nadoo.ai/api/v1/hira-detect/detect-batch-async \
-H "x-api-key: pk_live_xxxxxxxx" -H "Content-Type: application/json" \
-d '{"imageUrls":["https://.../a.jpg","https://.../b.jpg"]}'
# → { "jobId": "job_abc", "status": "queued", "total": 2, "pollUrl": "/api/v1/jobs/job_abc" }작업 폴링 GET /api/v1/jobs/{jobId}
작업 진행 상태·결과를 조회합니다(본인 소유만). status가 종료 상태 (done 전건 성공 / partial 일부 실패 / failed 전건 실패)가 될 때까지 폴링하세요. 응답은 jobId·status·total·done·ok·failed·totalCostKrw·balanceKrw와 results[](항목별 index·status + 단건 검출 필드 items·uniqueManufacturers·output 등)를 포함합니다.
curl https://marketapi.nadoo.ai/api/v1/jobs/job_abc -H "x-api-key: pk_live_xxxxxxxx"
# → { "jobId": "job_abc", "status": "done", "total": 2, "done": 2, "ok": 2, "failed": 0,
# "results": [ { "index": 0, "status": "ok",
# "items": [{ "code": "658107190", "manufacturer": "한풍제약 주식회사", "box": {...} }],
# "uniqueManufacturers": ["한풍제약 주식회사"], "output": { "mode": "gcs", "url": "https://..." } }, ... ] }