사업장 추가
게시 플랫폼에 필요한 필드로 사업장을 생성하고, 유효성 검사 오류를 처리하고, 제출 대기열에 추가되었는지 확인합니다.
등록 정보, 리뷰, 게시물, 분석 데이터는 모두 사업장 ID를 기준으로 연결됩니다. POST /api/v4/locations는 사업장을 생성하고 요금제에 포함된 게시 플랫폼마다 등록 정보 1개를 대기열에 추가합니다.
1. 필수 필드 준비
필수 필드는 10개입니다. 서비스 제공 지역 기반 사업체도 전체 주소를 전송합니다. hideAddress: true를 사용하면 ListingsAPI는 주소를 저장하지만 게시 플랫폼에 제출하지 않습니다. 게시 플랫폼은 생략된 선택 필드를 빈칸으로 표시하므로, 보유한 정보를 모두 전송합니다.
2. 사업장 생성
POST /api/v4/locations는 JSON 요청 본문의 input 객체로 필드를 받습니다. Python SDK 메서드 locations.add()는 같은 필드를 키워드 인수로 받으며, 요청을 보내기 전에 필수 필드의 유효성을 검사합니다. Node SDK 메서드 createLocation()은 camelCase 객체를 직접 받습니다.
curl -X POST https://listingsapi.com/api/v4/locations \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{ "input": { "name": "Acme Kitchen", "storeId": "ACME-NYC-001", "description": "Acme Kitchen is a family-owned neighborhood restaurant in downtown New York serving wood-fired pizza, hand-rolled pasta, and a short seasonal menu built around produce from nearby farms. Open for lunch and dinner seven days a week, with takeout and delivery available.", "street": "123 Jump Street", "city": "New York", "stateIso": "NY", "postalCode": "10013", "countryIso": "US", "phone": "6443859313", "bizUrl": "https://acmekitchen.example.com", "subCategoryId": 1432, "businessHours": [ { "day": "MONDAY", "type": "OPEN", "slots": [{ "start": "11:00am", "end": "10:00pm" }] }, { "day": "TUESDAY", "type": "OPEN", "slots": [{ "start": "11:00am", "end": "10:00pm" }] }, { "day": "WEDNESDAY", "type": "OPEN", "slots": [{ "start": "11:00am", "end": "10:00pm" }] }, { "day": "THURSDAY", "type": "OPEN", "slots": [{ "start": "11:00am", "end": "10:00pm" }] }, { "day": "FRIDAY", "type": "OPEN", "slots": [{ "start": "11:00am", "end": "11:00pm" }] }, { "day": "SATURDAY", "type": "OPEN", "slots": [{ "start": "12:00pm", "end": "11:00pm" }] }, { "day": "SUNDAY", "type": "CLOSED", "slots": [] } ] }}'3. 응답 확인
생성에 성공하면 success: true와 함께 data.createLocation.location에 새 사업장을 반환합니다. 두 식별자를 모두 보관합니다. id는 이후의 모든 쓰기 작업에 사용하는 base64 값이며, databaseId는 대시보드와 웹훅 페이로드에 표시되는 숫자 값입니다.
{ "data": { "createLocation": { "success": true, "errors": null, "location": { "id": "TG9jYXRpb246MTgwMDI5MA==", "databaseId": 1800290, "storeId": "ACME-NYC-001", "name": "Acme Kitchen", "city": "New York", "stateIso": "NY", "countryIso": "US", "status": "PENDING" } } }}사업장의 유효성을 검사하고 대기열에 추가하는 동안 status는 PENDING입니다. 추가 API 호출 없이 다음 상태로 진행됩니다.
4. 유효성 검사 오류 처리
생성은 2가지 지점에서 실패할 수 있습니다. 요청 형식이 잘못되었거나 키가 유효하지 않으면 최상위 errors 배열이 포함된 4xx를 반환합니다. 요청 형식은 올바르지만 API가 거부하는 필드가 있으면 success: false와 data.createLocation.errors 내부의 문제 정보가 포함된 200을 반환하므로, 모든 쓰기 작업에서 상태 코드뿐 아니라 응답 본문도 확인합니다.
{ "data": { "createLocation": { "success": false, "errors": [ { "code": "SY10005", "message": "SY10005: description must be at least 200 characters", "path": ["input", "description"] } ], "location": null } }}두 SDK 모두 실패 시 예외를 발생시킵니다. Python의 locations.add()는 필수 필드를 로컬에서 검사하고 요청을 보내기 전에 ValidationError를 발생시킵니다. Node의 createLocation()은 API가 입력을 거부하면 ValidationError를 발생시키므로, 위 예제에서는 성공 여부 플래그를 검사하지 않습니다.
가장 자주 접하는 코드는 다음과 같습니다.
5. 제출이 시작되었는지 확인
사업장을 생성하면 이용 중인 요금제의 게시 플랫폼마다 등록 정보 1개가 대기열에 추가됩니다. 각 등록 정보는 AVAILABLE 또는 IN_PROGRESS 상태로 시작하며, 게시 플랫폼이 이를 수락하면 listingUrl과 함께 SYNCED 상태로 전환됩니다.
curl https://listingsapi.com/api/v4/locations/TG9jYXRpb246MTgwMDI5MA==/listings/premium \-H "Authorization: API $LISTINGSAPI_KEY"웹훅을 구성하면 폴링이 필요하지 않습니다. 레코드가 존재하면 profile.created 이벤트가 발생하고, 각 게시 플랫폼의 상태가 변경될 때마다 해당 게시 플랫폼에 대해 listing.submission 이벤트가 발생합니다.
다음 단계
- 사업장 업데이트: 영업시간을 변경하고, 임시 휴업을 표시하고, Google 카테고리를 추가합니다.
- 사업장 사진 업로드: 로고, 커버 및 갤러리 이미지를 업로드합니다.
- Google 연결 및 사업장 가져오기: Google Business Profile을 연결하여 Google 등록 정보, 리뷰 및 게시물의 동기화를 시작합니다.
- Apple Business Connect 연결: 소유자의 인증된 Apple Business 계정을 통해 Apple Maps에 게시하거나, 소유자에게 해당 계정이 없으면 ListingsAPI 계정을 통해 게시합니다.
- 등록 정보 상태 및 실제 게시된 링크 확인: 방금 대기열에 추가한 제출 항목을 모니터링합니다.