> ## Documentation Index
> Fetch the complete documentation index at: https://docs.usedatabrain.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Update Semantic Layer

> Update the semantic layer for a datamart by modifying table descriptions, column metadata, or feedback.

Modify the semantic layer metadata for an existing datamart. You can update table descriptions, column metadata, and feedback in a single request. Only the fields you include are updated — omitted tables and columns retain their existing values.

<Note>
  The datamart must already have a semantic layer. If no semantic data exists, this endpoint returns `404 SEMANTIC_LAYER_NOT_FOUND`. Use [POST](/developer-docs/helpers/api-reference/create-semantic-layer) to create a semantic layer first.
</Note>

## Authentication

This endpoint requires a **service token** in the Authorization header. Data app API tokens are not permitted and will be rejected with a `403` error.

To access your service token:

1. Go to your Databrain dashboard and open **Settings**.
2. Navigate to **Settings**.
3. Find the **Service Tokens** section.
4. Click the **"Generate Token"** button to generate a new service token if you don't have one already.

Use this token as the Bearer value in your Authorization header.

## Headers

<ParamField header="Authorization" type="string" required>
  Bearer token for API authentication. Use your service token.

  ```
  Authorization: Bearer dbn_live_abc123...
  ```
</ParamField>

<ParamField header="Content-Type" type="string" required>
  Must be set to `application/json` for all requests.

  ```
  Content-Type: application/json
  ```
</ParamField>

## Request Body

<ParamField body="datamartName" type="string" required>
  Name of the existing datamart to update. Must match exactly (case-sensitive).
</ParamField>

<ParamField body="tables" type="array">
  Array of table objects with updated semantic metadata. Only tables and columns included in the request are modified — others remain unchanged.
</ParamField>

<ParamField body="tables.name" type="string" required>
  Table name from the datamart. Must match an existing table.
</ParamField>

<ParamField body="tables.description" type="string">
  Updated description for the table. Maximum 500 characters.
</ParamField>

<ParamField body="tables.synonyms" type="string[]">
  Updated synonyms for the table. Maximum 10 synonyms, each up to 100 characters. Must be unique (case-insensitive).
</ParamField>

<ParamField body="tables.miscellaneousInfo" type="string">
  Updated additional context. Maximum 1000 characters.
</ParamField>

<ParamField body="tables.columns" type="array">
  Array of column objects to update. Only listed columns are modified.
</ParamField>

<ParamField body="tables.columns.name" type="string" required>
  Column name from the table. Must match an existing column.
</ParamField>

<ParamField body="tables.columns.description" type="string">
  Updated description. Maximum 500 characters.
</ParamField>

<ParamField body="tables.columns.synonyms" type="string[]">
  Updated synonyms. Maximum 10 synonyms, each up to 100 characters.
</ParamField>

<ParamField body="tables.columns.miscellaneousInfo" type="string">
  Updated additional context. Maximum 1000 characters.
</ParamField>

<ParamField body="tables.columns.columnType" type="string">
  Updated semantic column type. Must be one of: `String`, `Long String`, `String (Custom)`, `ENUM`, `Mapper`, `Range`, `Expression`, `Identifier`, `Number`, `JSON`. Must be compatible with the column's underlying datatype.
</ParamField>

<ParamField body="tables.columns.columnTypeConfig" type="object | string | null">
  Updated configuration for the column type. Same shapes as [create](/developer-docs/helpers/api-reference/create-semantic-layer): object map for `String` / `String (Custom)` / `ENUM` / `Mapper`; `{ lowerLimit, upperLimit }` (numbers) for `Range`; string for `Expression` and `JSON`; `null` or omit for `Identifier`, `Number`, and `Long String`.
</ParamField>

<ParamField body="tables.columns.isIdentifier" type="boolean">
  Updated identifier flag.
</ParamField>

<ParamField body="tables.columns.isNotIndexed" type="boolean">
  Updated indexing exclusion flag.
</ParamField>

<ParamField body="feedback" type="string">
  Updated global feedback text. Maximum 2000 characters. When provided, replaces the existing feedback.
</ParamField>

## Response

