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()andpost(), but you can activate just one) - Which serialization formats to accept — typically
json, sometimesxml - 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.
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 —cookieauthentication only recognizes an active browser session, not Basic Auth credentials. The mobile app's auth method would need to be added tosupported_auth, or it needs to authenticate via a method that already is.)
Key takeaways
- A discovered
@RestResourceplugin is not automatically reachable — it needs explicit per-method format and authentication configuration before it responds to anything. granularity: methodlets each HTTP method on a resource have its own formats/auth combination;granularity: resourceapplies one shared configuration to all of them.- This configuration is a normal
rest.resource.*config entity — exportable and deployable viadrush config:export/config:import, not something that has to live only in the admin UI. - A
406response means the request's format isn't supported for that method; a401/403means the authentication method isn't accepted — checksupported_formats/supported_authrespectively 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.