<!-- https://developers.silktide.com/v1/governance/metadata/set-section-metadata | Governance / Metadata -->

# Set some of a section's metadata

`POST /v1/websites/{websiteId}/sections/{sectionId}/meta`

Sets some of a section's metadata values and returns all of them, as
[Get a section's metadata](https://developers.silktide.com/v1/governance/metadata/get-section-metadata.md)
does. Section `0` is the whole website. Send only the values you want to
change; the rest keep theirs.

Setting metadata needs "Can admin this website", like the website's other
settings. Reading it needs only "Can see section".

Each value is checked against its property before anything is saved:

- An `int` takes a whole number, and a `float` any number. Either may be
  sent as a number or as a string such as `"2023"`. `min` and `max` are the
  smallest and largest allowed.
- A `bool` takes `true` or `false`, or `"true"`, `"false"`, `1` or `0`.
- A `url` takes an `http` or `https` address.
- A `string` takes text, at least `min` and at most `max` characters long.
- When a property has `choices` and `allowOther` is `false`, the value must
  be one of them.
- No value may be longer than 1,024 characters.

Send `null` or `""` to empty a value, unless the property `isRequired`. An
emptied `int` reads back as `0`, and an emptied `bool` as `false`.

A value equal to the one already stored is always accepted, even if it no
longer fits its property, so you can send every value back unchanged.

If any value is refused, nothing is saved. The answer is `400`
`InvalidRequest`; its message says what is wrong and `properties.field`
names the property:

```json
{
  "error": {
    "type": "InvalidRequest",
    "message": "Year created must be at least 1995.",
    "properties": { "field": "year" }
  }
}
```

## Request

### Path parameters

- `websiteId` (integer, required, at least 1): The website.
- `sectionId` (integer, required): The section. `0` is the whole website.

### Body

- `values` (map of strings or numbers or booleans, optional): The values to set, by property name. Properties left out keep their value, and `null` or `""` empties one. Each value is checked against its property. Left out, nothing changes.

## Response

Status `200`.

- `values` (map of strings or numbers or booleans or empty list, required): The section's values, by property name. Only properties that have been given a value are here. An empty array (`[]`), not an object, when none have.
- `properties` (list of objects, required): Every metadata property the account defines for sections, in the account's order.
  - `name` (string, required): The property's name: the key of its value in `values`.
  - `label` (string, required): Its name as people see it.
  - `propertyType` (string, required): The type of value it holds. One of: `string`, `int`, `float`, `bool`, `url`.
  - `isRequired` (boolean, required): Whether every section is meant to have a value for it.
  - `min` (integer, required, can be null): The smallest value (`int`, `float`) or shortest length (`string`, `url`) it is meant to take. Null for no limit.
  - `max` (integer, required, can be null): The largest value or longest length it is meant to take. Null for no limit.
  - `choices` (list of strings, required, can be null): The values to pick from. Null when it has no list.
  - `allowOther` (boolean, required): With `choices`, whether a value not in the list is meant to be allowed.

## Errors

| Status | Type | When |
| --- | --- | --- |
| 404 | `ModelNotFound` | No website or section with those ids exists in the account, or the API key's user cannot see it. |
| 403 | `AccessDenied` | The API key's user cannot admin this website. |
| 400 | `InvalidRequest` | A value does not fit its property, names no property the account has, or `values` is not an object. `properties.field` names the property, and nothing is saved. |
| 401 | `NotLoggedIn` | No API key was sent, or it is not a key for this region. |
| 429 | `TooManyRequests` | Too many requests to this path in five seconds. Retry after the number of seconds in the `Retry-After` header, which `properties.retryAfter` repeats. |
| 503 | - | Silktide is busy. Retry after the number of seconds in the `Retry-After` header. |

## Access

- Permission: Can admin this website
- Plan feature: none
- Edition: Silktide 4 and Silktide 5
- Cost: free
- Stability: stable, since 1.0.0

## Example: Set a section's region, author and year

```bash
curl -X POST "https://api.eu.silktide.com/v1/websites/3/sections/2/meta" \
  -H "Authorization: silktide token=$SILKTIDE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "values": {
    "region": "US",
    "author": "Jane Doe",
    "year": 2023
  }
}'
```

Response:

```json
{
  "values": {
    "region": "US",
    "author": "Jane Doe",
    "year": 2023
  },
  "properties": [
    {
      "name": "region",
      "label": "Region",
      "propertyType": "string",
      "isRequired": true,
      "min": null,
      "max": null,
      "choices": [
        "UK",
        "US",
        "Europe",
        "AU"
      ],
      "allowOther": false
    },
    {
      "name": "author",
      "label": "Author",
      "propertyType": "string",
      "isRequired": false,
      "min": null,
      "max": null,
      "choices": [
        "John Smith",
        "Jane Doe",
        "Joe Bloggs"
      ],
      "allowOther": true
    },
    {
      "name": "year",
      "label": "Year created",
      "propertyType": "int",
      "isRequired": false,
      "min": 1995,
      "max": 3000,
      "choices": null,
      "allowOther": false
    }
  ]
}
```