On success, the response body contains only the datamart name. There is no `error` field in the JSON body when the request succeeds.

<ResponseField name="id" type="string">
  The name of the updated datamart (same as the input `datamartName`).
</ResponseField>

## Examples

<Panel>
  <RequestExample>
    ```bash cURL - Update Tables & Feedback theme={"dark"}
    curl --request PUT \
      --url https://api.usedatabrain.com/api/v2/data-app/datamarts/semantic-layer \
      --header 'Authorization: Bearer dbn_live_abc123...' \
      --header 'Content-Type: application/json' \
      --data '{
        "datamartName": "sales-analytics",
        "tables": [
          {
            "name": "orders",
            "description": "Updated: Customer purchase orders with status tracking",
            "columns": [
              {
                "name": "status",
                "description": "Order lifecycle status",
                "synonyms": ["order status", "state", "order state"]
              }
            ]
          }
        ],
        "feedback": "Updated context: All amounts in USD. Fiscal year starts April 1."
      }'
    ```

    ```bash cURL - Update Feedback Only theme={"dark"}
    curl --request PUT \
      --url https://api.usedatabrain.com/api/v2/data-app/datamarts/semantic-layer \
      --header 'Authorization: Bearer dbn_live_abc123...' \
      --header 'Content-Type: application/json' \
      --data '{
        "datamartName": "sales-analytics",
        "feedback": "Updated: All amounts in USD. Customer IDs are numeric."
      }'
    ```

    ```javascript Node.js icon="fa-brands fa-node-js" theme={"dark"}
    const response = await fetch('https://api.usedatabrain.com/api/v2/data-app/datamarts/semantic-layer', {
      method: 'PUT',
      headers: {
        'Authorization': 'Bearer dbn_live_abc123...',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        datamartName: 'sales-analytics',
        tables: [
          {
            name: 'orders',
            description: 'Updated order descriptions',
            columns: [
              {
                name: 'status',
                description: 'Order lifecycle status',
                synonyms: ['order status', 'state']
              }
            ]
          }
        ],
        feedback: 'Updated feedback text.'
      })
    });

    const result = await response.json();

    if (result.error) {
      console.error('Update failed:', result.error.message);
    } else {
      console.log('Semantic layer updated:', result.id);
    }
    ```

    ```python Python icon="fa-brands fa-python" theme={"dark"}
    import requests

    response = requests.put(
        'https://api.usedatabrain.com/api/v2/data-app/datamarts/semantic-layer',
        headers={
            'Authorization': 'Bearer dbn_live_abc123...',
            'Content-Type': 'application/json'
        },
        json={
            'datamartName': 'sales-analytics',
            'tables': [
                {
                    'name': 'orders',
                    'description': 'Updated order descriptions',
                    'columns': [
                        {
                            'name': 'status',
                            'description': 'Order lifecycle status',
                            'synonyms': ['order status', 'state']
                        }
                    ]
                }
            ],
            'feedback': 'Updated feedback text.'
        }
    )

    result = response.json()

    if result.get('error'):
        print(f"Update failed: {result['error']['message']}")
    else:
        print(f"Semantic layer updated: {result['id']}")
    ```

    ```ruby Ruby icon="fa-solid fa-gem" theme={"dark"}
    require 'net/http'
    require 'json'

    uri = URI('https://api.usedatabrain.com/api/v2/data-app/datamarts/semantic-layer')
    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = true

    request = Net::HTTP::Put.new(uri)
    request['Authorization'] = 'Bearer dbn_live_abc123...'
    request['Content-Type'] = 'application/json'
    request.body = {
      datamartName: 'sales-analytics',
      tables: [
        {
          name: 'orders',
          description: 'Updated order descriptions',
          columns: [
            { name: 'status', description: 'Order lifecycle status' }
          ]
        }
      ]
    }.to_json

    response = http.request(request)
    result = JSON.parse(response.body)
    puts "Updated: #{result['id']}"
    ```

    ```java Java icon="fa-brands fa-java" theme={"dark"}
    import java.net.http.HttpClient;
    import java.net.http.HttpRequest;
    import java.net.http.HttpResponse;
    import java.net.URI;

    public class UpdateSemanticLayer {
        public static void main(String[] args) throws Exception {
            HttpClient client = HttpClient.newHttpClient();

            String requestBody = """
                {
                    "datamartName": "sales-analytics",
                    "tables": [
                        {
                            "name": "orders",
                            "description": "Updated order descriptions",
                            "columns": [
                                {
                                    "name": "status",
                                    "description": "Order lifecycle status"
                                }
                            ]
                        }
                    ],
                    "feedback": "Updated feedback text."
                }""";

            HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://api.usedatabrain.com/api/v2/data-app/datamarts/semantic-layer"))
                .header("Authorization", "Bearer dbn_live_abc123...")
                .header("Content-Type", "application/json")
                .PUT(HttpRequest.BodyPublishers.ofString(requestBody))
                .build();

            HttpResponse<String> response = client.send(request,
                HttpResponse.BodyHandlers.ofString());
            System.out.println(response.body());
        }
    }
    ```

    ```go Go icon="fa-brands fa-golang" theme={"dark"}
    package main

    import (
        "bytes"
        "encoding/json"
        "fmt"
        "net/http"
    )

    func main() {
        body := map[string]interface{}{
            "datamartName": "sales-analytics",
            "tables": []map[string]interface{}{
                {
                    "name":        "orders",
                    "description": "Updated order descriptions",
                    "columns": []map[string]interface{}{
                        {
                            "name":        "status",
                            "description": "Order lifecycle status",
                        },
                    },
                },
            },
            "feedback": "Updated feedback text.",
        }

        jsonData, _ := json.Marshal(body)

        req, _ := http.NewRequest("PUT",
            "https://api.usedatabrain.com/api/v2/data-app/datamarts/semantic-layer",
            bytes.NewBuffer(jsonData))
        req.Header.Set("Authorization", "Bearer dbn_live_abc123...")
        req.Header.Set("Content-Type", "application/json")

        client := &http.Client{}
        resp, _ := client.Do(req)
        defer resp.Body.Close()

        fmt.Println("Semantic layer updated")
    }
    ```

    ```php PHP icon="fa-brands fa-php" theme={"dark"}
    <?php
    $url = 'https://api.usedatabrain.com/api/v2/data-app/datamarts/semantic-layer';
    $data = [
        'datamartName' => 'sales-analytics',
        'tables' => [
            [
                'name' => 'orders',
                'description' => 'Updated order descriptions',
                'columns' => [
                    [
                        'name' => 'status',
                        'description' => 'Order lifecycle status'
                    ]
                ]
            ]
        ],
        'feedback' => 'Updated feedback text.'
    ];

    $options = [
        'http' => [
            'header' => [
                'Authorization: Bearer dbn_live_abc123...',
                'Content-Type: application/json'
            ],
            'method' => 'PUT',
            'content' => json_encode($data)
        ]
    ];

    $context = stream_context_create($options);
    $response = file_get_contents($url, false, $context);
    $result = json_decode($response, true);

    echo "Updated: " . $result['id'];
    ?>
    ```
  </RequestExample>

  <ResponseExample>
    ```json 200 - Success theme={"dark"}
    {
      "id": "sales-analytics"
    }
    ```

    ```json 400 - Missing datamartName theme={"dark"}
    {
      "error": {
        "code": "INVALID_REQUEST_BODY",
        "message": "\"datamartName\" is required"
      }
    }
    ```

    ```json 400 - No Section Provided theme={"dark"}
    {
      "error": {
        "code": "INVALID_REQUEST_BODY",
        "message": "\"value\" must contain at least one of [tables, feedback]"
      }
    }
    ```

    ```json 400 - Invalid Table theme={"dark"}
    {
      "error": {
        "code": "INVALID_TABLE",
        "message": "Table 'nonexistent_table' not found in datamart 'sales-analytics'"
      }
    }
    ```

    ```json 404 - No Semantic Layer theme={"dark"}
    {
      "error": {
        "code": "SEMANTIC_LAYER_NOT_FOUND",
        "message": "No semantic layer found for datamart 'sales-analytics'. Use POST to create first."
      }
    }
    ```

    ```json 403 - Data App Token theme={"dark"}
    {
      "error": {
        "code": "AUTHENTICATION_ERROR",
        "message": "Semantic Layer API requires a service token, not a data app API token"
      }
    }
    ```
  </ResponseExample>
