apick-api 4.5.0 → 4.8.2
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 +32 -0
- package/LICENSE +21 -21
- package/README.md +15 -8
- package/SECURITY.md +11 -11
- package/docs/guide.en.md +1 -22
- package/docs/guide.ko.md +1 -22
- package/package.json +71 -71
- package/src/index.cjs +45 -79
- package/src/index.d.ts +45 -108
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,35 @@
|
|
|
1
|
+
# 4.8.2
|
|
2
|
+
|
|
3
|
+
- 차명에 등급·연식·좌석을 함께 넣을 수 있습니다(`파나메라 gts 4인승 19년식`, `PANAMERA GTS 19년`). 입력한 연식·등급을 우선하며 좌석 수는 실제 제원과 일치해야 합니다. 근접 연식을 선택하면 반환 연식과 안내를 확인하세요. 지정 등급을 찾지 못하거나 확신이 낮으면 제원 없이 무료 후보만 반환하며, 유사 차량이 전혀 없으면 없음 오류로 응답하고 과금하지 않습니다. 별도 연식·등급과 문장 조건이 충돌하면 입력 오류입니다.
|
|
4
|
+
- Put the model, trim, year and seat count in model (for example, PANAMERA GTS 19년). Matching prioritizes the supplied year and trim, and the seat count must match the specification. Check the returned year and notice when a nearby year is selected. Unmatched trims and low-confidence matches return suggestions without specifications or charges; no similar vehicle returns a no-result error without charging. Conflicting explicit and free-text constraints are rejected.
|
|
5
|
+
|
|
6
|
+
# 4.8.1
|
|
7
|
+
|
|
8
|
+
- `vehicleModelInfo(options)` also covers motorcycles and scooters alongside passenger cars; the `차체형상` value adds 스쿠터, 언더본, 네이키드, 스포츠바이크, 투어링바이크, 크루저, 어드벤처, 오프로드 and 클래식바이크. Request and response shapes are unchanged.
|
|
9
|
+
- `vehicleModelInfo(options)` 가 승용차에 더해 오토바이·스쿠터 같은 이륜차도 조회합니다. `차체형상` 값에 스쿠터·언더본·네이키드·스포츠바이크·투어링바이크·크루저·어드벤처·오프로드·클래식바이크가 추가됩니다. 요청·응답 형식은 바뀌지 않았습니다.
|
|
10
|
+
|
|
11
|
+
# 4.8.0
|
|
12
|
+
|
|
13
|
+
- `vehicleModelInfo(options)` now finds the closest model when the brand, model name or trim is written differently (`아반테`/`아반떼`, `K5 하이브리드`/`K5`, `520i`/`5시리즈`). A high-confidence match returns the specification plus `추천` (`자동선택: true`, `대안`); a low-confidence match returns `추천.대안` only and is not billed. When the requested trim has no specification, the response keeps the same model's base specification and adds `제원.등급후보` and `안내` instead of silently returning a different trim.
|
|
14
|
+
- 브랜드·차명·등급 표기가 달라도(`아반테`/`아반떼`, `K5 하이브리드`/`K5`, `520i`/`5시리즈`) `vehicleModelInfo(options)` 가 가장 비슷한 차종을 찾습니다. 확신이 높으면 제원과 함께 `추천`(`자동선택: true`, `대안`)을 주고, 낮으면 `추천.대안` 만 주며 과금하지 않습니다. 지정한 등급의 제원이 없으면 다른 등급을 조용히 돌려주지 않고 같은 차명의 기본 제원과 `제원.등급후보`, `안내` 를 함께 줍니다.
|
|
15
|
+
|
|
16
|
+
- Added `requestNpsDeductionCert(input)` / `getNpsDeductionCert(transactionId)` for `POST /rest/req_nps_deduction_cert` and `POST /rest/get_nps_deduction_cert` — the National Pension payment certificate used for income deduction. Takes an optional `years` (1-5, default 1) and returns per-year paid amounts (`연도별내역`) for workplace subscribers, regional subscribers, retroactive payments, additional payments and unemployment credit, plus the certificate holder name and birth date.
|
|
17
|
+
- Added `requestNpsCareerHistory(input)` / `getNpsCareerHistory(transactionId)` for `POST /rest/req_nps_career_history` and `POST /rest/get_nps_career_history` — employment career history derived from the join history. Takes optional `from`/`to` (`YYYY-MM`) and returns workplace careers (`경력`) with the workplace name, period, last standard monthly income, paid and unpaid months and paid amount, a per-workplace summary (`합계`), and periods without a workplace such as regional subscribers (`사업장외가입`). Both share one phone approval with `requestNpsJoinHistory` and are billed the same way (acceptance is billed, the first result is billed, re-reads are free).
|
|
18
|
+
- 국민연금 소득공제용 납부확인서 조회 메서드 `requestNpsDeductionCert()` / `getNpsDeductionCert()` 를 추가했습니다(`POST /rest/req_nps_deduction_cert`·`POST /rest/get_nps_deduction_cert`). 선택 입력 `years`(1~5, 기본 1)를 받고 발급연도별 납부금액(`연도별내역`: 사업장가입자 고지·지역가입자 등 납부·소급·추납·실업크레딧·총합계)과 증명서의 이름·생년월일을 돌려줍니다.
|
|
19
|
+
- 국민연금 경력 이력 조회 메서드 `requestNpsCareerHistory()` / `getNpsCareerHistory()` 를 추가했습니다(`POST /rest/req_nps_career_history`·`POST /rest/get_nps_career_history`). 가입내역에서 사업장 단위 경력을 파생하며 선택 입력 `from`/`to`(`YYYY-MM`)를 받습니다. 사업장명·기간·기준소득월액·납부개월·미납개월·납부금액(`경력`), 사업장 기준 합계(`합계`), 지역가입 등 사업장이 없는 구간(`사업장외가입`)을 돌려줍니다. 두 상품 모두 `requestNpsJoinHistory` 와 승인 1회를 공유하고 과금 방식도 같습니다(접수 과금, 최초 결과 과금, 재조회 무료).
|
|
20
|
+
|
|
21
|
+
# 4.7.0
|
|
22
|
+
|
|
23
|
+
- Added `vehicleModelInfo(options)` for `POST /rest/vehicle_model_info` — look up Korean-market vehicle model specifications (dimensions, engine, efficiency, tires, trim candidates) by brand, model name, model year and trim. Every input field is optional: with no `model` the response is the brand or model list and the call is free, and an unknown model or a model without specifications fails without being charged. Specification values come back in fixed standard notation (`연료` gasoline·diesel·LPG·electric·hydrogen·hybrid, `구동방식` front·rear·2WD·AWD, `변속기` `자동 8단`·`DCT 7단`·`CVT`, `에너지효율등급` `1등급`~`5등급`), with multiple values joined by `+`.
|
|
24
|
+
- 차종별 차량정보 조회 메서드 `vehicleModelInfo(options)` 를 추가했습니다(`POST /rest/vehicle_model_info`). 브랜드·차명·연식·등급으로 배기량·연비·치수·타이어·등급 후보 같은 제원을 조회합니다. 입력은 모두 선택이며 `model` 을 비우면 브랜드·차종 목록을 무료로 돌려주고, 없는 차종이나 제원이 아직 없는 차종은 과금 없이 실패합니다. 제원 값은 고정된 표준 표기로만 내려갑니다(연료·구동방식·변속기·차체형상·에너지효율등급, 여러 값은 `+` 연결).
|
|
25
|
+
|
|
26
|
+
# 4.6.0
|
|
27
|
+
|
|
28
|
+
- Removed the collection-job methods `createInstagramPostsJob()`, `createInstagramCommentsJob()`, `createTiktokSearchJob()`, `createTiktokVideoJob()`, `createTiktokCommentsJob()`, `createAmazonReviewsJob()`, `createGoogleMapsPlaceJob()`, `getScrapeJob()` and `waitForScrapeJob()` and their types (`ScrapeJobProduct`, `ScrapeJobOptions`, `ScrapeJob<T>`) — every request is now a single synchronous call. The synchronous methods (`amazonProduct()`, `xProfile()`, `xPost()`, `googleMapsSearch()`, `youtubeComments()`, …) are unchanged.
|
|
29
|
+
- Results of retired job submissions already accepted are still settled by the server; `apick-mcp` 4.6.0 matches this release.
|
|
30
|
+
- 결과 건수 과금 수집 작업 메서드 `createInstagramPostsJob()`·`createInstagramCommentsJob()`·`createTiktokSearchJob()`·`createTiktokVideoJob()`·`createTiktokCommentsJob()`·`createAmazonReviewsJob()`·`createGoogleMapsPlaceJob()`·`getScrapeJob()`·`waitForScrapeJob()` 과 타입(`ScrapeJobProduct`, `ScrapeJobOptions`, `ScrapeJob<T>`)을 제거했습니다. 모든 요청은 단발 동기 호출만 사용합니다. 동기 메서드(`amazonProduct()`, `xProfile()`, `xPost()`, `googleMapsSearch()`, `youtubeComments()` 등)는 그대로입니다.
|
|
31
|
+
- 이미 접수된 작업의 정산은 서버가 계속 처리합니다. `apick-mcp` 4.6.0 과 같은 계약입니다.
|
|
32
|
+
|
|
1
33
|
# 4.5.0
|
|
2
34
|
|
|
3
35
|
- Added `coupangProduct(urlOrProductId)`, `naverShoppingProduct(url)`, `linkedinProfile(url)`, `linkedinCompany(url)` and `linkedinJob(url)` with the matching result types (`CoupangProduct`, `NaverShoppingProduct`, `LinkedinProfile`, `LinkedinCompany`, `LinkedinJob`). Coupang takes a product number or `/vp/products/{id}` URL, Naver takes a brand store product URL (`brand.naver.com/{store}/products/{id}`), and LinkedIn takes profile (`/in/`), company (`/company/`) or job posting (`/jobs/view/`) URLs. Each call is synchronous; failed calls are not charged.
|
package/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 APICK
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 APICK
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -64,6 +64,7 @@ Leave the allowed-IP list blank for unrestricted access. To restrict access, reg
|
|
|
64
64
|
| `validatePhone(number)` | 전화번호 유효성 / Phone validation | JSON |
|
|
65
65
|
| `holidays(year, month)` | 대한민국 공휴일 / Korean holidays | JSON |
|
|
66
66
|
| `searchAddress(query, options)` | 도로명주소 검색 / Road address search | JSON |
|
|
67
|
+
| `vehicleModelInfo(options)` | 차종별 차량정보 조회 / Vehicle model specifications for cars and motorcycles/scooters (승용차·이륜차 / 표기가 달라도 가장 비슷한 차종 / closest match when spelled differently · 값은 표준 표기 / standard notation values) | JSON |
|
|
67
68
|
| `ocr(image, options)` | 이미지 OCR / Image OCR | JSON |
|
|
68
69
|
| `dnsLookup(domain)` | DNS 조회 / DNS lookup | JSON |
|
|
69
70
|
| `geolocate(address)` | 도메인·IP 위치 / Domain and IP location | JSON |
|
|
@@ -95,14 +96,6 @@ Leave the allowed-IP list blank for unrestricted access. To restrict access, reg
|
|
|
95
96
|
| `linkedinProfile(url)` | 링크드인 프로필 / LinkedIn profile | JSON |
|
|
96
97
|
| `linkedinCompany(url)` | 링크드인 회사 정보 / LinkedIn company | JSON |
|
|
97
98
|
| `linkedinJob(url)` | 링크드인 채용공고 / LinkedIn job posting | JSON |
|
|
98
|
-
| `createInstagramPostsJob(usernameOrUrl, options)` | 인스타그램 게시물 목록 수집 접수(최대 100) / Instagram posts job | JSON |
|
|
99
|
-
| `createInstagramCommentsJob(url, options)` | 인스타그램 댓글 수집 접수(최대 15) / Instagram comments job | JSON |
|
|
100
|
-
| `createTiktokSearchJob(keyword, options)` | 틱톡 키워드 영상 검색 접수(최대 50) / TikTok keyword search job | JSON |
|
|
101
|
-
| `createTiktokVideoJob(url, options)` | 틱톡 영상 정보 접수 / TikTok video job | JSON |
|
|
102
|
-
| `createTiktokCommentsJob(url, options)` | 틱톡 댓글 수집 접수(최대 100) / TikTok comments job | JSON |
|
|
103
|
-
| `createAmazonReviewsJob(urlOrAsin, options)` | 아마존 리뷰 수집 접수(최대 100) / Amazon reviews job | JSON |
|
|
104
|
-
| `createGoogleMapsPlaceJob(placeIdOrUrl, options)` | 구글 지도 장소 상세·별점 분포·대표 리뷰 접수 / Google Maps place details and top reviews job | JSON |
|
|
105
|
-
| `getScrapeJob(jobId)` / `waitForScrapeJob(jobId, options)` | 수집 작업 상태·결과(무료, 결과 건수로 정산) / Collection job status and results | JSON |
|
|
106
99
|
| `createTtsJob(text, options)` | 한국어 내레이션 작업 접수 / Create TTS job | JSON |
|
|
107
100
|
| `getTtsJob(jobId)` | TTS 작업 상태 / TTS job status | JSON |
|
|
108
101
|
| `cancelTtsJob(jobId)` | 대기·생성 중 TTS 작업 취소 / Cancel waiting or processing TTS job | JSON |
|
|
@@ -125,6 +118,8 @@ Leave the allowed-IP list blank for unrestricted access. To restrict access, reg
|
|
|
125
118
|
| `requestEmployment(input)` / `getEmployment(transactionId)` | 재직·보험료 확인 / Employment & insurance premium check | JSON |
|
|
126
119
|
| `requestPersonalIncome(input)` / `getPersonalIncome(transactionId)` | 금융소득(이자·배당) 조회 / Financial income (interest/dividend) | JSON |
|
|
127
120
|
| `requestNpsJoinHistory(input)` / `getNpsJoinHistory(transactionId)` | 국민연금 가입내역조회 / National Pension join history | JSON |
|
|
121
|
+
| `requestNpsDeductionCert(input)` / `getNpsDeductionCert(transactionId)` | 국민연금 소득공제용 납부확인서 / National Pension payment certificate for income deduction | JSON |
|
|
122
|
+
| `requestNpsCareerHistory(input)` / `getNpsCareerHistory(transactionId)` | 국민연금 경력 이력 조회 / National Pension career history | JSON |
|
|
128
123
|
| `requestDrivingLicense(input)` / `getDrivingLicense(transactionId)` | 운전면허 조회 / Driver's license check | JSON |
|
|
129
124
|
| `requestHealthCheckup(input)` / `getHealthCheckup(transactionId)` | 국가 건강검진 결과 조회 / National health checkup results | JSON |
|
|
130
125
|
| `requestCashReceiptDeduction(input)` / `getCashReceiptDeduction(transactionId)` | 현금영수증 소득공제 내역 / Cash receipt income deductions | JSON |
|
|
@@ -410,6 +405,8 @@ Acceptance is billed at a flat rate; the result is billed only on its first succ
|
|
|
410
405
|
| 재직·보험료 확인 / Employment & insurance premium | `requestEmployment` / `getEmployment` | `insuranceYears` (1–3) |
|
|
411
406
|
| 금융소득 조회 / Financial income | `requestPersonalIncome` / `getPersonalIncome` | `incomeYears` (1–5) |
|
|
412
407
|
| 국민연금 가입내역 / NPS join history | `requestNpsJoinHistory` / `getNpsJoinHistory` | `from`, `to` (`YYYY-MM`) |
|
|
408
|
+
| 국민연금 소득공제용 납부확인서 / NPS payment certificate | `requestNpsDeductionCert` / `getNpsDeductionCert` | `years` (1–5) |
|
|
409
|
+
| 국민연금 경력 이력 / NPS career history | `requestNpsCareerHistory` / `getNpsCareerHistory` | `from`, `to` (`YYYY-MM`) |
|
|
413
410
|
| 운전면허 조회 / Driver's license | `requestDrivingLicense` / `getDrivingLicense` | — |
|
|
414
411
|
| 국가 건강검진 결과 / Health checkup | `requestHealthCheckup` / `getHealthCheckup` | — |
|
|
415
412
|
| 현금영수증 소득공제 내역 / Cash receipt deductions | `requestCashReceiptDeduction` / `getCashReceiptDeduction` | `incomeYears` (1–3) |
|
|
@@ -508,3 +505,13 @@ Set `APICK_API_KEY` in the environment. 원격 MCP는 업로드된 자료를 처
|
|
|
508
505
|
|
|
509
506
|
|
|
510
507
|
TTS: [Gemini·ChatGPT·정규화 / engines and normalization](docs/tts.md). `createOpenAiTtsJob`, `listOpenAiTtsVoices`, `getTtsOptions`를 포함한 최신 계약입니다.
|
|
508
|
+
|
|
509
|
+
## 차량 자유문 검색 / Vehicle free-text search
|
|
510
|
+
|
|
511
|
+
차명에 등급·연식·좌석을 함께 넣을 수 있습니다(`파나메라 gts 4인승 19년식`, `PANAMERA GTS 19년`). 입력한 연식·등급을 우선하며 좌석 수는 실제 제원과 일치해야 합니다. 근접 연식을 선택하면 반환 연식과 안내를 확인하세요. 지정 등급을 찾지 못하거나 확신이 낮으면 제원 없이 무료 후보만 반환하며, 유사 차량이 전혀 없으면 없음 오류로 응답하고 과금하지 않습니다. 별도 연식·등급과 문장 조건이 충돌하면 입력 오류입니다.
|
|
512
|
+
|
|
513
|
+
Put the model, trim, year and seat count in model (for example, PANAMERA GTS 19년). Matching prioritizes the supplied year and trim, and the seat count must match the specification. Check the returned year and notice when a nearby year is selected. Unmatched trims and low-confidence matches return suggestions without specifications or charges; no similar vehicle returns a no-result error without charging. Conflicting explicit and free-text constraints are rejected.
|
|
514
|
+
|
|
515
|
+
```js
|
|
516
|
+
await client.vehicleModelInfo({ model: "파나메라 gts 4인승 19년식" });
|
|
517
|
+
```
|
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
|
@@ -93,27 +93,6 @@ const job = await client.linkedinJob('https://www.linkedin.com/jobs/view/4001234
|
|
|
93
93
|
|
|
94
94
|
Coupang accepts a product number or a product URL (`/vp/products/{id}`), and Naver accepts a brand store product URL (`brand.naver.com/{store}/products/{id}`). LinkedIn accepts profile (`/in/`), company (`/company/`) and job posting (`/jobs/view/`) URLs.
|
|
95
95
|
|
|
96
|
-
### Collection jobs (lists, comments, search, reviews)
|
|
97
|
-
|
|
98
|
-
Products that collect many items return a `job_id` immediately. Submitting reserves `maxResults` × unit price; when you read the result, only the results actually returned are charged and the rest is refunded. Failed jobs and missing targets are fully refunded, and results are kept for 72 hours. Comment and review authors are public usernames only.
|
|
99
|
-
|
|
100
|
-
```js
|
|
101
|
-
const job = await client.createTiktokSearchJob('camping recipes', { maxResults: 10, idempotencyKey: 'camping-0001' });
|
|
102
|
-
const done = await client.waitForScrapeJob(job.data.job_id); // every 10 s, up to 10 min
|
|
103
|
-
console.log(done.data.status, done.data.charged_point, done.data.items);
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
Result-billed collection jobs are charged per result; from 2026-11-06 a job with at least one result has a base fee (10 points, Instagram comments 50). Jobs with no results or failures are fully refunded.
|
|
107
|
-
|
|
108
|
-
For a Google Maps place, pass the `place_id` from `googleMapsSearch` to get details, the star distribution and top reviews (up to 10). 20 points per place; text is returned in English.
|
|
109
|
-
|
|
110
|
-
```js
|
|
111
|
-
const places = await client.googleMapsSearch('cafes near Gangnam station');
|
|
112
|
-
const placeJob = await client.createGoogleMapsPlaceJob(places.data.items[0].place_id);
|
|
113
|
-
const place = await client.waitForScrapeJob(placeJob.data.job_id);
|
|
114
|
-
console.log(place.data.items[0].rating_distribution, place.data.items[0].top_reviews);
|
|
115
|
-
```
|
|
116
|
-
|
|
117
96
|
## OCR
|
|
118
97
|
|
|
119
98
|
OCR accepts PNG and JPEG files up to 50MB.
|
|
@@ -325,7 +304,7 @@ try {
|
|
|
325
304
|
|
|
326
305
|
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)
|
|
327
306
|
|
|
328
|
-
`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`). `requestCashReceiptDeduction` takes optional `incomeYears` (1-3) and `requestTaxReturnHistory` takes optional `years` (1-10). The remaining products are `requestDrivingLicense` and `requestHealthCheckup`.
|
|
307
|
+
`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`). `requestNpsDeductionCert` takes optional `years` (1-5) and `requestNpsCareerHistory` takes optional `from`/`to` (`YYYY-MM`). `requestCashReceiptDeduction` takes optional `incomeYears` (1-3) and `requestTaxReturnHistory` takes optional `years` (1-10). The remaining products are `requestDrivingLicense` and `requestHealthCheckup`.
|
|
329
308
|
|
|
330
309
|
## Skills
|
|
331
310
|
|
package/docs/guide.ko.md
CHANGED
|
@@ -93,27 +93,6 @@ const job = await client.linkedinJob('https://www.linkedin.com/jobs/view/4001234
|
|
|
93
93
|
|
|
94
94
|
쿠팡은 상품 번호나 상품 주소(`/vp/products/{번호}`)를, 네이버는 브랜드스토어 상품 주소(`brand.naver.com/{스토어}/products/{번호}`)를 받습니다. 링크드인은 프로필(`/in/`)·회사(`/company/`)·채용공고(`/jobs/view/`) 주소를 받습니다.
|
|
95
95
|
|
|
96
|
-
### 수집 작업(목록·댓글·검색·리뷰)
|
|
97
|
-
|
|
98
|
-
여러 건을 모으는 상품은 접수 즉시 `job_id` 를 돌려줍니다. 접수 때 `maxResults` × 단가를 예약하고, 결과를 받을 때 실제 결과 건수만 차감한 뒤 나머지는 돌려드립니다. 실패하거나 대상이 없으면 전액 환불되며 결과는 72시간 보관합니다. 댓글·리뷰 작성자는 공개 사용자명만 제공합니다.
|
|
99
|
-
|
|
100
|
-
```js
|
|
101
|
-
const job = await client.createTiktokSearchJob('캠핑 요리', { maxResults: 10, idempotencyKey: 'camping-0001' });
|
|
102
|
-
const done = await client.waitForScrapeJob(job.data.job_id); // 기본 10초 간격, 최대 10분
|
|
103
|
-
console.log(done.data.status, done.data.charged_point, done.data.items);
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
결과 건수 과금 수집 작업은 결과 1건당 단가로 정산하며, 2026-11-06부터 결과가 1건 이상이면 작업당 기본요금(10P, 인스타그램 댓글 50P)을 최소액으로 받습니다. 결과가 없거나 실패하면 예약한 포인트를 모두 돌려드립니다.
|
|
107
|
-
|
|
108
|
-
구글 지도 장소는 `googleMapsSearch` 결과의 `place_id` 로 상세·별점 분포·대표 리뷰(최대 10건)를 받습니다. 건당 20포인트이고 텍스트는 영어로 제공합니다.
|
|
109
|
-
|
|
110
|
-
```js
|
|
111
|
-
const places = await client.googleMapsSearch('강남역 카페');
|
|
112
|
-
const placeJob = await client.createGoogleMapsPlaceJob(places.data.items[0].place_id);
|
|
113
|
-
const place = await client.waitForScrapeJob(placeJob.data.job_id);
|
|
114
|
-
console.log(place.data.items[0].rating_distribution, place.data.items[0].top_reviews);
|
|
115
|
-
```
|
|
116
|
-
|
|
117
96
|
## OCR
|
|
118
97
|
|
|
119
98
|
PNG와 JPEG를 지원하며 최대 크기는 50MB입니다.
|
|
@@ -328,7 +307,7 @@ try {
|
|
|
328
307
|
|
|
329
308
|
근거: [APICK 개발가이드](https://apick.app/dev_guide/data_health_checkup) · [MCP 3.5.0 상태 계약](https://github.com/lead788/apick-mcp/blob/a803abcb81d07377c85f49bb0b670baf0c17ed04/TOOLS.md)
|
|
330
309
|
|
|
331
|
-
`authProvider`는 `AUTH_PROVIDERS`(13종: kakao, naver, toss, pass, samsung, kb, shinhan, hana, woori, ibk, nh, kakaobank, banksalad) 중 하나입니다. 접수는 정액 과금, 결과는 최초 반환에서만 과금되며 재조회는 무료입니다. `requestEmployment`는 `insuranceYears`(1~3), `requestPersonalIncome`은 `incomeYears`(1~5), `requestNpsJoinHistory`는 `from`/`to`(`YYYY-MM`) 선택 입력을 받습니다. `requestCashReceiptDeduction`은 `incomeYears`(1~3), `requestTaxReturnHistory`는 `years`(1~10) 선택 입력을 받습니다. 나머지 상품은 `requestDrivingLicense`, `requestHealthCheckup`입니다.
|
|
310
|
+
`authProvider`는 `AUTH_PROVIDERS`(13종: kakao, naver, toss, pass, samsung, kb, shinhan, hana, woori, ibk, nh, kakaobank, banksalad) 중 하나입니다. 접수는 정액 과금, 결과는 최초 반환에서만 과금되며 재조회는 무료입니다. `requestEmployment`는 `insuranceYears`(1~3), `requestPersonalIncome`은 `incomeYears`(1~5), `requestNpsJoinHistory`는 `from`/`to`(`YYYY-MM`) 선택 입력을 받습니다. `requestNpsDeductionCert`는 `years`(1~5), `requestNpsCareerHistory`는 `from`/`to`(`YYYY-MM`) 선택 입력을 받습니다. `requestCashReceiptDeduction`은 `incomeYears`(1~3), `requestTaxReturnHistory`는 `years`(1~10) 선택 입력을 받습니다. 나머지 상품은 `requestDrivingLicense`, `requestHealthCheckup`입니다.
|
|
332
311
|
|
|
333
312
|
## Skills
|
|
334
313
|
|
package/package.json
CHANGED
|
@@ -1,71 +1,71 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "apick-api",
|
|
3
|
-
"version": "4.
|
|
4
|
-
"description": "Official zero-dependency Node.js client for APICK data, AI, and image APIs. 에이픽 데이터·AI·이미지 API 공식 Node.js SDK.",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "./src/index.cjs",
|
|
7
|
-
"module": "./src/index.js",
|
|
8
|
-
"types": "./src/index.d.ts",
|
|
9
|
-
"exports": {
|
|
10
|
-
".": {
|
|
11
|
-
"types": "./src/index.d.ts",
|
|
12
|
-
"import": "./src/index.js",
|
|
13
|
-
"require": "./src/index.cjs"
|
|
14
|
-
}
|
|
15
|
-
},
|
|
16
|
-
"files": [
|
|
17
|
-
"src",
|
|
18
|
-
"docs",
|
|
19
|
-
"examples",
|
|
20
|
-
"README.md",
|
|
21
|
-
"CHANGELOG.md",
|
|
22
|
-
"SECURITY.md",
|
|
23
|
-
"LICENSE"
|
|
24
|
-
],
|
|
25
|
-
"sideEffects": false,
|
|
26
|
-
"engines": {
|
|
27
|
-
"node": ">=18"
|
|
28
|
-
},
|
|
29
|
-
"scripts": {
|
|
30
|
-
"test": "node --test && npm run test:types",
|
|
31
|
-
"test:types": "tsc -p tsconfig.json",
|
|
32
|
-
"test:coverage": "node --test --experimental-test-coverage",
|
|
33
|
-
"prepublishOnly": "npm test"
|
|
34
|
-
},
|
|
35
|
-
"devDependencies": {
|
|
36
|
-
"typescript": "^7.0.2"
|
|
37
|
-
},
|
|
38
|
-
"repository": {
|
|
39
|
-
"type": "git",
|
|
40
|
-
"url": "git+https://github.com/lead788/apick-api.git"
|
|
41
|
-
},
|
|
42
|
-
"bugs": {
|
|
43
|
-
"url": "https://github.com/lead788/apick-api/issues"
|
|
44
|
-
},
|
|
45
|
-
"homepage": "https://apick.app/dev_guide",
|
|
46
|
-
"license": "MIT",
|
|
47
|
-
"author": "APICK",
|
|
48
|
-
"publishConfig": {
|
|
49
|
-
"access": "public",
|
|
50
|
-
"provenance": false
|
|
51
|
-
},
|
|
52
|
-
"keywords": [
|
|
53
|
-
"apick",
|
|
54
|
-
"api",
|
|
55
|
-
"sdk",
|
|
56
|
-
"korea",
|
|
57
|
-
"korean-api",
|
|
58
|
-
"business-registry",
|
|
59
|
-
"parcel-tracking",
|
|
60
|
-
"address",
|
|
61
|
-
"ocr",
|
|
62
|
-
"whois",
|
|
63
|
-
"dns",
|
|
64
|
-
"google-search",
|
|
65
|
-
"pdf",
|
|
66
|
-
"excel",
|
|
67
|
-
"tts-jobs",
|
|
68
|
-
"text-summary",
|
|
69
|
-
"image-generation"
|
|
70
|
-
]
|
|
71
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "apick-api",
|
|
3
|
+
"version": "4.8.2",
|
|
4
|
+
"description": "Official zero-dependency Node.js client for APICK data, AI, and image APIs. 에이픽 데이터·AI·이미지 API 공식 Node.js SDK.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./src/index.cjs",
|
|
7
|
+
"module": "./src/index.js",
|
|
8
|
+
"types": "./src/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./src/index.d.ts",
|
|
12
|
+
"import": "./src/index.js",
|
|
13
|
+
"require": "./src/index.cjs"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"src",
|
|
18
|
+
"docs",
|
|
19
|
+
"examples",
|
|
20
|
+
"README.md",
|
|
21
|
+
"CHANGELOG.md",
|
|
22
|
+
"SECURITY.md",
|
|
23
|
+
"LICENSE"
|
|
24
|
+
],
|
|
25
|
+
"sideEffects": false,
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=18"
|
|
28
|
+
},
|
|
29
|
+
"scripts": {
|
|
30
|
+
"test": "node --test && npm run test:types",
|
|
31
|
+
"test:types": "tsc -p tsconfig.json",
|
|
32
|
+
"test:coverage": "node --test --experimental-test-coverage",
|
|
33
|
+
"prepublishOnly": "npm test"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"typescript": "^7.0.2"
|
|
37
|
+
},
|
|
38
|
+
"repository": {
|
|
39
|
+
"type": "git",
|
|
40
|
+
"url": "git+https://github.com/lead788/apick-api.git"
|
|
41
|
+
},
|
|
42
|
+
"bugs": {
|
|
43
|
+
"url": "https://github.com/lead788/apick-api/issues"
|
|
44
|
+
},
|
|
45
|
+
"homepage": "https://apick.app/dev_guide",
|
|
46
|
+
"license": "MIT",
|
|
47
|
+
"author": "APICK",
|
|
48
|
+
"publishConfig": {
|
|
49
|
+
"access": "public",
|
|
50
|
+
"provenance": false
|
|
51
|
+
},
|
|
52
|
+
"keywords": [
|
|
53
|
+
"apick",
|
|
54
|
+
"api",
|
|
55
|
+
"sdk",
|
|
56
|
+
"korea",
|
|
57
|
+
"korean-api",
|
|
58
|
+
"business-registry",
|
|
59
|
+
"parcel-tracking",
|
|
60
|
+
"address",
|
|
61
|
+
"ocr",
|
|
62
|
+
"whois",
|
|
63
|
+
"dns",
|
|
64
|
+
"google-search",
|
|
65
|
+
"pdf",
|
|
66
|
+
"excel",
|
|
67
|
+
"tts-jobs",
|
|
68
|
+
"text-summary",
|
|
69
|
+
"image-generation"
|
|
70
|
+
]
|
|
71
|
+
}
|
package/src/index.cjs
CHANGED
|
@@ -26,6 +26,7 @@ const SERVICE_DEFINITIONS = Object.freeze({
|
|
|
26
26
|
validatePhone: { endpoint: '/rest/check_phone_valid', timeoutMs: 20_000, output: 'json' },
|
|
27
27
|
holidays: { endpoint: '/rest/holiday_info', timeoutMs: 35_000, output: 'json' },
|
|
28
28
|
searchAddress: { endpoint: '/rest/search_juso', timeoutMs: 20_000, output: 'json' },
|
|
29
|
+
vehicleModelInfo: { endpoint: '/rest/vehicle_model_info', timeoutMs: 20_000, output: 'json' },
|
|
29
30
|
ocr: { endpoint: '/rest/ocr', timeoutMs: 35_000, output: 'json' },
|
|
30
31
|
maskResidentNumber: { endpoint: '/rest/hide_rrn', timeoutMs: 35_000, output: 'binary', filename: 'masked.png' },
|
|
31
32
|
maskResidenceCard: { endpoint: '/rest/identity_document_residence_card', timeoutMs: 35_000, output: 'json' },
|
|
@@ -52,7 +53,6 @@ const SERVICE_DEFINITIONS = Object.freeze({
|
|
|
52
53
|
linkedinProfile: { endpoint: '/rest/linkedin_profile', timeoutMs: 110_000, output: 'json' },
|
|
53
54
|
linkedinCompany: { endpoint: '/rest/linkedin_company', timeoutMs: 110_000, output: 'json' },
|
|
54
55
|
linkedinJob: { endpoint: '/rest/linkedin_job', timeoutMs: 110_000, output: 'json' },
|
|
55
|
-
getScrapeJob: { endpoint: '/rest/scrape_jobs', timeoutMs: 35_000, output: 'json' },
|
|
56
56
|
screenshot: { endpoint: '/rest/url_screenshot', timeoutMs: 75_000, output: 'binary', filename: 'screenshot.jpeg' },
|
|
57
57
|
youtubeMetadata: { endpoint: '/rest/youtube_metadata', timeoutMs: 60_000, output: 'json' },
|
|
58
58
|
youtubeThumbnail: { endpoint: '/rest/youtube_thumbnail', timeoutMs: 60_000, output: 'binary', filename: 'thumbnail.jpg' },
|
|
@@ -73,6 +73,8 @@ const SERVICE_DEFINITIONS = Object.freeze({
|
|
|
73
73
|
requestEmployment: { endpoint: '/rest/req_employment', timeoutMs: 35_000, output: 'json' },
|
|
74
74
|
requestPersonalIncome: { endpoint: '/rest/req_personal_income', timeoutMs: 35_000, output: 'json' },
|
|
75
75
|
requestNpsJoinHistory: { endpoint: '/rest/req_nps_join_history', timeoutMs: 35_000, output: 'json' },
|
|
76
|
+
requestNpsDeductionCert: { endpoint: '/rest/req_nps_deduction_cert', timeoutMs: 35_000, output: 'json' },
|
|
77
|
+
requestNpsCareerHistory: { endpoint: '/rest/req_nps_career_history', timeoutMs: 35_000, output: 'json' },
|
|
76
78
|
requestDrivingLicense: { endpoint: '/rest/req_driving_license', timeoutMs: 35_000, output: 'json' },
|
|
77
79
|
requestHealthCheckup: { endpoint: '/rest/req_health_checkup', timeoutMs: 35_000, output: 'json' },
|
|
78
80
|
requestCashReceiptDeduction: { endpoint: '/rest/req_cash_receipt_deduction', timeoutMs: 35_000, output: 'json' },
|
|
@@ -99,12 +101,6 @@ function profileInput(value) {
|
|
|
99
101
|
return /^https?:\/\//i.test(text) ? { url: text } : { username: text.replace(/^@/, '') };
|
|
100
102
|
}
|
|
101
103
|
|
|
102
|
-
// 구글 지도 장소 입력: 주소면 url, 아니면 place_id(googleMapsSearch 결과의 place_id)로 보낸다.
|
|
103
|
-
function placeInput(value) {
|
|
104
|
-
const text = requiredString('placeIdOrUrl', value, 2048);
|
|
105
|
-
return /^https?:\/\//i.test(text) ? { url: text } : { place_id: text };
|
|
106
|
-
}
|
|
107
|
-
|
|
108
104
|
// 아마존 상품 입력: 주소면 url, 10자리 ASIN 이면 asin 으로 보낸다.
|
|
109
105
|
function amazonInput(value) {
|
|
110
106
|
const text = requiredString('urlOrAsin', value, 2048);
|
|
@@ -127,23 +123,6 @@ function linkedinInput(value) {
|
|
|
127
123
|
return { url: requiredString('url', value, 2048) };
|
|
128
124
|
}
|
|
129
125
|
|
|
130
|
-
const SCRAPE_JOB_PRODUCTS = Object.freeze({ instagram_posts: 100, instagram_comments: 15, tiktok_search: 50, tiktok_video: 1, tiktok_comments: 100, amazon_reviews: 100, google_maps_place: 1 });
|
|
131
|
-
|
|
132
|
-
// 수집 작업 공통 옵션: maxResults(상품별 상한), idempotencyKey(응답을 못 받아 다시 보낼 때 같은 접수로 처리).
|
|
133
|
-
function scrapeJobOptions(product, payload, options) {
|
|
134
|
-
const config = options || {};
|
|
135
|
-
if (config.maxResults !== undefined && SCRAPE_JOB_PRODUCTS[product] > 1) {
|
|
136
|
-
const max = Number(config.maxResults);
|
|
137
|
-
if (!Number.isInteger(max) || max < 1 || max > SCRAPE_JOB_PRODUCTS[product]) throw new RangeError(`maxResults must be an integer from 1 to ${SCRAPE_JOB_PRODUCTS[product]}.`);
|
|
138
|
-
payload.max_results = max;
|
|
139
|
-
}
|
|
140
|
-
if (config.idempotencyKey !== undefined) {
|
|
141
|
-
if (typeof config.idempotencyKey !== 'string' || !/^[A-Za-z0-9_.:-]{8,128}$/.test(config.idempotencyKey)) throw new TypeError('idempotencyKey must be 8-128 characters of letters, digits, and . _ : -');
|
|
142
|
-
payload.idempotency_key = config.idempotencyKey;
|
|
143
|
-
}
|
|
144
|
-
return payload;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
126
|
function requiredString(name, value, maxLength) {
|
|
148
127
|
if (typeof value !== 'string' || !value.trim()) {
|
|
149
128
|
throw new TypeError(`${name} must be a non-empty string.`);
|
|
@@ -285,6 +264,10 @@ function optionalSkillText(name, value, maxLength) {
|
|
|
285
264
|
return requiredString(name, String(value), maxLength);
|
|
286
265
|
}
|
|
287
266
|
|
|
267
|
+
function optionalText(name, value, maxLength) {
|
|
268
|
+
return optionalSkillText(name, value, maxLength);
|
|
269
|
+
}
|
|
270
|
+
|
|
288
271
|
function numberOrNull(value) {
|
|
289
272
|
if (value === undefined || value === null || value === '') return null;
|
|
290
273
|
const number = Number(value);
|
|
@@ -584,6 +567,19 @@ class ApickClient {
|
|
|
584
567
|
});
|
|
585
568
|
}
|
|
586
569
|
|
|
570
|
+
// 브랜드·차명·연식·등급으로 제원·사양·등급 후보를 조회한다.
|
|
571
|
+
// 차명(model)을 비우면 브랜드 목록 또는 그 브랜드의 차종 목록을 무료로 돌려준다.
|
|
572
|
+
// 제원 값은 표준 표기로만 내려간다(연료·구동방식·변속기·차체형상·에너지효율등급, 여러 값은 "+" 연결).
|
|
573
|
+
vehicleModelInfo(options) {
|
|
574
|
+
const config = options || {};
|
|
575
|
+
return this._call('vehicleModelInfo', {
|
|
576
|
+
maker: optionalText('maker', config.maker, 60),
|
|
577
|
+
model: optionalText('model', config.model, 60),
|
|
578
|
+
modelYear: optionalText('modelYear', config.modelYear, 60),
|
|
579
|
+
trim: optionalText('trim', config.trim, 60)
|
|
580
|
+
});
|
|
581
|
+
}
|
|
582
|
+
|
|
587
583
|
async ocr(image, options) {
|
|
588
584
|
const upload = await normalizeImage(image, options);
|
|
589
585
|
const form = new FormData();
|
|
@@ -659,7 +655,6 @@ class ApickClient {
|
|
|
659
655
|
googleMapsSearch(keyword) {
|
|
660
656
|
return this._call('googleMapsSearch', { keyword: requiredString('keyword', keyword, 200) });
|
|
661
657
|
}
|
|
662
|
-
|
|
663
658
|
// keyword 로 구글을 검색했을 때 domain 이 1~100위 중 몇 위인지 확인한다.
|
|
664
659
|
googleRankCheck(keyword, domain) {
|
|
665
660
|
return this._call('googleRankCheck', {
|
|
@@ -720,60 +715,6 @@ class ApickClient {
|
|
|
720
715
|
return this._call('linkedinJob', linkedinInput(url));
|
|
721
716
|
}
|
|
722
717
|
|
|
723
|
-
// 수집 작업: 접수 즉시 job_id 를 돌려준다. maxResults × 단가를 예약하고 결과를 받을 때 실제 건수만 차감한다.
|
|
724
|
-
_createScrapeJob(product, payload, options) {
|
|
725
|
-
return this._call('getScrapeJob', scrapeJobOptions(product, payload, options), null, { endpoint: '/rest/' + product + '/jobs', json: true });
|
|
726
|
-
}
|
|
727
|
-
|
|
728
|
-
createInstagramPostsJob(usernameOrUrl, options) {
|
|
729
|
-
return this._createScrapeJob('instagram_posts', profileInput(usernameOrUrl), options);
|
|
730
|
-
}
|
|
731
|
-
|
|
732
|
-
createInstagramCommentsJob(url, options) {
|
|
733
|
-
return this._createScrapeJob('instagram_comments', { url: requiredString('url', url, 2048) }, options);
|
|
734
|
-
}
|
|
735
|
-
|
|
736
|
-
createTiktokSearchJob(keyword, options) {
|
|
737
|
-
return this._createScrapeJob('tiktok_search', { keyword: requiredString('keyword', keyword, 100) }, options);
|
|
738
|
-
}
|
|
739
|
-
|
|
740
|
-
createTiktokVideoJob(url, options) {
|
|
741
|
-
return this._createScrapeJob('tiktok_video', { url: requiredString('url', url, 2048) }, options);
|
|
742
|
-
}
|
|
743
|
-
|
|
744
|
-
createTiktokCommentsJob(url, options) {
|
|
745
|
-
return this._createScrapeJob('tiktok_comments', { url: requiredString('url', url, 2048) }, options);
|
|
746
|
-
}
|
|
747
|
-
|
|
748
|
-
createAmazonReviewsJob(urlOrAsin, options) {
|
|
749
|
-
return this._createScrapeJob('amazon_reviews', amazonInput(urlOrAsin), options);
|
|
750
|
-
}
|
|
751
|
-
|
|
752
|
-
// 구글 지도 장소 상세·대표 리뷰(건당 고정가). 텍스트는 영어로 온다.
|
|
753
|
-
createGoogleMapsPlaceJob(placeIdOrUrl, options) {
|
|
754
|
-
return this._createScrapeJob('google_maps_place', placeInput(placeIdOrUrl), options);
|
|
755
|
-
}
|
|
756
|
-
|
|
757
|
-
// 상태·결과 조회(무료). 끝난 작업은 실제 결과 건수로 정산돼 있다.
|
|
758
|
-
getScrapeJob(jobId) {
|
|
759
|
-
if (typeof jobId !== 'string' || !/^[a-f0-9]{32}$/.test(jobId)) throw new TypeError('jobId must be a 32-character job ID.');
|
|
760
|
-
return this._call('getScrapeJob', null, null, { endpoint: '/rest/scrape_jobs/' + jobId, method: 'GET', timeoutMs: 70_000 });
|
|
761
|
-
}
|
|
762
|
-
|
|
763
|
-
// completed 또는 failed 가 될 때까지 조회한다. 기본 10초 간격, 최대 10분.
|
|
764
|
-
async waitForScrapeJob(jobId, options) {
|
|
765
|
-
const config = options || {};
|
|
766
|
-
const intervalMs = Math.max(3_000, positiveInteger('intervalMs', config.intervalMs, 10_000));
|
|
767
|
-
const deadline = Date.now() + positiveInteger('timeoutMs', config.timeoutMs, 600_000);
|
|
768
|
-
for (;;) {
|
|
769
|
-
const result = await this.getScrapeJob(jobId);
|
|
770
|
-
const status = result && result.data && result.data.status;
|
|
771
|
-
if (status === 'completed' || status === 'failed') return result;
|
|
772
|
-
if (Date.now() + intervalMs > deadline) throw new ApickApiError('Scrape job did not finish in time.', { code: 'APICK_TIMEOUT' });
|
|
773
|
-
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
774
|
-
}
|
|
775
|
-
}
|
|
776
|
-
|
|
777
718
|
screenshot(url) {
|
|
778
719
|
return this._call('screenshot', { url: normalizeUrl(url) });
|
|
779
720
|
}
|
|
@@ -1121,6 +1062,31 @@ class ApickClient {
|
|
|
1121
1062
|
return this._call('requestNpsJoinHistory', { transactionId: normalizeTransactionId(transactionId) }, null, { endpoint: '/rest/get_nps_join_history' });
|
|
1122
1063
|
}
|
|
1123
1064
|
|
|
1065
|
+
requestNpsDeductionCert(input) {
|
|
1066
|
+
const payload = dataRequestInput(input);
|
|
1067
|
+
const years = optionalRangeInteger('years', (input || {}).years, 1, 5);
|
|
1068
|
+
if (years !== undefined) payload.years = years;
|
|
1069
|
+
return this._call('requestNpsDeductionCert', payload);
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
getNpsDeductionCert(transactionId) {
|
|
1073
|
+
return this._call('requestNpsDeductionCert', { transactionId: normalizeTransactionId(transactionId) }, null, { endpoint: '/rest/get_nps_deduction_cert' });
|
|
1074
|
+
}
|
|
1075
|
+
|
|
1076
|
+
requestNpsCareerHistory(input) {
|
|
1077
|
+
const payload = dataRequestInput(input);
|
|
1078
|
+
const config = input || {};
|
|
1079
|
+
const from = normalizeYearMonth('from', config.from);
|
|
1080
|
+
const to = normalizeYearMonth('to', config.to);
|
|
1081
|
+
if (from !== undefined) payload.from = from;
|
|
1082
|
+
if (to !== undefined) payload.to = to;
|
|
1083
|
+
return this._call('requestNpsCareerHistory', payload);
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
getNpsCareerHistory(transactionId) {
|
|
1087
|
+
return this._call('requestNpsCareerHistory', { transactionId: normalizeTransactionId(transactionId) }, null, { endpoint: '/rest/get_nps_career_history' });
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1124
1090
|
requestDrivingLicense(input) {
|
|
1125
1091
|
return this._call('requestDrivingLicense', dataRequestInput(input));
|
|
1126
1092
|
}
|
package/src/index.d.ts
CHANGED
|
@@ -269,104 +269,6 @@ export interface LinkedinJob {
|
|
|
269
269
|
readonly url: string;
|
|
270
270
|
}
|
|
271
271
|
|
|
272
|
-
export interface TiktokVideo {
|
|
273
|
-
readonly video_id: string;
|
|
274
|
-
readonly url: string;
|
|
275
|
-
readonly username: string;
|
|
276
|
-
readonly description: string;
|
|
277
|
-
readonly posted_at: string;
|
|
278
|
-
readonly views: number | null;
|
|
279
|
-
readonly likes: number | null;
|
|
280
|
-
readonly comments: number | null;
|
|
281
|
-
readonly shares: number | null;
|
|
282
|
-
readonly saves: number | null;
|
|
283
|
-
readonly duration_sec: number | null;
|
|
284
|
-
readonly hashtags: readonly string[];
|
|
285
|
-
readonly region: string;
|
|
286
|
-
readonly cover_image_url: string;
|
|
287
|
-
readonly author: { readonly followers: number | null; readonly is_verified: boolean };
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
/** 댓글 작성자는 공개 사용자명만 제공한다. */
|
|
291
|
-
export interface SocialComment {
|
|
292
|
-
readonly comment_id: string;
|
|
293
|
-
readonly username: string;
|
|
294
|
-
readonly text: string;
|
|
295
|
-
readonly posted_at: string;
|
|
296
|
-
readonly likes: number | null;
|
|
297
|
-
readonly replies: number | null;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
export interface AmazonReview {
|
|
301
|
-
readonly review_id: string;
|
|
302
|
-
readonly rating: number | null;
|
|
303
|
-
readonly title: string;
|
|
304
|
-
readonly text: string;
|
|
305
|
-
readonly author: string;
|
|
306
|
-
readonly posted_at: string;
|
|
307
|
-
readonly country: string;
|
|
308
|
-
readonly is_verified_purchase: boolean;
|
|
309
|
-
readonly helpful_count: number | null;
|
|
310
|
-
readonly variant: string;
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
export interface GoogleMapsPlace {
|
|
314
|
-
readonly name: string;
|
|
315
|
-
readonly category: string;
|
|
316
|
-
readonly categories: readonly string[];
|
|
317
|
-
readonly address: string;
|
|
318
|
-
readonly country_code: string;
|
|
319
|
-
readonly phone: string;
|
|
320
|
-
readonly website: string;
|
|
321
|
-
readonly description: string;
|
|
322
|
-
readonly rating: number | null;
|
|
323
|
-
readonly reviews_count: number | null;
|
|
324
|
-
/** 별점별 리뷰 수. */
|
|
325
|
-
readonly rating_distribution: Readonly<Record<"1" | "2" | "3" | "4" | "5", number | null>>;
|
|
326
|
-
/** 대표 리뷰(최대 10건). 작성자는 공개 표시 이름만. */
|
|
327
|
-
readonly top_reviews: readonly { readonly reviewer_name: string; readonly rating: number | null; readonly posted_at: string; readonly text: string }[];
|
|
328
|
-
readonly open_hours: Readonly<Record<string, string>>;
|
|
329
|
-
/** day: 1=월 … 7=일 */
|
|
330
|
-
readonly popular_times: readonly { readonly day: number | null; readonly hours: readonly { readonly hour: string; readonly busy_percent: number | null }[] }[];
|
|
331
|
-
readonly similar_places: readonly { readonly name: string; readonly category: string; readonly rating: number | null; readonly reviews_count: number | null }[];
|
|
332
|
-
readonly photo_urls: readonly string[];
|
|
333
|
-
readonly main_image_url: string;
|
|
334
|
-
readonly is_claimed: boolean;
|
|
335
|
-
readonly permanently_closed: boolean;
|
|
336
|
-
readonly temporarily_closed: boolean;
|
|
337
|
-
readonly latitude: number | null;
|
|
338
|
-
readonly longitude: number | null;
|
|
339
|
-
readonly place_id: string;
|
|
340
|
-
readonly map_url: string;
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
export type ScrapeJobProduct = "instagram_posts" | "instagram_comments" | "tiktok_search" | "tiktok_video" | "tiktok_comments" | "amazon_reviews" | "google_maps_place";
|
|
344
|
-
|
|
345
|
-
export interface ScrapeJobOptions {
|
|
346
|
-
/** 최대 결과 수. 이 수 × 단가를 예약하고 실제 결과 건수만 차감한다(instagram_comments 15, tiktok_search 50, 그 밖 100). */
|
|
347
|
-
readonly maxResults?: number;
|
|
348
|
-
/** 응답을 못 받아 다시 보낼 때 같은 접수로 처리할 키(8~128자). */
|
|
349
|
-
readonly idempotencyKey?: string;
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
export interface ScrapeJob<T = unknown> {
|
|
353
|
-
readonly job_id: string;
|
|
354
|
-
readonly product: ScrapeJobProduct;
|
|
355
|
-
readonly status: "waiting" | "processing" | "completed" | "failed";
|
|
356
|
-
readonly max_results: number;
|
|
357
|
-
readonly unit_point: number;
|
|
358
|
-
readonly reserved_point: number;
|
|
359
|
-
readonly charged_point: number;
|
|
360
|
-
readonly result_count: number;
|
|
361
|
-
readonly created_at: string;
|
|
362
|
-
readonly completed_at: string | null;
|
|
363
|
-
/** 결과 보관 기한(완료 후 72시간). */
|
|
364
|
-
readonly result_expires_at?: string;
|
|
365
|
-
readonly result_expired?: boolean;
|
|
366
|
-
readonly items?: readonly T[];
|
|
367
|
-
readonly error?: { readonly code: string; readonly message: string };
|
|
368
|
-
}
|
|
369
|
-
|
|
370
272
|
export interface InstagramProfile {
|
|
371
273
|
readonly username: string;
|
|
372
274
|
readonly full_name: string;
|
|
@@ -469,6 +371,8 @@ export interface DataRequestInput {
|
|
|
469
371
|
export interface RequestEmploymentInput extends DataRequestInput { insuranceYears?: number; }
|
|
470
372
|
export interface RequestPersonalIncomeInput extends DataRequestInput { incomeYears?: number; }
|
|
471
373
|
export interface RequestNpsJoinHistoryInput extends DataRequestInput { from?: string; to?: string; }
|
|
374
|
+
export interface RequestNpsDeductionCertInput extends DataRequestInput { years?: number; }
|
|
375
|
+
export interface RequestNpsCareerHistoryInput extends DataRequestInput { from?: string; to?: string; }
|
|
472
376
|
export interface RequestDrivingLicenseInput extends DataRequestInput {}
|
|
473
377
|
export interface RequestHealthCheckupInput extends DataRequestInput {}
|
|
474
378
|
export interface RequestCashReceiptDeductionInput extends DataRequestInput { incomeYears?: number; }
|
|
@@ -552,6 +456,33 @@ export interface NpsJoinHistoryInfo {
|
|
|
552
456
|
}
|
|
553
457
|
export interface NpsJoinHistoryResultPayload { npsJoinHistory: NpsJoinHistoryInfo; }
|
|
554
458
|
|
|
459
|
+
export interface NpsDeductionCertYearEntry {
|
|
460
|
+
발급연도: string; 사업장가입자고지금액: number; 지역가입자등납부금액: number;
|
|
461
|
+
사업장가입자소급금액: number; 추납보험료납부금액: number; 실업크레딧납부금액: number; 총합계: number;
|
|
462
|
+
}
|
|
463
|
+
export interface NpsDeductionCertInfo {
|
|
464
|
+
조회기간: { 시작: string; 끝: string };
|
|
465
|
+
신청인: string;
|
|
466
|
+
생년월일: string;
|
|
467
|
+
연도별내역: NpsDeductionCertYearEntry[];
|
|
468
|
+
}
|
|
469
|
+
export interface NpsDeductionCertResultPayload { npsDeductionCert: NpsDeductionCertInfo; }
|
|
470
|
+
|
|
471
|
+
export interface NpsCareerHistoryEntry {
|
|
472
|
+
사업장: string; 시작: string; 종료: string;
|
|
473
|
+
기준소득월액: number; 납부개월: number; 미납개월: number; 납부금액: number;
|
|
474
|
+
}
|
|
475
|
+
export interface NpsCareerHistoryOtherEntry {
|
|
476
|
+
시작: string; 종료: string; 가입자구분: string; 납부개월: number; 납부금액: number;
|
|
477
|
+
}
|
|
478
|
+
export interface NpsCareerHistoryInfo {
|
|
479
|
+
조회기간: { 시작: string; 끝: string };
|
|
480
|
+
합계: { 사업장수: number; 경력건수: number; 사업장납부개월: number; 사업장납부금액: number; 사업장외납부개월: number };
|
|
481
|
+
경력: NpsCareerHistoryEntry[];
|
|
482
|
+
사업장외가입: NpsCareerHistoryOtherEntry[];
|
|
483
|
+
}
|
|
484
|
+
export interface NpsCareerHistoryResultPayload { npsCareerHistory: NpsCareerHistoryInfo; }
|
|
485
|
+
|
|
555
486
|
export interface DrivingLicenseAcquisition {
|
|
556
487
|
면허종류코드: string; 발급일자: string; 합격일자: string; 발급지역: string; 발급일련번호: string;
|
|
557
488
|
학원명: string; 졸업일자: string; 공고시험장: string; 등록일자: string; 면허조건: string;
|
|
@@ -709,12 +640,21 @@ export class ApickBinaryResult {
|
|
|
709
640
|
}
|
|
710
641
|
|
|
711
642
|
export const DEFAULT_BASE_URL: 'https://apick.app';
|
|
712
|
-
|
|
713
643
|
export const SERVICES: Readonly<Record<string, Readonly<{
|
|
714
644
|
endpoint: string;
|
|
715
645
|
output: 'json' | 'binary';
|
|
716
646
|
}>>>;
|
|
717
647
|
|
|
648
|
+
/** Brand, model name, model year and trim — all optional. With no `model` the call returns the brand/model list and is free. */
|
|
649
|
+
export interface VehicleModelInfoOptions {
|
|
650
|
+
maker?: string;
|
|
651
|
+
/** 차명과 등급·연식·좌석을 함께 입력할 수 있습니다. Free text, e.g. PANAMERA GTS 19년. */
|
|
652
|
+
model?: string;
|
|
653
|
+
/** 2자리 또는 4자리 연식. Two or four digits; must agree with the year in model. */
|
|
654
|
+
modelYear?: string;
|
|
655
|
+
trim?: string;
|
|
656
|
+
}
|
|
657
|
+
|
|
718
658
|
export class ApickClient {
|
|
719
659
|
createVideoJob(model: VideoModel, prompt: string, options?: VideoJobOptions): Promise<ApickResult<VideoJobData>>;
|
|
720
660
|
getVideoJob(model: VideoModel, jobId: string): Promise<ApickResult<VideoJobData>>;
|
|
@@ -728,6 +668,8 @@ export class ApickClient {
|
|
|
728
668
|
validatePhone(number: string): Promise<ApickResult>;
|
|
729
669
|
holidays(year: number | string, month: number | string): Promise<ApickResult>;
|
|
730
670
|
searchAddress(query: string, options?: { page?: number }): Promise<ApickResult>;
|
|
671
|
+
/** Look up Korean-market vehicle specifications. Values use fixed standard notation (fuel, drive type, transmission, body type, efficiency grade; multiple values joined with `+`). */
|
|
672
|
+
vehicleModelInfo(options?: VehicleModelInfoOptions): Promise<ApickResult>;
|
|
731
673
|
ocr(image: string | BinaryInput | ArrayBuffer | ArrayBufferView, options?: OcrOptions): Promise<ApickResult>;
|
|
732
674
|
maskResidentNumber(image: string | BinaryInput | ArrayBuffer | ArrayBufferView, options: MaskResidentNumberOptions): Promise<ApickBinaryResult>;
|
|
733
675
|
maskResidenceCard(image: string | BinaryInput | ArrayBuffer | ArrayBufferView, options?: OcrOptions): Promise<ApickResult>;
|
|
@@ -754,15 +696,6 @@ export class ApickClient {
|
|
|
754
696
|
linkedinProfile(url: string): Promise<ApickResult<LinkedinProfile>>;
|
|
755
697
|
linkedinCompany(url: string): Promise<ApickResult<LinkedinCompany>>;
|
|
756
698
|
linkedinJob(url: string): Promise<ApickResult<LinkedinJob>>;
|
|
757
|
-
createInstagramPostsJob(usernameOrUrl: string, options?: ScrapeJobOptions): Promise<ApickResult<ScrapeJob<InstagramPost>>>;
|
|
758
|
-
createInstagramCommentsJob(url: string, options?: ScrapeJobOptions): Promise<ApickResult<ScrapeJob<SocialComment>>>;
|
|
759
|
-
createTiktokSearchJob(keyword: string, options?: ScrapeJobOptions): Promise<ApickResult<ScrapeJob<TiktokVideo>>>;
|
|
760
|
-
createTiktokVideoJob(url: string, options?: Pick<ScrapeJobOptions, "idempotencyKey">): Promise<ApickResult<ScrapeJob<TiktokVideo>>>;
|
|
761
|
-
createTiktokCommentsJob(url: string, options?: ScrapeJobOptions): Promise<ApickResult<ScrapeJob<SocialComment>>>;
|
|
762
|
-
createAmazonReviewsJob(urlOrAsin: string, options?: ScrapeJobOptions): Promise<ApickResult<ScrapeJob<AmazonReview>>>;
|
|
763
|
-
createGoogleMapsPlaceJob(placeIdOrUrl: string, options?: Pick<ScrapeJobOptions, "idempotencyKey">): Promise<ApickResult<ScrapeJob<GoogleMapsPlace>>>;
|
|
764
|
-
getScrapeJob<T = unknown>(jobId: string): Promise<ApickResult<ScrapeJob<T>>>;
|
|
765
|
-
waitForScrapeJob<T = unknown>(jobId: string, options?: { intervalMs?: number; timeoutMs?: number }): Promise<ApickResult<ScrapeJob<T>>>;
|
|
766
699
|
screenshot(url: string): Promise<ApickBinaryResult>;
|
|
767
700
|
youtubeMetadata(url: string): Promise<ApickResult<YoutubeMetadata>>;
|
|
768
701
|
youtubeThumbnail(url: string): Promise<ApickBinaryResult>;
|
|
@@ -807,6 +740,10 @@ export class ApickClient {
|
|
|
807
740
|
getPersonalIncome(transactionId: string): Promise<ApickResult<DataRequestResult<PersonalIncomeResultPayload>>>;
|
|
808
741
|
requestNpsJoinHistory(input: RequestNpsJoinHistoryInput): Promise<ApickResult<DataRequestAcceptedData>>;
|
|
809
742
|
getNpsJoinHistory(transactionId: string): Promise<ApickResult<DataRequestResult<NpsJoinHistoryResultPayload>>>;
|
|
743
|
+
requestNpsDeductionCert(input: RequestNpsDeductionCertInput): Promise<ApickResult<DataRequestAcceptedData>>;
|
|
744
|
+
getNpsDeductionCert(transactionId: string): Promise<ApickResult<DataRequestResult<NpsDeductionCertResultPayload>>>;
|
|
745
|
+
requestNpsCareerHistory(input: RequestNpsCareerHistoryInput): Promise<ApickResult<DataRequestAcceptedData>>;
|
|
746
|
+
getNpsCareerHistory(transactionId: string): Promise<ApickResult<DataRequestResult<NpsCareerHistoryResultPayload>>>;
|
|
810
747
|
requestDrivingLicense(input: RequestDrivingLicenseInput): Promise<ApickResult<DataRequestAcceptedData>>;
|
|
811
748
|
getDrivingLicense(transactionId: string): Promise<ApickResult<DataRequestResult<DrivingLicenseResultPayload>>>;
|
|
812
749
|
requestHealthCheckup(input: RequestHealthCheckupInput): Promise<ApickResult<DataRequestAcceptedData>>;
|