Configuring REST Endpoints: Formats, Auth, and Granularityfor Drupal 8 , 9 , 10 , and 11

Last updated :  

Defining a @RestResource plugin, like you did in the last lesson, only gets you halfway there — Drupal won't actually respond to requests against it until you configure which formats (JSON? XML? both?) and which authentication methods (cookie, basic auth, OAuth?) that specific resource accepts. This lesson is entirely about that configuration step: the part that turns a discovered plugin into a live, callable endpoint.

What you'll learn in this lesson

  • Why a REST resource plugin existing isn't enough — and what actually activates it
  • How to enable a resource's formats and authentication providers via the REST UI module
  • How the same configuration looks as exportable YAML, for doing it in code/config instead of the admin UI
  • How to verify an endpoint is really live before you start debugging client code

Why REST resources need per-resource configuration

Every @RestResource plugin Drupal discovers is registered, but disabled by default — deliberately. A site might have a dozen resource plugins available (from core, contrib, and custom modules) but only want three of them actually reachable, each with different rules: one public and JSON-only, another requiring authentication, a third accepting XML from a legacy integration. That per-resource, per-format, per-auth-method control is exactly what this configuration layer provides.

Configuring a resource through the REST UI

With the core REST UI contrib module (or the core REST module's own admin form) enabled, visit Configuration → Web Services → REST. Every discovered resource plugin appears in a list — including my_custom_resource from the previous lesson — with an Enable/Disable toggle. Enabling one opens a form where you choose:

  • Which HTTP methods to expose (a resource plugin might implement get() and post(), but you can activate just one)
  • Which serialization formats to accept — typically json, sometimes xml
  • Which authentication providers are allowed — cookie (browser sessions), basic_auth, or a contrib provider like OAuth2

The same configuration as exportable YAML

Everything the REST UI form sets is really just a rest.resource.* configuration entity, which means it's exportable and deployable like any other config — no manual admin-UI clicking required on production:

langcode: en
status: true
dependencies: {  }
id: my_custom_resource
plugin_id: my_custom_resource
granularity: method
configuration:
  GET:
    supported_formats:
      - json
    supported_auth:
      - cookie
      - basic_auth

granularity: method means each HTTP method (GET, POST, ...) gets its own formats/auth combination — the more common and more flexible choice. The alternative, granularity: resource, applies one shared configuration to every method the plugin implements; simpler, but less precise if your GET should be public while your POST requires authentication.

A resource enabled with no authentication providers listed is effectively unreachable — Drupal has nothing to check the request against and will reject it. If your endpoint suddenly starts returning 406 or 401 responses after a config change, checking the enabled supported_auth list for that method is usually the fastest diagnosis.

Verifying the endpoint is actually live

Before debugging client code, confirm the endpoint itself responds correctly with a direct request, sending an explicit Accept header matching a format you enabled:

curl -H "Accept: application/json" https://your-site.example/api/v1/custom-resource

A working, correctly-configured resource returns your JSON payload directly. A 406 Not Acceptable means the format you requested isn't in that method's supported_formats; a 401 or 403 means the authentication method you're sending (or not sending) isn't in supported_auth.

Quick check: your resource's GET method is configured with supported_auth: [cookie] only. A mobile app tries to call it using HTTP Basic Auth credentials instead. What happens? (Answer: the request is rejected — cookie authentication only recognizes an active browser session, not Basic Auth credentials. The mobile app's auth method would need to be added to supported_auth, or it needs to authenticate via a method that already is.)

Key takeaways

  • A discovered @RestResource plugin is not automatically reachable — it needs explicit per-method format and authentication configuration before it responds to anything.
  • granularity: method lets each HTTP method on a resource have its own formats/auth combination; granularity: resource applies one shared configuration to all of them.
  • This configuration is a normal rest.resource.* config entity — exportable and deployable via drush config:export/config:import, not something that has to live only in the admin UI.
  • A 406 response means the request's format isn't supported for that method; a 401/403 means the authentication method isn't accepted — check supported_formats/supported_auth respectively before assuming a deeper bug.

Coming up next

An endpoint that's reachable by anyone isn't the same as an endpoint that's actually secure. Next, we'll look specifically at securing REST resources — going beyond "which auth providers are allowed" into permissions, access checks, and the specific mistakes that leave custom REST endpoints accidentally wide open.