Skip to content

Repository files navigation

Membrane API Gateway

For REST, OpenAPI, and GraphQL with first-class Legacy Support for XML, SOAP, and WSDL

GitHub release Build Docker Pulls License

Animated demo of Membrane API Gateway

Built on the Java platform, Membrane bridges legacy and modern APIs. It supports XML-to-JSON transformation, WSDL-to-OpenAPI conversion, SOAP-to-REST integration, and validation against OpenAPI and WSDL.

For modern APIs, Membrane supports technologies such as OAuth 2, JWT, and AI, along with a broad range of routing, transformation, and observability features. It is easy to set up and deploy, either as a container or as a Java application on a virtual machine.

Try Membrane in 5 Minutes

Start the API Gateway

Run Membrane as a container or as a Java application:

docker run --rm -it -p 2000:2000 predic8/membrane

Open these URLs in your browser to access sample APIs:

Or call an API from the command line:

curl http://localhost:2000/shop/v2/products

Proxy Your First API

Create a file apis.yaml with the following content:

api:
  port: 2000
  target:
    url: https://apibin.io

Start Membrane with your configuration:

Linux/macOS:

docker run --rm -p 2000:2000 -v "$(pwd)/apis.yaml:/opt/membrane/conf/apis.yaml" predic8/membrane

Windows PowerShell:

docker run --rm -p 2000:2000 -v "${PWD}/apis.yaml:/opt/membrane/conf/apis.yaml" predic8/membrane

Requests to http://localhost:2000 are now forwarded to https://apibin.io.

Make the Getting Started Tutorial

  1. Download the Membrane distribution
  2. Unzip
  3. Open tutorials/getting-started/10-First-API.yaml in your text editor and follow the instructions.

Why Membrane

From OpenAPI and OAuth to SOAP, XML, LLMs, and MCP, Membrane bridges modern APIs and enterprise integration.

Native OpenAPI Support

Deploy APIs directly from OpenAPI documents, validate messages against them, and even generate OpenAPI specifications from legacy WSDL. In addition to OpenAPI 3.0, and 3.1, Membrane also supports OpenAPI 3.2.

Legacy XML and Web Services Integration

wsdl2openapi transforms a Web Service's WSDL into an OpenAPI and uses the underlying XSD schema for the conversion between XML and JSON. Deploy a WSDL, and Membrane exposes the service as an API with an OpenAPI description.

XML and JSON are deeply integrated into Membrane. XPath and JSONPath expressions provide direct access to message data for routing, filtering, and transformation.

Templates and XSLT allow for flexible message transformation and SOAP-to-REST conversion.

XML and Web Services Security

Secure legacy services with WSDL and XSD message validation, XML message protection, and XML signatures.

OpenAPI, JSON Schema, XSD, and WSDL Validation

Validate messages against API and service specifications. Don't let invalid messages slip into your organization.

API Orchestration

Orchestrate calls to external APIs and process collections with loops and conditional flows.

Easy Configuration and Extensibility

Take a look at the samples below and the tutorials to see what just a few lines of configuration can do.

When you need more flexibility, extend Membrane with expressions and scripting using JSONPath, XPath, Groovy, or SpEL, or write your own plugin in Java. In most cases, custom Java code is not necessary.

Speed & Footprint

Although Membrane is written in Java, it delivers high performance with a low memory footprint. HTTP streaming, Keep-Alive, and non-blocking processing enable efficient resource utilization and high throughput. The Membrane distribution is only about 55 MB, making it smaller than many other API gateways.

On a single server Membrane can process 39,000 requests per second. However, raw throughput benchmarks often measure only simple proxying without message protection or transformation.

Membrane is implemented entirely in Java, from the HTTP engine to OpenAPI processing. This avoids the overhead of crossing between a native proxy core and a separate scripting runtime for plugins.

As a result, Membrane can maintain high performance even when multiple plugins for validation, security, and transformation are active. What matters is not performance in reduced benchmark setups, but performance under realistic gateway configurations.

