본문으로 건너뛰기

비즈니스 데이터 업로드

Kaleidr는 조직 자체 데이터 — property, listing, room, rate, 운영 시간, document — 와 세계에 대한 기본 지식을 함께 사용하여 질문에 답할 수 있습니다.

아래의 모든 결정에 영향을 주기 때문에 무엇보다 먼저 명확히 할 가치가 있는 사항이 두 가지 있습니다.

데이터는 해당 조직에만 다시 제공됩니다. Application logic이 아니라 database level에서 격리되며 consumer Kaleidr Map의 답변에는 절대 사용되지 않습니다. 자체 B2B surface에서만 사용할 수 있습니다.

언어 모델이 데이터를 직접 작성하지 않습니다. 모델은 export의 header와 일부 sample row를 읽고 column mapping을 제안합니다. 이후 deterministic code가 그 mapping을 모든 row에 적용합니다. 잘못된 mapping은 form에서 수정하면 됩니다. 모델이 500개 row를 전사하게 만들면 나중에 자신감 있는 timestamp와 함께 인용될 수 있는 price를 만들어낼 기회가 500번 생기며, 만들어진 price는 실제 price와 구분할 수 없습니다.

이용 가능 여부

Vendor data upload는 Enterprise-tier 기능입니다. upload UI와 API 모두 VENDOR_UPLOAD_TIERS = {"enterprise"}를 확인하며, Pro-tier owner 또는 admin은 어떤 upload call에서도 **403 vendor_data_requires_enterprise**를 받습니다.

vendor-data UI는 현재 production에서 비활성화되어 있습니다(vendorDataEnabled config flag). Enterprise를 사용 중이고 조직에 활성화가 필요하다면 Kaleidr support에 문의하세요.

또한 Enterprise owner 또는 admin role이 필요합니다 — 이는 project별 데이터가 아니라 organization-level data입니다.

두 가지 방법

Upload page. kaleidr.com에 로그인하고 account area의 Your Data를 여세요(nav path /vendor-data, Billing 및 API keys 옆). API와 동일한 네 단계 — file 선택, 제안된 mapping 검토, 이해된 내용 preview, publish — 를 진행합니다. spreadsheet에는 이 방법이 적합합니다.

API는 아래에 설명되어 있습니다. 데이터가 이미 push 가능한 system에 존재하거나 upload를 schedule하려는 경우 사용하세요.

인증

모든 call은 Cognito access token을 bearer로 사용하며, 현재 session이 이미 보유한 것과 동일합니다:

Authorization: Bearer <access token>

platform API key가 아닙니다. Platform key는 integration을 식별하지만 data upload는 organization administration 작업이므로 role을 가진 person으로 인증됩니다. 아래 모든 path는 https://api.kaleidr.com 아래에 있습니다.

Upload 구조

하나의 upload는 하나의 ingest(job)와 하나의 release(versioned result)를 생성합니다. release는 publish되기 전까지 draft이며, publish 시 이전 release가 atomically supersede됩니다 — reader가 반만 적용된 update를 보는 일도 없고 organization에 data가 없는 시간도 없습니다.

1. Mapping 제안

file 앞부분 — header row와 몇 개의 data row만 보내고 전체 export는 보내지 마세요.

MethodPathBodyReturns
POST/inference-api/vendor/mapping/propose{ csv_head }{ mapping_spec, columns, sample_result, notes, errors[] }

csv_head는 16 KB로 제한되며 sample은 server-side에서 잘립니다 — 더 큰 file을 보내도 model이 볼 수 있는 범위는 늘어나지 않습니다.

sample_result를 확인해야 합니다. 제안된 mapping은 표시되기 전에 자체 sample row에 대해 dry-run되며 sample_result는 section별로 무엇을 produced했는지 보여줍니다. 그럴듯해 보이지만 아무것도 생성하지 않는 mapping은 그렇지 않으면 upload 후에야 발견할 수 있습니다.

제안을 적용할 수 없어도 errors가 채워진 200을 받으며 5xx가 아닙니다. mapping은 편집 가능하며 column 하나를 고치는 것이 전체 상호작용입니다. errors는 한 번에 알 수 있는 모든 것을 반환하므로 missing required field와 sheet에 존재하지 않는 column name이 round trip마다 하나씩이 아니라 동시에 도착합니다.

upload 전에 확인하는 항목: 모든 row에 필요한 field가 누락된 section (stay_date, price_amount, units_available, place의 name 또는 timezone), 실제 IANA zone이 아닌 {"const": …} timezone, 세 글자가 아닌 currency const, const container가 아닌 object rule. 그렇지 않으면 각각 upload 후 row마다 한 번씩 실패합니다.

사용자당 시간당 30 proposals로 제한됩니다.

2. Preview stage

MethodPathBodyReturns
POST/shared-api/vendor-data/ingests{ filename, artifact, source, mapping_spec?, preview?, org_id? }{ ingest_id, release_id, status, status_url, dispatched }
  • filename.json 또는 .csv로 끝나야 합니다.
  • artifact는 raw file text입니다.
  • sourcecsv, json 또는 manual입니다.
  • mapping_spec은 step 1의 반환값이며 필요하면 편집할 수 있습니다. 이미 normalized된 JSON bundle 또는 places-only CSV를 보내는 경우 생략하세요.
  • preview: truepublish하지 않고 stage합니다 — 첫 upload와 mapping 변경 시 강력히 권장됩니다.
  • org_id는 선택 사항이며 기본값은 관리 중인 organization입니다.

