apick-api 3.2.0 → 3.4.1
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/CHANGELOG.md +102 -75
- package/LICENSE +21 -21
- package/README.md +392 -286
- package/SECURITY.md +11 -11
- package/docs/guide.en.md +282 -196
- package/docs/guide.ko.md +290 -204
- package/examples/basic.mjs +10 -10
- package/examples/commonjs.cjs +12 -12
- package/examples/files.mjs +9 -9
- package/package.json +71 -71
- package/src/form.cjs +28 -0
- package/src/index.cjs +805 -694
- package/src/index.d.ts +298 -176
- package/src/index.js +13 -12
package/SECURITY.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
# Security
|
|
2
|
-
|
|
3
|
-
## API keys
|
|
4
|
-
|
|
5
|
-
Keep APICK API keys in server-side environment variables. Do not commit keys, include them in client-side browser bundles, place them in URLs, or print them in logs.
|
|
6
|
-
|
|
7
|
-
If a key may have been exposed, regenerate it from your APICK account immediately.
|
|
8
|
-
|
|
9
|
-
## Reporting a vulnerability
|
|
10
|
-
|
|
11
|
-
Please report security issues privately through the contact channel listed at <https://apick.app>. Do not open a public issue containing credentials, personal data, or exploit details.
|
|
1
|
+
# Security
|
|
2
|
+
|
|
3
|
+
## API keys
|
|
4
|
+
|
|
5
|
+
Keep APICK API keys in server-side environment variables. Do not commit keys, include them in client-side browser bundles, place them in URLs, or print them in logs.
|
|
6
|
+
|
|
7
|
+
If a key may have been exposed, regenerate it from your APICK account immediately.
|
|
8
|
+
|
|
9
|
+
## Reporting a vulnerability
|
|
10
|
+
|
|
11
|
+
Please report security issues privately through the contact channel listed at <https://apick.app>. Do not open a public issue containing credentials, personal data, or exploit details.
|
package/docs/guide.en.md
CHANGED
|
@@ -1,206 +1,292 @@
|
|
|
1
|
-
# apick-api English guide
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
1
|
+
# apick-api English guide
|
|
2
|
+
|
|
3
|
+
## Request and response formats
|
|
4
|
+
|
|
5
|
+
All SDK requests with a body use `multipart/form-data`. Arrays use separate indexed fields such as `utterance_ids[0]`; let the SDK set the Content-Type boundary. GET requests have no body. The server continues accepting older JSON requests for compatibility.
|
|
6
|
+
|
|
7
|
+
The SDK preserves original LF/CR characters using UTF-8 Base64 and a `__apick_encoding[field]=base64-utf8` form metadata field. Excel cells also carry type metadata; dates become ISO strings and sparse array cells become null.
|
|
8
|
+
|
|
9
|
+
Responses remain service-specific JSON or direct files. A failed download may return JSON, which the SDK exposes as `ApickApiError`. Individual REST guides provide OpenAPI and Postman downloads. External MCP connections retain JSON-RPC.
|
|
10
|
+
|
|
11
|
+
`apick-api` is the official zero-dependency Node.js SDK for a focused set of popular APICK REST APIs. It supports ESM, CommonJS, and TypeScript.
|
|
12
|
+
|
|
13
|
+
## Install and authenticate
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install apick-api
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
```js
|
|
20
|
+
import { ApickClient } from 'apick-api';
|
|
21
|
+
|
|
22
|
+
const client = new ApickClient({
|
|
23
|
+
apiKey: process.env.APICK_API_KEY,
|
|
24
|
+
timeoutMs: 60_000
|
|
25
|
+
});
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Pass the API key only to the constructor. The SDK does not keep it in enumerable client properties and never prints it in logs or error messages.
|
|
29
|
+
|
|
30
|
+
Leave the allowed-IP list blank for unrestricted access. To restrict access, register the public IPv4 address seen by APICK as an exact address or CIDR such as `/32`. Changes apply immediately with no separate synchronization.
|
|
31
|
+
|
|
32
|
+
## Business, validation, and addresses
|
|
33
|
+
|
|
34
|
+
```js
|
|
35
|
+
const business = await client.businessDetails('439-87-00761');
|
|
36
|
+
const venture = await client.ventureBusiness('4398700761');
|
|
37
|
+
const email = await client.validateEmail('sample@example.com');
|
|
38
|
+
const phone = await client.validatePhone('01012341234');
|
|
39
|
+
const holidays = await client.holidays(2026, 10);
|
|
40
|
+
const addresses = await client.searchAddress('가산디지털로', { page: 1 });
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Hyphens are removed from business numbers automatically. Invalid required values fail locally with `TypeError` or `RangeError` before an API request is sent.
|
|
44
|
+
|
|
45
|
+
## Parcel tracking
|
|
46
|
+
|
|
47
|
+
Use carrier-specific tracking when you know the carrier:
|
|
48
|
+
|
|
49
|
+
```js
|
|
50
|
+
const parcel = await client.trackParcel('cj', '123456789012');
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Use automatic carrier detection when you only have the tracking number:
|
|
54
|
+
|
|
55
|
+
```js
|
|
56
|
+
const parcel = await client.trackParcelAuto('123456789012');
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Domain and search tools
|
|
60
|
+
|
|
61
|
+
```js
|
|
62
|
+
const dns = await client.dnsLookup('apick.app');
|
|
63
|
+
const location = await client.geolocate('apick.app');
|
|
64
|
+
const registration = await client.whois('apick.app');
|
|
65
|
+
const web = await client.googleSearch('APICK API', { page: 1 });
|
|
66
|
+
const images = await client.googleImageSearch('Seoul skyline', { page: 1 });
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## OCR
|
|
70
|
+
|
|
71
|
+
OCR accepts PNG and JPEG files up to 50MB.
|
|
72
|
+
|
|
73
|
+
```js
|
|
74
|
+
const ocr = await client.ocr('./receipt.jpg');
|
|
75
|
+
console.log(ocr.data.result.full_text);
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
For in-memory input, supply a filename and MIME type when needed:
|
|
79
|
+
|
|
80
|
+
```js
|
|
81
|
+
await client.ocr(bytes, {
|
|
82
|
+
filename: 'scan.png',
|
|
83
|
+
contentType: 'image/png'
|
|
84
|
+
});
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Generated files
|
|
88
|
+
|
|
89
|
+
TTS supports 16 voice IDs. Use `TTS_VOICE_IDS` and the developer guide for the current list.
|
|
90
|
+
|
|
91
|
+
`v2_ann_m_30s_01`, `v2_ann_m_30s_02`, `v2_ann_m_30s_04`, `v2_ann_m_30s_05`, `v2_ann_f_30s_01`, `v2_ann_f_30s_02`, `v2_ann_f_30s_03`, `v2_ann_f_30s_04`, `v2_ann_f_30s_05`, `v2_m_teen_01`, `v2_m_young_01`, `v2_m_mid_01`, `v2_m_senior_01`, `v2_f_teen_01`, `v2_f_young_01`, `v2_f_senior_01`
|
|
92
|
+
|
|
93
|
+
```js
|
|
94
|
+
const screenshot = await client.screenshot('https://example.com');
|
|
95
|
+
await screenshot.save('./example.jpeg');
|
|
96
|
+
|
|
97
|
+
const created = await client.createTtsJob('오늘의 이야기를 시작합니다.', { voiceId: 'v2_ann_m_30s_01' });
|
|
98
|
+
const jobId = created.data.job_id;
|
|
99
|
+
let job = await client.getTtsJob(jobId);
|
|
100
|
+
while (job.data.status === 'waiting' || job.data.status === 'processing') {
|
|
101
|
+
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
102
|
+
job = await client.getTtsJob(jobId);
|
|
103
|
+
}
|
|
104
|
+
if (job.data.status === 'completed') {
|
|
105
|
+
const result = await client.downloadTtsResult(jobId);
|
|
106
|
+
await result.save(`./${jobId}.mp3`); // audio/mpeg; downloadable once
|
|
107
|
+
const subtitles = await client.downloadTtsSubtitles(jobId);
|
|
108
|
+
await subtitles.save(`./${jobId}.ass`); // ASS subtitles; separately downloadable once
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Cancellation is available while waiting or processing and does not refund the accepted charge.
|
|
112
|
+
// MP3 and ASS downloads each consume their server copy immediately and cannot be repeated.
|
|
113
|
+
|
|
114
|
+
const pdf = await client.htmlToPdf('<h1>Report</h1>', { pagination: true });
|
|
115
|
+
await pdf.save('./report.pdf');
|
|
116
|
+
|
|
117
|
+
const excel = await client.jsonToExcel([{ item: 'A', count: 3 }], {
|
|
118
|
+
sheetName: 'Inventory'
|
|
119
|
+
});
|
|
120
|
+
await excel.save('./inventory.xlsx');
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Binary results expose `bytes`, `size`, `filename`, `contentType`, and `meta`. `save()` writes a file in Node.js, while `toBlob()` creates a standard `Blob`.
|
|
124
|
+
|
|
125
|
+
## Text AI
|
|
126
|
+
|
|
127
|
+
```js
|
|
128
|
+
const summary = await client.summarize(longText);
|
|
129
|
+
const polished = await client.polish(draftText);
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Text input is limited to 100,000 characters.
|
|
133
|
+
|
|
134
|
+
## Image AI
|
|
135
|
+
|
|
136
|
+
```js
|
|
137
|
+
const result = await client.generateImages('A clean product photo on white', {
|
|
138
|
+
imageCount: 4, size: '1024x1024', outputFormat: 'webp',
|
|
139
|
+
idempotencyKey: 'product-draft-001'
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
const referenceResult = await client.generateImages('Keep the product shape and composition, and change the background to a sunny kitchen', {
|
|
143
|
+
referenceImage: './reference.png',
|
|
144
|
+
referenceFilename: 'reference.png',
|
|
145
|
+
referenceContentType: 'image/png'
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
const job = await client.createImageGenerationJob('Landscape article cover concepts', { imageCount: 20, size: '1536x1024' });
|
|
149
|
+
const status = await client.getImageJob(job.data.job_id);
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
`imageCount` is the number of images to make and defaults to one. Synchronous generation and editing support 1–4 images; job methods support 1–50. Add `referenceImage` to generation when the prompt should build from an existing composition, palette, or product shape. Editing accepts one PNG, JPEG, or WebP source up to 50 MB plus a prompt; mask files are not supported. Choose one of five sizes: `1024x1024`, `1536x1024`, `1024x1536`, `1152x864`, or `864x1152`; prompts may contain up to 28,000 characters. The full image count × 25 points is deducted when accepted, and 25 points are refunded immediately for every failed image. Accepted jobs cannot be cancelled. Results remain available for 24 hours.
|
|
153
|
+
|
|
154
|
+
`idempotencyKey` is a safety identifier that prevents duplicate generation and billing if a network problem sends the same request twice. Use 8–128 letters, numbers, underscores, or hyphens. Reuse it only for the exact same request and create a new value when the prompt or options change.
|
|
155
|
+
|
|
156
|
+
Methods: `generateImages`, `editImages`, `createImageGenerationJob`, `createImageEditJob`, `getImageJob`, `downloadImageJobImage`, and `downloadImageJobArchive`.
|
|
157
|
+
|
|
158
|
+
## Response shape
|
|
159
|
+
|
|
160
|
+
JSON methods resolve to:
|
|
161
|
+
|
|
162
|
+
```ts
|
|
163
|
+
{
|
|
164
|
+
data: unknown;
|
|
165
|
+
meta: {
|
|
166
|
+
cost: number | null;
|
|
167
|
+
durationMs: number | null;
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
`meta.cost` is the point charge reported by the API response. See the APICK documentation for current rates.
|
|
173
|
+
|
|
174
|
+
## Identity masking
|
|
175
|
+
|
|
176
|
+
```js
|
|
177
|
+
const png = await client.maskResidentNumber('./id-card.jpg', { type: 3 });
|
|
178
|
+
await png.save('./masked.png');
|
|
179
|
+
|
|
180
|
+
const result = await client.maskDriverLicense('./license.jpg');
|
|
181
|
+
console.log(result.data.result.fields);
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
The document-specific methods are `maskResidenceCard`, `maskPassport`, `maskIdCard`, and `maskDriverLicense`. Identity errors are exposed as `IDENTITY_TEXT_UNREADABLE`, `IDENTITY_DOCUMENT_MISMATCH`, or `IDENTITY_PROCESSING_FAILED` through `ApickApiError.serviceCode`.
|
|
185
|
+
|
|
186
|
+
`maskResidenceCard` accepts one front-side image of a residence card, permanent resident card, or overseas Korean resident card. Permanent and overseas Korean card support is limited to PII masking and does not expand the alien registration card authenticity-check scope.
|
|
187
|
+
|
|
188
|
+
## Simple-auth data lookups
|
|
189
|
+
|
|
190
|
+
Employment, income, pension, driver's license, and health checkup lookups require the user's own simple-auth verification, so the call is split into acceptance (`request*`) and result polling (`get*`).
|
|
191
|
+
|
|
192
|
+
Use this helper for all five products. Poll sequentially with the same `transactionId`, waiting 5→10→20→30 seconds and then keeping the 30-second interval. Return the result immediately when `resultAvailable === true`. `SUCCESS` means full success; `PARTIAL_SUCCESS` means partial success, so inspect `sources` for missing or failed items. `AUTH_REJECTED`, `AUTH_EXPIRED`, and `FAILED` are terminal failures; `errorCode: 'RESULT_EXPIRED'` means the retained result has expired. Never resubmit automatically after failure or expiry.
|
|
193
|
+
|
|
194
|
+
<!-- simple-auth-polling:start -->
|
|
85
195
|
```js
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
196
|
+
async function pollDataResult(getResult, accepted, { timeoutMs = 600_000 } = {}) {
|
|
197
|
+
const pending = new Set([
|
|
198
|
+
'AUTH_REQUESTED', 'AUTH_WAITING', 'AUTH_COMPLETED', 'COLLECTING', 'COLLECTED'
|
|
199
|
+
]);
|
|
200
|
+
const failed = new Set(['AUTH_REJECTED', 'AUTH_EXPIRED', 'FAILED']);
|
|
201
|
+
const completed = new Set(['SUCCESS', 'PARTIAL_SUCCESS']);
|
|
202
|
+
const delays = [5_000, 10_000, 20_000, 30_000];
|
|
203
|
+
const deadline = Date.now() + timeoutMs;
|
|
204
|
+
const transactionId = accepted.data.transactionId;
|
|
205
|
+
const stop = code => { throw Object.assign(new Error(code), { code }); };
|
|
206
|
+
let response = accepted;
|
|
207
|
+
let attempt = 0;
|
|
208
|
+
|
|
209
|
+
for (;;) {
|
|
210
|
+
const data = response.data;
|
|
211
|
+
if (data.errorCode === 'RESULT_EXPIRED') stop('RESULT_EXPIRED');
|
|
212
|
+
if (failed.has(data.status)) stop(data.errorCode || data.status);
|
|
213
|
+
if (data.resultAvailable === true) {
|
|
214
|
+
if (data.result == null) stop('INVALID_RESULT');
|
|
215
|
+
return response;
|
|
216
|
+
}
|
|
217
|
+
if (completed.has(data.status)) stop('RESULT_NOT_AVAILABLE');
|
|
218
|
+
if (!pending.has(data.status)) stop('UNKNOWN_STATUS');
|
|
219
|
+
|
|
220
|
+
const awaitingApproval = ['AUTH_REQUESTED', 'AUTH_WAITING'].includes(data.status);
|
|
221
|
+
const authDeadline = Date.parse(data.expiresAt || accepted.data.expiresAt);
|
|
222
|
+
const limit = awaitingApproval && Number.isFinite(authDeadline)
|
|
223
|
+
? Math.min(deadline, authDeadline) : deadline;
|
|
224
|
+
const timeoutCode = awaitingApproval && limit === authDeadline
|
|
225
|
+
? 'AUTH_WAIT_TIMEOUT' : 'CLIENT_POLL_TIMEOUT';
|
|
226
|
+
const remaining = limit - Date.now();
|
|
227
|
+
if (remaining <= 0) stop(timeoutCode);
|
|
228
|
+
await new Promise(resolve => setTimeout(resolve,
|
|
229
|
+
Math.min(delays[Math.min(attempt++, delays.length - 1)], remaining)));
|
|
230
|
+
if (Date.now() >= limit) stop(timeoutCode);
|
|
231
|
+
response = await getResult(transactionId);
|
|
232
|
+
}
|
|
101
233
|
}
|
|
102
|
-
|
|
103
|
-
// Cancellation is available while waiting or processing and does not refund the accepted charge.
|
|
104
|
-
// MP3 and ASS downloads each consume their server copy immediately and cannot be repeated.
|
|
105
|
-
|
|
106
|
-
const pdf = await client.htmlToPdf('<h1>Report</h1>', { pagination: true });
|
|
107
|
-
await pdf.save('./report.pdf');
|
|
108
|
-
|
|
109
|
-
const excel = await client.jsonToExcel([{ item: 'A', count: 3 }], {
|
|
110
|
-
sheetName: 'Inventory'
|
|
111
|
-
});
|
|
112
|
-
await excel.save('./inventory.xlsx');
|
|
113
234
|
```
|
|
235
|
+
<!-- simple-auth-polling:end -->
|
|
114
236
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
## Text AI
|
|
237
|
+
`AUTH_REQUESTED` and `AUTH_WAITING` wait for the user's approval; `AUTH_COMPLETED`, `COLLECTING`, and `COLLECTED` keep polling until a result is available. Billing fields (`charged`, `success`) do not indicate completion. Apply `expiresAt` only while awaiting approval, then use the overall waiting limit. The example's 10-minute limit is a client policy; configure the SDK's `timeoutMs` separately to bound each in-flight call. `AUTH_WAIT_TIMEOUT`, `CLIENT_POLL_TIMEOUT`, `RESULT_NOT_AVAILABLE`, `INVALID_RESULT`, and `UNKNOWN_STATUS` are local example errors that prevent endless polling on inconsistent responses or unknown states. Transport errors propagate without retries.
|
|
118
238
|
|
|
239
|
+
<!-- simple-auth-usage:start -->
|
|
119
240
|
```js
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
## Image AI
|
|
127
|
-
|
|
128
|
-
```js
|
|
129
|
-
const result = await client.generateImages('A clean product photo on white', {
|
|
130
|
-
imageCount: 4, size: '1024x1024', outputFormat: 'webp',
|
|
131
|
-
idempotencyKey: 'product-draft-001'
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
const referenceResult = await client.generateImages('Keep the product shape and composition, and change the background to a sunny kitchen', {
|
|
135
|
-
referenceImage: './reference.png',
|
|
136
|
-
referenceFilename: 'reference.png',
|
|
137
|
-
referenceContentType: 'image/png'
|
|
241
|
+
const accepted = await client.requestDrivingLicense({
|
|
242
|
+
name: 'Hong Gildong',
|
|
243
|
+
birthDate: '19900101',
|
|
244
|
+
phone: '01011112222',
|
|
245
|
+
authProvider: 'kakao'
|
|
138
246
|
});
|
|
139
247
|
|
|
140
|
-
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
## Response shape
|
|
151
|
-
|
|
152
|
-
JSON methods resolve to:
|
|
153
|
-
|
|
154
|
-
```ts
|
|
155
|
-
{
|
|
156
|
-
data: unknown;
|
|
157
|
-
meta: {
|
|
158
|
-
cost: number | null;
|
|
159
|
-
durationMs: number | null;
|
|
160
|
-
};
|
|
161
|
-
}
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
`meta.cost` is the point charge reported by the API response. See the APICK documentation for current rates.
|
|
165
|
-
|
|
166
|
-
## Identity masking
|
|
167
|
-
|
|
168
|
-
```js
|
|
169
|
-
const png = await client.maskResidentNumber('./id-card.jpg', { type: 3 });
|
|
170
|
-
await png.save('./masked.png');
|
|
171
|
-
|
|
172
|
-
const result = await client.maskDriverLicense('./license.jpg');
|
|
173
|
-
console.log(result.data.result.fields);
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
The document-specific methods are `maskResidenceCard`, `maskPassport`, `maskIdCard`, and `maskDriverLicense`. Identity errors are exposed as `IDENTITY_TEXT_UNREADABLE`, `IDENTITY_DOCUMENT_MISMATCH`, or `IDENTITY_PROCESSING_FAILED` through `ApickApiError.serviceCode`.
|
|
177
|
-
|
|
178
|
-
`maskResidenceCard` accepts one front-side image of a residence card, permanent resident card, or overseas Korean resident card. Permanent and overseas Korean card support is limited to PII masking and does not expand the alien registration card authenticity-check scope.
|
|
179
|
-
|
|
180
|
-
## Errors and retries
|
|
181
|
-
|
|
182
|
-
`ApickApiError` includes public error information: `code`, optional `serviceCode`, `status`, and `message`. The SDK does not retry automatically because a retry could duplicate an API call and its charge. If your application needs retries, decide explicitly after checking the error code and whether the operation is safe to repeat.
|
|
183
|
-
# TTS quality and recovery
|
|
184
|
-
|
|
185
|
-
Use `getTtsQuality(jobId)` to inspect utterance speed, rejection reasons, and candidate history. Candidates remain available for 72 hours after the job terminates. `downloadTtsCandidate(jobId, candidateId)` does not consume the final MP3 or ASS download.
|
|
186
|
-
|
|
187
|
-
`retryTtsJob(jobId, ['u002'], idempotencyKey)` requests technical recovery within the same job without an additional charge. Reuse the same key and utterance list after a lost response. Check `resume_revision` to identify the current revision. Required quality checks must pass before a job completes.
|
|
188
|
-
|
|
189
|
-
## Video model versions
|
|
190
|
-
|
|
191
|
-
Omitting `version` preserves Seedance 2.5, Veo 3.1 and Kling 3.0. Set `version` and `tier` explicitly to select a generation; jobs are never silently switched to another version. Submission and status responses include `version`.
|
|
192
|
-
|
|
193
|
-
Available generations: Seedance 1.0/1.5/2.0/2.5, including Seedance 2.0 Standard/Fast/Mini; Veo 3.1 (Standard/Fast/Lite); Kling 1.6/2.0/2.1/2.5/2.6/3.0/O1/O3. Veo 3.0 is unavailable. Seedance 2.0 Mini supports 480p/720p and 4–15 seconds. Modes, tiers, resolutions, durations, audio, file limits and prices vary by combination. See the [Seedance](https://apick.app/dev_guide/seedancejobs), [Veo](https://apick.app/dev_guide/veojobs) and [Kling](https://apick.app/dev_guide/klingjobs) version tables. Unsupported combinations are rejected before submission.
|
|
194
|
-
|
|
195
|
-
Seedance reference mode accepts `referenceImages`, `referenceVideos`, and `referenceAudios` (MP3/WAV) when supported by the selected version.
|
|
196
|
-
|
|
197
|
-
```js
|
|
198
|
-
const job = await client.createVideoJob("kling", "A boat crossing the sea", {
|
|
199
|
-
version: "1.6", tier: "std", mode: "text", duration: 5, audio: false,
|
|
200
|
-
idempotencyKey: "boat-video-0001"
|
|
201
|
-
});
|
|
202
|
-
const status = await client.getVideoJob("kling", job.data.job_id);
|
|
203
|
-
if (status.data.status === "completed") {
|
|
204
|
-
await (await client.downloadVideoResult("kling", job.data.job_id)).save("boat.mp4");
|
|
248
|
+
try {
|
|
249
|
+
const result = await pollDataResult(id => client.getDrivingLicense(id), accepted);
|
|
250
|
+
if (result.data.status === 'PARTIAL_SUCCESS') console.warn(result.data.sources);
|
|
251
|
+
console.log(result.data.result);
|
|
252
|
+
} catch (error) {
|
|
253
|
+
if ((error.serviceCode || error.code) === 'RESULT_EXPIRED') {
|
|
254
|
+
console.error('Result expired. Ask the user before starting a new authentication request.');
|
|
255
|
+
} else {
|
|
256
|
+
throw error;
|
|
257
|
+
}
|
|
205
258
|
}
|
|
206
259
|
```
|
|
260
|
+
<!-- simple-auth-usage:end -->
|
|
261
|
+
|
|
262
|
+
Sources: [APICK development guide](https://apick.app/dev_guide/data_health_checkup) · [MCP 3.5.0 status contract](https://github.com/lead788/apick-mcp/blob/a803abcb81d07377c85f49bb0b670baf0c17ed04/TOOLS.md)
|
|
263
|
+
|
|
264
|
+
`authProvider` is one of the 13 values in `AUTH_PROVIDERS` (kakao, naver, toss, pass, samsung, kb, shinhan, hana, woori, ibk, nh, kakaobank, banksalad). Acceptance is billed at a flat rate; the result is billed only on its first return and free to re-poll afterward. `requestEmployment` takes an optional `insuranceYears` (1-3), `requestPersonalIncome` takes `incomeYears` (1-5), and `requestNpsJoinHistory` takes optional `from`/`to` (`YYYY-MM`). The remaining products are `requestDrivingLicense` and `requestHealthCheckup`.
|
|
265
|
+
|
|
266
|
+
## Errors and retries
|
|
267
|
+
|
|
268
|
+
`ApickApiError` includes public error information: `code`, optional `serviceCode`, `status`, and `message`. The SDK does not retry automatically because a retry could duplicate an API call and its charge. If your application needs retries, decide explicitly after checking the error code and whether the operation is safe to repeat.
|
|
269
|
+
# TTS quality and recovery
|
|
270
|
+
|
|
271
|
+
Use `getTtsQuality(jobId)` to inspect utterance speed, rejection reasons, and candidate history. Candidates remain available for 72 hours after the job terminates. `downloadTtsCandidate(jobId, candidateId)` does not consume the final MP3 or ASS download.
|
|
272
|
+
|
|
273
|
+
`retryTtsJob(jobId, ['u002'], idempotencyKey)` requests technical recovery within the same job without an additional charge. Reuse the same key and utterance list after a lost response. Check `resume_revision` to identify the current revision. Required quality checks must pass before a job completes.
|
|
274
|
+
|
|
275
|
+
## Video model versions
|
|
276
|
+
|
|
277
|
+
Omitting `version` preserves Seedance 2.5, Veo 3.1 and Kling 3.0. Set `version` and `tier` explicitly to select a generation; jobs are never silently switched to another version. Submission and status responses include `version`.
|
|
278
|
+
|
|
279
|
+
Available generations: Seedance 1.0/1.5/2.0/2.5, including Seedance 2.0 Standard/Fast/Mini; Veo 3.1 (Standard/Fast/Lite); Kling 1.6/2.0/2.1/2.5/2.6/3.0/O1/O3. Veo 3.0 is unavailable. Seedance 2.0 Mini supports 480p/720p and 4–15 seconds. Modes, tiers, resolutions, durations, audio, file limits and prices vary by combination. See the [Seedance](https://apick.app/dev_guide/seedancejobs), [Veo](https://apick.app/dev_guide/veojobs) and [Kling](https://apick.app/dev_guide/klingjobs) version tables. Unsupported combinations are rejected before submission.
|
|
280
|
+
|
|
281
|
+
Seedance reference mode accepts `referenceImages`, `referenceVideos`, and `referenceAudios` (MP3/WAV) when supported by the selected version.
|
|
282
|
+
|
|
283
|
+
```js
|
|
284
|
+
const job = await client.createVideoJob("kling", "A boat crossing the sea", {
|
|
285
|
+
version: "1.6", tier: "std", mode: "text", duration: 5, audio: false,
|
|
286
|
+
idempotencyKey: "boat-video-0001"
|
|
287
|
+
});
|
|
288
|
+
const status = await client.getVideoJob("kling", job.data.job_id);
|
|
289
|
+
if (status.data.status === "completed") {
|
|
290
|
+
await (await client.downloadVideoResult("kling", job.data.job_id)).save("boat.mp4");
|
|
291
|
+
}
|
|
292
|
+
```
|