What Can You Do With Membrane?

  • Expose and protect APIs for partners over the public Internet.
  • Secure APIs with OAuth 2.0, JWT, API keys, TLS, and message validation.
  • Modernize legacy services by integrating SOAP, XML, and WSDL with REST, JSON, and OpenAPI.
  • Transform messages between JSON, XML, SOAP, HTTP headers, query parameters, and other formats.
  • Route and control traffic with flexible rules, rate limiting, load balancing, and conditional processing.
  • Use Membrane as an outgoing gateway to control access to partner and public APIs.
  • Observe API traffic with logging, metrics, Prometheus, and OpenTelemetry tracing.
  • Use Membrane as an AI Gateway for LLM providers and MCP servers.
  • Replace maintenance-intensive Backend for Frontend (BFF) services with declarative gateway configuration where appropriate.
  • Embed Membrane into your own Java applications and products.
  • Deploy Membrane in containers, virtual machines, private clouds, or public clouds.

Membrane Features with Examples

For a quick overview of what you can do with Membrane, the sections below provide a selection of short examples and configuration snippets.

  1. OpenAPI Deployment, Validation and Swagger UI
  2. Legacy Web Services with SOAP and WSDL
  3. AI and LLM Gateway
  4. Routing
  5. Message Transformation
  6. Orchestration and Call Outs
  7. Scripting
  8. Security
  9. Traffic Control
  10. Operation

1. OpenAPI Deployment, Validation and Swagger UI

OpenAPI is a native feature in Membrane. The gateway supports OpenAPI 3.0, 3.1, and 3.2, including the QUERY HTTP method.

Membrane can deploy an API directly from an OpenAPI description. It uses the defined paths, schemas, operations, and backend URLs to configure routing and, optionally, validate incoming requests and outgoing responses.

api:
  port: 2000
  openapi:
    - location: openapi/fruitshop-v2-2-0.oas.yml
      validateRequests: true

Membrane lets you explore APIs deployed from OpenAPI APIs in a single overview page.

List of OpenAPI Deployments

For documentation and testing the gateway hosts also a Swagger UI for the deployed APIs.

Swagger UI

See: OpenAPI tutorial

2. Legacy Web Services with SOAP and WSDL

Integrate and modernize legacy SOAP web services.

WSDL to OpenAPI Conversion

Membrane can expose a SOAP web service described by WSDL as a REST API with an OpenAPI specification.

This configuration:

api:
  port: 2000
  flow:
    - wsdl2openapi:
        wsdl: mocks/partner.wsdl
        operations:
          getPartners:
            method: GET
            path: /partners
            tag: Partner
          getPartner:
            method: GET
            path: /partners/{id}
            tag: Partner
          createPartner:
            method: POST
            path: /partners
            tag: Partner
          updatePartner:
            method: PUT
            path: /partners/{id}
            tag: Partner
          deletePartner:
            method: DELETE
            path: /partners/{id}
            tag: Partner
  target:
    url: http://localhost:3000/partner-service

turns this WSDL into an OpenAPI specification including JSON schemas derived from the WSDL's XSD schemas:

OpenAPI from WSDL

After deploying this configuration, clients can send JSON requests to the REST API. Membrane transforms them into SOAP requests for the backend Web Service and converts the XML responses back to JSON.

The conversion uses the XML Schema definitions from the WSDL to map data precisely between JSON and XML.

Manual SOAP to REST Conversion

The easiest way to expose a SOAP Web Service as a REST API is to use the wsdl2openapi plugin described above.

For more control over the conversion, you can define the REST API manually and map individual REST endpoints to SOAP operations.

The following configuration accepts a request such as GET /cities/Tokio, creates a SOAP request for the backend service, and transforms the SOAP response into JSON:

api:
  port: 2000
  method: GET
  path:
    uri: /cities/{city}
  flow:
    - request:
        - soapBody:
            src: |
              <getCity xmlns="https://predic8.de/cities">
                  <name>${pathParam.city}</name>
              </getCity>
        - setHeader:
            name: SOAPAction
            value: https://predic8.de/cities/get
    - response:
        - template:
            contentType: application/json
            src: |
              {
                "country": ${xpath('//country')},
                "population": ${xpath('//population')}
              }
  target:
    # Change method to POST
    method: POST
    url: https://www.predic8.de/city-service