이 call에는 Idempotency-Key가 필요합니다(8–128자). scope는 organization별입니다. 같은 key로 retry하면 두 번째 ingest를 만들지 않고 기존 ingest를 반환합니다. mapping 편집 후 의도적으로 다시 stage하는 경우에는 새로운 key를 사용하세요 — 실제로 다른 request이며 file 기반 key를 사용하면 이전 mapping으로 만들어진 ingest가 반환됩니다.

3. 상태 확인

MethodPathReturns
GET/shared-api/vendor-data/ingests/{ingest_id}{ status, attempts, row_counts, error_report, created_at, started_at, finished_at }

statuspendingrunningsucceeded 또는 failed로 변합니다. 성공하면 row_counts에 이해한 내용 — "47 places, 312 rates" — 이 들어가고 error_report에는 읽지 못한 row와 각각의 이유가 들어갑니다.

4. Publish

MethodPathReturns
POST/shared-api/vendor-data/ingests/{ingest_id}/publish{ ingest_id, release_id, status, status_url, dispatched }

preview: true로 stage되어 성공한 ingest에만 사용됩니다.

Publish는 flag를 변경하는 대신 job을 다시 실행합니다. 동일한 artifact를 다시 읽고 동일한 mapping을 재적용하므로 count와 identifier는 구조상 일치합니다 — 하지만 geocoding은 live call이므로 provider가 preview 이후 coordinate를 수정했다면 달라질 수 있습니다.

여기서는 Idempotency-Key를 보내지 마세요. 이 endpoint는 이를 받지 않으며 필요하지도 않습니다. 동일 ingest를 두 번 publish할 수 없습니다. 첫 request가 사용자 측에서는 timeout됐지만 서버에서는 성공했다면 retry는 409ingest_is_not_a_preview, 또는 두 시도가 정확히 겹치면 publish_already_in_progress 를 반환합니다. 둘 다 publish가 이미 진행 중이라는 뜻입니다. retry할 error가 아니라 success로 처리하세요.

Release 목록

MethodPathReturns
GET/shared-api/vendor-data/releases[{ id, status, published_at, superseded_at, created_at }]

?status=로 선택적으로 filter할 수 있습니다. organization당 정확히 하나의 release만 동시에 published 상태입니다.

Preview 만료

승인하지 않은 preview는 staging이 끝난 시점부터 14일 후 retire됩니다. delete되지 않고 superseded로 표시되므로 upload history에는 남지만 더 이상 publish할 수 없으며 다시 upload해야 합니다. 만료된 preview를 publish하면 409 no_previewed_release_to_publish를 반환합니다.

Field 참고 사항

timezone은 모든 place에 필수이며 중요합니다. Rate 및 availability 답변은 property의 local calendar로 계산됩니다 — Sydney hotel의 "tonight"은 server의 "tonight"과 다른 날짜일 수 있습니다. export에 실제로 timezone column이 없다면 constant를 명시적으로 map하세요:

{ "timezone": { "const": "UTC" } }

default에 맡기지 말고 의도적으로 작성하세요. UTC 시간으로 운영하는 property에는 UTC가 올바르지만, 그렇지 않은 property에는 미묘하게 잘못된 값이며 이 오류는 stay window의 경계에서만 나타납니다.

timezone을 생략하거나 존재하지 않는 zone을 지정하면 upload 후가 아니라 propose step에서 거부됩니다.

coordinates가 있다면 제공하세요. lat/lng가 있는 place는 그대로 사용됩니다 — 사용자의 coordinates가 authoritative하며 다시 계산하지 않습니다. address만 있는 place는 geocode되고 confidence가 낮은 match는 추측하지 않고 거부합니다. property가 잘못된 지도 위치에 표시되는 것이 unresolvable로 보고되는 것보다 나쁘기 때문입니다. coordinate가 절반만 있으면 gap이 아니라 typo로 처리됩니다.

재업로드는 비용이 낮고 안전합니다. identifier는 mapping에서 identifying으로 지정한 column을 기반으로 생성되므로 동일한 export는 동일한 reference를 만듭니다 — 재업로드는 duplicate가 아니라 update가 됩니다.

오류

StatusMeaning
401Access token 누락 또는 expired
403 vendor_data_requires_enterpriseorg가 Enterprise tier가 아님
403organization에 data upload가 활성화되지 않음
404organization에 해당 ingest가 없음
409ingest가 이 call을 허용하는 state가 아님 — 위 publish note 참조
413file이 upload limit 초과
422file 또는 mapping을 읽을 수 없음. body에 row와 reason이 표시됨
429Rate limited — 잠시 후 retry

향후 제공 예정

현재 API는 complete bundle을 받습니다. mapping이 저장되고 재사용 가능한 object가 되면 자체 export + mapping id도 받을 수 있어 integration이 기존에 생성하던 file을 먼저 reshaping하지 않고 그대로 보낼 수 있게 됩니다. 이후 natural key별 upsert/delete와 since cursor를 제공하는 delta API가 같은 route를 따릅니다.