# Mark a listing or set Google's review link

- **OpenAPI Version:** `3.2.0`
- **API Version:** `3.1.0`
- **Contact:** Syndai <https://syndai.ai>

## Contents

**Operations**

- [PUT /api/v1/external/coding/customers/{customer\_id}/seo/sites/{site\_id}/listings/{key}](#scalar-operation-put-apiv1externalcodingcustomerscustomer-idseositessite-idlistingskey)

**Schemas**

- [SeoListingMarkRequest](#scalar-schema-seolistingmarkrequest)
- [SeoListingsRead](#scalar-schema-seolistingsread)
- [SeoListingFactsRead](#scalar-schema-seolistingfactsread)
- [SeoGoogleListingRead](#scalar-schema-seogooglelistingread)
- [SeoListingPlaceRead](#scalar-schema-seolistingplaceread)
- [ProblemDetail](#scalar-schema-problemdetail)
- [ExternalErrorCode](#scalar-schema-externalerrorcode)

<a id="scalar-context-global-servers"></a>

## Servers

- **URL:** `https://api.syndai.ai`

<a id="scalar-context-global-authentication"></a>

## Authentication

- **CustomerApiKey**: HTTP bearer (`API Key`)

  Customer API key sent as a bearer token

## Tags

### Sites

Beta: may change without notice. Websites connected for search and AI visibility: connect a site, link it to Google Search Console, read its SEO tab, show or hide it on Google, and run a priced Ask AI check of how assistants answer about it.

## Operations

<a id="scalar-operation-put-apiv1externalcodingcustomerscustomer-idseositessite-idlistingskey"></a>

### Mark a listing or set Google's review link

- **Method:** `PUT`
- **Path:** `/api/v1/external/coding/customers/{customer_id}/seo/sites/{site_id}/listings/{key}`
- **Operation ID:** `markSiteListing`
- **Tags:** Sites

The owner's mark on one place a local business lists itself (`google_business`, `bing_places`, `yelp`, `apple_business`, `facebook_page`, `nextdoor`): `state` `done`, `skipped` or `todo` (clears it). `review_link` (Google only, else 400): the business's own review link, https `g.page/r/...` or `search.google.com/local/writereview...`, at most 500 characters (anything else is 422 with nothing written); `null` clears it. Returns the Listings section. An unknown key, or a site that is not a local business, is 404. Needs `coding:apps:publish`; a portal member who is not an owner or admin is 403.

**Servers:** [Inherited servers](#scalar-context-global-servers)

**Authentication:** [Global authentication](#scalar-context-global-authentication)

#### Path parameters

- **`customer_id` (required)**: `string`, format: `uuid`
- **`site_id` (required)**: `string`, format: `uuid`
- **`key` (required)**: `string`

#### Request body

**Required:** `true`

**Content type:** `application/json`

[SeoListingMarkRequest](#scalar-schema-seolistingmarkrequest)

<a id="scalar-example-1"></a>

**Generated example:**

```json
{
  "review_link": "",
  "state": "done"
}
```

#### Responses

##### 200 Request fulfilled, document follows

**Content type:** `application/json`

[SeoListingsRead](#scalar-schema-seolistingsread)

<a id="scalar-example-2"></a>

**Generated example:**

```json
{
  "done": 1,
  "facts": {
    "address": "",
    "hours": "",
    "missing": [
      ""
    ],
    "name": "",
    "phone": "",
    "website": ""
  },
  "google": {
    "checked_at": "",
    "fixes": [
      ""
    ],
    "rating": 1,
    "review_link": "",
    "reviews": 1,
    "status": ""
  },
  "places": [
    {
      "blurb": "",
      "can_fill": true,
      "catch": "",
      "key": "",
      "name": "",
      "state": "",
      "url": ""
    }
  ],
  "total": 1
}
```

##### 400, 401, 403, 404

- `400` Bad request syntax or unsupported method
- `401` Invalid or missing customer API key
- `403` Insufficient scope or forbidden customer access
- `404` Resource not found

**Content type:** `application/problem+json`

[ProblemDetail](#scalar-schema-problemdetail)

RFC 7807 problem detail returned for public CaaS errors.

<a id="scalar-example-3"></a>

**Generated example:**

```json
{
  "code": "BUDGET_EXHAUSTED",
  "detail": null,
  "existing_run_id": null,
  "instance": null,
  "status": 1,
  "title": "",
  "type": "about:blank",
  "additionalProperty": "anything"
}
```

##### 429 Rate limit exceeded

**Headers:**

- **`Retry-After`**

  Seconds to wait before retrying the request

  `integer`

**Content type:** `application/problem+json`

[ProblemDetail](#scalar-schema-problemdetail)

RFC 7807 problem detail returned for public CaaS errors.

[Generated example](#scalar-example-3)

##### default Unexpected error

**Content type:** `application/problem+json`

[ProblemDetail](#scalar-schema-problemdetail)

<a id="scalar-example-4"></a>

**Generated example:**

```json
null
```

## Schemas

<a id="scalar-schema-seolistingmarkrequest"></a>

### SeoListingMarkRequest

**Type:** `object`

- **`review_link`**: `string | null`, maxLength: `500`
- **`state`**

  **One of:**
  - `string`, possible values: `"done", "skipped", "todo"`

<a id="scalar-example-5"></a>

**Generated example:**

```json
{
  "review_link": "",
  "state": "done"
}
```

<a id="scalar-schema-seolistingsread"></a>

### SeoListingsRead

**Type:** `object`

- **`done` (required)**: `integer`
- **`facts` (required)**: [SeoListingFactsRead](#scalar-schema-seolistingfactsread)
- **`google` (required)**: [SeoGoogleListingRead](#scalar-schema-seogooglelistingread)
- **`places` (required)**: array of [SeoListingPlaceRead](#scalar-schema-seolistingplaceread)
- **`total` (required)**: `integer`

<a id="scalar-example-6"></a>

**Generated example:**

```json
{
  "done": 1,
  "facts": {
    "address": "",
    "hours": "",
    "missing": [
      ""
    ],
    "name": "",
    "phone": "",
    "website": ""
  },
  "google": {
    "checked_at": "",
    "fixes": [
      ""
    ],
    "rating": 1,
    "review_link": "",
    "reviews": 1,
    "status": ""
  },
  "places": [
    {
      "blurb": "",
      "can_fill": true,
      "catch": "",
      "key": "",
      "name": "",
      "state": "",
      "url": ""
    }
  ],
  "total": 1
}
```

<a id="scalar-schema-seolistingfactsread"></a>

### SeoListingFactsRead

**Type:** `object`

- **`missing` (required)**: `array of string`
- **`address`**: `string | null`
- **`hours`**: `string | null`
- **`name`**: `string | null`
- **`phone`**: `string | null`
- **`website`**: `string | null`

<a id="scalar-example-7"></a>

**Generated example:**

```json
{
  "address": "",
  "hours": "",
  "missing": [
    ""
  ],
  "name": "",
  "phone": "",
  "website": ""
}
```

<a id="scalar-schema-seogooglelistingread"></a>

### SeoGoogleListingRead

**Type:** `object`

- **`fixes` (required)**: `array of string`
- **`status` (required)**: `string`
- **`checked_at`**: `string | null`
- **`rating`**: `number | null`
- **`review_link`**: `string | null`
- **`reviews`**: `integer | null`

<a id="scalar-example-8"></a>

**Generated example:**

```json
{
  "checked_at": "",
  "fixes": [
    ""
  ],
  "rating": 1,
  "review_link": "",
  "reviews": 1,
  "status": ""
}
```

<a id="scalar-schema-seolistingplaceread"></a>

### SeoListingPlaceRead

**Type:** `object`

- **`blurb` (required)**: `string`
- **`can_fill` (required)**: `boolean`
- **`catch` (required)**: `string`
- **`key` (required)**: `string`
- **`name` (required)**: `string`
- **`state` (required)**: `string`
- **`url` (required)**: `string`

<a id="scalar-example-9"></a>

**Generated example:**

```json
{
  "blurb": "",
  "can_fill": true,
  "catch": "",
  "key": "",
  "name": "",
  "state": "",
  "url": ""
}
```

<a id="scalar-schema-problemdetail"></a>

### ProblemDetail

**Type:** `object`

RFC 7807 problem detail returned for public CaaS errors.

- **`code` (required)**: `string`, possible values: `"BUDGET_EXHAUSTED", "QUOTA_EXCEEDED", "RUN_CONCURRENCY_LIMIT", "CUSTOMER_DISABLED", "REPO_NOT_BOUND", "IDEMPOTENCY_REPLAY", "CONFLICT", "MISSION_BUSY_RETRY", "HITL_REQUEST_CONFLICT", "HITL_REQUEST_SETTLED", "RUN_TERMINATED_BEFORE_RESPONSE", "INVALID_POLICY", "INVALID_SCOPE", "RATE_LIMITED", "INSTALLATION_INCOMPLETE", "SUBSCRIPTION_USAGE_UNAVAILABLE", "INVALID_TOKEN", "ROLE_REQUIRED", "PLAN_UPGRADE_REQUIRED", "EMAIL_MISMATCH", "EXPIRED_TOKEN", "NOT_FOUND", "OVERSCOPE_ACK_REQUIRED", "VERIFY_FAILED", "PUBLISH_IN_FLIGHT", "PUBLISH_UNSUPPORTED_REPO", "PUBLICATION_NOT_LIVE", "NO_APP_DATA", "FEATURE_REQUESTS_NEEDS_MEMBERS", "EMPTY_UPDATE", "BAD_CURSOR", "HUMAN_APPROVAL_REQUIRED", "PROTECTED_PATHS_MANAGED_ONLY", "RUN_IN_FLIGHT", "TEXT_EDIT_REFUSED", "CLI_UPGRADE_REQUIRED", "PRODUCTION_STEP_UP_REQUIRED", "PRICES_UPDATING", "GITHUB_UNAVAILABLE", "PUBLISH_NOT_SET_UP", "VERSION_NOT_DEPLOYED", "INTERNAL_ERROR"`

  Stable error codes surfaced to public CaaS clients.
- **`status` (required)**: `integer`
- **`title` (required)**: `string`
- **`detail`**: `string | null`, default: `null`
- **`existing_run_id`**: `string | null`, default: `null`
- **`instance`**: `string | null`, default: `null`
- **`type`**: `string`, default: `"about:blank"`

<a id="scalar-example-10"></a>

**Generated example:**

```json
{
  "code": "BUDGET_EXHAUSTED",
  "detail": null,
  "existing_run_id": null,
  "instance": null,
  "status": 1,
  "title": "",
  "type": "about:blank",
  "additionalProperty": "anything"
}
```

<a id="scalar-schema-externalerrorcode"></a>

### ExternalErrorCode

**Type:** `string`, possible values: `"BUDGET_EXHAUSTED", "QUOTA_EXCEEDED", "RUN_CONCURRENCY_LIMIT", "CUSTOMER_DISABLED", "REPO_NOT_BOUND", "IDEMPOTENCY_REPLAY", "CONFLICT", "MISSION_BUSY_RETRY", "HITL_REQUEST_CONFLICT", "HITL_REQUEST_SETTLED", "RUN_TERMINATED_BEFORE_RESPONSE", "INVALID_POLICY", "INVALID_SCOPE", "RATE_LIMITED", "INSTALLATION_INCOMPLETE", "SUBSCRIPTION_USAGE_UNAVAILABLE", "INVALID_TOKEN", "ROLE_REQUIRED", "PLAN_UPGRADE_REQUIRED", "EMAIL_MISMATCH", "EXPIRED_TOKEN", "NOT_FOUND", "OVERSCOPE_ACK_REQUIRED", "VERIFY_FAILED", "PUBLISH_IN_FLIGHT", "PUBLISH_UNSUPPORTED_REPO", "PUBLICATION_NOT_LIVE", "NO_APP_DATA", "FEATURE_REQUESTS_NEEDS_MEMBERS", "EMPTY_UPDATE", "BAD_CURSOR", "HUMAN_APPROVAL_REQUIRED", "PROTECTED_PATHS_MANAGED_ONLY", "RUN_IN_FLIGHT", "TEXT_EDIT_REFUSED", "CLI_UPGRADE_REQUIRED", "PRODUCTION_STEP_UP_REQUIRED", "PRICES_UPDATING", "GITHUB_UNAVAILABLE", "PUBLISH_NOT_SET_UP", "VERSION_NOT_DEPLOYED", "INTERNAL_ERROR"`

Stable error codes surfaced to public CaaS clients.
