# Upsert Faq

> Upsert by external_ref: 200 updated, 201 created (the handler sets the status).

Source: https://shopassist.coec.dk/docs/api/reference/knowledge/upsert-faq · Updated 2026-11-03

`PUT /v1/stores/{store_id}/knowledge/faqs/{external_ref}`

- Scope: `knowledge:write`
- Rate limit: 600 requests/min per API key (test keys: 60/min)

Upsert by `external_ref`: `200` updated, `201` created (the handler sets the status).

## Parameters [#parameters]

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `store_id` | path | `string` | yes |  |
| `external_ref` | path | `string` | yes | Merchant FAQ key |

## Request body (FaqUpsert) [#request-body]

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `answer` | `string` | yes | 1–10000 characters |
| `locale` | `string` | no | 2–35 characters · pattern `^[A-Za-z]{2,3}(-[A-Za-z0-9]{2,8})*$` |
| `question` | `string` | yes | 1–500 characters |

## Example request [#example-request]

```bash
curl -X PUT "https://api.shopassist.coec.dk/v1/stores/sto_01j8000000e008000000000000/knowledge/faqs/string" \
  -H "Authorization: Bearer $SHOPASSIST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"answer":"string","locale":"da-DK","question":"string"}'
```

## Response 200 (KnowledgeDocument) [#response]

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `chunk_count` | `integer` | yes |  |
| `content_preview` | `string` | yes |  |
| `doc_type` | `string (enum)` | yes | one of policy, page, faq, file, blog, size_chart, other |
| `fetched_at` | `string \| null` | yes | format date-time |
| `id` | `string` | yes | pattern `^kdoc_[0-9a-hjkmnp-tv-z]{26}$` |
| `injection_flags` | `InjectionFlag[]` | yes |  |
| `injection_flags[].excerpt` | `string` | yes |  |
| `injection_flags[].rule` | `string` | yes |  |
| `locale` | `string \| null` | yes |  |
| `pending_change` | `PendingChange \| null` | yes |  |
| `pending_change.diff_preview` | `string` | yes |  |
| `pending_change.reason` | `"off_domain" \| "crawled_policy" \| "content_changed" \| "mass_change"` | yes |  |
| `pending_change.since` | `string` | yes | format date-time |
| `policy_type` | `string (enum) \| null` | yes | one of refund, return, shipping, privacy, terms, contact, legal_notice, subscription, withdrawal, other |
| `review_status` | `"approved" \| "pending_review" \| "rejected"` | yes |  |
| `source_id` | `string` | yes | pattern `^ksrc_[0-9a-hjkmnp-tv-z]{26}$` |
| `status` | `"active" \| "excluded" \| "error"` | yes |  |
| `title` | `string` | yes |  |
| `updated_at` | `string` | yes | format date-time |
| `url` | `string \| null` | yes | format uri · ≤ 2048 characters |

```json
{
  "chunk_count": 1,
  "content_preview": "string",
  "doc_type": "policy",
  "fetched_at": "2026-09-28T10:15:30.123Z",
  "id": "kdoc_01j8000000e008000000000000",
  "injection_flags": [
    {
      "excerpt": "string",
      "rule": "string"
    }
  ],
  "locale": "da-DK",
  "pending_change": {
    "diff_preview": "string",
    "reason": "off_domain",
    "since": "2026-09-28T10:15:30.123Z"
  },
  "policy_type": "refund",
  "review_status": "approved",
  "source_id": "ksrc_01j8000000e008000000000000",
  "status": "active",
  "title": "string",
  "updated_at": "2026-09-28T10:15:30.123Z",
  "url": "https://shop.example/products/linen-shirt"
}
```

## Errors [#errors]

| Status | Meaning |
| --- | --- |
| 400 | Bad Request ([error codes](/docs/api/errors)) |
| 401 | Unauthorized ([error codes](/docs/api/errors)) |
| 403 | Forbidden ([error codes](/docs/api/errors)) |
| 404 | Not Found ([error codes](/docs/api/errors)) |
| 422 | Unprocessable Content ([error codes](/docs/api/errors)) |
| 429 | Too Many Requests ([error codes](/docs/api/errors)) |