Note: Membrane automatically escapes expression values such as ${xpath(...)} for the specified content type.

See the SOAP to REST tutorial for more details.

API Configuration from WSDL

Membrane can create a SOAP proxy directly from a WSDL:

soapProxy:
  port: 2000
  wsdl: https://www.predic8.de/city-service?wsdl

After startup, Membrane exposes:

Message Validation against WSDL and XSD

The validator checks SOAP messages against a WSDL document including referenced XSD schemas.

soapProxy:
  port: 2000
  wsdl: https://www.predic8.de/city-service?wsdl
  flow:
    # Validates SOAP messages against the WSDL and XSDs
    - validator: {}

Web Services Security (WSS)

Legacy SOAP services protected with Web Services Security (WS-Security) may require credentials and an XML Signature.

api:
  port: 2000
  flow:
     - wsSecurity:
         secure:
           - usernameToken:
               username: alice
               password: secret
           - signature:
               references:
                 - by: BODY
                 - by: USERNAME_TOKEN
target:
    url: http://localhost:2001

Membrane can create and validate WS-Security UsernameTokens and XML Signatures.

3. AI and LLM Gateway

Membrane can act as a gateway for Large Language Models (LLMs) and Model Context Protocol (MCP) servers, providing centralized access control, usage policies, and API key management.

MCP Protection

The mcpProtectionplugin sits in front of an MCP server and controls which tools clients can discover and call.

Membrane MCP protection in front of an MCP server

api:
  port: 2000
  flow:
    - mcpProtection:
        tools:
          - allow: getCustomers
          - allow: getOrders
          - deny: '.*'
  target:
    url: http://my-mcp-server

See the MCP protection tutorial.

LLM Gateway

The llmGateway plugin routes requests to LLM providers such as Anthropic Claude, OpenAI, and Google Gemini. It can centralize provider API keys and enforce policies for token usage and allowed models.

api:
  port: 2000
  flow:
    - llmGateway:
        claude: {}
        apiKey: <<Replace with your API_KEY>>
        policies:
          maxOutputTokens: 100000
          models:
            - claude-opus-4-8
            - claude-sonnet-5
        simpleStore:
          users:
            - name: alice
              apiKey: abc123
              tokens: 2000000
            - name: bob
              apiKey: qwertz
              tokens: 10000000
          limitResetPeriod: 86400
  target:
    url: https://api.anthropic.com

Instead of handing the API key to every developer, keep it in the gateway and issue per-user keys. Membrane authenticates the user, enforces a per-user token budget, restricts the allowed models, and forwards the request using the shared provider key.

See: LLM key sharing tutorial.

4. Routing

Membrane provides flexible routing based on HTTP properties and custom expressions.

# Only GET to /products on port 2000
api:
  port: 2000
  method: GET
  path: /products
  flow:
    - response:
        - static:
            src: Oui!
    - return:
        status: 200

There are many routing options:

Option Description
port Listening port
method HTTP method, e.g. GET, POST, QUERY
path Request path
host Hostname, e.g. api.predic8.de
test Custom expression, e.g. header['content-type'].startsWith('text/plain')

See the API reference documentation.

5. Message Transformation

POST to GET with Query Parameters

Transform a POST request such as:

POST /products
Content-Type: application/json

{"limit": 100, "sort": "name"}

into a GET request: GET /products?limit=100&sort=name using a URI template with JSONPath expressions:

api:
  port: 2000
  target:
    method: GET
    url: https://api.predic8.de/shop/v2/products?sort=${$.sort}&limit=${$.limit}
    language: jsonpath

Note: Membrane automatically escapes expression values such as ${$.sort} for the specified content type.

See the tutorial to transform from GET to POST.

Templates

Templates can transform request and response bodies using data from the current message or the environment.