</Panel>

## HTTP Status Code Summary

| Status Code | Description                                                  |
| ----------- | ------------------------------------------------------------ |
| `200`       | **OK** — Semantic layer updated successfully                 |
| `400`       | **Bad Request** — Validation failed (see error codes below)  |
| `401`       | **Unauthorized** — Invalid or missing API token              |
| `403`       | **Forbidden** — Data app token used instead of service token |
| `404`       | **Not Found** — No semantic layer exists for this datamart   |
| `500`       | **Internal Server Error** — Server error occurred            |

## Possible Errors

| Error Code                   | HTTP Status | Description                                         |
| ---------------------------- | ----------- | --------------------------------------------------- |
| `INVALID_REQUEST_BODY`       | 400         | Missing required fields or validation failure       |
| `INVALID_DATAMART`           | 400         | Datamart not found                                  |
| `INVALID_TABLE`              | 400         | Table name doesn't exist in the datamart            |
| `INVALID_COLUMN`             | 400         | Column name doesn't exist in the table              |
| `INVALID_COLUMN_TYPE`        | 400         | Column type incompatible with the column's datatype |
| `INVALID_COLUMN_TYPE_CONFIG` | 400         | Column type config has wrong shape                  |
| `DUPLICATE_SYNONYM`          | 400         | Duplicate synonyms detected (case-insensitive)      |
| `SEMANTIC_LAYER_NOT_FOUND`   | 404         | No semantic layer exists — use POST to create first |
| `AUTHENTICATION_ERROR`       | 403         | Data app token used instead of service token        |
| `INTERNAL_SERVER_ERROR`      | 500         | Server error                                        |

