Using n8n as a SCIM facade in front of third-party REST API

Just out of curiosity, has anyone ever attempted to use n8n as a SCIM facade?
I figured that with n8n having webhooks that we can set path variables, this could be a possibility to sit in front of a service with a REST API but without its own SCIM connector.

Describe the problem/error/question

Many services have REST API’s to create, retrieve, update, and delete users. However, these may not have a SCIM connector available, making it difficult to provision using an IdP like Okta or Entra.
Given that n8n has webhooks that allow for path variables, using a switch to pass these off to return ServiceProviderConfig, ResourceTypes, Schemas, and transforming responses to SCIM-formatted JSON might work.
Thoughts?

What is the error message (if any)?

Please share your workflow

Information on your n8n setup

  • n8n version: 2.27.4
  • Running n8n via (Docker, npm, n8n cloud, desktop app): n8n cloud

@ThomasLu_EarthDaily yeah its doable, people run n8n as a thin SCIM server like this, webhooks with :path params + a Switch is the right shape and the static endpoints (ServiceProviderConfig etc) are trivial. the hard part is three things: PATCH (IdPs send a PatchOp operations array for everything incl deactivation as replace active=false, so you parse operations not a clean object), filtering (Okta/Entra hit ?filter=userName eq “x” to check existence before creating, so you parse the SCIM filter), and id vs externalId mapping (SCIM needs a stable id across calls but webhooks are stateless, so your downstream api or a data table has to own it). nail those three plus strict status codes and it holds up. whats the service behind it?

Yes, it works — I have built a lightweight SCIM v2 facade with n8n. Here is the pattern:

**Webhook setup**

One Webhook node per HTTP method (GET, POST, PUT, PATCH, DELETE) because n8n does not natively multiplex methods on the same path. Set each to the SCIM base path with a path variable: /scim/v2/Users/:id (id is optional on GET-list and POST).

**Routing**

A Switch node on $json.method or just rely on separate webhook paths. For the SCIM filter param on GET /Users, parse $request.query.filter with a Code node (the filter syntax is simple: userName eq “value” covers 90% of IdP queries).

**The hard parts**

  1. Response envelope — SCIM has a strict JSON schema (schemas array, totalResults, Resources, meta.resourceType). The Respond to Webhook node must return this exact shape or Okta/Entra will reject it. Use a Code node to build the envelope before the response.
  2. PATCH uses JSON Patch (RFC 6902) ops, not a plain body merge. You need to handle op: replace/add/remove explicitly.
  3. ETag / If-Match headers — some IdPs send these for optimistic concurrency. n8n does not natively expose response headers for inbound requests, so you have to skip ETag validation or parse the raw headers from $request.

**What works well**

Okta SCIM provisioning against an n8n facade is achievable in a weekend. Entra (Azure AD) is stricter on the response schema but still doable. The n8n workflow handles the translation layer cleanly once the envelope is right.

Happy to share the Code node snippet for the SCIM response envelope if useful.

Thanks for the offer if sharing your Code node snippet.

Since n8n has an MCP now though, I want to see if I can prompt it to build this out for me first.
In the future, I might look into building a community node to orchestrate everything, once I figure it all out first.

Thanks again everyone!