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

# Connect Drupal to Semji

> Step-by-step guide to connect your Drupal site to Semji through JSON:API and Basic Auth, so AI agents can read, create, and update content.

Semji connects to Drupal through the **JSON:API** core module, authenticating
every request with **HTTP Basic Auth**. Once connected, Semji's AI agents can
explore your content model, list and read content, create and update it, and
— if you allow it — delete it.

Compatible from **Drupal 8.7** (the version where JSON:API joined Drupal core).

## Prerequisites

* **Drupal 8.7 or newer**, served over **HTTPS** and reachable from the
  **public internet**.
* The **JSON:API** core module enabled.
* The **HTTP Basic Authentication** (`basic_auth`) core module enabled.
* For publishing and updating: JSON:API set to read-write — check **"Accept
  all JSON:API create, read, update, and delete operations"** under
  `/admin/config/services/jsonapi`. JSON:API ships **read-only by default**;
  this is the most common blocker.
* A dedicated Drupal user account for Semji, with the permissions listed in
  [Permissions for the API account](#permissions-for-the-api-account). A
  plain editor role is **not** enough — see that section for why.
* To let agents write meta descriptions: the **Metatag** module, plus a
  *Meta tags* field on each content type concerned. See
  [Meta descriptions](#meta-descriptions).
* If a firewall, WAF, or anti-bot protection (Cloudflare, Akamai, Sucuri, …)
  sits in front of your site, it must **allow Semji's IP addresses** — see
  [Firewalls and IP allowlisting](#firewalls-and-ip-allowlisting).
* You are a **workspace owner** in Semji. The connection is shared with the
  whole workspace.

<Note>
  Availability of the Drupal integration depends on your Semji plan. If the
  **Connect** button opens an upgrade dialog instead of the connection form,
  contact your account manager.
</Note>

## Step 1 — Prepare your Drupal site

<Steps>
  <Step title="Enable the required modules">
    In the Drupal admin, go to **Extend** and enable **JSON:API** and **HTTP
    Basic Authentication**. Both ship with Drupal core.
  </Step>

  <Step title="Allow write operations">
    Go to **Configuration → Web services → JSON:API**
    (`/admin/config/services/jsonapi`) and select **"Accept all JSON:API
    create, read, update, and delete operations"**.
  </Step>

  <Step title="Create a dedicated role and user for Semji">
    Under **People → Roles**, create a role (e.g. *Semji API*) and grant it
    the permissions listed in
    [Permissions for the API account](#permissions-for-the-api-account).
    Then, under **People**, create an account (e.g. `semji-api`) with a strong
    password and assign it that role.

    Do not reuse a plain editor role: it lacks the permission Semji needs to
    set the publication status, and every write fails with a `403`.
  </Step>

  <Step title="Add a Meta tags field, if you want meta descriptions">
    Only if agents should write meta descriptions — see
    [Meta descriptions](#meta-descriptions) for the full procedure.
  </Step>
</Steps>

## Permissions for the API account

Grant these to the role you created for Semji. Replace `article` with each
content type agents will work on.

| Permission                      | Why Semji needs it                                | Required                                        |
| ------------------------------- | ------------------------------------------------- | ----------------------------------------------- |
| `access content`                | Read published content                            | Always                                          |
| `create article content`        | Create new content                                | To create                                       |
| `edit any article content`      | Update content the account did not author         | To update                                       |
| `use text format basic_html`    | Write the body in the text format Semji targets   | Always                                          |
| `administer nodes`              | Set the publication status (draft vs published)   | On content types **without** Content Moderation |
| Workflow transition permissions | Move content between moderation states            | On content types **with** Content Moderation    |
| `create terms in tags`          | Match or create tags in the `tags` vocabulary     | If agents attach tags                           |
| Paragraphs type permissions     | Create the paragraphs of a component-based layout | If your site uses **Paragraphs**                |
| `delete any article content`    | Delete content                                    | Only if you enable the Delete tool              |
| `administer node fields`        | Read the field definitions of your content types  | Optional — see below                            |

<Warning>
  **`administer nodes` is required on content types that do not use Content
  Moderation.** Semji always states the publication status explicitly, so
  content is never published by accident — and Drupal reserves writing the
  `status` field to that permission. Without it, every create and update
  fails with *"The current user is not allowed to POST the selected field
  (status). The 'administer nodes' permission is required."*

  On a content type governed by **Content Moderation**, Semji writes the
  moderation state instead, so `administer nodes` is not needed — grant the
  transition permissions of your workflow instead.
</Warning>

### About `administer node fields`

This one is **optional but recommended**. With it, Semji reads your content
types' field definitions directly and knows exactly which field holds what.
Without it, Semji falls back to inspecting an existing piece of content to
infer the structure — which works, but is less precise and needs at least one
existing item per content type.

Drupal flags this permission as restricted, because the same permission also
allows *adding and deleting fields* through the admin UI. If your security
policy rules that out, leave it off: the integration works without it.

## Meta descriptions

Drupal core has no meta description field. Semji writes meta descriptions
through the **[Metatag](https://www.drupal.org/project/metatag)** contributed
module, which most Drupal SEO setups already use.

<Steps>
  <Step title="Install and enable Metatag">
    Install the module the way you normally install contributed modules, then
    enable it under **Extend**.
  </Step>

  <Step title="Add a Meta tags field to each content type">
    Go to **Structure → Content types → *your type* → Manage fields → Create a
    new field**, and pick the **Meta tags** field type. Any label and machine
    name work — Semji identifies the field by its type, not its name.
  </Step>
</Steps>

Once the field exists, pass the meta description to an agent like any other
instruction ("write the meta description too") — Semji formats and stores it
for you. On an update it **merges** into the tags already on the item, so a
meta title you wrote by hand is preserved.

<Note>
  If a content type has no *Meta tags* field, agents write the content
  normally and tell you the meta description could not be saved. They never
  fall back to pasting it into the body.
</Note>

## Step 2 — Connect from Semji

<Steps>
  <Step title="Open the CMS integrations">
    In Semji, go to **Settings → Integrations**, open the **CMS** tab, and
    click **Connect** on the Drupal row.
  </Step>

  <Step title="Enter your credentials">
    Fill in the three fields:

    * **Site URL** — the canonical HTTPS base URL of your site, e.g.
      `https://your-site.com`. Semji does not follow redirects, so use the
      exact URL your site resolves to (`www` vs non-`www` matters).
    * **Username** — the Drupal login of the API account created in step 1.
    * **Password** — that account's password.

    Click **Next**. Semji tests the connection live by calling
    `GET /jsonapi` on your site and verifying that Drupal authenticates the
    account.
  </Step>

  <Step title="Pick the Drupal tools">
    Choose what AI agents can do on your site. All groups are enabled by
    default:

    * **Read** — browse, read, and inspect the site's content and structure.
    * **Write** — create and update content on the site.
    * **Delete** — delete content from the site (destructive).
  </Step>

  <Step title="Activate">
    Click **Activate**. The Drupal row now shows as connected.
  </Step>
</Steps>

## What Semji can do once connected

| Tool group | What it does                                                                                                                                                                                                |
| ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Read       | List content types, discover a type's fields and text formats, list and read content (including the raw stored HTML for lossless edits)                                                                     |
| Write      | Create and update content — new content is created as **draft** unless you explicitly ask an agent to publish; tags are matched or created in the `tags` vocabulary; Paragraphs-based layouts are supported |
| Delete     | Permanently delete a piece of content (agents ask for explicit confirmation first)                                                                                                                          |

### Content defaults

Out of the box, Semji targets the **`article`** content type with the
**`basic_html`** text format. On sites using **Content Moderation**, Semji
writes the `published` / `draft` moderation states instead of the raw status
field. Contact Semji support if your site needs different defaults (another
content type, text format, or custom moderation state names).

## Manage or disconnect

From **Settings → Integrations → CMS**, the Drupal row offers:

* **Manage tools** — enable or disable each tool group.
* **Disconnect** — remove the integration for the whole workspace.

## Firewalls and IP allowlisting

Semji's servers call your Drupal JSON:API directly. If your site sits behind
Cloudflare or another WAF, you must allow those calls or the connection will
fail.

Semji's servers reach the internet through a fixed set of outbound IP addresses. If a firewall, WAF, or anti-bot protection (Cloudflare, Akamai, Sucuri, …) sits in front of your site, it can block Semji's requests — typically with a `403 Forbidden` — before they ever reach your CMS, even when your credentials are correct.

Allow the following Semji IP addresses:

```text theme={null}
63.34.75.122
63.35.78.179
54.228.104.165
18.200.156.37
34.248.117.83
52.213.28.177
```

On **Cloudflare**, create a WAF custom rule with the **Skip** action matching
requests where the source IP is one of the addresses above and the path
starts with `/jsonapi/`.

<Warning>
  A WAF answering `403 Forbidden` on `/jsonapi` makes Semji report **"Invalid
  Drupal credentials"** even though your username and password are correct.
  If you are sure of the credentials, check the firewall first.
</Warning>

## Troubleshooting

<AccordionGroup>
  <Accordion title="&#x22;Invalid Drupal credentials. Check the username and the password.&#x22;">
    Drupal did not authenticate the request. Either the username or password
    is wrong, the **`basic_auth`** module is not enabled (Drupal then treats
    the request as anonymous), or a WAF is blocking the request with a `403`
    before it reaches Drupal.
  </Accordion>

  <Accordion title="&#x22;Could not connect to the Drupal site. Check the credentials, the site URL, and that the JSON:API and Basic Auth modules are enabled.&#x22;">
    Frequent causes:

    * **JSON:API module disabled** — `/jsonapi` returns 404.
    * **The URL redirects.** Semji follows no redirects: if
      `https://example.com` redirects to `https://www.example.com`, enter the
      `www` URL.
    * **The site is unreachable** — DNS failure, host down, or the domain
      resolves to a private network address.
    * **A WAF challenge page** — an HTML anti-bot response is not valid
      JSON:API and fails the connection.
    * **The site is too slow** — responses must arrive within 10 seconds.
  </Accordion>

  <Accordion title="Publishing fails with a JSON:API read-only error">
    *"Drupal JSON:API is configured to accept only read operations."* — an
    administrator must enable **"Accept all JSON:API create, read, update,
    and delete operations"** under `/admin/config/services/jsonapi`.
  </Accordion>

  <Accordion title="An agent reports a permission error">
    *"Drupal authentication or permission error: the API account cannot
    create or update this content."* — the API account lacks create/edit
    permission on the target content type. For Paragraphs-based sites:
    *"check Paragraphs Type Permissions for the API account."*
  </Accordion>

  <Accordion title="Every write fails, but the credentials and JSON:API settings are correct">
    Check whether the account has **`administer nodes`**. Drupal reserves
    writing the `status` field to that permission, and Semji always states
    the publication status explicitly, so an account without it fails on
    every create and update — even though reading works fine and the
    connection test passes. See
    [Permissions for the API account](#permissions-for-the-api-account).
  </Accordion>

  <Accordion title="The connection test fails while the site looks fine in a browser">
    If your site is in **maintenance mode**, Drupal answers `503` on
    `/jsonapi` for every account without the *"Use the site in maintenance
    mode"* permission — which the API account normally does not have. You can
    browse the site yourself because your admin session bypasses it. Turn
    maintenance mode off under **Configuration → Development → Maintenance
    mode**, or grant that permission to the Semji role.
  </Accordion>

  <Accordion title="An agent says the meta description was not saved">
    Two distinct cases:

    * *No meta description field on this content type* — install **Metatag**
      and add a *Meta tags* field, as described in
      [Meta descriptions](#meta-descriptions).
    * *Drupal accepted the write but stored nothing* — Semji could not read
      your field definitions and guessed the wrong format. Grant
      **`administer node fields`** to the API account, or set that one meta
      description by hand.

    In both cases the rest of the content is written normally.
  </Accordion>

  <Accordion title="URL validation errors before submitting">
    * *"Please enter a valid URL."* — the value does not parse as a URL.
    * *"The site URL must start with https\://."* — HTTP sites cannot be
      connected.
    * *"The site URL points to a private or reserved address, which is not
      allowed."* — localhost and private-network hosts are rejected; the site
      must be publicly reachable.
  </Accordion>
</AccordionGroup>

## Related

* [Sync drafts to your CMS](/guides/sync-drafts-to-cms) — API-based publishing flow, if you prefer to drive the sync yourself.