## Quick Start Guide

<Steps>
  <Step title="Get current semantic layer">
    Retrieve the existing semantic layer before making changes:

    ```bash theme={"dark"}
    curl --request GET \
      --url 'https://api.usedatabrain.com/api/v2/data-app/datamarts/semantic-layer?datamartName=sales-analytics' \
      --header 'Authorization: Bearer dbn_live_abc123...'
    ```

    <Check>
      Save this response in case you need to rollback your changes.
    </Check>
  </Step>

  <Step title="Prepare your update">
    Determine what you want to update:

    * **Tables/Columns**: Include only the tables and columns you want to change
    * **Feedback**: Provide the new text (replaces existing)

    <Tip>
      Unlike the datamart update API, the semantic layer update is additive for tables and columns — only the ones you include are modified.
    </Tip>
  </Step>

  <Step title="Update the semantic layer">
    ```bash theme={"dark"}
    curl --request PUT \
      --url https://api.usedatabrain.com/api/v2/data-app/datamarts/semantic-layer \
      --header 'Authorization: Bearer dbn_live_abc123...' \
      --header 'Content-Type: application/json' \
      --data '{ "datamartName": "sales-analytics", "feedback": "Updated context." }'
    ```
  </Step>

  <Step title="Verify the update">
    Retrieve the semantic layer again to confirm changes and check the updated completion score.
  </Step>
</Steps>

## Next Steps

<CardGroup cols={2}>
  <Card title="Get Semantic Layer" icon="eye" href="/developer-docs/helpers/api-reference/get-semantic-layer">
    Retrieve and verify your changes
  </Card>

  <Card title="Create Semantic Layer" icon="plus" href="/developer-docs/helpers/api-reference/create-semantic-layer">
    Create a semantic layer for a new datamart
  </Card>

  <Card title="Delete Semantic Layer" icon="trash" href="/developer-docs/helpers/api-reference/delete-semantic-layer">
    Remove semantic layer metadata entirely
  </Card>

  <Card title="Semantic Layer Guide" icon="book" href="/guides/datasources/semantic-layer">
    Configure the semantic layer in the Databrain UI
  </Card>
</CardGroup>
