apick-api 2.3.1 → 3.0.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/CHANGELOG.md +12 -0
- package/README.md +13 -7
- package/docs/guide.en.md +12 -4
- package/docs/guide.ko.md +12 -4
- package/package.json +1 -1
- package/src/index.cjs +33 -15
- package/src/index.d.ts +8 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 3.0.0 - 2026-09-05
|
|
4
|
+
|
|
5
|
+
- 이미지 프롬프트 허용 길이를 최대 28,000자로 확대했습니다.
|
|
6
|
+
- 작업 접수 시 전체 포인트를 먼저 차감하고 실패한 이미지의 포인트를 즉시 환급하는 계약을 반영했습니다.
|
|
7
|
+
- 접수된 이미지 작업은 취소할 수 없도록 `cancelImageJob` 메서드와 `cancelled` 상태를 제거했습니다.
|
|
8
|
+
|
|
9
|
+
## 2.4.0 - 2026-09-05
|
|
10
|
+
|
|
11
|
+
- 이미지 장수 옵션을 의미가 분명한 `imageCount`로 바꾸고 압축 조정 옵션을 제거했습니다.
|
|
12
|
+
- 이미지 크기를 5개 표준 크기 중에서만 선택하도록 타입과 런타임 검증을 강화했습니다.
|
|
13
|
+
- 생성 요청에 선택적 `referenceImage`를 더해 참고 이미지와 텍스트를 함께 사용할 수 있습니다.
|
|
14
|
+
|
|
3
15
|
## 2.3.1 - 2026-09-05
|
|
4
16
|
|
|
5
17
|
- 이미지 편집 입력에서 마스크 파일을 제거하고 원본 이미지와 프롬프트만 받도록 계약을 단순화했습니다.
|
package/README.md
CHANGED
|
@@ -80,7 +80,7 @@ Leave the allowed-IP list blank for unrestricted access. To restrict access, reg
|
|
|
80
80
|
| `editImages(image, prompt, options)` | 이미지 편집 / Image editing | JSON |
|
|
81
81
|
| `createImageGenerationJob(prompt, options)` | 대량 이미지 생성 작업 / Batch generation job | JSON |
|
|
82
82
|
| `createImageEditJob(image, prompt, options)` | 대량 이미지 편집 작업 / Batch edit job | JSON |
|
|
83
|
-
| `getImageJob(jobId)`
|
|
83
|
+
| `getImageJob(jobId)` | 이미지 작업 상태 조회 / Job status | JSON |
|
|
84
84
|
| `downloadImageJobImage(jobId, index)` | 개별 결과 / Individual result | Binary |
|
|
85
85
|
| `downloadImageJobArchive(jobId)` | ZIP 결과 / ZIP archive | Binary |
|
|
86
86
|
|
|
@@ -101,29 +101,35 @@ console.log(result.meta);
|
|
|
101
101
|
|
|
102
102
|
## 이미지 생성·편집 / Image generation and editing
|
|
103
103
|
|
|
104
|
-
이미지는 장당 25포인트이며 동기는 1~4장, 작업형 API는 최대 50장까지 지원합니다.
|
|
104
|
+
이미지는 장당 25포인트이며 동기는 1~4장, 작업형 API는 최대 50장까지 지원합니다. 요청이 접수되면 전체 금액을 먼저 차감하고, 생성에 실패한 이미지가 있으면 해당 장수만큼 즉시 환급합니다. 접수된 작업은 취소할 수 없으며 결과는 완료 후 24시간 동안 반복 다운로드할 수 있습니다.
|
|
105
105
|
|
|
106
|
-
Images cost 25 points each. Synchronous calls support 1–4 images and job calls support up to 50.
|
|
106
|
+
Images cost 25 points each. Synchronous calls support 1–4 images and job calls support up to 50. The full amount is deducted when a request is accepted, and failed images are refunded immediately. Accepted jobs cannot be cancelled. Completed results remain downloadable for 24 hours.
|
|
107
107
|
|
|
108
108
|
```js
|
|
109
109
|
const made = await apick.generateImages("따뜻한 조명의 미니멀 제품 사진", {
|
|
110
|
-
|
|
110
|
+
imageCount: 2, size: "1024x1024", outputFormat: "webp",
|
|
111
111
|
idempotencyKey: "catalog-cover-20260905"
|
|
112
112
|
});
|
|
113
113
|
|
|
114
|
+
const referenced = await apick.generateImages("구도와 제품 형태는 유지하고 여름 해변 분위기로", {
|
|
115
|
+
referenceImage: "./reference.png",
|
|
116
|
+
referenceFilename: "reference.png",
|
|
117
|
+
referenceContentType: "image/png"
|
|
118
|
+
});
|
|
119
|
+
|
|
114
120
|
const edited = await apick.editImages("./source.png", "컵 색상을 파란색으로 변경", {
|
|
115
121
|
outputFormat: "png"
|
|
116
122
|
});
|
|
117
123
|
|
|
118
|
-
const queued = await apick.createImageGenerationJob("여행 포스터 시안", {
|
|
124
|
+
const queued = await apick.createImageGenerationJob("여행 포스터 시안", { imageCount: 20 });
|
|
119
125
|
const job = await apick.getImageJob(queued.data.job_id);
|
|
120
126
|
const image = await apick.downloadImageJobImage(job.data.job_id, 0);
|
|
121
127
|
await image.save("./result.png");
|
|
122
128
|
```
|
|
123
129
|
|
|
124
|
-
PNG·JPEG·WebP 출력, 투명 배경 미리보기(PNG/WebP), 표준
|
|
130
|
+
PNG·JPEG·WebP 출력, 투명 배경 미리보기(PNG/WebP), 5개 표준 크기(`1024x1024`, `1536x1024`, `1024x1536`, `1152x864`, `864x1152`)를 지원합니다. 입력 프롬프트는 최대 28,000자입니다. `idempotencyKey`는 네트워크 재전송 때 중복 생성과 중복 과금을 막는 8~128자의 요청 식별자이며, 같은 작업을 다시 보낼 때 같은 값을 사용합니다. 자동 재시도는 하지 않습니다.
|
|
125
131
|
|
|
126
|
-
PNG, JPEG, and WebP outputs, transparent-background previews for PNG/WebP, and standard
|
|
132
|
+
PNG, JPEG, and WebP outputs, transparent-background previews for PNG/WebP, and five standard sizes are supported. Prompts are limited to 28,000 characters. `idempotencyKey` identifies the same request during network retransmission to prevent duplicate generation and billing. Requests are never retried automatically.
|
|
127
133
|
|
|
128
134
|
OCR은 PNG/JPEG 파일 경로, `Blob`, `ArrayBuffer`, `Uint8Array`를 받습니다. 최대 크기는 50MB입니다.
|
|
129
135
|
OCR accepts a PNG/JPEG file path, `Blob`, `ArrayBuffer`, or `Uint8Array`, up to 50MB.
|
package/docs/guide.en.md
CHANGED
|
@@ -127,17 +127,25 @@ Text input is limited to 100,000 characters.
|
|
|
127
127
|
|
|
128
128
|
```js
|
|
129
129
|
const result = await client.generateImages('A clean product photo on white', {
|
|
130
|
-
|
|
130
|
+
imageCount: 4, size: '1024x1024', outputFormat: 'webp',
|
|
131
131
|
idempotencyKey: 'product-draft-001'
|
|
132
132
|
});
|
|
133
133
|
|
|
134
|
-
const
|
|
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'
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
const job = await client.createImageGenerationJob('Landscape article cover concepts', { imageCount: 20, size: '1536x1024' });
|
|
135
141
|
const status = await client.getImageJob(job.data.job_id);
|
|
136
142
|
```
|
|
137
143
|
|
|
138
|
-
Synchronous generation and editing support 1–4 images; job methods support 1–50. Editing accepts one PNG, JPEG, or WebP source up to 50 MB plus a prompt; mask files are not supported.
|
|
144
|
+
`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.
|
|
145
|
+
|
|
146
|
+
`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.
|
|
139
147
|
|
|
140
|
-
Methods: `generateImages`, `editImages`, `createImageGenerationJob`, `createImageEditJob`, `getImageJob`, `
|
|
148
|
+
Methods: `generateImages`, `editImages`, `createImageGenerationJob`, `createImageEditJob`, `getImageJob`, `downloadImageJobImage`, and `downloadImageJobArchive`.
|
|
141
149
|
|
|
142
150
|
## Response shape
|
|
143
151
|
|
package/docs/guide.ko.md
CHANGED
|
@@ -127,19 +127,27 @@ const polished = await client.polish(draftText);
|
|
|
127
127
|
|
|
128
128
|
```js
|
|
129
129
|
const result = await client.generateImages('흰 배경의 제품 사진', {
|
|
130
|
-
|
|
130
|
+
imageCount: 4,
|
|
131
131
|
size: '1024x1024',
|
|
132
132
|
outputFormat: 'webp',
|
|
133
133
|
idempotencyKey: 'product-draft-001'
|
|
134
134
|
});
|
|
135
135
|
|
|
136
|
-
const
|
|
136
|
+
const referenceResult = await client.generateImages('제품 모양과 구도는 유지하고 배경을 햇살 좋은 주방으로 변경', {
|
|
137
|
+
referenceImage: './reference.png',
|
|
138
|
+
referenceFilename: 'reference.png',
|
|
139
|
+
referenceContentType: 'image/png'
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
const job = await client.createImageGenerationJob('가로형 커버 시안', { imageCount: 20, size: '1536x1024' });
|
|
137
143
|
const status = await client.getImageJob(job.data.job_id);
|
|
138
144
|
```
|
|
139
145
|
|
|
140
|
-
동기 생성·편집은 1~4장, 작업형 생성·편집은 1~50장입니다. 편집은 50MB 이하의 PNG/JPEG/WebP 원본 이미지 한 장과 프롬프트를 받으며 마스크 파일은 지원하지 않습니다.
|
|
146
|
+
`imageCount`는 만들 이미지 장수이며 생략하면 1장입니다. 동기 생성·편집은 1~4장, 작업형 생성·편집은 1~50장입니다. 생성에 `referenceImage`를 함께 전달하면 참고 이미지의 구도·색감·제품 형태 등을 프롬프트와 조합할 수 있습니다. 편집은 50MB 이하의 PNG/JPEG/WebP 원본 이미지 한 장과 프롬프트를 받으며 마스크 파일은 지원하지 않습니다. 크기는 `1024x1024`, `1536x1024`, `1024x1536`, `1152x864`, `864x1152` 중에서 선택하고 프롬프트는 최대 28,000자까지 입력할 수 있습니다. 접수 시 이미지 장수×25포인트를 먼저 차감하며 실패한 이미지의 25포인트는 즉시 환급합니다. 접수된 작업은 취소할 수 없습니다. 결과 보관 기간은 완료 후 24시간입니다.
|
|
147
|
+
|
|
148
|
+
`idempotencyKey`는 같은 요청이 통신 오류로 두 번 전송됐을 때 중복 생성과 중복 과금을 막는 안전번호입니다. 영문·숫자·밑줄·하이픈으로 8~128자를 만들고, 같은 작업을 다시 보낼 때는 같은 값을 사용하세요. 프롬프트나 옵션이 달라진 새 작업에는 새 값을 사용해야 합니다.
|
|
141
149
|
|
|
142
|
-
지원 메서드: `generateImages`, `editImages`, `createImageGenerationJob`, `createImageEditJob`, `getImageJob`, `
|
|
150
|
+
지원 메서드: `generateImages`, `editImages`, `createImageGenerationJob`, `createImageEditJob`, `getImageJob`, `downloadImageJobImage`, `downloadImageJobArchive`.
|
|
143
151
|
|
|
144
152
|
## 응답 구조
|
|
145
153
|
|
package/package.json
CHANGED
package/src/index.cjs
CHANGED
|
@@ -4,6 +4,8 @@ const DEFAULT_BASE_URL = 'https://apick.app';
|
|
|
4
4
|
const DEFAULT_TIMEOUT_MS = 30_000;
|
|
5
5
|
const MAX_OCR_BYTES = 50 * 1024 * 1024;
|
|
6
6
|
const MAX_IMAGE_AI_BYTES = 50 * 1024 * 1024;
|
|
7
|
+
const IMAGE_AI_SIZES = Object.freeze(['1024x1024', '1536x1024', '1024x1536', '1152x864', '864x1152']);
|
|
8
|
+
const IMAGE_AI_SIZE_SET = new Set(IMAGE_AI_SIZES);
|
|
7
9
|
const TTS_VOICE_IDS = Object.freeze([
|
|
8
10
|
'narrator_m_01', 'narrator_m_02', 'narrator_m_03', 'narrator_m_04', 'narrator_m_05',
|
|
9
11
|
'narrator_f_10s_01', 'narrator_f_10s_02', 'narrator_f_10s_03',
|
|
@@ -529,17 +531,18 @@ class ApickClient {
|
|
|
529
531
|
|
|
530
532
|
_imageOptions(prompt, options, maxCount) {
|
|
531
533
|
const config = options || {};
|
|
532
|
-
for (const key of ['model', 'quality', 'n', 'input_fidelity', 'moderation', 'mask', 'maskFilename', 'maskContentType']) {
|
|
534
|
+
for (const key of ['model', 'quality', 'count', 'n', 'outputCompression', 'input_fidelity', 'moderation', 'mask', 'maskFilename', 'maskContentType']) {
|
|
533
535
|
if (Object.prototype.hasOwnProperty.call(config, key)) throw new TypeError(`${key} is not a supported image option.`);
|
|
534
536
|
}
|
|
535
|
-
const
|
|
536
|
-
if (
|
|
537
|
+
const imageCount = positiveInteger('imageCount', config.imageCount, 1);
|
|
538
|
+
if (imageCount > maxCount) throw new RangeError(`imageCount must not exceed ${maxCount}.`);
|
|
539
|
+
const size = config.size || '1024x1024';
|
|
540
|
+
if (!IMAGE_AI_SIZE_SET.has(size)) throw new TypeError(`size must be one of: ${IMAGE_AI_SIZES.join(', ')}.`);
|
|
537
541
|
const payload = {
|
|
538
|
-
prompt: requiredString('prompt', prompt,
|
|
539
|
-
size
|
|
542
|
+
prompt: requiredString('prompt', prompt, 28_000), image_count: imageCount,
|
|
543
|
+
size, output_format: config.outputFormat || 'png',
|
|
540
544
|
background: config.background || 'auto'
|
|
541
545
|
};
|
|
542
|
-
if (config.outputCompression !== undefined) payload.output_compression = config.outputCompression;
|
|
543
546
|
if (config.idempotencyKey !== undefined) {
|
|
544
547
|
payload.idempotency_key = requiredString('idempotencyKey', config.idempotencyKey, 128);
|
|
545
548
|
if (!/^[A-Za-z0-9_-]{8,128}$/.test(payload.idempotency_key)) throw new TypeError('idempotencyKey must use 8-128 letters, numbers, underscores, or hyphens.');
|
|
@@ -547,8 +550,18 @@ class ApickClient {
|
|
|
547
550
|
return payload;
|
|
548
551
|
}
|
|
549
552
|
|
|
550
|
-
generateImages(prompt, options) {
|
|
551
|
-
|
|
553
|
+
async generateImages(prompt, options) {
|
|
554
|
+
const config = options || {}, payload = this._imageOptions(prompt, config, 4);
|
|
555
|
+
if (config.referenceImage === undefined) return this._call('generateImages', payload);
|
|
556
|
+
const uploadOptions = {
|
|
557
|
+
filename: config.referenceFilename, contentType: config.referenceContentType,
|
|
558
|
+
allowedTypes:['image/png','image/jpeg','image/webp'], maxBytes:MAX_IMAGE_AI_BYTES,
|
|
559
|
+
typeError:'referenceImage must be PNG, JPEG, or WebP.'
|
|
560
|
+
};
|
|
561
|
+
const source = await normalizeImage(config.referenceImage, uploadOptions), form = new FormData();
|
|
562
|
+
Object.entries(payload).forEach(([key,value]) => form.append(key, String(value)));
|
|
563
|
+
form.append('reference_image', source.blob, source.filename);
|
|
564
|
+
return this._call('generateImages', null, form);
|
|
552
565
|
}
|
|
553
566
|
|
|
554
567
|
async editImages(image, prompt, options) {
|
|
@@ -560,8 +573,18 @@ class ApickClient {
|
|
|
560
573
|
return this._call('generateImages', null, form, { endpoint:'/rest/image-generation/edit' });
|
|
561
574
|
}
|
|
562
575
|
|
|
563
|
-
createImageGenerationJob(prompt, options) {
|
|
564
|
-
|
|
576
|
+
async createImageGenerationJob(prompt, options) {
|
|
577
|
+
const config = options || {}, payload = this._imageOptions(prompt, config, 50);
|
|
578
|
+
if (config.referenceImage === undefined) return this._call('generateImages', payload, null, { endpoint:'/rest/image-generation/jobs/generate', timeoutMs:60_000 });
|
|
579
|
+
const uploadOptions = {
|
|
580
|
+
filename: config.referenceFilename, contentType: config.referenceContentType,
|
|
581
|
+
allowedTypes:['image/png','image/jpeg','image/webp'], maxBytes:MAX_IMAGE_AI_BYTES,
|
|
582
|
+
typeError:'referenceImage must be PNG, JPEG, or WebP.'
|
|
583
|
+
};
|
|
584
|
+
const source = await normalizeImage(config.referenceImage, uploadOptions), form = new FormData();
|
|
585
|
+
Object.entries(payload).forEach(([key,value]) => form.append(key, String(value)));
|
|
586
|
+
form.append('reference_image', source.blob, source.filename);
|
|
587
|
+
return this._call('generateImages', null, form, { endpoint:'/rest/image-generation/jobs/generate', timeoutMs:60_000 });
|
|
565
588
|
}
|
|
566
589
|
|
|
567
590
|
async createImageEditJob(image, prompt, options) {
|
|
@@ -578,11 +601,6 @@ class ApickClient {
|
|
|
578
601
|
return this._call('generateImages', null, null, { endpoint:'/rest/image-generation/jobs/'+id, method:'GET', timeoutMs:30_000 });
|
|
579
602
|
}
|
|
580
603
|
|
|
581
|
-
cancelImageJob(jobId) {
|
|
582
|
-
const id = normalizeTtsJobId(jobId);
|
|
583
|
-
return this._call('generateImages', null, null, { endpoint:'/rest/image-generation/jobs/'+id+'/cancel', timeoutMs:30_000 });
|
|
584
|
-
}
|
|
585
|
-
|
|
586
604
|
downloadImageJobImage(jobId, index) {
|
|
587
605
|
const id=normalizeTtsJobId(jobId), value=Number(index);
|
|
588
606
|
if(!Number.isInteger(value)||value<0||value>49) throw new RangeError('index must be an integer from 0 through 49.');
|
package/src/index.d.ts
CHANGED
|
@@ -29,13 +29,15 @@ export interface OcrOptions {
|
|
|
29
29
|
|
|
30
30
|
export type ImageAiFormat = 'png' | 'jpeg' | 'webp';
|
|
31
31
|
export type ImageAiBackground = 'auto' | 'opaque' | 'transparent';
|
|
32
|
-
export type
|
|
32
|
+
export type ImageAiSize = '1024x1024' | '1536x1024' | '1024x1536' | '1152x864' | '864x1152';
|
|
33
|
+
export type ImageAiStatus = 'waiting' | 'processing' | 'completed' | 'completed_partial' | 'failed';
|
|
33
34
|
export type ApickImageErrorCode = `APICK_IMAGE_${string}`;
|
|
34
|
-
export interface ImageAiOptions {
|
|
35
|
+
export interface ImageAiOptions { imageCount?: number; size?: ImageAiSize; outputFormat?: ImageAiFormat; background?: ImageAiBackground; idempotencyKey?: string; }
|
|
36
|
+
export interface ImageAiGenerateOptions extends ImageAiOptions { referenceImage?: string|BinaryInput|ArrayBuffer|ArrayBufferView; referenceFilename?: string; referenceContentType?: 'image/png'|'image/jpeg'|'image/webp'; }
|
|
35
37
|
export interface ImageAiEditOptions extends ImageAiOptions { filename?: string; contentType?: 'image/png'|'image/jpeg'|'image/webp'; }
|
|
36
38
|
export interface ImageAiResultImage { index:number; b64_json:string; mime_type:'image/png'|'image/jpeg'|'image/webp'; width:number; height:number; }
|
|
37
|
-
export interface ImageAiResultData { request_id:string;
|
|
38
|
-
export interface ImageAiJobData { job_id:string; status:ImageAiStatus; requested_count:number; completed_count?:number; failed_count?:number; charged_point?:number; result_available?:boolean; expires_at?:string|null; error_code?:ApickImageErrorCode|null; }
|
|
39
|
+
export interface ImageAiResultData { request_id:string; image_count:number; images:ImageAiResultImage[]; idempotent_replay?:boolean; }
|
|
40
|
+
export interface ImageAiJobData { job_id:string; status:ImageAiStatus; requested_count:number; completed_count?:number; failed_count?:number; prepaid_point?:number; charged_point?:number; refunded_point?:number; result_available?:boolean; expires_at?:string|null; error_code?:ApickImageErrorCode|null; }
|
|
39
41
|
|
|
40
42
|
export interface MaskResidentNumberOptions extends OcrOptions {
|
|
41
43
|
type: 1 | 2 | 3;
|
|
@@ -121,12 +123,11 @@ export class ApickClient {
|
|
|
121
123
|
jsonToExcel(data: unknown[], options?: { sheetName?: string }): Promise<ApickBinaryResult>;
|
|
122
124
|
summarize(text: string): Promise<ApickResult>;
|
|
123
125
|
polish(text: string): Promise<ApickResult>;
|
|
124
|
-
generateImages(prompt:string, options?:
|
|
126
|
+
generateImages(prompt:string, options?:ImageAiGenerateOptions): Promise<ApickResult<ImageAiResultData>>;
|
|
125
127
|
editImages(image:string|BinaryInput|ArrayBuffer|ArrayBufferView, prompt:string, options?:ImageAiEditOptions): Promise<ApickResult<ImageAiResultData>>;
|
|
126
|
-
createImageGenerationJob(prompt:string, options?:
|
|
128
|
+
createImageGenerationJob(prompt:string, options?:ImageAiGenerateOptions): Promise<ApickResult<ImageAiJobData>>;
|
|
127
129
|
createImageEditJob(image:string|BinaryInput|ArrayBuffer|ArrayBufferView, prompt:string, options?:ImageAiEditOptions): Promise<ApickResult<ImageAiJobData>>;
|
|
128
130
|
getImageJob(jobId:string): Promise<ApickResult<ImageAiJobData>>;
|
|
129
|
-
cancelImageJob(jobId:string): Promise<ApickResult<ImageAiJobData>>;
|
|
130
131
|
downloadImageJobImage(jobId:string,index:number): Promise<ApickBinaryResult>;
|
|
131
132
|
downloadImageJobArchive(jobId:string): Promise<ApickBinaryResult>;
|
|
132
133
|
}
|