deliveryapi 1.8.0 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +425 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1026 -374
- package/dist/index.d.ts +1026 -374
- package/dist/index.js +433 -20
- package/dist/index.js.map +1 -1
- package/package.json +4 -2
package/dist/index.d.cts
CHANGED
|
@@ -1,542 +1,883 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* 택배 배송 상태 코드
|
|
2
|
+
* 택배 배송 상태 코드
|
|
3
3
|
*
|
|
4
|
-
* 모든 택배사의 상태를 하나의
|
|
5
|
-
*
|
|
6
|
-
* @example
|
|
7
|
-
* if (result.deliveryStatus === CourierDeliveryStatus.DELIVERED) {
|
|
8
|
-
* console.log('배송 완료')
|
|
9
|
-
* }
|
|
4
|
+
* 모든 택배사의 상태를 하나의 통합 코드로 정규화합니다.
|
|
10
5
|
*/
|
|
11
6
|
declare enum CourierDeliveryStatus {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
OUT_FOR_DELIVERY = "OUT_FOR_DELIVERY",
|
|
24
|
-
/** 배송 완료 */
|
|
25
|
-
DELIVERED = "DELIVERED",
|
|
26
|
-
/** 배송 실패 */
|
|
27
|
-
FAILED = "FAILED",
|
|
28
|
-
/** 반송 */
|
|
29
|
-
RETURNED = "RETURNED",
|
|
30
|
-
/** 취소 */
|
|
31
|
-
CANCELLED = "CANCELLED",
|
|
32
|
-
/** 보류 */
|
|
33
|
-
HOLD = "HOLD",
|
|
34
|
-
/** 알 수 없음 */
|
|
7
|
+
PENDING = "PENDING",// 접수 대기
|
|
8
|
+
REGISTERED = "REGISTERED",// 접수 완료
|
|
9
|
+
PICKUP_READY = "PICKUP_READY",// 집하 준비
|
|
10
|
+
PICKED_UP = "PICKED_UP",// 집하 완료
|
|
11
|
+
IN_TRANSIT = "IN_TRANSIT",// 배송 중
|
|
12
|
+
OUT_FOR_DELIVERY = "OUT_FOR_DELIVERY",// 배송 출발
|
|
13
|
+
DELIVERED = "DELIVERED",// 배송 완료
|
|
14
|
+
FAILED = "FAILED",// 배송 실패
|
|
15
|
+
RETURNED = "RETURNED",// 반송
|
|
16
|
+
CANCELLED = "CANCELLED",// 취소
|
|
17
|
+
HOLD = "HOLD",// 보류
|
|
35
18
|
UNKNOWN = "UNKNOWN"
|
|
36
19
|
}
|
|
20
|
+
|
|
37
21
|
/**
|
|
38
|
-
* API 에러 코드
|
|
22
|
+
* API 에러 코드 (모든 엔드포인트 공통)
|
|
23
|
+
*
|
|
24
|
+
* ApiResponse.errorCode 필드에 포함되어 반환됩니다.
|
|
25
|
+
* 클라이언트가 에러 유형을 프로그래밍적으로 구분할 수 있도록 합니다.
|
|
39
26
|
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
27
|
+
* 참고: 택배 조회의 아이템별 에러는 TrackingErrorCode를 사용합니다.
|
|
28
|
+
* (TrackingResult.error.code 필드)
|
|
42
29
|
*/
|
|
43
|
-
type ApiErrorCode = 'UNAUTHORIZED' | 'FORBIDDEN' | '
|
|
30
|
+
type ApiErrorCode = 'UNAUTHORIZED' | 'FORBIDDEN' | 'MISSING_PARAMS' | 'INVALID_PARAMS' | 'NOT_FOUND' | 'CONFLICT' | 'RATE_LIMITED' | 'EMAIL_ALREADY_EXISTS' | 'COURIER_OTP_REQUIRED' | 'COURIER_AUTH_FAILED' | 'WEBHOOK_ENDPOINT_LIMIT' | 'WEBHOOK_ENDPOINT_UNREACHABLE' | 'INVALID_ITEMS' | 'NOT_IMPLEMENTED' | 'INTERNAL_ERROR';
|
|
31
|
+
|
|
44
32
|
/**
|
|
45
|
-
*
|
|
33
|
+
* 택배사 코드 상수 및 정보
|
|
46
34
|
*
|
|
47
|
-
*
|
|
35
|
+
* ⚠️ 이 파일은 farmfree/packages/common과 별도로 관리됩니다
|
|
36
|
+
* - delivery-saas-api-functions는 완전히 독립된 프로젝트입니다
|
|
37
|
+
* - farmfree와 코드를 공유하지 않습니다 (API 호출만 함)
|
|
48
38
|
*/
|
|
49
|
-
|
|
39
|
+
declare const COURIER_CODES: {
|
|
40
|
+
readonly LOTTE: "lotte";
|
|
41
|
+
readonly CJ: "cj";
|
|
42
|
+
readonly POST: "post";
|
|
43
|
+
readonly HANJIN: "hanjin";
|
|
44
|
+
readonly LOGEN: "logen";
|
|
45
|
+
readonly GSPOSTBOX: "gspostbox";
|
|
46
|
+
readonly ILYANG: "ilyang";
|
|
47
|
+
readonly KYUNGDONG: "kyungdong";
|
|
48
|
+
readonly DAESIN: "daesin";
|
|
49
|
+
readonly HAPDONG: "hapdong";
|
|
50
|
+
readonly COUPANG: "coupang";
|
|
51
|
+
readonly WOORI: "woori";
|
|
52
|
+
};
|
|
53
|
+
type CourierCode = (typeof COURIER_CODES)[keyof typeof COURIER_CODES];
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* 택배사 ID 타입
|
|
57
|
+
* COURIER_INFO_MAP의 CourierCode와 동일
|
|
58
|
+
*/
|
|
59
|
+
type CourierProviderId = CourierCode;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* 개별 택배 조회 항목
|
|
63
|
+
*/
|
|
64
|
+
interface TrackingItem {
|
|
65
|
+
id?: string;
|
|
66
|
+
clientId?: string;
|
|
67
|
+
courierCode: string;
|
|
68
|
+
trackingNumber: string;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* 택배 조회 요청 (배열로 다건 지원)
|
|
72
|
+
*/
|
|
73
|
+
interface TrackingRequest {
|
|
74
|
+
items: TrackingItem[];
|
|
75
|
+
includeProgresses?: boolean;
|
|
76
|
+
}
|
|
50
77
|
/**
|
|
51
|
-
*
|
|
78
|
+
* 택배 진행 상황
|
|
52
79
|
*/
|
|
53
80
|
interface TrackingProgress {
|
|
54
|
-
/** 처리 시간 (ISO 8601) */
|
|
55
81
|
dateTime: string;
|
|
56
|
-
/** 처리 위치 (예: "서울 허브") */
|
|
57
82
|
location: string;
|
|
58
|
-
/** 택배사 원본 상태 텍스트 */
|
|
59
83
|
status: string;
|
|
60
|
-
/** 정규화된 상태 코드 */
|
|
61
84
|
statusCode?: CourierDeliveryStatus;
|
|
62
|
-
/** 상세 설명 */
|
|
63
85
|
description?: string;
|
|
64
|
-
/** 연락처 */
|
|
65
86
|
telno?: string;
|
|
66
|
-
/** 추가 연락처 */
|
|
67
87
|
telno2?: string;
|
|
68
88
|
}
|
|
69
89
|
/**
|
|
70
|
-
* 통합 택배 조회
|
|
90
|
+
* 통합 택배 조회 응답
|
|
71
91
|
*/
|
|
72
92
|
interface UnifiedTrackingResponse {
|
|
73
|
-
/** 송장번호 */
|
|
74
93
|
trackingNumber: string;
|
|
75
|
-
/** 택배사 코드 (예: `'cj'`, `'lotte'`) */
|
|
76
94
|
courierCode: string;
|
|
77
|
-
/** 택배사 이름 (예: `'CJ대한통운'`) */
|
|
78
95
|
courierName: string;
|
|
79
|
-
/** 정규화된 배송 상태 코드 */
|
|
80
96
|
deliveryStatus: CourierDeliveryStatus;
|
|
81
|
-
/** 택배사 원본 상태 텍스트 */
|
|
82
97
|
deliveryStatusText: string;
|
|
83
|
-
/** 배송 완료 여부 */
|
|
84
98
|
isDelivered: boolean;
|
|
85
|
-
/** 발송인 이름 */
|
|
86
99
|
senderName?: string;
|
|
87
|
-
/** 수취인 이름 */
|
|
88
100
|
receiverName?: string;
|
|
89
|
-
/** 수취인 주소 */
|
|
90
101
|
receiverAddress?: string;
|
|
91
|
-
/** 상품명 */
|
|
92
102
|
productName?: string;
|
|
93
|
-
/** 수량 */
|
|
94
103
|
productQuantity?: number;
|
|
95
|
-
/** 배송 완료일 (ISO 8601, 완료 시에만 존재) */
|
|
96
104
|
dateDelivered?: string;
|
|
97
|
-
/** 배송 예정일 (ISO 8601) */
|
|
98
105
|
dateEstimated?: string;
|
|
99
|
-
/** 마지막 진행 날짜/시간 (`yyyy-MM-dd HH:mm:ss`) */
|
|
100
106
|
dateLastProgress: string;
|
|
101
|
-
/** 배송 진행 내역 (최신순) */
|
|
102
107
|
progresses: TrackingProgress[];
|
|
103
|
-
/** 조회 시점 (ISO 8601) */
|
|
104
108
|
queriedAt: string;
|
|
105
109
|
}
|
|
106
110
|
/**
|
|
107
|
-
*
|
|
111
|
+
* 택배 조회 에러 코드
|
|
112
|
+
*
|
|
113
|
+
* 과금 정책:
|
|
114
|
+
* - NOT_FOUND만 과금 (택배사 API를 호출했으나 데이터 없음 = 사용자 책임)
|
|
115
|
+
* - 나머지는 비과금 (요청 검증 실패 또는 시스템 오류)
|
|
108
116
|
*/
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
117
|
+
type TrackingErrorCode = 'MISSING_PARAMS' | 'INVALID_TRACKING_NUMBER' | 'UNSUPPORTED_COURIER' | 'NOT_FOUND' | 'TRACKING_FAILED';
|
|
118
|
+
/**
|
|
119
|
+
* 택배 조회 오류
|
|
120
|
+
*/
|
|
121
|
+
interface TrackingError {
|
|
122
|
+
code: TrackingErrorCode;
|
|
123
|
+
message: string;
|
|
124
|
+
courierCode?: string;
|
|
125
|
+
trackingNumber?: string;
|
|
126
|
+
details?: unknown;
|
|
127
|
+
billable: boolean;
|
|
120
128
|
}
|
|
121
129
|
/**
|
|
122
|
-
*
|
|
130
|
+
* 택배 조회 아이템별 에러 (courierCode, trackingNumber 필수)
|
|
123
131
|
*
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
* items: [
|
|
127
|
-
* { courierCode: 'cj', trackingNumber: '1234567890', clientId: 'order_001' }
|
|
128
|
-
* ],
|
|
129
|
-
* includeProgresses: true,
|
|
130
|
-
* })
|
|
132
|
+
* TrackingError의 변형으로, 개별 조회 결과에서 사용
|
|
133
|
+
* (courierCode/trackingNumber가 반드시 존재하는 경우)
|
|
131
134
|
*/
|
|
132
|
-
interface
|
|
133
|
-
/** 조회할 택배 목록 (1건도 배열로 전달) */
|
|
134
|
-
items: TraceItem[];
|
|
135
|
-
/**
|
|
136
|
-
* 배송 진행 내역 포함 여부
|
|
137
|
-
*
|
|
138
|
-
* `false`로 설정하면 `progresses`가 빈 배열로 반환됩니다.
|
|
139
|
-
* 상태만 확인할 때 사용하면 응답 크기가 줄어듭니다.
|
|
140
|
-
* @default true
|
|
141
|
-
*/
|
|
142
|
-
includeProgresses?: boolean;
|
|
143
|
-
}
|
|
144
|
-
/** 아이템별 조회 에러 */
|
|
145
|
-
interface TraceItemError {
|
|
146
|
-
/** 에러 코드 */
|
|
135
|
+
interface TrackingItemError {
|
|
147
136
|
code: TrackingErrorCode;
|
|
148
|
-
/** 에러 메시지 */
|
|
149
137
|
message: string;
|
|
150
|
-
/** 택배사 코드 */
|
|
151
138
|
courierCode: string;
|
|
152
|
-
/** 송장번호 */
|
|
153
139
|
trackingNumber: string;
|
|
154
|
-
/**
|
|
155
|
-
* 과금 여부
|
|
156
|
-
*
|
|
157
|
-
* `true`이면 이 건은 사용량으로 집계됩니다.
|
|
158
|
-
* `NOT_FOUND` 에러만 과금됩니다.
|
|
159
|
-
*/
|
|
160
140
|
billable: boolean;
|
|
161
141
|
}
|
|
162
|
-
/**
|
|
163
|
-
|
|
164
|
-
|
|
142
|
+
/**
|
|
143
|
+
* 캐시 메타데이터
|
|
144
|
+
*/
|
|
145
|
+
interface TrackingCacheInfo {
|
|
165
146
|
fromCache: boolean;
|
|
166
|
-
/** 캐시 저장 시점 (ISO 8601, 캐시 히트 시에만 존재) */
|
|
167
147
|
cachedAt?: string;
|
|
168
148
|
}
|
|
169
|
-
/**
|
|
170
|
-
|
|
171
|
-
|
|
149
|
+
/**
|
|
150
|
+
* 개별 택배 조회 결과
|
|
151
|
+
*/
|
|
152
|
+
interface TrackingResult {
|
|
153
|
+
id?: string;
|
|
172
154
|
clientId?: string;
|
|
173
|
-
/** 조회 성공 여부 */
|
|
174
155
|
success: boolean;
|
|
175
|
-
/** 성공 시 배송 정보 */
|
|
176
156
|
data?: UnifiedTrackingResponse;
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
interface
|
|
184
|
-
|
|
185
|
-
results: TraceResult[];
|
|
186
|
-
/** 집계 요약 */
|
|
157
|
+
error?: TrackingError;
|
|
158
|
+
cache?: TrackingCacheInfo;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* 택배 조회 응답 (배열로 다건 응답)
|
|
162
|
+
*/
|
|
163
|
+
interface TrackingResponse {
|
|
164
|
+
results: TrackingResult[];
|
|
187
165
|
summary: {
|
|
188
|
-
/** 전체 요청 건수 */
|
|
189
166
|
total: number;
|
|
190
|
-
/** 성공 건수 */
|
|
191
167
|
successful: number;
|
|
192
|
-
/** 실패 건수 */
|
|
193
168
|
failed: number;
|
|
194
|
-
/** 과금 대상 건수 (성공 + `NOT_FOUND`) */
|
|
195
169
|
billable: number;
|
|
196
170
|
};
|
|
197
171
|
}
|
|
198
|
-
|
|
199
|
-
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Firebase Timestamp 호환 인터페이스
|
|
175
|
+
* firebase-admin/firestore 및 firebase/firestore의 Timestamp와 구조적으로 호환됨
|
|
176
|
+
*/
|
|
177
|
+
interface Timestamp {
|
|
178
|
+
seconds: number;
|
|
179
|
+
nanoseconds: number;
|
|
180
|
+
toDate(): Date;
|
|
181
|
+
toMillis(): number;
|
|
182
|
+
isEqual(other: Timestamp): boolean;
|
|
183
|
+
valueOf(): string;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* 웹훅 시스템 타입 정의
|
|
188
|
+
* - 다건 추적 요청 (최대 100건)
|
|
189
|
+
* - 재시도 없음 (1시간 폴링이 자연 재전송)
|
|
190
|
+
* - 엔드포인트별 독립 컬렉션
|
|
191
|
+
*/
|
|
192
|
+
|
|
193
|
+
type TrackingBatchStatus = 'active' | 'completed' | 'cancelled';
|
|
194
|
+
interface TrackingBatchSummary {
|
|
195
|
+
total: number;
|
|
196
|
+
delivered: number;
|
|
197
|
+
active: number;
|
|
198
|
+
failed: number;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* 웹훅으로 전송되는 개별 항목
|
|
202
|
+
*/
|
|
203
|
+
interface WebhookTrackingItem {
|
|
204
|
+
courierCode: string;
|
|
205
|
+
trackingNumber: string;
|
|
206
|
+
clientId?: string;
|
|
207
|
+
currentStatus: CourierDeliveryStatus;
|
|
208
|
+
previousStatus?: CourierDeliveryStatus;
|
|
209
|
+
hasChanged: boolean;
|
|
210
|
+
isDelivered: boolean;
|
|
211
|
+
trackingData?: UnifiedTrackingResponse;
|
|
212
|
+
error?: string;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* 웹훅 POST 페이로드
|
|
216
|
+
*/
|
|
217
|
+
interface WebhookPayload {
|
|
218
|
+
event: 'tracking.polled' | 'tracking.completed';
|
|
219
|
+
requestId: string;
|
|
220
|
+
timestamp: string;
|
|
221
|
+
summary: {
|
|
222
|
+
total: number;
|
|
223
|
+
delivered: number;
|
|
224
|
+
active: number;
|
|
225
|
+
hasChanges: boolean;
|
|
226
|
+
};
|
|
227
|
+
items: WebhookTrackingItem[];
|
|
228
|
+
metadata?: Record<string, string>;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/** 지원 택배사 정보 (API 응답용) */
|
|
232
|
+
interface CourierInfoResponse {
|
|
200
233
|
/** 택배사 코드 (예: `'cj'`, `'lotte'`) */
|
|
201
234
|
trackingApiCode: string;
|
|
202
235
|
/** 택배사 표시명 (예: `'CJ대한통운'`) */
|
|
203
236
|
displayName: string;
|
|
204
237
|
}
|
|
205
|
-
/**
|
|
206
|
-
interface
|
|
207
|
-
|
|
208
|
-
couriers: CourierInfo[];
|
|
209
|
-
/** 전체 택배사 수 */
|
|
238
|
+
/** GET /v1/tracking/couriers 응답 */
|
|
239
|
+
interface GetCouriersApiResponse {
|
|
240
|
+
couriers: CourierInfoResponse[];
|
|
210
241
|
total: number;
|
|
211
242
|
}
|
|
212
|
-
/**
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
* @example
|
|
216
|
-
* const endpoint = await client.webhooks.endpoints.create({
|
|
217
|
-
* url: 'https://my-server.com/webhook',
|
|
218
|
-
* name: '운영 서버',
|
|
219
|
-
* })
|
|
220
|
-
* // endpoint.webhookSecret 은 이 응답에서만 확인 가능합니다 — 안전하게 보관하세요!
|
|
221
|
-
*/
|
|
222
|
-
interface CreateEndpointParams {
|
|
223
|
-
/**
|
|
224
|
-
* 웹훅을 수신할 URL
|
|
225
|
-
*
|
|
226
|
-
* `https://` 로 시작해야 합니다.
|
|
227
|
-
* 등록 시 서버에서 테스트 POST 요청을 전송하여 URL을 검증합니다.
|
|
228
|
-
*/
|
|
243
|
+
/** POST /v1/webhooks/endpoints 요청 */
|
|
244
|
+
interface CreateEndpointRequest {
|
|
245
|
+
/** 웹훅 수신 URL (https:// 필수) */
|
|
229
246
|
url: string;
|
|
230
|
-
/** 엔드포인트 이름
|
|
231
|
-
name
|
|
232
|
-
/**
|
|
233
|
-
* 서명 시크릿 직접 지정 (선택)
|
|
234
|
-
*
|
|
235
|
-
* 미제공 시 서버가 랜덤 시크릿을 생성합니다.
|
|
236
|
-
* 최소 5자 이상이어야 합니다.
|
|
237
|
-
*/
|
|
247
|
+
/** 엔드포인트 이름 */
|
|
248
|
+
name?: string;
|
|
249
|
+
/** 서명 시크릿 직접 지정 (선택, 미제공 시 서버 생성, 최소 5자) */
|
|
238
250
|
webhookSecret?: string;
|
|
239
251
|
}
|
|
240
|
-
/**
|
|
241
|
-
interface
|
|
242
|
-
/** 생성된 엔드포인트 ID */
|
|
252
|
+
/** POST /v1/webhooks/endpoints 응답 */
|
|
253
|
+
interface CreateEndpointApiResponse {
|
|
243
254
|
endpointId: string;
|
|
244
|
-
/** 등록된 URL */
|
|
245
255
|
url: string;
|
|
246
|
-
/** 엔드포인트 이름 */
|
|
247
256
|
name?: string;
|
|
248
|
-
/**
|
|
249
|
-
* 웹훅 서명 시크릿
|
|
250
|
-
*
|
|
251
|
-
* **이 응답에서만 평문으로 반환됩니다. 이후에는 조회 불가합니다.**
|
|
252
|
-
* 분실 시 `rotateSecret()`으로 재발급해야 합니다.
|
|
253
|
-
*
|
|
254
|
-
* 수신된 웹훅의 `X-Webhook-Signature` 헤더를 이 값으로 HMAC-SHA256 검증하세요.
|
|
255
|
-
*/
|
|
257
|
+
/** 최초 1회만 평문 반환 */
|
|
256
258
|
webhookSecret: string;
|
|
257
|
-
/** 생성 시각 (ISO 8601) */
|
|
258
259
|
dateCreated: string;
|
|
259
260
|
}
|
|
260
261
|
/** 엔드포인트 목록 아이템 */
|
|
261
|
-
interface
|
|
262
|
-
/** 엔드포인트 ID */
|
|
262
|
+
interface EndpointListItem {
|
|
263
263
|
endpointId: string;
|
|
264
|
-
/** 웹훅 수신 URL */
|
|
265
264
|
url: string;
|
|
266
|
-
/** 엔드포인트 이름 */
|
|
267
265
|
name?: string;
|
|
268
|
-
/**
|
|
269
|
-
* 엔드포인트 상태
|
|
270
|
-
*
|
|
271
|
-
* 연속 5회 이상 전송 실패 시 자동으로 `inactive` 로 전환됩니다.
|
|
272
|
-
*/
|
|
273
266
|
status: 'active' | 'inactive';
|
|
274
|
-
/**
|
|
275
|
-
* 연속 실패 횟수
|
|
276
|
-
*
|
|
277
|
-
* 5회 초과 시 엔드포인트가 비활성화됩니다.
|
|
278
|
-
*/
|
|
279
267
|
consecutiveFailures: number;
|
|
280
|
-
/** 생성 시각 (ISO 8601) */
|
|
281
268
|
dateCreated: string;
|
|
282
|
-
/** 최종 수정 시각 (ISO 8601) */
|
|
283
269
|
dateModified: string;
|
|
284
270
|
}
|
|
285
|
-
/**
|
|
286
|
-
interface
|
|
287
|
-
|
|
288
|
-
endpoints: EndpointInfo[];
|
|
289
|
-
/** 전체 수 */
|
|
271
|
+
/** GET /v1/webhooks/endpoints 응답 */
|
|
272
|
+
interface ListEndpointsApiResponse {
|
|
273
|
+
endpoints: EndpointListItem[];
|
|
290
274
|
total: number;
|
|
291
275
|
}
|
|
292
|
-
/**
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
* URL은 변경할 수 없습니다. 이름만 수정 가능합니다.
|
|
296
|
-
*/
|
|
297
|
-
interface UpdateEndpointParams {
|
|
298
|
-
/** 새 엔드포인트 이름 */
|
|
276
|
+
/** PATCH /v1/webhooks/endpoints/:id 요청 */
|
|
277
|
+
interface UpdateEndpointRequest {
|
|
278
|
+
/** name만 변경 가능, URL 변경 불가 */
|
|
299
279
|
name: string;
|
|
300
280
|
}
|
|
301
|
-
/**
|
|
302
|
-
|
|
303
|
-
*/
|
|
304
|
-
interface RotateSecretParams {
|
|
305
|
-
/**
|
|
306
|
-
* 새 시크릿 직접 지정 (선택)
|
|
307
|
-
*
|
|
308
|
-
* 미제공 시 서버가 랜덤 시크릿을 생성합니다.
|
|
309
|
-
*/
|
|
281
|
+
/** POST /v1/webhooks/endpoints/:id/rotate-secret 요청 */
|
|
282
|
+
interface RotateSecretRequest {
|
|
283
|
+
/** 새 시크릿 직접 지정 (선택, 미제공 시 서버 생성) */
|
|
310
284
|
webhookSecret?: string;
|
|
311
285
|
}
|
|
312
|
-
/**
|
|
313
|
-
interface
|
|
314
|
-
/** 엔드포인트 ID */
|
|
286
|
+
/** POST /v1/webhooks/endpoints/:id/rotate-secret 응답 */
|
|
287
|
+
interface RotateSecretApiResponse {
|
|
315
288
|
endpointId: string;
|
|
316
|
-
/**
|
|
317
|
-
* 새 웹훅 서명 시크릿
|
|
318
|
-
*
|
|
319
|
-
* **이 응답에서만 평문으로 반환됩니다.**
|
|
320
|
-
*/
|
|
289
|
+
/** 최초 1회만 평문 반환 */
|
|
321
290
|
webhookSecret: string;
|
|
322
|
-
/** 재발급 시각 (ISO 8601) */
|
|
323
291
|
dateRotated: string;
|
|
324
292
|
}
|
|
325
|
-
/**
|
|
326
|
-
interface
|
|
327
|
-
/** 택배사 코드 (예: `'cj'`, `'lotte'`) */
|
|
293
|
+
/** 추적 등록 아이템 */
|
|
294
|
+
interface RegisterTrackingItem {
|
|
328
295
|
courierCode: string;
|
|
329
|
-
/** 송장번호 */
|
|
330
296
|
trackingNumber: string;
|
|
331
|
-
/**
|
|
332
|
-
* 클라이언트 매핑 ID (선택)
|
|
333
|
-
*
|
|
334
|
-
* 주문번호 등을 넣으면 웹훅 페이로드에 그대로 포함됩니다.
|
|
335
|
-
*/
|
|
297
|
+
/** 클라이언트 매핑 ID (선택, 웹훅 페이로드에 그대로 포함) */
|
|
336
298
|
clientId?: string;
|
|
337
299
|
}
|
|
338
|
-
/**
|
|
339
|
-
interface
|
|
340
|
-
/**
|
|
341
|
-
* 구독/요청 ID
|
|
342
|
-
*
|
|
343
|
-
* `subscriptions.get(requestId)`, `subscriptions.cancel(requestId)` 에 사용합니다.
|
|
344
|
-
*/
|
|
300
|
+
/** POST /v1/webhooks/subscriptions 응답 */
|
|
301
|
+
interface RegisterTrackingApiResponse {
|
|
345
302
|
requestId: string;
|
|
346
|
-
/** 등록된 아이템 수 */
|
|
347
303
|
itemCount: number;
|
|
348
|
-
/** 반복 구독 여부 */
|
|
349
304
|
recurring: boolean;
|
|
350
305
|
}
|
|
351
|
-
/**
|
|
352
|
-
interface
|
|
353
|
-
/**
|
|
354
|
-
total: number;
|
|
355
|
-
/** 배송 완료 수 */
|
|
356
|
-
delivered: number;
|
|
357
|
-
/** 배송 진행 중 수 */
|
|
358
|
-
active: number;
|
|
359
|
-
/** 조회 실패 수 */
|
|
360
|
-
failed: number;
|
|
361
|
-
}
|
|
362
|
-
/** `webhooks.subscriptions.list()` 파라미터 */
|
|
363
|
-
interface ListSubscriptionsParams {
|
|
364
|
-
/**
|
|
365
|
-
* 페이지네이션 커서
|
|
366
|
-
*
|
|
367
|
-
* 이전 응답의 `nextCursor` 값을 전달합니다.
|
|
368
|
-
* 생략하면 처음부터 조회합니다.
|
|
369
|
-
*/
|
|
306
|
+
/** GET /v1/webhooks/subscriptions 요청 파라미터 */
|
|
307
|
+
interface ListSubscriptionsRequest {
|
|
308
|
+
/** 페이지네이션 커서 (이전 응답의 nextCursor) */
|
|
370
309
|
cursor?: string;
|
|
371
|
-
/** 페이지 크기 */
|
|
372
310
|
limit?: number;
|
|
311
|
+
status?: 'active' | 'completed' | 'cancelled';
|
|
312
|
+
/** 시작일 필터 (YYYY-MM-DD) */
|
|
313
|
+
from?: string;
|
|
314
|
+
/** 종료일 필터 (YYYY-MM-DD) */
|
|
315
|
+
to?: string;
|
|
373
316
|
}
|
|
374
317
|
/** 구독 목록 아이템 */
|
|
375
318
|
interface SubscriptionListItem {
|
|
376
|
-
/** 구독 ID */
|
|
377
319
|
requestId: string;
|
|
378
|
-
/** 연결된 엔드포인트 ID */
|
|
379
320
|
endpointId?: string;
|
|
380
|
-
/** 반복 구독 여부 */
|
|
381
321
|
recurring: boolean;
|
|
382
|
-
/** 구독 활성 여부 */
|
|
383
322
|
isActive: boolean;
|
|
384
|
-
|
|
323
|
+
status: TrackingBatchStatus;
|
|
385
324
|
itemCount: number;
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
325
|
+
summary: {
|
|
326
|
+
total: number;
|
|
327
|
+
delivered: number;
|
|
328
|
+
active: number;
|
|
329
|
+
failed: number;
|
|
330
|
+
};
|
|
389
331
|
dateCreated: string;
|
|
390
332
|
}
|
|
391
|
-
/**
|
|
392
|
-
interface
|
|
393
|
-
/** 구독 목록 */
|
|
333
|
+
/** GET /v1/webhooks/subscriptions 응답 */
|
|
334
|
+
interface ListSubscriptionsApiResponse {
|
|
394
335
|
subscriptions: SubscriptionListItem[];
|
|
395
|
-
/** 전체 수 */
|
|
396
336
|
total: number;
|
|
397
|
-
/**
|
|
398
|
-
* 다음 페이지 커서
|
|
399
|
-
*
|
|
400
|
-
* 마지막 페이지이면 존재하지 않습니다.
|
|
401
|
-
*/
|
|
337
|
+
/** 다음 페이지 커서 (마지막 페이지이면 없음) */
|
|
402
338
|
nextCursor?: string;
|
|
403
339
|
}
|
|
404
|
-
/**
|
|
405
|
-
interface
|
|
406
|
-
/** 택배사 코드 */
|
|
340
|
+
/** 추적 결과 아이템 (구독 상세/배치 결과에서 사용) */
|
|
341
|
+
interface TrackingResultItem {
|
|
407
342
|
courierCode: string;
|
|
408
|
-
/** 송장번호 */
|
|
409
343
|
trackingNumber: string;
|
|
410
|
-
/** 클라이언트 매핑 ID */
|
|
411
344
|
clientId?: string;
|
|
412
|
-
/** 현재 배송 상태 */
|
|
413
345
|
currentStatus: CourierDeliveryStatus;
|
|
414
|
-
/** 이전 배송 상태 */
|
|
415
346
|
previousStatus?: CourierDeliveryStatus;
|
|
416
|
-
/** 상태 변경 여부 */
|
|
417
347
|
hasChanged: boolean;
|
|
418
|
-
/** 배송 완료 여부 */
|
|
419
348
|
isDelivered: boolean;
|
|
420
|
-
/** 최신 배송 조회 데이터 */
|
|
421
349
|
trackingData?: UnifiedTrackingResponse;
|
|
422
|
-
/** 조회 에러 메시지 (실패 시) */
|
|
423
350
|
error?: string;
|
|
424
351
|
}
|
|
425
|
-
/**
|
|
426
|
-
interface
|
|
427
|
-
/** 구독 ID */
|
|
352
|
+
/** GET /v1/webhooks/subscriptions/:id 응답 */
|
|
353
|
+
interface SubscriptionDetailApiResponse {
|
|
428
354
|
requestId: string;
|
|
429
|
-
/** 연결된 엔드포인트 ID */
|
|
430
355
|
endpointId?: string;
|
|
431
|
-
/** 반복 구독 여부 */
|
|
432
356
|
recurring: boolean;
|
|
433
|
-
/** 구독 활성 여부 */
|
|
434
357
|
isActive: boolean;
|
|
435
|
-
|
|
358
|
+
status: TrackingBatchStatus;
|
|
436
359
|
itemCount: number;
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
360
|
+
summary: {
|
|
361
|
+
total: number;
|
|
362
|
+
delivered: number;
|
|
363
|
+
active: number;
|
|
364
|
+
failed: number;
|
|
365
|
+
};
|
|
366
|
+
items: TrackingResultItem[];
|
|
442
367
|
lastPolledAt?: string;
|
|
443
|
-
/** 다음 폴링 예정 시각 (ISO 8601) */
|
|
444
368
|
nextPollAt?: string;
|
|
445
|
-
/** 이용자 정의 메타데이터 */
|
|
446
369
|
metadata?: Record<string, string>;
|
|
447
|
-
/** 등록 시각 (ISO 8601) */
|
|
448
370
|
dateCreated: string;
|
|
449
|
-
/** 최종 수정 시각 (ISO 8601) */
|
|
450
371
|
dateModified: string;
|
|
451
372
|
}
|
|
452
|
-
/**
|
|
373
|
+
/** 배치 결과 검색 아이템 */
|
|
453
374
|
interface BatchResultItem {
|
|
454
|
-
/** 택배사 코드 */
|
|
455
375
|
courierCode: string;
|
|
456
|
-
/** 송장번호 */
|
|
457
376
|
trackingNumber: string;
|
|
458
377
|
}
|
|
459
|
-
/**
|
|
460
|
-
|
|
461
|
-
*
|
|
462
|
-
* 여러 송장번호의 최신 배송 정보를 한 번에 조회합니다.
|
|
463
|
-
* 구독 ID가 아닌 (택배사 코드 + 송장번호)로 검색합니다.
|
|
464
|
-
*/
|
|
465
|
-
interface BatchResultsParams {
|
|
466
|
-
/** 조회할 아이템 목록 */
|
|
378
|
+
/** POST /v1/webhooks/subscriptions/batch-results 요청 */
|
|
379
|
+
interface BatchResultsRequest {
|
|
467
380
|
items: BatchResultItem[];
|
|
468
381
|
}
|
|
469
382
|
/** 배치 결과 단건 */
|
|
470
383
|
interface BatchResultEntry {
|
|
471
|
-
/** 택배사 코드 */
|
|
472
384
|
courierCode: string;
|
|
473
|
-
/** 송장번호 */
|
|
474
385
|
trackingNumber: string;
|
|
475
|
-
/** 클라이언트 매핑 ID */
|
|
476
386
|
clientId?: string;
|
|
477
|
-
/** 구독 ID */
|
|
478
387
|
requestId: string;
|
|
479
|
-
/** 현재 배송 상태 */
|
|
480
388
|
currentStatus: CourierDeliveryStatus;
|
|
481
|
-
/** 배송 완료 여부 */
|
|
482
389
|
isDelivered: boolean;
|
|
483
|
-
/** 최신 배송 데이터 */
|
|
484
390
|
trackingData?: UnifiedTrackingResponse;
|
|
485
|
-
/** 에러 메시지 (실패 시) */
|
|
486
391
|
error?: string;
|
|
487
|
-
/** 마지막 폴링 시각 (ISO 8601) */
|
|
488
392
|
lastPolledAt?: string;
|
|
489
393
|
}
|
|
490
|
-
/**
|
|
491
|
-
interface
|
|
492
|
-
/** 결과 목록 */
|
|
394
|
+
/** POST /v1/webhooks/subscriptions/batch-results 응답 */
|
|
395
|
+
interface BatchResultsApiResponse {
|
|
493
396
|
results: BatchResultEntry[];
|
|
494
|
-
/** 전체 수 */
|
|
495
397
|
total: number;
|
|
496
398
|
}
|
|
399
|
+
|
|
497
400
|
/**
|
|
498
|
-
*
|
|
499
|
-
*
|
|
500
|
-
*
|
|
501
|
-
* `X-Webhook-Signature` 헤더를 `webhookSecret`으로 HMAC-SHA256 검증하세요.
|
|
502
|
-
*
|
|
503
|
-
* @example
|
|
504
|
-
* // Express 수신 예시
|
|
505
|
-
* app.post('/webhook', (req, res) => {
|
|
506
|
-
* const sig = req.headers['x-webhook-signature']
|
|
507
|
-
* const body = JSON.stringify(req.body)
|
|
508
|
-
* const expected = crypto.createHmac('sha256', webhookSecret).update(body).digest('hex')
|
|
509
|
-
* if (sig !== expected) return res.status(401).send('Invalid signature')
|
|
401
|
+
* transmitting: sent to courier but no response received (may or may not be registered — system failure)
|
|
402
|
+
* completed: courier response received + all successful items have courierDeliveryId secured
|
|
403
|
+
* failed: courier response received + all items rejected (zero successes)
|
|
510
404
|
*
|
|
511
|
-
*
|
|
512
|
-
* if (payload.event === 'tracking.completed') {
|
|
513
|
-
* console.log(`${payload.requestId} 배송 추적 완료`)
|
|
514
|
-
* }
|
|
515
|
-
* res.sendStatus(200)
|
|
516
|
-
* })
|
|
405
|
+
* Note: pre-validation failures (auth, address format, etc.) do not create a history document
|
|
517
406
|
*/
|
|
518
|
-
|
|
407
|
+
type BulkUploadStatus = 'transmitting' | 'completed' | 'failed' | 'deleted';
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* 배송 주소 정보
|
|
411
|
+
*/
|
|
412
|
+
interface DeliveryAddress {
|
|
413
|
+
zipCode?: string;
|
|
414
|
+
roadAddress?: string;
|
|
415
|
+
jibunAddress?: string;
|
|
416
|
+
detailAddress?: string;
|
|
417
|
+
fullAddress: string;
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
420
|
+
* 배송 담당자 정보
|
|
421
|
+
*/
|
|
422
|
+
interface DeliveryPerson {
|
|
423
|
+
name: string;
|
|
424
|
+
phoneNumber?: string;
|
|
425
|
+
branchName?: string;
|
|
426
|
+
branchCode?: string;
|
|
427
|
+
branchPhone?: string;
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* 요금 정보
|
|
431
|
+
*/
|
|
432
|
+
interface FareInfo {
|
|
433
|
+
fareType: string;
|
|
434
|
+
fareTypeCode?: string;
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* 택배 계정 조회 응답 (개별 배송 정보)
|
|
438
|
+
* UnifiedTrackingResponse를 확장하여 계정 조회에 필요한 추가 정보 포함
|
|
439
|
+
*/
|
|
440
|
+
interface AccountInquiryItem {
|
|
441
|
+
courierTrackingId: string;
|
|
442
|
+
trackingNumber: string;
|
|
443
|
+
orderNumber?: string;
|
|
444
|
+
courierCode: string;
|
|
445
|
+
courierName: string;
|
|
446
|
+
deliveryStatus: CourierDeliveryStatus;
|
|
447
|
+
deliveryStatusText: string;
|
|
448
|
+
isDelivered: boolean;
|
|
449
|
+
cancelReason?: string;
|
|
450
|
+
isReturn?: boolean;
|
|
451
|
+
returnType?: string;
|
|
452
|
+
originalTrackingNumber?: string;
|
|
453
|
+
senderName: string;
|
|
454
|
+
senderPhone?: string;
|
|
455
|
+
senderPhone2?: string;
|
|
456
|
+
senderAddress?: DeliveryAddress;
|
|
457
|
+
receiverName: string;
|
|
458
|
+
receiverPhone: string;
|
|
459
|
+
receiverPhone2?: string;
|
|
460
|
+
receiverAddress: DeliveryAddress;
|
|
461
|
+
productName: string;
|
|
462
|
+
productQuantity: number;
|
|
463
|
+
productDetails?: string;
|
|
464
|
+
productOption?: string;
|
|
465
|
+
deliveryMessage?: string;
|
|
466
|
+
pickupDate?: string;
|
|
467
|
+
firstScanDate?: string;
|
|
468
|
+
deliveryDate?: string;
|
|
469
|
+
estimatedDeliveryDate?: string;
|
|
470
|
+
pickupBranch?: DeliveryPerson;
|
|
471
|
+
deliveryBranch?: DeliveryPerson;
|
|
472
|
+
pickupPerson?: DeliveryPerson;
|
|
473
|
+
deliveryPerson?: DeliveryPerson;
|
|
474
|
+
fareInfo?: FareInfo;
|
|
475
|
+
accountCustomerCode?: string;
|
|
476
|
+
accountCustomerName?: string;
|
|
477
|
+
pickupCustomerCode?: string;
|
|
478
|
+
pickupCustomerName?: string;
|
|
479
|
+
queriedAt: string;
|
|
480
|
+
rawData?: Record<string, unknown>;
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* 택배 계정 조회 응답
|
|
484
|
+
*/
|
|
485
|
+
interface AccountInquiryResponse {
|
|
486
|
+
items: AccountInquiryItem[];
|
|
487
|
+
summary: {
|
|
488
|
+
total: number;
|
|
489
|
+
pending: number;
|
|
490
|
+
inTransit: number;
|
|
491
|
+
delivered: number;
|
|
492
|
+
cancelled: number;
|
|
493
|
+
returned: number;
|
|
494
|
+
};
|
|
495
|
+
dateRange: {
|
|
496
|
+
from: string;
|
|
497
|
+
to: string;
|
|
498
|
+
};
|
|
499
|
+
courierInfo: {
|
|
500
|
+
courierCode: string;
|
|
501
|
+
courierName: string;
|
|
502
|
+
accountId: string;
|
|
503
|
+
};
|
|
504
|
+
lastUpdated: string;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
/** Parameters for registering a courier account */
|
|
508
|
+
interface RegisterAccountParams {
|
|
509
|
+
/** Courier provider ID */
|
|
510
|
+
providerId: 'lotte' | 'cj';
|
|
511
|
+
/** Account login ID */
|
|
512
|
+
accountId: string;
|
|
513
|
+
/** Account login password */
|
|
514
|
+
accountPassword: string;
|
|
515
|
+
/** Display name for the account */
|
|
516
|
+
accountName?: string;
|
|
517
|
+
/** Account description */
|
|
518
|
+
description?: string;
|
|
519
|
+
/** Enable automatic SMS OTP capture (CJ 2FA accounts) */
|
|
520
|
+
smsAutoCapture?: boolean;
|
|
521
|
+
/** Phone number for receiving OTP SMS (used with smsAutoCapture) */
|
|
522
|
+
phoneNumber?: string;
|
|
523
|
+
}
|
|
524
|
+
/** Response from account registration (formatAccountResponse — 6 fields) */
|
|
525
|
+
interface RegisterAccountResponse {
|
|
526
|
+
/** Unique key for the registered account */
|
|
527
|
+
courierAccountKey: string;
|
|
528
|
+
/** Courier provider ID */
|
|
529
|
+
providerId: string;
|
|
530
|
+
/** Account login ID */
|
|
531
|
+
accountId: string;
|
|
532
|
+
/** Display name */
|
|
533
|
+
accountName: string;
|
|
534
|
+
/** Whether the account is active */
|
|
535
|
+
isActive: boolean;
|
|
536
|
+
/** Whether 2FA (OTP) is required */
|
|
537
|
+
requires2FA: boolean;
|
|
538
|
+
}
|
|
539
|
+
/** Account info returned in list response (GET /courier/accounts) */
|
|
540
|
+
interface CourierAccountInfo {
|
|
541
|
+
courierAccountKey: string;
|
|
542
|
+
providerId: string;
|
|
543
|
+
accountId: string;
|
|
544
|
+
accountName: string;
|
|
545
|
+
description: string;
|
|
546
|
+
isActive: boolean;
|
|
547
|
+
requires2FA: boolean;
|
|
548
|
+
smsAutoCapture: boolean;
|
|
549
|
+
/** Last inquiry date (ISO 8601) */
|
|
550
|
+
lastInquiryDate: string | null;
|
|
551
|
+
/** Account creation date (ISO 8601) */
|
|
552
|
+
dateCreated: string | null;
|
|
553
|
+
/** Token expiration date (ISO 8601) */
|
|
554
|
+
expiresAt: string | null;
|
|
555
|
+
}
|
|
556
|
+
/** Account detail returned by GET /courier/accounts/:accountKey (no expiresAt, has accountPassword) */
|
|
557
|
+
interface CourierAccountDetail extends Omit<CourierAccountInfo, 'expiresAt'> {
|
|
558
|
+
/** Always "(암호화하여 저장중)" — actual password is never exposed */
|
|
559
|
+
accountPassword: string;
|
|
560
|
+
}
|
|
561
|
+
/** SDK-friendly bulk upload item — sender fields are optional (account defaults used) */
|
|
562
|
+
interface BulkUploadItemParams {
|
|
563
|
+
/** Client-side order ID for result matching */
|
|
564
|
+
clientOrderId: string;
|
|
565
|
+
/** Receiver name */
|
|
566
|
+
receiverName: string;
|
|
567
|
+
/** Receiver phone number */
|
|
568
|
+
receiverPhone1: string;
|
|
569
|
+
/** Receiver address (road or jibun) */
|
|
570
|
+
receiverAddress: string;
|
|
571
|
+
/** Product name */
|
|
572
|
+
productName: string;
|
|
573
|
+
/** Product quantity */
|
|
574
|
+
quantity: number;
|
|
575
|
+
/** Receiver secondary phone */
|
|
576
|
+
receiverPhone2?: string;
|
|
577
|
+
/** Receiver detail address (building, floor, etc.) */
|
|
578
|
+
receiverDetailAddress?: string;
|
|
579
|
+
/** Receiver zip code */
|
|
580
|
+
receiverZipCode?: string;
|
|
581
|
+
/** Sender name (omit to use account default) */
|
|
582
|
+
senderName?: string;
|
|
583
|
+
/** Sender phone number (omit to use account default) */
|
|
584
|
+
senderPhone1?: string;
|
|
585
|
+
/** Sender secondary phone */
|
|
586
|
+
senderPhone2?: string;
|
|
587
|
+
/** Sender address (omit to use account default) */
|
|
588
|
+
senderAddress?: string;
|
|
589
|
+
/** Sender detail address */
|
|
590
|
+
senderDetailAddress?: string;
|
|
591
|
+
/** Sender zip code */
|
|
592
|
+
senderZipCode?: string;
|
|
593
|
+
/** Delivery message for the courier */
|
|
594
|
+
deliveryMessage?: string;
|
|
595
|
+
}
|
|
596
|
+
/** Parameters for bulk upload */
|
|
597
|
+
interface BulkUploadParams {
|
|
598
|
+
/** Courier account key (from register or list) */
|
|
599
|
+
courierAccountKey: string;
|
|
600
|
+
/** Items to upload (max 1,000) */
|
|
601
|
+
items: BulkUploadItemParams[];
|
|
602
|
+
}
|
|
603
|
+
/** Delivery status filter for inquiry */
|
|
604
|
+
type DeliveryStatusFilter = 'all' | 'delivered' | 'not_delivered' | 'in_transit' | 'pending';
|
|
605
|
+
/** Parameters for delivery inquiry */
|
|
606
|
+
interface InquiryParams {
|
|
607
|
+
/** Courier account key */
|
|
608
|
+
courierAccountKey: string;
|
|
609
|
+
/** Start date (YYYY-MM-DD) */
|
|
610
|
+
fromDate: string;
|
|
611
|
+
/** End date (YYYY-MM-DD) */
|
|
612
|
+
toDate: string;
|
|
519
613
|
/**
|
|
520
|
-
*
|
|
521
|
-
*
|
|
522
|
-
* - `
|
|
523
|
-
* - `
|
|
614
|
+
* Delivery status filter
|
|
615
|
+
* - `'all'` — all statuses (default)
|
|
616
|
+
* - `'delivered'` — delivered only
|
|
617
|
+
* - `'not_delivered'` — failed delivery only
|
|
618
|
+
* - `'in_transit'` — in transit / out for delivery
|
|
619
|
+
* - `'pending'` — pending / registered / pickup ready / picked up
|
|
524
620
|
*/
|
|
525
|
-
|
|
526
|
-
/**
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
621
|
+
statusFilter?: DeliveryStatusFilter;
|
|
622
|
+
/** Include raw courier data in response */
|
|
623
|
+
includeDetails?: boolean;
|
|
624
|
+
}
|
|
625
|
+
/** Parameters for dashboard statistics (GET — sent as query params) */
|
|
626
|
+
interface DashboardParams {
|
|
627
|
+
/** Courier account key */
|
|
628
|
+
courierAccountKey: string;
|
|
629
|
+
/** Start date (YYYY-MM-DD) */
|
|
630
|
+
fromDate: string;
|
|
631
|
+
/** End date (YYYY-MM-DD) */
|
|
632
|
+
toDate: string;
|
|
633
|
+
}
|
|
634
|
+
/** Parameters for cancelling deliveries */
|
|
635
|
+
interface CancelDeliveriesParams {
|
|
636
|
+
/** Courier account key */
|
|
637
|
+
courierAccountKey: string;
|
|
638
|
+
/** Courier delivery IDs to cancel */
|
|
639
|
+
courierDeliveryIds: string[];
|
|
640
|
+
}
|
|
641
|
+
/** SDK-facing bulk upload history item (Timestamp → ISO string) */
|
|
642
|
+
interface BulkUploadHistoryItemInfo {
|
|
643
|
+
/** Item index within the upload batch (0-based) */
|
|
644
|
+
requestIndex: number;
|
|
645
|
+
/** Client-provided order ID */
|
|
646
|
+
clientOrderId: string;
|
|
647
|
+
/** Receiver name */
|
|
648
|
+
receiverName: string;
|
|
649
|
+
/** Product name */
|
|
650
|
+
productName: string;
|
|
651
|
+
/** Whether this item was uploaded successfully */
|
|
652
|
+
success: boolean;
|
|
653
|
+
/** Result message */
|
|
654
|
+
message: string;
|
|
655
|
+
/** Tracking number (issued at print time, may be undefined) */
|
|
656
|
+
trackingNumber?: string;
|
|
657
|
+
/** Courier management number (issued at upload time) */
|
|
658
|
+
courierDeliveryId?: string;
|
|
659
|
+
/** Print date (ISO 8601, set when printed) */
|
|
660
|
+
datePrinted?: string;
|
|
661
|
+
}
|
|
662
|
+
/** SDK-facing bulk upload history (Timestamp → ISO string, internal fields omitted) */
|
|
663
|
+
interface BulkUploadHistoryInfo {
|
|
664
|
+
/** History document ID (yyyyMMddHHmm_random5chars) */
|
|
665
|
+
id: string;
|
|
666
|
+
/** Courier account key */
|
|
667
|
+
courierAccountKey: string;
|
|
668
|
+
/** Courier provider ID */
|
|
669
|
+
providerId: string;
|
|
670
|
+
/** Upload status */
|
|
671
|
+
status: BulkUploadStatus;
|
|
672
|
+
/** Total items in upload */
|
|
673
|
+
totalCount: number;
|
|
674
|
+
/** Successfully uploaded items */
|
|
675
|
+
successCount: number;
|
|
676
|
+
/** Failed items */
|
|
677
|
+
failCount: number;
|
|
678
|
+
/** Individual item results */
|
|
679
|
+
items: BulkUploadHistoryItemInfo[];
|
|
680
|
+
/** Courier file acceptance number (CJ: actual value, Lotte: null) */
|
|
681
|
+
fileAcptOdrNo: string | null;
|
|
682
|
+
/** Last management number before registration (Lotte only) */
|
|
683
|
+
lastRsrvMgrNo: string | null;
|
|
684
|
+
/** Upload creation date (ISO 8601) */
|
|
685
|
+
dateCreated: string | null;
|
|
686
|
+
/** Last modification date (ISO 8601) */
|
|
687
|
+
dateModified: string | null;
|
|
688
|
+
}
|
|
689
|
+
/** Parameters for listing bulk upload histories (GET — sent as query params) */
|
|
690
|
+
interface ListHistoriesParams {
|
|
691
|
+
/** Courier provider ID (required) */
|
|
692
|
+
providerId: string;
|
|
693
|
+
/** Filter by courier account key */
|
|
694
|
+
courierAccountKey?: string;
|
|
695
|
+
/** Start date filter (YYYY-MM-DD) */
|
|
696
|
+
fromDate?: string;
|
|
697
|
+
/** End date filter (YYYY-MM-DD) */
|
|
698
|
+
toDate?: string;
|
|
699
|
+
/** Max number of results (default 50) */
|
|
700
|
+
limit?: number;
|
|
701
|
+
}
|
|
702
|
+
/** Response from listing bulk upload histories */
|
|
703
|
+
interface ListHistoriesResponse {
|
|
704
|
+
histories: BulkUploadHistoryInfo[];
|
|
705
|
+
}
|
|
706
|
+
/** Parameters for getting history detail */
|
|
707
|
+
interface HistoryDetailParams {
|
|
708
|
+
/** Courier account key (required for ownership verification) */
|
|
709
|
+
courierAccountKey: string;
|
|
710
|
+
}
|
|
711
|
+
/** Response from getting history detail (history + live delivery status) */
|
|
712
|
+
interface HistoryDetailResponse {
|
|
713
|
+
/** The bulk upload history record */
|
|
714
|
+
history: BulkUploadHistoryInfo;
|
|
715
|
+
/** Live delivery status for items in this upload (from courier API) */
|
|
716
|
+
detailItems: AccountInquiryItem[];
|
|
717
|
+
}
|
|
718
|
+
/** Parameters for deleting/cancelling a bulk upload history */
|
|
719
|
+
interface DeleteHistoryParams {
|
|
720
|
+
/** Courier account key (required for ownership verification) */
|
|
721
|
+
courierAccountKey: string;
|
|
722
|
+
/** Specific delivery IDs to cancel (omit for full cancel/delete) */
|
|
723
|
+
courierDeliveryIds?: string[];
|
|
724
|
+
}
|
|
725
|
+
/** Parameters for creating a print session */
|
|
726
|
+
interface CreatePrintSessionParams {
|
|
727
|
+
/** Courier account key */
|
|
728
|
+
courierAccountKey: string;
|
|
729
|
+
/** Courier provider ID */
|
|
730
|
+
providerId: string;
|
|
731
|
+
/** Specific courier tracking IDs to print */
|
|
732
|
+
courierTrackingIds?: string[];
|
|
733
|
+
/** Print all items from a bulk upload history */
|
|
734
|
+
bulkUploadHistoryId?: string;
|
|
735
|
+
}
|
|
736
|
+
/** Response from creating a print session */
|
|
737
|
+
interface PrintSessionResponse {
|
|
738
|
+
/** Session ID for accessing the print page */
|
|
739
|
+
sessionId: string;
|
|
740
|
+
/** Session expiration time (ISO 8601, 10-minute TTL) */
|
|
741
|
+
expiresAt: string;
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
/**
|
|
745
|
+
* 개별 택배 정보
|
|
746
|
+
* - OrderPen.deliveryItems에 저장되는 배송 정보
|
|
747
|
+
* - AccountInquiryItem보다 간소화된 형태 (DB 저장용)
|
|
748
|
+
*/
|
|
749
|
+
interface DeliveryItem {
|
|
750
|
+
id: string;
|
|
751
|
+
courierProvider: CourierProviderId;
|
|
752
|
+
courierAccountId: string;
|
|
753
|
+
courierTrackingId: string;
|
|
754
|
+
trackingNumber: string;
|
|
755
|
+
deliveryStatus: CourierDeliveryStatus;
|
|
756
|
+
isPickupScanned: boolean;
|
|
757
|
+
isReturn: boolean;
|
|
758
|
+
dateCreated: Timestamp;
|
|
759
|
+
dateModified: Timestamp;
|
|
760
|
+
cancelReason: string;
|
|
761
|
+
accountCustomerCode?: string;
|
|
762
|
+
accountCustomerName?: string;
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
/**
|
|
766
|
+
* 대량 업로드 응답 타입 정의
|
|
767
|
+
* ⚠️ farmfree와 동기화 필요 (packages/common/types/courierSaas/bulkUpload.ts)
|
|
768
|
+
*/
|
|
769
|
+
|
|
770
|
+
/**
|
|
771
|
+
* 개별 아이템 업로드 결과
|
|
772
|
+
*/
|
|
773
|
+
interface BulkUploadResultItem$1 {
|
|
774
|
+
requestIndex: number;
|
|
775
|
+
success: boolean;
|
|
776
|
+
message: string;
|
|
777
|
+
trackingNumber?: string;
|
|
778
|
+
courierDeliveryId?: string;
|
|
779
|
+
clientOrderId?: string;
|
|
780
|
+
quantityOriginal: number;
|
|
781
|
+
quantityUploaded: number;
|
|
782
|
+
skipped: boolean;
|
|
783
|
+
skipReason?: string;
|
|
784
|
+
deliveryItem?: DeliveryItem;
|
|
785
|
+
courierMetadata?: {
|
|
786
|
+
acceptanceDate?: string;
|
|
787
|
+
acceptanceFileNo?: string;
|
|
788
|
+
};
|
|
789
|
+
}
|
|
790
|
+
/**
|
|
791
|
+
* 대량 업로드 전체 응답
|
|
792
|
+
*/
|
|
793
|
+
interface BulkUploadResponse$1 {
|
|
794
|
+
success: boolean;
|
|
795
|
+
historyId: string;
|
|
796
|
+
totalRequested: number;
|
|
797
|
+
totalUploaded: number;
|
|
798
|
+
totalSkipped: number;
|
|
799
|
+
totalFailed: number;
|
|
800
|
+
results: BulkUploadResultItem$1[];
|
|
801
|
+
fileAcptOdrNo?: string;
|
|
802
|
+
acptDt?: string;
|
|
803
|
+
warning?: string;
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
/**
|
|
807
|
+
* 대시보드 통계 인터페이스
|
|
808
|
+
* 롯데택배 API 응답 기준으로 설계
|
|
809
|
+
* 모든 택배사가 동일한 형식으로 반환해야 함
|
|
810
|
+
*/
|
|
811
|
+
/**
|
|
812
|
+
* 대시보드 통계 항목
|
|
813
|
+
* 개별 데이터 및 집계 데이터를 포함
|
|
814
|
+
*/
|
|
815
|
+
interface DashboardStatsItem {
|
|
816
|
+
totCnt: number;
|
|
817
|
+
prtCnt: number;
|
|
818
|
+
nonPrtCnt: number;
|
|
819
|
+
pickCnt: number;
|
|
820
|
+
pickCclCnt: number;
|
|
821
|
+
outCnt: number;
|
|
822
|
+
nonOutCnt: number;
|
|
823
|
+
arvCnt: number;
|
|
824
|
+
nonArvCnt: number;
|
|
825
|
+
dlvcpCnt: number;
|
|
826
|
+
nonDlvCnt: number;
|
|
827
|
+
invRgstCnt: number;
|
|
828
|
+
nonInvRgstCnt: number;
|
|
829
|
+
dlvbCnt: number;
|
|
830
|
+
pcadCnt: number;
|
|
831
|
+
stbhCnt: number;
|
|
832
|
+
pickYmd: string | null;
|
|
833
|
+
fstmIstrYmd: string | null;
|
|
834
|
+
ustRtgSctCd: string | null;
|
|
835
|
+
ustRtgSctNm: '출고' | '반품';
|
|
836
|
+
ustRtgSct: string | null;
|
|
837
|
+
jobCustCd: string | null;
|
|
838
|
+
jobCustNm: string;
|
|
839
|
+
pickYmdGrouping: number;
|
|
840
|
+
ustRtgSctCdGrouping: number;
|
|
841
|
+
ustRtgSctNmGrouping: number;
|
|
842
|
+
jobCustCdGrouping: number;
|
|
843
|
+
jobCustNmGrouping: number;
|
|
844
|
+
}
|
|
845
|
+
/**
|
|
846
|
+
* 대시보드 요약 통계
|
|
847
|
+
* [총 계] 행에서 추출한 핵심 지표
|
|
848
|
+
*/
|
|
849
|
+
interface DashboardSummary {
|
|
850
|
+
totalCount: number;
|
|
851
|
+
pending: number;
|
|
852
|
+
inTransit: number;
|
|
853
|
+
delivered: number;
|
|
854
|
+
problem: number;
|
|
855
|
+
}
|
|
856
|
+
/**
|
|
857
|
+
* 대시보드 API 응답
|
|
858
|
+
* 전체 데이터 + 요약 통계 포함
|
|
859
|
+
*/
|
|
860
|
+
interface DashboardStatsResponse {
|
|
861
|
+
items: DashboardStatsItem[];
|
|
862
|
+
summary: DashboardSummary;
|
|
863
|
+
dateRange: {
|
|
864
|
+
from: string;
|
|
865
|
+
to: string;
|
|
866
|
+
};
|
|
867
|
+
lastUpdated: string;
|
|
538
868
|
}
|
|
539
869
|
|
|
870
|
+
/** Individual bulk upload result item (SDK-safe: deliveryItem is raw JSON) */
|
|
871
|
+
type BulkUploadResultItem = Omit<BulkUploadResultItem$1, 'deliveryItem'> & {
|
|
872
|
+
/** Courier delivery data (raw JSON object, only present when tracking number is updated) */
|
|
873
|
+
deliveryItem?: Record<string, unknown>;
|
|
874
|
+
};
|
|
875
|
+
/** Bulk upload response */
|
|
876
|
+
type BulkUploadResponse = Omit<BulkUploadResponse$1, 'results'> & {
|
|
877
|
+
/** Individual item results (same order as request items) */
|
|
878
|
+
results: BulkUploadResultItem[];
|
|
879
|
+
};
|
|
880
|
+
|
|
540
881
|
/**
|
|
541
882
|
* API 호출 실패 시 throw 되는 에러 클래스
|
|
542
883
|
*
|
|
@@ -560,7 +901,14 @@ declare class ApiError extends Error {
|
|
|
560
901
|
readonly code: ApiErrorCode | string;
|
|
561
902
|
/** HTTP 상태 코드 */
|
|
562
903
|
readonly status: number;
|
|
563
|
-
|
|
904
|
+
/**
|
|
905
|
+
* 에러 상세 데이터 (에러 종류에 따라 포함될 수 있음)
|
|
906
|
+
*
|
|
907
|
+
* 예) `INVALID_ITEMS` 에러 시 잘못된 항목 목록:
|
|
908
|
+
* `[{ courierCode, trackingNumber, errorCode }]`
|
|
909
|
+
*/
|
|
910
|
+
readonly data?: unknown;
|
|
911
|
+
constructor(code: ApiErrorCode | string, message: string, status: number, data?: unknown);
|
|
564
912
|
}
|
|
565
913
|
/** API Key 인증 정보 */
|
|
566
914
|
interface AuthCredentials {
|
|
@@ -580,7 +928,7 @@ declare class TrackingResource {
|
|
|
580
928
|
* const { couriers } = await client.tracking.getCouriers()
|
|
581
929
|
* // couriers: [{ trackingApiCode: 'cj', displayName: 'CJ대한통운' }, ...]
|
|
582
930
|
*/
|
|
583
|
-
getCouriers(): Promise<
|
|
931
|
+
getCouriers(): Promise<GetCouriersApiResponse>;
|
|
584
932
|
/**
|
|
585
933
|
* 송장번호로 배송 정보를 조회합니다.
|
|
586
934
|
*
|
|
@@ -615,7 +963,7 @@ declare class TrackingResource {
|
|
|
615
963
|
clientId?: string;
|
|
616
964
|
}[];
|
|
617
965
|
includeProgresses?: boolean;
|
|
618
|
-
}): Promise<
|
|
966
|
+
}): Promise<TrackingResponse>;
|
|
619
967
|
}
|
|
620
968
|
|
|
621
969
|
declare class EndpointsResource {
|
|
@@ -646,7 +994,7 @@ declare class EndpointsResource {
|
|
|
646
994
|
name: string;
|
|
647
995
|
/** 서명 시크릿 직접 지정 (미제공 시 서버 자동 생성, 최소 5자) */
|
|
648
996
|
webhookSecret?: string;
|
|
649
|
-
}): Promise<
|
|
997
|
+
}): Promise<CreateEndpointApiResponse>;
|
|
650
998
|
/**
|
|
651
999
|
* 등록된 웹훅 엔드포인트 목록을 조회합니다.
|
|
652
1000
|
*
|
|
@@ -655,7 +1003,7 @@ declare class EndpointsResource {
|
|
|
655
1003
|
* const active = endpoints.filter(ep => ep.status === 'active')
|
|
656
1004
|
* console.log(active[0].endpointId) // 'ep_xxxx'
|
|
657
1005
|
*/
|
|
658
|
-
list(): Promise<
|
|
1006
|
+
list(): Promise<ListEndpointsApiResponse>;
|
|
659
1007
|
/**
|
|
660
1008
|
* 웹훅 엔드포인트 이름을 수정합니다.
|
|
661
1009
|
*
|
|
@@ -696,7 +1044,7 @@ declare class EndpointsResource {
|
|
|
696
1044
|
rotateSecret(endpointId: string, params?: {
|
|
697
1045
|
/** 새 시크릿 직접 지정 (미제공 시 서버 자동 생성) */
|
|
698
1046
|
webhookSecret?: string;
|
|
699
|
-
}): Promise<
|
|
1047
|
+
}): Promise<RotateSecretApiResponse>;
|
|
700
1048
|
}
|
|
701
1049
|
|
|
702
1050
|
declare class SubscriptionsResource {
|
|
@@ -791,7 +1139,7 @@ declare class SubscriptionsResource {
|
|
|
791
1139
|
* 웹훅 페이로드의 `metadata` 필드에 그대로 포함되어 반환됩니다.
|
|
792
1140
|
*/
|
|
793
1141
|
metadata?: Record<string, string>;
|
|
794
|
-
}): Promise<
|
|
1142
|
+
}): Promise<RegisterTrackingApiResponse>;
|
|
795
1143
|
/**
|
|
796
1144
|
* 구독 목록을 조회합니다.
|
|
797
1145
|
*
|
|
@@ -808,7 +1156,7 @@ declare class SubscriptionsResource {
|
|
|
808
1156
|
* cursor = page.nextCursor
|
|
809
1157
|
* } while (cursor)
|
|
810
1158
|
*/
|
|
811
|
-
list(params?:
|
|
1159
|
+
list(params?: ListSubscriptionsRequest): Promise<ListSubscriptionsApiResponse>;
|
|
812
1160
|
/**
|
|
813
1161
|
* 구독 상세 정보를 조회합니다.
|
|
814
1162
|
*
|
|
@@ -820,7 +1168,7 @@ declare class SubscriptionsResource {
|
|
|
820
1168
|
* console.log(item.trackingNumber, item.currentStatus)
|
|
821
1169
|
* }
|
|
822
1170
|
*/
|
|
823
|
-
get(requestId: string): Promise<
|
|
1171
|
+
get(requestId: string): Promise<SubscriptionDetailApiResponse>;
|
|
824
1172
|
/**
|
|
825
1173
|
* 구독을 취소합니다.
|
|
826
1174
|
*
|
|
@@ -851,7 +1199,7 @@ declare class SubscriptionsResource {
|
|
|
851
1199
|
courierCode: string;
|
|
852
1200
|
trackingNumber: string;
|
|
853
1201
|
}[];
|
|
854
|
-
}): Promise<
|
|
1202
|
+
}): Promise<BatchResultsApiResponse>;
|
|
855
1203
|
}
|
|
856
1204
|
|
|
857
1205
|
/**
|
|
@@ -904,6 +1252,299 @@ declare class WebhooksResource {
|
|
|
904
1252
|
constructor(auth: AuthCredentials);
|
|
905
1253
|
}
|
|
906
1254
|
|
|
1255
|
+
declare class AccountsResource {
|
|
1256
|
+
private readonly auth;
|
|
1257
|
+
constructor(auth: AuthCredentials);
|
|
1258
|
+
/**
|
|
1259
|
+
* 택배사 계정을 등록합니다.
|
|
1260
|
+
*
|
|
1261
|
+
* 롯데택배, CJ대한통운 계정을 등록할 수 있습니다.
|
|
1262
|
+
* CJ대한통운은 2FA(OTP) 인증이 필요할 수 있으며, 이 경우 `COURIER_OTP_REQUIRED` 에러가 발생합니다.
|
|
1263
|
+
*
|
|
1264
|
+
* @param params - 계정 등록 파라미터
|
|
1265
|
+
* @returns 등록된 계정 정보 (courierAccountKey 포함)
|
|
1266
|
+
* @throws {ApiError} COURIER_OTP_REQUIRED — CJ 계정 OTP 인증 필요
|
|
1267
|
+
* @throws {ApiError} COURIER_AUTH_FAILED — 계정 인증 실패 (아이디/비밀번호 오류)
|
|
1268
|
+
* @throws {ApiError} FORBIDDEN — 계정 슬롯 한도 초과
|
|
1269
|
+
*
|
|
1270
|
+
* @example
|
|
1271
|
+
* const account = await client.courier.accounts.register({
|
|
1272
|
+
* providerId: 'lotte',
|
|
1273
|
+
* accountId: 'my-lotte-id',
|
|
1274
|
+
* accountPassword: 'my-password',
|
|
1275
|
+
* accountName: '메인 롯데 계정',
|
|
1276
|
+
* })
|
|
1277
|
+
* console.log(account.courierAccountKey) // 이후 API 호출에 사용
|
|
1278
|
+
*/
|
|
1279
|
+
register(params: RegisterAccountParams): Promise<RegisterAccountResponse>;
|
|
1280
|
+
/**
|
|
1281
|
+
* 등록된 택배사 계정 목록을 조회합니다.
|
|
1282
|
+
*
|
|
1283
|
+
* @returns 계정 목록 (courierAccountKey, providerId, isActive 등)
|
|
1284
|
+
*
|
|
1285
|
+
* @example
|
|
1286
|
+
* const accounts = await client.courier.accounts.list()
|
|
1287
|
+
* const active = accounts.filter(a => a.isActive)
|
|
1288
|
+
* console.log(active[0].courierAccountKey)
|
|
1289
|
+
*/
|
|
1290
|
+
list(): Promise<CourierAccountInfo[]>;
|
|
1291
|
+
/**
|
|
1292
|
+
* 특정 택배사 계정의 상세 정보를 조회합니다.
|
|
1293
|
+
*
|
|
1294
|
+
* 목록 조회와 달리 `accountPassword` 필드가 포함됩니다 (항상 마스킹된 값).
|
|
1295
|
+
* `expiresAt` 필드는 포함되지 않습니다.
|
|
1296
|
+
*
|
|
1297
|
+
* @param accountKey - 조회할 계정의 courierAccountKey
|
|
1298
|
+
* @returns 계정 상세 정보
|
|
1299
|
+
* @throws {ApiError} NOT_FOUND — 존재하지 않는 계정
|
|
1300
|
+
*
|
|
1301
|
+
* @example
|
|
1302
|
+
* const detail = await client.courier.accounts.get('your-account-key')
|
|
1303
|
+
* console.log(detail.accountId) // 'my-lotte-id'
|
|
1304
|
+
* console.log(detail.accountPassword) // '(암호화하여 저장중)'
|
|
1305
|
+
*/
|
|
1306
|
+
get(accountKey: string): Promise<CourierAccountDetail>;
|
|
1307
|
+
/**
|
|
1308
|
+
* 택배사 계정을 삭제합니다.
|
|
1309
|
+
*
|
|
1310
|
+
* @param accountKey - 삭제할 계정의 courierAccountKey
|
|
1311
|
+
* @throws {ApiError} NOT_FOUND — 존재하지 않는 계정
|
|
1312
|
+
*
|
|
1313
|
+
* @example
|
|
1314
|
+
* await client.courier.accounts.delete('your-account-key')
|
|
1315
|
+
*/
|
|
1316
|
+
delete(accountKey: string): Promise<void>;
|
|
1317
|
+
}
|
|
1318
|
+
|
|
1319
|
+
declare class HistoriesResource {
|
|
1320
|
+
private readonly auth;
|
|
1321
|
+
constructor(auth: AuthCredentials);
|
|
1322
|
+
/**
|
|
1323
|
+
* 대량 등록 이력 목록을 조회합니다.
|
|
1324
|
+
*
|
|
1325
|
+
* @param params - 조회 파라미터 (providerId 필수)
|
|
1326
|
+
* @returns 이력 목록 (histories 배열)
|
|
1327
|
+
*
|
|
1328
|
+
* @example
|
|
1329
|
+
* const { histories } = await client.courier.deliveries.histories.list({
|
|
1330
|
+
* providerId: 'lotte',
|
|
1331
|
+
* courierAccountKey: 'your-key',
|
|
1332
|
+
* limit: 20,
|
|
1333
|
+
* })
|
|
1334
|
+
* const completed = histories.filter(h => h.status === 'completed')
|
|
1335
|
+
*/
|
|
1336
|
+
list(params: ListHistoriesParams): Promise<ListHistoriesResponse>;
|
|
1337
|
+
/**
|
|
1338
|
+
* 대량 등록 이력의 상세 정보를 조회합니다.
|
|
1339
|
+
*
|
|
1340
|
+
* 택배사 API를 호출하여 실시간 배송 상태를 함께 반환합니다.
|
|
1341
|
+
*
|
|
1342
|
+
* @param historyId - 이력 ID
|
|
1343
|
+
* @param params - 조회 파라미터 (courierAccountKey 필수)
|
|
1344
|
+
* @returns 이력 정보 + 실시간 배송 상태 (detailItems)
|
|
1345
|
+
* @throws {ApiError} NOT_FOUND — 존재하지 않는 이력 또는 계정
|
|
1346
|
+
*
|
|
1347
|
+
* @example
|
|
1348
|
+
* const { history, detailItems } = await client.courier.deliveries.histories.get(
|
|
1349
|
+
* '202603221456_a1b2c',
|
|
1350
|
+
* { courierAccountKey: 'your-key' },
|
|
1351
|
+
* )
|
|
1352
|
+
* const delivered = detailItems.filter(d => d.isDelivered)
|
|
1353
|
+
*/
|
|
1354
|
+
get(historyId: string, params: HistoryDetailParams): Promise<HistoryDetailResponse>;
|
|
1355
|
+
/**
|
|
1356
|
+
* 대량 등록 이력을 삭제(취소)합니다.
|
|
1357
|
+
*
|
|
1358
|
+
* `courierDeliveryIds`를 지정하면 부분 취소, 생략하면 전체 취소(soft delete)입니다.
|
|
1359
|
+
* 택배사 API를 호출하여 실제 접수도 취소합니다.
|
|
1360
|
+
*
|
|
1361
|
+
* @param historyId - 이력 ID
|
|
1362
|
+
* @param params - 삭제 파라미터 (courierAccountKey 필수)
|
|
1363
|
+
* @throws {ApiError} NOT_FOUND — 존재하지 않는 이력 또는 계정
|
|
1364
|
+
*
|
|
1365
|
+
* @example
|
|
1366
|
+
* // 전체 취소
|
|
1367
|
+
* await client.courier.deliveries.histories.delete('202603221456_a1b2c', {
|
|
1368
|
+
* courierAccountKey: 'your-key',
|
|
1369
|
+
* })
|
|
1370
|
+
*
|
|
1371
|
+
* // 부분 취소
|
|
1372
|
+
* await client.courier.deliveries.histories.delete('202603221456_a1b2c', {
|
|
1373
|
+
* courierAccountKey: 'your-key',
|
|
1374
|
+
* courierDeliveryIds: ['7705241632'],
|
|
1375
|
+
* })
|
|
1376
|
+
*/
|
|
1377
|
+
delete(historyId: string, params: DeleteHistoryParams): Promise<void>;
|
|
1378
|
+
}
|
|
1379
|
+
|
|
1380
|
+
declare class DeliveriesResource {
|
|
1381
|
+
private readonly auth;
|
|
1382
|
+
/** 대량 등록 이력 관리 */
|
|
1383
|
+
readonly histories: HistoriesResource;
|
|
1384
|
+
constructor(auth: AuthCredentials);
|
|
1385
|
+
/**
|
|
1386
|
+
* 택배를 대량 등록합니다. 최대 1,000건까지 한 번에 등록 가능합니다.
|
|
1387
|
+
*
|
|
1388
|
+
* 등록 직후에는 관리번호(courierDeliveryId)만 발급됩니다.
|
|
1389
|
+
* 송장번호(trackingNumber)는 **송장 출력 시점에 발급**됩니다.
|
|
1390
|
+
*
|
|
1391
|
+
* HTTP 200으로 응답하며, `success`는 전체 성공 여부입니다.
|
|
1392
|
+
* 부분 실패가 가능하므로 반드시 `results[].success`로 개별 확인하세요.
|
|
1393
|
+
*
|
|
1394
|
+
* @param params - 대량 등록 요청 파라미터
|
|
1395
|
+
* @returns 등록 결과 (부분 성공 포함, results[].success로 개별 확인)
|
|
1396
|
+
* @throws {ApiError} RATE_LIMITED — 요청 한도 초과
|
|
1397
|
+
* @throws {ApiError} FORBIDDEN — 계정 슬롯 한도 초과
|
|
1398
|
+
*
|
|
1399
|
+
* @example
|
|
1400
|
+
* const result = await client.courier.deliveries.bulkUpload({
|
|
1401
|
+
* courierAccountKey: 'your-key',
|
|
1402
|
+
* items: [{
|
|
1403
|
+
* clientOrderId: 'ORD-001',
|
|
1404
|
+
* receiverName: '홍길동',
|
|
1405
|
+
* receiverPhone1: '01012345678',
|
|
1406
|
+
* receiverAddress: '서울특별시 중구 세종대로 110',
|
|
1407
|
+
* productName: '테스트 상품',
|
|
1408
|
+
* quantity: 1,
|
|
1409
|
+
* }],
|
|
1410
|
+
* })
|
|
1411
|
+
* const failed = result.results.filter(r => !r.success)
|
|
1412
|
+
* const ids = result.results.filter(r => r.success).map(r => r.courierDeliveryId)
|
|
1413
|
+
*/
|
|
1414
|
+
bulkUpload(params: BulkUploadParams): Promise<BulkUploadResponse>;
|
|
1415
|
+
/**
|
|
1416
|
+
* 택배사 계정의 배송 목록을 조회합니다.
|
|
1417
|
+
*
|
|
1418
|
+
* 택배사 API를 실시간으로 호출하여 최신 배송 상태를 반환합니다.
|
|
1419
|
+
*
|
|
1420
|
+
* @param params - 조회 파라미터
|
|
1421
|
+
* @returns 배송 목록 (items) + 요약 통계 (summary)
|
|
1422
|
+
* @throws {ApiError} NOT_FOUND — 존재하지 않는 계정
|
|
1423
|
+
*
|
|
1424
|
+
* @example
|
|
1425
|
+
* const result = await client.courier.deliveries.inquiry({
|
|
1426
|
+
* courierAccountKey: 'your-key',
|
|
1427
|
+
* fromDate: '2026-03-01',
|
|
1428
|
+
* toDate: '2026-03-22',
|
|
1429
|
+
* })
|
|
1430
|
+
* console.log(result.summary.delivered) // 배송 완료 건수
|
|
1431
|
+
* const pending = result.items.filter(i => i.deliveryStatus === 'PENDING')
|
|
1432
|
+
*/
|
|
1433
|
+
inquiry(params: InquiryParams): Promise<AccountInquiryResponse>;
|
|
1434
|
+
/**
|
|
1435
|
+
* 택배사 계정의 배송 통계(대시보드)를 조회합니다.
|
|
1436
|
+
*
|
|
1437
|
+
* @param params - 조회 파라미터
|
|
1438
|
+
* @returns 배송 통계 (items: 상세 행, summary: 요약)
|
|
1439
|
+
* @throws {ApiError} NOT_FOUND — 존재하지 않는 계정
|
|
1440
|
+
*
|
|
1441
|
+
* @example
|
|
1442
|
+
* const stats = await client.courier.deliveries.dashboard({
|
|
1443
|
+
* courierAccountKey: 'your-key',
|
|
1444
|
+
* fromDate: '2026-03-01',
|
|
1445
|
+
* toDate: '2026-03-22',
|
|
1446
|
+
* })
|
|
1447
|
+
* console.log(stats.summary.totalCount) // 전체 건수
|
|
1448
|
+
* console.log(stats.summary.delivered) // 배송 완료 건수
|
|
1449
|
+
*/
|
|
1450
|
+
dashboard(params: DashboardParams): Promise<DashboardStatsResponse>;
|
|
1451
|
+
/**
|
|
1452
|
+
* 등록된 배송을 취소합니다.
|
|
1453
|
+
*
|
|
1454
|
+
* **주의**: 등록 후 7일 이내의 배송만 취소 가능합니다.
|
|
1455
|
+
* 7일 이상 경과한 배송은 택배사에서 조회되지 않아 취소할 수 없습니다.
|
|
1456
|
+
* 지원하지 않는 택배사의 경우 에러가 반환됩니다.
|
|
1457
|
+
*
|
|
1458
|
+
* 이력 단위 취소가 필요하면 `client.courier.deliveries.histories.delete()`를 사용하세요.
|
|
1459
|
+
*
|
|
1460
|
+
* @param params - 취소 파라미터 (courierDeliveryId 목록)
|
|
1461
|
+
* @throws {ApiError} NOT_FOUND — 존재하지 않는 계정
|
|
1462
|
+
* @throws {ApiError} INVALID_PARAMS — 택배사가 배송 취소를 지원하지 않음
|
|
1463
|
+
*
|
|
1464
|
+
* @example
|
|
1465
|
+
* await client.courier.deliveries.cancel({
|
|
1466
|
+
* courierAccountKey: 'your-key',
|
|
1467
|
+
* courierDeliveryIds: ['7705241632', '7705241633'],
|
|
1468
|
+
* })
|
|
1469
|
+
*/
|
|
1470
|
+
cancel(params: CancelDeliveriesParams): Promise<void>;
|
|
1471
|
+
}
|
|
1472
|
+
|
|
1473
|
+
declare class PrintResource {
|
|
1474
|
+
private readonly auth;
|
|
1475
|
+
constructor(auth: AuthCredentials);
|
|
1476
|
+
/**
|
|
1477
|
+
* 송장 출력 세션을 생성합니다.
|
|
1478
|
+
*
|
|
1479
|
+
* 세션 ID로 출력 페이지(`https://print.deliveryapi.co.kr?session={sessionId}`)에 접속할 수 있습니다.
|
|
1480
|
+
* 세션은 **10분 유효, 1회용**입니다. OZ Viewer 설치가 필요합니다.
|
|
1481
|
+
*
|
|
1482
|
+
* `courierTrackingIds` 또는 `bulkUploadHistoryId` 중 하나를 지정하세요.
|
|
1483
|
+
*
|
|
1484
|
+
* **중요**: 대부분의 택배사에서 송장번호(trackingNumber)는 이 출력 시점에 발급됩니다.
|
|
1485
|
+
* 출력 후 `client.courier.deliveries.inquiry()`로 발급된 송장번호를 확인하세요.
|
|
1486
|
+
*
|
|
1487
|
+
* @param params - 출력 세션 생성 파라미터
|
|
1488
|
+
* @returns 세션 정보 (sessionId, expiresAt)
|
|
1489
|
+
* @throws {ApiError} NOT_FOUND — 존재하지 않는 계정 또는 배송 ID
|
|
1490
|
+
*
|
|
1491
|
+
* @example
|
|
1492
|
+
* // 개별 ID로 출력
|
|
1493
|
+
* const session = await client.courier.print.createSession({
|
|
1494
|
+
* courierAccountKey: 'your-key',
|
|
1495
|
+
* providerId: 'lotte',
|
|
1496
|
+
* courierTrackingIds: ['7705241632', '7705241633'],
|
|
1497
|
+
* })
|
|
1498
|
+
* // 브라우저에서 출력 페이지 열기
|
|
1499
|
+
* window.open(`https://print.deliveryapi.co.kr?session=${session.sessionId}`)
|
|
1500
|
+
*
|
|
1501
|
+
* @example
|
|
1502
|
+
* // 이력 전체 출력
|
|
1503
|
+
* const session = await client.courier.print.createSession({
|
|
1504
|
+
* courierAccountKey: 'your-key',
|
|
1505
|
+
* providerId: 'lotte',
|
|
1506
|
+
* bulkUploadHistoryId: '202603221456_a1b2c',
|
|
1507
|
+
* })
|
|
1508
|
+
*/
|
|
1509
|
+
createSession(params: CreatePrintSessionParams): Promise<PrintSessionResponse>;
|
|
1510
|
+
}
|
|
1511
|
+
|
|
1512
|
+
/**
|
|
1513
|
+
* 택배 계정 서비스 리소스
|
|
1514
|
+
*
|
|
1515
|
+
* 택배사 계정을 등록하고, 택배를 대량 등록·조회·취소하며, 송장을 출력합니다.
|
|
1516
|
+
* 현재 롯데택배, CJ대한통운을 지원합니다.
|
|
1517
|
+
*
|
|
1518
|
+
* @example
|
|
1519
|
+
* // 전체 플로우: 계정 등록 → 대량 등록 → 송장 출력 → 배송 추적
|
|
1520
|
+
* const account = await client.courier.accounts.register({
|
|
1521
|
+
* providerId: 'lotte',
|
|
1522
|
+
* accountId: 'my-id',
|
|
1523
|
+
* accountPassword: 'my-password',
|
|
1524
|
+
* })
|
|
1525
|
+
*
|
|
1526
|
+
* const upload = await client.courier.deliveries.bulkUpload({
|
|
1527
|
+
* courierAccountKey: account.courierAccountKey,
|
|
1528
|
+
* items: [{ clientOrderId: 'ORD-001', receiverName: '홍길동', ... }],
|
|
1529
|
+
* })
|
|
1530
|
+
*
|
|
1531
|
+
* const session = await client.courier.print.createSession({
|
|
1532
|
+
* courierAccountKey: account.courierAccountKey,
|
|
1533
|
+
* providerId: 'lotte',
|
|
1534
|
+
* courierTrackingIds: upload.results.filter(r => r.success).map(r => r.courierDeliveryId!),
|
|
1535
|
+
* })
|
|
1536
|
+
* // 출력 후 trackingNumber가 발급됨 → inquiry로 확인 → webhooks로 추적
|
|
1537
|
+
*/
|
|
1538
|
+
declare class CourierResource {
|
|
1539
|
+
/** 택배사 계정 관리 (등록, 조회, 삭제) */
|
|
1540
|
+
readonly accounts: AccountsResource;
|
|
1541
|
+
/** 배송 관리 (대량 등록, 조회, 대시보드, 취소, 이력) */
|
|
1542
|
+
readonly deliveries: DeliveriesResource;
|
|
1543
|
+
/** 송장 출력 (세션 생성) */
|
|
1544
|
+
readonly print: PrintResource;
|
|
1545
|
+
constructor(auth: AuthCredentials);
|
|
1546
|
+
}
|
|
1547
|
+
|
|
907
1548
|
/** `DeliveryAPIClient` 생성 옵션 */
|
|
908
1549
|
interface DeliveryAPIClientOptions {
|
|
909
1550
|
/**
|
|
@@ -965,9 +1606,20 @@ declare class DeliveryAPIClient {
|
|
|
965
1606
|
* **`webhooks.subscriptions`** — 택배 추적 구독 등록/관리
|
|
966
1607
|
*/
|
|
967
1608
|
readonly webhooks: WebhooksResource;
|
|
1609
|
+
/**
|
|
1610
|
+
* 택배 계정 서비스 API
|
|
1611
|
+
*
|
|
1612
|
+
* 택배사 계정 등록, 택배 대량 등록·조회·취소, 송장 출력을 제공합니다.
|
|
1613
|
+
* 현재 롯데택배, CJ대한통운을 지원합니다.
|
|
1614
|
+
*
|
|
1615
|
+
* **`courier.accounts`** — 택배사 계정 관리
|
|
1616
|
+
* **`courier.deliveries`** — 대량 등록, 배송 조회/취소, 이력
|
|
1617
|
+
* **`courier.print`** — 송장 출력 세션 생성
|
|
1618
|
+
*/
|
|
1619
|
+
readonly courier: CourierResource;
|
|
968
1620
|
/** API Base URL (`https://api.deliveryapi.co.kr`) */
|
|
969
1621
|
readonly baseUrl: string;
|
|
970
1622
|
constructor(options: DeliveryAPIClientOptions);
|
|
971
1623
|
}
|
|
972
1624
|
|
|
973
|
-
export { ApiError, type ApiErrorCode, type BatchResultEntry, type BatchResultItem, type BatchResultsParams, type BatchResultsResponse, CourierDeliveryStatus, type CourierInfo, type CreateEndpointParams, type CreateEndpointResponse, DeliveryAPIClient, type DeliveryAPIClientOptions, type EndpointInfo, type GetCouriersResponse, type ListEndpointsResponse, type ListSubscriptionsParams, type ListSubscriptionsResponse, type RegisterItem, type RegisterResponse, type RotateSecretParams, type RotateSecretResponse, type SubscriptionDetail, type SubscriptionItem, type SubscriptionListItem, type SubscriptionSummary, type TraceCacheInfo, type TraceItem, type TraceItemError, type TraceParams, type TraceResponse, type TraceResult, type TrackingErrorCode, type TrackingProgress, type UnifiedTrackingResponse, type UpdateEndpointParams, type WebhookPayload };
|
|
1625
|
+
export { type AccountInquiryItem, type AccountInquiryResponse, AccountsResource, ApiError, type ApiErrorCode, type BatchResultEntry, type BatchResultItem, type BatchResultsRequest as BatchResultsParams, type BatchResultsApiResponse as BatchResultsResponse, type BulkUploadHistoryInfo, type BulkUploadHistoryItemInfo, type BulkUploadItemParams, type BulkUploadParams, type BulkUploadResponse, type BulkUploadResultItem, type BulkUploadStatus, type CancelDeliveriesParams, type CourierAccountDetail, type CourierAccountInfo, CourierDeliveryStatus, type CourierInfoResponse as CourierInfo, CourierResource, type CreateEndpointRequest as CreateEndpointParams, type CreateEndpointApiResponse as CreateEndpointResponse, type CreatePrintSessionParams, type DashboardParams, type DashboardStatsItem, type DashboardStatsResponse, type DashboardSummary, type DeleteHistoryParams, DeliveriesResource, DeliveryAPIClient, type DeliveryAPIClientOptions, type DeliveryStatusFilter, type EndpointListItem as EndpointInfo, type GetCouriersApiResponse as GetCouriersResponse, HistoriesResource, type HistoryDetailParams, type HistoryDetailResponse, type InquiryParams, type ListEndpointsApiResponse as ListEndpointsResponse, type ListHistoriesParams, type ListHistoriesResponse, type ListSubscriptionsRequest as ListSubscriptionsParams, type ListSubscriptionsApiResponse as ListSubscriptionsResponse, PrintResource, type PrintSessionResponse, type RegisterAccountParams, type RegisterAccountResponse, type RegisterTrackingItem as RegisterItem, type RegisterTrackingApiResponse as RegisterResponse, type RotateSecretRequest as RotateSecretParams, type RotateSecretApiResponse as RotateSecretResponse, type SubscriptionDetailApiResponse as SubscriptionDetail, type WebhookTrackingItem as SubscriptionItem, type SubscriptionListItem, type TrackingBatchSummary as SubscriptionSummary, type TrackingCacheInfo as TraceCacheInfo, type TrackingItem as TraceItem, type TrackingItemError as TraceItemError, type TrackingRequest as TraceParams, type TrackingResponse as TraceResponse, type TrackingResult as TraceResult, type TrackingErrorCode, type TrackingProgress, type UnifiedTrackingResponse, type UpdateEndpointRequest as UpdateEndpointParams, type WebhookPayload, type WebhookTrackingItem };
|