WHATTA 운영 API 개발자 문서
Base URL: https://www.whatta.co.kr
Sandbox와의 분리
| 구분 | 운영 API | 공개 Sandbox |
|---|---|---|
| 주소 | https://www.whatta.co.kr | https://sandbox.whatta.co.kr |
| 데이터 | 운영 계정·운영 저장소에 귀속될 수 있음 | Sandbox 전용 상태 저장소 |
| 택배사 | 회원 소유 또는 별도 승인된 서버 선택 binding과 운영 게이트 필요. 실제 운영 접수는 미검증 | 항상 mock. 실제 carrier HTTP 호출 없음 |
| 결과 | CREATED는 WHATTA 주문 수신 결과 | ACCEPTED, 송장번호와 라벨은 synthetic mock |
인증·scope·quota
회원의 연동 계정 발급 화면에서 발급한 Bearer 토큰을 외부 쇼핑몰의 비밀정보 저장소에 보관하세요. 원문은 발급 시 한 번만 표시되고 URL·로그·응답에는 넣지 않습니다.
Authorization: Bearer ${WHATTA_TOKEN}
Content-Type: application/json
VALIDATE_ONLY:validateOnly: true인 검증만 허용합니다. 저장·carrier 호출은 수행하지 않습니다.ORDER_WRITE: 주문 검증과 WHATTA 주문 저장을 허용합니다. 이 scope만으로 carrier 접수 권한이 생기지는 않습니다.- 택배 접수는 별도의 승인·활성 carrier binding, 자격정보와 운영 게이트가 모두 필요합니다. 플랫폼 binding은 별도 서버 게이트가 켜진 경우에만 사용됩니다.
- 무료
FREE_API_30은 배송 건수가 아닌 유효한 API 요청 30회 기준입니다. 인증 실패·scope 거부·문서·health 요청은 차감하지 않습니다. 검증·배송·상태·라벨 요청은 유효한 인증을 통과하면 차감될 수 있습니다. 별도 quota 조회 route는 없습니다.
주문 수신
POST /api/shop/orders/
주문 검증 또는 WHATTA 주문 수신 route입니다. 택배 접수나 쇼핑몰 역전송 route가 아닙니다.
curl --fail-with-body -sS \
-H "Authorization: Bearer ${WHATTA_TOKEN}" \
-H 'Content-Type: application/json' \
https://www.whatta.co.kr/api/shop/orders/ \
--data '{
"provider":"CUSTOM",
"validateOnly":true,
"shopOrderId":"DOC-ORDER-0001",
"receiver":{"name":"가상 수령인","phone":"010-0000-0000","zipcode":"06236","address1":"서울 테스트구 검증로 1"},
"items":[{"name":"가상 상품","quantity":1}]
}'
| HTTP | 상태 / 오류 | 의미 |
|---|---|---|
| 200 | VALIDATION_OK | 검증 완료, 저장 없음 |
| 200 | NEEDS_REVIEW / SHIPMENT_REQUIRED_MISSING | 필수 배송값 확인 필요 |
| 200 | CREATED / DUPLICATE | WHATTA 주문 수신 결과. 택배 접수 완료가 아님 |
| 400/401/403/413/429/503 | INVALID_JSON, INVALID_VALIDATE_ONLY, FORBIDDEN_SCOPE 등 | 문서의 OpenAPI 오류 응답 참조 |
배송 검증·접수
POST /api/shop/shipments/
현재 형식상 CJ, POST_OFFICE, LOTTE와 주문번호, idempotency key, 발송인·수취인·상품 정보가 필요합니다. validateOnly: true는 입력과 서버가 선택한 승인 binding 사전검사만 수행하며 실제 접수·송장·라벨을 만들지 않습니다.
curl --fail-with-body -sS \
-H "Authorization: Bearer ${WHATTA_TOKEN}" \
-H 'Content-Type: application/json' \
https://www.whatta.co.kr/api/shop/shipments/ \
--data '{
"validateOnly":true,
"carrier":"CJ",
"shopOrderId":"DOC-SHIP-0001",
"idempotencyKey":"DOC-SHIP-0001-v1",
"sender":{"name":"가상 발송인","phone":"010-0000-0000","zipcode":"06236","address1":"서울 테스트구 검증로 1"},
"receiver":{"name":"가상 수령인","phone":"010-1111-1111","zipcode":"04524","address1":"서울 테스트구 확인로 2"},
"product":{"name":"가상 상품","quantity":1}
}'
실제 접수 요청은 별도 명시 요청이어야 하며, 현재 운영 gate가 기본 비활성이라 정상 운영 환경에서는 차단됩니다. 성공적인 carrier 접수·운송장·공식 라벨은 현재 검증되지 않았습니다.
상태·라벨 route
GET /api/shop/shipments/?shopOrderId=...: 같은 외부 API 계정(tenant) 소유 배송 상태 조회. 다른 거래처 데이터는 조회할 수 없습니다.GET /api/shop/shipments/label/?shopOrderId=...: 인증된 WHATTA 출력 세션을 통한 SVG 경로. carrier 공식 라벨 제공으로 확정하지 않습니다.POST /api/shop/shipments/label/:shopOrderId와action=mark_printed로 출력 상태를 기록합니다.
UNKNOWN은 응답 유실 등으로 결과가 확정되지 않은 상태입니다. 자동 재접수·idempotency key 변경·payload 변경을 하지 말고 상태 조회와 운영 확인 후 수동 판단하세요. LABEL_PENDING 또는 LABEL_NOT_READY에서 라벨을 강제 생성하지 않습니다.
오류 코드
| HTTP | 코드 예시 | 처리 |
|---|---|---|
| 400 | AUTH_TOKEN_REQUIRED, INVALID_JSON, INVALID_VALIDATE_ONLY | 요청 형식 수정 |
| 401 | INVALID_OR_DISABLED_TOKEN | 토큰 저장소 확인. 토큰을 로그에 남기지 않음 |
| 403 | FORBIDDEN_SCOPE, CUSTOMER_CARRIER_CONTRACT_REQUIRED | 권한·승인 binding 확인 |
| 409 | PAYLOAD_CONFLICT, LABEL_NOT_READY | 기존 요청을 변경하지 않고 상태 확인 |
| 404/410 | SHIPMENT_NOT_FOUND, LABEL_SESSION_EXPIRED | 소유권과 세션 상태 확인 |
| 422 | INVALID_SHIPMENT, LABEL_RENDER_UNAVAILABLE | 입력값 또는 렌더링 지원 범위 확인 |
| 429 | RATE_LIMITED, API_QUOTA_EXCEEDED | 한도 정책에 따라 중단 |
| 502/503 | CARRIER_SUBMISSION_FAILED, CARRIER_SUBMISSION_DISABLED | 자동 재접수하지 않고 운영 확인 |
택배사별 현재 상태
| 택배사 | 코드 경로 | 현재 상태 |
|---|---|---|
| CJ대한통운 | 기존 gateway/client와 외부 adapter 경계 | 코드 경로 확인됨. 계약·승인·운영 gate·실접수·공식 라벨은 미검증 |
| 우체국 | 기존 serializer/client/parser 경계 | 코드 경로 확인됨. 승인·allowlist·실접수·공식 라벨은 미검증 |
| 롯데택배 | 기존 client·주소정제·renderer 경계 | 코드 경로 확인됨. 번호 확보 방식·공식 라벨 승인·실접수는 미검증 |
현재 외부 API에는 택배 취소·반품·carrier 원본 라벨 다운로드를 보장하는 공개 route가 없습니다. 실제 지원 여부가 확인되지 않은 기능은 사용하지 마세요.
PHP 예제
<?php
$token = getenv('WHATTA_TOKEN');
if (!is_string($token) || $token === '') { throw new RuntimeException('WHATTA_TOKEN is required'); }
$payload = json_encode([
'provider' => 'CUSTOM', 'validateOnly' => true, 'shopOrderId' => 'DOC-ORDER-0001',
'receiver' => ['name' => '가상 수령인', 'phone' => '010-0000-0000', 'zipcode' => '06236', 'address1' => '서울 테스트구 검증로 1'],
'items' => [['name' => '가상 상품', 'quantity' => 1]],
], JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR);
$ch = curl_init('https://www.whatta.co.kr/api/shop/orders/');
curl_setopt_array($ch, [CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer '.$token, 'Content-Type: application/json'], CURLOPT_POSTFIELDS => $payload]);
$body = curl_exec($ch); if ($body === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch); echo $body;
공개 전제와 미검증 범위
이 문서는 실제 운영 route와 현재 코드·설정 검토 결과를 설명합니다. 운영 POST, carrier API, migration, binding 승인, scope 변경은 문서 공개 검증에서 수행하지 않았습니다. 계약·승인·운영 계정이 준비되지 않은 carrier는 요청 전에 차단됩니다. 개인정보 보관기간과 carrier 공식 라벨 승인 여부는 별도 운영·정책 확인 항목입니다.