Membrane uses a Groovy-based template engine with dynamic constructs such as loops and conditionals. Its syntax is similar to template engines commonly used in web applications.

The example creates a JSON document containing the names and values of the request's HTTP headers.

- template:
    contentType: application/json
    pretty: true
    src: |
      {
        <% header.eachWithIndex { e, i -> %>
          <% if (i > 0) { %>,<% } %>
          <%= e.key %>: <%= e.value %>
        <% } %>
      }

Templates can access message data using JSONPath, XPath, and Groovy.

6. Orchestration and Call Outs

Membrane can orchestrate calls to external APIs and process collections with loops and conditional flows.

The example iterates over a list of fruits and sends a POST request for each item:

api:
  port: 2000
  flow:
    - for:
        # Loops over a list of objects [{ "name": "Mango", "price": 1.23 }, ..]
        in: $.fruits
        language: jsonpath
        flow:
          - setBody:
              # Serialize the current item to a JSON string
              value: ${toJSON(it)}
          # callout to an external API
          - call:
              method: POST
              url: https://api.predic8.de/shop/v2/products
          - log:
              message: "Created product: ${it['name']}"
    - return:
        status: 200

See orchestration tutorials

7. Scripting

Scripts can inspect and modify requests, responses, and extend gateway behavior. This makes it possible to implement custom API logic for use cases such as:

  • Routing: Load balance requests across multiple backends
  • Error Handling: Create custom error responses
  • Orchestration: Chain multiple APIs together to form a complex workflow
  • Creating Responses: Tailor responses dynamically based on client requests or internal logic.
  • Mocking APIs: Simulate API behavior during testing or development phases.
  • Debugging and Tracing: Inspect incoming requests during development.
api:
  port: 2000
  flow:
    - groovy:
        src: |
          println "I'm executed in the ${flow} flow"
          println "HTTP Headers:\n${header}"
  target:
    url: https://api.predic8.de

You can write scripts in Groovy and JavaScript.

Conditional Processing With the ´if´-Statement

A Membrane flow does not have to follow a fixed sequence. The if and choose plugins let you execute parts of a flow only when specific conditions are met. A common use case is error handling.

api:
  port: 2000
  flow:
    - response:
        - if:
            test: statusCode >= 500
            flow:
              - static:
                  src: Failure!
  target:
    url: https://httpbin.org/status/500

8. Security

Membrane provides security features for protecting APIs, services, and backend systems.

API Keys

Incoming requests can be authenticated by validating an API key against keys stored in a file or database.

global:
  - apiKey:
      stores:
        - simple:
            - secret:
                value: aed8bcc4-7c83-44d5-8789-21e4024ac873
            - secret:
                value: 08f121fa-3cda-49c6-90db-1f189ff80756
      extractors:
        - header: X-Api-Key

Membrane also supports:

  • Defining permissions as scopes in OpenAPI and enforcing them with API keys.
  • Extracting API keys from headers, query parameters, or custom locations using expressions.
  • Role-based access control (RBAC) with fine-grained permissions.

See the API Key Tutorials

JSON Web Tokens

The API below only allows requests that present a valid JSON Web Token issued by Microsoft Azure Entra ID.

api:
  port: 2000
  flow:
    - jwtAuth:
        expectedAud: api://2axxxx16-xxxx-xxxx-xxxx-faxxxxxxxxf0
        jwks:
          jwksUris: https://login.microsoftonline.com/common/discovery/keys
  target:
    url: https://your-backend

OAuth2

Secure APIs with OAuth2

Use OAuth2/OpenID to secure endpoints against Google, Azure Entra ID, GitHub, Keycloak or Membrane Authentication Servers.

api:
  port: 2000
  flow:
    - oauth2Resource2:
        membrane:
          src: http://localhost:8000
          clientId: abc
          clientSecret: def
          scope: openid profile
          claims: username
          claimsIdt: sub
    - request:
        # Forward the authenticated user’s email to the backend in an HTTP header.
        - setHeader:
            name: X-EMAIL
            value: ${property['membrane.oauth2'].userinfo['email']}
  target:
    url: http://backend

Try the OAuth tutorial

Membrane as Authorization Server

The following example shows a minimal configuration for running Membrane as an OAuth 2.0 authorization server.

api:
  port: 8000
  flow:
    - oauth2authserver:
        issuer: http://localhost:8000
        location: logindialog
        consentFile: consentFile.json
        staticUserDataProvider:
          users:
            - username: john
              password: secret
              email: john@predic8.de
        staticClientList:
          clients:
            - clientId: abc
              clientSecret: def
              callbackUrl: http://localhost:2000/oauth2callback
        bearerToken: {}
        claims:
          value: aud email iss sub username
          scopes:
            - id: username
              claims: username
            - id: profile
              claims: username email

User accounts can be stored in a file, in an LDAP server or backed by a database.

SSL/TLS

This example enables TLS for connections from clients to the API Gateway:

api:
  port: 443
  ssl:
    keystore:
      location: keystore.p12
      password: changeit
    truststore:
      location: keystore.p12
      password: changeit
  target:
    url: http://backend

Membrane supports advanced TLS scenarios, including:

  • TLS termination at the API Gateway with optional TLS forwarding to the backend.
  • SNI-based routing.
  • Routing TLS connections without decrypting them.

See the TLS/SSL tutorial

XML, JSON, JSON-RPC and GraphQL Protection

Membrane protects APIs from risks associated with XML, JSON, JSON-RPC and GraphQL payloads.

api:
  port: 2000
  flow:
    - xmlProtection:
        maxAttributeCount: 3
        maxElementNameLength: 100
        removeDTD: true
    - return:
        status: 200

See the XML protection, JSON protection , JSON-RPC protection, and GraphQl protection references.

9. Traffic Control

Rate Limiting

Limit the number of incoming requests within a defined time period:

global:
  - rateLimiter:
      requestLimit: 1000
      requestLimitDuration: PT1H

Load Balancing

Distribute the workload across multiple API backend nodes.

api:
  port: 8080
  flow:
    - balancer:
        clusters:
          - name: Default
            nodes:
              - host: my.backend-1
                port: 4000
              - host: my.backend-2
                port: 4000
              - host: my.backend-3
                port: 4000

See the API loadbalancing examples

10. Operation

Monitoring with Prometheus and Grafana

Expose Membrane metrics for Prometheus:

api:
  port: 2000
  path:
    uri: /metrics
  flow:
    - prometheus: {}

The collected metrics can be visualized in a Grafana dashboard:

Grafana Dashboard for Membrane API Gateway

OpenTelemetry Integration

Membrane supports integration with OpenTelemetry. This enables detailed tracing of requests across Membrane and backend services.

OpenTelemetry Example

For working examples of Prometheus, Grafana and OpenTelemetry see the operation tutorial.

Community and Enterprise Support

Community Support

To get support from our community, post your questions to our discussions page @GitHub.

If you find a bug, report it using GitHub Issues. Please provide a minimal example that reproduces the issue and the version of Membrane you are using.

Enterprise-Grade Support

See commercial support options and pricing.

API Gateway eBook(Free Download)

Learn how API Gateways work through practical scenarios and real-world examples.

API Gateway eBook Cover

Download instantly. No registration required.

Participate in the API Tech Talk

Meet other Membrane users online to discuss API gateway operation and architecture. Membrane developers answer questions and welcome your feedback and feature requests.

Upcoming Topics

  • September 30, 2026 Legacy Integration with XML, SOAP, and WSDL
  • October 28, 2026 Authentication with JSON Web Tokens (JWT)
  • November 25, 2026 MCP and AI Tool Integration
  • December 30, 2026 Message Transformation

Learn more

About

Java-based API Gateway bridging legacy and modern APIs with WSDL-to-OpenAPI, SOAP-to-REST, XML, OAuth2, and GraphQL.

Topics

Resources

Security policy

Stars

641 stars

Watchers

42 watching

Forks

Releases

Used by

Contributors

Languages