# Advanced Communication Protocols Source: https://tyk.io/docs/advanced-configuration/other-protocols Learn how to configure advanced communication protocols in Tyk, including TCP, gRPC, and WebSockets ## Overview Tyk API Gateway is primarily designed to handle HTTP/HTTPS traffic, but it also provides robust support for several other protocols to accommodate modern API architectures and communication patterns. This flexibility allows developers to leverage Tyk's security, monitoring, and management capabilities across a wider range of API technologies. ### Use Cases These advanced protocol capabilities enhance Tyk's usefulness beyond traditional REST APIs: * **Real-time Applications**: WebSockets enable bidirectional communication for chat applications, collaborative tools, and live dashboards. * **Microservices Communication**: gRPC support facilitates efficient inter-service communication with strong typing and performance benefits. * **Event-Driven Architectures**: SSE enables efficient server-push notifications without the overhead of maintaining WebSocket connections. ## Supported Protocols Tyk currently supports the following protocols other than HTTP/HTTPS: 1. **[TCP Proxy](/docs/key-concepts/tcp-proxy)** 2. **[gRPC](/docs/key-concepts/grpc-proxy)** 3. **[Server-Sent Events (SSE)](/docs/advanced-configuration/sse-proxy)** 4. **[WebSockets](/docs/advanced-configuration/websockets)** # Server Sent Events Proxy Source: https://tyk.io/docs/advanced-configuration/sse-proxy Learn how to use Tyk as a simple Server-Sent Events (SSE) Proxy [Server-Sent Events](https://en.wikipedia.org/wiki/Server-sent_events) (SSE) is a server push technology enabling a subscribed client to receive automatic updates from a server via a long running HTTP connection. Unlike WebSockets, SSE is a one-way communication of server to clients (WebSockets is a bidirectional communication between server and client). As such, if you only need clients to receive data from a server, and don't require them sending messagess back, SSE could be a simpler way to make that happen. An online stock quotes, or notifications and feeds are good examples for applications that use SSE. ## Using Tyk as a server-sent events (SSE) Proxy Tyk Gateway supports SSE proxying over HTTP, and can sit in the middle between the client and the SSE server and support the server sending updates to the client. ### Setup * Enable SSE support on the Gateway: Set `http_server_options.enable_websockets` to `true` in your Tyk Gateway config file. * To maintain an open connection between the API consumer and the Tyk Gateway, set `http_server_options.read_timeout` and `http_server_options.write_timeout` to appropriately high values (in milliseconds). For example, you could try setting both to `2000`, but this is for you to determine in your environment. `flush_interval` does not need to be configured for SSE APIs. The Gateway automatically handles immediate flushing for `text/event-stream` responses. ### Example using Tyk as an SSE proxy For this we will need: * An SSE server. For this example we will use [Golang HTML 5 SSE example](https://github.com/kljensen/golang-html5-sse-example) * An instance of the Tyk Gateway and optionally the Tyk Dashboard **Steps for Configuration:** * Ensure the Gateway configurations detailed in the Setup section are set. * Run the SSE server as per the example instructions. By default this runs on port `8000`. ``` go run ./server.go ``` * Publish an API with the following configuration: 1. Set an appropriate listen path, e.g. `"listen_path": "/sse"` 2. Strip the listen path, e.g. `"strip_listen_path": true,` 3. Set the target url as the SSE server, e.g. the example SSE server:`"target_url": "http://host.docker.internal:8000"` 4. Click Save, and wait for the Gateway to reload the API before testing it * To test the protected SSE service via the API in the Tyk Gateway run: ```bash theme={null} curl http://localhost:8080/sse/events/ ``` You should see a stream of updates from the server. In this example, you will see: ```bash theme={null} Message: 20 - the time is 2013-03-08 21:08:01.260967 -0500 EST Message: 21 - the time is 2013-03-08 21:08:06.262034 -0500 EST Message: 22 - the time is 2013-03-08 21:08:11.262608 -0500 EST ``` # Websockets Source: https://tyk.io/docs/advanced-configuration/websockets Learn how to configure and use WebSockets with Tyk As from Tyk gateway v2.2, Tyk supports transparent WebSocket connection upgrades. To enable this feature, set the `enable_websockets` value to `true` in your `tyk.conf` file. WebSocket proxying is transparent, Tyk will not modify the frames that are sent between client and host, and rate limits are on a per-connection, not per-frame basis. The WebSocket upgrade is the last middleware to fire in a Tyk request cycle, and so can make use of HA capabilities such as circuit breakers and enforced timeouts. Tyk needs to decrypt the inbound and re-encrypt the outbound for the copy operations to work, Tyk does not just pass through the WebSocket. When the target is on default SSL port you must explicitly specify the target url for the API: ```{.copyWrapper} theme={null} https://target:443/ ``` ## WebSocket Example We are going to set up Tyk with a WebSocket proxy. Set up Tyk using our Docker [guide](/docs/tyk-self-managed/install/docker). We will be using the [Postman WebSocket Echo Service](https://blog.postman.com/introducing-postman-websocket-echo-service/) to test the connection. **Steps for Configuration** 1. **Setup the API in Tyk** Create a new API in Tyk. For this demo we are going to select Open (Keyless) as the **Authentication mode**. Set the **Target URL** to `wss://ws.postman-echo.com/raw` 2. **Test the Connection** 1. From Postman, select **File > New > WebSocket Request** (or from **Workspace > New > WebSocket Request** if using the web based version). Postman WebSocket Request 2. Enter your Tyk API URL in the **Enter server URL** field (minus the protocol). 3. Enter some text in the **New Message** field and click **Send**. 4. You will see a successful connection. Postman WebSocket Connection Result If your API uses an Authentication mode other than Open (Keyless), add the details in the Header tab. An example Header configuration for using an Authentication Token with an API: Postman WebSocket Connection Result with Authorization token See the [Access an API](/docs/api-management/gateway-config-managing-classic#access-an-api) tutorial for details on adding an Authentication Token to your APIs. # Natural-language interaction with Tyk Docs (MCP) Source: https://tyk.io/docs/ai-management/mcps/tyk-docs-mcp Connect an MCP client to Tyk documentation for semantic search and doc-backed answers, with setup steps for popular AI assistants. ## Overview Tyk Docs [MCP](https://modelcontextprotocol.io/introduction) exposes the Tyk documentation to AI assistants. Instead of searching manually, users can ask natural-language questions and get answers backed by Tyk docs. The tool makes AI-assisted support, troubleshooting, and documentation exploration fast and reliable. Here you can see the AI assistant chooses to use Tyk Docs MCP (*Cline* in VS Code) while answering the query *How do I set a rate limit for a Tyk API?*: Screenshot of the response to request of AI to create a new user Screenshot of the response to request of AI to create a new user ## Key Features * **Semantic search** — finds the most relevant content, not just keyword matches * **Contextual results** — includes sections around your result for better understanding * **Product filters** — limit results by product (Gateway, Dashboard, etc.) * **Includes links** — jump straight into the relevant section of the docs * **Answer snippets** — shows concise answers when possible * **Always up to date** — syncs with the latest Tyk documentation ## Use Cases Let AI do the digging — here’s how teams use Tyk Docs MCP: * **First-line support** - *How do I set a rate limit for a Tyk API?*
AI can help answer questions about Tyk products, features, and usage cases. * **Feature implementation help** - *How do I enable JWT authentication in Tyk Gateway?*
AI can help developers use Tyk's features by providing ad hoc step-by-step instructions and examples. * **Troubleshooting guidance** - *I'm seeing 'Auth field missing' error. What does that mean?*
AI can help identify issues and provide guidance on how to resolve them. * **Fast API reference** - *What fields are in the /apis response?*
AI can help developers quickly find the information they need to implement Tyk's features. * **Discover what’s possible** - *What analytics tools does Tyk include?*
AI can help developers discover new ways to use Tyk's features and capabilities. ## Quick Start To get started, connect your AI assistant to the Tyk Docs MCP server, which is hosted remotely at `https://tyk.io/docs/mcp`. ### Requirements * [Node.js v18+](https://nodejs.org/en/download) installed (needed to run `npx`) * Internet access to reach `tyk.io` * An MCP-compatible AI assistant, such as Claude Code, Claude Desktop, Cursor, VS Code, or Codex ### Configure your AI Assistant **Step 1.** The easiest way to connect is the [`add-mcp`](https://github.com/neon-solutions/add-mcp) CLI. It detects the AI assistants installed on your machine and adds the server to whichever ones you choose: ```bash theme={null} npx add-mcp https://tyk.io/docs/mcp ``` You can also click **Add MCP** in the menu at the top of any Tyk Docs page to get the same command, pre-filled for that page. Mintlify Context Menu Options If your assistant supports remote HTTP MCP servers but isn't detected automatically, add the server to its MCP configuration manually instead: ```json theme={null} { "mcpServers": { "tyk-docs": { "type": "http", "url": "https://tyk.io/docs/mcp" } } } ``` **Step 2.** Once connected, ask the AI to perform an operation as suggested in the [use cases above](#use-cases). ## How It Works Under the Hood Tyk Docs MCP is Mintlify's built-in MCP server for the Tyk Documentation site. It indexes the live, published documentation, so results always reflect the current content, with no local package to install or keep up to date. Aside from a `submit_feedback` tool, which lets a connected assistant report a documentation issue such as an incorrect, outdated, or confusing page directly to the Tyk docs team, the server is read-only. # Gateway and API Sharding Source: https://tyk.io/docs/api-management/api-sharding Learn how to segment a Tyk cluster into zones using node and segment tags, so that specific Gateways selectively load specific APIs ## What is API Sharding ? It is possible to use tags in various Tyk objects to change the behavior of a Tyk cluster or to modify the data that is sent to the analytics engine. Tags are free-form strings that can be embedded in Gateway configurations, API definitions, Policies and Individual Keys. Tags are used in two ways: To segment a cluster into various "zones" of API management, and secondly, to push more data into the analytics records to make reporting and tracking easier. ### API Sharding API Sharding is what we are calling our approach to segmenting a Tyk cluster (or data centers) into different zones. An example of this in action would be to imagine you have separate VPCs that deal with different classes of services, lets say: Health, Banking and Pharma. You don't need the nodes that handle all the traffic for your Pharma APIs to load up the definitions for the other zones' services, this could allow someone to send unexpected traffic through (it may not go anywhere). Alternatively, you could use segmentation to have separate API definitions for multiple data centers. In this way you could shard your API definitions across those DC's and not worry about having to reconfigure them if there is a failover event. ### Using Sharding to handle API life-cycle with multiple data centers You can use sharding to very quickly publish an API from a `development` system to `staging` or `live`, simply by changing the tags that are applied to an API definition. With Tyk Community Edition and Tyk Pro, these clusters must all share the same Redis DB. If you are an Enterprise user, then you can go a step further and use the [Tyk Multi Data Center Bridge](/docs/api-management/mdcb#managing-geographically-distributed-gateways-to-minimize-latency-and-protect-data-sovereignty) to have full multi-DC, multi-zone cluster segmentation, and manage APIs in different segments across different database back-ends. ### Analytics and Reporting In order to use tags in analytics, there are two places where you can add a `"tags":[]` section: a Policy Definition, and a Session object for a token. Policy tags completely replace key tags, these tags are then fed into the analytics system and can be filtered in the dashboard. ### Node Tags If your API is segmented, node tags will be appended to the analytics data, this will allow you to filter out all traffic going through a specific node or node cluster. If you set `use_db_app_options.node_is_segmented` to `true` for multiple gateway nodes, you should ensure that `management_node` is set to `false`. This is to ensure visibility for the management node across all APIs. `management_node` is available from v2.3.4 and onwards. See [Tyk Gateway Configuration Options](/docs/tyk-oss-gateway/configuration) for more details on node tags. ## Gateway Sharding With Tyk, it is easy to enable a sharded configuration, you can deploy Gateways which selectively load APIs. This unlocks abilities to run Gateways in multiple zones, all connected to the same Control Plane. This allows for GDPR deployments, development/test Gateways, or even DMZ/NON-DMZ Gateways. Couple this functionality with the Tyk [Multi Data Center Bridge](/docs/api-management/mdcb#managing-geographically-distributed-gateways-to-minimize-latency-and-protect-data-sovereignty) to achieve a global, multi-cloud deployment. ### Configure a Gateway as a shard Setting up a Gateway to be a shard, or a zone, is very easy. All you do is tell the node in the tyk.conf file what tags to respect and that it is segmented: ```{.copyWrapper} theme={null} ... "db_app_conf_options": { "node_is_segmented": true, "tags": ["qa", "uat"] }, ... ``` Tags are always treated as OR conditions, so this node will pick up all APIs that are marked as `qa` or `uat`. In order to expose more details about the Gateway to the Dashboard, you can now configure the [edge\_endpoints](/docs/tyk-dashboard/configuration#edge_endpoints) section in the tyk-analytics.conf, and the Dashboard UI will pick that up and present you a list of Gateways you can chose from when creating an API. ### Tag an API for a shard using the Dashboard From the API Designer, select the **Advanced Options** tab: Advanced options tab Scroll down to the **Segment Tags** options: Segment tags section Set the tag name you want to apply, and click **Add**. When you save the API, the tags will become immediately active. If any Gateways are configured to only load tagged API Definitions then this configuration will only be loaded by the relevant Gateway. ### Tag an API for a shard using Tyk Operator Add the tag names to the tags mapping field within an API Definition as shown in the example below: ```yaml {linenos=table,hl_lines=["8-9"],linenostart=1} theme={null} apiVersion: tyk.tyk.io/v1alpha1 kind: ApiDefinition metadata: name: httpbin spec: name: httpbin use_keyless: true tags: - edge protocol: http active: true proxy: target_url: http://httpbin.org listen_path: /httpbin strip_listen_path: true ``` ### Exposed Gateway tags to Dashboard UI From version 3.2.2 of the Tyk Dashboard, if [edge\_endpoints](/docs/tyk-dashboard/configuration#edge_endpoints) are being configured in tyk-analytics.conf, your Dashboard will automatically pick that list up for you, and display it in the UI when you create your API. List of available Gateways Once you select one or more Gateways, the *Segment Tags* section will be automatically prefilled with the tag values from the `edge_endpoints` configuration. List of segment tags Also, for every Gateway selected, there will be an API URL presented at the top of the page, within the *Core Settings* tab. List of API URLs ### Target an API Definition via JSON In your API definition, add a tags section to the root of the API Definition: ```{.copyWrapper} theme={null} "tags": ["private-gw"] ``` This will also set the tags for the API and when API requests are made through this Gateway, these tags will be transferred in to the analytics data set. ### API Tagging with On-Premises API Sharding with Self-Managed is very flexible, but it behaves a little differently to sharding with Tyk Cloud Hybrid & Tyk Global Self-Managed deployments. The key difference is that with the latter, you can have federated Gateway deployments with **their own redis databases**. However with Tyk Self-Managed the zoning is limited to tags only, and must share a single Redis database. To isolate Self-Managed Gateway installations across data centers you will need to use Tyk Multi Data Center Bridge component. This system powers the functionality of Tyk Cloud & Tyk Cloud Hybrid in our cloud and is available to our enterprise customers as an add-on. # Basic Authentication Source: https://tyk.io/docs/api-management/authentication/basic-authentication How to configure basic authentication in Tyk? ## What is Basic Authentication? Basic Authentication is a straightforward authentication method where the user's credentials (username and password) are sent to the server, usually in a standard HTTP header. ## How does Basic Authentication Work? The user credentials are combined and encoded in this form: ``` Basic base64Encode(username:password) ``` A real request could look something like: ``` GET /api/widgets/12345 HTTP/1.1 Host: localhost:8080 Authorization: Basic am9obkBzbWl0aC5jb206MTIzNDU2Nw== Cache-Control: no-cache ``` In this example the username is `john@smith.com` and the password is `1234567` (see [base64encode.org](https://www.base64encode.org)) ### The Problem with Basic Authentication With Basic Authentication, the authentication credentials are transferred from client to server as encoded plain text. This is not a particularly secure way to transfer the credentials as it is highly susceptible to intercept; as the security of user authentication is usually of critical importance to API owners, Tyk recommends that Basic Authentication should only ever be used in conjunction with additional measures, such as [mTLS](/docs/api-management/implement-tls#secure-hosted-apis-with-mtls). ## Configuring your API to use Basic Authentication The OpenAPI Specification indicates the use of [Basic Authentication](https://swagger.io/docs/specification/v3_0/authentication/basic-authentication/) in the `components.securitySchemes` object using the `type: http` and `scheme: basic`: ```yaml theme={null} components: securitySchemes: myAuthScheme: type: http scheme: basic security: - myAuthScheme: [] ``` With this configuration provided by the OpenAPI description, all that is left to be configured in the Tyk Vendor Extension is to enable authentication, to select this security scheme and to indicate where Tyk should look for the credentials. Usually the credentials will be provided in the `Authorization` header, but Tyk is configurable, via the Tyk Vendor Extension, to support custom header keys and credential passing via query parameter or cookie. ```yaml theme={null} x-tyk-api-gateway: server: authentication: enabled: true securitySchemes: myAuthScheme: enabled: true header: enabled: true name: Authorization ``` Note that URL query parameter keys and cookie names are case sensitive, whereas header names are case insensitive. You can optionally [strip the user credentials](/docs/api-management/client-authentication#managing-authorization-data) from the request prior to proxying to the upstream using the `authentication.stripAuthorizationData` field (Tyk Classic: `strip_auth_data`). ### Multiple User Credential Locations The OpenAPI Specification's `securitySchemes` mechanism allows only one location for the user credentials, but in some scenarios an API might need to support multiple potential locations to support different clients. The Tyk Vendor Extension supports this by allowing configuration of alternative locations in the basic auth entry in `server.authentication.securitySchemes`. Building on the previous example, we can add optional query and cookie locations as follows: ```yaml theme={null} x-tyk-api-gateway: server: authentication: enabled: true securitySchemes: myAuthScheme: enabled: true header: enabled: true name: Authorization query: enabled: true name: query-auth cookie: enabled: true name: cookie-auth ``` ### Extract Credentials from the Request Payload In some cases, for example when dealing with SOAP, user credentials can be passed within the request body rather in the standard Basic Authentication format. You can configure Tyk to handle this situation by extracting the username and password from the body using regular expression matching (regexps). You must instruct Tyk to check the request body by adding the `extractCredentialsFromBody` field to the basic auth entry in `server.authentication.securitySchemes`, for example: ```yaml theme={null} x-tyk-api-gateway: server: authentication: enabled: true securitySchemes: myAuthScheme: enabled: true extractCredentialsFromBody: enabled: true userRegexp: '(.*)' passwordRegexp: '(.*)' ``` Note that each regexp should contain only one match group, which must point to the actual values of the user credentials. ### Caching User Credentials The default behaviour of Tyk's Basic Authentication middleware is to cache user credentials, improving the performance of the authentication step when a client makes frequent requests on behalf of the same user. When a request is received, it presents credentials which are checked against the users registered in Tyk. When a match occurs and the request is authorized, the matching credentials are stored in a cache with a configurable refresh period. When future requests are received, Tyk will check the presented credentials against those in the cache first, before checking the full list of registered users. The cache will refresh after `cacheTTL` seconds (Tyk Classic: `basic_auth.cache_ttl`). If you do not want to cache user credentials, you can turn this off using `disableCaching` in the basic auth entry in `server.authentication.securitySchemes` (Tyk Classic: `basic_auth.disable_caching`). ### Using Tyk Classic APIs As noted in the Tyk Classic API [documentation](/docs/api-management/gateway-config-tyk-classic#configuring-authentication-for-tyk-classic-apis), you can select Basic Authentication using the `use_basic_auth` option. This will default to expect the user credentials in the `Authorization` header. ## Using Tyk Dashboard to Configure Basic Authentication Using the Tyk Dashboard, you can configure the Basic Authentication method from the Server section in the API Designer by enabling **Authentication** and selecting **Basic Authentication** from the drop-down: Target Details: Basic Auth * select the location(s) where Tyk should look for the token * provide the key name for each location (we prefill the default `Authorization` for the *header* location, but you can replace this if required) * optionally select [strip authorization data](/docs/api-management/client-authentication#managing-authorization-data) to remove the auth token locations from the request prior to proxying to the upstream * optionally configure the [basic authentication cache](/docs/api-management/authentication/basic-authentication#caching-user-credentials) * optionally configure [extraction of credentials from the request body](#extract-credentials-from-the-request-payload) ## Registering Basic Authentication User Credentials with Tyk When using Basic Authentication, the API key used to access the API is not generated by the Tyk system, instead you need to create and register the credentials of your users with Tyk. Tyk will compare the credentials provided in the request against the list of users you have created. The way that this is implemented is through the creation of a key that grants access to the API (as you would for an API protected by [auth token](/docs/api-management/authentication/bearer-token)), however for this key you will provide a username and password. When calling the API, users would never use the key itself as a token, instead their client must provide the Basic Auth credentials formed from the registered username and password, as [described previously](#how-does-basic-authentication-work). ### Using Tyk Dashboard UI You can use the Tyk Dashboard to register a user's Basic Authentication credentials that can then be used to access your API. Navigate to the **Keys** screen and select **Add Key**. Follow the instructions in the [access key guide](/docs/api-management/gateway-config-managing-classic#access-an-api) and you'll notice that, when you select the Basic Auth protected API, a new **Authentication** tab appears: Note that the **Authentication** tab will also be displayed if you create a key from a policy that grants access to a Basic Auth protected API. Complete the user's credentials on this tab and create the key as normal. The key that is created in Tyk Dashboard is not in itself an access token (that is, it cannot be used directly to gain access to the API) but is used by Tyk to validate the credentials provided in the request and to determine the appropriate authorization, including expiry of authorization. ### Using the Tyk Dashboard API You can register user credentials using the `POST /api/apis/keys/basic/{username}` endpoint in the [Tyk Dashboard API](/docs/tyk-dashboard-api). The request payload is a [Session Object](/docs/api-management/access-control/sessions-and-keys/understanding-sessions). * the user's *username* is provided as a path parameter * the user's *password* is provided as `basic_auth_data.password` within the request payload You use the `POST` method to create a new user and `PUT` to update an existing entry. Be careful to ensure that the `org_id` is set correctly and consistently so that the Basic Authentication user is created in the correct organization. ### Using the Tyk Gateway API You can register user credentials using the `POST /tyk/keys/{username}` endpoint in the [Tyk Dashboard API](/docs/tyk-dashboard-api). The request payload is a [Session Object](/docs/api-management/access-control/sessions-and-keys/understanding-sessions). * the user's *username* is provided as a path parameter * the user's *password* is provided as `basic_auth_data.password` within the request payload You use the `POST` method to create a new user and `PUT` to update an existing entry. Be careful to ensure that the `org_id` is set correctly and consistently so that the Basic Authentication user is created in the correct organization. # Authentication Token Source: https://tyk.io/docs/api-management/authentication/bearer-token How to use Authentication Tokens to Secure APIs ## Introduction [IETF RFC6750](https://datatracker.ietf.org/doc/html/rfc6750) opens with: > Any party in possession of a bearer token (a "bearer") can use it to get access to the associated resources (without demonstrating possession of a cryptographic key). To prevent misuse, bearer tokens need to be protected from disclosure in storage and in transport. The bearer token is a cryptic string, usually generated by the server. When the client makes a request to consume an API on the server, it must send this token in a header, typically as: `Authorization: Bearer `. When the server receives the token, it checks its validity and authentcates that the "bearer" of the token is the entity to which the token was issued. The [OpenAPI Specification](https://swagger.io/docs/specification/v3_0/authentication/api-keys/) defines an API Key as: > a token that a client provides when making API calls. API keys are supposed to be a secret that only the client and server know ... API key-based authentication is only considered secure if used together with other security mechanisms such as HTTPS/SSL. Bearer Token, API Key, Authentication Token... from the perspective of Tyk these are different names for the same thing: a "token" string that can be used to access an API secured using Tyk's **Auth Token** authentication method. ### An Overview of the Auth Token method Tyk's "Auth Token" authentication method is a flexible mechanism that functions like a Bearer Token but is defined as an 'API Key' according to OpenAPI 3.0 standards. * Tyk Gateway issues Auth Tokens (called **Keys** in the Tyk Dashboard App) * For each token, a session state object is created with the Redis key containing the token string * this session object contains details of the access rights and consumption limits to be applied to the client presenting the token * The client can present the token in a header, query parameter or cookie * the location is configurable within the API definition * The `Bearer` identifier is optional when using a header for the token * When the token is presented, it is used as a simple key lookup against the Redis keys and validated if a matching session object is found * From Tyk 5.12.0 the token can be [bound to a client certificate](/docs/api-management/authentication/bearer-token#client-certificate-token-binding) to provide an extra layer of authentication security * when this is in use, Tyk validates that the certificate presented with the token matches that bound to the session ## Configuring your API to use Auth Token The OpenAPI Specification indicates the use of Auth Tokens (API Keys) in the `components.securitySchemes` object using `type: apiKey`. It also includes specification of the location (`in`) and key (`name`) that are to be used when providing the token to the API, for example: ```yaml theme={null} components: securitySchemes: myAuthScheme: type: apiKey in: header name: Authorization security: - myAuthScheme: [] ``` With this configuration provided by the OpenAPI description, all that is left to be configured in the Tyk Vendor Extension is to enable authentication and to select this security scheme. ```yaml theme={null} x-tyk-api-gateway: server: authentication: enabled: true securitySchemes: myAuthScheme: enabled: true ``` Note that URL query parameter keys and cookie names are case sensitive, whereas header names are case insensitive. You can optionally [strip the auth token](/docs/api-management/client-authentication#managing-authorization-data) from the request prior to proxying to the upstream using the `authentication.stripAuthorizationData` field (Tyk Classic: `strip_auth_data`). ## Multiple Auth Token Locations The OpenAPI Specification's `securitySchemes` mechanism allows only one location for the auth token, but in some scenarios an API might need to support multiple potential locations to support different clients. The Tyk Vendor Extension supports this by allowing configuration of alternative locations in the auth token entry in `server.authentication.securitySchemes`. Building on the previous example, we can add optional query and cookie locations as follows: ```yaml theme={null} x-tyk-api-gateway: server: authentication: enabled: true securitySchemes: myAuthScheme: enabled: true query: enabled: true name: query-auth cookie: enabled: true name: cookie-auth ``` ## Client Certificate - Token Binding In **Tyk 5.12.0** we introduced an option when combining the Auth Token method with [static mTLS](/docs/api-management/implement-tls#using-a-static-client-certificate-allow-list) to form a binding association between the Auth Token issued to a client and their client certificate. This works as follows: 1. The client certificate must first be registered with the Tyk Certificate Store and added to the statically declared *allow list* in the API definition, the act of doing this enforces the mTLS handshake for requests to the API. 2. When the Auth Token is issued by Tyk, the certificate is bound to the session object that is created in Redis (the certificateID is stored in the [`mtls_static_certificate_bindings`](/docs/api-management/access-control/sessions-and-keys/understanding-sessions#authentication-data) field in the Session) 3. When a request is made by the client, they must provide a certificate to satisfy the mTLS handshake. This certificate is then checked against the allow list in the API definition and then the binding in the session object. If it is not present in the allow list or not in the bound certificates list, authentication will fail and the request will be rejected. Multiple client certificates can be bound to a token, for additional flexibility. Proactive maintenance of the list of bound certificates supports seamless rotation of certificates, as the new certificate can be registered and bound prior to the client switching to use it. This feature is fully backward-compatible. Existing tokens that do not have certificate bindings will continue to work as before, as the binding check is simply skipped. No additional configuration is required in the Tyk Gateway configuration nor in the API Definition. Policies do not currently support certificate-token binding. This will be added in a future release. ## Dynamic mTLS with Auth Token The Auth Token method can support [Dynamic mTLS](/docs/api-management/implement-tls#using-a-dynamic-client-certificate-allow-list) where the client can provide a TLS certificate in lieu of a standard Auth Token. This can be configured for an API using the [enableClientCertificate](/docs/api-management/gateway-config-tyk-oas#token) option (Tyk Classic: `auth.use_certificate`). You can use your own identity provider to generate access tokens, then import them to Tyk via `POST /tyk/keys/{keyID}` in the Tyk Gateway API. This lets Tyk manage access control, quotas, and rate limiting for you. ## Legacy Options ### Dynamic mTLS with Auth Token *Dynamic mTLS* became a standalone authentication method in Tyk 5.12.0 and is now more accurately called [Certificate Authentication](/docs/api-management/authentication/certificate-auth) Prior to Tyk 5.12.0, [Dynamic mTLS](/docs/api-management/implement-tls#using-a-dynamic-client-certificate-allow-list) was configured via the Auth Token method by setting the `enableClientCertificate` flag (Tyk Classic: `auth_configs.authToken.use_certificate`). ```json theme={null} server: authentication: enabled: true securitySchemes: authToken: enabled: true enableClientCertificate: true ``` This was later changed to Certificate Authentication, as explained [here](/docs/api-management/implement-tls#legacy-dynamic-mtls-mode). ### Auth Token with Signature If you are migrating from platforms like Mashery, which use request signing, you can enable signature validation alongside auth token by configuring the additional [signatureValidation](/docs/api-management/gateway-config-tyk-oas#token) field (Tyk Classic: `auth.signature`). You can configure: * the location of the signature * the algorithm used to create the signature (`MasherySHA256` or `MasheryMD5`) * secret used during signature (which can be retrieved from the [Session metadata](/docs/api-management/access-control/sessions-and-keys/session-metadata)) * an allowable clock skew ## Using Tyk Dashboard to Configure Auth Token Using the Tyk Dashboard, you can configure the Auth Token authentication method from the Server section in the API Designer by enabling **Authentication** and selecting **Auth Token** from the drop-down: Configuring the Auth Token method * select the location(s) where Tyk should look for the token * provide the key name for each location (we prefill the default `Authorization` for the *header* location, but you can replace this if required) * select **Strip authorization data** to remove the auth token locations from the request prior to proxying to the upstream, as described [here](/docs/api-management/client-authentication#managing-authorization-data) Note that the [auth token + signature](/docs/api-management/authentication/bearer-token#auth-token-with-signature) option is not available in the Tyk Dashboard API Designer. ### Binding a Client Certificate to a Token Certificates are bound to tokens when the tokens are issued or when the session object is subsequently updated. When an API secured by Auth Token and mTLS is selected in the **Access Rights** tab of the **API Security > Keys** screen, an additional tab will be displayed: **Authentication**. Creating an API Key for an API secured with Auth Token and mTLS On the **Authentication** tab there is an option to bind certificates to the token: Optionally bind a client certificate to the API Key If you select this option, you can then select the client certificate to bind to the new token. You can choose from the existing client certificates in the Tyk Certificate Store or, if required, you can upload new certificates (in PEM format). Tyk will register these within the Tyk Certificate Store so that they are available for use. Select **Attach Certificate**. Uploading a client certificate to bind to the API Key The certificate will be added to a list of bound certificates. The new cert is shown in the list of bound certificates You can optionally add more certificates, or proceed to issue the key by selecting **Create Key**. You can add and remove certificate bindings for existing tokens from the **Update Key** screen: The new cert is shown in the list of bound certificates **Note** Binding a certificate to an Auth Token does not automatically add that certificate to the static allow list for the API(s) that the token is authorised to access. When a request is made using the token, the presented client certificate will be checked against the allow list after the mTLS handshake has completed and before the binding is checked. Authentication will fail if the certificate is not in the allow list. ## Using Tyk Classic APIs As noted in the Tyk Classic API [documentation](/docs/api-management/gateway-config-tyk-classic#configuring-authentication-for-tyk-classic-apis), a new Tyk Classic API will use the auth (bearer) token method by default with the token expected in the `Authorization` header, so configuration is slightly different as there is no need to `enable` this method. You should configure the `auth` object for any non-default settings, such as a different token location or Dynamic mTLS. # Certificate Authentication Source: https://tyk.io/docs/api-management/authentication/certificate-auth Authenticate using just an mTLS client certificate ## What is Certificate Authentication? Certificate Authentication is a client authentication method introduced in Tyk 5.12.0 that replaces the legacy [Dynamic mTLS](/docs/api-management/implement-tls#using-a-dynamic-client-certificate-allow-list) feature. This method provides enhanced security and flexibility for API authentication using client certificates. ### Evolution from Dynamic mTLS Certificate Authentication has evolved from Dynamic mTLS through the enforcement of the mutual TLS handshake and the disallowing of authentication using a token. Only the registered client certificate can now be used to authenticate with the Gateway. This change was introduced because Dynamic mTLS treated the certificate as optional and did not enforce the mTLS handshake. Mutual TLS was not enforced if only the token was presented in the request, reducing the security of the Dynamic mTLS authentication method. For more details, see [the problem with Dynamic mTLS](/docs/api-management/implement-tls#legacy-dynamic-mtls-mode). If you are currently using Dynamic mTLS, no change is required to your API definition to use Certificate Authentication. When using Tyk OAS APIs, the legacy configuration (`x-tyk-api-gateway.server.authentication.securitySchemes.authToken.enableClientCertificate`) is still supported (though marked as deprecated in favor of a new, cleaner configuration). When using Tyk Classic APIs, there is no change to the configuration in the API definition (`auth_configs.authToken.useCertificate`). The legacy mode (where the token can be used to authenticate with Tyk) is available via the Gateway configuration option `allow_unsafe_dynamic_mtls_token`. ## How does Certificate Authentication work? Certificate Authentication uses X.509 [client certificates](/docs/api-management/certificates#digital-certificates) to authenticate API requests. It relies upon a one-to-one mapping between API clients and client certificates. When a client makes a request: 1. The client presents their certificate during the mTLS handshake 2. If the client is successfully authenticated, Tyk checks the client certificate against a list of authorized certificates (the "dynamic allow list") 3. If a match is found, authorization proceeds as usual, based on the content of the linked session and any policies applied to it Each client certificate must be [pre-registered](/docs/api-management/authentication/certificate-auth#registering-certificate-authentication-user-credentials) with the [Tyk Certificate Store](/docs/api-management/certificates#tyk-certificate-store) and a [Session](/docs/api-management/access-control/sessions-and-keys/understanding-sessions) created for each in the in-memory database (Redis) to create the dynamic allow list. This list is dynamic because certificate-linked session objects (and hence clients) can be added to or removed from the list without making any change to the API definition. This is in contrast to the [static allow list](/docs/api-management/implement-tls#using-a-static-client-certificate-allow-list) approach where the list of authorized certificates is stored in the API definition. ## Configuring your API to use Certificate Authentication The Gateway must be configured to use TLS for the [hosted API interface](/docs/api-management/implement-tls#tyk-gateway-as-a-tls-server-inbound-connections). Certificate Auth is configured within the Tyk Vendor Extension by adding the `certificateAuth` object within the `server.authentication` section and enabling authentication. ```yaml theme={null} x-tyk-api-gateway: server: authentication: enabled: true certificateAuth: enabled: true ``` There are no additional configuration options for this authentication method. The client must present their certificate in the usual manner for the mTLS handshake, for example: ```bash theme={null} curl --cert client_cert.pem --key client_key.pem https://my-gateway/my-api/ ``` Note that the `HTTPS` protocol must be used. ### Using Tyk Classic As noted in the Tyk Classic API [documentation](/docs/api-management/gateway-config-tyk-classic#configuring-authentication-for-tyk-classic-apis), you can select Certificate Authentication using the `auth_configs.authToken.useCertificate` option. ## Using Tyk Dashboard to Configure Certificate Authentication Using the Tyk Dashboard, you can configure the Certificate Auth method from the Server section in the API Designer by enabling **Authentication** and selecting **Certificate Authentication** from the drop-down: Selecting Certificate Authentication in the Tyk OAS API Designer ## Registering Certificate Authentication User Credentials The *dynamic allow list* comprises session state objects in the Gateway's in-memory database (typically Redis) that reference the client certificates that should be accepted. 1. First you must [register](/docs/api-management/certificates#tyk-certificate-store-api) the client certificate with the Tyk Certificate Store and note the certificate ID that is assigned. 2. Next you *create a key*, providing the certificate ID in the `certificate` field of the session object payload. * Tyk Gateway API: `POST /tyk/keys/create` * Tyk Dashboard API: `POST /api/keys/create` 3. Tyk will create a session object with the Redis key containing the certificate ID, which forms part of the dynamic allow list. * The Redis key is formed from a combination of the Organization ID and Certificate ID * Deleting this object (key) will remove the certificate from the allow list, restricting access to any client presenting that certificate From the Tyk Dashboard UI, if you [create a key](/docs/getting-started/using-tyk-dashboard#api-security) that grants access to an API secured with a dynamic allow list, the **Authentication** tab will be displayed, where you can select the client certificate from the Tyk Certificate Store. Associating a client certificate with an API for Certificate Authentication # Custom Authentication Source: https://tyk.io/docs/api-management/authentication/custom-auth How to implement custom authentication in Tyk using Go plugins, Python CoProcess, and JSVM plugins. ## Go Plugins Go Plugin Authentication allows you to implement custom authentication logic using the Go programming language. This method is useful for scenarios where you need to implement specialized authentication mechanisms that are not natively supported by Tyk. To learn more about using Tyk Golang Plugins, go [here](/docs/api-management/plugins/golang) ## Use Python CoProcess and JSVM Plugin Authentication Tyk allows for custom authentication logic using Python and JavaScript Virtual Machine (JSVM) plugins. This method is useful for implementing unique authentication mechanisms that are tailored to your specific requirements. * See [Custom Authentication with a Python plugin](/docs/api-management/plugins/rich-plugins#custom-authentication-plugin-tutorial) for a detailed example of a custom Python plugin. * See [JavaScript Middleware](/docs/api-management/plugins/javascript#) for more details on using JavaScript Middleware. # JWT Authorization Source: https://tyk.io/docs/api-management/authentication/jwt-authorization Tyk Gateway's JWT Authorization process extracts user identity and applies security policies based on JWT claims for API access control. ## Availability | Component | Editions | | :- | :- | | Tyk Gateway | Community and Enterprise | ## Introduction [JSON Web Tokens (JWT)](https://www.jwt.io/introduction) are a popular method for client authentication and authorization that can be used to secure access to your APIs via Tyk's [JWT Auth](/docs/basic-config-and-security/security/authentication-authorization/json-web-tokens) method. After the JWT signature has been [validated](/docs/basic-config-and-security/security/authentication-authorization/json-web-tokens), Tyk uses the **claims** within the token to determine which security policies (access rights, rate limits and quotas) should be applied to the request. From Tyk 5.10, Tyk can perform optional [validation](/docs/api-management/authentication/jwt-claim-validation) of these claims. In this page, we explain how Tyk performs JWT authorization, including how it identifies the user and the policies to be applied. ## JWT Authorization Flow When a request with a JWT arrives at Tyk Gateway, after the authentication (signature and claim validation) step, Tyk performs the following steps to authorize the request: 1. **Identity Extraction**: The user identity is extracted from the token according to this order of precedence: * The `kid` header (unless `skipKid` is enabled) * A custom claim (specified in `subjectClaims`) * The standard `sub` claim (fallback) 2. **Policy Resolution**: Tyk determines which [Policy](/docs/api-management/policies) to apply to the request: * From scope-to-policy mapping * From default policies 3. **Update Session**: The [Session](/docs/api-management/access-control/sessions-and-keys/understanding-sessions) is updated with the identity and policies. In the following sections, we provide a detailed explanation of each of these steps. ## Identifying the Session Owner A unique identity is stored in the Session to associate it with the authenticated user. This identifier is extracted from the JWT by checking the following fields in order of precedence: 1. The standard Key ID header (`kid`) in the JWT (unless the `skipKid` option is enabled) 2. The subject identity claim identified by the value(s) stored in `subjectClaims` (which allows API administrators to designate any JWT claim as the identity source (e.g., user\_id, email, etc.). When multiple values are provided in the `subjectClaims` array, Tyk processes them as follows: 1. Tyk tries each claim **in the exact order they appear** in the array 2. For each claim, Tyk checks if: * The claim exists in the token * The claim value is a string and is not empty 3. Tyk uses the **first valid, non-empty value** it finds and stops processing further claims 4. If none of the claims yield a valid identity, Tyk proceeds to the next stage (the `sub` claim) Prior to Tyk 5.10, the subject identity claim was retrieved from `identityBaseField`; see [using multiple identity providers](#using-multiple-identity-providers) for details and for the Tyk Classic API alternative. 3. The `sub` [registered claim](/docs/api-management/authentication/jwt-claim-validation#registered-vs-custom-claims). **Example** In this example, `skipKid` has been set to `true`, so Tyk checks the `subjectClaims` and determines that the value in the custom claim `user_id` within the JWT should be used as the identity for the session object. ```yaml theme={null} x-tyk-api-gateway: server: authentication: securitySchemes: jwtAuth: skipKid: true subjectClaims: [user_id] ``` Session objects can be cached to improve performance, so the identity extraction is only performed on the first request with a JWT, or when the cache is refreshed. ## Identifying the Tyk Policies to be applied [Policies](/docs/api-management/policies) are applied (or mapped) to the Session to configure authorization for the request. Policies must be [registered](/docs/api-management/access-control/policies/managing-policies#creating-policies) with Tyk, such that they have been allocated a unique [*Policy Id*](/docs/api-management/access-control/policies/applying-policies#policy-ids). Tyk supports three different types of policy mapping, which are applied in this priority order: 1. Direct policy mapping 2. Scope policy mapping 3. Default policy mapping ### Direct policies You can optionally specify policies to be applied to the session via the *policy claim* in the JWT. This is a [Private](https://datatracker.ietf.org/doc/html/rfc7519#section-4.3) Claim (not a registered claim) and can be anything you want, but typically we recommend the use of `pol`. You must instruct Tyk where to look for the policy claim by configuring the `basePolicyClaims` field in the API definition. Note that we typically refer to Private Claims as Custom Claims. In this example, Tyk has been configured to check the `pol` claim in the JWT to find the *Policy Ids* for the policies to be applied to the session object: ```yaml theme={null} x-tyk-api-gateway: server: authentication: securitySchemes: jwtAuth: basePolicyClaims: [pol] ``` In the JWT, you should then provide the list of Tyk policy IDs as an array of values in that claim, for example you might declare: ``` "pol": ["685a8af28c24bdac0dc21c28", "685bd90b8c24bd4b6d79443d"] ``` Prior to Tyk 5.10, the base policy claim was retrieved from `policyFieldName`; see [using multiple identity providers](#using-multiple-identity-providers) for details and for the Tyk Classic API alternative. ### Default policies A *default policy* is a fallback option if no specific policies are identified from the JWT claims and prevents a session from being created with no authorization to interact with APIs on the Gateway. You **must** configure one or more default policies unless using [scope policies](/docs/api-management/authentication/jwt-authorization#scope-policies). Prior to **Tyk 5.11.0** a default policy was required even when using scope policies. Default policies are configured using the `defaultPolicies` field in the API definition, which accepts a list of policy IDs. The Gateway will return `HTTP 403 Forbidden` if no default policies are configured (prior to Tyk 5.11 or if scope policies are not in use), if the referenced policies don’t exist, or if policies are invalid or incorrectly formatted. ```yaml theme={null} x-tyk-api-gateway: server: authentication: securitySchemes: jwtAuth: defaultPolicies: - 685a8af28c24bdac0dc21c28 - 685bd90b8c24bd4b6d79443d ``` ### Scope policies Directly mapping policies to APIs relies on the sharing of Tyk Policy IDs with the IdP (so that they can be included in the JWT) and may not provide the required flexibility. Tyk supports a more advanced approach where policies are applied based on scopes declared in the JWT. This keeps separation between the IdP and Tyk-specific concepts, and supports much more flexible configuration. Within the JWT, you identify a Private Claim that will hold the authorization (or access) scopes for the API. You then provide, within that claim, a list of *scopes*. In your API definition, you configure the `scopes.claims` to instruct Tyk where to look for the scopes and then you declare a mapping of scopes to policies within the `scopes.scopeToPolicyMapping` object. ```yaml theme={null} x-tyk-api-gateway: server: authentication: securitySchemes: jwtAuth: scopes: scopeToPolicyMapping: - scope: read: users policyId: 685bd90b8c24bd4b6d79443d - scope: write: users policyId: 685a8af28c24bdac0dc21c28 claims: [accessScopes] ``` In this example, Tyk will check the `accessScopes` claim within the incoming JWT and apply the appropriate policy if that claim contains the value `read: users` or `write: users`. If neither scope is declared in the claim, or the claim is missing, the default policy will be applied. Prior to Tyk 5.10, the authorization scopes claim was retrieved from `scopes.claimName`; see [using multiple identity providers](#using-multiple-identity-providers) for details and for the Tyk Classic API alternative. #### Declaring Multiple Scopes You can declare multiple scopes by setting the value of the **authorization scopes claim** in one of the following ways: * **String with space-delimited list of values (standard format)** ```json theme={null} "accessScopes": "read: users write: users" ``` * **Array of strings** ```json theme={null} "accessScopes": ["read: users", "write: users"] ``` * **String with space-delimited list inside a nested key** ```json theme={null} "accessScopes": { "access": "read: users write: users" } ``` * **Array of strings inside a nested key** ```json theme={null} "accessScopes": { "access": ["read: users", "write: users"] } ``` **Important:** * If your scopes are defined inside a nested key, use **dot notation** for the `scopes.claims` value. * For **examples 1 and 2**, set `scopes.claims` to: ``` accessScopes ``` * For **examples 3 and 4**, set `scopes.claims` to: ``` accessScopes.access ``` **Example JWT fragment:** If this JWT is provided to an API configured as described above, Tyk will apply both policies to the session object. ```json theme={null} { "sub": "1234567890", "name": "Alice Smith", "accessScopes": ["read: users", "write: users"] } ``` ### Combining policies Where multiple policies are mapped to a session (for example, if several scopes are declared in the JWT claim, or if you set multiple *default policies*), Tyk will apply all the matching policies to the request, combining their access rights and using the most permissive rate limits and quotas. It's important when creating those policies to ensure that they do not conflict with each other. Policies are combined as follows: 1. Apply direct-mapped policies declared via `basePolicyClaims` 2. Apply scope-mapped policies declared in `scopeToPolicyMapping` based upon scopes in the JWT 3. If no policies have been applied in steps 1 or 2, apply the default policies from `defaultPolicies` When multiple policies are combined, the following logic is applied: * **access rights** A user gets access to an endpoint if ANY of the applied policies grant access * **consumption limits** Tyk uses the most permissive values (highest quota, highest throughput ) * **other settings** The most permissive settings from any policy are applied ### Policy Best Practices When creating multiple policies that might be applied to the same JWT, we recommend using [partitioned policies](/docs/api-management/access-control/policies/applying-policies#partitioned-policies) - policies that control specific aspects of API access rather than trying to configure everything in a single policy. For example: * Create one policy that grants read-only access to specific endpoints * Create another policy that grants write access to different endpoints * Create a third policy that sets specific rate limits To ensure these policies work correctly when combined: * Set `per_api` to `true` in each policy. This ensures that the policy's settings only apply to the specific APIs listed in that policy, not to all APIs globally. * Avoid listing the same `API ID` in multiple policies with conflicting settings. Instead, create distinct policies with complementary settings that can be safely combined. ## Session Updates After authenticating the token and extracting the necessary identity and policy information, Tyk creates or updates a session object that controls access to the API. The following [session attributes](/docs/api-management/access-control/sessions-and-keys/understanding-sessions#configuration-options) are modified based on the Policies: 1. **Access Rights**: Determines which API endpoints the token can access 2. **Rate Limits**: Controls how many requests per second/minute the token can make 3. **Quotas**: Sets the maximum number of requests allowed in a time period 4. **Metadata**: Custom metadata from the policies is added to the session 5. **Tags**: Policy tags are added to the session In addition to updating the session, Tyk extracts claims from the JWT and makes them available as context variables for use in other [middleware](/docs/api-management/traffic-transformation). When a JWT's claims change (for example, by configuring different scopes or policies), Tyk updates the session with the new policies on the subsequent request made with the token. ## Advanced Configuration ### Using Multiple Identity Providers When using multiple Identity Providers (IdPs), you may need to check different claim locations for the same information. Tyk supports definition of **multiple claim locations** for subject identity and policy IDs. * **Before Tyk 5.10 (and for Tyk Classic APIs):** * The Gateway could only check **single claims** for: * Subject identity * Base policy * Scope-to-policy mapping * This setup didn’t support multiple IdPs using different claim names (e.g **Keycloak** uses `scope` and **Okta** uses `scp`) * **From Tyk 5.10 onwards (Tyk OAS APIs):** * You can configure **multiple claim names** for: * Subject identity * Base policy * Scope-to-policy mapping * This allows Tyk to locate data across various tokens and IdPs more flexibly. **Configuration summary:** | API Configuration Type | Tyk Version | Subject Identity Locator | Base Policy Locator | Scope-to-Policy Mapping Locator | | :- | :- | :- | :- | :- | | Tyk OAS | pre-5.10 | `identityBaseField` | `policyFieldName` | `scopes.claimName` | | Tyk OAS | 5.10+ | `subjectClaims` | `basePolicyClaims` | `scopes.claims` | | Tyk Classic | all | `jwt_identity_base_field` | `jwt_policy_field_name` | `jwt_scope_claim_name` | **Example configuration:** ```yaml theme={null} x-tyk-api-gateway: server: authentication: securitySchemes: jwtAuth: # Legacy single field (still supported) identityBaseField: "sub" # New multi-location support (Tyk 5.10+) subjectClaims: - "sub" - "username" - "user_id" ``` #### Backward Compatibility The new configuration is fully backward compatible: * Existing `identityBaseField`, `policyFieldName`, and `scopes.claimName` settings continue to work * If both old and new fields are specified, the new fields take precedence * When using only new fields, the first element in each array is used to set the corresponding legacy field for backward compatibility # JWT Claim Validation Source: https://tyk.io/docs/api-management/authentication/jwt-claim-validation Tyk Gateway's JWT Claim Validation enables fine-grained access control by validating registered and custom claims in JSON Web Tokens. ## Availability | Component | Editions | | :- | :- | | Tyk Gateway | Community and Enterprise | ## Introduction A JSON Web Token consists of three parts separated by dots: `header.payload.signature`. The payload contains the claims, a set of key-value pairs that carry information about the token and its subject. Tyk can validate these claims to ensure that incoming JWTs meet your security requirements before granting access to your APIs. By validating JWT claims, you can enforce fine-grained access control policies, ensure tokens originate from trusted sources, and verify that users have the appropriate permissions for your APIs. **Viewing JWT Claims** To inspect the claims in a JWT, use online tools like [jwt.io](https://jwt.io) for quick debugging ## JWT Claims Fundamentals ### Registered vs Custom Claims JWT claims can be categorized into two types: * **Registered Claims**: Registered Claims are standardized by the JWT specification ([RFC 7519](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1)) and have predefined meanings. These claims are further grouped into: * **Temporal Claims:** time-based validation * **Identity Claims:** content-based validation | Claim | Name | Purpose | Type | | - | - | - | - | | `iss` | Issuer | Identifies who issued the token | Identity | | `aud` | Audience | Identifies who the token is intended for | Identity | | `sub` | Subject | Identifies the subject of the token | Identity | | `exp` | Expiration Time | When the token expires | Temporal | | `iat` | Issued At | When the token was issued | Temporal | | `nbf` | Not Before | When the token becomes valid | Temporal | | `jti` | JWT ID | Unique identifier for the token | Identity | * **Custom Claims**: Custom Claims, referred to as Private Claims in the [JWT Specification](https://datatracker.ietf.org/doc/html/rfc7519#section-4.3), are application-specific and can contain any information relevant to your use case, such as user roles, permissions, department, or metadata. **Example JWT Payload with Both Registered and Custom Claims**: ```json theme={null} { // Registered claims "iss": "https://auth.company.com", "aud": "api.company.com", "sub": "user123", "exp": 1735689600, "iat": 1735603200, // Custom claims "department": "engineering", "role": "admin" } ``` ### Supported Claims and API Types | Claim Category | Sub-Category | Tyk OAS APIs | Tyk Classic APIs | Version | | :- | :- | :- | :- | :- | | **Registered Claims** | **Temporal** (`exp`, `iat`, `nbf`) | ✅ Yes | ✅ Yes | All versions | | **Registered Claims** | **Identity** (`iss`, `aud`, `sub`, `jti`) | ✅ Yes | ❌ Yes | 5.10+ | | **Custom Claims** | — | ✅ Yes | ❌ No | 5.10+ | ### How Tyk Processes JWT Claims After [verifying](/docs/basic-config-and-security/security/authentication-authorization/json-web-tokens) that the token hasn't been tampered with, Tyk processes claims in this order: 1. **Claims Extraction**: All claims from the JWT payload are extracted and stored in [context variables](/docs/api-management/traffic-transformation/request-context-variables) with the format `jwt_claims_CLAIMNAME`. For example, a claim named `role` becomes accessible as `jwt_claims_role`. 2. **Claims Validation**: * [Registered Claims Validation](#registered-claims-validation): Checks standard claims against your configuration * [Custom Claims Validation](#custom-claims-validation): Applies your business rules to custom claims * [Authorization](/docs/api-management/authentication/jwt-authorization): Uses validated claims to determine API access and apply policies If any validation step fails, Tyk rejects the request with a specific error message indicating which claim validation failed and why. ## Registered Claims Validation [Registered Claims](#registered-vs-custom-claims) are grouped into: * **Temporal claims** (time-based validation): Supported in both Tyk Classic APIs and OAS APIs * **Identity claims** (content-based validation): Available only in Tyk OAS APIs ### Temporal Claims Temporal claims define the validity period of a JWT. Tyk automatically validates these claims when present in the token. * **Expiration Time (exp)**: the `exp` claim specifies when the token expires (as a Unix timestamp). Tyk rejects tokens where the current time is after the expiration time. * **Issued At (iat)**: the `iat` claim specifies when the token was issued. Tyk rejects tokens that claim to be issued in the future. * **Not Before (nbf)**: the `nbf` claim specifies the earliest time the token can be used. Tyk rejects tokens before this time. #### Clock Skew Configuration Due to the nature of distributed systems, you may encounter clock skew between your Identity Provider and Tyk servers. You can configure tolerance for timing differences: ```yaml theme={null} x-tyk-api-gateway: server: authentication: securitySchemes: jwtAuth: issuedAtValidationSkew: 5 # Allow tokens issued up to 5 seconds in the future notBeforeValidationSkew: 2 # Allow tokens to be valid 2 seconds early expiresAtValidationSkew: 2 # Allow tokens to be valid 2 seconds past expiration ``` * `expiresAtValidationSkew` allows recently expired tokens to be considered valid * `issuedAtValidationSkew` allows tokens claiming future issuance to be valid * `notBeforeValidationSkew` allows tokens to be valid before their `nbf` time Temporal claim validation and the associated clock skew controls were supported by Tyk before 5.10.0 and also for [Tyk Classic APIs](/docs/api-management/gateway-config-tyk-classic#configuring-authentication-for-tyk-classic-apis) ### Identity Claims Identity claims provide information about the token's origin and intended use. Unlike temporal claims, these require explicit configuration to enable validation. #### Issuer Validation (iss) Validates that a trusted Identity Provider issued the token: ```yaml theme={null} x-tyk-api-gateway: server: authentication: securitySchemes: jwtAuth: allowedIssuers: - "https://auth.company.com" - "https://auth.partner.com" ``` Tyk accepts tokens if the `iss` claim matches any configured issuer. If `allowedIssuers` is empty, no issuer validation is performed. #### Audience Validation (aud) Validates that the token is intended for your API: ```yaml theme={null} x-tyk-api-gateway: server: authentication: securitySchemes: jwtAuth: allowedAudiences: - "api.company.com" - "mobile-app" ``` The `aud` claim can be a string or an array. Tyk accepts tokens if any audience value matches any configured audience. If `allowedAudiences` is empty, no audience validation is performed. #### Subject Validation (sub) Validates the token subject against allowed values: ```yaml theme={null} x-tyk-api-gateway: server: authentication: securitySchemes: jwtAuth: allowedSubjects: - "user" - "service-account" - "admin" ``` Useful for restricting API access to specific types of subjects or known entities. If `allowedSubjects` is empty, no subject validation is performed. #### JWT ID Validation (jti) Validates that the token contains a unique identifier: ```yaml theme={null} x-tyk-api-gateway: server: authentication: securitySchemes: jwtAuth: jtiValidation: enabled: true ``` When enabled, Tyk requires the `jti` claim to be present. This is useful for token tracking and revocation scenarios. Note that Tyk does not perform any validation on the content of the claim, only that it is present. ### Configuration Examples Basic registered claims validation: ```yaml theme={null} x-tyk-api-gateway: server: authentication: securitySchemes: jwtAuth: allowedIssuers: ["https://auth.company.com"] allowedAudiences: ["api.company.com"] jtiValidation: enabled: true expiresAtValidationSkew: 5 ``` Multi-IdP configuration: ```yaml theme={null} x-tyk-api-gateway: server: authentication: securitySchemes: jwtAuth: allowedIssuers: - "https://auth0.company.com" - "https://keycloak.company.com" allowedAudiences: - "api.company.com" - "mobile.company.com" subjectClaims: ["sub", "username"] ``` In this example, we expect one Identity Provider to present the subject in the `sub` claim, and the other to present it in the `username` claim. ## Custom Claims Validation Custom claims validation allows you to enforce business-specific rules on JWT tokens beyond the standard registered claims. **Use Cases**: * **Role-based access control**: Validate that users have required roles (for example, `admin`, `editor`, `viewer`) * **Department restrictions**: Ensure users belong to authorized departments * **Feature flags**: Check if users have access to specific features or API endpoints * **Geographic restrictions**: Validate user location or region-based access * **Subscription tiers**: Enforce access based on user subscription levels ### Validation Types The custom claims validation supports three distinct validation types. These validation types can be applied to any custom claim in your JWT tokens, providing flexible control over your authorization logic. #### Required Required type validation ensures that a specific claim exists in the JWT token, regardless of its value. **Use Cases:** * Ensuring user metadata is present (even if empty) * Validating that required organizational fields exist * Confirming compliance with token structure requirements **Behavior:** * ✅ **Passes** if the claim exists with any non-null value (including empty strings, arrays, or objects) * ❌ **Fails** if the claim is missing or explicitly set to `null` **Example Configuration:** ```yaml theme={null} x-tyk-api-gateway: server: authentication: securitySchemes: jwtAuth: customClaimValidation: department: type: required user_metadata: type: required ``` #### Exact Match Exact match type validation verifies that a claim's value exactly matches one of the specified allowed values. **Use Cases:** * Role validation (e.g., `admin`, `editor`, `viewer`) * Environment-specific access (e.g., `production`, `staging`, `development`) * Subscription tier validation (e.g., `premium`, `standard`, `basic`) * Boolean flag validation (`true`, `false`) **Behavior:** * ✅ Passes if the claim value exactly matches any value in the allowedValues array * ❌ Fails if the claim value doesn't match any allowed value, if the claim is missing, or if allowedValues is empty * Case-sensitive for string comparisons * Type-sensitive (string "true" ≠ boolean true) **Example Configuration:** ```yaml theme={null} x-tyk-api-gateway: server: authentication: securitySchemes: jwtAuth: customClaimValidation: role: type: exact_match allowedValues: - admin - editor - viewer subscription_tier: type: exact_match allowedValues: - premium - standard ``` #### Contains The Contains type validation checks whether a claim's value contains or includes one of the specified values. This validation type works differently depending on the data type of the claim and is particularly useful for array-based permissions and substring matching. **Use Cases:** * Permission arrays (`["read: users", "write: posts", "admin: system"]`) * Tag-based access control * Partial string matching for departments or locations * Multi-value scope validation **Behavior by Data Type:** Arrays: * ✅ Passes if the array contains any of the specified values * ❌ Fails if none of the specified values are found in the array Strings: * ✅ Passes if the string contains any of the specified substrings * ❌ Fails if none of the specified substrings are found Other Types: * Converts to a string and performs substring matching Example Configuration: ```yaml theme={null} x-tyk-api-gateway: server: authentication: securitySchemes: jwtAuth: customClaimValidation: permissions: type: contains allowedValues: - admin: system - write:api department_code: type: contains allowedValues: - ENG - SALES ``` With this configuration, a token might contain these claims: ```json theme={null} { "permissions": ["read: users", "write: posts", "admin: system"], "department_code": "ENG-BACKEND", } ``` In this example: * `permissions` validation passes because the array contains `"admin: system"` * `department_code` validation passes because the string contains `"ENG"` ### Data Type Support The framework is designed to handle the diverse data types commonly found in JWT tokens. The validation behavior adapts intelligently based on the actual data type of each claim, ensuring robust and predictable validation across different token structures. #### Supported Data Types ##### String Values String claims are the most common type in JWT tokens and support all three validation types with intuitive behavior. **Validation behavior** * **Required**: Passes if the string exists (including empty strings `""`) * **Exact Match**: Performs case-sensitive string comparison * **Contains**: Checks if the string contains any of the specified substrings **Example** Claims: ```json theme={null} { "department": "Engineering", "user_id": "user123", "email": "john.doe@company.com" } ``` Validation configuration: ```yaml theme={null} x-tyk-api-gateway: server: authentication: securitySchemes: jwtAuth: customClaimValidation: department: type: exact_match allowedValues: - Engineering - Sales - Marketing email: type: contains allowedValues: - "@company.com" - "@partner.com" ``` ##### Numeric Values Numeric claims (integers and floating-point numbers) are validated with type-aware comparison logic. **Validation behavior** * **Required**: Passes if the number exists (including `0`) * **Exact Match**: Performs numeric equality comparison (`42` matches `42.0`) * **Contains**: Converts to a string and performs substring matching **Example** Claims: ```json theme={null} { "user_level": 5, "account_balance": 1250.75, "login_count": 0 } ``` Validation configuration: ```yaml theme={null} x-tyk-api-gateway: server: authentication: securitySchemes: jwtAuth: customClaimValidation: user_level: type: exact_match allowedValues: - 1 - 2 - 3 - 4 - 5 account_balance: type: required ``` ##### Boolean Values Boolean claims are commonly used for feature flags and permission toggles. **Validation Behavior** * **Required**: Passes if the boolean exists (`true` or `false`) * **Exact Match**: Performs strict boolean comparison * **Contains**: Converts to string (`"true"` or `"false"`) and performs substring matching **Example** Claims: ```json theme={null} { "is_admin": true, "email_verified": false, "beta_features": true } ``` Validation configuration: ```yaml theme={null} x-tyk-api-gateway: server: authentication: securitySchemes: jwtAuth: customClaimValidation: is_admin: type: exact_match allowedValues: - true email_verified: type: required ``` ##### Array Values Arrays are particularly powerful for permission systems and multi-value attributes. **Validation behavior** * **Required**: Passes if the array exists (including empty arrays `[]`) * **Exact Match**: Checks if the entire array exactly matches one of the allowed arrays * **Contains**: Checks if the array contains any of the specified values (most common use case) **Example** Claims: ```json theme={null} { "roles": ["user", "editor"], "permissions": ["read: posts", "write: posts", "delete: own"], "departments": ["engineering", "product"], "tags": [] } ``` Validation configuration: ```yaml theme={null} x-tyk-api-gateway: server: authentication: securitySchemes: jwtAuth: customClaimValidation: permissions: type: contains allowedValues: - write: posts - admin: system roles: type: contains allowedValues: - admin - editor - moderator tags: type: required ``` ##### Object Values Complex object claims can be validated, though typically you'll want to validate specific nested properties using [dot notation](#nested-claims). **Validation Behavior** * **Required**: Passes if the object exists (including empty objects `{}`) * **Exact Match**: Performs deep object comparison (rarely used) * **Contains**: Converts to a JSON string and performs substring matching **Example** Claims: ```json theme={null} { "user_metadata": { "department": "Engineering", "level": 5, "location": "US" }, "preferences": {} } ``` Configuration: ```yaml theme={null} x-tyk-api-gateway: server: authentication: securitySchemes: jwtAuth: customClaimValidation: user_metadata: type: required preferences: type: required ``` ##### Type Coercion and Edge Cases **Null and Undefined Values** * null values: Always fail validation (treated as missing) * undefined/missing claims: Fail all validation types except when validation is not configured **Mixed-Type Arrays** Arrays containing different data types are supported. The `contains` validation will attempt to match values using appropriate type comparison, ```json theme={null} { "mixed_permissions": ["read", 42, true, "admin"] } ``` **Type Mismatches** When the expected value type doesn't match the claim type, Tyk performs intelligent conversion: * Numbers to strings: `42` becomes `"42"` * Booleans to strings: `true` becomes "`true"` * Objects/arrays to strings: Converted to JSON representation ##### Best Practices * Be Explicit About Types: When configuring `allowedValues`, use the same data type as expected in the token * Use Arrays for Multi-Value Validation: Prefer array-based claims for permissions and roles * Consider Empty Values: Remember that empty strings, arrays, and objects pass `required` validation * Test Type Coercion: Verify behavior when token types don't match expected types ### Nested Claims JSON Web Tokens often contain complex, hierarchical data structures with nested objects and arrays. Tyk's custom claims validation framework supports validating nested claim structures using dot notation syntax. **Basic Syntax:** * `user.name` - Access the `name` property within the `user` object * `permissions.0.resource` - Access the `resource` property of the first element in the `permissions` array **Dot Notation** Tyk uses [gjson](https://github.com/tidwall/gjson) to parse dot notation paths. #### Nested Object Validation The most common use case for dot notation is validating properties within nested objects, such as user metadata, organizational information, or configuration settings. **Example Token** ```json theme={null} { "user": { "name": "John Doe", "email": "john.doe@company.com", "profile": { "department": "Engineering", "level": "senior", "location": { "country": "US", "region": "West" } } } } ``` You could set the following configuration to validate the requester's department and level: ```yaml theme={null} x-tyk-api-gateway: server: authentication: securitySchemes: jwtAuth: customClaimValidation: user.profile.department: type: exact_match allowedValues: - Engineering - Sales - Marketing user.profile.level: type: contains allowedValues: - senior - lead - principal ``` #### Nested Array Validation Arrays are commonly used in JWT claims to represent lists of permissions, roles, or other multi-value attributes. Tyk supports validating specific elements within arrays using dot notation with numeric indices. **Example Token** ```json theme={null} { "permissions": [ { "resource": "users", "actions": ["read", "write"] }, { "resource": "reports", "actions": ["read"] } ] } ``` You can validate specific array elements: ```yaml theme={null} x-tyk-api-gateway: server: authentication: securitySchemes: jwtAuth: customClaimValidation: "permissions.0.resource": type: exact_match allowedValues: ["users"] "permissions.1.actions.0": type: exact_match allowedValues: ["read"] ``` **Dot Notation** When a nested path doesn't exist (e.g., `user.profile.level` but `profile` doesn't exist) or when an array index is out of bounds (e.g., `permissions.999.resource`), the claim is treated as missing. This will cause validation to fail for blocking rules or generate a warning for non-blocking rules. #### Recommendations Test your nested claim validation rules with representative JWT tokens to ensure they behave as expected. Use online tools like [gjson.dev](https://gjson.dev/) to experiment with dot notation paths and verify they correctly access the desired values. ### Non-blocking Validation Non-blocking validation allows JWT claims to fail validation with a warning logged, while still permitting the request to proceed. This behavior allows you to: * Monitor how new validation rules would affect traffic without disrupting users * Gradually roll out stricter validation requirements * Debug validation issues in production environments #### How Non-blocking Validation Works When configured, a validation rule can be set to "non-blocking" mode, which means: 1. If validation passes, the request proceeds normally 2. If validation fails, instead of rejecting the request: * A warning is logged to the Tyk Gateway log file at the `WARN` log level * The validation process continues to evaluate other custom claims * The request is allowed to proceed to the upstream API #### Configuring Non-Blocking Mode Non-blocking mode can be configured for any custom claim validation rule with the addition of the boolean `nonBlocking` flag, for example: ```yaml theme={null} x-tyk-api-gateway: server: authentication: securitySchemes: jwtAuth: customClaimValidation: user.profile.department: type: exact_match allowedValues: - Engineering - Sales - Marketing user.preferences.notifications: type: required nonBlocking: true ``` The `nonBlocking` flag in the validation rule for `user.preferences.notifications` means that if this claim is missing from the received token, the token will not fail validation, but a warning will be logged. ## FAQ Yes, you can configure `AllowedIssuers` to specify which iss (issuer) claim values are accepted. Tokens from other issuers will be rejected. Use the `CustomClaimValidation` configuration to validate specific claims with different validation types (Required, ExactMatch, or Contains). # JWT Quick Start: Securing APIs with Auth0, Descope or Keycloak Source: https://tyk.io/docs/api-management/authentication/jwt-quick-start Learn how to secure your Tyk OAS APIs using JWT authentication with Auth0, Descope or Keycloak as identity providers. In this tutorial, we'll secure a Tyk OAS API using JWT authentication with Auth0, Descope or Keycloak as the identity provider. If you want to try out JWT Auth without linking up to a third-party IdP then you can skip step 1 and provide the base64 encoded public key for your JWT (in the `source` field rather than configuring `jwksURIs`) in step 3. You'll need to generate a JWT for the request, but otherwise everything stays the same. Now back to the tutorial... We'll start by configuring the identity provider, then set up JWT validation in Tyk, create a security policy, configure the API to use the policy, and finally test the secured API with a valid token. ### Prerequisites * A Tyk installation (Cloud or Self-Managed) with Tyk Dashboard license * An Auth0 account, a Descope project, or a Keycloak installation * An existing Tyk OAS API (see [this tutorial](/docs/api-management/gateway-config-managing-oas#using-tyk-dashboard-api-designer-to-create-an-api)) * Postman, cURL, or another API testing tool ### Step-by-Step Guide 1. **Configure Your Identity Provider to obtain your JWKS URI** The first step is to configure your Identity Provider (IdP) to issue JWTs and provide a JWKS URI that Tyk can use to validate the tokens. Below are instructions for both Auth0 and Keycloak. 1. Log in to your Auth0 dashboard 2. Navigate to Applications > APIs and click Create API 3. Enter a name and identifier (audience) for your API 4. Note your Auth0 domain (e.g. `your-tenant.auth0.com`) 5. Your JWKS URI will be: `https://your-tenant.auth0.com/.well-known/jwks.json` Descope issues JWTs through **[Inbound Apps](https://docs.descope.com/identity-federation/inbound-apps)**, its OAuth 2.0 authorization server. The signing keys are published per project rather than per application, so every Inbound App in a project shares one JWKS URI. 1. Log in to the [Descope Console](https://app.descope.com) 2. Navigate to **Inbound Apps** and create an app, or select an existing one 3. Note your **Project ID**, shown in the Connection Information section alongside the client ID and discovery URL 4. Your JWKS URI will be: `https://api.descope.com//.well-known/jwks.json` 5. Your issuer will be: `https://api.descope.com/v1/apps/` Substitute your regional or custom base URL for `api.descope.com` if you use one. Descope signs with RS256, so select **RSA Public Key** as the token signing method in step 3. Granted scopes arrive in the `scope` claim as a space-delimited string. 1. Log in to your Keycloak admin console 2. Create or select a realm (e.g. `tyk-demo`) 3. Navigate to Clients and create a new client with: * Client ID: `tyk-api-client` * Client Protocol: `openid-connect` * Access Type: `confidential` 4. After saving, go to the Installation tab and select "OIDC JSON" format 5. Your JWKS URI will be: `http://your-keycloak-host/realms/tyk-demo/protocol/openid-connect/certs` 2. **Create a Security Policy** 1. In the Tyk Dashboard, navigate to **Policies** 2. Click **Add Policy** 3. Configure the policy: * Name: `JWT Auth Policy` * APIs: Select your Tyk OAS API * Access Rights: Configure appropriate paths and methods * Authentication: Select JWT * JWT Scope Claim Name: Enter the JWT claim that contains scopes (e.g. `scope` or `permissions`) * Required Scopes: Add any required scopes for access (optional) 4. Click Create to save your policy 3. **Configure JWT Authentication in Tyk OAS API** 1. Navigate to APIs and select your API 2. Click **Edit** 3. Enable **Authentication** in the **Server** section, select **JSON Web Token (JWT)** as the authentication method 4. Configure the JWT settings: * Token Signing Method: Select `RSA Public Key` * Subject identity claim: Set to `sub` * JWKS Endpoint: Enter your JWKS URI for your IdP obtained in step 1 * Policy claim: Set to `pol` * Default policy: Select `JWT Auth Policy` (the policy you created previously) * Clock Skew (optional): Set to accommodate time differences (e.g. `10`) * Authentication Token Location: `header` * Header Name: `Authorization` * Strip Authorization Data: `Enabled` 5. Click **Save API** 4. **Test your API** 1. Obtain a JWT from your IdP 2. Make a request to your API providing the JWT as a Bearer token in the `Authorization` header; Tyk will validate the JWT using the JWKS that it retrieves from your JWKS URI 3. Observe that the request is successful ```bash theme={null} curl -X GET {API URL} -H "Accept: application/json" -H "Authorization: Bearer {token}" ``` # JWT Signature Validation Source: https://tyk.io/docs/api-management/authentication/jwt-signature-validation How to validate JWT signatures in Tyk API Gateway. ## Availability | Component | Editions | | - | - | | Tyk Gateway | Community and Enterprise | ## Introduction A JSON Web Token consists of three parts separated by dots: `header.payload.signature`. The signature verifies that the sender of the JWT is who it claims to be and that the message wasn't altered along the way. Tyk can validate the signature of incoming JWTs to ensure that they meet your security requirements before granting access to your APIs. ## JWT Signature Fundamentals The JWT signature serves three main purposes: 1. **Integrity:** If anyone modifies the header or payload, the signature will no longer match. 2. **Authenticity:** Confirms that the token was issued by a trusted source. 3. **Security:** Prevents malicious users from forging tokens or altering claims. ### How JWT Signatures Are Created The JWT signature is created by taking the encoded header, the encoded payload, a secret, and the algorithm specified in the header. **Example**: ``` HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret ) ``` Or, for asymmetric algorithms like RSA or ECDSA: ``` RSASHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), private_key ) ``` ### Verification Process When Tyk receives a JWT, it performs the following steps to validate the signature: 1. It extracts the header and payload. 2. Recomputes the signature using its own secret/public key. 3. Compares it with the token’s signature. * If they match, the token is valid. * If not, the token is rejected. ## Supported Algorithms for Signature Validation | Method | Cryptographic Style | Secret Type | Supported Algorithms | | - | - | - | - | | **HMAC** | Symmetric | Shared secret | `HS256`, `HS384`, `HS512` | | **RSA** | Asymmetric | Public key | `RS256`, `RS384`, `RS512`, `PS256`, `PS384`, `PS512` | | **ECDSA** | Asymmetric | Public key | `ES256`, `ES384`, `ES512` | ## Configuration Options Tyk supports two approaches to supplying the key or secret used to validate incoming JWTs: * **[Identity Provider](#identity-providers) (IdP)**: Tyk fetches public keys from a JWKS endpoint exposed by the IdP. The IdP can be configured centrally in the Identity Provider Registry, or directly in the API definition. * **[Local Keys](#local-keys)**: The key or secret is supplied directly in the API definition, either as a hard-coded value or as a reference to an external secret store. ### Identity Providers An Identity Provider (IdP) issues JWTs and exposes a JWKS endpoint where Tyk fetches the public keys needed to validate token signatures. The IdP can be configured centrally in the [Identity Provider Registry](/docs/api-management/client-idp-registry), or directly in the API definition. #### Feature Compatibility Summary | Feature | Tyk Classic APIs | Tyk OAS APIs | Available From | | - | - | - | - | | Identity Provider Registry (recommended) | ✅ | ✅ | 5.14.0 (Enterprise) | | Single JWKS endpoint in API definition | ✅ | ✅ | All versions | | Multiple JWKS endpoints in API definition | ❌ | ✅ | 5.9.0 | #### Identity Provider Registry The [Identity Provider Registry](/docs/api-management/client-idp-registry) is a centralized store for IdP configuration (JWKS endpoints, scope claim names, and [scope-to-policy mappings](/docs/api-management/authentication/jwt-authorization#scope-policies)) managed independently of API definitions in the Tyk Dashboard. Available from **Tyk 5.14.0** (Enterprise), it is the recommended approach when using Dynamic Client Registration or when multiple systems need to manage IdP configuration for the same API. Adopting the registry is a non-breaking change: existing API definitions are unaffected. #### Configuring IdPs in the API Definition If you are not using the Identity Provider Registry, JWKS endpoints can be configured directly in the API definition. **Multiple JWKS Endpoints** From **Tyk 5.9.0** onwards, Tyk OAS APIs can validate against multiple JWKS endpoints, allowing different IdPs to issue JWTs for the same API. Multiple JWKS endpoints can be configured in the `.jwksURIs` array. Tyk retrieves the JSON Web Key Sets from each endpoint and uses them to attempt to validate the received JWT. For example, the following fragment configures the JWT authentication middleware to retrieve the JWKS from both Auth0 and Keycloak when validating the signature of incoming JWTs: ```yaml theme={null} x-tyk-api-gateway: server: authentication: securitySchemes: jwtAuth: jwksURIs: - url: https://your-tenant.auth0.com/.well-known/jwks.json - url: http://your-keycloak-host/realms/tyk-demo/protocol/openid-connect/certs ``` Multiple JWKS endpoints and the `jwksURIs` array are not supported by Tyk Classic APIs. **Single JWKS Endpoint** If using Tyk Classic APIs, or Tyk OAS APIs on versions before 5.9.0, a single JWKS endpoint can be configured in `server.authentication.securitySchemes..source` (in Tyk Classic, this is [jwt\_source](/docs/api-management/gateway-config-tyk-classic#configuring-authentication-for-tyk-classic-apis)). This field accepts the base64-encoded full URI (including the protocol) of the JWKS endpoint. For example, the following Tyk OAS fragment configures the JWT authentication middleware to retrieve the JWKS from `https://your-tenant.auth0.com/.well-known/jwks.json`: ```yaml theme={null} x-tyk-api-gateway: server: authentication: securitySchemes: jwtAuth: source: aHR0cHM6Ly95b3VyLXRlbmFudC5hdXRoMC5jb20vLndlbGwta25vd24vandrcy5qc29u ``` The `.source` URIs must be base64 encoded in the API definition. If both `.source` and `.jwksURIs` are configured, the latter will take precedence. ### Local Keys The key or secret used to validate JWTs can be supplied directly in the API definition via `server.authentication.securitySchemes..source` (in Tyk Classic, this is [jwt\_source](/docs/api-management/gateway-config-tyk-classic#configuring-authentication-for-tyk-classic-apis)). The value must be base64 encoded. This approach supports both symmetric (HMAC shared secret) and asymmetric (RSA/ECDSA public key) algorithms. Rather than hard-coding the value, the recommended approach is to store the key or secret in an [external secret store](/docs/tyk-configuration-reference/kv-store) such as Consul or Vault, and place a KV reference in `source` instead. The reference is base64 encoded in the same way as a hard-coded value. For example, the following fragment hard-codes the secret `mysecret`: ```yaml theme={null} x-tyk-api-gateway: server: authentication: securitySchemes: jwtAuth: source: bXlzZWNyZXQ= # base64("mysecret") ``` The following fragment uses a Consul KV reference instead, keeping the secret out of the API definition: ```yaml theme={null} x-tyk-api-gateway: server: authentication: securitySchemes: jwtAuth: source: Y29uc3VsOi8vc2VjcmV0cy9qd3Qtc2VjcmV0 # base64("consul://secrets/jwt-secret") ``` Refer to the [Tyk OAS API Definition](/docs/api-management/gateway-config-tyk-oas#jwt) reference for details. ## JWKS Caching Tyk caches public keys fetched from Identity Providers to reduce the performance impact of contacting external services during request handling. ### Feature Compatibility Summary | Feature | Tyk Classic | Tyk OAS | Available From | | - | - | - | - | | Configurable cache timeout | ✅ | ✅ | Tyk 5.12.0+ | | Per-IdP cache timeout | ❌ | ✅ | Tyk 5.10.0+ | | Pre-fetch on API load | ❌ | ✅ | Tyk 5.10.0+ | | Cache management API | ✅ | ✅ | Tyk 5.10.0+ | ### Configuration Options #### Gateway-Level Configuration Unless otherwise configured, all cached keys expire after 240 seconds, after which the cache is refreshed when a new request is received. From **Tyk 5.12.0**, this default timeout is configurable in the Gateway config file (`tyk.conf`) or the equivalent environment variable: ```json theme={null} { "jwks": { "cache": { "timeout": 90 } } } ``` The [`timeout`](/docs/tyk-oss-gateway/configuration#jwks-cache-timeout) is given in seconds. This setting applies to all IdPs, including those configured via the [Identity Provider Registry](/docs/api-management/client-idp-registry). #### API-Level Configuration From **Tyk 5.10**, Tyk OAS APIs support a per-IdP cache timeout on each IdP configured via `jwksURIs`. If set, this overrides the gateway-level timeout for that IdP. For example, the following fragment assigns a 300 second cache timeout to Auth0 and 180 seconds to Keycloak: ```yaml theme={null} x-tyk-api-gateway: server: authentication: securitySchemes: jwtAuth: jwksURIs: - url: https://your-tenant.auth0.com/.well-known/jwks.json cacheTimeout: "300s" - url: http://your-keycloak-host/realms/tyk-demo/protocol/openid-connect/certs cacheTimeout: "3m" ``` | Field | Type | Description | Default | Supported Formats | | - | - | - | - | - | | `url` | string | JWKS endpoint URL | Required | Full URI including protocol | | `cacheTimeout` | string | Cache validity period | 240s | `"300s"`, `"5m"`, `"1h"`, etc. | For more details, refer to the [Tyk OAS API definition reference](/docs/api-management/gateway-config-tyk-oas#jwk). Tyk Classic APIs do not support per-IdP cache timeouts and use the gateway-level timeout (from Tyk 5.12.0) or the default of 240 seconds. Per-IdP `cacheTimeout` applies only to IdPs [configured directly in the API definition](#configuring-idps-in-the-api-definition) via `jwksURIs`. IdPs configured in the [Identity Provider Registry](/docs/api-management/client-idp-registry) always use the gateway-level `jwks.cache.timeout` and cannot currently be tuned per IdP. Per-IdP cache timeout configuration is planned for a future release. ### Cache Management Tyk Gateway and Tyk Dashboard APIs expose endpoints to manage JWKS caches programmatically for both Tyk OAS and Tyk Classic APIs: | Endpoint | Method | Description | Availability | | - | - | - | - | | `/tyk/cache/jwks` | `DELETE` | Invalidate JWKS caches for all APIs | Tyk 5.10.0+ | | `/tyk/cache/jwks/{apiID}` | `DELETE` | Invalidate JWKS cache for a specific API | Tyk 5.10.0+ | | `/api/cache/jwks/{apiID}` | `DELETE` | Invalidate JWKS cache for a specific API on all connected Gateways | Tyk 5.11.0+ | The Dashboard API endpoint is restricted to users with `admin` privileges and can only be used to flush the cache for APIs in the user's [Organisation](/docs/tyk-dashboard-api#organisations-apis-and-users). **Example usage:** ```bash theme={null} # Flush all JWKS caches curl -X DELETE http://your-gateway:8080/tyk/cache/jwks \ -H "x-tyk-authorization: your-gateway-secret" # Flush JWKS cache for specific API curl -X DELETE http://your-gateway:8080/tyk/cache/jwks/your-api-id \ -H "x-tyk-authorization: your-gateway-secret" # Flush JWKS cache for specific API on all connected Gateways curl -X DELETE http://your-dashboard:8080/api/cache/jwks/your-api-id \ -H "authorization: your-dashboard-secret" ``` ## FAQ Yes, each API definition can have its own JWT configuration with different signing methods and keys. The recommended approach is to use the [Identity Provider Registry](/docs/api-management/client-idp-registry) (Enterprise, from Tyk 5.14.0), which natively supports multiple IdPs per API. If you are not using the registry, Tyk OAS APIs from Tyk 5.9.0 support multiple JWKS endpoints via the `jwksURIs` array. Tyk caches public keys fetched from IdPs, so a temporary outage does not immediately affect API availability. The cache timeout defaults to 240 seconds and is configurable via the gateway-level `jwks.cache.timeout` setting. For IdPs configured directly in a Tyk OAS API definition via `jwksURIs`, a per-IdP `cacheTimeout` can also be set on each entry. No, JWKS endpoints are designed for asymmetric cryptography (RSA and ECDSA), where public keys are used for signature verification. Symmetric cryptography (HMAC) requires a shared secret, which cannot be retrieved from a JWKS endpoint. By default, cached keys expire after 240 seconds. This can be changed gateway-wide using the `jwks.cache.timeout` setting in the Gateway config. For Tyk OAS APIs with IdPs configured directly in the API definition via `jwksURIs`, a per-IdP `cacheTimeout` can override the gateway-level setting. IdPs configured via the Identity Provider Registry always use the gateway-level timeout and cannot currently be tuned per IdP. The JWKS (JSON Web Key Set) pre-fetching functionality in Tyk Gateway is automatic and not configurable in terms of enabling/disabling it. When you configure JWKS URLs in your API definition, Tyk automatically pre-fetches the keys when the API loads. # JWT Split Token Source: https://tyk.io/docs/api-management/authentication/jwt-split-token Learn how to implement JWT Split Token flow in Tyk to enhance security by separating JWT components and storing sensitive data server-side. ## Availability | Component | Editions | | :- | :- | | Tyk Gateway | Community and Enterprise | ## Introduction Split Token Flow addresses a fundamental security concern with JWT tokens: when a JWT is stored on a client device (browser, mobile app, etc.), all of its contents can be easily decoded since JWTs are only base64-encoded, not encrypted. This means sensitive information in the payload is potentially exposed. The JWT consists of three parts: Split Token Example In the above example you can see that they are: * Header: `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9` * Payload: `eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJlbWFpbCI6ImhlbGxvQHdvcmxkLmNvbSJ9` * Signature: `EwIaRgq4go4R2M2z7AADywZ2ToxG4gDMoG4SQ1X3GJ0` The Split Token approach provides a solution by: 1. Separating the JWT into its three component parts: header, payload, and signature 2. Storing only the signature on the client side (which by itself is meaningless) 3. Keeping the header and payload securely on the server side (in Tyk) 4. Reconstructing the complete JWT when needed for authentication This approach combines the benefits of JWTs (rich claims, stateless validation) with the security of opaque tokens (no information disclosure). ### When to Use Split Token Flow Consider using Split Token Flow when: * Your JWT payload contains sensitive information that shouldn't be exposed to clients * You want to prevent token inspection by malicious actors * You need the flexibility of JWT while maintaining higher security * You're implementing systems that must meet strict security compliance requirements ## How Split Token Flow Works Here's how the process works with Tyk Gateway: ```mermaid theme={null} sequenceDiagram participant Client participant Tyk as Tyk Gateway participant Redis as Tyk Redis participant Auth as Authorization Server %% Token Issuance Flow rect rgb(240, 240, 255) note over Client, Auth: Token Issuance Client->>Tyk: Request token from /token endpoint Tyk->>Auth: Forward request to Auth Server Auth->>Tyk: Return complete JWT (header.payload.signature) Tyk->>Tyk: Split JWT into components Tyk->>Redis: Store header & payload using signature as key Tyk->>Client: Return only signature as "opaque" token end %% Token Usage Flow rect rgb(245, 255, 245) note over Client, Auth: Token Usage Client->>Tyk: API request with signature as Bearer token Tyk->>Redis: Look up header & payload using signature Redis->>Tyk: Return stored header & payload Tyk->>Tyk: Reconstruct complete JWT Tyk->>Tyk: Validate JWT Tyk->>Auth: Forward request with complete JWT Auth->>Tyk: Response Tyk->>Client: Return response to client end ``` 1. **Token Issuance**: * A `/token` endpoint is configured on Tyk from which the client should request the access token * Tyk requests an access token from an authorization server (e.g., Keycloak) on behalf of the client * The authorization server returns a complete JWT * Tyk intercepts this response through a [Virtual Endpoint](/docs/api-management/traffic-transformation/virtual-endpoints) * Tyk splits the JWT into its components and stores the header and payload in its Redis database * Only the signature portion is returned to the client as an "opaque" token 2. **Token Usage**: * The client makes API requests using only the signature as their access token * Tyk receives the request and looks up the stored header and payload using the signature * Tyk reconstructs the complete JWT and validates it * If valid, Tyk forwards the request to the upstream API with the full JWT 3. **Security Benefits**: * The client never possesses the complete JWT, only a meaningless signature * Token contents cannot be inspected by client-side code or malicious actors * Token validation still occurs using standard JWT verification ## Implementing Split Token Flow 1. **Create a Virtual Endpoint for Token Issuance** First, create a virtual endpoint in Tyk that will: * Receive authentication requests from clients * Forward these requests to your authorization server * Split the returned JWT * Store the header and payload in Tyk's storage * Return only the signature to the client * Here's a simplified implementation: ```javascript theme={null} function splitTokenHandler(request, session, config) { // 1. Forward the client's credentials to the authorization server var authServerResponse = forwardToAuthServer(request); if (authServerResponse.Code !== 200) { return TykJsResponse({ Body: authServerResponse.Body, Code: authServerResponse.Code }, session.meta_data); } // 2. Extract the JWT from the response var responseBody = JSON.parse(authServerResponse.Body); var fullJWT = responseBody.access_token; // 3. Split the JWT into its components var jwtParts = fullJWT.split("."); var header = jwtParts[0]; var payload = jwtParts[1]; var signature = jwtParts[2]; // 4. Store the complete JWT in Tyk's Redis database using the signature as the key // This function would use Tyk's storage API to save the data storeJWTComponents(signature, header, payload, fullJWT); // 5. Modify the response to return only the signature responseBody.access_token = signature; return TykJsResponse({ Body: JSON.stringify(responseBody), Code: 200 }, session.meta_data); } ``` Note that this example includes some level of abstraction for clarity and so is not a full implementation. 2. **Configure Custom Pre-Auth Plugin** Next, create a custom pre-auth plugin that reconstructs the JWT before it reaches the standard Tyk JWT Auth middleware: ```javascript theme={null} function reconstructJWT(request, session, config) { // 1. Extract the signature from the Authorization header var authHeader = request.Headers["Authorization"]; var signature = authHeader.replace("Bearer ", ""); // 2. Retrieve the stored JWT components using the signature var storedJWT = retrieveJWTComponents(signature); if (!storedJWT) { return TykJsResponse({ Body: "Invalid token", Code: 401 }, session.meta_data); } // 3. Replace the Authorization header with the full JWT request.SetHeaders["Authorization"] = "Bearer " + storedJWT.fullJWT; return request; } ``` 3. **Test the Implementation** To test your Split Token Flow: Request a token from your Tyk virtual endpoint: ```bash theme={null} curl -X POST https://your-tyk-gateway/token \ -d "grant_type=client_credentials&client_id=your-client-id&client_secret=your-client-secret" ``` You'll receive a response with only the signature as the access token, for example: ```json theme={null} { "access_token": "EwIaRgq4go4R2M2z7AADywZ2ToxG4gDMoG4SQ1X3GJ0", "token_type": "bearer", "expires_in": 3600 } ``` Use this token to access your JWT Auth protected API where you have configured the custom pre-auth plugin and JWT Auth: ```bash theme={null} curl https://your-tyk-gateway/protected-api \ -H "Authorization: Bearer EwIaRgq4go4R2M2z7AADywZ2ToxG4gDMoG4SQ1X3GJ0" ``` # Tyk OAuth 2.0 Authorization Server Source: https://tyk.io/docs/api-management/authentication/oauth-2 Learn how to use Tyk Gateway as a built-in OAuth 2.0 authorization server to issue and manage access tokens for APIs deployed on Tyk. ## OAuth 2.0 without an external Authorization Server Tyk can act as an OAuth 2.0 *authorization server*, performing token generation and management for *clients* accessing APIs deployed on Tyk. There are many great resources on the Internet that will help you to understand the OAuth 2.0 Authorization Framework, which we won't attempt to duplicate here. We will provide a basic introduction to the [concepts and terminology](#oauth-20-core-concepts) before we dive into the details of using Tyk as your *auth server*. Tyk offers some great features when used as the *authorization server* including: * **Fine-Grained Access Control:** Manage access using Tyk's built-in access controls, including versioning and named API IDs * **Usage Analytics:** Leverage Tyk's analytics capabilities to monitor OAuth 2.0 usage effectively, grouping data by Client Id * **Multi-API Access**: Enable access to multiple APIs using a single OAuth token; configure one API for OAuth 2.0 token issuance and the other APIs with the [Auth Token](/docs/api-management/authentication/bearer-token) method, linking them through a common policy *Tyk as OAuth authorization server* supports the following *grant types*: * [Authorization Code Grant](#using-the-authorization-code-grant): the *client* is redirected to an *identity server* where the *user* must approve access before an *access token* will be issued * [Client Credentials Grant](#using-the-client-credentials-grant): used for machine-to-machine access, authentication is performed using only the *client Id* and *client secret* * [Resource Owner Password Grant](#using-the-resource-owner-password-grant) (a.k.a. Password Grant): only for use where the *client* is highly trusted, as the *client* must provide the *Resource Owner*'s own credentials during authentication **Tyk does not recommend the use of Resource Owner Password Grant**. This method is considered unsafe and is prohibited in the [OAuth 2.0 Security Best Practice](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics-13#section-3.4") but is supported for use with legacy clients. To make use of this, you'll need to: * understand how to integrate your *client* (and, for Authorization Code grant, your *identity server*) according to the OAuth grant type * [register a client app](#client-app-registration) for each client that needs to access the API * [configure your API proxy](#configuring-your-api-proxy) to use the *Tyk OAuth 2.0* authentication method ``` **Vimeo video:** ```html theme={null} ``` **HTML5 video and audio:** ```html theme={null} ``` ### Custom Layouts ```html theme={null}
This is a custom callout box.
Sized image ``` ## Not Supported The portal does not render the following Markdown extensions: | Feature | What Happens | | - | - | | Footnotes | `[^1]` remains as plain text | | Definition Lists | `Term` followed by `: Definition` is not recognized | | Emoji shortcodes | `:smile:` remains as text (use Unicode emojis directly instead) | | Math/LaTeX | `$E=mc^2$` is not rendered | ## Known Limitations and Workarounds ### Table Styling Markdown tables are generated correctly but the default theme does not display borders. You can work around this in two ways: **Option 1: HTML table with Bootstrap class** ```html theme={null}
Column 1Column 2
Value 1Value 2
``` **Option 2: Markdown table with style wrapper** ```markdown theme={null}
| Column 1 | Column 2 | |----------|----------| | Value 1 | Value 2 |
``` ### Blockquotes Without Styling Blockquotes are generated in the HTML output but the default theme does not display any indentation or border. They appear as regular text. Adjust your theme's CSS to style the `blockquote` element if needed. ### Code Without Syntax Highlighting Code blocks render in monospace font but without syntax color highlighting in the default theme. # Customize Menus in Developer Portal Source: https://tyk.io/docs/portal/customization/menus How to customize menus in developer portal The Developer portal has two types of menus: 1. The main navigation at the top (in the header) 2. The footer at the bottom. Both of them are defined as [partials](/docs/portal/customization/themes#file-structure-of-a-theme) in the portal directory in `/themes/default/partials/`. ## Top Navigation Menu The Enterprise Developer portal enables admin users to customize the navigation menu that appears on the top navigational bar of the live portal. An admin user can create and manage menu items without any code from the admin dashboard of the Developer portal. The navigation menu Each menu item may: * lead to a specific page or URL: Regular menu item * show a dropdown list with possible navigational options: Dropdown menu item Admin users can create additional navigational menus and render them on any page of the live portal. This customization requires changes to a theme and is covered in the [Full customization section](/docs/portal/customization/menus). ### Manage Menu Items The management of the menu items is done from the **Menus** section of the Developer portal. 1. Open the admin dashboard. Navigate to the **Menus** section. Navigate to the Menus section 2. Select a menu that you want to modify. By default, the Developer portal has only one **Primary** menu. If you want to add more menus and render them on the live portal, please refer to [Full customization section](/docs/portal/customization/menus). Select a menu 3. Click on a **menu item** to modify it. You can change the following items: 1. **Title** that will be exposed to developers. 2. **Path** where developers will be redirected by clicking on that menu item. 3. **Children** items that will be exposed in the dropdown list that will appear when hovering mouse over the menu item. 4. To make the changes effectively, you need to save the changes by clicking on the **Save changes** button. Modify a menu item 4. To remove a menu item from the menu click on the **bin** icon and click on the **Save changes** button. Delete a menu item ### Create New Menu Items To create a new menu item, you need to: 1. Click on the **Add Menu Item** button. 2. Fill **Title**, **Path**, and **Children** fields. Save the changes by clicking on the **Save changes** button. Save a menu item The new menu item will appear on the live portal immediately. New menu item on the live portals ### Update Existing Menus 1. Log into your portal 2. Select **Menus** from the navigation menu 3. Click **Primary** to edit the menu Edit Menu dialog **Field Descriptions** * **Name**: You can give it any name you like, it does not have any effect in the live portal nor the admin app. * **Path**: This will be used in the code as a reference in order to render the menu. If you don’t have access to the template files, we recommend that you do not edit this field. Editing the `Path` for the default menus will hide the menu as there will be a mismatch between the Path and the reference in the template. * **Menu Items**: 1. **Title**: This will be the text that will be displayed in the live portal. 2. **Path**: this is where the user will be redirected to. 3. **Children**: In this section you add another nested menu item. We have added a dummy item (Product 1) to demonstrate Below is the menu item from its own view, which is available from the **Menu Items** option in the admin app side menu. Edit Menu item dialog Here's the menu as displayed in the app: Live menu in app We have mentioned above the relationship between a menu’s `Path` and the code reference in the menu template. Let’s see how the main menu template looks like (the file is `/themes/default/partials/` directory and is called `top_nav.tmpl`) for the part that we are interested in: ```go theme={null} {{ if GetMenus.Primary }} {{ range GetMenus.Primary.Children }} {{ end }} {{ end }} ``` Let's pick each line that is used to render the menu attributes and see how they work: 1. `{{ if GetMenus.Primary }}`: This statement calls the “GetMenus” function and checks if there is a menu called `Primary`. If present, it goes into the next line: 2. `{{ range GetMenus.Primary.Children }}` Each Menu (Primary) has some children (Menu items) so what this code does is loop through all the children and they are rendered as below: ```go theme={null} {{ end }} {{ end }} {{ end }} ``` #### GetProducts Returns the list of products for the current user. Expects the request as an argument. ##### Product Attributes Accessible via `{{ range $product := GetProducts req }}` | Attribute | Description | | :- | :- | | `{{ $product.ID }}` | Product ID | | `{{ $product.Name }}` | Product name | | `{{ $product.DisplayName }}` | Product display name | | `{{ $product.Path }}` | Product path | | `{{ $product.ReferenceID }}` | Product reference ID | | `{{ $product.Description }}` | Product description | | `{{ $product.AuthType }}` | Product auth type | | `{{ $product.Scopes }}` | Product scopes | | `{{ $product.Logo.URL }}` | Product logo URL | | `{{ $product.Feature }}` | true if the product is featured | | `{{ $product.DCREnabled }}` | true if DCR is enabled | | `{{ $product.ProviderID }}` | Provider ID | | `{{ $product.APIDetails }}` | Array of API details associated with the product | | `{{ $product.Catalogues }}` | Array of catalogues associated with the product | ##### API Details Attributes (Within product) Accessible via `{{ range $api := $product.APIDetails }}` | Attribute | Description | | :- | :- | | `{{ $api.Name }}` | API name | | `{{ $api.Description }}` | API description | | `{{ $api.APIType }}` | API type | | `{{ $api.TargetURL }}` | API target URL | | `{{ $api.ListenPath }}` | API listen path | | `{{ $api.OASUrl }}` | API OAS URL | | `{{ $api.Status }}` | "Active" if API status is active, otherwise "Inactive" | ##### Catalogue Attributes (Within product) Accessible via `{{ range $catalogue := $product.Catalogues }}` | Attribute | Description | | :- | :- | | `{{ $catalogue.Name }}` | Catalogue name | | `{{ $catalogue.VisibilityStatus }}` | Catalogue visibility status | ```html theme={null} {{ range GetProducts req }}
{{ if .Logo.URL }} {{ end }}
{{ .AuthType }}

{{ .ProductName }}

{{ if .Description }}

{{ .Description }}

{{ end }}
{{ end }} ```
#### IsPortalDisabled Returns true (exception: for admins is always enabled) if portal visibility was set to hidden. Expects the request as parameter. ##### Example Usage ``` {{ $portalDisabled := IsPortalDisabled req }} ``` #### IsPortalPrivate Returns true (exception: for admins is always enabled) if portal visibility was set to private. Expects the request as parameter. ##### Example Usage ``` {{ $portalPrivate := IsPortalPrivate req }} ``` #### ProductDocRenderer Returns the configured product OAS renderer (redoc or stoplight). ##### Example Usage ``` {{ $oas_template := ProductDocRenderer }} ``` #### ProviderUpstreamURL Returns the provider upstream URL for a given providerID. Expects the request and a provider ID as parameters. ##### Example Usage ``` {{ $upstreamURL := ProviderUpstreamURL req $thisProduct.ProviderID }} ``` #### SplitStrings Splits a given string with given separator and returns a slice of split strings. ##### Example Usage ``` {{ range $app.Credentials }} ... {{ range SplitStrings .GrantType "," }} ... {{ end }} {{ end }} ``` #### TruncateString Truncates a given string to a given length, returning the truncated string followed by three dots (…). ##### Example Usage ``` {{ TruncateString $api.Description 60 }} ``` #### TypeOfCredential Returns the credential type ("oAuth2.0" or "authToken") given the credential. ##### Example Usage ``` {{ range $app.Credentials }} ... {{ if eq (TypeOfCredential . ) "oAuth2.0" }} ... {{ end }} {{end}} ``` ## Email Templates This section provides a detailed overview of the email template data available in the Tyk Enterprise Developer Portal. The Tyk Enterprise Developer Portal uses a variety of email templates for different purposes, such as user registration and access request status or organization status updates. Each template has access to specific data or functions relevant to its purpose. It's important to note that while email templates can include template data or specific template functions, they do not have access to the global helper functions available in other portal templates. Please refer to [email workflow](/docs/portal/customization/email-notifications) for additional detail on email notifications sent by the portal. ### Available Email Templates * [Access Request Approve/Reject](#access-request-approvereject) * [Access Request Submitted](#access-request-submitted) * [Activate and Deactivate](#activate-and-deactivate) * [Key Expiration Warning](#key-expiration-warning) * [Key Expired](#key-expired) * [New User Request](#new-user-request) * [Organization Approve](#organization-approve) * [Organization Reject](#organization-reject) * [Organization Request](#organization-request) * [Reset Password](#reset-password) * [Targeted Invite](#targeted-invite) * [Welcome User](#welcome-user) #### Access Request Approve/Reject **Template Paths**: * `themes/default/mailers/approve.tmpl` * `themes/default/mailers/reject.tmpl` These templates are used for sending notifications to users when their access requests are approved or rejected. ##### Available Objects There's no data sent to these templates. ##### Example Usage ``` Hi, The API Credentials you provisioned have been rejected. Thanks, The Team ``` #### Access Request Submitted **Template Path**: `themes/default/mailers/submitted.tmpl` This template is used for notifying administrators about pending access requests. ##### Available Objects * `{{ .requests }}`: Returns the list of access requests pending approval. ##### Access Request Attributes Accessible via `{{ range .requests }}` | Attribute | Description | | :- | :- | | `{{ .PlanID }}` | Plan ID associated with access request | | `{{ .Status }}` | Request status | | `{{ .AuthType }}` | Request authentication type | | `{{ .UserID }}` | User ID associated with the request | | `{{ .ClientID }}` | Client ID associated with the request | | `{{ .DCREnabled }}` | Indicates if DCR (Dynamic Client Registration) is enabled for the request | | `{{ .ProvisionImmediately }}` | Indicates if provisioning is immediate for the request | | `{{ .CatalogueID }}` | Catalogue ID associated with the request | ##### Product Attributes (within Access Request) Accessible via `{{ range $product := $acreq.Products }}` | Attribute | Description | | :- | :- | | `{{ $product.ID }}` | Product ID | | `{{ $product.Name }}` | Product name | | `{{ $product.DisplayName }}` | Product display name | | `{{ $product.Description }}` | Product description | | `{{ $product.AuthType }}` | Product authentication type | | `{{ $product.DCREnabled }}` | Indicates if DCR (Dynamic Client Registration) is enabled for the product | ##### Example Usage ```html theme={null}

A new Access request has been submitted. Please log in to the administration dashboard to view the request.

    {{ range $acreq := .requests }}
  • Status: {{ $acreq.Status }}
    User ID: {{ $acreq.UserID }}
    Products:
      {{ range $product := $acreq.Products }}
    • {{ $product.DisplayName }} ({{ $product.AuthType }})
    • {{ end }}
  • {{ end }}
``` #### Activate and Deactivate **Template Paths**: * `themes/default/mailers/activate.tmpl` * `themes/default/mailers/deactivate.tmpl` These templates are used for sending activation and deactivation notifications to users. ##### Available Objects * `{{ .name }}`: Returns the user's full name. ##### Example Usage ``` Hi, {{.name}}
Your account has been activated. ``` #### Key Expiration Warning **Template Path**: `themes/default/mailers/keytoexpire.tmpl` This template is used to notify a developer that one of their credentials is about to expire. ##### Available Objects * `{{ .user }}`: Returns the credential owner. Refer to the User Attributes table below for accessible attributes and methods. * `{{ .credential }}`: Returns the credential that is about to expire (for example, `{{ .credential.CredentialHash }}` returns the credential hash). ##### User Attributes Accessible via `{{ .user }}` | Attribute/Method | Description | | :- | :- | | `{{ .ID }}` | User ID | | `{{ .First }}` | User name | | `{{ .Last }}` | User surname | | `{{ .Email }}` | User email | | `{{ .OrganisationID }}` | User organization ID | | `{{ .DisplayName }}` | User complete name | | `{{ .IdentityProvider }}` | User provider (Portal or Tyk Identity Broker) | | `{{ .GetOrganisationID }}` | User's organization ID | | `{{ .IsAdmin }}` | true if user is an admin | | `{{ .IsOrgAdmin }}` | true if user is an organization admin | | `{{ .DisplayRole }}` | User's role | ##### Example Usage ```

Hi {{ .user.First }},

Your credential {{ .credential.CredentialHash }} is about to expire. Please log in to the developer portal to renew it.

``` #### Key Expired **Template Path**: `themes/default/mailers/keyexpired.tmpl` This template is used to notify a developer that one of their credentials has expired. ##### Available Objects * `{{ .user }}`: Returns the credential owner. Refer to the Key Expiration Warning section for the available `{{ .user }}` attributes. * `{{ .credential }}`: Returns the credential that has expired (for example, `{{ .credential.CredentialHash }}` returns the credential hash). ##### Example Usage ```

Hi {{ .user.First }},

Your credential {{ .credential.CredentialHash }} has expired.

``` #### New User Request **Template Path**: `themes/default/mailers/newuser.tmpl` This template is used for notifying administrators about new user registration requests pending activation. ##### Available Objects * `{{ .user }}`: Returns the new user pending activation. #### User Attributes Accessible via `{{ .user }}` | Attribute/Method | Description | | :- | :- | | `{{ .ID }}` | User ID | | `{{ .First }}` | User name | | `{{ .Last }}` | User surname | | `{{ .Email }}` | User email | | `{{ .OrganisationID }}` | User organization ID | | `{{ .DisplayName }}` | User complete name | | `{{ .IdentityProvider }}` | User provider (Portal or Tyk Identity Broker) | | `{{ .GetOrganisationID }}` | User's organization ID | | `{{ .IsAdmin }}` | true if user is an admin | | `{{ .IsOrgAdmin }}` | true if user is an organization admin | | `{{ .DisplayRole }}` | User's role | | `{{ .Organisation.Name }}` | Organization name | | `{{ .Teams }}` | Array of user teams | | `{{ .Teams.ID }}` | Team ID | | `{{ .Teams.Name }}` | Team name | | `{{ .Teams.Default }}` | Indicates if the team is the default team (true/false) | ##### Example Usage ```

There is a new user request pending. Please approve it from the admin console.

Id: {{ .user.ID }}
User: {{ .user.DisplayName }} ({{ .user.Email }})
Role: {{ .user.Role }}
{{ if gt .user.OrganisationID 0 }} Organisation: {{ .user.Organisation.Name }}
{{ else }} Organisation: Administrators' organisation
{{ end }} {{ if gt (len .user.Teams) 0 }} Teams:

    {{ range .user.Teams }}
  • {{ .Name }}
  • {{ end }}
{{ else }} Teams: none {{ end }}

``` #### Organization Approve **Template Path**: `themes/default/mailers/organisation_approve.tmpl` This template is used for notifying users that their organization creation request has been approved. ##### Available Objects * `{{ site }}`: Returns the application host. ##### Example Usage ``` Hello, The organization registration request has been approved. You can now manage your organization in your dashboard here: https://{{.site}}/portal/private/dashboard Thanks, The team ``` #### Organization Reject **Template Path**: `themes/default/mailers/organisation_reject.tmpl` This template is used for notifying users that their organization creation request has been rejected. ##### Available Objects There's no data sent to this template. ##### Example Usage ``` Hello, The organization registration request has been rejected. Thanks, The team ``` #### Organization Request **Template Path**: `themes/default/mailers/organisation_request.tmpl` This template is used for notifying administrators about new organization creation requests. ##### Available Objects * `{{ .user }}`: Returns the user who made the request. * `{{ .organisationName }}`: Returns the new organization name. #### User Attributes Accessible via `{{ .user }}` | Attribute/Method | Description | | :- | :- | | `{{ .ID }}` | User ID | | `{{ .First }}` | User name | | `{{ .Last }}` | User surname | | `{{ .Email }}` | User email | | `{{ .OrganisationID }}` | User organization ID | | `{{ .DisplayName }}` | User complete name | | `{{ .IdentityProvider }}` | User provider (Portal or Tyk Identity Broker) | | `{{ .GetOrganisationID }}` | User's organization ID | | `{{ .IsAdmin }}` | true if user is an admin | | `{{ .IsOrgAdmin }}` | true if user is an organization admin | | `{{ .DisplayRole }}` | User's role | ##### Example Usage ``` There is a new organization registration request pending. Please approve it from the admin console. The organization name: {{ .organisationName }}. The user: {{ .user.DisplayName }} ({{ .user.Email }}). ``` #### Reset Password **Template Path**: `themes/default/mailers/auth/reset_password.tmpl` This template is used for sending password reset emails to users. ##### Available Functions * `{{ current_user }}`: Returns the current user object. * `{{ reset_password_url }}`: Returns the URL with the token for setting the password. * `{{ confirm_url }}`: Alias for `reset_password_url`; returns the same password-setting URL. * `{{ login_url }}`: Returns the portal login URL (the custom SSO login URL if configured, otherwise the default login URL). ##### User Attributes Accessible via `{{ current_user }}` | Attribute/Method | Description | | :- | :- | | `{{ .ID }}` | User ID | | `{{ .First }}` | User name | | `{{ .Last }}` | User surname | | `{{ .Email }}` | User email | | `{{ .Role }}` | User role | | `{{ .OrganisationID }}` | User organization ID | | `{{ .DisplayName }}` | User complete name | | `{{ .IdentityProvider }}` | User provider (Portal or Tyk Identity Broker) | | `{{ .GetOrganisationID }}` | User's organization ID | | `{{ .IsAdmin }}` | true if user is an admin | | `{{ .IsOrgAdmin }}` | true if user is an organization admin | | `{{ .DisplayRole }}` | User's role | ##### Example Usage ``` {{ $user := current_user}}

Hello {{ $user.DisplayName }},

Someone has requested a link to change your password. You can do this through the link below.

{{reset_password_url}}

If you didn't request this, please ignore this email.

Your password won't change until you access the link above and create a new one.

``` #### Targeted Invite **Template Path**: `themes/default/mailers/auth/targeted_invite.tmpl` This template is used for sending targeted invitations to users. ##### Available Functions * `{{ user }}`: Returns the targeted user object. * `{{ team }}`: Returns the team name to which the user is being invited. * `{{ invite_url }}`: Returns the URL with the token for setting the password. ##### User Attributes Accessible via `{{ user }}` | Attribute/Method | Description | | :- | :- | | `{{ .ID }}` | User ID | | `{{ .First }}` | User name | | `{{ .Last }}` | User surname | | `{{ .Email }}` | User email | | `{{ .Role }}` | User role | | `{{ .OrganisationID }}` | User organization ID | | `{{ .DisplayName }}` | User complete name | | `{{ .IdentityProvider }}` | User provider (Portal or Tyk Identity Broker) | | `{{ .GetOrganisationID }}` | User's organization ID | | `{{ .IsAdmin }}` | true if user is an admin | | `{{ .IsOrgAdmin }}` | true if user is an organization admin | | `{{ .DisplayRole }}` | User's role | ##### Example Usage ```html theme={null} {{ $u := user }} Hi, {{ $u.DisplayName }}

Someone is inviting you to join {{ if $u.IsAdmin }}as an Administrator{{ else }}the {{ team }} team{{end }}. You can do this through the link below.

{{ invite_url }}

If you didn't request this, please ignore this email.

``` #### Welcome User **Template Paths**: * `themes/default/mailers/welcome_admin.tmpl` * `themes/default/mailers/welcome_dev.tmpl` These templates are used for sending welcome emails to new users, with separate templates for administrators and developers. ##### Available Objects * `{{ .user }}`: Returns the user who made the request. Refer to the CurrentUser section for accessible attributes and methods. #### User Attributes Accessible via `{{ .user }}` | Attribute/Method | Description | | :- | :- | | `{{ .ID }}` | User ID | | `{{ .First }}` | User name | | `{{ .Last }}` | User surname | | `{{ .Email }}` | User email | | `{{ .OrganisationID }}` | User organization ID | | `{{ .DisplayName }}` | User complete name | | `{{ .IdentityProvider }}` | User provider (Portal or Tyk Identity Broker) | | `{{ .GetOrganisationID }}` | User's organization ID | | `{{ .IsAdmin }}` | true if user is an admin | | `{{ .IsOrgAdmin }}` | true if user is an organization admin | | `{{ .DisplayRole }}` | User's role | | `{{ .Organisation.Name }}` | organization name | | `{{ .Teams }}` | Array of user teams | | `{{ .Teams.ID }}` | Team ID | | `{{ .Teams.Name }}` | Team name | | `{{ .Teams.Default }}` | Indicates if the team is the default team (true/false) | ```html theme={null}

Welcome to Tyk Enterprise Developer Portal

Hello {{ .user.DisplayName }},

Your account has been created for the {{ .user.Organisation.Name }} organisation.

Your assigned teams:

    {{ range .user.Teams }}
  • {{ .Name }}{{ if .Default }} (Default){{ end }}
  • {{ end }}

We're excited to have you on board!

```
# Customize Themes in Developer Portal Source: https://tyk.io/docs/portal/customization/themes How to customize themes in developer portal ## What is a Theme? The Tyk Enterprise Developer Portal uses **themes** for customizing the live portal. We provide an out of the box theme that is using our own branding, it’s called the `default` theme. You are welcome to use it and modify it for your needs, yet if you want to start with a blank page, you can also create a completely new theme. The following section explains how they are structured and their main concepts. We recommend you to read this if you are creating your own theme, or making extensive changes to the ones we provide. ## File Structure of a Theme Generally speaking, a theme defines an application’s styling, templates and scripts. In the Tyk Developer Portal a `themes` folder is located in the root of the application and is the directory where each theme folder must be added. If you navigate to `path /themes/` you’ll see our default theme which has the following structure: Default Tyk Enterprise Portal theme structure * Manifest file (`theme.json`): It uses JSON syntax to define theme metadata (name, version and author) as well as a list of templates that are part of the theme. * `assets`: It intended for static assets like CSS, JS or images that are used by the theme. All contents from this directory are mounted under the `/assets` path in the portal HTTP server. * `layouts`: The layout is the top level view of your theme. * `views`: The view is rendered as a part of a layout. Each view can be rendered using a different layout. * `partials`: Partials provide an easier way to handle snippets of code that are reused across different views or layouts, for example if you want to inject a JS snippet that’s used in different places, you could set this code in a partial and include it anywhere by using the appropriate 'Go template directive'. In this way you could improve code readability and organize the theme in the most efficient way. ### Manifest File This file should sit in the root of a theme and hold the theme configuration. You can define a name and your templates along other options such as the version and the author. You can find an example of the manifest within the `default` theme that is located in `/themes/default`. The syntax looks as follows: ```json theme={null} { "name": "default", "version": "0.0.1", "author": "Tyk Technologies Ltd. ", "templates": [ { "name": "Content Page", "template": "page", "layout": "site_layout" }, { "name": "Portal Home", "template": "portal_home", "layout": "portal_layout" }, { "name": "Home", "template": "home", "layout": "portal_layout" }, { "name": "Catalogue", "template": "catalogue", "layout": "portal_layout" } ] } ``` The `templates` field establishes a list of available templates. Every template consists of three fields where `name` is a user-friendly name that will be seen on the Admin app when creating a page. `template` is a reference to the template file itself. `layout` is a reference to the layout that will be used to render the previously set template. To illustrate the current template hierarchy, this is what a typically rendered page would look like. The `layout` would be the top level template and base structure of the page: Template structure Also note that the Developer Portal will let you use not just multiple `layouts` and `views` but also any combination of them. These combinations are set in your manifest file (`theme.json`). Regarding `partials`, even though the illustration above shows two partials embedded on the `view` section, `partials` are intended for using in any place. You should be able to embed a `partial` directly into a layout, or even in multiple layouts. Content blocks are explored more deeply in the next sections. To summarise, its relationship with the above hierarchy is when rendering a particular page, a `layout`, a `view` and potentially a combination of partials get loaded from the theme directory. Content blocks are different because their content gets dynamically populated by database content. These contents are created from the Admin section. To be Concluded: * A layout is the wrapper of everything you want to include inside it. So, typically it would consist of tags such as ``, ``, ``, ``, and `<body>`. * A `template` is what we would inject in a layout and specifically within the `<body>` of a layout. * A `partial` can be, for example, the navigation menu so that you can inject it in the layout and it will be visible every time this layout is used ### Go Templates All theme template files use the Go template syntax. You will find every file in the layouts and views. Partials directory uses the `.tmpl` file extension, which is the default Go template extension. Go templates work in a similar way to ERB or EJS templates by letting the user mix HTML code with dynamic values. Sample syntax is as follows: `{{ render “top_nav” }}` The code sample above would execute the `render` template helper, which is a common function that’s used to inject code from other `views` into the current one. You may use this to embed content from other parts of the theme, typically `partials` or `views`. In this case, it will insert a `view` or `partial` named `top_nav` to the template where it’s used. The same delimiters `{{` and `}}` are used for all Go template directives. We’ll explore some of them in the upcoming sections. See the [Go package template documentation](https://pkg.go.dev/text/template#pkg-overview) for more information. ### Content Blocks The Developer Portal themes use content blocks to facilitate content management. A content block is defined as a part of a `view` by using a particular template directive in combination with a name or ID to identify the given block. For example, if you check the `home` template in the default theme (`themes/default/views/home.tmpl`), you will find the following code: ```go theme={null} div class="container"> <div class="row"> <div class="col-sm-6"> <div class="text-container"> <h1>{{.page.Title}}</h1> <p>{{.blocks.HeaderDescription.Content}}</p> <a href="{{.blocks.HeaderButtonLink.Content}}" class="btn btn-primary">{{.blocks.HeaderButtonLabel.Content}}</a> </div> …. ``` There are four code references in the above snippet. In this example we have a header, some text and then a button that act as a link. Let's see what each one is and how it correlates with the UI. 1. `{{ .page.Title }}`. This is the `Title` input in the form UI (Screenshot #1) 2. `{{ .blocks.HeaderDescription.Content }}`. This is the `HeaderDescription` input in the form UI (Screenshot #2) 3. `{{ .blocks.HeaderButtonLink.Content }}`. This is the `HeaderDescription` input in the form UI (Screenshot #3) 4. `{{ .blocks.HeaderButtonLabel.Content }}`. This is the `HeaderButtonLabel` input in the form UI (Screenshot #4) <img alt="Go template blocks and portal UI" /> This will display in your portal as following: <img alt="Example Portal content block" /> In order for a page to render properly the content manager will need to be aware of the content blocks that are required by a particular template. ## Managing Themes The Tyk Enterprise Developer Portal enables the admin users and developers to manage themes and select which theme is visible in the portal. To enable this capability, the portal has theme management UI. ### Create a Theme Follow the example below to create a new theme called "TestTheme" using the default theme as a blueprint: 1. As an admin user, navigate to the Theme management UI and download the default theme. The Tyk Enterprise Developer Portal doesn't allow modifications to the default theme so that you will always have access to the vanilla theme. <img alt="Download default theme" /> 2. Unzip the theme and rename it by modifying the Manifest file as described above. <img alt="Rename theme" /> 3. You can also modify other assets in the theme as described later in this guide. Once all modifications are done, you need to zip the theme and upload it to the portal. <img alt="Zip theme" /> 4. To upload the theme as an admin user, navigate to **Themes** and click on the **Add new theme** button. Please note that the size of individual files should not exceed 5 MB and the total size of all files in the theme should not exceed `PORTAL_MAX_UPLOAD_SIZE`. This parameter is [configurable](/docs/product-stack/tyk-enterprise-developer-portal/deploy/configuration#portal_max_upload_size). <img alt="Add new theme" /> 5. Then click on the **Add theme file** button. <img alt="Add theme file" /> 6. Select the archive that you've created earlier and click on the **Save** button. <img alt="Save new theme" /> 7. Now you should see a success message meaning the theme was successfully created. <img alt="Theme is created" /> ### Preview a Theme The Tyk Enterprise Developer Portal enables the admin users to preview the theme before it gets reflected on the public-facing portal. This enables to review the changes that are made to the theme before exposing them to the developer community. 1. To preview a theme as an admin user, navigate to the **Themes** menu. Select a theme, and click on the **Preview** button. <img alt="Preview theme" /> 2. The previewer will open the selected theme in a new tab. Now you can browse your theme and review the changes. For the demonstration purposes, we've modified the API Catalog page so it displays "Modified catalog" instead of "Product Catalogs". <img alt="Preview theme" /> 3. Once the review is done, you can quit the preview by clicking on the **Quit preview button**. <img alt="Quite theme preview" /> ### Activate a Theme The Tyk Enterprise Developer Portal enables you to have multiple themes at the same time but only one of them is active. 1. As an admin user, navigate to the **Themes** menu. The current status of each theme is displayed in the **Status** column. <img alt="Default theme is the current theme" /> 2. To activate the new theme, click on the **Activate** button. <img alt="Activate theme" /> 3. The selected theme is now active and displayed to all API consumers on the Live portal. <img alt="Modified theme is activated" /> ### Modify an Existing Theme The Tyk Enterprise Developer Portal enables modification to any existing theme, except the default one. 1. To start modification of any existing theme, navigate to the **Themes** menu and download the theme package. <img alt="Download existing theme" /> 2. Unzip the package, do any required modification and zip it back. You should keep the name of the theme. If you need to change the name of the theme, you will need to create a new theme as described above. 3. As an admin user, navigate to the **Themes** menu and select the modified theme. <img alt="Select modified theme" /> 4. Click on the **Add Theme File** button and select the theme archive. <img alt="Add theme file" /> 5. Click on the **Save changes** button to save changes to the theme. <img alt="Save changes" /> 6. If the theme is the current changes to the Live portal, it will be applied immediately. Otherwise, you can preview and activate the theme as described above. ## Upgrading Themes The Tyk Enterprise Developer Portal does not automatically update the default theme with each new release of the product, because doing so could result in the loss of customizations made by customers. Therefore, customers are required to manually upgrade their themes to access the latest updates and fixes. We recommend using GitFlow for the latest theme updates. Alternatively, you can download the theme package from the **Releases** section of the [portal-default-theme](https://github.com/TykTechnologies/portal-default-theme) repository. However, we advise against this method, as it requires you to merge your customized theme with the downloaded one, which is much simpler to accomplish via GitFlow. Follow the guide below to obtain the latest version of the portal theme and merge it with your customized version. ### Merge Latest Changes using Gitflow The default theme for the Tyk Enterprise Developer Portal is located in the [portal-default-theme](https://github.com/TykTechnologies/portal-default-theme) repository. The `main` branch contains code corresponding to the latest stable release. If you wish to check out a specific release (e.g., v1.8.3), you can use tags: ```console theme={null} git checkout tags/1.8.3 -b my-custom-theme branch ``` To organize local development in a way that facilitates seamless theme updates using git merge, follow the steps below: 1. Fork the `portal-default-theme` repo in [github](https://github.com/TykTechnologies/portal-default-theme). <img alt="Fork the portal-theme repo" /> 2. Clone the forked repository: ```console theme={null} git clone https://github.com/my-github-profile/portal-default-theme && cd ./portal-default-theme ``` 3. If you have an existing repository, check if you already have the `portal-default-theme` repo among your remotes before adding it. Execute the following command to check: ```console theme={null} git remote -v | grep 'TykTechnologies/portal-default-theme' ``` Skip the next step if you see the following: ```console theme={null} # portal-default-theme https://github.com/TykTechnologies/portal-default-theme (fetch) # portal-default-theme https://github.com/TykTechnologies/portal-default-theme (push) ``` If the output of the above command is empty, proceed to step 4 to add the `portal-default-theme`. 4. Add the `portal-default-theme` to the remotes by executing the following command: ```console theme={null} git remote add portal-default-theme https://github.com/TykTechnologies/portal-default-theme ``` 5. Create a new local branch that tracks the remote `main` branch. That branch will mirror the latest changes from the `portal-default-theme` main. You will be using it to import the latest changes from the `portal-default-theme` to your custom theme: ```console theme={null} git fetch portal-default-theme main:portal-default-theme-main ``` If you have an existing local branch that tracks the `main` branch in the `portal-default-theme` repo, you can just pull the latest updates: ```console theme={null} git checkout portal-default-theme-main git pull portal-default-theme main ``` 6. To start customizing the theme, create a local develop branch from the `portal-default-theme-main`: ```console theme={null} git checkout portal-default-theme-main git checkout -b dev-branch ``` 7. Once the required customizations are completed, commit the changes to the `dev-branch`. 8. Merge the latest updates from the `portal-default-theme` into the `dev-branch`. Please remember to always pull the latest changes from the `portal-default-theme-main` branch before merging: * Checkout to the portal-default-theme-main and fetch the latest changes. ```console theme={null} git checkout portal-default-theme-main git pull portal-default-theme main ``` * Checkout the dev-branch and merge the changes from the portal-default-theme-main to retrieve the latest changes from the portal-default-theme repo with the customized theme. ```console theme={null} git checkout dev-branch git merge portal-default-theme-main ``` Finally, address merge conflicts and commit changes. <Note> **You have successfully updated your custom theme** Now you can repeat the above described process when upgrading the portal version to make sure you have incorporated the latest theme changes to your customized theme. </Note> ### Upload the Theme to the Portal Once you have merged your local changes with the latest changes from the `portal-default-theme` repo, you need to create a zip archive with the customized theme and upload it to the portal. 1. Create a zip archive with the customized theme. Make sure you zip the content of the `src` folder and not the folder itself. To create a zip archive with the customized theme execute the following: * cd to the `src` directory to make sure you: ```console theme={null} cd ./src ``` * zip the content of the `src` directory: ```console theme={null} zip -r9 default.zip ``` 2. Upload the theme package that is created in the previous step to the portal. You can use the portal's [Admin dashboard](/docs/portal/customization/themes#create-a-theme) or the [admin API](/docs/product-stack/tyk-enterprise-developer-portal/api-documentation/tyk-edp-api) to do it. 3. Finally, you need to [activate](/docs/portal/customization/themes#activate-a-theme) the theme so that it will be applied to the portal. # Customize User Model in Developer Portal Source: https://tyk.io/docs/portal/customization/user-model How to customize user model in developer portal A **Model** in developer portal represents an physical entity. Currenlty, we only have the User model, which represent a user who will be consuming the API by signing up. In this section, you will learn how to customize the User model and the sign-up form for your API consumers. Customizing the User model enables the storage of custom data attributes in the User profile. Additionally, it allows these attributes to be optionally included in the credentials metadata (therefore accessible by the gateway runtime) and exposed in the user sign-up form. This feature enables the implementation of complex business logic when processing API requests. For example, it is particularly useful when the quota for API calls needs to be distributed among all developers of consumer organizations. In such cases, both the quota and the rate limit should be applied at the organization level, rather than according to individual credentials. In this event, the organization ID should be known to the gateway in runtime. This feature helps to achieve that. ## Add Custom Attributes to the User Model To customize the User model, navigate to the **Custom attributes** menu and then select the **User** model. Currently, it is possible to extend only the User model. In future releases we will add the same capabilities to other models. <img alt="Navigate to the User's attributes" /> To add a new attribute to the user model, click on the **Add Custom attribute** button and then fill in properties of the new attribute: * **Attribute ID**: A string that consists of letters (a-zA-Z), numbers (0-9), dashes, and underscores. This is used to reference the attribute in the [Admin APIs](/docs/product-stack/tyk-enterprise-developer-portal/api-documentation/tyk-edp-api) screen. * **Attribute Label**: The attribute's name that is displayed in the UI. * **Description**: Explains the intended usage of this attribute. It is also displayed in the UI. * **Type of attribute**: The type of data that can be stored in this attribute. You cannot change the value of this field once the attribute is created. The following data types are acceptable: * Boolean (true or false). * Dropdown (a list of values). * String. * Number. * **Validation Reg Exp**: A regular expression that is used to validate the value of this field. It is available for the **String** data type only. * **Enable validation**: Determines if the portal should apply the regular expression defined in the **Validation Reg Exp** to validate the value of this attribute when creating or updating a user profile. It is available for the **String** data type only. * **Dropdown Values**: A list of values for the attribute. It is available for the **Dropdown** data type only. * Fields that define the attribute's behavior: * **Write once read many**: Determines whether the value of the attribute can be changed after a user profile is created. This means that when **Write once read many** is enabled, the value of this attribute can be set only during the creation of a user profile. After the user profile is created, the value of this attribute cannot be edited, either through the admin APIs or via the Users UI. * **Add to the key metadata**: Determines if the value of the attribute should be added to the metadata of Auth keys or OAuth2.0 clients when a user creates them. Keep in mind that credential-level metadata will be accessible in both the gateway runtime and gateway database. Please be cautious when handling personally identifiable information (PII) data. * **Required**: Determines if this attribute is required to create a user profile. * **Show on sign-up form**: Determines if this attribute should be visible in the sing-up form. * **Behavior**: Determines if developers can view or edit this attribute. Possible values are: * Developers can view and edit the attribute. * Developers can only view the attribute. * Developers cannot see the attribute. For the purpose of this guide, make sure to tick the **Required** and **Show on sign-up form** checkboxes and select the **Developers can only view the attribute** option. <img alt="Add a new attribute to the user model" /> The new attribute will be added to the user sign-up form, once you have created a new custom attribute and saved changes to the user model by clicking on the **Save** button. <img alt="Customized user sign-up form" /> ## Default Attributes of User Model By default, the portal assigns the following attributes to credentials metadata in the gateway when provisioning API credentials: | Attribute | Name of the credential metadata field | Description | | :- | :- | :- | | Developer ID | DeveloperID | ID of the developer who created the credential | | Application ID | ApplicationID | ID of the application to which it belongs | | Organisation ID | OrganisationID | ID of the organization to which the developer who created the application belongs | | Team IDs | TeamIDs | Array of team IDs to which the developer, who created the application, belongs | Additionally, it is possible to include other default attributes of the User model in the credential metadata fields. However, it is important to remember that metadata at the credential level will be accessible both in the gateway runtime and in the gateway database. Exercise caution when dealing with personally identifiable information (PII). Additional default attributes include: | Attribute | Name of the credential metadata field | Description | | :- | :- | :- | | First name | First | First name of the developer who created the credential | | Last name | Last | Last name of the developer who created the credential | | Email | Email | Email name of the developer who created the credential | | Role | Role | Array of team IDs to which the developer, who created the application, belongs | | Organisation name | Organisation | Name of the organization to which the developer who created the application belongs | | Teams name | TeamNames | Array of team names to which the developer, who created the application, belongs | # Customize Webhooks in Developer Portal Source: https://tyk.io/docs/portal/customization/webhooks How to customize webhooks in developer portal In this section, you will learn how to configure webhooks for events that occur within the portal. Webhooks enable asynchronous integration with the portal by notifying third-party software about an event that has occurred. This feature facilitates the implementation of complex business logic when the portal is integrated with third-party systems such as CRMs and ITSM systems. Typical use cases for the webhooks include: * An asynchronous approval that occurs externally (e.g., in a third-party CRM, ITSM, or another system managing approvals). In this scenario, an access request (such as an API product access request, an organization registration request, or a new developer profile in an inactive state) is created in the portal. The portal then informs the third-party system by calling a registered webhook. * A follow-up action that needs to occur after a specific event in the portal. For example, after a developer profile is created, the customer must create a billing profile in their internal billing system (or a profile in a third-party billing engine such as Moesif, Lago, or a similar service) to automatically update and add this information into custom attributes. ## Create a Webhook in Developer Portal The configuration process consists of two steps: * Configure connectivity to the target endpoint by specify the Target URL, HTTP method, timeout, and request headers. * Select types of events that should be sent to the target endpoint. 1. **Configure the Target Endpoint** Each webhook delivers events to the **Target URL** via the specified **HTTP Method**. Additionally, it's possible to configure timeout header for requests. Finally, for each webhook it's possible to define HTTP headers that should be used for requests to the target URL via the **Headers** section. To add a new header, click on the **Add Headers** button, specify **Name** and **Value** of the header. Note that you can test connectivity to the **Target URL** by clicking on the **Test Connection** button. For testing connectivity, the portal sends a HEAD request to the specified target endpoint. Please note that the connectivity is tested only with the HEAD method, and the test call does not include any headers defined in the **Headers** section. <img alt="Create new webhook channel" /> Once the target endpoint is configured, proceed to the next section to select the types of events that should be sent to that endpoint. 2. **Select Event Types for the Webhook** To finish configuration, select types of events that should be sent to the **Target URL** and save the changes. Refer the docs below to know more about [supported event types](#supported-portal-events) <img alt="Select webhook events" /> ## Supported Portal Events The portal fires the following webhook events: * [UserRegistered](/docs/portal/customization/webhooks#new-user-registered) when a new user is registered. * [UserAccountActivated](/docs/portal/customization/webhooks#user-account-activated) when a user is activated. * [UserAccountDeactivated](/docs/portal/customization/webhooks#user-account-deactivated) when a user is deactivated. * [PasswordReset](/docs/portal/customization/webhooks#password-reset) when a user tries to reset a password. * [ApplicationRegistered](/docs/portal/customization/webhooks#new-application-registered) when a new API consumer application is created. * [CredentialRegistered](/docs/portal/customization/webhooks#new-credential-is-created) when a new API credential is created. * [AccessRequestCreated](/docs/portal/customization/webhooks#new-access-request-created) when a new API access request is created. * [AccessRequestApproved](/docs/portal/customization/webhooks#an-access-request-is-approved) when an API access request is approved. * [AccessRequestRejected](/docs/portal/customization/webhooks#an-access-request-is-rejected) when an API access request is rejected. * [OrganizationRegistered](/docs/portal/customization/webhooks#new-organization-registered) when an API consumer organization is created. * [OrganizationRequestCreated](/docs/portal/customization/webhooks#new-organization-registration-request-created) when a new API consumer organization registration request is created. * [OrganizationRequestApproved](/docs/portal/customization/webhooks#organization-registration-request-is-approved) when an API consumer organization registration request is approved. * [OrganizationRequestRejected](/docs/portal/customization/webhooks#organization-request-is-rejected) when an API consumer organization registration request is rejected. The complete list of events and their corresponding payloads is outlined below. ### New User Registered This event is fired whenever a new user is created via APIs, the admin UI, and the live portal UI (SSO or invite though the org dashboard or self-registration or invite code). Sample payload: ```json theme={null} { "Event": "UserRegistered", "Message": { "ID": 29, "Email": "developer@user.com", "First": "FirstName", "Last": "Lastname", "OrgID": 1, "Provider": "password", "Status": "active", "CreatedAt": "2024-04-22T16:38:54.068565+02:00", "ByUser": 1, "CustomAttributes": [ { "Identifier": "company-name", "Value": "ACME" } ] }, "Timestamp": "2024-04-22T16:38:54.082037+02:00" } ``` ### User Account Activated This event is fired whenever a user (either an admin or a developer) account is activated via APIs or the admin UI. Sample payload: ```json theme={null} { "Event": "UserAccountActivated", "Message": { "ID": 7, "Email": "devD1@tyk.io", "First": "Test", "Last": "User", "OrgID": 7, "Provider": "password", "Status": "active", "CreatedAt": "2024-04-22T15:46:40.128398Z", "ByUser": 1, "CustomAttributes": [ { "Identifier": "boolean-custom-attribute", "Value": "false" } ] }, "Timestamp": "2024-04-22T17:52:22.673077+02:00" } ``` ### User Account Deactivated This event is fired whenever a user account is deactivated via APIs or the admin UI. Sample payload: ```json theme={null} { "Event": "UserAccountDeactivated", "Message": { "ID": 7, "Email": "test@user.io", "First": "Test", "Last": "User", "OrgID": 7, "Provider": "password", "Status": "inactive", "CreatedAt": "2024-04-22T15:46:40.128398Z", "ByUser": 1, "CustomAttributes": [ { "Identifier": "boolean-custom-attribute", "Value": "false" } ] }, "Timestamp": "2024-04-22T17:51:22.24066+02:00" } ``` ### Password Reset This event is fired whenever a user tries to reset their password. Sample payload: ```json theme={null} { "Event": "PasswordReset", "Message": { "ID": 7, "Email": "test@user.io", "First": "Test", "Last": "User", "OrgID": 7, "Provider": "password", "Status": "active", "CreatedAt": "2024-04-22T15:46:40.128398Z", "CustomAttributes": [ { "Identifier": "boolean-custom-attribute", "Value": "false" } ] }, "Timestamp": "2024-04-22T17:58:10.223162+02:00" } ``` ### New Application Registered This event is fired whenever a new app is created via APIs, and the live portal UI (either via the checkout or the create app button in the developer’s dashboard). Sample payload: ```json theme={null} { "Event": "ApplicationRegistered", "Message": { "ID": 1, "Name": "New App", "UserID": 1, "CreatedAt": "2024-04-18T13:29:23.738726+02:00" }, "Timestamp": "2024-04-18T13:29:23.744826+02:00" } ``` ### New Credential Is Created This event is fired whenever a new credential is created via APIs, the admin UI (creation after approval) and the live portal UI. Sample payload: ```json theme={null} { "Event": "CredentialRegistered", "Message": { "ID": 1, "ByUser": 3, "AccessRequestID": 1, "AppID": 3, "CreatedAt": "2024-04-18T13:48:08.489611+02:00" }, "Timestamp": "2024-04-18T13:48:08.494266+02:00" } ``` ### New Access Request Created This event is fired whenever a new access request is created via APIs and the live portal UI. Sample payload: ```json theme={null} { "Event": "AccessRequestCreated", "Message": { "ID": 0, "AppID": 1, "ByUser": 2, "Status": "approved", "ProductIDs": [ 1 ], "PlanID": 2, "CreatedAt": "0001-01-01T00:00:00Z" }, "Timestamp": "2024-04-22T18:09:45.245357+02:00" } ``` ### An Access Request Is Approved This event is fired whenever an access request is approved or auto-approved via the admin APIs or admin UI. Sample payload: ```json theme={null} { "Event": "AccessRequestApproved", "Message": { "ID": 1, "AppID": 3, "ByUser": 3, "Status": "approved", "ProductIDs": [ 1 ], "PlanID": 2, "CreatedAt": "2024-04-18T13:36:02.769109+02:00" }, "Timestamp": "2024-04-18T13:48:08.508925+02:00" } ``` ### An Access Request Is Rejected This event is fired whenever an access request is rejected via the admin APIs or the admin UI. Sample payload: ```json theme={null} { "Event": "AccessRequestRejected", "Message": { "ID": 6, "AppID": 7, "ByUser": 3, "Status": "rejected", "ProductIDs": [], "PlanID": 2, "CreatedAt": "2024-04-18T14:40:15.81038+02:00" }, "Timestamp": "2024-04-18T14:40:28.998297+02:00" } ``` ### New Organization Registered This event is fired whenever a new consumer organization is created via the admin APIs, the live portal ([the become an organization flow](/docs/portal/api-consumer)) or the admin UI. Sample payload: ```json theme={null} { "Event": "OrganisationRegistered", "Message": { "ID": 8, "Name": "Organisation added from Admin UI", "CreatedAt": "2024-04-18T16:12:09.8437+02:00" }, "Timestamp": "2024-04-18T16:12:09.849045+02:00" } ``` ### New Organization Registration Request Created This event is fired whenever a new organization request is created via the live portal ([the become an organization flow](/docs/portal/api-consumer)) or the admin UI. Sample payload: ```json theme={null} { "Event": "OrganisationRequestCreated", "Message": { "Name": "Organisation added from Live Portal (the become an org flow)", "AdminEmail": "dev@tyk.io", "AdminID": 3, "ByUser": 3, "TeamIDs": [], "Status": "pending", "CreatedAt": "2024-04-18T16:13:50.766139+02:00" }, "Timestamp": "2024-04-18T16:13:50.796234+02:00" } ``` ### Organization Registration Request Is Approved This event is fired whenever an organization registration request is approved by an admin user. Sample payload: ```json theme={null} { "Event": "OrganisationRequestApproved", "Message": { "ID": 11, "Email": "dev@tyk.io", "First": "Developer", "Last": "User", "OrgID": 2, "Provider": "password", "Status": "inactive", "CreatedAt": "2024-04-24T15:26:04.312618088Z", "CustomAttributes": [] }, "Timestamp": "2024-04-24T15:26:04.329072196Z" } ``` ### Organization Request Is Rejected This event is fired whenever a new organization request is rejected by an admin user. Sample payload: ```json theme={null} { "Event": "OrganisationRequestRejected", "Message": { "Name": "ACME", "AdminEmail": "dev@tyk.io", "AdminID": 17, "ByUser": 17, "TeamIDs": [], "Status": "rejected", "CreatedAt": "2024-04-18T16:27:34.012613+02:00" }, "Timestamp": "2024-04-18T16:27:50.504654+02:00" } ``` # Developer Apps Source: https://tyk.io/docs/portal/developer-app All about Developer Apps with Tyk Developer Portal ## Introduction Developer Apps are containers for API access credentials in the Tyk Developer Portal. They represent the applications that API Consumers (developers) build using your APIs and provide a structured way to organize, manage, and monitor API usage. When developers want to access your APIs, they create Apps to hold the credentials for specific use cases or projects. Each App can contain credentials for multiple API Products, allowing developers to manage related API access in one place. Developer Apps transform how API consumers interact with your APIs by: * Organizing API credentials by project or use case * Enabling credential management (rotation, revocation) * Providing usage analytics for specific applications * Supporting different authentication types for various integration scenarios In the Tyk Developer Portal, Developer Apps serve as the bridge between API Consumers and your API Products, making credential management intuitive and secure. ## Key Concepts ### App Structure A Developer App consists of: * Basic Information: Name, description, and other metadata * Access Credentials: API keys, OAuth tokens, or other authentication credentials * Product Subscriptions: The API Products the App has access to * Usage Statistics: Analytics on how the App is consuming APIs <img alt="" /> ### App Lifecycle Developer Apps follow a typical lifecycle: * Creation: Developer creates a new App in the Live Portal * Subscription: Developer requests access to API Products for the App * Credential Issuance: Upon approval, credentials are issued to the App * Active Usage: Developer uses the credentials to access APIs * Management: Developer can rotate credentials, request additional access * Retirement: Developer can delete the App when no longer needed <Note> API Owners can create and manage Apps within the Admin Portal from the *API Consumers > Apps* section. From here they can create and delete apps, assign them to different users and issue credentials. In the [Reference Guide](/docs/portal/developer-app#developer-app-reference-guide) below we indicate where fields differ between Admin Portal and Live Portal views. </Note> ### App Ownership Apps are owned by specific developers, but can be configured with different levels of accessibility: * Personal Apps: Created and managed by a single API Consumer user * Team Apps: Accessible to all members of a Team * Organisation Apps: Accessible to all members of an Organisation ## Developer App Reference Guide ### Essential Information #### App Name The identifier for the Developer App. * **Location**: * Admin portal: *Apps > Add/Edit App > App name* * Live portal: *My Dashboard > My apps > Create/Edit App > App name* * **Purpose**: Helps users identify the App in the Developer Portal * **Best Practice**: Use descriptive names that indicate the App's function (e.g., "Mobile Weather App" or "Inventory Integration") #### Description A brief explanation of the App's purpose. * **Location**: * Admin portal: *Apps > Add/Edit App > Description* * Live portal: *My Dashboard > My apps > Create/Edit App > Description* * **Purpose**: Provides context about how the App uses the APIs * **Best Practice**: Include information about the application's purpose and which APIs it needs #### App Owner Only available in the Admin Portal, this gives the facility to reassign an App to a different user. * **Location**: * Admin portal: *Apps > Add/Edit App > App owner* * Live portal: *Not available* * **Purpose**: Associates App ownership with a specific API Consumer * **Note**: Reassigning an App may alter which other users of the Live Portal can [view](/docs/portal/developer-app#visibility) it and have access to its credentials #### Visibility Controls visibility of the App within the Live Portal. When an App is visible to a user, they can retrieve the Access Credentials and so are able to consume the APIs bundled in the Products that the App has been approved to access. * **Location**: * Admin portal: *Apps > Add/Edit App > Visibility* * Live portal: *My Dashboard > My apps > Create/Edit App > Visibility* * **Options**: * Personal: Only the owner (usually the creator of the App) can view the App * Team: All members of Teams of which the owner is a member can view the App * Organisation: All members of the Organisation of which the owner is a member can view the App * **Restrictions**: * When a user is in the [Default Organisation](/docs/tyk-stack/tyk-developer-portal/enterprise-developer-portal/managing-access/manage-api-consumer-organisations#developer-app-visibility), all of their Developer Apps will be restricted to Personal visibility * When a user is *only* in the [Default Team](/docs/tyk-stack/tyk-developer-portal/enterprise-developer-portal/managing-access/manage-api-consumer-organisations#developer-app-visibility-1) of a Custom Organisation, all of their Developer Apps will be restricted to Personal or Organisation level visibility * **Best Practice**: Share Apps when multiple developers need access to the same APIs #### Redirect URL The login redirect URL used in OAuth 2.0 authentication flows. These are specific to the OAuth client * **Location**: Details tab * Admin portal: *Not applicable* * Live portal: *My Dashboard > My apps > Create/Edit App > Redirect URLs* * **Purpose**: Required for OAuth 2.0 authorization code and implicit flows * **Format**: Valid URL where users will be redirected after authentication, multiple URLs can be provided in a comma separated list * **Requirement**: Only required for Apps using OAuth 2.0 authentication ### Product Subscriptions #### Approved Access API Products to which the App currently has access. * **Location**: * Admin portal: *Apps > Add/Edit App > Access and credentials* * Live portal: *My Dashboard > My apps > Create/Edit App > Approved access* * **Details**: * Admin portal: this section provides the opportunity to *view* or *revoke* the access that has been issued to the App. * Live portal: this section provides access to the Access Credentials that have been issued to the App. It also lists the API Products and gives details of the Plan that governs the credentials. Click **Rotate Credentials** for the Provider to issue new credentials, invalidating the previous token. #### Pending Approval API Products for which an access request has been made, but not yet approved. * **Location**: * Admin portal: *Apps > Add/Edit App > Pending requests* * Live portal: *My Dashboard > My apps > Create/Edit App > Pending access* * **Details**: * Admin portal: this section lists any requests pending for the Developer App, with the option to *approve* or *deny* the request. * Live portal: this section lists the API Product and Plan requests pending approval by an API Owner in the Admin Portal. #### Grant Access API Owner can grant a Developer App access to a combination of API Product and Plan with a request from the API Consumer. * **Location**: * Admin portal: *Apps > Add/Edit App > Add credential* * Live portal: *Not available* * **Options**: * *Credential alias*: A name for the credential set, identifying this as credentials assigned by the API Owner * *Type of credential*: Tyk allocated or Custom (manually assigned key:secret pair) * *Authentication method*: The type of credential to be assigned (Auth Token or OAuth 2.0 token) * *Access rights*: Select the API Product and Plan ## Best Practices for Developer Apps * Create purpose-specific Apps: Separate Apps by project or use case rather than combining unrelated API usage * Use descriptive names: Make App names clear and specific to aid in organization * Rotate credentials regularly: Implement a schedule for credential rotation to enhance security * Monitor usage patterns: Regularly review analytics to identify abnormal patterns * Document App purpose: Maintain clear descriptions of each App's function and required APIs # Install Developer Portal Source: https://tyk.io/docs/portal/install Install Tyk Developer Portal using Docker, Kubernetes, or Linux packages. This page explains the architecture, requirements, and how to install and bootstrap the portal. | Edition | Deployment Type | | :- | :- | | Enterprise | Self-Managed, Hybrid | <Note> This page is for installing the **Tyk Developer Portal** (self-managed). If you are looking to use the Developer Portal as part of **Tyk Cloud**, please refer to [the Tyk Cloud documentation](/docs/tyk-cloud/initial-portal-config). </Note> ## Architecture <img alt="Portal deployment diagram" /> <br /> The portal deployment comprises three main components: * **Portal application** - The main portal service * **Database** - Stores metadata including API products, plans, developers, applications, and more * **Asset storage** - Stores CMS assets such as images, themes, and OpenAPI specification files. Assets can reside in the database or separately in an S3 bucket or filesystem volume. Optionally, there could be three additional components: * **3rd party identity provider.** To [enable oAuth2.0 for your API Products](/docs/tyk-stack/tyk-developer-portal/enterprise-developer-portal/api-access/dynamic-client-registration), you'll need to utilize an OpenID-compliant third-party identity provider. It's essential to note that the [Tyk Stack](/docs/tyk-stack) doesn't include third-party identity providers, so you should refer to your Identity Provider's documentation for instructions on configuring and deploying it. This component is optional and required only for enabling oAuth2.0 * **[Tyk Identity Broker](/docs/tyk-identity-broker/overview)**. You only need this component if you want to configure Single Sign-On for the Tyk Developer Portal. For more guidance on this topic, please consult [the Single Sign-On section](/docs/tyk-stack/tyk-developer-portal/enterprise-developer-portal/managing-access/enable-sso) of the documentation * **Email server**. The portal is capable of sending notifications to both admin users and developers when specific events happen within the portal. To enable this feature, you need to specify a connection configuration to an email server or service, and configure other email settings. You can choose to use a server that is installed on your premises or an SMTP-compatible SaaS product. For step-by-step instructions, please refer to [the Email Settings section](/docs/portal/customization/email-notifications) ## Database Requirements The portal requires a database to store metadata. See [Configure SQL Storage](/docs/tyk-configuration-reference/sql) for supported databases, connection configuration, and connection pool tuning. ## Installation Process The portal installation process comprises two steps: 1. **Install the portal application.** To install the portal and launch it in the bootstrap mode, you need to configure your portal instance by specifying settings such as TLS, log level, and database connection. For further guidance on launching the portal, please refer to one of the installation options: [Docker container](/docs/portal/install/docker#docker), [Docker Compose](/docs/portal/install/docker#docker-compose), [Helm chart](/docs/portal/install/kubernetes#legacy-helm-chart), or [RPM package](/docs/portal/install/linux#red-hat-rhel-%2F-centos). 2. **[Bootstrap the portal](#bootstrapping-enterprise-developer-portal)** After you've launched the portal, it will wait for you to provide credentials for the super admin user before it starts accepting traffic. Once you've created the super admin user, the portal will complete its installation process by creating the necessary database structure and initialising the required assets for its operations. You can [bootstrap](#bootstrapping-enterprise-developer-portal) the portal either through the UI or using the bootstrap API. Please refer to [the Bootstrapping section](/docs/portal/install#bootstrapping-developer-portal) for implementing this step. ## Recommended Installation: Docker For development, testing, and proof of concept purposes, we recommend using our Docker installation, which allows you to quickly spin up developer portal on your local machine. <ResponsiveGrid> <Card href="/docs/portal/install/docker#docker"> Install with Docker </Card> <Card href="/docs/portal/install/docker#docker-compose"> Install with Docker Compose </Card> </ResponsiveGrid> ## Alternative Installation Methods <ResponsiveGrid> <Card href="/docs/portal/install/kubernetes"> Install on Kubernetes </Card> <Card href="/docs/portal/install/linux"> Install on Linux Distributions </Card> </ResponsiveGrid> ## Bootstrapping Developer Portal When launching the Tyk Developer portal for the first time, it starts in a special bootstrap mode, which is required to create the first admin user who will act as the super admin. After launching the portal, you can bootstrap it using either the portal UI or the bootstrap API. This section explains how to bootstrap the portal using both the portal UI and the bootstrap API. ### Bootstrapping the Portal via the UI After launching the portal for the first time, you can use its UI to bootstrap it. The portal will display a form that allows you to create a super admin user and set their password. Navigate to the portal UI in your browser to start bootstrapping the portal. You should see the following: <img alt="Portal bootstrap UI" /> Enter the admin email, password, first name, and last name. Then click on the `Register to Developer portal` button to complete the bootstrapping process. The bootstrap process should take no longer than a couple of seconds, so almost instantly the portal will display the following page, which confirms the successful bootstrap. <img alt="Successful bootstrapping" /> Click on the `Login` button to proceed to the login page, where you can use the newly created super admin credentials to log in to the portal. ### Bootstrapping the Portal via the API The second approach to bootstrap the portal is through the bootstrap API, which allows you to programmatically bootstrap the portal. To bootstrap the portal via an API call, call the bootstrap API: ```shell theme={null} curl --location 'http://<your-portal-host>:<your-portal-port>/portal-api/bootstrap' \ --header 'Content-Type: application/json' \ --data-raw '{ "username":"super-admin@tyk.io", "password": "tyk123", "first_name":"John", "last_name":"Doe" }' ``` The bootstrap API accepts the following parameters: * **username** - email of the super admin, it is also used as their login * **password** - the super admin login password * **first\_name** - first name of the super admin * **last\_name** - first name of the super admin The bootstrap process should take no longer than a couple of seconds. You will receive the following response as a confirmation of the successful bootstrapping: ```json theme={null} { "code": "OK", "message": "Bootstrapped user successfully", "data": { "api_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJQcm92aWRlciI6Im5vbmUiLCJVc2VySUQiOiIkMmEkMTAkREF0czZhZTY0ZEZXSkFTbnR2OS8yLmMxcS91VTFhbTRGYk53RVJhTE1Ed2c0NHFsSXJnMkMifQ.ExTNl6UvjQA6WqrPE-7OkSNCBBixc2NGMnh3dnlk5Nw" } } ``` <Note> **Take a note of the api\_token field** You will need this to call other Portal APIs. </Note> ### Login as the super admin After you have bootstrapped the portal, either via the UI or the bootstrap API, you can use the super admin's login credentials to log in to the portal. Open the portal UI in your browser and click on the 'Login' button to open the login page. <img alt="Open the login page" /> <br /> On the login page, enter the super admin credentials for logging into the portal: <img alt="Open the login page" /> <br /> <Note> **Congratulations!** Now you have a fully functional portal. </Note> <br /> You can continue configuring and customizing it either via the UI or the portal admin API. Please refer to [the Tyk Developer Portal Concepts section](/docs/portal/overview/concepts) for further guidance. ## Configuration Reference For detailed configuration options, see the [Environment Variables Reference](/docs/product-stack/tyk-enterprise-developer-portal/deploy/configuration). ## API Documentation The Developer Portal exposes an [API](/docs/product-stack/tyk-enterprise-developer-portal/api-documentation/tyk-edp-api) for programmatic management. # Install Developer Portal on Docker Source: https://tyk.io/docs/portal/install/docker Installation guide for the Tyk Developer Portal on Docker | Edition | Deployment Type | | :- | :- | | Enterprise | Self-Managed, Hybrid, Cloud | ## Prerequisites * [Docker](https://docs.docker.com/get-docker/) * [Enterprise Edition License](/docs/portal/overview/intro#getting-access) <Note> Running on Podman, containerd, or another container runtime? See [Container Runtimes](/docs/deployment-and-operations/container-runtimes). </Note> ## Docker This section explains how to install Tyk Developer Portal in a container using Docker. Depending on your preferences, you can use MariaDB, MySQL or PostgreSQL for the database. In this recipe, the database and the portal container will run on the same network, with the database storing its data on a volume. The portal's CMS assets (images, files and themes) are stored in the database, although this guide provides links to the documentation to use a persistent volume or an S3 bucket as a storage medium for CMS assets. Additionally, all settings for the Portal are configured using an env-file. <Warning> **Note** This document is just an example. Customize all fields, including the username, password, root password, database name and more. Be sure to update the connection DSN in the env-file accordingly. </Warning> ### Using PostgreSQL 1. **Create a network for the portal deployment** To start with, you need to create a Docker network for communication between the database and the portal. Execute the following command to create it: ```console theme={null} docker network create tyk-portal ``` 2. **Create an init script for PostgreSQL** To initialize a PostgreSQL database, you need to create an init script that will later be used to launch the PostgreSQL instance. Copy the content below to a file named `init.sql`, which you will need in the next step. ```sql theme={null} -- init.sql -- Creating user CREATE USER admin WITH ENCRYPTED PASSWORD 'secr3t'; CREATE DATABASE portal; GRANT ALL PRIVILEGES ON DATABASE portal TO admin; ``` 3. **Create the database volume and launch the database** The next step is to launch the PostgreSQL database for the portal. To achieve this, create a data volume for the database first: ```console theme={null} docker volume create tyk-portal-postgres-data ``` Then launch the PostgreSQL instance by executing the following command: ```container theme={null} docker run \ -d \ --name tyk-portal-postgres \ --restart on-failure:5 \ -e POSTGRES_PASSWORD=secr3t \ -e PGDATA=/var/lib/postgresql/data/pgdata \ --mount type=volume,source=tyk-portal-postgres-data,target=/var/lib/postgresql/data/pgdata \ --mount type=bind,src=$(pwd)/init.sql,dst=/docker-entrypoint-initdb.d/init.sql \ --network tyk-portal \ -p 5432:5432 \ postgres:10-alpine ``` **Note** <Warning> The above PostgreSQL configuration is an example. You can customize deployment of your PostgreSQL instance. Please refer to [the PostgreSQL documentation](https://www.postgresql.org/docs/current/installation.html) for further guidance. </Warning> 4. **Create an environment variables file** Creating an environment variables file to specify settings for the portal is the next step. This is optional, as you can alternatively specify all the variables using the -e option when starting your deployment. Here is an example of a sample environment file. For a comprehensive reference of environment variables, please refer to the [configuration section](/docs/product-stack/tyk-enterprise-developer-portal/deploy/configuration) in the Tyk Developer Portal documentation. ```ini theme={null} PORTAL_HOSTPORT=3001 PORTAL_DATABASE_DIALECT=postgres PORTAL_DATABASE_CONNECTIONSTRING=host=tyk-portal-postgres port=5432 dbname=portal user=admin password=secr3t sslmode=disable PORTAL_DATABASE_ENABLELOGS=false PORTAL_THEMING_THEME=default PORTAL_STORAGE=db PORTAL_LICENSEKEY=<your-license-here> ``` Once you have completed this step, you are ready to launch the portal application with PostgreSQL in a Docker container. 5. **Pull and launch the portal container** To pull and launch the portal using Docker, use the command provided below. Ensure that you replace `<tag>` with the specific version of the portal you intend to launch before executing the command, e.g. `tykio/portal:v1.7` for the portal v1.7. You can browse all available versions on [Docker Hub](https://hub.docker.com/r/tykio/portal/tags) and in the [release notes section](/docs/developer-support/release-notes/portal#1-7-0-release-notes). ```console theme={null} docker run -d \ -p 3001:3001 \ --env-file .env \ --network tyk-portal \ --name tyk-portal \ tykio/portal:<tag> ``` This command will launch the portal on localhost at port 3001. Now, you can bootstrap the portal and start managing your API products. 6. **Bootstrap the portal** Now the portal is running on port 3001, but it needs to be bootstrapped by providing credentials for the super admin user since it's the first time you are launching it. Follow the [bootstrapping section](/docs/portal/install#bootstrapping-developer-portal) of the documentation to bootstrap the portal via the UI or the admin API. 7. **Clean up** If you want to clean up your environment or start the installation process from scratch, execute the following commands to stop and remove the portal container: ```console theme={null} docker stop tyk-portal docker rm tyk-portal docker stop tyk-portal-postgres docker rm tyk-portal-postgres docker volume rm tyk-portal-postgres-data ``` ### Using MySQL 1. **Create a network for the portal deployment** To start with, you need to create a Docker network for communication between the database and the portal. Execute the following command to create it: ```console theme={null} docker network create tyk-portal ``` 2. **Create the database volume and launch the database** The next step is to launch the MySQL database for the portal. To achieve this, create a data volume for the database first: ```console theme={null} docker volume create tyk-portal-mysql-data ``` Then launch the MySQL instance by executing the following command: ```console theme={null} docker run \ -d \ --name tyk-portal-mysql \ --restart on-failure:5 \ -e MYSQL_ROOT_PASSWORD=sup3rsecr3t \ -e MYSQL_DATABASE=portal \ -e MYSQL_USER=admin \ -e MYSQL_PASSWORD=secr3t \ --mount type=volume,source=tyk-portal-mysql-data,target=/var/lib/mysql \ --network tyk-portal \ -p 3306:3306 \ mysql:5.7 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --sql-mode=ALLOW_INVALID_DATES ``` <Warning> **Note** The above MySQL configuration is an example. You can customize deployment of your MySQL instance. Please refer to the [MySQL documentation](https://dev.mysql.com/doc/refman/5.7/en/charset-applications.html) for further guidance. </Warning> 3. **Create an environment variables file** Creating an environment variables file to specify settings for the portal is the next step. This is optional, as you can alternatively specify all the variables using the -e option when starting your deployment. Here is an example of a sample environment file. For a comprehensive reference of environment variables, please refer to the [configuration](/docs/product-stack/tyk-enterprise-developer-portal/deploy/configuration) section in the Tyk Developer Portal documentation. ```ini theme={null} MYSQL_ROOT_PASSWORD=sup3rsecr3t MYSQL_DATABASE=portal MYSQL_USER=admin MYSQL_PASSWORD=secr3t PORTAL_HOSTPORT=3001 PORTAL_DATABASE_DIALECT=mysql PORTAL_DATABASE_CONNECTIONSTRING=admin:secr3t@tcp(tyk-portal-mysql:3306)/portal?charset=utf8mb4&parseTime=true PORTAL_DATABASE_ENABLELOGS=false PORTAL_THEMING_THEME=default PORTAL_STORAGE=db PORTAL_LICENSEKEY=<your-license-here> ``` Once you have completed this step, you are ready to launch the portal application with MySQL in a Docker container or via Docker Compose. 4. **Pull and launch the portal container** To pull and launch the portal using Docker, use the command provided below. Ensure that you replace `<tag>` with the specific version of the portal you intend to launch before executing the command, e.g. `tykio/portal:v1.7` for the portal v1.7. You can browse all available versions on [Docker Hub](https://hub.docker.com/r/tykio/portal/tags) and in the [release notes](/docs/developer-support/release-notes/portal#1-7-0-release-notes) section. ```console theme={null} docker run -d \ -p 3001:3001 \ --env-file .env \ --network tyk-portal \ --name tyk-portal \ --mount type=bind,src=/tmp/portal/themes,dst=/opt/portal/themes \ --mount type=bind,src=/tmp/portal/system,dst=/opt/portal/public/system \ tykio/portal:<tag> ``` This command will launch the portal on localhost at port 3001. Now, you can bootstrap the portal and start managing your API products. 5. **Bootstrap the portal** Now the portal is running on port 3001, but it needs to be bootstrapped by providing credentials for the super admin user since it's the first time you are launching it. Follow the [bootstrapping](/docs/portal/install#bootstrapping-developer-portal) section of the documentation to bootstrap the portal via the UI or the admin API. 6. **Clean up** If you want to clean up your environment or start the installation process from scratch, execute the following commands to stop and remove the portal container: ```console theme={null} docker stop tyk-portal docker rm tyk-portal docker stop tyk-portal-mysql docker rm tyk-portal-mysql docker volume rm tyk-portal-mysql-data ``` ## Docker Compose This section provides a clear and concise, step-by-step recipe for launching the Tyk Developer Portal in a container using Docker Compose. Depending on your preferences, you can use MariaDB, MySQL or PostgreSQL for the database. In this recipe, the database and the portal containers will run on the same network, with the database storing it's data on a volume. The portal's CMS assets (images, files and themes) are stored in the database, although this guide provides links to the documentation to use a persistent volume or an S3 bucket as a storage medium for CMS assets. Additionally, all settings for the Portal are configured using an env-file. <Warning> **Note** This document is just an example. Customize all fields, including the username, password, root password, database name and more. </Warning> ### Using PostgreSQL 1. **Create an init script for PostgreSQL** To initialize a PostgreSQL database, you need to create an init script that will later be used to launch the PostgreSQL instance. Copy the content below to a file named `init.sql`, which you will need in the next step. ```sql theme={null} -- init.sql -- Creating user CREATE USER admin WITH ENCRYPTED PASSWORD 'secr3t'; CREATE DATABASE portal; GRANT ALL PRIVILEGES ON DATABASE portal TO admin; ``` 2. **Create an environment variables file for configuring the portal and the database** Creating an environment file to specify settings for the portal is the next step. Here is an example of a sample environment file. For a comprehensive reference of environment variables, please refer to the [configuration section](/docs/product-stack/tyk-enterprise-developer-portal/deploy/configuration) in the Tyk Developer Portal documentation. ```ini theme={null} PORTAL_HOSTPORT=3001 PORTAL_DATABASE_DIALECT=postgres PORTAL_DATABASE_CONNECTIONSTRING=host=tyk-portal-postgres port=5432 dbname=portal user=admin password=secr3t sslmode=disable PORTAL_DATABASE_ENABLELOGS=false PORTAL_THEMING_THEME=default PORTAL_LICENSEKEY=<your-license-here> PORTAL_STORAGE=db ``` Once you have completed this step, you are ready to launch the portal application with PostgreSQL via Docker Compose. 3. **Create a docker-compose file** Before launching the portal using docker-compose, you will need to create a `docker-compose.yaml` file. An example of the portal's docker-compose file is provided below, which you can use as a starting point and further customize to meet your specific requirements. Ensure that you replace `<tag>` with the specific version of the portal you intend to launch before executing the command, e.g. `tykio/portal:v1.7` for the portal v1.7. You can browse all available versions on [Docker Hub](https://hub.docker.com/r/tykio/portal/tags) and in the [release notes section](/docs/developer-support/release-notes/portal#1-7-0-release-notes). ```yaml theme={null} version: '3.6' services: tyk-portal: depends_on: - tyk-portal-postgres image: tykio/portal:<tag> networks: - tyk-portal ports: - 3001:3001 environment: - PORTAL_DATABASE_DIALECT=${PORTAL_DATABASE_DIALECT} - PORTAL_DATABASE_CONNECTIONSTRING=${PORTAL_DATABASE_CONNECTIONSTRING} - PORTAL_THEMING_THEME=${PORTAL_THEMING_THEME} - PORTAL_THEMING_PATH=${PORTAL_THEMING_PATH} - PORTAL_LICENSEKEY=${PORTAL_LICENSEKEY} - PORTAL_STORAGE=${PORTAL_STORAGE} tyk-portal-postgres: image: postgres:10-alpine volumes: - tyk-portal-postgres-data:/var/lib/postgresql/data/pgdata - ${PWD}/init.sql:/docker-entrypoint-initdb.d/init.sql networks: - tyk-portal environment: - POSTGRES_PASSWORD=secr3t - PGDATA=/var/lib/postgresql/data/pgdata volumes: tyk-portal-postgres-data: networks: tyk-portal: ``` 4. **Pull and launch the portal container using docker-compose** To launch the portal using docker-compose, execute the command provided below. ```console theme={null} docker-compose --env-file .env up -d docker-compose --env-file .env up -d ``` This command will launch the portal on localhost at port 3001. Now, you can bootstrap the portal and start managing your API products. 5. **Bootstrap the portal** Now the portal is running on port 3001, but it needs to be bootstrapped by providing credentials for the super admin user since it's the first time you are launching it. Follow the [bootstrapping section](#bootstrapping-enterprise-developer-portal) of the documentation to bootstrap the portal via the UI or the admin API. 6. **Clean up** If you want to clean up your environment or start the installation process from scratch, execute the following commands to stop and remove the portal container: ```console theme={null} docker-compose down ``` ### Using MySQL 1. **Create an environment variables file for configuring the portal and the database** The first step is to create an environment file to specify settings for the portal. Here is an example of a sample environment file. For a comprehensive reference of environment variables, please refer the [configuration section](/docs/product-stack/tyk-enterprise-developer-portal/deploy/configuration) in the Tyk Developer Portal documentation. ```ini theme={null} MYSQL_ROOT_PASSWORD=sup3rsecr3t MYSQL_DATABASE=portal MYSQL_USER=admin MYSQL_PASSWORD=secr3t PORTAL_HOSTPORT=3001 PORTAL_DATABASE_DIALECT=mysql PORTAL_DATABASE_CONNECTIONSTRING=admin:secr3t@tcp(tyk-portal-mysql:3306)/portal?charset=utf8mb4&parseTime=true PORTAL_DATABASE_ENABLELOGS=false PORTAL_THEMING_THEME=default PORTAL_STORAGE=db PORTAL_LICENSEKEY=<your-license-here> ``` Once you have completed this step, you are ready to launch the portal application with MySQL via Docker Compose. 2. **Create a docker-compose file** Before launching the portal using docker-compose, you will need to create a `docker-compose.yaml` file. An example of the portal's docker-compose file is provided below, which you can use as a starting point and further customize to meet your specific requirements. Ensure that you replace `<tag>` with the specific version of the portal you intend to launch before executing the command, e.g. `tykio/portal:v1.7` for the portal v1.7. You can browse all available versions on [Docker Hub](https://hub.docker.com/r/tykio/portal/tags) and in the [release notes section](/docs/developer-support/release-notes/portal#1-7-0-release-notes). ```yaml theme={null} version: '3.6' services: tyk-portal: depends_on: - tyk-portal-mysql image: tykio/portal:<tag> networks: - tyk-portal ports: - 3001:3001 environment: - PORTAL_DATABASE_DIALECT=${PORTAL_DATABASE_DIALECT} - PORTAL_DATABASE_CONNECTIONSTRING=${PORTAL_DATABASE_CONNECTIONSTRING} - PORTAL_THEMING_THEME=${PORTAL_THEMING_THEME} - PORTAL_THEMING_PATH=${PORTAL_THEMING_PATH} - PORTAL_LICENSEKEY=${PORTAL_LICENSEKEY} - PORTAL_STORAGE=${PORTAL_STORAGE} tyk-portal-mysql: image: mysql:5.7 command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci volumes: - tyk-portal-mysql-data:/var/lib/mysql networks: - tyk-portal environment: - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} - MYSQL_DATABASE=${MYSQL_DATABASE} - MYSQL_USER=${MYSQL_USER} - MYSQL_PASSWORD=${MYSQL_PASSWORD} volumes: tyk-portal-mysql-data: networks: tyk-portal: ``` 3. **Pull and launch the portal container using docker-compose** To launch the portal using docker-compose, execute the command provided below. ```console theme={null} docker-compose --env-file .env up -d docker-compose --env-file .env up -d ``` This command will launch the portal on localhost at port 3001. Now, you can bootstrap the portal and start managing your API products. 4. **Bootstrap the portal** Now the portal is running on port 3001, but it needs to be bootstrapped by providing credentials for the super admin user since it's the first you are launching it. Follow the [bootstrapping section](#bootstrapping-enterprise-developer-portal) of the documentation to bootstrap the portal via the UI or the admin API. 5. **Clean up** If you want to clean up your environment or start the installation process from scratch, execute the following commands to stop and remove the portal container: ```console theme={null} docker-compose down ``` # Install Developer Portal on Kubernetes Source: https://tyk.io/docs/portal/install/kubernetes Installation guide for the Tyk Developer Portal on Kubernetes using Helm charts | Edition | Deployment Type | | :- | :- | | Enterprise | Self-Managed, Hybrid | ## Compatible Kubernetes Versions 1.33.x, 1.34.x, 1.35.x ## Prerequisites * [Kubernetes](https://kubernetes.io/docs/setup/) * [Helm 3+](https://helm.sh/docs/intro/install/) * [Enterprise Edition License](/docs/portal/overview/intro#getting-access) <Note> Running on Podman, containerd, or another container runtime? See [Container Runtimes](/docs/deployment-and-operations/container-runtimes). </Note> ## Tyk Stack (New Helm Chart) There are two ways to install the portal on Kubernetes: 1. **As part of Tyk Self-Managed** - Enable `global.components.devPortal` during Tyk Self-Managed deployment using the [tyk-stack chart](/docs/product-stack/tyk-charts/tyk-stack-chart) 2. **Standalone installation** - Use the [tyk-dev-portal](https://github.com/TykTechnologies/tyk-charts/tree/main/components/tyk-dev-portal) Helm chart (described below) This section provides a step-by-step instruction for installing the Tyk Developer Portal as standalone component using the new helm chart. ### Instructions 1. **Create the `tyk-dev-portal-conf` secret** Make sure the `tyk-dev-portal-conf` secret exists in your namespace. This secret will automatically be generated if Tyk Dashboard instance was bootstrapped with [tyk-boostrap](https://artifacthub.io/packages/helm/tyk-helm/tyk-bootstrap) component chart and `bootstrap.devPortal` was set to `true` in the `values.yaml`. If the secret does not exist, you can create it by running the following command. ```bash theme={null} kubectl create secret generic tyk-dev-portal-conf -n ${NAMESPACE} \ --from-literal=TYK_ORG=${TYK_ORG} \ --from-literal=TYK_AUTH=${TYK_AUTH} ``` The fields `TYK_ORG` and `TYK_AUTH` are the Tyk Dashboard *Organization ID* and the Tyk Dashboard API *Access Credentials* respectively. These can be obtained under your profile in the Tyk Dashboard. 2. **Config settings** You must set the following values in the `values.yaml` or with `--set {field-name}={field-value}` using the helm upgrade command: | Field Name | Description | | - | - | | `global.adminUser.email` and `global.adminUser.password` | Set portal admin username and email for bootstrapping | | `global.secrets.devPortal` | Enable portal bootstrapping by providing secret name | | `license` | Tyk license key for your portal installation | | `storage.type` | Portal storage type, e.g. *fs*, *s3* and *db* | | `image.tag` | Developer Portal version. You can get the latest version image tag from [Docker Hub](https://hub.docker.com/r/tykio/portal/tags) | | `database.dialect` | Portal database dialect, e.g. *mysql*, *postgres* | | `database.connectionString` | Connection string to the Portal's database, e.g. for the *mysql* dialect: `admin:secr3t@tcp(tyk-portal-mysql:3306)/portal?charset=utf8mb4&parseTime=true` | In addition to `values.yaml`, you can also define the environment variables described in the [configuration section](/docs/product-stack/tyk-enterprise-developer-portal/deploy/configuration) to further customize your portal deployment. These environment variables can also be listed as a name value list under the `extraEnvs` section of the helm chart. 3. **Launch the portal using the helm chart** Run the following command to update your infrastructure and install the developer portal: ```bash theme={null} helm install tyk-dev-portal tyk-helm/tyk-dev-portal -f values.yaml -n tyk ``` 4. **Bootstrapping the Developer Portal** Follow the [bootstrapping section](/docs/portal/install#bootstrapping-developer-portal) of the documentation to bootstrap the portal via the UI or the admin API. ### Configuration For the full list of configurable values, refer to the [tyk-stack chart guide](/docs/product-stack/tyk-charts/tyk-stack-chart). The sections below cover common production configuration scenarios. > **Note**: Helm chart supports Developer Portal v1.2.0+. ### Pod Security Context The chart ships with hardened defaults for the Portal pod that satisfy the Kubernetes [Restricted Pod Security Standard](https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted): ```yaml expandable highlight={2} theme={null} securityContext: enabled: true fsGroup: 2000 runAsNonRoot: true containerSecurityContext: enabled: true runAsNonRoot: true allowPrivilegeEscalation: false privileged: false readOnlyRootFilesystem: true seccompProfile: type: RuntimeDefault capabilities: drop: - ALL ``` Override these in your `values.yaml` to match your cluster's PSS policy. <Note> From Tyk Helm Chart v5.4.0, no `runAsUser` is set by default. Kubelet uses the `USER` declared in the image, which is a non-root numeric UID, and `runAsNonRoot: true` continues to be enforced. If you pin an older Portal image tag that declares no numeric `USER`, set `runAsUser` explicitly or the pod fails admission with `CreateContainerConfigError`. To omit a block entirely so that the cluster assigns its own IDs, set `enabled: false` on it. See [Deploy Tyk on OpenShift](/docs/tyk-self-managed/install/openshift). </Note> The bootstrap job has its own independent security context, configured under `bootstrapJob.securityContext` and `bootstrapJob.containerSecurityContext`. <Warning> **The bootstrap job does not inherit the Portal pod's security context.** Because its own blocks are empty by default, the job pod is rendered with no security context at all, and clusters enforcing PSS Restricted or Baseline profiles will reject it. Populate `bootstrapJob.securityContext` and `bootstrapJob.containerSecurityContext` with the fields your policy requires. Alternatively, disable the automatic bootstrap and run it manually after deployment. See [Bootstrap Job](#bootstrap-job) below. </Warning> ### Bootstrap Job The bootstrap job runs once after `helm install`. It waits for the Portal pod to become ready, then calls `POST /portal-api/bootstrap` to create the bootstrap admin ([API Owner](/docs/portal/api-owner)) user. The Portal blocks its startup sequence until this call succeeds. **Verify bootstrap completed:** ```bash theme={null} kubectl get jobs -n <namespace> kubectl logs job/dev-portal-job-<release-name> -n <namespace> ``` A successful run logs: `API call completed.` **To disable automatic bootstrap and bootstrap manually**, which is one way to handle clusters with strict Pod Security Standards: 1. Set `global.components.bootstrap: false` in your `values.yaml` and deploy. 2. Wait for the Portal pod to be ready, then send the bootstrap request: ```bash theme={null} curl -X POST http://<portal-service>:<port>/portal-api/bootstrap \ -H "Content-Type: application/json" \ -d '{ "username": "admin@example.com", "password": "your-password", "first_name": "Admin", "last_name": "User" }' ``` Once the call succeeds, the Portal detects the new user and completes its startup sequence. ### Storage The `storage.type` setting controls where the portal stores assets (themes, images, OpenAPI specs). Session storage is always backed by the Portal database, regardless of this setting. | Type | Description | Notes | | - | - | - | | `db` | Assets stored in the Portal database | Recommended for Kubernetes. No PVC required. | | `s3` | Assets stored in an S3-compatible bucket | Suitable for cloud or multi-replica deployments | | `fs` | Assets stored on the container filesystem | Requires a PersistentVolumeClaim | For `fs` storage, configure a PVC using `storage.persistence`: ```yaml theme={null} storage: type: fs persistence: storageClass: "standard" accessModes: - ReadWriteOnce size: 8Gi ``` <Note> `storage.type: fs` with multiple replicas requires a storage class that supports `ReadWriteMany`. Use `db` or `s3` to avoid this constraint. </Note> #### S3 Credentials For `s3` storage, the Portal reads its AWS credentials from a Kubernetes Secret. By default it looks for the keys `DevPortalAwsAccessKeyId` and `DevPortalAwsSecretAccessKey`, in the Secret named by `useSecretName` if you set one, or otherwise in the Secret the chart generates for the release. When the Secret is managed by an external tool such as Crossplane, those key names are usually not under your control. Use `storage.s3.secretRef` to point at a different Secret and name its keys: ```yaml highlight={4} theme={null} storage: type: s3 s3: secretRef: name: portal-s3-credentials accessKeyIdKey: aws_access_key_id secretAccessKeyKey: aws_secret_access_key ``` `secretRef.name` takes precedence over `useSecretName` for S3 credentials only. If `accessKeyIdKey` or `secretAccessKeyKey` is omitted, the defaults above apply. ### Environment Variables Use `extraEnvs` to set any of the variables described in the [configuration section](/docs/product-stack/tyk-enterprise-developer-portal/deploy/configuration). Full Kubernetes environment variable syntax is supported, including `valueFrom`, so you can source values from Secrets and ConfigMaps rather than committing them to your values file: ```yaml expandable theme={null} extraEnvs: - name: PORTAL_REFRESHINTERVAL value: "10" - name: PORTAL_API_SECRET valueFrom: secretKeyRef: name: my-secret key: apiSecret - name: PORTAL_LOG_LEVEL valueFrom: configMapKeyRef: name: portal-settings key: logLevel ``` **`valueFrom` is available from Tyk Helm Chart v5.4.0.** ### Scaling and Replicas The default `kind: StatefulSet` is suited for single-pod deployments. To run multiple replicas, switch to `Deployment`: ```yaml theme={null} kind: Deployment replicaCount: 3 storage: type: db # or s3; both support concurrent access from multiple replicas ``` Portal sessions are stored in the Portal database. All replicas share the same session store automatically via the shared database connection. No sticky sessions or additional session store configuration is required. ### Troubleshooting For bootstrap job failures, crash-loops, database connectivity issues, and license key errors, see [Kubernetes Bootstrap Failures](/docs/portal/troubleshooting/kubernetes-bootstrap-failures). ## Legacy Helm Chart <Warning> **Note** It is recommended to use new helm charts instead of legacy charts. Guide for new charts can be found [here](/docs/portal/install/kubernetes) </Warning> This section provides a clear and concise, step-by-step recipe for installing the Tyk Developer Portal using [legacy helm chart](https://github.com/TykTechnologies/tyk-helm-chart/tree/master/tyk-pro). ### Instructions 1. **Create the `tyk-enterprise-portal-conf` secret** Make sure the `tyk-enterprise-portal-conf` secret exists in your namespace. This secret will automatically be generated during the Tyk Dashboard bootstrap if the `dash.enterprisePortalSecret` value is set to `true` in the `values.yaml`. If the secret does not exist, you can create it by running the following command. ```bash theme={null} kubectl create secret generic tyk-enterprise-portal-conf -n ${NAMESPACE} \ --from-literal=TYK_ORG=${TYK_ORG} \ --from-literal=TYK_AUTH=${TYK_AUTH} ``` Where `TYK_ORG` and `TYK_AUTH` are the Tyk Dashboard Organization ID and the Tyk Dashboard API Access Credentials respectively. Which can be obtained under your profile in the Tyk Dashboard. 2. **Config settings** You must set the following values in the `values.yaml` or with `--set {field-name}={field-value}` with the helm upgrade command: | Field Name | Description | | - | - | | `enterprisePortal.enabled` | Enable Portal installation | | `enterprisePortal.bootstrap` | Enable Portal bootstrapping | | `enterprisePortal.license` | Tyk license key for your portal installation | | `enterprisePortal.storage.type` | Portal database dialect, e.g *mysql*, *postgres* | | `enterprisePortal.storage.connectionString` | Connection string to the Portal's database, e.g for the mysql dialect: `admin:secr3t@tcp(tyk-portal-mysql:3306)/portal?charset=utf8mb4&parseTime=true` | In addition to values.yaml, you can also define the environment variables described in the [configuration section](/docs/product-stack/tyk-enterprise-developer-portal/deploy/configuration) to further customize your portal deployment. These environment variables can also be listed as a name value list under the `extraEnvs` section of the helm chart. 3. **Launch the portal using the helm chart** Run the following command to update your infrastructure and install the developer portal: ```bash theme={null} helm upgrade tyk-pro tyk-helm/tyk-pro -f values.yaml -n tyk ``` <Note> In case this is the first time you are launching the portal, it will be necessary to bootstrap it before you can use it. For detailed instructions, please refer to the [bootstrapping documentation](#bootstrapping-enterprise-developer-portal). </Note> > **Note**: Helm chart supports Developer Portal v1.2.0+. # Install Developer Portal on Linux Distributions Source: https://tyk.io/docs/portal/install/linux Installation guide for the Tyk Developer Portal on Linux distributions using Ubuntu, Debian, Red Hat, and CentOS | Edition | Deployment Type | | :- | :- | | Enterprise | Self-Managed, Hybrid | ## Compatible Operating Systems | Operating System | Version | | - | - | | Ubuntu | 20.04 (focal), 22.04 (jammy), 24.04 (noble) | | Red Hat Enterprise Linux | 7.9, 8.9, 9.3 | | CentOS Stream | Stream 9, Stream 10 | | Debian | 11 (Bullseye), 12 (Bookworm) | | Amazon Linux | 2023.7 | ### Binaries Installation packages for supported Linux distributions are available on [packagecloud.io](https://packagecloud.io/tyk/portal). ## Prerequisites * [Enterprise Edition License](/docs/portal/overview/intro#getting-access) ## Red Hat (RHEL / CentOS) This guide provides a step-by-step recipe for launching the Tyk Developer Portal using an RPM package in Red Hat environment (RHEL / CentOS). <Warning> **Note** This document is just an example. Customize all fields, including the username, password, root password, database name and more. Be sure to update the connection DSN in the env-file accordingly. </Warning> ### Prerequisites To successfully install the Tyk Developer Portal using RPM, your environment should satisfy the following requirements: * Connectivity to [packagecloud.io](https://packagecloud.io/tyk/portal). If your environment doesn't have connectivity to packagecloud, you will need to download the portal package and copy it to the target host. * RPM Package Manager should be installed on the host machine. ### Instructions 1. **Download the portal package** To start with, you need to download the portal package from [packagecloud.io](https://packagecloud.io/tyk/portal). To keep things organized, first create a directory where all installation assets (packages and config files) will be stored: ```console theme={null} mkdir ~/portal-install cd ~/portal-install ``` Next, download the portal package from [packagecloud.io](https://packagecloud.io/tyk/portal) by executing the command below. Ensure to replace `distro-type`, `distro-version` and `package-version` with actual values e.g. [https://packagecloud.io/tyk/portal/packages/ubuntu/noble/portal\_1.16.0\_amd64.deb/download.deb?distro\_version\_id=284](https://packagecloud.io/tyk/portal/packages/ubuntu/noble/portal_1.16.0_amd64.deb/download.deb?distro_version_id=284) for the portal v1.16.0 for Ubuntu 24.04 (noble) amd64. ```console theme={null} wget --content-disposition "https://packagecloud.io/tyk/portal/packages/<distro-type>/<distro-version>/portal_<package-version>_1.x86_64.rpm/download.rpm?distro_version_id=284" ``` 2. **Install the portal package** Once the package is downloaded, you need to install using RPM. Execute the below command to so. Once again, ensure to replace `portal-1.16.0-1.x86_64.rpm` with an actual filename of the package you have downloaded on the previous step. ```console theme={null} sudo rpm -i portal-1.16.0-1.x86_64.rpm ``` 3. **Update the configuration file with your license** Before starting the portal service, you need to configure the portal. Once the rpm package has been installed, the portal configuration file will be located in `/opt/portal/portal.conf`. Initially, the config file is filled with the default values. The minimal configuration change to start the portal is to add the `LicenseKey` property to the config file. The below sample configuration will start the portal on portal 3001 with PostgreSQL as a database, no TLS enabled, and all CMS assets (images, theme files, etc.) are stored in the filesystem. You can, however, customize the provided example and make more suitable for your need using the [configuration](/docs/product-stack/tyk-enterprise-developer-portal/deploy/configuration) reference. ```json theme={null} { "HostPort": 3001, "LicenseKey": "<your-license-here>", "Database": { "Dialect": "postgres", "ConnectionString": "host=tyk-portal-postgres port=5432 dbname=portal user=admin password=secr3t sslmode=disable", "EnableLogs": false }, "Blog": { "Enable": true }, "Site": { "Enable": true }, "Forms": { "Enable": false }, "StoreSessionName": "portal-store-session-name", "PortalAPISecret": "123456", "Storage": "fs", "S3": { "AccessKey": "your-access-key-here", "SecretKey": "your-secret-key-here", "Region": "s3-region", "Endpoint": "if-any", "Bucket": "your-bucket-here", "ACL": "", "PresignURLs": true }, "TLSConfig": { "Enable": false, "InsecureSkipVerify": false, "Certificates":[ { "Name": "localhost", "CertFile": "portal.crt", "KeyFile": "portal.key" } ] } } ``` 4. **Start the portal service** Now when the portal package is installed and the configuration is updated, it is time to start the portal by executing the following command: ```console theme={null} sudo systemctl start portal.service ``` To check status and log of the portal execute the following command: ```console theme={null} systemctl status portal.service ``` 5. **Bootstrap the portal** Now the portal is running on port 3001, but it needs to be bootstrapped by providing credentials for the super admin user since it's the first you are launching it. Follow the [bootstrapping](#bootstrapping-enterprise-developer-portal) section of the documentation to bootstrap the portal via the UI or the admin API. ## Ubuntu / Debian This guide provides a step-by-step recipe for launching the Tyk Developer Portal using a DEB package in Ubuntu / Debian environment. ### Prerequisites To successfully install the Tyk Developer Portal using DEB, your environment should satisfy the following requirements: * Connectivity to [packagecloud.io](https://packagecloud.io/tyk/portal). If your environment doesn't have connectivity to packagecloud, you will need to download the portal package and copy it to the target host. * Debian Package Manager should be installed on the host machine. ### Instructions 1. **Download the portal package** To start with, you need to download the portal package from [packagecloud.io](https://packagecloud.io/tyk/portal). To keep things organized, first create a directory where all installation assets (packages and config files) will be stored: ```console theme={null} mkdir ~/portal-install cd ~/portal-install ``` Next, download the portal package from [packagecloud.io](https://packagecloud.io/tyk/portal) by executing the command below. Ensure to replace `distro-type`, `distro-version` and `package-version` with actual values e.g. [https://packagecloud.io/tyk/portal/packages/ubuntu/noble/portal\_1.16.0\_amd64.deb/download.deb?distro\_version\_id=284](https://packagecloud.io/tyk/portal/packages/ubuntu/noble/portal_1.16.0_amd64.deb/download.deb?distro_version_id=284) for the portal v1.16.0 for Ubuntu 24.04 (noble) amd64. ```console theme={null} wget --content-disposition "https://packagecloud.io/tyk/portal/packages/<distro-type>/<distro-version>/portal_<package-version>_amd64.deb/download.deb?distro_version_id=284" ``` 2. **Install the portal package** Once the package is downloaded, you need to install using DEB. Execute the below command to so. Once again, ensure to replace `portal_1.16.0_amd64.deb` with an actual filename of the package you have downloaded on the previous step. ```console theme={null} sudo dpkg -i portal_1.16.0_amd64.deb ``` 3. **Update the configuration file with your license** Before starting the portal service, you need to configure the portal. Once the deb package has been installed, the portal configuration file will be located in `/opt/portal/portal.conf`. Initially, the config file is filled with the default values. The minimal configuration change to start the portal is to add the `LicenseKey` property to the config file. The below sample configuration will start the portal on portal 3001 with PostgreSQL as a database, no TLS enabled, and all CMS assets (images, theme files, etc.) are stored in the filesystem. You can, however, customize the provided example and make more suitable for your need using the [configuration](/docs/product-stack/tyk-enterprise-developer-portal/deploy/configuration) reference. ```json theme={null} { "HostPort": 3001, "LicenseKey": "<your-license-here>", "Database": { "Dialect": "postgres", "ConnectionString": "host=tyk-portal-postgres port=5432 dbname=portal user=admin password=secr3t sslmode=disable", "EnableLogs": false }, "Blog": { "Enable": true }, "Site": { "Enable": true }, "Forms": { "Enable": false }, "StoreSessionName": "portal-store-session-name", "PortalAPISecret": "123456", "Storage": "fs", "S3": { "AccessKey": "your-access-key-here", "SecretKey": "your-secret-key-here", "Region": "s3-region", "Endpoint": "if-any", "Bucket": "your-bucket-here", "ACL": "", "PresignURLs": true }, "TLSConfig": { "Enable": false, "InsecureSkipVerify": false, "Certificates":[ { "Name": "localhost", "CertFile": "portal.crt", "KeyFile": "portal.key" } ] } } ``` 4. **Start the portal service** Once the configuration is updated, you can start the portal service using the following command: ```console theme={null} sudo systemctl start portal.service ``` To check status and log of the portal execute the following command: ```console theme={null} systemctl status portal.service ``` 5. **Bootstrap the portal** Now the portal is running on port 3001, but it needs to be bootstrapped by providing credentials for the super admin user since it's the first you are launching it. Follow the [bootstrapping](/docs/portal/install#bootstrapping-developer-portal) section of the documentation to bootstrap the portal via the UI or the admin API. # Developer Portal Upgrade Guide Source: https://tyk.io/docs/portal/install/upgrade-guide Step-by-step instructions for upgrading the Tyk Developer Portal across Docker, Kubernetes, and Linux deployments. | Edition | Deployment Type | | :- | :- | | Enterprise | Self-Managed, Hybrid, Cloud | This guide explains how to upgrade the Tyk Developer Portal to a new version. The upgrade process involves replacing the Portal binary or container image, after which the Portal automatically applies any required database migrations on startup. You must also manually upgrade your theme to pick up template changes. ## Before You Upgrade Complete the following steps before starting the upgrade: 2. **Review the release notes** for every version between your current version and the target version. Pay particular attention to the "Breaking Changes" section. See [Portal Release Notes](/docs/developer-support/release-notes/portal). 3. **Back up your database.** The Portal stores its configuration and Product, Plan, and Developer data in the database. Use the native backup utility for your database engine (PostgreSQL, MySQL, or MariaDB). 4. **Back up your theme files.** If you have a custom theme, export it from the Admin Portal or copy the theme directory before upgrading. See [Upgrade Your Theme](#upgrade-your-theme). <Warning> Skipping the theme upgrade after a Portal version bump can cause template rendering errors, UI breakages on the Live Portal, or failed authentication flows. Always upgrade your theme as part of the Portal upgrade process. </Warning> 5. **Note your current Portal version.** You can find this in the Admin Portal under the account settings, or by checking the running container image tag. ## Upgrade Procedure ### Tyk Cloud On Tyk Cloud, the Developer Portal upgrade is managed through the Tyk Cloud Console. You do not run Docker or Kubernetes commands directly. 1. **Open the Tyk Cloud Console** and navigate to your deployment settings. 2. **Select the target Portal version** from the **version** dropdown. 3. **Apply the update.** Tyk Cloud orchestrates the rolling upgrade of the underlying infrastructure on your behalf. Database migrations run automatically during this process. After the upgrade completes, proceed to [Post-Upgrade Verification](#post-upgrade-verification). ### Docker #### Docker Run 1. **Stop and remove the running Portal container.** ```console theme={null} docker stop tyk-portal docker rm tyk-portal ``` 2. **Pull the new Portal image.** Replace `<NEW_VERSION>` with the target version, for example `v1.17.1`. You can browse all available versions on [Docker Hub](https://hub.docker.com/r/tykio/portal/tags). ```console theme={null} docker pull tykio/portal:<NEW_VERSION> ``` 3. **Start the Portal container using the new image.** Use the same `docker run` command from your initial installation, updating only the image tag. The Portal applies any required database migrations automatically on startup. ```console theme={null} docker run -d \ -p 3001:3001 \ --env-file .env \ --network tyk-portal \ --name tyk-portal \ tykio/portal:<NEW_VERSION> ``` 4. **Verify the Portal has started successfully.** Confirm there are no startup errors before proceeding to post-upgrade verification. ```console theme={null} docker logs tyk-portal ``` #### Docker Compose 1. **Update the Portal image tag** in your `docker-compose.yaml` file: ```yaml theme={null} tyk-portal: image: tykio/portal:<NEW_VERSION> ``` 2. **Pull the new image and restart the Portal container.** ```console theme={null} docker-compose pull tyk-portal docker-compose up -d tyk-portal ``` 3. **Verify the Portal has started successfully.** ```console theme={null} docker-compose logs tyk-portal ``` ### Kubernetes [Developer Portal Helm Chart](https://github.com/TykTechnologies/tyk-charts/tree/main/components/tyk-dev-portal) (`tyk-dev-portal`) 1. **Update the Portal image tag** in your `values.yaml`: ```yaml theme={null} image: tag: "<NEW_VERSION>" ``` 2. **Run the Helm upgrade.** ```console theme={null} helm upgrade tyk-dev-portal tyk-helm/tyk-dev-portal \ -f values.yaml \ -n tyk ``` If the Portal is deployed as part of the full [Tyk Stack chart](https://github.com/TykTechnologies/tyk-charts/tree/main/tyk-stack), update `global.components.devPortal.image.tag` and run: ```console theme={null} helm upgrade tyk tyk-helm/tyk-stack \ -f values.yaml \ -n tyk ``` 3. **Watch the rollout.** ```console theme={null} kubectl rollout status deployment/<portal-deployment-name> -n tyk ``` 4. **Check the logs for startup errors.** ```console theme={null} kubectl logs -f <portal-pod-name> -n tyk ``` <Note> If the Portal pod restarts before startup completes, particularly after a theme upgrade, increase the `initialDelaySeconds` value in your readiness and liveness probe configuration to at least 60 seconds. A smaller value may cause Kubernetes to mark the pod as unhealthy and restart it before the application has finished initializing. </Note> ### Linux #### Red Hat / CentOS 1. **Download the new Portal RPM package** from [packagecloud.io](https://packagecloud.io/tyk/portal). Replace `<VERSION>` with the target version. ```console theme={null} wget --content-disposition "https://packagecloud.io/tyk/portal/packages/<distro-type>/<distro-version>/portal_<VERSION>_1.x86_64.rpm/download.rpm?distro_version_id=284" ``` 2. **Upgrade the installed package.** ```console theme={null} sudo rpm -Uvh portal-<VERSION>-1.x86_64.rpm ``` 3. **Review the Portal configuration file** at `/opt/portal/portal.conf`. Consult the release notes for any changes to configuration options required by the new version. 4. **Restart the Portal service.** ```console theme={null} sudo systemctl restart portal.service ``` 5. **Check the service status.** ```console theme={null} systemctl status portal.service ``` #### Ubuntu / Debian 1. **Download the new Portal DEB package** from [packagecloud.io](https://packagecloud.io/tyk/portal). Replace `<VERSION>` with the target version. ```console theme={null} wget --content-disposition "https://packagecloud.io/tyk/portal/packages/<distro-type>/<distro-version>/portal_<VERSION>_amd64.deb/download.deb?distro_version_id=284" ``` 2. **Install the new package.** `dpkg -i` replaces the existing installation. ```console theme={null} sudo dpkg -i portal_<VERSION>_amd64.deb ``` 3. **Review the Portal configuration file** at `/opt/portal/portal.conf`. Consult the release notes for any changes to configuration options required by the new version. 4. **Restart the Portal service.** ```console theme={null} sudo systemctl restart portal.service ``` 5. **Check the service status.** ```console theme={null} systemctl status portal.service ``` ## Upgrade Your Theme To prevent from accidentally overwriting your customizations, the Developer Portal does not automatically update the default theme when the Portal is upgraded. After every Portal upgrade, you must check whether the new version includes theme changes and merge them into your custom theme. See [Upgrading Themes](/docs/portal/customization/themes#upgrading-themes) for the full procedure. <Warning> Skipping the theme upgrade after a Portal version bump can cause template rendering errors, UI breakages on the Live Portal, or failed authentication flows. Always upgrade your theme as part of the portal upgrade process. </Warning> ## Post-Upgrade Verification After the Portal has started, confirm the following before directing traffic to the upgraded instance: 1. **Admin Portal is accessible.** Log in at `http://<your-portal-host>:<port>/portal-admin`. 2) **Provider sync is working.** Navigate to **Providers** in the Admin Portal and confirm your Providers show a healthy sync status. If sync fails after upgrade, check whether any policies in Tyk Dashboard reference API IDs that no longer exist. A stale policy referencing a deleted API will abort the entire sync. Delete or correct the affected policy and re-trigger sync. See also [Troubleshooting > Upgrade Failures](/docs/portal/troubleshooting/upgrade-failures). 3) **Consumer login works.** Open the Live Portal and verify that existing API Consumer users can log in. 4) **API Catalog is visible.** Confirm that published API Products are visible to users on the Live Portal. 5) **Theme renders correctly.** Check the Live Portal for visual regressions or template errors in the browser console. 6) **Review the Portal logs.** Look for any `ERROR` or `WARN` messages that indicate a migration or configuration issue. ## Rollback Procedure If the upgrade causes issues that you cannot resolve, roll back to the previous version using the steps below. <Warning> A rollback involves restoring the database backup taken before the upgrade. Any data changes made after the upgrade, including new users, access requests, and configuration updates, will be lost. </Warning> ### Docker 1. **Stop and remove the upgraded container.** ```console theme={null} docker stop tyk-portal docker rm tyk-portal ``` 2. **Restore the database** from the backup you took before the upgrade. 3. **Start the Portal using the previous image tag.** ```console theme={null} docker run -d \ -p 3001:3001 \ --env-file .env \ --network tyk-portal \ --name tyk-portal \ tykio/portal:<PREVIOUS_VERSION> ``` ### Kubernetes 1. **Restore the database** from the backup you took before the upgrade. 2. **Roll back the Helm release.** First, list available revisions: ```console theme={null} helm history tyk-dev-portal -n tyk ``` Then roll back to the previous revision: ```console theme={null} helm rollback tyk-dev-portal -n tyk ``` To roll back to a specific revision number: ```console theme={null} helm rollback tyk-dev-portal <REVISION_NUMBER> -n tyk ``` ### Linux 1. **Restore the database** from the backup taken before the upgrade. 2. **Downgrade the package** to the previous version. On Ubuntu / Debian: ```console theme={null} sudo apt-get install tyk-portal=<PREVIOUS_VERSION> ``` On Red Hat / CentOS: ```console theme={null} sudo yum downgrade tyk-portal-<PREVIOUS_VERSION> ``` 3. **Restart the Portal service.** ```console theme={null} sudo systemctl restart portal.service ``` ## Common Upgrade Issues For detailed troubleshooting steps for common upgrade failure scenarios, including Admin Portal inaccessible after upgrade, broken Product and Plan sync, and user login failures, see [Troubleshooting > Upgrade Failures](/docs/portal/troubleshooting/upgrade-failures). # View MCP Documentation in the Developer Portal Source: https://tyk.io/docs/portal/mcp-documentation How MCP product documentation renders on the Live Portal, including the Service explorer tab and the docs page for MCP proxies. ## Availability | Component | Version | Editions | | :- | :- | :- | | Developer Portal | v1.19.0 | Enterprise | ## Overview MCP is a documentation type alongside OpenAPI and GraphQL SDL. Once an operator has [added MCP documentation to a Product](/docs/portal/api-products#api-reference-documentation), that content is reachable to developers from the Product's catalogue card and from its detail page, the same way OpenAPI and GraphQL documentation already are. ## Prerequisites * Developer Portal v1.19.0 or later * A Product with an MCP proxy and authored MCP documentation. See [API Reference Documentation](/docs/portal/api-products#api-reference-documentation) to add MCP content to a Product. * The Product published to a Catalog the developer has access to ## The Service Explorer Tab On a Product's detail page, the **Service explorer** tab renders documentation for each of the Product's Services. What it renders depends on the Service's type: * An OpenAPI-documented API renders its specification in Redoc. * A GraphQL-documented API renders the [GraphQL Playground](/docs/tyk-developer-portal/graphql-playground). * An MCP proxy renders the operator-authored markdown content and the MCP server URL. If a Product bundles more than one MCP proxy, a **Select an API** dropdown appears above the rendered content so the developer can switch between them. The first MCP proxy's documentation loads with the page; the rest load on selection from their own docs page. ## The MCP Documentation Page Each MCP proxy also has its own documentation page, reachable from the catalogue card's **Docs** dropdown or from the Service explorer tab. The page shows: * The MCP server URL, with a control to copy it * The operator-authored documentation, rendered from markdown If no documentation has been authored for the MCP proxy, the page states that no documentation has been provided, rather than showing an empty page. <Note> Documentation-only MCP Products (no access policy) are fully supported: their documentation page is reachable the same way as a regular Product's. </Note> ## Content Sanitization Operator-authored MCP markdown is sanitized before it renders on the Live Portal: scripts, event handlers, and `javascript:` URLs are stripped. Standard Markdown and GitHub-Flavored Markdown formatting, including tables and task lists, render as authored. ## What this page does not cover There is no interactive tool testing on this page. Executing an MCP proxy's tools from the Portal is covered by the embedded [MCP Inspector](/docs/portal/mcp-inspector-playground). ## Troubleshooting <AccordionGroup> <Accordion title="The Service explorer tab shows no documentation for an MCP proxy"> No markdown has been authored for that MCP proxy yet. Add documentation from the Product's [API Reference Documentation](/docs/portal/api-products#api-reference-documentation) section in the Admin Portal. </Accordion> <Accordion title="A Product has multiple MCP proxies but only one is visible"> Use the **Select an API** dropdown above the rendered content on the Service explorer tab to switch between the MCP proxies in the Product. </Accordion> </AccordionGroup> # Test MCP Tools with the Embedded MCP Inspector Source: https://tyk.io/docs/portal/mcp-inspector-playground How to use the embedded MCP Inspector to test an MCP product's tools directly from the Developer Portal, before writing agent code. ## Availability | Component | Version | Editions | | :- | :- | :- | | Developer Portal | v1.19.0 | Enterprise | ## Overview The embedded MCP Inspector lets you test an MCP product's tools directly from the Live Portal, so you can validate a connection and see what a tool returns before writing any agent code. ## Open the Inspector The Inspector is available for MCP-typed products only, and appears in two places. On the Product's detail page, the **Service explorer** tab embeds it inline under a **Try it** toggle (**Instructions** shows the operator-authored markdown instead). Selecting **Try it out** on an individual service opens that service's own documentation page, which shows the same **Try it** / **Instructions** toggle. Once the Inspector loads: 1. It lists the tools the MCP server exposes. 2. Select a tool to see its input parameters. 3. Fill in the parameters and call the tool. The response appears in the same view. ## How the Inspector Connects The Inspector does not talk to your MCP server directly. It talks to a proxy hosted by the Portal itself, which forwards the connection to the MCP server URL configured on the product. You cannot point the Inspector at a different server; the Portal always decides the upstream. ## Providing Credentials Unlike the GraphQL Playground, the Inspector does not automatically populate your credentials. Enter your issued credential into the Inspector's connection form yourself. The Portal's proxy forwards it to the MCP server without reading or modifying it. See [Access protected MCP proxies with OAuth 2.1](/docs/portal/mcp-oauth-access) for how the Portal surfaces credentials and token information for a PRM-protected MCP proxy. ## Configuring the /fetch Endpoint's SSRF Guard The Inspector uses a generic HTTP fetcher, `/fetch`, for OAuth and PRM metadata discovery (for example, resolving an authorization server's metadata document). This is separate from the MCP JSON-RPC proxying [described above](#how-the-inspector-connects) and does not affect tool calls. | Setting | Environment variable | Default | Description | | :- | :- | :- | :- | | Block private fetch targets | `PORTAL_MCP_INSPECTOR_BLOCKPRIVATEFETCH` | `true` | When `true`, `/fetch` rejects targets that resolve to loopback, RFC 1918/RFC 4193 private ranges, link-local addresses (including cloud metadata endpoints), CGNAT (`100.64.0.0/10`), or multicast/unspecified addresses. Redirect hops are re-checked against the same rules. | | Public base URL | `PORTAL_MCP_INSPECTOR_PUBLICBASEURL` | Empty | A trusted absolute origin (`scheme://host`) used for the Inspector's proxy address and DNS-rebind checks instead of the request's `Host`/`X-Forwarded-Proto` headers. Leave empty for a single-host deployment; the Portal falls back to the request's own origin. | `PORTAL_MCP_INSPECTOR_BLOCKPRIVATEFETCH` defaults to `true` for security (to prevent SSRF). For local development against a Gateway or authorization server on `localhost` or a private network address, it needs to be set to `false`. The Portal logs a startup warning while it is off. Turning it on only affects `/fetch` (OAuth/PRM metadata discovery), not the Inspector's ability to call MCP tools. If your authorization server or its metadata endpoint is only reachable at a private or internal address, enabling this setting blocks the Inspector from reaching it. ## Vendored Inspector Version The Portal ships v1.0.1 of the [MCP Inspector](https://github.com/modelcontextprotocol/inspector), which supports the [2025-11-25 MCP specification](https://modelcontextprotocol.io/specification/2025-11-25). The Inspector's v2 line supports the newer [2026-07-28 specification](https://modelcontextprotocol.io/specification/2026-07-28); Tyk does not yet support v2, so tools and features that depend on the 2026-07-28 specification are not available in the embedded Inspector. ## Troubleshooting <AccordionGroup> <Accordion title="The Inspector still connects to an old MCP server URL after an operator changes it"> The proxy caches the upstream address per API. If an operator updates the product's MCP server URL, the change may not take effect until the Portal is restarted. </Accordion> <Accordion title="The Inspector shows a connection error immediately"> Check whether the issue is the Portal's proxy or the upstream MCP server itself - the Inspector's banner indicates which side is unreachable. </Accordion> <Accordion title="OAuth/PRM discovery fails with "Target address is not allowed""> `PORTAL_MCP_INSPECTOR_BLOCKPRIVATEFETCH` is enabled, and the authorization server or metadata endpoint the Inspector tried to reach resolves to a private, loopback, link-local, or cloud-metadata address. See [Configuring the /fetch endpoint's SSRF guard](#configuring-the-fetch-endpoints-ssrf-guard). </Accordion> </AccordionGroup> # Access Protected MCP Proxies with OAuth 2.1 Source: https://tyk.io/docs/portal/mcp-oauth-access How the Developer Portal surfaces Protected Resource Metadata and issues credentials for OAuth 2.1-protected MCP proxies, including secret-less PKCE clients. ## Availability | Component | Version | Editions | | :- | :- | :- | | Developer Portal | v1.19.0 | Enterprise | ## Overview An MCP proxy can be protected using OAuth 2.1 and Protected Resource Metadata (PRM, [RFC 9728](https://www.rfc-editor.org/rfc/rfc9728)). PRM tells an MCP client where to obtain a token and for which resource. The Developer Portal surfaces this metadata so a developer who has been granted access to a Product can find out how to get a working token, without needing it explained by the platform team. ## Prerequisites This page describes what a developer sees. It assumes your organization already has: * Developer Portal v1.19.0 or later * At least one Product containing a PRM-protected MCP proxy, published to a Catalog To follow the steps on this page yourself, you need: * A [Developer App](/docs/portal/developer-app) with an approved subscription to a Product containing a PRM-protected MCP proxy. See [Request access to an API](/docs/portal/request-access) if you haven't done this yet. ## Mirror and Static PRM A PRM-protected MCP proxy is configured in one of two modes: * **Mirror mode**: the Portal shows runtime-discovery guidance rather than a fixed authorization server, since the correct authorization server is resolved dynamically. * **Static mode**: the Portal shows the configured resource, authorization server, and scopes directly. ## Where Developers Find Token Information Once a developer's Developer App is approved for a Product containing a PRM-protected MCP proxy, both the Product's detail page and the issued credential's card show a "where to get a token" section for that proxy: the resource, the authorization server, and the required scopes. In mirror mode, this section shows discovery guidance instead of a fixed authorization server value. The section gives you what you need to build a token request against your authorization server yourself, together with the Client ID and Secret shown elsewhere on the card - it does not provide a runnable command. ## Clients That Can't Hold a Secret Some MCP clients, such as VS Code, cannot hold a client secret. For these, the Portal can issue a credential with no secret through Dynamic Client Registration, secured with PKCE instead. When a credential is issued this way, its credential card shows PKCE connection guidance in place of a secret field. ## Scopes If the underlying API requires specific OAuth 2.0 scopes, those scopes are included automatically in the token issued for the credential. The credential card shows the scopes that apply, read-only. ## Known Limitation In static mode, the Portal does not validate the configured authorization server. If it is set incorrectly, the error only appears when a client attempts to exchange a token, not when the configuration is saved. ## Troubleshooting <AccordionGroup> <Accordion title="An MCP client that cannot store a secret has nowhere to put its credential"> The Product's Dynamic Client Registration is issuing a confidential (secret-bearing) client, which a secret-less MCP client such as VS Code cannot use. Ask the Product's administrator to add or switch to a secret-less, PKCE-secured [Client Profile](/docs/portal/api-products#configure-the-product-for-dcr) for Dynamic Client Registration, then request a new credential - an existing confidential credential does not convert automatically. </Accordion> </AccordionGroup> # Core Concepts of Tyk Developer Portal Source: https://tyk.io/docs/portal/overview/concepts Understand the fundamental concepts behind the Tyk Developer Portal, including APIs, access control, and customisation. This page provides an overview of the fundamental concepts that form the foundation of the Tyk Developer Portal. Understanding these concepts is crucial for setting up and effectively managing your portal. <iframe /> ## Portal Structure and Roles User management in the Tyk Developer Portal provides a flexible framework for organizing both the administrators who manage the portal and the developers who consume your APIs. The portal’s hierarchical structure of organizations and teams enables fine-grained access control, collaboration, and visibility management. The Developer Portal’s user management system allows you to: * Separate API management from API consumption through distinct user types * Create organizational hierarchies that mirror your business relationships * Enable collaboration among developer teams while maintaining appropriate boundaries * Control access to API Products, documentation, and credentials * Delegate administrative responsibilities to trusted partners This comprehensive approach to user management ensures that each participant in your API ecosystem has exactly the access and capabilities they need—no more, no less. ### API Consumers API Consumers are the external users who access your APIs through the Live Portal. There are two categories of API Consumer: * **Team Members** are the individual developers who can register, browse catalogs, request access to APIs, and view details of their API consumption. They are restricted to operate within their assigned *Team*. * **Administrators** operate within an *Organisation* and in addition to the capabilies of *Team Members* are also user managers. They can invite new users (both team members and admins), assign users to teams within the Organisation, and delete users from the Organisation. API Consumers exist within a hierarchical structure, allowing for flexible access management: * **Teams** are groups of users who share access to specific catalogs and can collaborate on API projects. Teams provide a way to organize users within an Organisation. Users can be members of multiple Teams. **All users are members of at least one team**. * **Organisation** can contain multiple teams and can represent external companies or business units that consume your APIs. **Teams are always members of only one Organisation**. ### API Owners API Owners are the internal users who manage the publication of API Catalogs onto the Live Portal. They can configure the visual appearance of the portal, create [Catalogs, Products and Plans](/docs/portal/overview/concepts#api-packaging-and-access-control), and manage the Organisation, Teams, and Users granted access to the Live Portal. They operate within the Admin Portal and have read-only access to the Live Portal. ### Developer Portal Views When the Tyk Developer Portal is deployed, two separate views are offered depending on the type of user logging in. The **Live Portal** is the public-facing website where [API Consumers](/docs/portal/overview/concepts#api-consumers) can: * Discover available API Products * Read API documentation * Request access to APIs * Manage their access credentials * Create and manage apps The Live Portal displays the content for a single Organisation (restricting the API Consumer's view according to their access rights). The **Admin Portal** is the private administrative view where [API Owners](/docs/portal/overview/concepts#api-owners) can manage the content displayed in the Live Portal, approve access requests, and configure API Products.. It is also where users, Teams, and Organisation are administered. <br /> <Note> The Live Portal will only display content visible to the Team or Teams of which the logged in API Consumer is a member. </Note> ## API Packaging and Access Control ### API Products An API Product is a strategic packaging of one or more APIs that delivers specific value to API Consumers. Rather than exposing individual API endpoints, API Products allow you to bundle related functionality together with appropriate documentation and access controls. For example, a "Weather API" product might combine current weather data, historical weather records, and forecast APIs into a cohesive offering that solves a specific business need. When creating an API Product, you should focus on: * Which APIs to include in the product * How to document the product's capabilities * Which business problems does the product solve * Who is the target audience for the product ### API Plans API or Subscription Plans (usually referred to simply as Plans) define the terms under which API Consumers can access your API Products and control aspects like: * Rate limits (requests per second/minute/hour) * Quotas (total requests allowed in a period) Different Plans can be attached to the same API Product, allowing you to offer various service tiers (for example, free, basic, and premium) ### API Catalogs Catalogs organize how API Products and Plans are presented to different audiences. They enable you to create customized views of your API offerings based on: * Visibility requirements (public or private) * Target audience (partners, customers, internal teams) * Business domains (finance, marketing, operations) With catalogs, you can: * Make some API Products visible only to specific teams * Offer different plans to different consumer segments * Create specialized marketplaces for different business units For example, you might create: * A public catalog with basic API Products for general consumers * A partner catalog with enhanced API Products and preferential plans * An internal catalog with development and testing APIs <img alt="A sample catalogue set-up" /> ## Consumer Access Management ### Consumer Apps An app serves as a container for access credentials issued to an API Consumer. Apps help organize and manage API access by: * Grouping related API access credentials together * Providing a context for API usage (e.g., "Mobile App", "Website Integration") * Enabling credential management (rotation, revocation) API Consumers can create multiple apps to organize their API usage by project or purpose, and each app can contain credentials for multiple API Products. ### Access Credentials This is the unified naming for any API Keys, Tokens, or Secrets provisioned for a specific app. Access credentials are the security tokens that allow API Consumers to authenticate with your APIs. These depend upon the configuration of those APIs in the API definition managed by Tyk Dashboard and may include: * API keys * OAuth tokens * JWT tokens * Mutual TLS certificates The Developer Portal manages the lifecycle of these credentials, including: * Generation upon provisioning request approval * Secure delivery to the API Consumer * Rotation and revocation as needed ### Provisioning Requests When an API Consumer requests access to an API Product through a specific Plan, a provisioning request is generated. This request: * Captures the consumer's intended use case * Records the API Product and Plan they've selected * Initiates an approval workflow (if required) * Triggers credential generation upon approval Provisioning requests can be configured to require manual approval by an API Owner or to be automatically approved based on the Plan settings. ### Access Flow Types Access Flow Types determine how developers request access to API Products in your Developer Portal. There are two core approaches: * **Direct Access Flow (Recommended)** provides a streamlined, single-product experience where developers can immediately request access to individual APIs without cart management. This eliminates friction with fewer steps and automatic credential handling. * **Cart-Based Flow** offers a traditional shopping cart experience, allowing developers to bundle multiple API products into a single access request. This supports multi-product selection, cart review capabilities, and consolidated checkout. The choice between flows shapes your entire developer experience. Direct Access optimizes for speed and simplicity, while Cart-Based supports complex, multi-API integrations. ## Integration ### API Provider A Provider is a connection to a Tyk Dashboard instance that supplies APIs, policies, and authentication mechanisms to the Developer Portal. The Provider serves as the bridge between your API management infrastructure and the Developer Portal experience. * API Source: Providers make APIs defined in the Tyk Dashboard available for inclusion in API Products * Policy Management: Providers supply the access and rate limit policies used by Products and Plans * Credential Issuance: When developers request access to APIs, the Provider generates and manages the necessary credentials * Multi-Provider Support: The Developer Portal can connect to multiple Providers simultaneously, allowing you to expose APIs from different Tyk environments While the Developer Portal can connect to multiple Providers, each API Product or Plan can only be associated with a single Provider. This is because the access policies that define Products and Plans exist within a specific Provider instance. ### Using Tyk Policies The Developer Portal leverages Tyk's [partitioned policies](/docs/api-management/access-control/policies/applying-policies#partitioned-policies) in two distinct ways: * **for API Products** When creating an API Product, Tyk will associate a policy that defines only access rights to APIs, without rate limiting or quota restrictions. * **for Plans**: When creating a plan, Tyk will associate a policy that defines only quota and rate limiting settings, which will be applied to the APIs included in the associated API Product. This separation allows for flexible combinations of API access and usage constraints. # Set up the Developer Portal Source: https://tyk.io/docs/portal/overview/getting-started Get started quickly with setting up and using the Tyk Developer Portal. ## Introduction Once you have [installed](/docs/portal/install#alternative-installation-methods) your Developer Portal, you'll need to connect it to a Provider (Tyk Dashboard) so that it can synchronise Products and Subscription Plans to appear in your Catalog. You can use a single Developer Portal to publish Catalogs from multiple Providers. In this section we'll take you through the steps to connect to a single Tyk Dashboard installation. <iframe /> ## Registering the Developer Portal with Tyk Dashboard Tyk Dashboard exposes a management API with a user management system that performs fine-grained Role Based Access Control (RBAC). The Developer Portal uses this API to configure and control security policies on the Dashboard. These policies implement the Developer Portal's Products and Plans, and are used in the creation and maintenance of access credentials for Consumers. The Developer Portal thus needs access to the Tyk Dashboard API, so you will need to create a dedicated user on your Tyk Dashboard, following the steps indicated [here](/docs/platform-management/dashboard-users#manage-tyk-dashboard-users). Ensure that this user has the following permissions: | Permission | Access level | | :- | :- | | APIs | Write | | Certificates | Write | | Keys | Write | | Policies | Write | | Analytics | Read | | Users | Read | ### Locating the Access Credentials in Tyk Dashboard 1. Select **Users** from the **User Management** section. 2. In the users list, click **Edit** for the user you have created for the Developer Portal 3. The Secret is the **Tyk Dashboard API Access Credentials** 4. If required, the **Organization ID** is underneath **Reset key** <img alt="API key location" /> ## Configuring the Provider 1. Go to the **Provider** section in the **Admin Portal** 2. Click **Add new Provider** 3. Add your provider details | Field | Description | | :- | :- | | Name | A local name for this Provider; Tyk Developer Portal can publish catalogs for multiple providers | | URL | The host URL for your Tyk Dashboard installation | | Secret | The access credential that the Developer Portal must present when consuming the provider's management API, for example the [Tyk Dashboard API Access Credential](/docs/portal/overview/getting-started#locating-the-access-credentials-in-tyk-dashboard) | | Organization ID | (optional) In some configurations, the Dashboard's [Organization Id](/docs/portal/overview/getting-started#locating-the-access-credentials-in-tyk-dashboard) is required | | Policy tags | (optional) This field can be used to synchronise only a subset of the Products and Plans present on the Provider | | Baseline URL | (optional) The URL of the API Gateway that Consumers will use to make requests to the published APIs | | Insecure skip verify | Check this box to ignore mTLS between the Provider and Developer Portal, often used in test environments | 4. Click **Save Changes** If a tag is defined here, it needs to also be defined in the [Policy](/docs/api-management/policies) for it to be retrieved during the [synchronization](/docs/portal/api-provider#synchronizing-developer-portal-with-providers). If this field is left empty in the Provider configuration, then all partitioned ([access](/docs/portal/api-products#data-distribution-and-management) and [consumption limit](/docs/portal/api-plans#data-distribution-and-management)) policies will be imported from the Tyk instance. For Products and Plans created on the Developer Portal, the policy tag will automatically be created for the corresponding policies created on the Tyk Dashboard. ### Testing the Connection After creating the Provider in your Developer Portal you can test the connection by clicking on **Synchronize** on the **Providers** screen in the Admin Portal. This will display a confirmation message if the connection is made successfully, pulling any policies relating to Products and Plans (with the appropriate Policy tags) over to the Portal. ## Create an Organizational Structure After connecting your Developer Portal to a Provider, the next step is to set up the organizational structure for your Consumers. This structure determines how external developers will access and interact with your APIs. In this guide, you'll learn how to create Organisation (Orgs), Teams, and Consumer Admin users, which form the foundation of your Developer Portal's access control system. When the Portal was [bootstrapped](/docs/portal/install#bootstrapping-developer-portal) a default *org* is created; this is intended to act as a backstop for any Consumer users that have not been assigned to another *Organisation*; **we do not recommend publishing Products and Plans in the default Organisation**. Every Org is automatically provisioned with a default *team* which, again, is intended as a backstop for any user not assigned to another team. **Note** that if you remove a User from all teams in an org, they will automatically be assigned to the default Team. ### Step 1: Create an Organisation Organisation represent companies or business units that will consume your APIs. Start by creating your first Organisation: 1. Log in to the Developer Portal using your API Owner credentials * this will take you to the Admin Portal view 2. Navigate to **Consumers > Organisation** 3. Click **Add Organisation** <img alt="Add a new Organisation" /> 4. Enter a *Name* for the Organisation * this will only be used within the Admin Portal view to identify the org <img alt="Name the new Organisation" /> 5. Click **Save Changes** * note that a *default team* is automatically created within the new org ### Step 2: Create a Team Within the Organisation Teams allow you to group users within an Organisation who need similar API access: 1. Navigate to **Consumers > Teams** 2. Click **Add new team** 3. Enter the following details: * Name: A descriptive name (e.g., "Mobile Developers") * Organisation: Select the org that you created in [step 1](/docs/portal/overview/getting-started#step-1-create-an-organisation) 4. Click **Save changes** 5. Repeat this process to create all the teams you need within the Organisation. ### Step 3: Create a Consumer Admin User Consumer Admin users have special privileges to manage other users within their Organisation: 1. Navigate to **Consumers > Users** 2. Click **Add new user** 3. Enter the user's details: * First Name and Last Name * Email: The user's email address (this will be their login) * Select the **activate developer** checkbox * Select the org that you created in [step 1](/docs/portal/overview/getting-started#step-1-create-an-organisation) * Select the Team that you created in [step 2](/docs/portal/overview/getting-started#step-2-create-a-team-within-the-organisation) * For this tutorial provide an initial password for the user 4. Click **Save changes** ## What's Next? **Congratulations** You have successfully connected your Developer Portal to your Tyk Dashboard provider and created a basic organizational structure for your Developer Portal with a Consumer Admin user account for your client's use. Next, you probably want to add some content to the Portal for them to consume. It's time to [create your first API Catalog](/docs/portal/publish-api-catalog). ### Best Practices * **Plan your hierarchy**: Design your organizational structure before creating Orgs and Teams * **Use descriptive names**: Make Organisation and Team names clear and meaningful * **Start simple**: Begin with a basic structure and expand as needed * **Document your structure**: Keep a record of your Organisation, Teams, and their purposes * **Regular review**: Periodically review and clean up unused Organisation and Teams # Tyk Developer Portal Source: https://tyk.io/docs/portal/overview/intro Learn what the Tyk Developer Portal is, its key features, and how it supports API management. ## Introduction The Tyk Developer Portal is a comprehensive solution designed for API providers who want to publish, monetize, and drive adoption of their APIs. It offers a flexible, full-featured CMS-like system that supports all stages of the API adoption journey, from customizing the look and feel to exposing APIs and enabling third-party developers to register and utilize your APIs. <br /> <Note> **A note on spelling** Throughout this documentation, we use specific spelling conventions to help distinguish between product features and general concepts: * Organisation (with an 's') refers specifically to the entity within the Tyk Developer Portal (sometimes abbreviated to Org) * Organization (with a 'z') refers to real-world businesses or the general concept of organizing This British/American English distinction helps clarify when we're discussing the Tyk Developer Portal feature versus general organizational concepts. </Note> ### Key Capabilities The Developer Portal enables you to: * **Completely customize the portal's appearance** to match your brand identity * **Bundle related APIs into cohesive packages** that deliver specific value to consumers * **Provide comprehensive documentation** including OpenAPI specifications, blogs, and tutorials * **Segment your developer audience** through multiple Organisation and Teams * **Tailor API visibility** with multiple catalogs showing different offerings to different audiences * **Integrate with popular Identity Providers** via Dynamic Client Registration * **Control the developer experience** with customizable sign-up and enrollment flows * **Monitor API usage** with comprehensive analytics <iframe /> ### API Monetization with Tyk Developer Portal The Tyk Developer Portal does not include built-in billing or payment processing for monetizing APIs. However, you can implement monetization strategies through: * Usage-based billing: The traffic logs generated by Tyk Gateway can be associated with access credentials assigned to Developer Apps, allowing for external calculation and billing based on API usage. * Tiered access plans: Create different API Plans with varying usage limits and capabilities that correspond to different pricing tiers. * Manual subscription management: Track subscriptions to API Plans in an external system and manually approve/revoke access based on payment status. If you require integrated API monetization, you can implement a custom integration between the Developer Portal and your billing system using the Portal's [webhook](/docs/portal/customization/webhooks) system. ## Where It Fits in the Tyk Ecosystem The Developer Portal serves as the bridge between your API infrastructure and your developer community. It serves as a central hub where API providers can publish their offerings and API consumers can discover, learn about, and access those APIs. The Developer Portal connects to one or more instances of the Tyk Dashboard (referred to as "Providers"). Each Tyk Dashboard provides access to: * API definitions that configure the Gateway to manage traffic to your upstream services * Security policies that define access rights and rate limits * Authentication mechanisms for securing API access The API owner bundles API definitions into [API Products](/docs/portal/overview/concepts#api-products), which are then published to specific audiences in [API Catalogs](/docs/portal/overview/concepts#api-catalogs). They create [Subscription Plans](/docs/portal/overview/concepts#api-plans) that use security policies to control granular access, for example, gold, silver, and bronze tiers. When an API consumer discovers an API Product they want to use, they request access through the Portal via a Subscription Plan. Once approved (either automatically or by an administrator), the Developer Portal issues a provisioning request to the relevant Tyk Dashboard, which then generates the necessary access credentials (API keys, OAuth tokens, etc.). This separation between the Developer Portal and the Tyk Dashboard creates a clean distinction between: * **API Management** - how you define, secure, and monitor your APIs (handled by Tyk Dashboard) * **API Publishing** - how you present, document, and provide access to your APIs (handled by Developer Portal) This architecture enables you to maintain a consistent developer experience, even if your backend API infrastructure spans multiple environments or utilizes different configurations. ## Getting Started To begin using the Tyk Developer Portal: * [Install Tyk Developer Portal](/docs/portal/install) * [Connect your Portal to a Provider (Tyk Dashboard)](/docs/portal/overview/getting-started) * [Create and publish a Catalog of Products and Plans](/docs/portal/publish-api-catalog) * [Access an API from the Catalog](/docs/portal/request-access) ## Getting Access The Tyk Developer Portal is a licensed product. If you're interested in getting access, [contact our team](https://tyk.io/contact/) to obtain a license or get self-managed trial license by completing the registration on our [website](https://tyk.io/self-managed-trial/). # Publish your first API Catalog Source: https://tyk.io/docs/portal/publish-api-catalog Build an API Catalog on the Tyk Developer Portal. ## Introduction After installing your Developer Portal and configuring your organizational structure, the next step is to create an API catalog with products and plans. This is where you'll package your APIs into consumable products and define how developers can access them. In this guide, you'll learn how to create a catalog, add API products, and define access plans - the essential components that enable developers to discover and consume your APIs. ### Prerequisites Before you begin, ensure you have: * [Installed](/docs/portal/install) the Developer Portal * [Connected](/docs/portal/overview/getting-started#configuring-the-provider) to a Provider (Tyk Dashboard) * [Configured](/docs/portal/overview/getting-started#create-an-organizational-structure) at least one Organisation and Team * [Created](/docs/getting-started/configure-first-api#set-up-your-api) at least one API in Tyk Dashboard that you will make available to your API consumers, for this tutorial we assume this is secured with the [Auth Token](/docs/api-management/authentication/bearer-token) authentication method ## Step 1: Create the API Catalog [Catalogs](/docs/tyk-stack/tyk-developer-portal/enterprise-developer-portal/managing-access/manage-catalogues) determine which API products and plans are visible to different developer audiences. You'll need to create a catalog and then later you'll create content to publish to its audience. 1. Log in to the Developer Portal using your API Owner credentials * this will take you to the Admin Portal view, Navigate to Catalogs 2. Navigate to **Developer Portal > Catalogues** <img alt="Navigate the to catalogues menu" /> 3. Click **Add new catalogue** <img alt="Create a catalogue" /> 4. Enter the following details: * Name: A descriptive name (e.g., "First APIs") * Path URL: select **Sync URL with Name** to auto-complete this field * Visibility: Choose **Private** from the drop-down to restrict access only to selected audience * Audience: Select the team you created [previously](/docs/portal/overview/getting-started#step-2-create-a-team-within-the-organisation) * Catalogue content: Leave this blank for now, as we don't have any API Products or Plans to publish 5. Click **Save Changes** ## Step 2: Create an API Product [API Products](/docs/portal/api-products) bundle one or more APIs into a package that delivers value to developers. When you create an API Product in the Developer Portal, a corresponding [access policy](/docs/api-management/access-control/policies/applying-policies#partitioned-policies) will be created in the Tyk Dashboard (Provider) that configures the access controls that will be applied to API Consumer access credentials created from the Product. 1. Navigate to **Developer Portal > API Products** 2. Click **Add new API Product** <img alt="Add an API Product" /> 3. On the **Details** tab enter the basic product information: <img alt="Configure API Product details" /> * Product name: A unique product name (e.g., "Test product") which will be used by the Provider (Tyk Dashboard) when naming the access policy * Catalogue display name: (optional) Descriptive name that will be used on the Live Portal * Description: (optional) A short summary of the product to engage API consumers * Publish API product to catalogue: Select the catalog you created [previously](/docs/portal/publish-api-catalog#step-1-create-the-api-catalog) * you can leave the other fields empty for now 4. On the **APIs** tab identify which APIs should be accessible via this Product: <img alt="Add APIs" /> * Choose a provider: Select your provider from the dropdown * Choose Authentication method: Select the **Authentication Token** option from the dropdown (or the appropriate [authentication method](/docs/api-management/client-authentication) you've used for your API created in Tyk Dashboard) * Select APIs: Choose at least one API (REST or GraphQL) to include in the Product 5. On the **Documentation** tab optionally upload documentation for the API(s) included in the Product: * REST APIs: Upload an OpenAPI (Swagger) file in JSON or YAML format * GraphQL APIs: Upload a GraphQL SDL file (in .graphql, .graphqls, .gql, or JSON format) <img alt="Add API Specifications" /> 6. On the **"Getting Started" guides** tab, optionally create Product Guides <img alt="Add Product Guides" /> 7. Click **Save Changes** ## Step 3: Create an API Plan [Plans](/docs/portal/api-plans) define the terms under which developers can access your API products. When you create an API Plan in the Developer Portal, a corresponding [limits policy](/docs/api-management/access-control/policies/applying-policies#partitioned-policies) will be created in the Tyk Dashboard (Provider) that configures quotas and rate limits that will be applied to API Consumer access credentials created from the Plan. 1. Navigate to **Developer Portal > Plans** 2. Click **Add new Plan** <img alt="Add a Plan" /> 3. Enter the basic plan information: * Provider: Select your provider from the dropdown * Plan name: A unique plan name (e.g., "Free tier") which will be used by the Provider (Tyk Dashboard) when naming the access policy * Catalogue display name: (optional) Descriptive name that will be used on the Live Portal * Plan description: (optional) A short summary of the plan that will be displayed in the Live Portal <img alt="Add Plan Details" /> 4. Configure the consumption rules (limits) that will be applied to Developer Apps using the plan: * Usage quota: Set a total volume of requests that an App will be permitted to make in a time period, for example 25 requests per hour * Rate limit: Set a maximum frequency of requests that an App will be permitted to make, for example 3 requests per 10 seconds * Key expires after: for this tutorial leave this as **Key never expires** <img alt="Add Plan Limits" /> 5. For this tutorial, select **Auto approve access request** 6. In the **Accessible in the following catalogues** dropdown, select the catalog you created [previously](/docs/portal/publish-api-catalog#step-1-create-the-api-catalog) 7. Click **Save Changes** ## Step 4: Verify the Catalog You can now go back to your Catalog to check that the API Product and Plan have been successfully added, ready for your API Consumers to gain access to your service. 1. Navigate to **Developer Portal > Catalogue** 2. Select the Catalog that you created [previously](/docs/portal/publish-api-catalog#step-1-create-the-api-catalog) 3. Find the **Catalogue content** section and confirm that your Product and Plan are listed 4. Click **Cancel** or **Save Changes** ## What's Next? **Congratulations** You have successfully created an API Product and a Plan and included them in a private Catalog that will only be available to a selected audience in your Developer Portal. Now you're ready to experience the API Consumer side. It's time to [create your first Developer App](/docs/portal/request-access). ### Best Practices * **Start simple**: Begin with one catalog, a few products, and basic plans * **Use clear naming**: Make product and plan names descriptive and intuitive * **Provide complete documentation**: Include comprehensive API documentation for each product * **Test the developer experience**: Go through the subscription process as a developer would * **Gather feedback**: Ask test users about the clarity and usability of your catalog # Request access to an API Source: https://tyk.io/docs/portal/request-access Create aa App to consume a Product published on the Tyk Developer Portal. ## Introduction After setting up your Developer Portal with Organisation, Catalogs, API products, and Plans, it's time to experience the portal from an API Consumer's perspective. In this guide, you'll learn how to log in as an API Consumer, create an application, request API access, and test the API with the provided credentials. This workflow represents the typical experience your API consumers will have when using your Developer Portal to access your APIs. ### Prerequisites Before you begin, ensure you have: * [Installed](/docs/portal/install) the Developer Portal * [Connected](/docs/portal/overview/getting-started#configuring-the-provider) to a Provider (Tyk Dashboard) * [Configured](/docs/portal/overview/getting-started#create-an-organizational-structure) at least one Organisation and Team * [Created](/docs/portal/overview/getting-started#step-3-create-a-consumer-admin-user) an API Consumer Admin user * [Published](/docs/portal/publish-api-catalog) an API Catalog with at least one API Product and Plan ## Step 1: Log in as an API Consumer First, access the Developer Portal as an API consumer: 1. Open your Developer Portal's public URL in a web browser 2. Select **Log In** in the top navigation bar 3. Enter the email address and password for the API consumer admin user you created [previously](/docs/portal/overview/getting-started#step-3-create-a-consumer-admin-user) 4. Select **Log In** You should now be logged in to the Live Portal as an API consumer. You'll see the *default theme* provided by Tyk, all of which is [customisable](/docs/portal/customization) for your brand and workflows. ## Step 2: Browse the API Catalog Next, explore the catalog to find the API product you want to use: 1. Navigate to **Catalogues** in the main navigation * In this tutorial there is only one Catalog, containing a single API Product 2. Select the API Product you created [previously](/docs/portal/publish-api-catalog#step-2-create-an-api-product) * Note that the Authentication requirements are shown in the Catalog view 3. You can now view the details from the perspective of an API Consumer: * Product description * APIs to which the Product grants access * The subscription plans available to you, including their rate limits and quotas * API documentation and Getting Started guides (if you created any) ## Step 3: Create a Developer App You need to create a [Developer App](/docs/portal/developer-app) to contain your API credentials for any API Products to which you are granted access. 1. Hover over your user name in the main navigation and choose **My Dashboard** from the dropdown menu 2. Navigate to **My Apps** in the left hand navigation 3. Select **Create New App** 4. Enter the following details: * App name: A descriptive name (e.g., "Weather Dashboard") * Description: What the app will do with the API * Visibility: select **Personal** so that the access credentials are not visible to other users in your Org * Redirect URL: leave blank, as we're using Auth Token 5. Select **Create App** 6. You will be shown a read-only summary of the App's details; if you want to make changes simply select **Edit details** 7. Select **Back to Apps overview** to return to your *My Apps* list ## Step 4: Request API Access Now, we will request access to the API product through your app. 1. Return to the API product page in the catalog, which we did in [Step 2](/docs/portal/request-access#step-2-browse-the-api-catalog). 2. Select **Access with this plan** 3. Select **Go to cart** 4. You are now on the access request form where you can see the API Product and Plan that you've selected. If granted access for this combination, you will be issued access credentials to use in your API requests. These must be associated with a Developer App. We just created an App, so select **Existing app** and choose your App from the dropdown 5. Select **Submit request** ## Step 5: View Your API Access Credentials When we [created](/docs/portal/publish-api-catalog#step-3-create-an-api-plan) the Plan, we configured it to automatically approve access requests, so Tyk will have created access credentials immediately. If we hadn't selected auto-approve, the request would appear in the Admin Portal for an API Owner to approve. Let's find the access credentials so that we can start to consume the API: 1. Hover over your user name in the main navigation and choose **My Dashboard** from the dropdown menu 2. Navigate to **My Apps** in the left hand navigation 3. Select the app you created [previously](/docs/portal/request-access#step-3-create-a-developer-app) 4. In the API Credentials section, you'll see your access credentials * Click Show to reveal the API key * Copy the credentials for use in step 6 ## Step 6: Test the API Finally, let's use your credentials to make a test API request: **REST APIs** 1. Navigate to the API Product details page, either from the App details or Catalog 2. You can see the *listen path* for the API and, if you provided API documentation when creating the Product, may have more detail of the available endpoints 3. Open a terminal or API testing tool (like Postman or cURL) 4. Construct your API request using the access credentials issued in [Step 5](/docs/portal/request-access#step-5-view-your-api-access-credentials) * For example, with cURL: ``` curl -X GET "https://your-api-gateway.com/your-api-path" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" ``` 5. Send the request and verify that you receive a successful response **GraphQL APIs** If your API Product contains a GraphQL API and you provided a valid GraphQL server URL, you can test it interactively using the built-in GraphQL Playground in the Developer Portal. ## Troubleshooting If you encounter issues when testing the API: * Authentication Errors: Verify that you're including the correct API key and using the proper authentication method * Rate Limit Exceeded: Check if you've exceeded the rate limits defined in your plan * Access Denied: Ensure your access request has been approved * Endpoint Not Found: Confirm you're using the correct API endpoint URL ## What's Next? **Congratulations** You have successfully created a Developer App, requested access to an API Product and accessed an API using the credentials issued by the Developer Portal. This concludes the Getting Started tutorial for Tyk Developer Portal! Check out the rest of the documentation for more details on each of the elements we've used in the tutorial and full guidance on how to customise Tyk Developer Portal to give your API consumers the best possible experience. # Migrate Resources Between Environments Source: https://tyk.io/docs/portal/resource-migration Learn how to migrate resources between environments in the Tyk Enterprise Developer Portal. ## Migrate Resources Between Environments This guide explains how to migrate Developer Portal resources (API Products, Plans, Tutorials etc.) between different portal environments. This capability was made possible with introduction of [Custom IDs](#custom-ids-in-developer-portal) (more on this later) in v1.13. ## Prerequisites Before you begin, make sure the following are true: * Your Tyk Developer Portal version is 1.13 or later. * All resources in your source environment have **Custom IDs** (CIDs) assigned. Resources created after version 1.13 automatically include a CID, while resources from earlier versions receive CIDs through the portal's startup process. * You have admin access to both the source and target environments. ## Custom IDs in Developer Portal Starting with Portal 1.13, we introduced **Custom IDs (CIDs)** - additional persistent identifiers that work alongside database IDs to provide stable references across environments and recreations. While database IDs remain the primary internal identifiers, CIDs provide a reliable way to track and maintain relationships between resources across different environments. ### The Role of Database IDs and CIDs Resources in the Tyk Developer Portal use both types of identifiers: * **Database IDs**: Primary internal identifiers that are automatically generated and managed by the database. * **Custom IDs (CIDs)**: Additional stable identifiers that remain consistent across environments. ### The Problem with Database-Generated IDs Before Portal 1.13, resources were identified solely by database-generated IDs. While this worked for single-environment setups, it caused challenges when: * Migrating resources between environments. * Recreating or restoring resources. * Maintaining relationships between connected resources. For example, if you recreated an API product that was linked to a plan, the product would receive a new database ID. This would break the connection between the product and plan, requiring manual intervention to fix the relationship. ### Benefits of Custom IDs (CIDs) Custom IDs solve these problems by providing: * Persistent identification across environments. * Stable reference points for resource relationships. * Reliable migration and synchronization capabilities. Resources that now support CIDs include: * OAuth Providers and Client Types * Products, Plans, Tutorials, and OAS Documents * Organisations and Teams * Pages and Content Blocks These resources are now easily transferable between environments, with their relationships preserved via CIDs, ensuring smooth migrations and consistent management. ### Automatic CID Assignment When upgrading to Tyk Portal 1.13 from an earlier version, the portal automatically runs a **background process** to assign CIDs to resources created in previous versions. This process also runs every time the portal starts, ensuring any new resources without CIDs are retroactively assigned one, whether after an upgrade or a fresh installation. You can fetch a specific organisation using either its database ID or CID. For example, to fetch the "foo" organisation: **Using database ID:** ```bash theme={null} curl -X GET 'http://localhost:3001/portal-api/organisations/27' \ -H "Authorization: ${TOKEN}" \ -H 'Content-Type: application/json' \ -H 'Accept: application/json' ``` **Using CID (recommended):** ```bash theme={null} curl -X GET 'http://localhost:3001/portal-api/organisations/2sG5umt8rGHMiwjcgaHXxwExt8O' \ -H "Authorization: ${TOKEN}" \ -H 'Content-Type: application/json' \ -H 'Accept: application/json' ``` While both methods work, using CIDs is recommended as they remain consistent across environments. ## Step-by-Step Instructions In this guide, we'll walk through the process of migrating selected organisations and their teams from one environment (Environment A) to another (Environment B). This involves exporting data from the source environment and importing it into the target environment. <br /> <Note> This guide only migrates the `Organization` and `Teams` resources from the developer portal; the same process must be repeated for other resources. </Note> ### Example Scenario * **Source**: Environment A at `https://portal-env-a.example.com` * **Target**: Environment B at `https://portal-env-b.example.com` * **Goal**: Migrate organisations and their associated teams ### Setting Up Environment Variables Before running the migration scripts, you'll need to set up authentication tokens for both environments. You can find these tokens in the Developer Portal UI: 1. Log in to the Developer Portal as an admin 2. Click on your user profile in the top right corner 3. Copy **API credential** ```bash theme={null} # For Environment A (source) export ENV_A_TOKEN="your-source-environment-token" # For Environment B (target) export ENV_B_TOKEN="your-target-environment-token" ``` ### Export Organisations from Environment A To start, you'll want to gather the relevant data from Environment A. This ensures you have everything you need for a smooth migration. The data is saved into a JSON file, making it easy to handle during the import process. Here's an example of how you can export organisations from Environment A: ```bash theme={null} # Fetch organisations from Environment A response=$(curl -s -H "Authorization: ${ENV_A_TOKEN}" \ -H "Content-Type: application/json" \ -H "Accept: application/json" \ "https://portal-env-a.example.com/organisations?page=1&per_page=50") # Process each organisation echo "$response" | jq -c '.[] | select(.Name != "Default Organisation") | del(.ID, .CreatedAt, .UpdatedAt, .Teams)' > data/organisations.json ``` ### Export Teams from Environment A After exporting organisations, the next step is to export the teams associated with each organisation. We exclude default teams since these are created automatically by the portal, and dealing with them could lead to conflicts. The data is saved into JSON files for structured storage and easy access during the import process. Here's an example of how you can export teams from Environment A: ```bash theme={null} # Read each organisation and fetch its teams while IFS= read -r org; do org_cid=$(echo "$org" | jq -r '.CID') echo "Fetching teams for organisation CID: $org_cid..." # Fetch teams for the organisation teams_response=$(curl -s -H "Authorization: ${ENV_A_TOKEN}" \ -H "Content-Type: application/json" \ -H "Accept: application/json" \ "https://portal-env-a.example.com/organisations/$org_cid/teams?page=1&per_page=50") # Process each team echo "$teams_response" | jq -c '.[] | select(.Name | endswith("All users") | not) | del(.Users)' > "data/teams_${org_cid}.json" done < data/organisations.json ``` ### Import Organisations to Environment B Now, let's move those organisations into Environment B, one by one. The goal here is to recreate the organisational structure in Environment B accurately. By using the JSON files, you ensure that each organisation is imported correctly, keeping the relationships intact from Environment A. Here's an example of how you can import organisations into Environment B: ```bash theme={null} # Read each organisation and import it while IFS= read -r org; do org_cid=$(echo "$org" | jq -r '.CID') echo "Importing organisation CID: $org_cid..." # Import the organisation curl -s -o /dev/null -w "%{http_code}" -X POST \ -H "Authorization: ${ENV_B_TOKEN}" \ -H "Content-Type: application/json" \ -H "Accept: application/json" \ -d "$org" "https://portal-env-b.example.com/organisations" done < data/organisations.json ``` ### Import Teams to Environment B After importing organisations, the next step is to import the teams associated with each organisation. This ensures that the organisational structure is accurately recreated in Environment B. Here's an example of how you can import teams into Environment B: ```bash theme={null} # Read each team file and import the teams for file in data/teams_*.json; do [[ -e "$file" ]] || continue while IFS= read -r team; do org_cid=$(basename "$file" | sed 's/teams_\(.*\)\.json/\1/') team_cid=$(echo "$team" | jq -r '.CID') echo "Importing team CID: $team_cid for organisation CID: $org_cid..." # Import the team curl -s -o /dev/null -w "%{http_code}" -X POST \ -H "Authorization: ${ENV_B_TOKEN}" \ -H "Content-Type: application/json" \ -H "Accept: application/json" \ -d "$team" "https://portal-env-b.example.com/organisations/$org_cid/teams" done < "$file" done ``` ### Verify the Migration After completing the migration, follow these steps to verify that everything was imported correctly: 1. **Compare Organisation Counts** * Check that the number of organisations in Environment B matches what you exported from Environment A * Verify that each organisation's details (name, status, etc.) are correct 2. **Verify Team Structure** * Ensure all teams were created under their correct organisations * Check that team configurations (permissions, settings) were preserved Example of verification script: ```bash theme={null} #!/bin/bash # Track total number of mismatches found errors=0 echo "Starting verification..." # === Organisation Verification === echo "Checking organisations..." # Get organisations from source data file # Format: "CID Name" for each organisation, sorted for comparison source_orgs=$(jq -r '.[] | .CID + " " + .Name' data/organisations.json | sort) # Get organisations from target environment via API # Exclude default organisation and format same as source target_orgs=$(curl -s -H "Authorization: ${ENV_B_TOKEN}" \ -H "Accept: application/json" \ "https://portal-env-b.example.com/organisations" | \ jq -r '.[] | select(.Name != "Default Organisation") | .CID + " " + .Name' | sort) # Compare organisation lists # diff will show: < for missing in target, > for extra in target if [ "$source_orgs" != "$target_orgs" ]; then echo "❌ Organisation mismatch!" diff <(echo "$source_orgs") <(echo "$target_orgs") || true ((errors++)) else echo "✅ Organisations match" fi # === Team Verification === echo -e "\nChecking teams..." # Iterate through each organisation to check its teams while IFS= read -r org; do # Split organisation line into CID and Name org_cid=$(echo "$org" | cut -d' ' -f1) org_name=$(echo "$org" | cut -d' ' -f2-) # Get teams from source data file for this organisation source_teams=$(jq -r '.[] | .Name' "data/teams_${org_cid}.json" | sort) # Get teams from target environment for this organisation # Exclude auto-generated "All users" teams target_teams=$(curl -s -H "Authorization: ${ENV_B_TOKEN}" \ -H "Accept: application/json" \ "https://portal-env-b.example.com/organisations/$org_cid/teams" | \ jq -r '.[] | select(.Name | endswith("All users") | not) | .Name' | sort) # Compare team lists for this organisation if [ "$source_teams" != "$target_teams" ]; then echo "❌ Team mismatch in '$org_name'" diff <(echo "$source_teams") <(echo "$target_teams") || true ((errors++)) else echo "✅ Teams match in '$org_name'" fi done <<< "$source_orgs" # === Final Status === # Exit with appropriate code: 0 for success, 1 for any errors if [ $errors -eq 0 ]; then echo -e "\n✅ SUCCESS: Migration verified" exit 0 else echo -e "\n❌ FAILURE: Found $errors error(s)" exit 1 fi ``` If you find any discrepancies, you may need to: * Review the migration logs * Re-run the import for specific resources a # Managing Webcrawlers Source: https://tyk.io/docs/portal/webcrawlers Configuring your Live Portal to restrit webcrawlers and bots ## Configure robots.txt (Built-in Solution) From version 1.14.0, the Tyk Developer Portal includes built-in support for customizing the `robots.txt` file, which is the standard way to instruct search engines and other well-behaved crawlers about which parts of your site they should not access. To configure this: 1. Log in to the Admin Portal 2. Navigate to **Settings > General** 3. Scroll down to the **robots.txt Settings** section 4. Edit the content to control crawler access A restrictive `robots.txt` configuration would look like: ``` User-agent: * Disallow: / ``` This instructs all crawlers to avoid indexing any part of your site. By default, the Portal already uses a restrictive `robots.txt` configuration. ## Implement Additional HTTP Headers You can add custom response headers to further discourage crawling: * `X-Robots-Tag: noindex, nofollow` - Similar to robots.txt but as an HTTP header * `Cache-Control: no-store, no-cache, must-revalidate` - Prevents caching These can be added in your proxy configuration or by customizing your portal theme. ## Best Practices * Regularly check your server logs for unusual crawling patterns * Consider using a CAPTCHA for registration forms to prevent automated sign-ups (not supported natively by Tyk Developer Portal at this time) * Use JavaScript-based content rendering for sensitive information, as basic crawlers may not execute JavaScript Remember that while these methods can deter most crawlers, they cannot provide absolute protection against determined scrapers that deliberately ignore `robots.txt` rules or use sophisticated techniques to mimic human behavior. # Tyk Developer Portal API Source: https://tyk.io/docs/product-stack/tyk-enterprise-developer-portal/api-documentation/tyk-edp-api Tyk Developer Portal API documentation. This page provides details on how to use the Tyk Developer Portal Management API for managing portal resources. <img alt="Tyk Developer Portal" /> <ButtonLeft href="https://raw.githubusercontent.com/TykTechnologies/tyk-docs/refs/heads/production/swagger/5.15/enterprise-developer-portal-swagger.yaml" /> ## <a name="introduction" /> Introduction The Tyk Developer Portal Management API offers programmatic access to all portal resources that your instance of the portal manages. This API repeats functionality of the user interface and enables APIs consumers integrating their portal instances with their other IT systems such as billings, CRMs, ITSM systems and other software. ## Authentication This API requires an admin authorisation token that is available for admin users of the portal in the profile page. ## Pagination List endpoints in the Tyk Developer Portal Management API return their results in pages. Control pagination with the following query parameters: | Parameter | Description | Default | | - | - | - | | `page` | The page number to return. Pages are numbered from 1. | `1` | | `per_page` | The number of items to return per page. | `20` | | `limit` | The maximum number of records to return for this request. It overrides the row count only, not the page offset, so use `per_page` for paging rather than `limit`. | Value of `per_page` | For example, to return the second page of products with 50 products per page: ``` GET /products?page=2&per_page=50 ``` To page through an entire collection, start at `page=1` and increase `page` until a response returns fewer items than `per_page`, or an empty list. <Note> The Tyk Developer Portal Management API uses `page` for the page number. The Tyk Dashboard API uses `p` for the same purpose, so check the parameter name when you move between the two APIs. </Note> A few endpoints that return fixed collections, such as listing themes, return all results and ignore these parameters. # Environment Variables and Configuration Source: https://tyk.io/docs/product-stack/tyk-enterprise-developer-portal/deploy/configuration Configuration reference for the Tyk Enterprise Developer Portal To configure the Tyk Enterprise Developer Portal, you can use either a config file or environment variables. The table below provides a reference to all options available to you when configuring the portal. ### Environment Variable Type Mapping When configuring Tyk components using environment variables, it's important to understand how different data types are represented. The type of each variable is based on its definition in the Go source code. This section provides a guide on how to format values for common data types. | Go Type | Environment Variable Format | Example | | - | - | - | | `string` | A regular string of text. | `TYK_GW_SECRET="mysecret"` | | `int`, `int64` | A whole number. | `TYK_GW_LISTENPORT=8080` | | `bool` | `true` or `false`. | `TYK_GW_USEDBAPPCONFIG=true` | | `[]string` | A comma-separated list of strings. | `TYK_PMP_PUMPS_STDOUT_FILTERS_SKIPPEDAPIIDS="api1,api2,api3"` | | `map[string]string` | A comma-separated list of key:value pairs. | `TYK_GW_GLOBALHEADERS="X-Tyk-Test:true,X-Tyk-Version:1.0"` | | `map[string]interface{}` | A JSON string representing the object. | `TYK_GW_POLICIES_POLICYSOURCE_CONFIG='{"connection_string": "..."}'` | <Note> For complex types like `map[string]interface{}`, the value should be a valid JSON string. For `[]string` and `map[string]string`, ensure there are no spaces around the commas unless they are part of the value itself. </Note> ## Portal settings This section explains the general portal settings, including which port it will be listening on, how often it should synchronize API Products and plans with the Tyk Dashboard, and so on. Most of these settings are optional, except for the PORTAL\_LICENSEKEY. If you don't specify these settings, the default values will be used. However, you can leverage the settings below to customize the deployment of your portal. ### Sample storage setting section via config file ```json theme={null} { "HostPort": 3001, "RefreshInterval": 10, "LicenseKey": "your-license-key", "Theming": { "Theme": "default", "Path": "./themes" }, "ProductDocRenderer": "stoplight", "LogLevel": "debug", "LogFormat": "dev", "SSOCustomLoginURL": "https://your-idp.example.com/login", "TLSConfig": { "Enable": true, "InsecureSkipVerify": true, "Certificates": [ { "Name": "localhost", "CertFile": "portal.crt", "KeyFile": "portal.key" } ], "MinVersion": "772" }, "PortalAPISecret": "your-portal-api-secret" } ``` ### Sample storage setting section via environment variables ```.ini theme={null} PORTAL_HOSTPORT=3001 PORTAL_REFRESHINTERVAL=10 PORTAL_LICENSEKEY=your-license-key PORTAL_THEMING_THEME=default PORTAL_THEMING_PATH=./themes PORTAL_DOCRENDERER=stoplight PORTAL_LOG_LEVEL=debug PORTAL_LOG_FORMAT=dev PORTAL_SSO_CUSTOM_LOGIN_URL=https://your-idp.example.com/login PORTAL_TLS_ENABLE=true PORTAL_TLS_INSECURE_SKIP_VERIFY=true PORTAL_TLS_CERTIFICATES = '[{"Name": "localhost","CertFile": "portal.crt","KeyFile": "portal.key"}]' PORTAL_API_SECRET=your-portal-api-secret ``` ### PORTAL\_HOSTPORT **Config file:** HostPort <br /> **Type:** `int` <br /> **Description**: The port on which the portal will run inside the container. Not required. If it is not specified, the default value is 3001. ### PORTAL\_REFRESHINTERVAL **Config file:** RefreshInterval <br /> **Type:** `int` <br /> **Description**: How the portal will synchronise API Products and plans with the Tyk Dashboard. The value is specified in minutes. Not required. If it is not specified, the default value is 10. ### PORTAL\_LICENSEKEY **Config file:** LicenseKey <br /> **Type:** `string` <br /> **Description**: A license key that Tyk provides. Required to start the portal. ### PORTAL\_THEMING\_THEME **Config file:** Theming.Theme <br /> **Type:** `string` <br /> **Description**: The name of a theme the portal should use after the start-up. You can change this later via the Themes UI. It's not required to specify, as the portal comes with only one theme named `default`; therefore, PORTAL\_THEMING\_THEME defaults to `default`. However, if you have already created [a theme](/docs/portal/customization#) and want the portal to use when it starts for the first time, then you can use this setting to achieve that. ### PORTAL\_THEMING\_PATH **Config file:** Theming.Path <br /> **Type:** `string` <br /> **Description**: Defines a folder where themes are located. Depending on the storage type that you use, you can specify either a relative or an absolute path: * If you use the `fs` storage type, you can specify both a relative path (e.g., `./themes`) and an absolute path (e.g., `/themes`) * If you use the `s3` or `db` storage type, however, you can only use an absolute path (e.g., `/themes`). The default value for this variable is `./themes`, so it's important to redefine it if you plan to use the `s3` or `db` storage types. ### PORTAL\_THEMING\_DISABLE\_UPLOAD **Config file:** Theming.DisableUpload <br /> **Type:** `boolean` <br /> **Description**: Disables uploading theme via the UI. The default value is `false`. ### PORTAL\_MAX\_UPLOAD\_SIZE **Config file:** MaxUploadSize <br /> **Type:** `int` <br /> **Description**: Defines the maximum size in bytes of a theme file that can be uploaded via the UI. The default value is 33554432 bytes (32 mb). Please note that the size of individual files should not exceed 5 MB. If the size of any individual file in a theme exceeds 5 MB, the theme will not be uploaded, even if the total size of all files is less than `PORTAL_MAX_UPLOAD_SIZE`. ### PORTAL\_DOCRENDERER **Config file:** ProductDocRenderer <br /> **Type:** `string` <br /> **Options:** * `stoplight` to use Stoplight as a documentation renderer; * `redoc` to use Redoc as a documentation renderer. **Description**: Use this setting to specify which OAS documentation renderer to use to render the OpenAPI Specification. Not required. If it is not specified, the default value is `stoplight`. ### TYK\_PORTAL\_ENABLEIDPREGISTRY **Config file:** EnableIDPRegistry <br /> **Type:** `boolean` <br /> **Description**: Enables the [Identity Provider Registry](/docs/api-management/client-idp-registry) for Dynamic Client Registration. When set to `true`, the Portal stores IdP configuration centrally in the Tyk Dashboard rather than writing it directly into API definitions. Requires Tyk 5.14.0 or later. The default value is `false`. ### PORTAL\_DCR\_LOG\_ENABLED **Config file:** DCRLogEnabled <br /> **Type:** `boolean` <br /> **Description**: When enabled, the portal will print raw responses from the OAuth2.0 Identity Provider for the DCR flow. Raw responses from the Identity Providers may contain sensitive information; therefore, we recommend enabling this option only for debugging purposes. Available options are: * `true` for enabling the detailed logs; * `false` for disabling the detailed logs. The default value is `false`. ## Audit log settings This section explains how to configure the audit log in the portal. When the audit log is enabled, each admin's action will leave a trace in the *portal.log* file located in the directory specified by the `PORTAL_AUDIT_LOG_ENABLE` setting. ### PORTAL\_AUDIT\_LOG\_ENABLE **Config file:** AuditLog.Enable <br /> **Type:** `boolean` <br /> **Description**: Enables the audit log capability. The default value is `false`. ### PORTAL\_AUDIT\_LOG\_PATH **Config file:** AuditLog.Path <br /> **Type:** `string` <br /> **Description**: Path to a directory with the audit log file. When audit log is enabled, the portal will create a file called `portal.log` in that directory. All admin actions will be reflected in that file. ## Session management This section explains how to configure session management for the portal. Using the settings below, you can configure: * Name of the portal's session cookie. * Various aspects of cookie security, including: should it be sent using a TLS-encrypted connection,and is it accessible by JavaScript API on the client-side? * Cookie encryption key. * Cookie lifetime. ### PORTAL\_SESSION\_NAME **Config file:** Session.Name <br /> **Type:** `string` <br /> **Description**: Name of the portal's cookie. The default value is `portal-session`. ### PORTAL\_SESSION\_SECURE **Config file:** Session.Secure <br /> **Type:** `boolean` <br /> **Description**: Controls whether the portal adds the `Secure` attribute to the `Set-Cookie` header in all responses from the portal's backend, except for the admin APIs. It's important to note that if the connection between the portal and the browser is not secured with TLS, the browser will ignore the `Secure` attribute. We recommend enabling TLS and setting this attribute to `true` for all production environments. The default value is `false`. ### PORTAL\_SESSION\_HTTPONLY **Config file:** Session.HttpOnly <br /> **Type:** `boolean` <br /> **Description**: Controls whether the portal adds the `HttpOnly` attribute to the `Set-Cookie` header in all responses from the portal's backend, except for the admin APIs. This cookie attribute controls if the cookie is only accessible at the server and not by JavaScript on the client side. This is a security measure to prevent XSS attacks. We recommend setting it to `true` in production environments. The default value is `true`. ### PORTAL\_SESSION\_SAMESITE **Config file:** Session.SameSite <br /> **Type:** `string` <br /> **Description**: Controls the value of the `SameSite` attribute for the portal’s cookie. The portal adds the `SameSite` attribute with the value specified in `PORTAL_SESSION_SAMESITE` to the `Set-Cookie` header in all responses from the portal's backend, except for the admin APIs. Available options are: * `None`; * `Lax`; * `Strict`. The default value is `Strict`. If the value specified in the `PORTAL_SESSION_SAMESITE` setting does not match any of the above-mentioned options, it defaults to `Strict`. ### PORTAL\_SESSION\_KEY **Config file:** Session.Key <br /> **Type:** `string` <br /> **Description**: The cookie encryption key. The default value is a random 32-bytes string. ### PORTAL\_SESSION\_LIFETIME **Config file:** Session.LifeTime <br /> **Type:** `int` <br /> **Description**: The lifetime of the portal's session in seconds. The default value is 604800 seconds (7 days). ### PORTAL\_SESSION\_IDLE\_TIMEOUT **Config file:** Session.IdleTimeout <br /> **Type:** `int` <br /> **Description**: The duration in seconds before a portal session is considered idle. A session is deemed idle when there is no user activity, such as clicks, navigation, or input. Once the idle timeout is reached, the session will expire, requiring the user to log in again. The default value is 3600 seconds (1 hour). ### PORTAL\_ENABLE\_HTTP\_PROFILER **Config file:** EnableHttpProfiler <br /> **Type:** `boolean` <br /> **Description**: Enables debugging of the portal by exposing the Golang profiling information at `/debug/pprof/`. The default value is `false`. <Note> **Profiling** We recommend using the profiler only in non-production environments. Be sure to disable it in production by setting `PORTAL_ENABLE_HTTP_PROFILER` to `false`. </Note> ### PORTAL\_LOG\_LEVEL **Config file:** LogLevel <br /> **Type:** `string` <br /> **Description**: Defines the log level, available options are: * debug * info * warn * error * dpanic * panic * fatal ### PORTAL\_LOG\_FORMAT **Config file:** LogFormat <br /> **Type:** `string` <br /> **Description**: Defines the log format, available options are: * `dev` for verbose human-readable output * `prod` for output in json format. ### PORTAL\_TLS\_ENABLE **Config file:** TLSConfig.Enable <br /> **Type:** `boolean` <br /> **Description**: Enables TLS. The default value is `false`. ### PORTAL\_TLS\_INSECURE\_SKIP\_VERIFY **Config file:** TLSConfig.InsecureSkipVerify <br /> **Type:** `boolean` <br /> **Description**: Skip verification of self-signed certificates. ### PORTAL\_TLS\_MIN\_VERSION **Config file:** TLSConfig.MinVersion <br /> **Type:** `string` <br /> **Description**: Minimum TLS version. Defaults to 769 (TLS 1.0). Values for TLS Versions: | TLS Version | Value to Use | | :- | :- | | 1.0 | 769 | | 1.1 | 770 | | 1.2 | 771 | | 1.3 | 772 | ### PORTAL\_TLS\_MAX\_VERSION **Config file:** TLSConfig.MaxVersion <br /> **Type:** `string` <br /> **Description**: Maximum TLS version. Defaults to 772 (TLS 1.3). Values for TLS Versions: | TLS Version | Value to Use | | :- | :- | | 1.0 | 769 | | 1.1 | 770 | | 1.2 | 771 | | 1.3 | 772 | ### PORTAL\_TLS\_CIPHER\_SUITES **Config file:** TLSConfig.CipherSuites <br /> **Type:** `[]string` <br /> **Description**: Array of allowed cipher suites as defined at [https://golang.org/pkg/crypto/tls/#pkg-constants](https://golang.org/pkg/crypto/tls/#pkg-constants). ### PORTAL\_TLS\_CERTIFICATES **Config file:** TLSConfig.Certificates <br /> **Type:** `json` <br /> **Description**: JSON (or JSON-formatted string in case of environment variable) containing a list of certificates. Each certificate is defined by three properties: * Name * CertFile * KeyFile ### PORTAL\_API\_SECRET **Config file:** PortalAPISecret <br /> **Type:** `string` <br /> **Description**: API secret for enabling [Single Sign-on (SSO) flow](/docs/tyk-stack/tyk-developer-portal/enterprise-developer-portal/managing-access/enable-sso) with the Tyk Identity Broker. You can specify any string value in this setting. Omit this setting if you don't require SSO. ### PORTAL\_SSO\_CUSTOM\_LOGIN\_URL **Config file:** SSOCustomLoginURL <br /> **Type:** `string` <br /> **Description**: Redirects the portal login page to a custom SSO login URL. When set, GET requests to `/auth/password/login` are automatically redirected to this URL, and the portal's "Log in" button points to it. This is useful when using an Identity Provider (IDP) based login/SSO profile, as it allows you to bypass the default portal password login page and direct users to your external IDP login page instead. This setting only affects the login page redirect; user registration and password reset pages remain unchanged. ## Response Headers Configuration This section explains how to configure custom HTTP response headers that will be added to all responses from the Portal. ### PORTAL\_RESPONSE\_HEADERS **Config file:** ResponseHeaders <br /> **Type:** `[]{Key: string, Value: string}` <br /> **Description**: Configures custom HTTP response headers that will be added to all responses from the Portal. The value must be a JSON array of objects containing Key and Value fields. **Example configuration via environment variable:** ```bash theme={null} export PORTAL_RESPONSE_HEADERS='[{"Key":"X-Frame-Options", "Value":"DENY"}, {"Key":"Content-Security-Policy", "Value":"default-src '\''self'\''"}]' ``` **Example configuration via config file:** ```json theme={null} { "ResponseHeaders": [ { "Key": "X-Frame-Options", "Value": "DENY" }, { "Key": "Content-Security-Policy", "Value": "default-src 'self'" } ] } ``` **Common use cases include:** * Security headers (`X-Frame-Options`, `Content-Security-Policy`) * CORS headers * Cache control headers * Custom application headers If the JSON format is invalid, the Portal will return an error message indicating the correct format: ``` Invalid value for PORTAL_RESPONSE_HEADERS. Valid Format: '[{"Key": "header-key", "Value": "value-for-given-key"}]' ``` ## Storage settings Using variables from this section, you can configure storage for the portal's CMS assets, such as themes, images, and Open API Specification files. The portal supports two types of storage: * S3 volume; * And filesystem. ### Sample storage setting section via config file ```json theme={null} { "Storage": "s3", "S3": { "AccessKey": "your-access-key", "SecretKey": "your-secret-key", "Region": "sa-east-1", "Endpoint": "https://s3.sa-east-1.amazonaws.com", "Bucket": "your-portal-bucket", "ACL": "private", "PresignURLs": true } } ``` ### Sample storage setting section via environment variables ```.ini theme={null} PORTAL_STORAGE=s3 PORTAL_S3_AWS_ACCESS_KEY_ID=your-access-key PORTAL_S3_AWS_SECRET_ACCESS_KEY=your-secret-key PORTAL_S3_REGION=sa-east-1 PORTAL_S3_ENDPOINT=your-portal-bucket PORTAL_S3_BUCKET=https://s3.sa-east-1.amazonaws.com PORTAL_S3_ACL=private PORTAL_S3_PRESIGN_URLS=true ``` ### PORTAL\_STORAGE **Config file:** Storage <br /> **Type:** `string` <br /> **Options:** * `fs` to use file system storage type; * `db` to use the portal's main database. If the `db` is selected as a storage type, the portal application will create appropriate structure in the database that * `s3` to use S3 volume for storing the portal assets. **Description**: Defines which type of storage to use for the portal's CMS assets. Not required. If it is not specified, the default value is `fs`. ### PORTAL\_S3\_AWS\_ACCESS\_KEY\_ID **Config file:** S3.AccessKey <br /> **Type:** `string` <br /> **Description**: Access key for your S3 bucket. This option is only required for the `s3` storage type and will be ignored for the `fs` and `db` storage types. ### PORTAL\_S3\_AWS\_SECRET\_ACCESS\_KEY **Config file:** S3.SecretKey <br /> **Type:** `string` <br /> **Description**: Secret access key for your S3 bucket. This option is only required for the `s3` storage type and will be ignored for the `fs` and `db` storage types. ### PORTAL\_S3\_REGION **Config file:** S3.Region <br /> **Type:** `string` <br /> **Description**: AWS region where the S3 bucket is hosted. E.g., `sa-east-1`. This option is only required for the `s3` storage type and will be ignored for the `fs` and `db` storage types. ### PORTAL\_S3\_ENDPOINT **Config file:** S3.Endpoint <br /> **Type:** `string` <br /> **Description**: URL to object storage service. E.g., `https://s3.sa-east-1.amazonaws.com` or `https://play.min.io`. This option is only required for the `s3` storage type and will be ignored for the `fs` and `db` storage types. ### PORTAL\_S3\_BUCKET **Config file:** S3.Bucket <br /> **Type:** `string` <br /> **Description**: Name of the S3 bucket. Required only for the `s3` storage type. This option is only required for the `s3` storage type and will be ignored for the `fs` and `db` storage types. ### PORTAL\_S3\_ACL **Config file:** S3.ACL <br /> **Type:** `string` <br /> **Description**: ACL permissions are set on the bucket, with options including `private`, `public-read`, `public-read-write`, and `authenticated-read`. If the bucket uses a policy to set permissions, you should leave the ACL value empty. This option is only required for the `s3` storage type and will be ignored for the `fs` and `db` storage types. ### PORTAL\_S3\_PRESIGN\_URLS **Config file:** S3.PresignURLs <br /> **Type:** `string` <br /> **Description**: The PresignURLs option instructs the client to retrieve presigned URLs for the objects. This is particularly useful if the bucket is private and you need to access the object directly, such as when displaying an image on a web page. This option is only required for the `s3` storage type and will be ignored for the `fs` and `db` storage types. ### PORTAL\_ASSETS\_CACHE\_DISABLE **Config file:** AssetsCache.Disable <br /> **Type:** `boolean` <br /> **Description**: If the storage type is set to `db`, an in-memory cache will be used for the themes storage. This configuration disables the assets cache. The default value is `false`. ## TLS configuration This section explains the TLS configuration settings to enable connection to the portal's UI over HTTPS. ### PORTAL\_TLS\_ENABLE **Config file:** TLSConfig.Enable <br /> **Type:** `boolean` <br /> **Description**: Enables or disables connection over HTTPS. When TLS is enabled, the portal will expect a TLS certificate to be provided via *PORTAL\_TLS\_CERTIFICATES*. When TLS is enabled and no certificates are provided, the portal won't start. The default value is `false`. ### PORTAL\_TLS\_CERTIFICATES **Config file:** TLSConfig.Certificates <br /> **Type:** `string` <br /> **Description**: A JSON-formatted string that provides the hostname, in addition to the paths to a TLS certificate and key file: * `Name`: The hostname of the portal. This should match the hostname of the certificate file. * `CertFile`: The path to a TLS certificate file in the CRT format for the specified hostname. * `KeyFile`: The path to a TLS key file for the specified hostname. Example: ```json theme={null} [{"Name": "tyk.io","CertFile": "portal.crt","KeyFile": "portal.key"}] ``` ## Database connection settings This section provides a reference for the database connection settings used in the portal. ### Sample database connection setting section via config file ```json theme={null} { "Database": { "Dialect": "mysql", "ConnectionString": "admin:secr3t@(localhost:3308)/portal?charset=utf8&parseTime=True&loc=Local", "EnableLogs": true, "MaxRetries": 3, "RetryDelay": 2000, "MaxOpenConnections": 20, "MaxIdleConnections": 2, "ConnectionMaxLifetime": 180000 } } ``` ### Sample database connection setting section via environment variables ```.ini theme={null} PORTAL_DATABASE_DIALECT="mysql" PORTAL_DATABASE_CONNECTIONSTRING="admin:secr3t@(localhost:3308)/portal?charset=utf8&parseTime=True&loc=Local" PORTAL_DATABASE_ENABLELOGS=true PORTAL_DATABASE_MAXRETRIES=3 PORTAL_DATABASE_RETRYDELAY=5000 PORTAL_DATABASE_MAX_OPEN_CONNECTIONS=20 PORTAL_DATABASE_MAX_IDLE_CONNECTIONS=2 PORTAL_DATABASE_CONNECTION_MAX_LIFETIME=180000 ``` ### PORTAL\_DATABASE\_DIALECT **Config file:** Database.Dialect <br /> **Type:** `string` <br /> **Description**: A database will be used to store the portal data. Available dialects are: * `mysql` * `postgres` * `sqlite3` ### PORTAL\_DATABASE\_CONNECTIONSTRING **Config file:** Database.ConnectionString <br /> **Type:** `string` <br /> **Description**: Connection string to the selected database. This setting must be present if the `PORTAL_DATABASE_DIALECT` is specified. ### PORTAL\_DATABASE\_ENABLELOGS **Config file:** Database.EnableLogs <br /> **Type:** `boolean` <br /> **Description**: Enables logging connection to the database. We recommend disabling this in production environments. ### PORTAL\_DATABASE\_MAXRETRIES **Config file:** Database.MaxRetries <br /> **Type:** `int` <br /> **Description**: Defines how many times the portal will retry to connect to the database. Optional, the default value is 3. ### PORTAL\_DATABASE\_RETRYDELAY **Config file:** Database.RetryDelay <br /> **Type:** `int` <br /> **Description**: Defines the delay between connect attempts (in milliseconds). Optional. Default value: 5000. ### PORTAL\_DATABASE\_MAX\_OPEN\_CONNECTIONS **Config file:** Database.MaxOpenConnections <br /> **Type:** `int` <br /> **Description**: Defines the maximum number of concurrent connections that the database can handle from the application. When the number of open connections reaches this limit, new requests will wait until a connection becomes available. Optional. Default value: unlimited. ### PORTAL\_DATABASE\_MAX\_IDLE\_CONNECTIONS **Config file:** Database.MaxIdleConnections <br /> **Type:** `int` <br /> **Description**: Defines the maximum number of idle connections in the database connection pool. Idle connections are open but not currently being used. Keeping some idle connections can improve performance by reducing the time it takes to establish a new connection when demand increases. Optional. Default value: 2. ### PORTAL\_DATABASE\_CONNECTION\_MAX\_LIFETIME **Config file:** Database.ConnectionMaxLifetime <br /> **Type:** `int` <br /> **Description**: Defines the maximum lifetime of a connection in milliseconds. This setting is optional. If not specified, the default value is 1800000 milliseconds (30 minutes). If set to `0`, the connection lifetime is unlimited, meaning connections are reused indefinitely unless closed due to errors or manually by the application. ## CORS settings This section explains how to configure [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) for the portal. ### PORTAL\_CORS\_ENABLE **Config file:** CORS.Enable <br /> **Type:** `boolean` <br /> **Description**: Enables or disables the CORS settings for the portal. When disabled, no CORS settings are applied. In other words, any cross-origin request will be denied. When enabled, the below defined CORS settings are applied. The default value is `false`. ### PORTAL\_CORS\_ALLOWED\_ORIGINS **Config file:** CORS.AllowedOrigins <br /> **Type:** `[string]` <br /> **Description**: A list of origin domains to allow access from. Wildcards are also supported, e.g. \[`*.foo.com`] will allow access from any domain that ends with *.foo.com*. When unset, the Portal responds with `Access-Control-Allow-Origin: *`. Because Portal uses cookie-based sessions, browsers block credentialed requests to a wildcard origin. Specify individual origins to restrict access, or set to `http://*,https://*` to allow all origins. To configure using a configuration file: ```json theme={null} { "CORS": { "AllowedOrigins": ["*.foo.com","*.bar.com"] } } ``` To configure using an environment variable: ```console theme={null} PORTAL_CORS_ALLOWED_ORIGINS=*.foo.com,*.bar.com ``` ### PORTAL\_CORS\_ALLOWED\_HEADERS **Config file:** CORS.AllowedHeaders <br /> **Type:** `[string]` <br /> **Description**: Headers that are allowed within a request. To apply this setting, specify an array of the allowed headers. By default, no headers are allowed. To configure using a configuration file: ```json theme={null} { "CORS": { "AllowedHeaders": ["X-Method-Override","X-API-Key"] } } ``` To configure using an environment variable: ```console theme={null} PORTAL_CORS_ALLOWED_HEADERS=X-Method-Override,X-API-Key ``` ### PORTAL\_CORS\_ALLOWED\_METHODS **Config file:** CORS.AllowedMethods <br /> **Type:** `[string]` <br /> **Description**: A list of methods that are allowed access. To apply this setting, specify an array of the allowed methods. By default, `GET` and `POST` methods are allowed. To configure using a configuration file: ```json theme={null} { "CORS": { "AllowedMethods": ["GET", "POST", "HEAD"] } } ``` To configure using an environment variable: ```console theme={null} PORTAL_CORS_ALLOWED_METHODS=GET,POST,HEAD ``` ### PORTAL\_CORS\_MAX\_AGE **Config file:** CORS.MaxAge <br /> **Type:** `int` <br /> **Description**: Indicates how long the results of a preflight request can be cached. The default value is `0`, which stands for no max age. ### PORTAL\_DISABLE\_CSRF\_CHECK **Config file:** DisableCSRFCheck <br /> **Type:** `bool` <br /> **Description**: When set to `true`, disables CSRF protection for all routes. By default, CSRF protection is enabled to prevent cross-site request forgery attacks. Only disable this in development environments or when you have alternative security measures in place. ### PORTAL\_CORS\_ALLOW\_CREDENTIALS **Config file:** CORS.AllowCredentials <br /> **Type:** `boolean` <br /> **Description**: Indicates whether the request can include user credentials like cookies, HTTP authentication, or client-side SSL certificates. The default is `false`. ### PORTAL\_TIB\_ENABLED **Config file:** TIB.Enable <br /> **Type:** `boolean` <br /> **Description**: Enables or disables the Tyk Identity Broker (TIB) integration. When disabled, it will not appear in the UI. The default value is `false`. ### PORTAL\_NOTIFICATIONS\_JOB\_FREQUENCY **Config file:** NotificationsJobFrequency <br /> **Type:** `int` <br /> **Description**: Defines the frequency of the notifications job that fetches notifications from the portal's database in minutes. The default value is `30` minutes. ## Webhooks settings This section explains how to configure webhooks in the portal. ### PORTAL\_WEBHOOKS\_SECRET **Config file:** Webhooks.Secret <br /> **Type:** `string` <br /> **Description**: The global secret key used to sign all outgoing webhooks. ### PORTAL\_WEBHOOKS\_PAUSE\_DURATION **Config file:** Webhooks.PauseDuration <br /> **Type:** `int` <br /> **Description**: The duration (in seconds) to pause a webhook after a failed delivery attempt before retrying. Defaults to 5 seconds. ### PORTAL\_WEBHOOKS\_CACHE\_EXPIRATION **Config file:** Webhooks.CacheExpiration <br /> **Type:** `int` <br /> **Description**: The expiration time (in seconds) for the webhook cache. ### PORTAL\_WEBHOOKS\_CACHE\_CLEANUP\_INTERVAL **Config file:** Webhooks.CacheCleanupInterval <br /> **Type:** `int` <br /> **Description**: The interval (in seconds) at which the webhook cache is cleaned up. Defaults to 5 seconds. ### PORTAL\_WEBHOOKS\_DISPATCH\_TIMEOUT **Config file:** Webhooks.DispatchTimeout <br /> **Type:** `int` <br /> **Description**: The timeout (in seconds) for dispatching a single webhook request. ### PORTAL\_WEBHOOKS\_TOTAL\_WORKERS **Config file:** Webhooks.TotalWorkers <br /> **Type:** `int` <br /> **Description**: The number of worker goroutines used to process webhooks concurrently. Defaults to 10. ### PORTAL\_WEBHOOKS\_PROVIDER **Config file:** Webhooks.Provider <br /> **Type:** `string` <br /> **Description**: The storage provider used for managing webhooks (for example, `db`). ### PORTAL\_WEBHOOKS\_DISABLE **Config file:** Webhooks.Disable <br /> **Type:** `bool` <br /> **Description**: A boolean flag (`true` or `false`) that disables webhooks entirely when set to `true`. ## Sample config file ```json theme={null} { "HostPort": 3001, "RefreshInterval": 10, "LicenseKey": "your-license-key", "Theming": { "Theme": "default", "Path": "./themes" }, "ProductDocRenderer": "stoplight", "LogLevel": "debug", "LogFormat": "dev", "SSOCustomLoginURL": "https://your-idp.example.com/login", "TLSConfig": { "Enable": true, "InsecureSkipVerify": true, "Certificates": [ { "Name": "localhost", "CertFile": "portal.crt", "KeyFile": "portal.key" } ] }, "PortalAPISecret": "your-portal-api-secret", "Storage": "s3", "S3": { "AccessKey": "your-access-key", "SecretKey": "your-secret-key", "Region": "sa-east-1", "Endpoint": "https://s3.sa-east-1.amazonaws.com", "Bucket": "your-portal-bucket", "ACL": "private", "PresignURLs": true }, "Database": { "Dialect": "mysql", "ConnectionString": "admin:secr3t@(localhost:3308)/portal?charset=utf8&parseTime=True&loc=Local", "EnableLogs": true, "MaxRetries": 3, "RetryDelay": 2000 }, "TIB": { "Enable": true } } ``` ## Sample .env file ```ini theme={null} PORTAL_HOSTPORT=3001 PORTAL_REFRESHINTERVAL=10 PORTAL_LICENSEKEY=your-license-key PORTAL_THEMING_THEME=default PORTAL_THEMING_PATH=./themes PORTAL_DOCRENDERER=stoplight PORTAL_LOG_LEVEL=debug PORTAL_LOG_FORMAT=dev PORTAL_SSO_CUSTOM_LOGIN_URL=https://your-idp.example.com/login PORTAL_TLS_ENABLE=true PORTAL_TLS_INSECURE_SKIP_VERIFY=true PORTAL_TLS_CERTIFICATES = '[{"Name": "localhost","CertFile": "portal.crt","KeyFile": "portal.key"}]' PORTAL_API_SECRET=your-portal-api-secret PORTAL_STORAGE=s3 PORTAL_S3_AWS_ACCESS_KEY_ID=your-access-key PORTAL_S3_AWS_SECRET_ACCESS_KEY=your-secret-key PORTAL_S3_REGION=sa-east-1 PORTAL_S3_ENDPOINT=your-portal-bucket PORTAL_S3_BUCKET=https://s3.sa-east-1.amazonaws.com PORTAL_S3_ACL=private PORTAL_S3_PRESIGN_URLS=true PORTAL_DATABASE_DIALECT="mysql" PORTAL_DATABASE_CONNECTIONSTRING="admin:secr3t@(localhost:3308)/portal?charset=utf8&parseTime=True&loc=Local" PORTAL_DATABASE_ENABLELOGS=true PORTAL_DATABASE_MAXRETRIES=3 PORTAL_TIB_ENABLED=true ``` # Set up email notification service Source: https://tyk.io/docs/product-stack/tyk-enterprise-developer-portal/getting-started/setup-email-notifications Learn how to set up email notifications in the Tyk Enterprise Developer Portal. ## Email Configuration Configuring the emailing settings is necessary for the portal to send notifications to admin users and API consumers. Once the configuration is finished, the portal will send emails upon the following events: * Password reset; * New access request; * Access request approved; * Access request rejected; * Pending user registration request; * Invitation to a user to register in the portal; * User account is activated; * User account is deactivated; * New Organisation registration request is created; * Organisation registration request is accepted; * Organisation registration request is rejected. **Prerequisites** Before setting up the emailing configuration, you need your email server up and running. To complete the email setup, you will need the following information about your SMTP server: * Address of your SMTP server; * A port on which it accepts connections; * Username and password to connect to your SMTP server. ## Portal Admin User Notifications To start with, you need to configure an email address where the portal will send notifications for admin users: new API Product access requests, new Organisation registration requests, and so on. For that, you need to navigate to the General section in the Setting menu, scroll down to the Portal admin notification address, and specify the admin email address in the Portal admin email field. <img alt="Portal admin notification address settings" /> ## Outbound Mailing ### The default from email To enable the portal to send notifications to admin users and API Consumers, you need to specify the outbound email address in the Default Email From field. No notifications will be sent until the Default Email From field is specified. <img alt="Default from email settings" /> ### Email Subjects Once the default from email is configured, you can specify subjects for notifications. If you don’t, the default subjects will be used for email notifications. <img alt="Email subject settings" /> ### SMTP Server Settings Once the default from email, the admin notification email, and the subjects for outbound emails are configured, you need to configure settings for the SMTP server. To do so, navigate to the SMTP setting section in the Settings/General menu and specify: * Your SMTP server host and port; * The SMTP username and password if authentication is configured for your SMTP server. <img alt="SMTP settings" /> # How to Request Access to API Products Using Direct Access Flow Source: https://tyk.io/docs/tyk-developer-portal/direct-access-flow This guide explains how to use the Direct Access Flow in the Tyk Developer Portal to request access to API products without the shopping cart, including creating applications, attaching credentials, changing plans, and admin configuration. ## Availability | Component | Version | Editions | | :- | :- | :- | | Developer Portal | Available since [v1.16.0](/docs/developer-support/release-notes/portal#1-16-0-release-notes) | Enterprise | ## Prerequisites 1. **Dashboard License**: [Contact our team](https://tyk.io/contact/) to obtain a license or get self-managed trial license by completing the registration on our [website](https://tyk.io/self-managed-trial/). 2. **Working Tyk Environment:** You need access to a running Tyk instance. For setup instructions using Docker, please refer to the [Tyk Getting Started Guide](/docs/getting-started/quick-start). 3. Developer Portal Setup with 1. Admin access to the Tyk Developer Portal. 2. The end user (developer accounts) must exist in the portal. 3. Tyk Developer Portal v1.16.0 or later. 4. [API Products](/docs/portal/api-products), [Plans](/docs/portal/api-plans) and [Catalogue](/docs/tyk-stack/tyk-developer-portal/enterprise-developer-portal/managing-access/manage-catalogues) already created and published in the portal. ## What we will do 1. Enable the Direct Access flow in the Admin Portal settings. 2. Request access to an [API Product](/docs/portal/api-products) as a developer and create a new [application](/docs/portal/developer-app). 3. Configure and manage access as an admin on behalf of developers. ## Instructions Follow these steps to configure and use the Direct Access flow in the Tyk Developer Portal: ### 1. Enable Direct Access Flow (Admin) 1. Log in to the **Admin Portal** as an administrator. 2. In the main navigation, go to **Settings**. 3. Select **General** from the settings menu. 4. Locate the **API product access flow** setting. * By default, this is set to **Cart-based flow**. 5. Switch the option from **Cart-based flow** to **Direct access flow**. 6. Click **Save** to apply the changes. <img alt="configure direct access flow in portal" /> <Note> Once enabled, all API consumers will experience the Direct Access flow when requesting access to API products from the Live Portal. </Note> ### 2. Request Access to an API Product (Developer) When the Direct Access flow is enabled, developers can request access to an API product without going through a shopping cart: 1. Log in to the **Developer Portal** as an API Consumer. 2. In the main navigation, go to **Catalogues**. 3. Browse the API Catalog and click on an API product you want to access. 4. Review the available plans and their rate limits/quotas. 5. Select the **Plan** you want to use. 6. Click **Access with this plan**. * Notice there is no shopping cart step - you go directly to the access request page. 7. In the access request form: * Enter an **Application name** (e.g., `My Weather App`). * Optionally add a **Description** for the application. 8. Click **Submit request**. <Note> If the plan is configured for auto-approval, credentials will be issued immediately. Otherwise, an API Owner will review and approve your request. </Note> #### View Your Credentials **After approval:** 1. Click on your profile icon in the top-right corner and select **My Dashboard** from the dropdown. 2. Go to **My Apps** in the left navigation. 3. Click on your application. 4. In the **Credential Management** section, you will see your access credentials. * Click **Show** to reveal the API key. * Copy the credentials for use in your API requests. <img alt="direct access flow credentials approved" /> ## Configure Access as an Admin Portal administrators can perform similar operations on behalf of developers from the Admin Portal: ### Create Applications for Developers 1. Log in to the **Admin Portal** as an administrator. 2. Navigate to **API Consumers > Applications**. 3. Click **Add new application**. 4. Enter the application details: * **Application name** * **Description** * Select the **Developer (API Consumer)** who will own the application. * Configure **Visibility settings**. 5. Click **Save**. ### Add Credentials and Products 1. Navigate to the application details page. 2. Click **Add credential**. 3. Choose the **API Product** and **Plan** to associate with the credential. <img alt="admin adding multiple api products to a single plan" /> 4. Click on **Save Changes** 5. The credential will be generated and associated with the selected product/plan. 6. Additional products on the same plan can be added to this credential. <img alt="single credentials for multiple api products" /> # Set Up GraphQL Documentation for API Products Source: https://tyk.io/docs/tyk-developer-portal/graphql-playground How to add GraphQL SDL documentation and enable the interactive Playground for an API Product in the Tyk Developer Portal. ## Availability | Component | Version | Editions | | :- | :- | :- | | Developer Portal | v1.15.0 | Enterprise | <Note> [GraphQL Server URL auto-population](#graphql-server-url-and-baseline-url) and [Universal Data Graph (UDG)](#universal-data-graph-apis) support require v1.16.0 or later. </Note> ## Overview You can add a GraphQL Schema Definition Language (SDL) file to an API Product to enable the interactive GraphQL Playground in the Live Portal. Consumers with approved access can write and execute queries directly from the Portal, with their credentials automatically pre-populated in the Playground headers. ## Prerequisites * Developer Portal v1.15.0 or later * A [working Tyk environment](/docs/getting-started/quick-start) with Tyk Gateway and Tyk Dashboard * A GraphQL SDL schema file in `.graphql`, `.graphqls`, `.gql`, or `.json` format ## Add GraphQL Documentation to an API Product 1. **Create a test GraphQL API** If you don't have an existing GraphQL API, use the built-in Star Wars example from the Tyk Dashboard: * Navigate to **APIs > Add New API**, click **Try example**, select **Star Wars GQL API**, and click **Use Example** * Copy the **Key ID** from the confirmation pop-up and save it; you will use this as the auth header when testing in the Playground * Go to the **Schema** tab of the newly created API and download the schema file; you will upload this as the SDL file in step 5 <img alt="GraphQL API Schema Tab" /> 2. Navigate to **Developer Portal > API Products** and [create a new API Product](/docs/portal/api-products#creating-a-new-product). 3. On the **APIs** tab, select your GraphQL API: * **Choose a Provider**: select the Tyk Dashboard Provider * **Choose authentication method**: match the authentication configured on your GraphQL API * **Select APIs**: check your GraphQL API from the list <img alt="Configure API Product details" /> 4. Go to the **Documentation** tab and click **Add API specification**. 5. Set the specification type to **GraphQL SDL**, then upload your schema file. Accepted formats are `.graphql`, `.graphqls`, `.gql`, and `.json`. <img alt="Documentation tab with GraphQL SDL upload and Server URL field" /> 6. Set the **GraphQL Server URL** to the live endpoint of your GraphQL API on the Tyk Gateway (for example, `http://gateway.example.com/my-graphql-api/`). From v1.16.0, this is [auto-populated](#graphql-server-url-and-baseline-url) from the Provider's Gateway Base URL and the API's listen path; you can always edit the value manually. <Note> The URL must end with a trailing slash. A missing trailing slash causes a 404 error in the Playground. </Note> 7. Click **Save Changes**. 8. Open your **Live Portal**, go to [**Product Catalogues**](/docs/tyk-stack/tyk-developer-portal/enterprise-developer-portal/managing-access/manage-catalogues), locate the product, and click **Docs**. <img alt="GraphQL API Docs Live Portal" /> 9. You should now see the **GraphQL Playground**, ready for interactive query testing. <Note> To test authenticated APIs, set the required headers in the Playground. The Star Wars GQL API uses [Auth Token](/docs/api-management/authentication/bearer-token) authentication. Add the `Authorization` header using the Key ID you saved in step 1: ```json theme={null} { "Authorization": "YOUR_KEY_ID" } ``` The `Bearer ` prefix is optional, Tyk Gateway strips it automatically if present. The exact header name depends on your API's authentication configuration. </Note> <img alt="GraphQL API Playground" /> ## GraphQL Server URL and Baseline URL The **GraphQL Server URL** is the endpoint the Playground sends queries to. It must point to your GraphQL API on the Tyk Gateway. From v1.16.0, the Developer Portal automatically constructs this URL from two values: ``` {Gateway Base URL}/{API listen path} ``` The **Gateway Base URL** is the public-facing base URL of your Tyk Gateway (for example, `https://gateway.example.com`). Set it in **Admin Portal > Providers > \[your provider] > Baseline URL**. If the Gateway Base URL is not configured, the server URL field displays `<<gateway url>>`. Enter the full URL manually before saving. ## SDL and Introspection Behavior GraphQL introspection is a built-in feature that allows clients to query an API's schema to discover its available types and operations. The Playground uses introspection to display the schema when no SDL file has been uploaded. The Playground loads its schema in the following order: | SDL file status | Playground behavior | | :- | :- | | SDL file uploaded | Schema is loaded from the uploaded file. Introspection is not needed, so the Playground works even on authenticated or network-restricted APIs. | | No SDL file | Playground attempts live introspection against the GraphQL Server URL. | | No SDL file, introspection fails | Playground enters read-only mode with a warning banner. Queries cannot be executed. | For APIs that require authentication, uploading an SDL file is strongly recommended. Introspection is blocked on protected endpoints, and without an SDL file the Playground will fall back to read-only mode. ## Universal Data Graph APIs From v1.16.0, [Universal Data Graph (UDG)](/docs/api-management/data-graph) APIs appear alongside standard GraphQL APIs in the API selection list. Configure the Documentation tab for a UDG API the same way: upload the SDL file and set the GraphQL Server URL. **Limitation:** REST data sources in a UDG API do not support GraphQL subscriptions. Subscription operations will not be available in the Playground for those data sources. ## Credential Injection in the Playground When an API Consumer's [Developer App](/docs/portal/developer-app) has been approved to access a Product, their credentials are automatically pre-populated in the Playground's HTTP headers. No additional configuration is required. The header format matches the authentication scheme of the APIs in the Product. For example, for an [Auth Token](/docs/api-management/authentication/bearer-token) API: ```json theme={null} { "Authorization": "<consumer-token>" } ``` ## Troubleshooting <AccordionGroup> <Accordion title="404 GraphQL API Not Found error in the Playground"> The Playground cannot locate your GraphQL API endpoint. Ensure the GraphQL Server URL ends with a trailing slash. For example, use `http://localhost:8080/my-graphql-api/` not `http://localhost:8080/my-graphql-api`. You can find the correct endpoint URL in the **Core Settings** tab of your GraphQL API in Tyk Dashboard. </Accordion> <Accordion title=""Failed to fetch" error in the Playground"> This error is caused by CORS (Cross-Origin Resource Sharing) restrictions on the API. The browser blocks requests from the Live Portal origin to the Gateway. Add the following CORS configuration to your GraphQL API definition, replacing the `allowed_origins` value with the URL of your Live Portal: ```json expandable theme={null} { "CORS": { "enable": true, "max_age": 24, "allow_credentials": true, "exposed_headers": ["*"], "allowed_headers": ["*"], "options_passthrough": true, "debug": false, "allowed_origins": ["http://<DEVELOPER_PORTAL>:<PORT>"], "allowed_methods": [] } } ``` </Accordion> <Accordion title="Playground is in read-only mode"> The Playground enters read-only mode when no SDL file has been uploaded and live introspection of the endpoint fails. To resolve this, try one of the following: * Upload a GraphQL SDL file on the **Documentation** tab of the API Product. * Verify the **GraphQL Server URL** is correct and reachable from the Portal server. * If the API requires authentication, upload an SDL file; introspection is blocked on authenticated endpoints. </Accordion> </AccordionGroup> # How to Associate API Products with Tyk Managed Custom Credentials Source: https://tyk.io/docs/tyk-developer-portal/import-custom-credentials This guide explains how an admin of the Tyk Developer Portal can associate API Products with Tyk Managed Custom Credentials. It covers the manual UI steps, how to verify on the developer portal, and guidance for bulk imports via the Developer Portal APIs. ## Availability | Component | Version | Editions | | :- | :- | :- | | Developer Portal | Available since [v1.12.0](/docs/developer-support/release-notes/portal#1-12-0-release-notes) | Enterprise | ## Prerequisites 1. **Dashboard License**: [Contact our team](https://tyk.io/contact/) to obtain a license or get self-managed trial license by completing the registration on our [website](https://tyk.io/self-managed-trial/). 2. **Working Tyk Environment:** You need access to a running Tyk instance. For setup instructions using Docker, please refer to the [Tyk Getting Started Guide](/docs/getting-started/quick-start). 3. Developer Portal Setup with 1. Admin access to the Tyk Developer Portal. 2. The end user (developer accounts) must exist in the portal. 3. Tyk Developer Portal v1.12.0 or later 4. [API Products](/docs/portal/api-products), [Plans](/docs/portal/api-plans) and [Catalogue](/docs/tyk-stack/tyk-developer-portal/enterprise-developer-portal/managing-access/manage-catalogues) already created and published in the portal. 4. The custom token or credential value you want to import. ## What we will do 1. Create an [application](/docs/portal/developer-app) in the Developer Portal for the user. 2. Add a custom credential to that app. 3. Select one or more [API Product](/docs/portal/api-products) and the [Plan](/docs/portal/api-plans) to associate with that credential. 4. Save, confirm visibility on the user’s developer portal dashboard, and verify API access. <Note> **Watch the video demo on YouTube** — a short walkthrough that shows the entire flow (creating an app, importing a custom token, attaching products & plans, and verifying access). <iframe title="How to Import Custom API Tokens into the Tyk Developer Portal (Step-by-Step)" /> </Note> ## Instructions Follow these steps to associate products and plans with custom credentials in the Tyk Developer Portal: ### 1. Create Application and Import Custom Credential 1. Log in to the Developer Portal as an **Administrator**. 2. In the left-hand navigation, go to **Apps** 3. Click **Add New App** * Enter a **Name** for the application (e.g., `Demo App`). * Select the **App Owner** that this application belongs to (the developer/customer account). 4. Next, click on the **Add Credential** button. <img alt="Add Custom Credential Button" /> * **Credential alias**: descriptive name for the credential (e.g., `Custom API Token`). * **Type of Credential**: choose **Tyk Managed** (so the portal can manage the credential metadata). * **Authentication method**: select **Auth Token**. * **Tyk authentication token type**: choose **Custom** (so you can paste your existing token value). * **Key ID**: paste the actual token value you are importing. 5. Next, in the **Access rights** section: * In the same dialog, choose the **Plan** you want to attach to this credential. * Select the API **Products** (one or more) that this credential should provide access to. 6. Click **Save** to create the application. <Note> When you add a Tyk Managed Custom Credential, the Developer Portal automatically creates a corresponding API key in the Tyk Dashboard for that credential. You can find this key in the Dashboard, which allows you to manage and monitor its usage alongside other credentials. <img alt="Custom Credentials Dashboard" /> </Note> ### 2. Verify in Live Portal 1. Log in to the **developer portal** as the end user. 2. Go to **My Apps**, by clicking on your profile icon in the top-right corner and select **My Dashboard** from the dropdown. <img alt="View My Apps" /> 3. Open the created **Application** (Demo App), now the user can view: 1. The imported custom token. 2. **Products** associated with the credential and click into them to view OpenAPI specs, Graph explorer, or other product details. 3. The Plan details (rate limits, quotas) should be visible as part of the application/product view so the user understands limits that apply to their token. <img alt="View My Credentials" /> ### 3. Verify API access The exact header and method depend on how your gateway expects the token (Authorization header, X-API-Key, etc.). Example (replace `CUSTOM_KEY` and `https://api.example.com/endpoint` with your values): ```bash theme={null} curl -v -H "Authorization: Bearer CUSTOM_KEY" https://api.example.com/endpoint ``` If everything is set up correctly, you should receive a successful response from the API, confirming that the custom credential is working and has access to the associated products. ## Import Custom Credentials via API If you have a large number of users and tokens to import, you can replicate the workflow above programmatically using the Tyk Developer Portal APIs. 1. Use the [Create Application API](https://tyk.io/docs/api-reference/applications-and-credentials/create-a-new-developer-application) to create the application for the user. ```bash theme={null} curl --request POST \ --url http://localhost:3001/portal-api/apps \ --header 'Authorization: <api-key>' \ --header 'Content-Type: application/json' \ --data '{ "Name": "Payment App", "Description": "This is my payment application", "RedirectURLs": "https://app-host/auth", "UserID": 1, "Visibility": "personal" }' ``` 2. Use the [Add Credential to Application API](https://tyk.io/docs/api-reference/applications-and-credentials/create-a-custom-credential) to add the custom credential, specifying the token value, and associating the desired products and plan. ```bash theme={null} curl --request POST \ --url http://localhost:3001/portal-api/apps/{app_id}/custom_credentials \ --header 'Authorization: <api-key>' \ --header 'Content-Type: application/json' \ --data '{ "Alias": "<string>", "Type": "CREDENTIAL_TYPE_TYK_MANAGED", "PlanID": 123, "AuthenticationMethod": "<string>", "ProductIDs": [ 123 ], "AuthTokenType": "AUTH_TOKEN_CUSTOM", "KeyID": "<string>", "CredentialKey": "<string>", "CredentialSecret": "<string>", "ProviderID": 123, "ClientTypeID": 123 }' ``` # How to use Existing Credentials with Multiple API Products Source: https://tyk.io/docs/tyk-developer-portal/single-credentials-multiple-api-products This guide explains how to use existing credentials with multiple API Products in the Tyk Developer Portal ## Availability | Component | Version | Editions | | :- | :- | :- | | Developer Portal | Available since [v1.16.0](/docs/developer-support/release-notes/portal#1-16-0-release-notes) | Enterprise | ## Prerequisites 1. **Dashboard License**: [Contact our team](https://tyk.io/contact/) to obtain a license or get self-managed trial license by completing the registration on our [website](https://tyk.io/self-managed-trial/). 2. **Working Tyk Environment:** You need access to a running Tyk instance. For setup instructions using Docker, please refer to the [Tyk Getting Started Guide](/docs/getting-started/quick-start). 3. Developer Portal Setup with 1. Admin access to the Tyk Developer Portal. 2. The end user (developer accounts) must exist in the portal. 3. Tyk Developer Portal v1.16.0 or later. 4. [API Products](/docs/portal/api-products), [Plans](/docs/portal/api-plans) and [Catalogue](/docs/tyk-stack/tyk-developer-portal/enterprise-developer-portal/managing-access/manage-catalogues) already created and published in the portal. 5. Approved access request to an API Product as a developer and an application already created. please refer to the [guide](/docs/tyk-developer-portal/direct-access-flow#instructions). ## What we will do 1. Request access to an [API Product](/docs/portal/api-products) as a developer and create a new [application](/docs/portal/developer-app). 2. Add more products to an existing application by reusing credentials. 3. Change the [Plan](/docs/portal/api-plans) for an existing credential. 4. Handle scenarios where different plans require separate credentials within the same app. ## Instructions Follow these steps to configure and use the Direct Access flow in the Tyk Developer Portal: ### 1. Add More Products Using an Existing Credential Once you have an application with approved access to at least one API product, you can add access to additional products using your existing credential: 1. Log in to the **Developer Portal** as an API Consumer. 2. Navigate to **Catalogues** and select another API product. 3. Select the **same plan** that your existing credential uses (e.g., if your existing credential uses "Gold", select "Gold" for the new product). 4. Click **Access with this plan**. 5. On the access request page, select your existing **Application** from the dropdown. You will see the option to **use an existing credential**. 6. Choose the existing **Credential** that uses the matching plan. 7. Click **Submit request**. <img alt="Select Existing Credentials for the API Product" /> <Note> **Key benefit**: Your existing credential will now provide access to both API products. You don't need to manage multiple API keys when using the same plan across multiple products. </Note> #### View Your Credentials **After approval:** 1. Click on your profile icon in the top-right corner and select **My Dashboard** from the dropdown. 2. Go to **My Apps** in the left navigation. 3. Click on your application. 4. In the **Credential Management** section, you will see your access credentials. * Click **Show** to reveal the API key. * Copy the credentials for use in your API requests. <img alt="single credentials multiple api products" /> ### 2. Change the Plan for an Existing Credential Developers can upgrade or downgrade their plan for existing product access: 1. Log in to the **Developer Portal** and navigate to **My Dashboard**. 2. Go to **My Apps** and click on the relevant application. 3. Find the credential you want to modify. 4. Click **Change plan** 5. Choose your new plan from the available options (e.g., upgrade from Gold to Platinum). 6. Submit the plan change request. <Warning> **Important behavior for plan changes:** * A plan change creates a new access request that requires approval (unless the new plan is configured for auto-approval). * Your current access remains active on the existing plan until the new plan is approved. * If your credential provides access to multiple API products, changing the plan will affect access to **all products** on that credential. </Warning> ### 3. Handle Different Plans Within the Same Application When you want to add an API product using a **different plan** than your existing credentials: 1. Log in to the **Developer Portal** and navigate to **Catalogues**. 2. Select an API product. 3. Select a **different plan** than your existing credentials use (e.g., if your existing credential uses "Gold" but you want "Bronze" for this product). 4. Click **Request access**. 5. On the access request page, you will **not** see the option to reuse your existing credential. 6. The system will require you to **create a new credential** for this plan: * Enter a **Name** for the new credential. * Complete the access request form. 7. Click **Submit request**. <Note> **Why a new credential is required**: A single credential can only be associated with ONE API plan. This ensures consistent rate limiting and quota enforcement across all products accessed through that credential. </Note> #### Credential Compatibility Reference | Scenario | Can Reuse Existing Credential? | Action Required | | - | - | - | | Same plan as existing credential | Yes | Select existing credential | | Different plan than existing credential | No | Create new credential | # Forgotten Password Source: https://tyk.io/docs/tyk-developer-portal/tyk-enterprise-developer-portal/api-consumer-portal/reset-password How to reset your password when using Tyk Developer Portal If you've forgotten your password, you can easily reset it through the Developer Portal. This process works for both API Owners and API Consumers. 1. Navigate to the Developer Portal and select the **Login** button. <img alt="Portal login screen showing the login form with username and password fields" /> 2. On the login screen, select the **Forgot Password?** link located below the login form. <img alt="Password reset form requesting email address" /> 3. Enter the email address associated with your account and select **Reset**. <img alt="Confirmation screen showing that a password reset email has been sent" /> 4. Check your email inbox for a message from the Tyk Developer Portal. The email will contain a password reset link in this format: `https://<your-portal-domain>/auth/reset/code?token=<token-id>` 5. Click the reset link in the email. This will take you to a password reset page in the Developer Portal. 6. Enter your new password in both fields and click **Reset**. <img alt="Password reset form with fields to enter and confirm a new password" /> 7. After successfully resetting your password, click **Login again** to return to the login screen with your new credentials. <img alt="Success screen confirming the password has been reset" /> ## Important Notes * Password reset links are valid for a limited time only * If your reset link expires, simply restart the process * Ensure your new password meets the system's security requirements * For security reasons, you'll be required to log in immediately after resetting your password # Managing API Access Requests Source: https://tyk.io/docs/tyk-stack/tyk-developer-portal/enterprise-developer-portal/api-access/approve-requests How to provision API Access Requests in Tyk Developer Portal ## Introduction API Access Requests are formal requests from API Consumers to access specific API Products and Plans through the Developer Portal. These requests initiate the workflow for granting, or provisioning, API access to users. ### Understanding the Provisioning Request Workflow When API Consumers discover APIs in your Catalog that they need access to, they initiate a API Access Request through the Live Portal. This request: * Identifies the specific API Product and subscriptionPlan they want to access * Specifies which Developer App should receive the access credentials * Creates an auditable record of the access request Depending on your configuration, these requests can be processed [automatically]() or require [manual approval](/docs/tyk-stack/tyk-developer-portal/enterprise-developer-portal/api-access/approve-requests#manual-approval-workflow). <img alt="" /> ## Requesting Access to an API Product API Consumers can request access to API Products through the Live Portal using one of two configured flows. To learn how to configure this flow visit [Access Flow Types](https://tyk.io/docs/portal/overview/concepts#Access-Flow-Types) ### Initial Steps (Both Flows): 1. From the **Catalogues** page, choose the API Product of interest and select **More info** 2. On the API Product detail page, decide which of the available Plans to subscribe to and select **Access with this Plan** 3. **The next steps depend on your portal's configured access flow**: #### Direct Access Flow When Direct Access Flow is enabled, you can request access to API Products immediately without using a shopping cart. **Steps:** * You'll be taken directly to the access request page with your selected product and plan pre-populated * Select or create a Developer App to store your credentials * Configure credentials (new or extend existing compatible credentials) * Select **Continue** to submit your request **Credential Compatibility Rules** For existing credentials to be compatible, they must: * Have the same Plan as the selected product * Not already include the selected product * Have a matching authentication type with the product For more information, refer to this [guide](/docs/tyk-developer-portal/direct-access-flow) #### Cart-Based Flow When Cart-Based Flow is enabled, you can add multiple API Products to a shopping cart before submitting a single access request. **Steps:** * The API Product and Plan combination will be added to your cart * Repeat steps 1-2 for additional API Products you want to access * Go to the **Cart** using the icon in the top right of the screen * Review your selections and select a Developer App * Select **Submit request** ### After Submission * Your access request will be submitted for approval (if required) * Track request status in **My Apps** * Once approved, credentials will be available in your selected Developer App ## Manual Approval Workflow The manual approval workflow provides API Owners with oversight of all API access. When an API Consumer completes an [access request](/docs/tyk-stack/tyk-developer-portal/enterprise-developer-portal/api-access/approve-requests#requesting-access-to-an-api-product), API Owners receive notification of pending request via [email](/docs/product-stack/tyk-enterprise-developer-portal/getting-started/setup-email-notifications) and should then: 1. Navigate to the **API Consumers > Access Requests** page in the Admin Portal 2. Review the request * User name * Developer App * Requested API Products * Selected subscription Plan 3. Approve or reject the request from the three dot menu * If approved, access is provisioned with credentials issued to the specified Developer App * If rejected, access will not be granted * API Consumer receives notification of the decision via email ## Automatic Approval Workflow For trusted users or specific API Products, you can enable automatic approval in the [subscription Plan](/docs/portal/api-plans#auto-approve-provisioning-requests). To configure automatic approval, the API Owner should: 1. Navigate to the **Plans** page in the Admin Portal 2. Select or create the API Plan that should be automatically approved 3. Set the **Auto approve access request** checkbox <img alt="Auto Approve API provisioning requests" /> 4. Select **Save changes** When an API Consumer requests access using this plan, the request will be approved immediately and access credentials provisioned to the Developer App. <Note> Despite automatic approval, a record of the request is maintained in the **API Consumers > Access requests** page in the Admin Portal. </Note> ## Notification of Decision The Dev Portal sends notification to the API Consumer when their request is approved or rejected. If the [email service](/docs/product-stack/tyk-enterprise-developer-portal/getting-started/setup-email-notifications) is configured, then: * When a request is approved: * The system sends an approval notification email to the user * The email uses the template "approve" with a configurable subject * The notification includes details about the approved access * When a request is rejected: * The system sends a rejection notification email to the user * The email uses the template "reject" with a configurable subject ## Update Products and Plans of an Access Request Starting from v1.16.0, the Tyk Developer Portal enables users to efficiently manage their access requests by adding or removing API Products and modifying subscription plans for existing credentials. This eliminates credential sprawl and provides a streamlined experience. The following features can be accessed via "App" page, under each access credential. #### Adding Products to Existing Access Request Users can extend their existing credentials with additional API Products when compatibility requirements are met, avoiding the need to creating new credentials for additional API products. **Compatibility Requirements** Products can be added to existing credentials when they share: * Same authentication method * Same subscription plan * Products not already included in the credential When requesting access to an API Product, developers can choose to create a new credential or use one of the compatible existing credential. For more information, refer to this [guide](/docs/tyk-developer-portal/single-credentials-multiple-api-products) #### Removing Products from Access Requests Users can remove individual API Products from credentials that contain multiple products, maintaining access to remaining products while revoking access to unwanted ones. This provides granular control over application permissions without affecting the entire credential. #### Plan Management Users can update subscription plans for existing access requests without generating new credentials. Plan modifications maintain existing product associations where compatibility allows. Currently, Plan management is available to OAuth 2.0 access requests only. # Configuring Custom Rate Limit Keys in Developer Portal Source: https://tyk.io/docs/tyk-stack/tyk-developer-portal/enterprise-developer-portal/api-access/configuring-custom-rate-limit-keys How to configure custom rate limit keys in Tyk Developer Portal ## Introduction The Tyk Enterprise Developer Portal supports custom rate limiting patterns that allow you to apply rate limits based on entities other than just credentials, such as per application, per developer, or per organization. This is particularly useful for B2B scenarios where API quotas need to be shared across multiple developers and applications within an organization. For detailed information about custom rate limiting concepts and configuration, see the [Custom Rate Limiting](/docs/api-management/rate-limit#custom-rate-limiting) section in the main Rate Limiting documentation. **Prerequisites** This capability works with [Tyk 5.3.0](/docs/developer-support/release-notes/dashboard#5-3-0-release-notes) or higher. ## Configuring Custom Rate Limit Keys in the Portal <Note> If you are using Tyk Developer Portal version 1.13.0 or later, you can configure the custom rate limit keys directly from the Developer Portal in the Advanced settings (optional) collapsible section of the Plan's view (by Credentials metadata). <img alt="Add Plan Advanced Settings" /> </Note> For general configuration of custom rate limit keys in policies, refer to the [Custom Rate Limiting](/docs/api-management/rate-limit#custom-rate-limiting) documentation. ## Using Custom Rate Limit Keys with the Portal The Tyk Enterprise Developer Portal facilitates the configuration of various rate limiting options based on a business model for API Products published in the portal. To achieve this, the portal, by default, populates the following attributes in the credential metadata, which can be used as part of a custom rate limit key: * **ApplicationID**: The ID of the application to which the credential belongs. * **DeveloperID**: The ID of the developer who created the credential. * **OrganisationID**: The ID of the organization to which the developer belongs. Additionally, it's possible to attach [custom attribute values](/docs/portal/customization/user-model#add-custom-attributes-to-the-user-model) defined in a developer profile as metadata fields to credentials. When a credential is provisioned by the portal, all the fields described above are added as metadata values to the credential, making them valid options for configuring the rate limit key: <img alt="Credential's metadata" /> This approach allows the portal to seamlessly apply rate limits based on any combination of the aforementioned fields and other custom metadata objects defined in policies used for plans or products. This is in addition to credentials. *** <Note> **Tyk Enterprise Developer Portal** If you are interested in getting access contact us at [support@tyk.io](<mailto:support@tyk.io?subject=Tyk Enterprise Portal Beta>) </Note> # Dynamic Client Registration Source: https://tyk.io/docs/tyk-stack/tyk-developer-portal/enterprise-developer-portal/api-access/dynamic-client-registration Learn how to use Dynamic Client Registration to grant access to API Products ## Introduction Dynamic Client Registration (DCR) is an [IETF protocol](https://datatracker.ietf.org/doc/html/rfc7591) that automates the registration of OAuth 2.0 clients with an authorization server. The Tyk Developer Portal uses DCR so that when an API Consumer is approved for access to an API Product, they receive OAuth 2.0 credentials automatically. The API Consumer has no direct interaction with the IdP during this process; the Portal handles client registration on their behalf. DCR requires an Identity Provider (IdP) that acts as an OAuth 2.0 authorization server, supports the DCR protocol, and exposes an OIDC well-known configuration endpoint. [OpenID Connect (OIDC)](https://openid.net/connect/) is an identity layer built on top of OAuth 2.0 that standardizes the discovery endpoint used by the Portal to locate the IdP's DCR and token endpoints. This page covers JWT-based flows, where the IdP issues access tokens as JSON Web Tokens (JWTs). When an API Consumer's access request is approved, the Portal registers a new client with the IdP and writes the resulting IdP configuration into Tyk. At runtime, the API Consumer uses their credentials to obtain a JWT from the IdP, then presents it to Tyk Gateway when calling an API. The Gateway [validates the token's signature](/docs/api-management/authentication/jwt-signature-validation) using the public keys published by the IdP at its JWKS endpoint, and maps the token's [scopes](#oauth-2-0-scopes) to Tyk policies to enforce access control. ```mermaid theme={null} sequenceDiagram participant Dev as Developer / App participant Portal as Tyk Developer Portal participant IdP as Identity Provider (IdP) participant GW as Tyk Gateway rect rgb(235, 245, 255) Note over Dev,GW: Setup: one time, on access request approval Dev->>Portal: Submit access request Portal->>IdP: Register OAuth 2.0 client (DCR) IdP-->>Portal: Client credentials Portal->>GW: Write JWKS URI + scope mappings Note over Portal,GW: via Identity Provider Registry or API definition Portal-->>Dev: Approval notification + credentials end rect rgb(240, 255, 240) Note over Dev,GW: Runtime: every API request Dev->>IdP: Request JWT (client credentials) IdP-->>Dev: JWT (signed access token) Dev->>GW: API call with JWT GW-->>IdP: Fetch JWKS (cached) GW->>GW: Validate signature + map scopes to policies GW-->>Dev: API response end ``` ### Developer Apps and OAuth Clients A Developer App in the Portal corresponds 1:1 to an OAuth 2.0 client registered in the IdP. When a DCR access request is approved, the Portal registers an OAuth client in the IdP on the API Consumer's behalf and stores the resulting credentials against the Developer App. The API Consumer uses these credentials to request access tokens from the IdP. A single Developer App can hold access to multiple API Products and Plans. Each subsequent approval adds the new scopes to the same OAuth client in the IdP rather than creating a new one. The API Consumer's credentials remain unchanged; their scope set grows. ### OAuth 2.0 Scopes OAuth 2.0 scopes are central to how Tyk enforces access control in the DCR flow. Understanding their role makes the configuration steps that follow easier to understand. In Tyk's DCR flow, scopes serve as the link between the IdP, the API Consumer's access token, and Tyk's access control policies. Each API Product and each Plan has a unique scope name assigned to it. That scope name is what gets embedded in the access token by the IdP, and it is what Tyk Gateway uses to look up which policy to apply. Tyk's scope-to-policy mapping resolves one scope name to exactly one Tyk policy. No two API Products or Plans may share a scope; a duplicate would cause both to resolve to the same policy. Tyk Gateway combines the policies resolved from all scopes present in the token to authorize the request. The full sequence is: 1. When an access request is approved, the Portal sends the scope names for the approved Product and Plan to the IdP as part of registering the OAuth 2.0 client. The IdP associates those scopes with that client, constraining what it can request. 2. When the API Consumer requests an access token, they must explicitly include those scope names. The IdP will only return scopes that are both registered with the client and present in the token request. 3. Tyk Gateway reads the scopes in the incoming JWT and maps each one to its corresponding Tyk policy, enforcing the access control and rate limits defined for that Product and Plan. Every API Product and Plan used with DCR must therefore have a unique scope assigned, and that scope must exist in the IdP before the Product or Plan is published. Publishing makes it available for access requests; if a scope is missing when a request is approved, the Portal's attempt to register the OAuth client will fail. Scope names must exactly match between the IdP and the Portal. ## How Portal Manages Identity Providers Identity Providers are configured in the Portal under the **OAuth 2.0 Providers** menu. This is the Portal's term for an IdP. The two are the same concept: an OAuth 2.0 Provider in the Portal represents an external IdP that the Portal will register DCR clients with. There are two approaches to how the Portal stores IdP configuration in Tyk. | Approach | Available From | Where Scope Mappings Are Written | | :- | :- | :- | | Identity Provider Registry (recommended) | Portal 1.18.0, Tyk 5.14.0 | Identity Provider Registry | | API Definition | All versions | API definitions | The **Identity Provider Registry** approach is recommended for all new deployments. It stores IdP configuration centrally in the Tyk Dashboard, decoupled from API definitions, eliminating write conflicts between the Portal and Tyk Dashboard and ensuring that IdP configuration is kept up to date as API Products change and as OAuth 2.0 Providers are created, updated, or deleted. Refer to the [Identity Provider Registry](/docs/api-management/client-idp-registry) page for more detail. The **API definition** approach is available for installations running Tyk prior to 5.14.0, or for deployments where the Registry cannot be used. The Portal writes the JWKS URI and scope-to-policy mappings directly into the relevant API definitions when an access request is approved. <Note> Refer to [Migrating to the Identity Provider Registry](#migrating-to-the-identity-provider-registry) if you have an existing installation using DCR and wish to use the IdP Registry. </Note> ## Configure Your Identity Provider Before configuring Tyk Developer Portal, you need to prepare the IdP in two ways: authorize the Portal to register OAuth 2.0 clients on behalf of API Consumers, and define the OAuth 2.0 scopes that will be included in access tokens. These steps are required regardless of which approach you use. ### Authorize the Portal Most IdPs use an [initial access token](https://openid.net/specs/openid-connect-registration-1_0.html#Terminology) to authorize a trusted client to register new OAuth 2.0 clients via the DCR protocol. The Portal presents this token when registering a client for an API Consumer, proving it has permission to do so. Some IdPs use a different authorization mechanism and do not require an initial access token, for example: * Gluu uses a `dynamicRegistrationEnabled` flag on each scope instead. * Auth0 uses a separate authorization model and does not issue initial access tokens. * Descope leaves its registration endpoint unauthenticated and constrains registration through approved scope and redirect URL lists instead. ### Define OAuth 2.0 Scopes Create scopes in the IdP for each API Product and Plan you intend to use with DCR, following the naming and uniqueness requirements in the [OAuth 2.0 Scopes](#oauth-2-0-scopes) section above. Scopes must exist before the Product or Plan is published; see that section for details. The provider-specific tabs below show how to create scopes in each supported IdP. ### Provider-Specific Instructions <Tabs> <Tab title="Keycloak"> Follow the [Keycloak client registration guide](https://www.keycloak.org/securing-apps/client-registration) to obtain the initial access token. Create scopes for each API Product and Plan from the **Client scopes** menu item. Set the scope type to **Optional**. Default scopes are applied automatically to all clients, but optional scopes can be requested on a case-by-case basis. The Portal requests specific scopes during client registration; using optional scopes ensures those scopes are included only when explicitly requested. <img alt="Navigate to the Client scopes menu item" /> <img alt="Client Scope Assigned Type" /> </Tab> <Tab title="Okta"> To obtain a Registration Access Token for Okta, go to **Okta Admin Console > Security > API > Tokens** and click **Create New Token**. Copy the token value; you will need it when configuring the OAuth 2.0 Provider in the Portal. For more details, refer to the [Okta Dynamic Client Registration guide](https://developer.okta.com/docs/reference/api/oauth-clients/). Create scopes for each API Product and Plan from the **Scopes** tab on the **Security > API** screen. All scopes must be associated with an authorization server. If you do not have a custom authorization server, use the **Default** one. Note the authorization server's issuer URL; you will need it when setting the OIDC well-known configuration URL in the Portal. The URL takes the form `https://{your-domain}/oauth2/default/.well-known/openid-configuration`. <img alt="Add or Edit OAuth servers in Okta" /> </Tab> <Tab title="Auth0"> Auth0 does not require an initial access token. Follow the [Auth0 Dynamic Client Registration guide](https://auth0.com/docs/get-started/applications/dynamic-client-registration) to configure DCR. Create scopes for each API Product and Plan by navigating to **Dashboard > Applications > APIs**, selecting your API, and opening the **Permissions** tab. Enter the permission name and description for each scope, then click **Add**. </Tab> <Tab title="Curity"> When using [Curity](https://curity.io) as the Identity Provider, you must configure the DCR endpoint to use `no-authentication`. By default, Curity requires a nonce token with a `dcr` scope to authenticate the DCR endpoint, but nonce tokens are one-time-use and cannot be stored as a reusable credential in the Portal. Setting the authentication method to `no-authentication` allows the Portal to register clients without presenting a token. Ensure that network access to the Curity DCR endpoint is restricted to Tyk only, since it will be unauthenticated. To configure this: go to **Profiles > Token Service > Dynamic Registration**, scroll to the **Non-templatized** section, and set **Authentication Method** to `no-authentication`. Create scopes for each API Product and Plan from **Profiles > Token Service > Scopes**. <img alt="Navigate to the Scopes menu" /> For more information, see the [Curity DCR documentation](https://curity.io/docs/identity-server/profiles/token-profile/clients/dcr). </Tab> <Tab title="Descope"> [Descope](https://www.descope.com/) does not use an initial access token for DCR. Leave the **Registration access token** field empty when you configure the OAuth 2.0 Provider. Restrict network access to the Descope registration endpoint to Tyk only, since it is unauthenticated. Descope calls its OAuth 2.0 authorization server feature **Inbound Apps**. To enable DCR, open the [Inbound Apps page](https://app.descope.com/apps/inbound) in the Descope Console, click **DCR Settings** in the top right, and turn on **Enable dynamic client registration**. The registration endpoint is absent from the discovery document until you do. The **OIDC well-known configuration URL** then takes the form `https://api.descope.com/v1/apps/<project-id>/.well-known/openid-configuration`. Substitute your regional or custom base URL if you use one. Create a scope for each API Product and Plan from the **Approved Scopes List** in the same settings panel. Descope grants only the scopes on this list. If the Portal requests a scope that is missing, registration still succeeds, but the token will not carry that scope and Tyk Gateway will reject the request. Turn **Empty Scope Handling** off as well: with it on, Descope grants the whole list to a registration that matches no approved scope. In **Approved Redirect URLs**, add the redirect URLs your API Consumers will enter at checkout. The field accepts `*` wildcards. Set the **Flow Hosting URL** to your consent flow before you register any client. The Portal cannot name a flow in its registration request, so Descope falls back to the project default. Descope accepts only the `authorization_code` and `refresh_token` grants at its registration endpoint, so define your Client Profiles with those. Descope rejects the client credentials grant with `400 Bad Request`. Descope does not return the [RFC 7592](https://datatracker.ietf.org/doc/html/rfc7592) credentials needed to add scopes to an OAuth 2.0 client after registration, so it cannot accumulate scopes on one client the way [Developer Apps and OAuth Clients](#developer-apps-and-oauth-clients) describes. Instruct your API Consumers to create a new credential for each API Product rather than reuse an existing one. For more information, see the [Descope Dynamic Client Registration documentation](https://docs.descope.com/identity-federation/inbound-apps/creating-inbound-apps#method-2-dynamic-client-registration-dcr). </Tab> <Tab title="Gluu"> [Gluu](https://gluu.org/) does not use an initial access token for DCR. Instead, DCR is authorized per-scope via the **Dynamic Registration** toggle. Create scopes for each API Product and Plan by navigating to **Configuration > OpenID Connect > Scopes** and clicking **Add Scope**. For each scope, enable the **Dynamic Registration** toggle so that it can be included in DCR client registration requests. For more information, see the [Gluu Server documentation](https://docs.gluu.org). </Tab> </Tabs> ## Configure Tyk Developer Portal ### Enable the Identity Provider Registry (Recommended) The Identity Provider Registry is available from Tyk Developer Portal 1.18.0 when using Tyk Dashboard 5.14.0 or later. It must be explicitly enabled in Tyk Developer Portal by setting [`TYK_PORTAL_ENABLEIDPREGISTRY=true`](/docs/product-stack/tyk-enterprise-developer-portal/deploy/configuration#tyk_portal_enableidpregistry) (or `EnableIDPRegistry = true` in the config file) and restarting the Portal. Ensure that Tyk Gateway and Tyk Dashboard are running on version 5.14.0 or later before starting Tyk Developer Portal with this flag enabled. <Note> If you are running Tyk Dashboard prior to 5.14.0, skip this step as the IdP Registry is not available. </Note> ### Configure OAuth 2.0 Providers In the Admin Portal, navigate to **OAuth 2.0 Providers** (the Developer Portal's name for Identity Providers) and create an entry for each IdP you want to use with DCR. #### Connection Settings <img alt="Configuring the connection to the IdP in OAuth 2.0 Providers" /> | Field | Description | | :- | :- | | **Name** | A label to identify this OAuth 2.0 Provider in the Portal UI. This is also stored as the name of the corresponding entry in the Identity Provider Registry. | | **Identity provider type** | Select your IdP from the dropdown. If it is not listed, select **Other** to use a standard RFC 7591-compliant client registration flow. | | **OIDC well-known configuration URL** (required) | The OIDC discovery endpoint for your IdP. | | **Scope claim name** (optional) | The JWT claim that contains the token's scopes. Different IdPs use different claim names: `scope` is the most common, but some use `scp` or another custom claim. Defaults to `scope`. Used by Tyk Gateway when [mapping token scopes to policies](/docs/api-management/authentication/jwt-authorization#scope-policies). | | **Registration access token** (optional) | The token obtained in the [Authorize the Portal](#authorize-the-portal) section. | | **SSL insecure skip verify** (optional) | Enable only if your IdP uses a self-signed or privately issued certificate that Tyk cannot verify. This disables TLS certificate verification for connections to the IdP and should not be used in production. | #### Client Profiles When the Portal registers an OAuth 2.0 client in the IdP on behalf of an API Consumer, it must specify certain parameters that describe how access tokens will be obtained. These include the OAuth [grant type](https://datatracker.ietf.org/doc/html/rfc6749#section-1.3) and the authentication method used by the token endpoint. A **Client Profile** is a named template for these parameters (referred to as a **client type** in the Portal UI). You can define multiple Client Profiles to support different use cases. For example, you might define one Client Profile using the client credentials grant for server-to-server integrations and another using the authorization code grant for user-facing applications. When requesting access to an API Product in the Portal, API Consumers select from the list of Client Profiles defined for the IdP. The Portal uses that template when registering the OAuth 2.0 client that the IdP will use to issue tokens to that API Consumer. To add a Client Profile, scroll to **Client Types** and click **Add client type**. <img alt="Configuring a Client Profile for OAuth 2.0 client creation" /> | Field | Description | | :- | :- | | **Client type display name** | The name shown to API Consumers at checkout. Keep it short and descriptive, for example "Server-to-server" or "Web application". | | **Description** | Additional context to help API Consumers choose the right Client Profile. Not shown by default but configurable via templates. | | **Allowed response types** | Controls what the IdP returns to the API Consumer's application after authorization. Note: when using Okta with the client credentials grant, set this to `token`. <ul><li>`code`: authorization code to exchange for tokens</li><li>`token`: access token returned directly</li><li>`id_token`: identity token (OIDC)</li></ul>See the [OIDC specification](https://openid.net/specs/openid-connect-core-1_0.html#Authentication) for details. | | **Allowed grant types** | The OAuth 2.0 grant flow the API Consumer's application will use to obtain tokens. <ul><li>`client_credentials`: server-to-server, no user involved</li><li>`authorization_code`: user-facing applications</li><li>`refresh_token`: obtain new access tokens without re-authenticating</li></ul>See the [OAuth 2.0 specification](https://datatracker.ietf.org/doc/html/rfc6749#section-1.3) for details. | | **Token endpoint auth methods** | How the API Consumer's application authenticates to the IdP's token endpoint. <ul><li>`client_secret_basic`: credentials as a Base64-encoded Authorization header</li><li>`client_secret_post`: credentials in the request body</li></ul>See the [OIDC specification](https://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication) for details. | | **Okta application type** (Okta only) | The Okta application type to create: `web` for server-side apps, `native` for mobile or desktop, `browser` for single-page apps, `service` for machine-to-machine. | <Note> Your IdP may override some of these settings based on its own configuration. </Note> When you have finished, click **Save Changes**. <Note> When an OAuth 2.0 Provider is created, updated, or deleted in Portal, the corresponding entry in the Identity Provider Registry is updated immediately on every connected Tyk Dashboard. No approval is required to propagate the change. </Note> ### API Products and Plans Each API Product and each Plan used with DCR must have a unique OAuth 2.0 scope assigned, matching a scope you created in the IdP. See the [OAuth 2.0 Scopes](#oauth-2-0-scopes) section for the full requirements. See [API Products](/docs/portal/api-products#dynamic-client-registration) and [API Plans](/docs/portal/api-plans#dynamic-client-registration) for configuration instructions. <Note> When APIs are added to or removed from a DCR-enabled API Product, or when its DCR scopes are changed, the scope-to-policy mappings in the Identity Provider Registry are updated immediately. Existing tokens gain or lose access without requiring a new approval. This applies only when at least one access request for the API Product has already been approved. If no approval has ever been made, the Registry has no entry for that Product yet and there is nothing to update; the first approval will write the full mapping. </Note> ## End-to-End DCR Flow This section walks through the complete DCR flow from the perspective of each actor: an API Consumer requesting access, an API Owner approving it, and the API Consumer using their credentials to call an API. It covers what happens at each stage and what to expect as output. Before proceeding, confirm that the following are in place: * At least one [OAuth 2.0 Provider](#configure-your-identity-provider) is configured in the Portal, with at least one [Client Profile](#client-profiles) defined. * At least one API in Tyk Dashboard has JWT authentication enabled. * An API Product includes that API and has DCR enabled, with a scope assigned. * A Plan has a scope assigned. * Both scopes [exist in the IdP](#oauth-2-0-scopes). ### Request Access to the API Product The API Consumer discovers the DCR-enabled API Product in the catalog and submits an access request. As part of checkout, they select how their application will obtain tokens. As an API Consumer, log in and navigate to the catalog page. Select the DCR-enabled API Product, proceed to checkout, and complete the following: * Select a Plan. * Select an existing Developer App or create a new one. * Select a Client Profile (**client type** in the Portal UI). * If your Client Profile uses the authorization code grant, enter your application's redirect URI in the **Redirect URLs** field. This is the URL the IdP will redirect the user to after authentication, carrying the authorization code your application exchanges for a token. Separate multiple URIs with commas. * Click **Submit request**. <img alt="Request access to the DCR-enabled product" /> ### Approve the Access Request An API Owner reviews and approves the request. The Portal then registers a new OAuth 2.0 client with the IdP on the API Consumer's behalf, using the selected Client Profile to determine the grant type and token endpoint authentication method. The scopes from the API Product and Plan are associated with that client in the IdP. As part of the same process, the Portal retrieves the JWKS URI from the IdP and writes it, together with the scope-to-policy mappings, into Tyk. With `EnableIDPRegistry = true`, these are written to the Identity Provider Registry. Otherwise, they are written into the API definition. As an API Owner, navigate to **Access Requests**, select the request, and click **Approve**. <img alt="Approve DCR access request" /> ### Obtain an Access Token Once the request is approved, the API Consumer can retrieve their OAuth 2.0 credentials from **My Dashboard**. Navigate to the Developer App and copy the **client ID** and **secret**. <img alt="Copy the OAuth 2.0 credentials" /> Use these credentials to request an access token from the IdP's token endpoint. You must include the scopes for the API Product and Plan in the request. Tyk Gateway uses these to identify which policies to apply, and will reject requests where the token does not contain the expected scopes. The example below uses the `client_credentials` grant with the `client_secret_basic` authentication method, where credentials are passed as a Base64-encoded `{client_id}:{client_secret}` string in the `Authorization` header. ```bash theme={null} curl --location --request POST '<your-idp-token-endpoint>' \ --header 'Authorization: Basic N2M2NGM2ZTQtM2I0Ny00NTMyLWFlMWEtODM1ZTMyMWY2ZjlkOjNwZGlJSXVxd004Ykp0M0toV0tLZHFIRkZMWkN3THQ0' \ --header 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'scope=product_payments free_plan' \ --data-urlencode 'grant_type=client_credentials' ``` A successful response includes a JWT access token. Decode it to confirm it contains the expected scopes before making an API call. <img alt="An example of a JWT" /> ### Make an API Call With a valid JWT access token, the API Consumer can call the API. Tyk Gateway validates the token signature and maps the scopes to policies before forwarding the request. Use the access token to call the API: ```bash theme={null} curl --location --request GET '<your-gateway-url>/payment-api/get' \ --header 'Authorization: Bearer <your-access-token>' ``` ## Migrating to the Identity Provider Registry DCR support in Tyk Developer Portal has evolved across three eras. The table below summarizes each to help you identify your current state before migrating. | Era | Portal Version | How IdP Config Is Stored | Limitations | | :- | :- | :- | :- | | Legacy | Before 1.13.0 | Manually in each API definition | No Portal management of IdP configuration; scope mappings require manual setup per API in Tyk Dashboard | | API Definition | 1.13.0 to 1.17.x | Portal writes to API definitions at approval | Write conflicts possible between Portal and Tyk Dashboard; configuration not updated automatically when API Products change | | Identity Provider Registry | 1.18.0+ | Centralized Registry in Tyk Dashboard | Recommended for all deployments | ### Legacy Setup (Before Portal 1.13.0) Before Portal 1.13.0, DCR required fully manual configuration of scope-to-policy mappings in each Tyk Dashboard API definition. The Portal did not write anything into API definitions when an access request was approved. For each JWT-authenticated API, this involved: * Creating Tyk policies for the API Product and Plan * Creating a No Operation API and policy to satisfy the default policy requirement without granting real access. On Gateway versions prior to 5.11.0, Tyk required a default policy on APIs using scope-to-policy mapping; the No Operation API satisfied this without overriding the Product and Plan policies. From Gateway 5.11.0 onwards this workaround is no longer needed. * Manually enabling scope-to-policy mapping on each API definition and configuring the JWKS URI, scope-to-policy mappings, and default policy directly To migrate to the Identity Provider Registry, first upgrade to Portal 1.18.0, then follow the [Migration Steps](#migration-steps) below. Note that the automatic backfill does not cover manually configured API definitions. You will need to create OAuth 2.0 Providers in the Portal for each IdP, then populate the Registry manually via `POST /api/clientidps`. ### API Definition Era (Portal 1.13.0 to 1.17.x) From Portal 1.13.0, the Portal began managing IdP configuration directly. OAuth 2.0 Providers and Client Profiles are configured in the Portal, and when an access request is approved, the Portal automatically writes the JWKS URI and scope-to-policy mappings into the relevant API definitions. For each JWT-authenticated API, the setup required leaving the **Public key** and **default policy** fields blank. The Portal populated these when an access request was approved. On Gateway versions prior to 5.11.0, a No Operation API and policy were also required to satisfy the default policy requirement; from Gateway 5.11.0 this is no longer needed. The limitation of this approach is that API definition configuration takes precedence over any changes made in Tyk Dashboard, and write conflicts can occur if the Portal and Tyk Dashboard both manage the same API definition. Configuration is also not updated automatically when API Products change outside of an approval event. To migrate to the Identity Provider Registry, first upgrade to Portal 1.18.0, then follow the [Migration Steps](#migration-steps) below. ### Migration Steps 1. Set [`TYK_PORTAL_ENABLEIDPREGISTRY=true`](/docs/product-stack/tyk-enterprise-developer-portal/deploy/configuration#tyk_portal_enableidpregistry) (or `EnableIDPRegistry = true` in the config file) and restart the Portal. On startup, the Portal runs a backfill that creates Registry entries in Tyk Dashboard for any existing OAuth 2.0 Providers. Any new, or changes to existing, OAuth 2.0 Providers and API Products will be stored in the Registry going forward. If moving from a [legacy version](#legacy-setup-before-portal-1-13-0) there will be nothing for the backfill to process. 2. **Audit your API definitions.** Call `GET /api/clientidps` against the Tyk Dashboard API to inspect the Registry entries created by the backfill. For each JWT-authenticated API, compare the JWKS URI and scope-to-policy mappings in the API definition against what the Registry now contains. Pay particular attention to any IdP configuration that was added directly in Tyk Dashboard rather than through the Portal. The backfill only covers OAuth 2.0 Providers managed by the Portal; configuration added manually outside the Portal will not appear in the Registry after the backfill. Any such configuration must be added to the Registry manually via `POST /api/clientidps` before proceeding to the next step. <Note> There is no Tyk Dashboard UI for the Identity Provider Registry. All inspection and manual management must be done via the [Tyk Dashboard API](/docs/tyk-dashboard-api). </Note> 3. **Remove IdP configuration from API definitions.** Once the Registry is verified as complete and correct, you can remove the JWKS URIs and scope-to-policy mappings from each API definition. The configuration in the API definition [takes precedence over the Registry](/docs/api-management/client-idp-registry#what-is-the-identity-provider-registry)) so if an issuer and scope match is found in the API definition, this will be used rather than the configuration in the Registry. <Warning> Do not remove configuration from an API definition until you have confirmed that the corresponding Registry entry exists and is correct. Removing configuration that has no Registry counterpart will break JWT validation for that API. </Warning> # Single Sign-On Source: https://tyk.io/docs/tyk-stack/tyk-developer-portal/enterprise-developer-portal/managing-access/enable-sso Learn how to configure Single Sign-On (SSO) for Tyk Developer Portal, allowing API Owners and API Consumers to log in with their existing identity provider credentials. Tyk Identity Broker (TIB) enables Single Sign-On (SSO) for Tyk Developer Portal, allowing users to log in using their existing identity provider (IdP) credentials. The Tyk Developer Portal has two distinct audiences, each requiring a different TIB configuration: * **API Owners** - Portal administrators who manage APIs, plans, and developer access from the Admin Portal. * **API Consumers** - External developers who browse the Live Portal and request API access. <Note> We recommend that you read the [Tyk Identity Broker overview](/docs/tyk-identity-broker/overview) before configuring SSO for Developer Portal. </Note> ## How It Works When a user logs in via SSO, TIB authenticates them against the configured IdP and then calls the Tyk Developer Portal API to obtain a one-time nonce. TIB redirects the user's browser to the Portal API's `/sso` endpoint with the nonce appended. Tyk Developer Portal validates the nonce and creates a session automatically. ```mermaid theme={null} sequenceDiagram actor User participant IDP as Identity Provider (IdP) participant TIB as Tyk Identity Broker participant Portal as Tyk Developer Portal User->>TIB: Log in TIB->>IDP: Verify identity IDP->>TIB: Identity confirmed TIB->>Portal: Request SSO nonce Portal->>TIB: One-time nonce TIB-->>User: Browser redirected to /sso?nonce=... Note over User,Portal: Browser follows redirect automatically Portal->>User: Session created, logged in ``` The outcome of a login depends entirely on which [TIB profile](/docs/tyk-identity-broker/overview#profile) is used. * You will typically configure two separate TIB profiles - one for each audience - and publish their respective login URLs to the appropriate users. * The login URL contains the profile ID: ``` http://{portal-host}/tib/auth/{profile-id}/{provider} ``` * The `ActionType` configured in that profile determines the result: | `ActionType` | Audience | Portal Access | | - | - | - | | `GenerateOrLoginUserProfile` | API Owners | Admin Portal | | `GenerateOrLoginDeveloperProfile` | API Consumers | Live Portal | ## Enabling Single Sign-On To enable Single Sign-On with Portal you must set the following configuration: * set `PORTAL_TIB_ENABLED=true` in [the portal configuration](/docs/product-stack/tyk-enterprise-developer-portal/deploy/configuration#sample-env-file) * set the `TYK_IB_SESSION_SECRET` environment variable with a secret that will be used to sign the [redirect session cookie](/docs/tyk-identity-broker/overview#redirect-session-cookie) if you are using an IdP that implements the redirect flow, such as those using OpenID Connect. <Note> From Portal v1.12.0, TIB is embedded in the portal and no separate TIB installation is required. If you are running an earlier version, or have a specific infrastructure requirement, see [Using Standalone TIB](#using-standalone-tib). </Note> ## API Owner Login Tyk Developer Portal maintains user accounts for all API Owners, identified by email address. When a user is authenticated by the IdP and is directed to a TIB profile configured for action `GenerateOrLoginUserProfile`, the following decision tree is followed: ```mermaid theme={null} flowchart TD A[API Owner authenticates via TIB] --> B{Account found with matching email address?} B -- Yes --> C{Account active?} B -- No --> D{Is AdminRegistrationAllow set to true?} C -- Yes --> E[Logged in] C -- No --> F[Login refused] D -- Yes --> G[New account created with Provider Admin role] G --> E D -- No --> F ``` <Note> By default, Tyk will automatically create a new account for any successful login where there is no existing admin account for the user's email address. Set `AdminRegistrationAllow` to `false` in the [Portal configuration](/docs/product-stack/tyk-enterprise-developer-portal/deploy/configuration) to require that an admin account must already exist before SSO login is permitted. </Note> ### API Owner Profile Configuration The following [TIB profile](/docs/tyk-identity-broker/overview#profile) fields are required for API Owner SSO: | Field | Value | | - | - | | `ID` | Unique identifier for this profile. Forms part of the TIB authentication URL. | | `ActionType` | `GenerateOrLoginUserProfile` | | `OrgID` | Must be `"0"` | | `ReturnURL` | `http://{portal-host}/sso` | | `IdentityHandlerConfig.DashboardCredential` | Must match `PORTAL_API_SECRET` in the Portal configuration | | `ProviderName` | Authentication method. See [IdP-specific guides](#set-up-sso-with-your-identity-provider). | | `ProviderConfig` | IdP-specific connection settings. See [IdP-specific guides](#set-up-sso-with-your-identity-provider). | | `Type` | `redirect` for OIDC/Social; `passthrough` for LDAP/Proxy. | The following optional fields are also available: | Field | Description | | - | - | | `CustomEmailField` | The IdP claim to use as the user's email address. If not set, TIB uses the standard email claim. | | `CustomUserIDField` | The IdP claim to use as the user's unique identifier. If not set, TIB uses the standard subject claim. | ## API Consumer Login When a user authenticates, the IdP returns a set of attributes about them, such as their name, email address, and group membership. TIB receives these attributes as a key-value map. When configured with an API Consumer SSO profile, TIB derives an **SSO key** from the user's IdP identity. The SSO key is a combination of the user's unique IdP user ID and the provider name (for example, `abc123@okta`). It is stored on the Portal developer account and used to recognize the same user on subsequent logins, independently of their email address. ### Login Flow TIB uses the SSO key to determine whether to create or update a Portal developer account: ```mermaid theme={null} flowchart TD A[User authenticates with IdP] --> B[TIB: look up account by SSO key] B --> C{SSO key matches existing account?} C -- Yes --> D{Account has existing Team allocation?} C -- No --> E{Email matches existing account?} D -- Yes --> F[Logged in] D -- No --> G[Assign to Team based on TIB profile and IdP claim] G --> F E -- Yes --> H[Link SSO key to account] H --> F E -- No --> I[Create new account with API Consumer Admin role] I --> G ``` <Note> There is no configuration option to restrict API Consumer SSO login to pre-existing accounts only. A new user who successfully authenticates via SSO will always have a new [API Consumer Admin](/docs/portal/api-consumer#api-consumer-admin) account created for them. </Note> ### Team Assignment When a user logs into an account which is not assigned to any Teams - either because it is newly created, or because all Teams were removed after the first login (as shown in the diagram above) - Team assignment takes place based on the TIB profile and claims in the attributes returned by the IdP. This assignment involves two stages: TIB resolves the user's IdP group claim to a Portal Team ID, then the Portal looks up that Team and assigns the user. **Stage 1: TIB resolves the Team ID** ```mermaid theme={null} flowchart TD A[TIB reads IdP attributes] --> B{Is CustomUserGroupField claim found?} B -- Yes --> C{Is the Value from CustomUserGroupField found in UserGroupMapping?} B -- No --> E{Is DefaultUserGroupID configured?} C -- Yes --> D[Use mapped Portal Team ID] C -- No --> E E -- Yes --> F[Use DefaultUserGroupID] E -- No --> G[No Team ID sent] ``` **Stage 2: Portal assigns the Team and Organisation** ```mermaid theme={null} flowchart TD A[Portal receives Team ID from TIB] --> B{Team ID provided?} B -- Yes --> C{Valid Team ID?} B -- No --> D[Account has no Team or Organisation] C -- Yes --> E[Assign Team, set Organisation from Team] C -- No --> F[Error: login fails] ``` <Warning> If `DefaultUserGroupID` is set to a Team ID that does not exist in the Portal, login will fail. Always ensure `DefaultUserGroupID` refers to a valid, existing Team. </Warning> <Note> Once a user has been assigned to a Team - whether via SSO on first login or manually by an admin - subsequent SSO logins will never change their Team or Organisation. Any manual changes made in the Portal are preserved. </Note> ### User Group Mapping Configuration The following TIB profile fields control how IdP group claims are resolved to Portal Team IDs (Stage 1 above): | Profile Field | Description | | - | - | | `CustomUserGroupField` | The key in the IdP attributes map that contains the user's group membership. | | `UserGroupMapping` | Maps IdP group values to Portal Team IDs. If multiple values match, the first match is used. | | `DefaultUserGroupID` | The Portal Team ID to use when no mapping matches. | <img alt="User group mapping" /> ### API Consumer Profile Configuration The following [TIB profile](/docs/tyk-identity-broker/overview#profile) fields are required for API Consumer SSO: | Field | Value | | - | - | | `ID` | Unique identifier for this profile. Forms part of the TIB authentication URL. | | `ActionType` | `GenerateOrLoginDeveloperProfile` | | `OrgID` | Must be `"0"` | | `ReturnURL` | `http://{portal-host}/sso` | | `IdentityHandlerConfig.DashboardCredential` | Must match `PORTAL_API_SECRET` in the Portal configuration | | `ProviderName` | Authentication method. See [IdP-specific guides](#set-up-sso-with-your-identity-provider). | | `ProviderConfig` | IdP-specific connection settings. See [IdP-specific guides](#set-up-sso-with-your-identity-provider). | | `Type` | `redirect` for OIDC/Social; `passthrough` for LDAP/Proxy. | The following optional fields are also available: | Field | Description | | - | - | | `CustomUserGroupField` | The IdP claim that contains the user's group membership. Required for [User Group Mapping](#user-group-mapping-configuration). | | `UserGroupMapping` | Maps IdP group values to Portal Team IDs. See [User Group Mapping](#user-group-mapping-configuration). | | `DefaultUserGroupID` | The Portal Team ID to use when no group mapping matches. See [User Group Mapping](#user-group-mapping-configuration). | | `CustomEmailField` | The IdP claim to use as the user's email address. If not set, TIB uses the standard email claim. | | `CustomUserIDField` | The IdP claim to use as the user's unique identifier. If not set, TIB uses the standard subject claim. | ## Creating a TIB Profile TIB profiles are managed in the Portal UI under **Settings > SSO Profiles**. 1. Select **Add new SSO Profile**. 2. Complete the **Profile action** step. Choose a **Name** (this becomes the profile `ID`), select the **Profile type** - **Profile for admin users** for API Owner login or **Profile for developers** for API Consumer login - and set the failure redirect URL. <img alt="SSO Profiles Wizard - Profile action step" /> 3. Select the **Provider type** for your IdP. <img alt="SSO Profiles Wizard - Provider type selection" /> 4. Complete the **Profile configuration** step with your IdP connection details. <img alt="SSO Profiles Wizard - Profile configuration" /> 5. For developer profiles, configure the **Group mapping**. Set **Custom user group claim name** to the IdP claim that contains the user's group membership. For admin profiles, skip this step. <img alt="SSO Profiles Wizard - Group mapping" /> 6. Click **Continue** to create the profile. You can view and edit the profile JSON directly from the **Raw editor** view. <img alt="SSO Profiles Raw Editor" /> <Note> The SSO profile wizard supports OIDC, LDAP, and Social provider types. SAML is not available as a selectable option so you would need to create the TIB profile in the **Raw editor** view. </Note> ## Initiating SSO Login The TIB authentication URL for each profile is shown in the profile's **Provider configuration** section in **Settings > SSO Profiles**. <img alt="SSO Profile Details - Login URL" /> How users initiate login depends on the flow type used by their IdP. ### Redirect Flow (OIDC, Social) For redirect-based IdPs, the IdP hosts the login page. Users need to be directed to the TIB authentication URL, which then redirects them to the IdP. From Portal v1.16.0, you can configure `PORTAL_SSO_CUSTOM_LOGIN_URL` to automatically redirect users from the Portal login page to your IdP's login flow. When set, all login requests - including the Portal's **Log in** button - are redirected to the specified URL instead of displaying the built-in login form. Set it to the TIB authentication URL for the profile: <Tabs> <Tab title="Environment variable"> ```ini theme={null} PORTAL_SSO_CUSTOM_LOGIN_URL=http://{portal-host}:{portal-port}/tib/auth/{profile-id}/openid-connect ``` </Tab> <Tab title="Config file"> ```json theme={null} { "SSOCustomLoginURL": "http://{portal-host}:{portal-port}/tib/auth/{profile-id}/openid-connect" } ``` </Tab> </Tabs> For the full reference, see [PORTAL\_SSO\_CUSTOM\_LOGIN\_URL](/docs/product-stack/tyk-enterprise-developer-portal/deploy/configuration#portal_sso_custom_login_url) in the Portal configuration reference. <Note> This setting only redirects the login entry point. User registration and password reset pages are not affected. </Note> For earlier Portal versions, share the TIB authentication URL directly with users. ### Passthrough Flow (LDAP, Proxy) For passthrough-based IdPs, there is no IdP-hosted login page. Users submit their credentials directly to TIB via a form `POST`. You must provide a custom HTML login page, for example: ```html expandable theme={null} <html> <head> <title>Developer Portal Login Login to the Developer Portal
Username:
Password:
``` Replace `{portal-host}`, `{portal-port}`, and `{profile-id}` with the values for your installation. ## Using Standalone TIB By default, Tyk Developer Portal uses its embedded TIB for SSO from v1.12.0 onwards. If you need to use a standalone TIB instance instead - for example, if you are running an earlier Portal version - install and configure TIB separately and point it at the Portal. The TIB configuration for standalone Portal SSO requires the `TykAPISettings.DashboardConfig` block to reference the Portal host and `PortalAPISecret`: ```json theme={null} { "TykAPISettings": { "DashboardConfig": { "Endpoint": "http://{portal-host}", "Port": "{portal-port}", "AdminSecret": "{portal-api-secret}" } } } ``` | Setting | Description | | - | - | | `Endpoint` | URL of the Tyk Developer Portal. | | `Port` | Port on which the Portal is running. | | `AdminSecret` | Must match `PORTAL_API_SECRET` in the Portal configuration. | For full installation and configuration instructions, see [Install Standalone TIB](/docs/tyk-identity-broker/standalone-tib). TIB uses the same `DashboardConfig` block to connect to both Tyk Dashboard and Tyk Developer Portal - a single standalone TIB instance can only point at one. If you need standalone TIB for both Dashboard SSO and Portal SSO in the same deployment, you must run a separate TIB instance for each. ## Set Up SSO with Your Identity Provider Select your identity provider to get started: | Identity Provider | Guide | | - | - | | Microsoft Entra ID (OIDC), ADFS | [SSO with Microsoft Entra ID](/docs/tyk-identity-broker/sso-entra-id) | | Okta (OIDC) | [SSO with Okta](/docs/tyk-identity-broker/sso-okta) | | Auth0 | [SSO with Auth0](/docs/tyk-identity-broker/sso-auth0) | | Keycloak | [SSO with Keycloak](/docs/tyk-identity-broker/sso-keycloak) | | Descope | [SSO with Descope](/docs/tyk-identity-broker/sso-descope) | | Active Directory, OpenLDAP | [SSO with LDAP](/docs/api-management/single-sign-on-ldap) | | Google, GitHub, LinkedIn, and other OAuth providers | [SSO with Social Providers](/docs/api-management/single-sign-on-social-idp) | | Custom or legacy authentication endpoints | [SSO with Proxy Provider](/docs/api-management/custom-auth-with-proxy-identity-provider) | # Organisations and Teams Source: https://tyk.io/docs/tyk-stack/tyk-developer-portal/enterprise-developer-portal/managing-access/manage-api-consumer-organisations How to manage Organisations in Tyk Developer Portal ## Introduction The Tyk Developer Portal uses Organisations and Teams to provide flexible, hierarchical access control for your API ecosystem. This structure allows you to manage API Consumers at both the organizational level and in smaller functional groups, reflecting real-world business relationships and access requirements. Unlike individual developer accounts, Organisations represent entire companies or business entities with sophisticated requirements: * **Team-based access:** Companies typically have multiple developers who need access to your APIs. Tyk Developer Portal's Organisation and Team structure ensures communication and access don't depend on a single individual who might leave the company. * **Secure credential sharing**: Organizations need secure ways to share API credentials within their teams. Without proper tooling, developers resort to sharing credentials through insecure channels, creating security risks. * **Hierarchical permissions**: Within organizations, some users need administrative capabilities while others require more limited access. The Tyk Developer Portal supports this through API Consumer Admin and Team Member roles. * **Self-service team management**: Organizations can maintain their own teams by inviting new members or removing departed ones, reducing administrative overhead for API providers. This organizational approach allows you to manage API Consumers at both the company level and in smaller functional groups, supporting complex business relationships while maintaining security and governance.
**A note on spelling** Throughout this documentation, we use specific spelling conventions to help distinguish between product features and general concepts: * Organisation (with an 's') refers specifically to the entity within the Tyk Developer Portal (sometimes abbreviated to Org) * organization (with a 'z') refers to real-world businesses or the general concept of organizing This British/American English distinction helps clarify when we're discussing the Tyk Developer Portal feature versus general organizational concepts. ### Understanding the Organizational Hierarchy Organisations and Teams create a two-level hierarchy that provides granular control over API access. This allows API Owners to manage access at multiple levels, supporting complex business relationships while maintaining security and governance. Note that users can belong to multiple Teams within an Organisation, allowing for flexible resource allocation based on project needs or job responsibilities. For example, consider a Partner (Acme Bank) that wishes to consume your APIs. They have an *Accounts* team that requires access to a specific set of APIs and a *Development* team that requires access to those plus additional APIs. * You create an Organisation for the client (Acme Bank) * You create separate Teams for their *Accounts* and *Development* users * You construct two [Catalogs](/docs/tyk-stack/tyk-developer-portal/enterprise-developer-portal/managing-access/manage-catalogues) of [API Products](/docs/portal/api-products) and [Plans](/docs/portal/api-plans) * Catalog 1 contains the Accounts APIs and subscription Plans * Catalog 2 contains the Developer APIs and subscription Plans * You configure Catalog visibility as follows: * Catalog 1 is made visible to both Teams * Catalog 2 is made visible only to the Developer Team * You create an [API Consumer Admin](/docs/portal/api-consumer#api-consumer-admin) user for each Team * these users can invite colleagues into their Team as [API Consumer Team Member](/docs/portal/api-consumer#team-member) users Diagram showing an Organisation with two Teams of API Consumers With this configuration, the Admin and Team Members in each team are unaware of the other Team or its members. The members of the Accounts team have access to discover and consume the API Products in Catalog 1, whilst the members of the Development team have access to both Catalogs. ### Default Organisation The system automatically creates a pre-configured "Default Organisation" during the [bootstrap](/docs/portal/install#bootstrapping-developer-portal) process that serves as the initial home for: * Self-registered users without an [invite code](/docs/portal/api-consumer#invite-codes) * API Consumer users created by API Owners without a specific Organisation assignment * API Consumer users whose Organisation has been [deleted](/docs/tyk-stack/tyk-developer-portal/enterprise-developer-portal/managing-access/manage-api-consumer-organisations#deleting-organisations) While the Default Organisation cannot be deleted, you can: * [Rename](/docs/tyk-stack/tyk-developer-portal/enterprise-developer-portal/managing-access/manage-api-consumer-organisations#editing-organisation-details) it to better reflect your business needs * Move users from it to other Organisations as needed * Use it as a holding area for users awaiting proper Organisation assignment #### Developer App visibility [Team and Organisation level app visibility](/docs/portal/developer-app#visibility) is not applied within the Default Organisation. This behavior has been implemented to prevent accidental exposure of Developer Apps if a user is removed from a custom Organisation and automatically reverts to the Default Org.
We do not recommend using the Default Org for publication of API Products and Plans. ## Managing Organisations Organisations represent companies or business units that consume your APIs. * **Purpose**: Group related teams and developers under a single entity * **Hierarchy**: Each API Consumer belongs to exactly one Organisation * **Default Organisation**: A system-provided Organisation where users are placed if not assigned elsewhere * **Creation**: Organisations can only be created by API Owners (or by self-registered developers if [Organisation requests](/docs/tyk-stack/tyk-developer-portal/enterprise-developer-portal/managing-access/manage-api-consumer-organisations#requesting-a-new-organisation) are enabled) * **Management**: * API Owners can create, modify, and delete any Organisation * API Consumer Admins can manage users within their Organisation ### Creating Organisations As an API Owner, you can create new Organisations to represent partner companies or business units: 1. Navigate to **API Consumers > Organisations** in the Admin Portal 2. Select **Add new Organisation** Click on Add to create a new Organisation 3. Provide a **Name** for the new Organisation Giving the new Organisation a name 4. Select **Save changes** to create the Organisation Once created, you can begin adding Teams and users to the Organisation. Note that a [default Team](/docs/tyk-stack/tyk-developer-portal/enterprise-developer-portal/managing-access/manage-api-consumer-organisations#default-team) is automatically created with the Organisation. ### Editing Organisation Details As an API Owner, you can change the name of an Organisations to represent changes in partner companies or business units: 1. Navigate to **API Consumers > Organisations** in the Admin Portal 2. Select the Organisation you want to rename 3. Update the **Name** 4. Select **Save changes** ### Deleting Organisations As an API Owner, you can delete an Organisation to represent changes in partner companies or business units: 1. Navigate to **API Consumers > Organisations** in the Admin Portal 2. Select the three dot menu next to the Organisation you want to delete 3. Select **Delete** 4. Confirm the deletion The Organisation and any Teams created within it will be deleted immediately. All users (both API Consumer Admins and Team Members) will be moved to the [default Team](/docs/tyk-stack/tyk-developer-portal/enterprise-developer-portal/managing-access/manage-api-consumer-organisations#default-team) in the [default Organisation](/docs/tyk-stack/tyk-developer-portal/enterprise-developer-portal/managing-access/manage-api-consumer-organisations#default-organisation) where any Developer Apps they own will have their visibility set to [Personal](/docs/portal/developer-app#visibility) ### Best Practices for Organisation Management * **Naming conventions**: Establish a consistent naming pattern for Organisations * **Regular audits**: Periodically review Organisation membership and activity * **Documentation**: Maintain records of which real-world entities each Organisation represents * **Onboarding process**: Create a standardized workflow for adding new Organisations ## Working With Teams Teams are groups of developers who collaborate on related projects. * **Purpose**: Enable collaboration and shared access to API resources * **Hierarchy**: * Teams exist within a specific Organisation * API Consumers can belong to multiple Teams within their Organisation * **Default Team**: Each Organisation has a default Team where users are placed if not assigned to any other team * **Creation**: Teams can only be created by API Owners * **Management**: * **API Owners** can create, modify, and delete any Team * **API Consumer Admins** can manage team membership within their Organisation ### Creating Teams Teams allow you to organize API Consumers into functional groups with specific API access: 1. As an API Owner, navigate to **API Consumers > Teams** in the Admin Portal 2. Select **Add new Team** 3. Complete the team details: * **Name**: A descriptive name for the team (required) * **Organisation**: Select the Organisation this team belongs to 4. Select **Save changes** Teams can represent departments, project groups, or any logical grouping that helps organize API access within an Organisation. ### Managing Team Membership Once a team is created, an API Owner can add members from the Organisation containing the Team: 1. Navigate to **API Consumers > Users** in the Admin Portal 2. Find and select the user you wish to add or remove 3. If they are not in the Organisation containing the Team, change their **Organisation** 4. Modify their Team membership in the **Teams** section 5. Select **Save changes** An API Consumer Admin can configure the Team membership of other API Consumer users that share any Teams with the Admin as described [here](/docs/portal/api-consumer#managing-api-consumer-users-in-the-live-portal). This self-service capability allows Organisations to manage their own structure while API Owners maintain control over API access. Remember that users can belong to multiple teams, gaining access to all API Catalogs assigned to any of their teams. ### Default Team Each Organisation has a system-generated Default Team that serves several important purposes: * Provides an initial home for new users in the Organisation * Provides a home for API Consumer users who have been [removed](/docs/tyk-stack/tyk-developer-portal/enterprise-developer-portal/managing-access/manage-api-consumer-organisations#deleting-organisations) from all other Teams in the Org * Can be used for Organisation-wide API access The Default Team cannot be deleted, however you can: * Rename it to better reflect your business needs * Move users from it to other Teams as needed * Use it as a holding area for users awaiting proper Team assignment #### Developer App visibility [Team level app visibility](/docs/portal/developer-app#visibility) is not applied within the Default Team. This behavior has been implemented to prevent accidental exposure of Developer Apps if a user is removed from a team and automatically reverts to the Default Team.
We do not recommend using the Default Team for consumption of API Products and Plans except for Organisation-wide API access. ### Best Practices for Team Management * **Logical grouping**: Create teams based on project needs or functional areas * **Minimal access**: Assign only the APIs each team needs to function * **Regular audits**: Periodically review team membership and API access * **Descriptive naming**: Use clear, consistent naming conventions for teams * **Documentation**: Maintain records of each team's purpose and required access ## Requesting a New Organisation The Developer Portal allows potential API Consumers to request the creation of a new Organisation during self-registration. This powerful feature balances self-service convenience with administrative control, addressing several key business needs: * When running an open API program that welcomes new business partners * When scaling your API ecosystem to reach more companies without proportionally increasing administrative work * When you want to capture interest from potential partners outside normal business hours * When you need clear differentiation between individual developers and those representing companies The Organisation request feature adds value with: * Accelerated Onboarding: Reduces the time from initial interest to active API usage by eliminating manual Organisation creation steps * Business Intelligence: Provides visibility into which companies are interested in your APIs, creating potential partnership opportunities * Improved User Experience: Allows users to properly identify themselves as representing a company from the start * Proper Governance: Maintains security through approval workflows while enabling self-service This self-service approach reduces administrative overhead while ensuring proper governance of your API ecosystem. It's particularly valuable for open API programs or when expanding your API consumer base. ### Requesting a new Organisation 1. Visit the Developer Portal and \[register] without an Invite Code 2. Log in to the Developer Portal (this can be done without the account having been approved) 3. Select **Create an Organisation** Request a new Organisation 4. Provide the requested Org with a **Name** Specify name of the Organisation 5. Select **Create Organisation** 6. The user receives confirmation that their request is pending review Organisation registration is pending 7. Note that if the Developer Portal settings are configured for [automatic approval](/docs/tyk-stack/tyk-developer-portal/enterprise-developer-portal/managing-access/manage-api-consumer-organisations#configuring-organisation-request-settings) of Organisation Requests without API Owner [review](/docs/tyk-stack/tyk-developer-portal/enterprise-developer-portal/managing-access/manage-api-consumer-organisations#reviewing-organisation-requests) then the Organisation will be created immediately and the requestor approved and converted to an API Consumer Admin within the new Org. Organisation registration is approved ### Reviewing Organisation Requests 1. If [automatic approval](/docs/tyk-stack/tyk-developer-portal/enterprise-developer-portal/managing-access/manage-api-consumer-organisations#configuring-organisation-request-settings) of Organisation Requests is not set, the API Owner users will be notified of Organisation request via email. New Organisation registration request notification 2. Navigate to **API Consumers > Organisations** in the Admin Portal 3. The requested Organisation appears as *pending* in the list 4. Select the pending Organisation to see which user made the request 5. After reviewing the request, an API Owner can use the options in the three dot menu to: * Approve the request, activating the new Organisation with the requestor automatically becoming an API Consumer Admin * Reject the request, with the requestor remaining a Team Member New Organisation registration request view 6. The requestor will receive an email notifying them of the approval or rejection of the request. **Note**: The API Owner can modify the name of the new Org during the review, if required. The content of the emails sent to API Owners and API Consumers can be [customized](/docs/portal/customization/email-notifications) to meet your business needs. ### Configuring Organisation Request Settings Control whether and how users can request new Organisations by configuring the Developer Portal settings: 1. Navigate to **Settings > General > API Consumer access** in the Admin Portal Organisation registration settings 2. Check or clear the options: * **Enable API consumers to register Organisations** * **Auto-approve API consumers registering organisation** 3. Select **Save changes** Note that enabling auto-approval will mean there is no opportunity to review Org requests, so should only be used in carefully controlled business environments. ## Use Cases and Implementation Strategies The Organisation and Team structure in Tyk Developer Portal can be adapted to support various business models and API programs. Here are strategic approaches for common scenarios: ### Enterprise Partner Ecosystem **Scenario**: Managing APIs for a network of business partners with different access needs **Implementation**: * Create an Organisation for each partner company * Structure teams based on partner's functional departments (e.g., Development, QA, Analytics) * Assign graduated API access tiers based on partnership level * Designate partner technical leads as API Consumer Admins **Benefits**: * Clear separation between different partner companies * Partners can self-manage their internal team structure * Access revocation is simplified when partnerships change * Usage analytics can be tracked at the partner company level ### Internal Developer Program **Scenario**: Providing API access across departments within your own company **Implementation**: * Create Organisations representing major business units or subsidiaries * Form teams based on projects, product lines, or functional groups * Use the Default Organisation for central IT or platform teams * Implement consistent naming conventions that align with internal structure **Benefits**: * Mirrors existing company hierarchy for easier governance * Supports chargeback models for internal API consumption * Enables department-specific policies and quotas * Provides visibility into cross-departmental API usage ### Public API Marketplace **Scenario**: Offering APIs to external developers with tiered access models **Implementation**: * Enable Organisation self-registration requests * Create template teams for common access patterns (Basic, Professional, Enterprise) * Implement automated workflows for upgrading access tiers * Use Default Teams for individual developers without complex needs **Benefits**: * Scales efficiently as your developer community grows * Supports freemium to premium conversion paths * Allows companies to start small and expand access as needed * Provides clear separation between individual developers and companies ### Implementation Checklist Regardless of your use case, consider these factors when designing your Organisation and Team structure: * **Scalability**: Will the structure accommodate growth in users and APIs? * **Governance**: Does it support your compliance and security requirements? * **Administration**: Is the overhead manageable for your API team? * **User Experience**: Does it make sense from the API Consumer perspective? * **Analytics**: Will you get the usage insights needed for your business? * **Flexibility**: Can it adapt as your API program evolves? By thoughtfully designing your Organisation and Team structure to match your specific business needs, you can create an API program that balances security, usability, and administrative efficiency. # API Catalogs Source: https://tyk.io/docs/tyk-stack/tyk-developer-portal/enterprise-developer-portal/managing-access/manage-catalogues Working with API Catalogs ## Introduction API Catalogs are curated collections of API Products and Plans that enable you to organize and present your API offerings to different developer audiences. Catalogs serve as the primary navigation and discovery mechanism in the Tyk Developer Portal, allowing you to create tailored API marketplaces for different consumer segments. Unlike traditional API documentation sites that present all APIs to everyone, Catalogs give you fine-grained control over who sees what. This enables you to create personalized experiences for different developer audiences - from public APIs available to anyone, to specialized offerings for specific partners or internal teams. Catalogs transform your API portfolio management by: * Segmenting API Products for different developer audiences * Creating customized discovery experiences for different use cases * Controlling visibility of API offerings based on business relationships * Enabling consistent organization of related API Products In the Tyk Developer Portal, Catalogs act as the bridge between your API Products and your developer community, ensuring that each developer sees exactly the APIs they need. ## Key Concepts ### Catalog Types The Tyk Developer Portal supports two visibility modes for Catalogs: * Public Catalogs: Visible to anyone visiting your Developer Portal, even without logging in. Ideal for openly available APIs and developer recruitment. * Private Catalogs: Visible only to authenticated users who have logged into your Developer Portal. They can be further restricted only to members of specific [teams](/docs/portal/api-consumer). Perfect for partner-specific APIs, internal teams, or premium offerings. ### Catalog Structure Each Catalog contains: * [API Products](/docs/portal/api-products): The functional API offerings available in this Catalog * [Plans](/docs/portal/api-plans): The subscription options available for Products in this Catalog * Visibility Settings: Controls which developers can see this Catalog * Presentation Elements: Name, description, and other display properties ### Catalog Relationships Understanding how Catalogs relate to other elements in the Developer Portal: * Products and Plans: A Product or Plan can appear in multiple Catalogs * Teams and Organisations: Can be granted access to specific Custom Catalogs * Developer Experience: Developers only see Catalogs they have access to ## API Catalog Reference Guide This comprehensive reference guide details all the configurable options and features of API Catalogs in the Tyk Developer Portal. ### Core Features #### Catalog Name The primary identifier for your Catalog within the Admin Portal, this is not exposed in the Live Portal * **Location**: *Catalogues > Add/Edit Catalogues > Name* * **Purpose**: Identifies the Catalog within the Developer Portal * **Best Practice**: Choose a clear, descriptive name that reflects the Catalog's purpose or audience #### Path URL This configuration is not currently in use and can be ignored. #### Sync URL with Name * **Location**: *Catalogues > Add/Edit Catalogues > Sync URL with Name* * **Note**: This configuration must be checked (selected). ### Catalog Visibility #### Visibility Options Controls which API Consumers can see and access this Catalog. * **Location**: *Catalogues > Add/Edit Catalogues > Visibility options* * **Options**: * Public: Visible to all visitors, even without logging in * Private: Visible only to authenticated users in the teams select in the [Audience](/docs/tyk-stack/tyk-developer-portal/enterprise-developer-portal/managing-access/manage-catalogues#audience) * **Default**: Private * **Best Practice**: Use the most restrictive visibility that meets your business needs #### Audience Specifies which teams can access a Private Catalog. * **Location**: *Catalogues > Add/Edit Catalogues > Team* * **Selection**: Select **Add Team** then choose from any Teams created on the Developer Portal; you can add multiple teams by repeating this action * **Behavior**: Only members of the selected teams will see this Catalog * **Note**: Teams must be created before they can be added to the audience; any combination of Teams can be added to a Catalog's audience across any number of Organisations ### Catalog Content #### Products Determines which API Products appear in this Catalog. * **Location**: *Catalogues > Add/Edit Catalogues > Products* * **Selection**: Select one or more Products from the dropdown * **Removal**: Click on the `x` next to the name of the Product you want to delete from the Catalog * **Relationship**: A Product can be assigned to multiple Catalogs * **Best Practice**: Ensure that Products and their relevant Plans are assigned to the same Catalogs #### Plans Determines which API Plans appear in this Catalog. * **Location**: *Catalogues > Add/Edit Catalogues > Plans* * **Selection**: Select one or more Plans from the dropdown * **Removal**: Click on the `x` next to the name of the Plan you want to delete from the Catalog * **Relationship**: A Plan can be assigned to multiple Catalogs * **Best Practice**: Ensure that Products and their relevant Plans are assigned to the same Catalogs ## Best Practices for API Catalogs * Create purpose-driven Catalogs: Design each Catalog with a specific audience and purpose in mind * Use clear naming conventions: Make Catalog names intuitive and descriptive * Maintain consistent organization: Apply similar structures across Catalogs for a predictable developer experience * Limit the number of Catalogs: Too many Catalogs can create confusion; aim for a manageable number * Review access regularly: Periodically audit Custom Catalog access to ensure it remains appropriate # Add a new specification to this Documentation Product Source: https://tyk.io/docs/api-reference/api-documentation-for-api-products/add-a-new-specification-to-this-documentation-product /swagger/5.15/enterprise-developer-portal-swagger.yaml post /products/{product_id}/spec-details Add a new specification to this Documentation Product # Delete a specification Source: https://tyk.io/docs/api-reference/api-documentation-for-api-products/delete-a-specification /swagger/5.15/enterprise-developer-portal-swagger.yaml delete /products/{product_id}/spec-details/{spec-id} Delete a specification from this Documentation Product # Delete GraphQL schema file of an API Source: https://tyk.io/docs/api-reference/api-documentation-for-api-products/delete-graphql-schema-file-of-an-api /swagger/5.15/enterprise-developer-portal-swagger.yaml delete /products/{product_id}/api-details/{api_id}/graphql/schema Remove GraphQL schema file from an API # Delete OAS file of a Specification Source: https://tyk.io/docs/api-reference/api-documentation-for-api-products/delete-oas-file-of-a-specification /swagger/5.15/enterprise-developer-portal-swagger.yaml delete /products/{product_id}/spec-details/{spec-id}/oas Remove OAS file from a Specification # Delete OAS file of an API Source: https://tyk.io/docs/api-reference/api-documentation-for-api-products/delete-oas-file-of-an-api /swagger/5.15/enterprise-developer-portal-swagger.yaml delete /products/{product_id}/api-details/{api_id}/oas Remove OAS file from an API # Delete Specification with GraphQL schema Source: https://tyk.io/docs/api-reference/api-documentation-for-api-products/delete-specification-with-graphql-schema /swagger/5.15/enterprise-developer-portal-swagger.yaml delete /products/{product_id}/spec-details/{spec-id}/graphql/schema Delete a Specification that contains a GraphQL schema. This removes the entire SpecDetails object. # Download GraphQL schema file of a Specification Source: https://tyk.io/docs/api-reference/api-documentation-for-api-products/download-graphql-schema-file-of-a-specification /swagger/5.15/enterprise-developer-portal-swagger.yaml get /products/{product_id}/spec-details/{spec-id}/graphql/schema Download a GraphQL schema file for a specific Specification in a Documentation Product # Download GraphQL schema file of an API Source: https://tyk.io/docs/api-reference/api-documentation-for-api-products/download-graphql-schema-file-of-an-api /swagger/5.15/enterprise-developer-portal-swagger.yaml get /products/{product_id}/api-details/{api_id}/graphql/schema Download a GraphQL schema file for a specific API in a Product # Download OAS file of a Specification Source: https://tyk.io/docs/api-reference/api-documentation-for-api-products/download-oas-file-of-a-specification /swagger/5.15/enterprise-developer-portal-swagger.yaml get /products/{product_id}/spec-details/{spec-id}/oas Download an OAS spec as a file for a specific Specification in a Documentation Product # Download OAS file of an API Source: https://tyk.io/docs/api-reference/api-documentation-for-api-products/download-oas-file-of-an-api /swagger/5.15/enterprise-developer-portal-swagger.yaml get /products/{product_id}/api-details/{api_id}/oas Download an OAS spec as a file for a specific API in a Product # Get description of a Specification Source: https://tyk.io/docs/api-reference/api-documentation-for-api-products/get-description-of-a-specification /swagger/5.15/enterprise-developer-portal-swagger.yaml get /products/{product_id}/spec-details/{spec-id} Get description of a Specification # Get description of an API Source: https://tyk.io/docs/api-reference/api-documentation-for-api-products/get-description-of-an-api /swagger/5.15/enterprise-developer-portal-swagger.yaml get /products/{product_id}/api-details/{api-id} Get description of an API # List all APIs included in this API Product Source: https://tyk.io/docs/api-reference/api-documentation-for-api-products/list-all-apis-included-in-this-api-product /swagger/5.15/enterprise-developer-portal-swagger.yaml get /products/{product_id}/api-details List all APIs included in this API Product # List all Specification details included in this Documentation Product Source: https://tyk.io/docs/api-reference/api-documentation-for-api-products/list-all-specification-details-included-in-this-documentation-product /swagger/5.15/enterprise-developer-portal-swagger.yaml get /products/{product_id}/spec-details List all Specification details included in this Documentation Product # Update description of a Specification Source: https://tyk.io/docs/api-reference/api-documentation-for-api-products/update-description-of-a-specification /swagger/5.15/enterprise-developer-portal-swagger.yaml put /products/{product_id}/spec-details/{spec-id} Update description of a Specification including name, OAS URL and alias # Update description of an API Source: https://tyk.io/docs/api-reference/api-documentation-for-api-products/update-description-of-an-api /swagger/5.15/enterprise-developer-portal-swagger.yaml put /products/{product_id}/api-details/{api-id} Update description of an API including name, OAS URL and description # Update OAS file of an API Source: https://tyk.io/docs/api-reference/api-documentation-for-api-products/update-oas-file-of-an-api /swagger/5.15/enterprise-developer-portal-swagger.yaml post /products/{product_id}/api-details/{api_id}/oas Update an OAS file for an API inside an API Product # Upload GraphQL schema file of a Specification Source: https://tyk.io/docs/api-reference/api-documentation-for-api-products/upload-graphql-schema-file-of-a-specification /swagger/5.15/enterprise-developer-portal-swagger.yaml put /products/{product_id}/spec-details/{spec-id}/graphql/schema Upload a GraphQL schema file for a Specification inside a Documentation Product # Upload GraphQL schema file of an API Source: https://tyk.io/docs/api-reference/api-documentation-for-api-products/upload-graphql-schema-file-of-an-api /swagger/5.15/enterprise-developer-portal-swagger.yaml post /products/{product_id}/api-details/{api_id}/graphql/schema Upload a GraphQL schema file for an API inside an API Product # Upload GraphQL SDL for Documentation Product Source: https://tyk.io/docs/api-reference/api-documentation-for-api-products/upload-graphql-sdl-for-documentation-product /swagger/5.15/enterprise-developer-portal-swagger.yaml post /products/{product_id}/spec-details/graphql/schema Upload and link a GraphQL SDL file to a documentation-only product. The uploaded file must be a valid GraphQL schema (with extension `.graphql`, `.gql`, or `.json`) and is stored as the latest schema for the product. Only works for documentation-only products. # Upload OAS file of a Specification Source: https://tyk.io/docs/api-reference/api-documentation-for-api-products/upload-oas-file-of-a-specification /swagger/5.15/enterprise-developer-portal-swagger.yaml post /products/{product_id}/spec-details/{spec-id}/oas Upload an OAS file for a Specification inside a Documentation Product # Create a new custom attribute Source: https://tyk.io/docs/api-reference/custom-attributes/create-a-new-custom-attribute /swagger/5.15/enterprise-developer-portal-swagger.yaml post /extended_attributes/{extended_attribute_id}/custom-attributes Create a new custom attribute for the extended model # Delete a custom attribute Source: https://tyk.io/docs/api-reference/custom-attributes/delete-a-custom-attribute /swagger/5.15/enterprise-developer-portal-swagger.yaml delete /extended_attributes/{extended_attribute_id}/custom-attributes/{custom_attribute_id} Delete a custom attribute from this extended model # Get a custom attribute Source: https://tyk.io/docs/api-reference/custom-attributes/get-a-custom-attribute /swagger/5.15/enterprise-developer-portal-swagger.yaml get /extended_attributes/{extended_attribute_id}/custom-attributes/{custom_attribute_id} Get a custom attribute for a particular extended model # Get a default attribute Source: https://tyk.io/docs/api-reference/custom-attributes/get-a-default-attribute /swagger/5.15/enterprise-developer-portal-swagger.yaml get /extended_attributes/{extended_attribute_id}/default-attributes/{default_attribute_id} Get a default attribute for a particular extended model # Get an extended model detail Source: https://tyk.io/docs/api-reference/custom-attributes/get-an-extended-model-detail /swagger/5.15/enterprise-developer-portal-swagger.yaml get /extended_attributes/{extended_attribute_id} Get an extended attribute detail # List all custom attributes for a particular extended model Source: https://tyk.io/docs/api-reference/custom-attributes/list-all-custom-attributes-for-a-particular-extended-model /swagger/5.15/enterprise-developer-portal-swagger.yaml get /extended_attributes/{extended_attribute_id}/custom-attributes Get a list of custom attributes for an extended model # List all default attributes for a particular extended model Source: https://tyk.io/docs/api-reference/custom-attributes/list-all-default-attributes-for-a-particular-extended-model /swagger/5.15/enterprise-developer-portal-swagger.yaml get /extended_attributes/{extended_attribute_id}/default-attributes Get attributes added to this extended model by default # List all extended models Source: https://tyk.io/docs/api-reference/custom-attributes/list-all-extended-models /swagger/5.15/enterprise-developer-portal-swagger.yaml get /extended_attributes List all extended models for custom attributes # Update a custom attribute Source: https://tyk.io/docs/api-reference/custom-attributes/update-a-custom-attribute /swagger/5.15/enterprise-developer-portal-swagger.yaml put /extended_attributes/{extended_attribute_id}/custom-attributes/{custom_attribute_id} Update a custom attribute for a particular extended model # Update default attribute Source: https://tyk.io/docs/api-reference/custom-attributes/update-default-attribute /swagger/5.15/enterprise-developer-portal-swagger.yaml put /extended_attributes/{extended_attribute_id}/default-attributes/{default_attribute_id} Update a default attribute for a particular extended model to include it in the credential metadata # Get an Identity Provider's data Source: https://tyk.io/docs/api-reference/oauth20-providers/get-an-identity-providers-data /swagger/5.15/enterprise-developer-portal-swagger.yaml get /oauth-providers/{provider_id} Get an OAuth2.0 provider's data # List all OAuth2.0 Identity providers that are registered in the portal Source: https://tyk.io/docs/api-reference/oauth20-providers/list-all-oauth20-identity-providers-that-are-registered-in-the-portal /swagger/5.15/enterprise-developer-portal-swagger.yaml get /oauth-providers List all OAuth2.0 providers # Register a new OAuth2.0 Identity Provider in the portal Source: https://tyk.io/docs/api-reference/oauth20-providers/register-a-new-oauth20-identity-provider-in-the-portal /swagger/5.15/enterprise-developer-portal-swagger.yaml post /oauth-providers Create a new OAuth2.0 provider # Update an OAuth2.0 Identity Provider Source: https://tyk.io/docs/api-reference/oauth20-providers/update-an-oauth20-identity-provider /swagger/5.15/enterprise-developer-portal-swagger.yaml put /oauth-providers/{provider_id} Update the OAuth2.0 provider configuration such its name, type, well-known endpoint URL, and the initial access token. Any existing credentials with this provider won't be updated, new and pending access requests with this provider will assume the new settings. # Create a new content block for a page Source: https://tyk.io/docs/api-reference/pages-and-content/create-a-new-content-block-for-a-page /swagger/5.15/enterprise-developer-portal-swagger.yaml post /pages/{page_id}/content-blocks Create a new content block for a page # Create a new content page Source: https://tyk.io/docs/api-reference/pages-and-content/create-a-new-content-page /swagger/5.15/enterprise-developer-portal-swagger.yaml post /pages Create a new content page # Delete a page Source: https://tyk.io/docs/api-reference/pages-and-content/delete-a-page /swagger/5.15/enterprise-developer-portal-swagger.yaml delete /pages/{page_id} Delete a page # Delete content blocks from this page Source: https://tyk.io/docs/api-reference/pages-and-content/delete-content-blocks-from-this-page /swagger/5.15/enterprise-developer-portal-swagger.yaml delete /pages/{page_id}/content-blocks/{content-block_id} Delete content blocks from this page # Get a content block Source: https://tyk.io/docs/api-reference/pages-and-content/get-a-content-block /swagger/5.15/enterprise-developer-portal-swagger.yaml get /pages/{page_id}/content-blocks/{content-block_id} Get a content block # Get a page Source: https://tyk.io/docs/api-reference/pages-and-content/get-a-page /swagger/5.15/enterprise-developer-portal-swagger.yaml get /pages/{page_id} Get a page # List all content blocks which are displayed on this page Source: https://tyk.io/docs/api-reference/pages-and-content/list-all-content-blocks-which-are-displayed-on-this-page /swagger/5.15/enterprise-developer-portal-swagger.yaml get /pages/{page_id}/content-blocks List all content blocks which are displayed on this page # Update a content block Source: https://tyk.io/docs/api-reference/pages-and-content/update-a-content-block /swagger/5.15/enterprise-developer-portal-swagger.yaml put /pages/{page_id}/content-blocks/{content-block_id} Update a content block including the content and name # Update a page Source: https://tyk.io/docs/api-reference/pages-and-content/update-a-page /swagger/5.15/enterprise-developer-portal-swagger.yaml put /pages/{page_id} Update a page including title, path, and status # Create a new plan Source: https://tyk.io/docs/api-reference/plans/create-a-new-plan /swagger/5.15/enterprise-developer-portal-swagger.yaml post /plans Create a new plan # Delete a plan Source: https://tyk.io/docs/api-reference/plans/delete-a-plan /swagger/5.15/enterprise-developer-portal-swagger.yaml delete /plans/{plan_id} Delete a plan # Get a plan Source: https://tyk.io/docs/api-reference/plans/get-a-plan /swagger/5.15/enterprise-developer-portal-swagger.yaml get /plans/{plan_id} Get a plan's details # List all plans Source: https://tyk.io/docs/api-reference/plans/list-all-plans /swagger/5.15/enterprise-developer-portal-swagger.yaml get /plans List all plans that exist in the portal # Update a plan Source: https://tyk.io/docs/api-reference/plans/update-a-plan /swagger/5.15/enterprise-developer-portal-swagger.yaml put /plans/{plan_id} Update a plan # Attach a client type to this API Product Source: https://tyk.io/docs/api-reference/products/attach-a-client-type-to-this-api-product /swagger/5.15/enterprise-developer-portal-swagger.yaml post /products/{product_id}/client_types Attach a client type to this API Product # Attach a tag to this API Product Source: https://tyk.io/docs/api-reference/products/attach-a-tag-to-this-api-product /swagger/5.15/enterprise-developer-portal-swagger.yaml post /products/{product_id}/tags Attach a tag to this API Product # Create a new product Source: https://tyk.io/docs/api-reference/products/create-a-new-product /swagger/5.15/enterprise-developer-portal-swagger.yaml post /products Create a new product (regular API product or documentation-only product) # Delete a product Source: https://tyk.io/docs/api-reference/products/delete-a-product /swagger/5.15/enterprise-developer-portal-swagger.yaml delete /products/{product_id} Delete a product # Delete a tag from this API Product Source: https://tyk.io/docs/api-reference/products/delete-a-tag-from-this-api-product /swagger/5.15/enterprise-developer-portal-swagger.yaml delete /products/{product_id}/tags/{tag_name} Delete a tag from this API Product # Delete the logo/product page image for this API Product Source: https://tyk.io/docs/api-reference/products/delete-the-logoproduct-page-image-for-this-api-product /swagger/5.15/enterprise-developer-portal-swagger.yaml delete /products/{product_id}/logo Delete the logo/product page image for this API Product # Delete the preview/catalogue page image for this API Product Source: https://tyk.io/docs/api-reference/products/delete-the-previewcatalogue-page-image-for-this-api-product /swagger/5.15/enterprise-developer-portal-swagger.yaml delete /products/{product_id}/preview Delete the preview/catalogue page image for this API Product # Detach a client type from this API Product Source: https://tyk.io/docs/api-reference/products/detach-a-client-type-from-this-api-product /swagger/5.15/enterprise-developer-portal-swagger.yaml delete /products/{product_id}/client_types/{client_type_id} Delete a client type from this API Product # Get a client type attached to this API Product Source: https://tyk.io/docs/api-reference/products/get-a-client-type-attached-to-this-api-product /swagger/5.15/enterprise-developer-portal-swagger.yaml get /products/{product_id}/client_types/{client_type_id} Get a client type attached to this API Product # Get a product Source: https://tyk.io/docs/api-reference/products/get-a-product /swagger/5.15/enterprise-developer-portal-swagger.yaml get /products/{product_id} Get a product # Get a tag from this API Product Source: https://tyk.io/docs/api-reference/products/get-a-tag-from-this-api-product /swagger/5.15/enterprise-developer-portal-swagger.yaml get /products/{product_id}/tags/{tag_name} Get a tag for this API Product # Get the logo/product page image for this API Product Source: https://tyk.io/docs/api-reference/products/get-the-logoproduct-page-image-for-this-api-product /swagger/5.15/enterprise-developer-portal-swagger.yaml get /products/{product_id}/logo Get the logo/product page image for this API Product # Get the preview/catalogue page image for this API Product Source: https://tyk.io/docs/api-reference/products/get-the-previewcatalogue-page-image-for-this-api-product /swagger/5.15/enterprise-developer-portal-swagger.yaml get /products/{product_id}/preview Get the preview/catalogue page image for this API Product # List all client types for this API Product Source: https://tyk.io/docs/api-reference/products/list-all-client-types-for-this-api-product /swagger/5.15/enterprise-developer-portal-swagger.yaml get /products/{product_id}/client_types List all client types attached to this API Product # List all products Source: https://tyk.io/docs/api-reference/products/list-all-products /swagger/5.15/enterprise-developer-portal-swagger.yaml get /products List all products available in the portal # List all tags for this API Product Source: https://tyk.io/docs/api-reference/products/list-all-tags-for-this-api-product /swagger/5.15/enterprise-developer-portal-swagger.yaml get /products/{product_id}/tags List all tags attached to this API Product # Update a product Source: https://tyk.io/docs/api-reference/products/update-a-product /swagger/5.15/enterprise-developer-portal-swagger.yaml put /products/{product_id} Update a product (regular API product or documentation-only product) # Upload a logo/product page image for this API Product Source: https://tyk.io/docs/api-reference/products/upload-a-logoproduct-page-image-for-this-api-product /swagger/5.15/enterprise-developer-portal-swagger.yaml post /products/{product_id}/logo Upload a logo/product page image for this API Product # Upload a preview/catalogue page image for this API Product Source: https://tyk.io/docs/api-reference/products/upload-a-previewcatalogue-page-image-for-this-api-product /swagger/5.15/enterprise-developer-portal-swagger.yaml post /products/{product_id}/preview Upload a preview/catalogue page image for this API Product # Create a new API Provider Source: https://tyk.io/docs/api-reference/providers/create-a-new-api-provider /swagger/5.15/enterprise-developer-portal-swagger.yaml post /providers Create a new API Provider. The new API Provider will have the 'Unknown' synchronization status until the first synchronization attempt # Delete an API Provider Source: https://tyk.io/docs/api-reference/providers/delete-an-api-provider /swagger/5.15/enterprise-developer-portal-swagger.yaml delete /providers/{provider_id} This endpoint deletes an API Provider provider and removes all assets related to it such as API Products and Plans # Get an API Provider configuration Source: https://tyk.io/docs/api-reference/providers/get-an-api-provider-configuration /swagger/5.15/enterprise-developer-portal-swagger.yaml get /providers/{provider_id} Get an API Provider configuration # List all API Providers Source: https://tyk.io/docs/api-reference/providers/list-all-api-providers /swagger/5.15/enterprise-developer-portal-swagger.yaml get /providers List all API Providers connected to this portal instance # Synchronize API Products and plans with an API Provider Source: https://tyk.io/docs/api-reference/providers/synchronize-api-products-and-plans-with-an-api-provider /swagger/5.15/enterprise-developer-portal-swagger.yaml put /providers/{provider_id}/synchronize Synchronize API Products and plans with an API Provider # Update Provider Source: https://tyk.io/docs/api-reference/providers/update-provider /swagger/5.15/enterprise-developer-portal-swagger.yaml put /providers/{provider_id} Update Provider # Create a new tag Source: https://tyk.io/docs/api-reference/tags/create-a-new-tag /swagger/5.15/enterprise-developer-portal-swagger.yaml post /tags Create a new tag # Delete a tag Source: https://tyk.io/docs/api-reference/tags/delete-a-tag /swagger/5.15/enterprise-developer-portal-swagger.yaml delete /tags/{tag_id} Delete a tag # Get a tag Source: https://tyk.io/docs/api-reference/tags/get-a-tag /swagger/5.15/enterprise-developer-portal-swagger.yaml get /tags/{tag_id} Get a tag # List all tags Source: https://tyk.io/docs/api-reference/tags/list-all-tags /swagger/5.15/enterprise-developer-portal-swagger.yaml get /tags List all tags # Update a tag Source: https://tyk.io/docs/api-reference/tags/update-a-tag /swagger/5.15/enterprise-developer-portal-swagger.yaml put /tags/{tag_id} Update a tag # Activate a theme Source: https://tyk.io/docs/api-reference/themes/activate-a-theme /swagger/5.15/enterprise-developer-portal-swagger.yaml put /themes/{theme_id}/activate Activate a theme. When a new theme is activated, it becomes the current theme for the live portal and is displayed to all developers visiting the portal # Download a theme Source: https://tyk.io/docs/api-reference/themes/download-a-theme /swagger/5.15/enterprise-developer-portal-swagger.yaml get /themes/{theme_id}/download Download a theme as a zip archive # Get a theme Source: https://tyk.io/docs/api-reference/themes/get-a-theme /swagger/5.15/enterprise-developer-portal-swagger.yaml get /themes/{theme_id} Get metadata for a theme such as name, author, version and status # List all themes Source: https://tyk.io/docs/api-reference/themes/list-all-themes /swagger/5.15/enterprise-developer-portal-swagger.yaml get /themes List all themes # Soft delete a theme Source: https://tyk.io/docs/api-reference/themes/soft-delete-a-theme /swagger/5.15/enterprise-developer-portal-swagger.yaml delete /themes/{theme_id} Soft delete a theme by its ID # Upload a theme Source: https://tyk.io/docs/api-reference/themes/upload-a-theme /swagger/5.15/enterprise-developer-portal-swagger.yaml post /themes/upload This endpoint uploads a theme that is archived as a zip file to the portal. If a theme with this name already exists in the portal, the uploaded theme will replace the existing one. Otherwise, a new theme will be created. The name of a theme is stored in the `name` field of `theme.json`. # Change order of tutorial pages Source: https://tyk.io/docs/api-reference/tutorials-for-api-products/change-order-of-tutorial-pages /swagger/5.15/enterprise-developer-portal-swagger.yaml post /products/{product_id}/docs/reorder Change order of tutorial pages in an API Product # Create a new tutorial page for this API Product Source: https://tyk.io/docs/api-reference/tutorials-for-api-products/create-a-new-tutorial-page-for-this-api-product /swagger/5.15/enterprise-developer-portal-swagger.yaml post /products/{product_id}/docs Create a new tutorial page for this API Product # Delete a tutorial page from this API Product Source: https://tyk.io/docs/api-reference/tutorials-for-api-products/delete-a-tutorial-page-from-this-api-product /swagger/5.15/enterprise-developer-portal-swagger.yaml delete /products/{product_id}/docs/{doc_id} Delete a tutorial page from this API Product # Get a tutorial page Source: https://tyk.io/docs/api-reference/tutorials-for-api-products/get-a-tutorial-page /swagger/5.15/enterprise-developer-portal-swagger.yaml get /products/{product_id}/docs/{doc_id} Get a tutorial page # List all tutorials for this API Product Source: https://tyk.io/docs/api-reference/tutorials-for-api-products/list-all-tutorials-for-this-api-product /swagger/5.15/enterprise-developer-portal-swagger.yaml get /products/{product_id}/docs List all tutorials for this API Product # Update a tutorial page Source: https://tyk.io/docs/api-reference/tutorials-for-api-products/update-a-tutorial-page /swagger/5.15/enterprise-developer-portal-swagger.yaml put /products/{product_id}/docs/{doc_id} Update a tutorial page including its metadata and content # Create a new user Source: https://tyk.io/docs/api-reference/users/create-a-new-user /swagger/5.15/enterprise-developer-portal-swagger.yaml post /users Create a new admin user or developer # Delete a custom attribute Source: https://tyk.io/docs/api-reference/users/delete-a-custom-attribute /swagger/5.15/enterprise-developer-portal-swagger.yaml delete /users/{user_id}/custom-attributes/{custom-attribute_id} Delete a user custom attribute # Delete a user Source: https://tyk.io/docs/api-reference/users/delete-a-user-portal-delete-user /swagger/5.15/enterprise-developer-portal-swagger.yaml delete /users/{user_id} Delete a user and all their applications. All credentials that are issued for those applications will be revoked and deleted as well # Get a user Source: https://tyk.io/docs/api-reference/users/get-a-user /swagger/5.15/enterprise-developer-portal-swagger.yaml get /users/{user_id} Get a user # Get a user custom attribute Source: https://tyk.io/docs/api-reference/users/get-a-user-custom-attribute /swagger/5.15/enterprise-developer-portal-swagger.yaml get /users/{user_id}/custom-attributes/{custom-attribute_id} Get a user custom attribute # Get extended custom attributes for user Source: https://tyk.io/docs/api-reference/users/get-extended-custom-attributes-for-user /swagger/5.15/enterprise-developer-portal-swagger.yaml get /users/{user_id}/custom-attributes Get extended custom attributes for user # List all users Source: https://tyk.io/docs/api-reference/users/list-all-users /swagger/5.15/enterprise-developer-portal-swagger.yaml get /users List all admin users and developers # Update a user Source: https://tyk.io/docs/api-reference/users/update-a-user /swagger/5.15/enterprise-developer-portal-swagger.yaml put /users/{user_id} Update a user data such as email, name, identity provider and organisation # Update a user custom attribute Source: https://tyk.io/docs/api-reference/users/update-a-user-custom-attribute /swagger/5.15/enterprise-developer-portal-swagger.yaml put /users/{user_id}/custom-attributes/{custom-attribute_id} Update a user custom attribute value if write once set false # REST API to MCP x-tyk-mcp-server extension Source: https://tyk.io/docs/ai-management/mcp-gateway/api-to-mcp-definitions Field reference for the x-tyk-mcp-server extension: source selection, tool and parameter overrides, behavioral hints, the allow-list rule, and examples. ## Availability | Component | Version | Editions | | :- | :- | :- | | Gateway | Available since [v5.15.0](/docs/developer-support/release-notes/gateway) | Enterprise | ## Overview An MCP proxy [generated directly from a Tyk-managed REST API](/docs/ai-management/mcps/api-to-mcp) has one further structure beyond the definition covered in [MCP proxy definitions](/docs/ai-management/mcp-gateway/mcp-proxy-definitions): `x-tyk-mcp-server`, a vendor extension alongside `x-tyk-api-gateway` rather than nested inside it. It holds the tool catalog Tyk derives from the source API's OpenAPI operations: which operations are exposed as tools, and any name, description, or parameter overrides applied to them. `x-tyk-mcp-server` can only be present when `upstream.url` is a REST API adapter target. Tyk rejects the extension outright on a proxy that fronts a remote MCP server. ## The Upstream Adapter Target For an MCP proxy generated directly from a Tyk-managed REST API, `upstream.url` holds an adapter target instead of a remote server's url, for example `tyk://a1b2c3d4e5f647a8b9c0d1e2f3a4b5c6/mcp`. `tyk://` is Tyk's internal-routing scheme for addressing another Tyk-managed API without a real network hop, always shaped `tyk:///`. For most uses of this scheme, `` is a real path on the target API. Here it is not: your REST API does not need an actual `/mcp` endpoint. `/mcp` is a fixed marker value that identifies this as a REST API to MCP adapter target rather than an ordinary internal call. Only the host portion identifies something real: your paired REST API's own ID. If your REST API's OpenAPI specification already defines a real path at `/mcp`, Tyk uses a different marker instead, appending `__mcp-server` to the API ID with no path. This is not something you configure. Tyk fills in this value for you when you create the proxy through the Dashboard wizard or the API, so you don't need to know the source API's ID yourself. If you're hand-authoring the definition, for example via Tyk Operator, you can find that ID: * **Dashboard**: on the source API's own detail page, where the API ID is shown and copyable. * **API**: in the `api_id` field of the response when you `GET` the source API's own definition. * **Tyk Operator**: in `.status.id` once the Operator has reconciled the source API's `TykOasApiDefinition`, for example, `kubectl get tykoasapidefinition -o jsonpath='{.status.id}'`. In Tyk, each version of a versioned API is its own separate API definition with its own distinct API ID: a base API just holds a lookup of version name to version ID, not the versions themselves. Because the adapter target points at one specific API ID, it points at one specific version of the source API, not "the API" across all its versions. Pick the version you want when you create the proxy: switching to a different version later means changing `upstream.url` to that version's own API ID, which in practice means creating a new proxy rather than editing the existing one. ## Structure `x-tyk-mcp-server` holds a single field, `primitives`, an array with one entry per tool you want to configure: | Field | Type | Description | | - | - | - | | `primitives[].source` | object | Identifies the source REST operation this entry configures. See [Source](#source). | | `primitives[].name` | string | Overrides the derived MCP-facing tool name. | | `primitives[].description` | string | Overrides the derived MCP-facing tool description. | | `primitives[].annotations` | object | Overrides the tool's behavioral hints. See [Behavioral Hints](#behavioral-hints). | | `primitives[].parameters` | array | Per-parameter name and description overrides. See [Overriding Tool and Parameter Names and Descriptions](#overriding-tool-and-parameter-names-and-descriptions). | | `primitives[].allow` | boolean | Whether this tool is exposed. See [Selecting Which Operations Become Tools](#selecting-which-operations-become-tools). | You only need to list a source operation here if you want to override something about it or explicitly select it. An operation with no entry at all still becomes a tool under the default (no-allow-list) behavior described below. A single entry using every field looks like this: ```json theme={null} { "source": { "operationId": "getOrderStatus" }, "name": "get_order_status", "description": "Look up the current status of a customer order by ID.", "annotations": { "readOnlyHint": true }, "parameters": [ { "param": "id", "name": "order_id", "description": "The order to look up." } ], "allow": true } ``` ## Source `source` identifies which REST operation a primitive entry configures, using exactly one of two forms. Specifying both, or neither, fails validation when the definition loads. | Field | Type | Description | | - | - | - | | `source.operationId` | string | Selects the source operation by its OpenAPI `operationId`. Use this whenever the operation has one. | | `source.method` + `source.path` | string | Selects the source operation by HTTP method and OAS path template, for operations with no `operationId`. Rejected if the matched operation actually has an `operationId` — use `source.operationId` for it instead. | Both of the following select the same operation, assuming `getOrderStatus` is that operation's `operationId` — but not both together, since combining `operationId` with `method`/`path` on the same entry is itself a validation error: ```json theme={null} { "source": { "operationId": "getOrderStatus" } } ``` ```json theme={null} { "source": { "method": "GET", "path": "/orders/{id}/status" } } ``` ## Selecting Which Operations Become Tools All operations become tools by default. To explicitly declare what operations are exposed as tools, add entries with `allow: true` for only the operations you want exposed. As soon as one entry has `allow: true`, Tyk switches to that explicit allow-list and every other operation is excluded. Source and `allow` are the only two fields required to expose a tool: no name, description, or other overrides are needed. ```json theme={null} { "source": { "operationId": "getOrderStatus" }, "allow": true } ``` ## Overriding Tool and Parameter Names and Descriptions `name` and `description` override the tool's caller-facing identity; `parameters` overrides individual arguments: | Field | Type | Description | | - | - | - | | `parameters[].param` | string | The derived MCP argument name to override. | | `parameters[].name` | string | The caller-facing replacement name. | | `parameters[].description` | string | The caller-facing replacement description. | Tool names must be non-empty, no more than 128 characters, and contain only ASCII letters, digits, underscores, hyphens, and dots (`^[A-Za-z0-9_.-]+$`). Tyk rejects an invalid name rather than sanitizing it. ```json theme={null} { "source": { "operationId": "getOrderStatus" }, "name": "get_order_status", "description": "Look up the current status of a customer order by ID.", "parameters": [ { "param": "id", "name": "order_id", "description": "The order to look up." } ] } ``` This renames the tool from its derived name to `get_order_status` with a clearer description, and renames its `id` parameter to `order_id` for the calling agent. ## Behavioral Hints `annotations` sets the tool's MCP behavioral hints: | Field | Type | Description | | - | - | - | | `annotations.title` | string | A human-readable display name for the tool. | | `annotations.readOnlyHint` | boolean | Whether the tool is expected to avoid modifying state. | | `annotations.destructiveHint` | boolean | Whether the tool may perform destructive updates. | | `annotations.idempotentHint` | boolean | Whether repeated calls with the same arguments have the same effect. | | `annotations.openWorldHint` | boolean | Whether the tool interacts with external systems. | ```json theme={null} { "source": { "operationId": "cancelOrder" }, "annotations": { "destructiveHint": true, "idempotentHint": false } } ``` This marks `cancelOrder` as destructive and explicitly not idempotent: calling it twice may cancel two different orders or otherwise produce different results, so an agent shouldn't retry it blindly on failure. These fields are configurable directly in the OAS definition, but the Tyk Dashboard's wizard and designer don't yet expose a UI control for them. ## Compact and Expanded Shapes The fields above are all Tyk persists. They do not show what inputs the finished tool expects, what type each one is, or where each goes in the REST request (a path segment, a query parameter, a header, or the request body). Requesting the definition with `expand=true` computes that from the source operation and adds it to the response as read-only fields, letting you preview the finished tool shape before saving: `inputSchema`, `outputSchema`, `parameterLocations`, `parameterSourceNames`, `parameterSerializations`, `parameterOrder`, and `requestBodyContentType`. These expanded fields are never accepted on write; sending them back has no effect. For example, this is all you write and Tyk stores for an entry: ```json theme={null} { "source": { "operationId": "getOrderStatus" }, "name": "get_order_status", "allow": true } ``` Requesting the definition with `expand=true` returns that same entry with the extra read-only fields filled in: ```json expandable theme={null} { "source": { "operationId": "getOrderStatus" }, "name": "get_order_status", "allow": true, "inputSchema": { "type": "object", "properties": { "id": { "type": "string" } }, "required": ["id"] }, "parameterLocations": { "id": "path" }, "parameterSourceNames": { "id": "id" } } ``` ## Complete Example ```json expandable theme={null} { "x-tyk-mcp-server": { "primitives": [ { "source": { "operationId": "getOrderStatus" }, "name": "get_order_status", "description": "Look up the current status of a customer order by ID.", "annotations": { "readOnlyHint": true }, "allow": true }, { "source": { "method": "POST", "path": "/orders/{id}/cancel" }, "name": "cancel_order", "description": "Cancel an order that hasn't shipped yet.", "parameters": [ { "param": "id", "name": "order_id", "description": "The order to cancel." } ], "annotations": { "destructiveHint": true } } ] } } ``` This proxy exposes exactly one tool, `get_order_status`, the only entry marked `allow: true`. `cancel_order` is not exposed, since it is not marked `allow: true`, and neither is any other operation on the source API. Its `description` and `annotations` overrides are still saved in the definition, and take effect only if you later add `allow: true` to that same entry. ```json expandable theme={null} { "x-tyk-mcp-server": { "primitives": [ { "source": { "method": "POST", "path": "/orders/{id}/cancel" }, "name": "cancel_order", "description": "Cancel an order that hasn't shipped yet.", "parameters": [ { "param": "id", "name": "order_id", "description": "The order to cancel." } ], "annotations": { "destructiveHint": true } } ] } } ``` In the above example, all operations on the source API are exposed as tools. `cancel_order` has overridden `description`, `parameters`, and `annotations`, but every other operation on the source API becomes a tool too. To build up an explicit allow-list, add `allow: true` to each operation you want exposed, one at a time. This means new operations added to the API later won't be inadvertently exposed as a tool unless you explicitly add them. # MCP Gateway: Core Concepts Source: https://tyk.io/docs/ai-management/mcp-gateway/core-concepts How Tyk MCP Gateway fits in the MCP protocol flow: the session lifecycle, the proxy definition, the three middleware levels, and the policy model. ## The gateway role Without a gateway, AI agents connect directly to MCP servers over HTTP. Each server is responsible for its own authentication, access control, and rate limiting, or has none at all. There is no central point to see which agents are calling which tools, no consistent way to revoke access, and no protection against a slow or unavailable server. For the full picture of why this creates operational risk at scale, see [MCP Gateway overview](/docs/ai-management/mcp-gateway/overview). Tyk sits between MCP clients and your upstream MCP servers. Unlike a generic reverse proxy that treats all traffic as an opaque HTTP stream, Tyk understands the MCP protocol. It parses the JSON-RPC request body on every `POST /mcp` to identify the method being called and the specific primitive being accessed. This is what makes primitive-level control possible. Because Tyk knows that a particular request is a `tools/call` for `get_current_weather` (not just a `POST` to `/mcp`), it can: * Rate limit that tool independently, without affecting other tools on the same server * Block access to a specific resource URI without restricting the entire resources category * Enforce a timeout on a slow tool without affecting fast tools * Strip that tool from `tools/list` responses for consumers whose policy does not permit it * Record the exact tool name in analytics so you can see precisely which primitives agents are calling The fundamental difference from a REST proxy is how operations are identified. REST APIs use URL paths and HTTP methods: Tyk routes `GET /weather` differently from `GET /weather/forecast`. MCP routes all traffic through a single endpoint and identifies the operation from the request body: ```text theme={null} REST API (Tyk OAS): GET /weather → weather current conditions GET /weather/forecast → weather forecast MCP proxy (Tyk MCP): POST /mcp { "method": "tools/call", "params": { "name": "get-weather" } } POST /mcp { "method": "tools/call", "params": { "name": "get-forecast" } } ``` MCP proxies share the same authentication mechanisms, policy engine, and analytics infrastructure as your REST and GraphQL APIs. The body inspection is the only difference in how operations are identified and matched. MCP definitions are supported in Tyk OAS format only. They are not available as Tyk Classic API definitions. ### Transport MCP uses **Streamable HTTP** as its transport. The MCP specification defines a single endpoint path (`/mcp`) that supports two HTTP methods with distinct roles. Tyk proxies both. **`POST /mcp`**: JSON-RPC messages. Clients send JSON-RPC 2.0 messages to `POST /mcp`. The upstream MCP server can respond with: * **`200 application/json`**: a single JSON-RPC response, for operations that complete immediately. * **`200 text/event-stream`**: a Server-Sent Events stream carrying multiple JSON-RPC messages, used when the server streams results or sends progress notifications. * **`202 Accepted`**: an acknowledgement for JSON-RPC notifications that do not expect a response body. Tyk executes the middleware chain against the incoming `POST` request (authenticating, applying rate limits, checking allowlists) and then proxies it to the upstream. Tyk preserves the response content type and streams SSE responses through to the client without buffering or transforming the body. **`GET /mcp`**: Server-Sent Events. Clients open a persistent `GET /mcp` connection to receive server-initiated messages. The upstream MCP server uses this channel to push progress notifications, resource update notifications, and server-to-client requests such as `sampling/createMessage`. Tyk proxies the SSE stream transparently, maintaining the long-lived connection for the duration of the session. Tyk supports Streamable HTTP only. It does not support these transports: * The legacy HTTP+SSE transport from MCP versions before `2025-03-26`, which uses a separate POST endpoint and a `/sse` endpoint. * The stdio transport, which is for local, in-process MCP servers. If your MCP server uses stdio, put a stdio-to-HTTP bridge, such as the one in the MCP SDK, between it and Tyk. ### Protocol headers MCP defines several protocol-specific headers that Tyk passes through unchanged in both directions: | Header | Direction | Purpose | | - | - | - | | `MCP-Protocol-Version` | Client → Server | Required. Specifies the MCP protocol revision (for example, `2025-11-25`). | | `Mcp-Session-Id` | Server → Client, then Client → Server | Session identifier. Returned by the server after initialization; clients echo it on subsequent requests. | | `Last-Event-ID` | Client → Server | SSE resume token sent when reconnecting to a `GET /mcp` stream. | | `Origin` | Client → Server | Used by servers for origin-based security validation. | The client and upstream MCP server handle version negotiation and session management. Tyk does not modify any MCP protocol headers. *** ## What is MCP? New to MCP? The [MCP introduction](https://modelcontextprotocol.io/introduction) is a good starting point before reading further. The Model Context Protocol (MCP) is an open standard that defines how AI applications connect to external tools, data sources, and services. It uses a client-server model: an **MCP client** (an AI agent, LLM orchestration framework, or application) connects to an **MCP server** that exposes capabilities, and the two communicate using JSON-RPC 2.0 messages carried over HTTP. **Tyk supports the `2025-11-25` revision of the MCP specification.** ### Primitives MCP servers expose three types of capability, collectively called **primitives**. | Primitive | Description | Discovery method | Invocation method | | - | - | - | - | | **Tool** | A callable function that takes structured arguments and returns a result. Used for actions and computed queries. | `tools/list` | `tools/call` | | **Resource** | A readable data source identified by a URI. Used for documents, files, and live data feeds. | `resources/list` | `resources/read` | | **Prompt** | A reusable prompt template the server exposes for common tasks. | `prompts/list` | `prompts/get` | Each primitive has a name (or URI for resources) that uniquely identifies it within the server: * A `tools/call` request names the tool in `params.name` * A `resources/read` request names the resource URI in `params.uri` * A `prompts/get` request names the prompt in `params.name` This name is what Tyk uses to apply primitive-level middleware and policy controls. ### Client-side primitives MCP also defines primitives that run in the opposite direction: capabilities that servers can request from clients rather than expose themselves. | Primitive | Description | Method | | - | - | - | | **Sampling** | Server requests the client to perform LLM inference on its behalf and return the result. | `sampling/createMessage` | | **Roots** | Server requests the list of filesystem roots (directories or URIs) the client is willing to share. | `roots/list` | | **Elicitation** | Server requests structured input from the user, mediated through the client. | `elicitation/create` | Tyk passes client-side primitive messages through to the upstream and back. Primitive-level middleware configuration (rate limits, access control, timeouts) applies to server-side primitives only. ### The request format Every MCP operation is a JSON-RPC 2.0 message sent to `POST /mcp`. Each message carries a `method` field that identifies the operation and, for invocation requests, a `params` object that names the specific primitive being accessed. A typical tool call looks like this: ```json theme={null} { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "get_current_weather", "arguments": { "location": "London" } } } ``` The `method` field identifies the category of operation: `tools/call` in this example. The `params.name` field identifies the specific tool. Tyk reads both fields on every incoming `POST /mcp` request to determine which middleware to execute before forwarding to the upstream. ### JSON-RPC methods The MCP specification groups its JSON-RPC methods by capability. The most common methods are: | Method | Category | Description | | - | - | - | | `initialize` | Session | Opens the session and negotiates capabilities. | | `notifications/initialized` | Session | Client confirms session is ready. | | `ping` | Session | Checks that the other side is still responsive. | | `tools/list` | Tools | Returns the list of tools the server exposes. | | `tools/call` | Tools | Invokes a named tool with the supplied arguments. | | `resources/list` | Resources | Returns the list of resources the server exposes. | | `resources/templates/list` | Resources | Returns the URI templates the server exposes. | | `resources/read` | Resources | Reads the content of a named resource URI. | | `resources/subscribe`, `resources/unsubscribe` | Resources | Starts or stops update notifications for a resource. | | `prompts/list` | Prompts | Returns the list of prompt templates the server exposes. | | `prompts/get` | Prompts | Retrieves a named prompt template, optionally with arguments. | | `completion/complete` | Completions | Requests autocompletion values for a prompt or resource argument. | | `logging/setLevel` | Logging | Sets the log level the server uses for log notifications. | | `sampling/createMessage` | Sampling | Requests the client to perform LLM sampling on behalf of the server. | | `notifications/tools/list_changed` | Notifications | Server-initiated notification that the tool list has changed. | Only three methods carry a primitive name: `tools/call` (`params.name`), `resources/read` (`params.uri`), and `prompts/get` (`params.name`). Tyk does not reject methods that are not in this table. It forwards them to the upstream, subject to any method-level access control, rate limit, or allowlist that you configure. Tyk can apply rate limits, access control, and middleware at the method level (for example, capping all `tools/call` requests) and at the primitive level (for example, rate limiting a specific named tool). The distinction matters: method-level controls apply to every invocation of that method regardless of which primitive is named; primitive-level controls apply only when that specific tool, resource, or prompt is requested. *** ## Session lifecycle MCP is a stateful protocol. When a client sends an `initialize` request, the upstream server responds with an `Mcp-Session-Id` header. The client includes this identifier on all subsequent requests, allowing the server to associate them with the established session context. Tyk passes the header through unmodified and does not maintain session state itself. A typical session proceeds through four phases. 1. **Handshake**: the client and server negotiate capabilities and establish a session identifier. 2. **Discovery**: the client queries the server's available tools, resources, and prompts. 3. **Invocation**: the client calls primitives; Tyk applies rate limiting, access control, and observability on each request. 4. **Session close**: the client terminates the session; the session identifier is invalidated. ### Handshake Tyk authenticates the `initialize` request before proxying it to the upstream. The upstream responds with an `Mcp-Session-Id` header that Tyk passes through to the client unchanged. The client confirms readiness with a `notifications/initialized` message, and the session is established. ```mermaid theme={null} sequenceDiagram autonumber participant C as MCP Client participant T as Tyk Gateway participant U as Upstream MCP Server rect rgb(240, 236, 255) Note over C,U: Handshake C->>T: POST /mcp — initialize Note over T: Authenticate request T->>U: initialize (proxied unchanged) U-->>T: 200 OK · Mcp-Session-Id: abc123 T-->>C: 200 OK · Mcp-Session-Id: abc123 (passed through) C->>T: POST /mcp — notifications/initialized · Mcp-Session-Id: abc123 T->>U: notifications/initialized (proxied) U-->>T: 202 Accepted T-->>C: 202 Accepted end ``` ### Discovery Once the session is open, the client calls `tools/list` (and optionally `resources/list`, `resources/templates/list`, and `prompts/list`) to learn what the server exposes. Tyk filters the upstream's response before it reaches the client. It removes every primitive that the consumer cannot call: * Primitives that the proxy's `allow` and `block` middleware do not permit. These rules apply to every consumer. * Primitives that the consumer's policy (`mcp_access_rights`) does not permit. These rules apply to each key separately. Tyk filters both single JSON responses and SSE streams. From the moment it connects, each consumer sees only the primitives that it can call. ```mermaid theme={null} sequenceDiagram autonumber participant C as MCP Client participant T as Tyk Gateway participant U as Upstream MCP Server rect rgb(235, 248, 255) Note over C,U: Discovery C->>T: POST /mcp — tools/list · Mcp-Session-Id: abc123 T->>U: tools/list (proxied) U-->>T: Full tool list Note over T: Filters to permitted tools only T-->>C: Filtered tool list (scoped to consumer entitlements) end ``` ### Invocation Each primitive call passes through Tyk's full middleware chain. Rate limiting, access control, and observability all fire on every `tools/call` request. If scope enforcement is configured, Tyk validates the inbound token's scopes against the primitive's requirements before proxying. If token exchange is configured, Tyk exchanges the inbound token for a backend-scoped token — the inbound SSO token never reaches the upstream MCP server. If the consumer's policy permits the named tool and rate limits allow the request, Tyk proxies it to the upstream and returns the response. This phase repeats for every tool, resource, or prompt the client invokes. ```mermaid theme={null} sequenceDiagram autonumber participant C as MCP Client participant T as Tyk Gateway participant U as Upstream MCP Server rect rgb(235, 255, 244) Note over C,U: Invocation (repeats per primitive call) C->>T: POST /mcp — tools/call · Mcp-Session-Id: abc123 Note over T: Rate limiting · access control · observability T->>U: tools/call (proxied) U-->>T: Tool response T-->>C: Tool response end ``` ### Session close When the client has finished, it sends `DELETE /mcp` with the `Mcp-Session-Id` header. Tyk proxies the request to the upstream, which terminates the session. After session close, the `Mcp-Session-Id` is invalid; a new `initialize` request is required to open a new session. ```mermaid theme={null} sequenceDiagram autonumber participant C as MCP Client participant T as Tyk Gateway participant U as Upstream MCP Server rect rgb(255, 240, 240) Note over C,U: Session close C->>T: DELETE /mcp · Mcp-Session-Id: abc123 T->>U: DELETE /mcp (proxied) U-->>T: 200 OK T-->>C: 200 OK Note over C,U: Session closed end ``` If the `GET /mcp` SSE connection drops, the client can reconnect by opening a new `GET /mcp` request with the `Last-Event-ID` header set to the ID of the last event received. Tyk passes this through to the upstream, which resumes the stream from that point. Tyk does not reconnect the stream itself. The client must open the new connection. *** ## The proxy definition The **MCP proxy definition** is the configuration object that describes the proxy. It is a Tyk OAS API definition that holds the listen path, upstream URL, authentication, and middleware. For its structure and a full example, see [MCP proxy definition](/docs/ai-management/mcp-gateway/mcp-proxy-definitions). You manage MCP proxy definitions through the [Tyk Gateway API](/docs/ai-management/mcp-gateway/mcp-api-extensions) (at `/tyk/mcps`) or the [Tyk Dashboard](/docs/ai-management/mcp-gateway/managing-proxies). ### Tool naming and discovery Every tool, resource, and prompt on an MCP server has a **name** (or URI for resources) that uniquely identifies it within that server. Understanding how names are assigned, and how Tyk uses them, is a prerequisite for configuring primitive-level middleware, blocking specific tools, or writing policies with allowlists and blocklists. **When an MCP proxy fronts a remote MCP server**, tool names come from the upstream server verbatim. Tyk does not modify or namespace them. If the upstream server exposes a tool named `get-weather`, that is the name Tyk uses for middleware matching, policy rules, and analytics. **When an MCP proxy is [generated directly from a Tyk-managed REST API](/docs/ai-management/mcps/api-to-mcp)**, tool names are derived from the `operationId` field of each OpenAPI operation. An operation with `operationId: getWeatherForecast` becomes a tool named `getWeatherForecast`. If an operation has no `operationId`, Tyk derives a deterministic tool name from its HTTP method and path instead, so `GET /orders/{id}` becomes `get_orders_id`. That derived name stays stable across reloads. There is one exception: if the source API's OAS uses an operation-level allow-list (`x-tyk-api-gateway.middleware.operations[...].allow`), operations without an `operationId` are excluded from the MCP tool catalog, because that allow-list is keyed by `operationId`. Tyk also filters list responses, so each consumer sees only the primitives that it can call. See [Discovery](/docs/ai-management/mcp-gateway/core-concepts#discovery). *** ## Middleware Tyk applies middleware to MCP traffic at three levels, all configured in the `x-tyk-api-gateway.middleware` section of the proxy definition. The levels are evaluated in order from broadest to most specific. ### Global middleware Global middleware applies to every request that reaches the proxy, before any method-level or primitive-level processing. Use it for server-wide concerns: CORS configuration, traffic logging, header injection into upstream requests, or custom plugins that should run on all traffic. ### Operation middleware Operation middleware applies to all requests for a specific JSON-RPC method, regardless of which primitive is called. Configure it in `middleware.operations`, keyed by the JSON-RPC method name with its HTTP method suffix (for example, `tools/callPOST`). Use it for method-wide policies, such as a rate limit that applies to all `tools/call` requests without distinguishing between individual tools. ```json theme={null} { "middleware": { "operations": { "tools/callPOST": { "rateLimit": { "enabled": true, "rate": 500, "per": 60 } } } } } ``` This rate limit applies to every `tools/call` request, regardless of which tool is named in `params`. ### Primitive middleware Primitive middleware applies to a specific tool, resource, or prompt. Configure it in one of three maps (`middleware.mcpTools`, `middleware.mcpResources`, or `middleware.mcpPrompts`), keyed by the primitive's identifier: the tool name, resource URI (or URI pattern), or prompt name. In addition to the standard middleware capabilities, two OAuth 2.0 features operate at this level: `scopeCheck` validates the inbound token's scopes against the primitive's `security:` requirements, and `exchange` replaces the `Authorization` header with a backend-scoped token before the request reaches the upstream (see [Token exchange](/docs/api-management/authentication/token-exchange)). ```json theme={null} { "middleware": { "mcpTools": { "execute-query": { "allow": { "enabled": true }, "rateLimit": { "enabled": true, "rate": 10, "per": 60 } } } } } ``` This configuration allowlists the `execute-query` tool and applies a rate limit of 10 requests per minute, independently of any other tools on the same proxy. When both operation-level and primitive-level middleware are configured, both apply. A `tools/call` request to `execute-query` must pass the operation-level limit (500/min for all tool calls) and the primitive-level limit (10/min for this tool). For how `allow` and `block` work, including allowlist mode, see [Access control](/docs/ai-management/mcp-gateway/mcp-middleware#access-control). ### Evaluation order When a request arrives, Tyk runs the levels in this order: 1. Global middleware. 2. Operation middleware for the matched JSON-RPC method. 3. Primitive middleware for the named tool, resource, or prompt. Scope check (`scopeCheck`) and token exchange (`exchange`) run at this level. 4. Tyk forwards the request to the upstream MCP server. If a level rejects the request, Tyk stops processing and returns an error to the client. See [MCP middleware](/docs/ai-management/mcp-gateway/mcp-middleware) for the full list of available capabilities: access control, request and response transformation, traffic management (rate limiting, timeouts, circuit breakers), virtual endpoints, and observability controls. *** ## Policies A **Tyk security policy** is a reusable template of access rights and usage limits that you apply to one or more API keys. You define a policy once and issue keys that inherit its rules automatically, rather than configuring each key individually. When you update the policy, every key bound to it picks up the change. Policies give you per-consumer control at every level of the MCP protocol: * **Proxy access**: control which MCP proxies a consumer key can reach * **JSON-RPC method access**: restrict which protocol operations a consumer can use (for example, allow `tools/call` but block `sampling/createMessage`) * **Primitive access**: define per-consumer allowlists and blocklists for individual tools, resources, and prompts, using regular expressions to match by name * **Per-primitive rate limits**: set independent rate limits on specific primitives, so a consumer exhausting their quota on one tool does not affect their access to others * **Quotas**: cap total call volume over a renewal period Primitive access control is enforced at two points in the MCP protocol. **At invocation time**: Tyk checks `tools/call`, `resources/read`, and `prompts/get` requests against the consumer's permitted primitives. Blocked calls return a JSON-RPC error before the request reaches the upstream. **At discovery time**: Tyk removes the primitives that the consumer cannot call from list responses. See [Discovery](/docs/ai-management/mcp-gateway/core-concepts#discovery). ### Policies versus middleware Both middleware and policies can enforce limits on MCP primitives, but they operate on different subjects. **Middleware** applies to all traffic through the proxy: a primitive rate limit in `mcpTools` caps the call rate for a tool across every caller combined. It protects the upstream from overload. **Policies** apply per consumer. A primitive rate limit in a policy caps the call rate for one specific key, with each consumer's counters tracked independently. This is how you enforce different entitlements for different consumers: a standard tier with read-only access and lower limits, a premium tier with access to sensitive tools and higher quotas. The two work together: middleware sets the ceiling for all traffic, policies determine what each consumer is entitled to within that ceiling. When both set a limit on the same primitive, Tyk enforces both, with separate counters. It checks the per-key policy limit first, and the first limit that a request exceeds blocks it. In the Tyk Dashboard, you set shared limits and allowlists on the proxy's **Primitives** tab, and per-consumer limits and access in a policy. A change to either applies at once to every key that it covers. Tyk also supports scope-based access control via the `oauth2` scheme's `scopeCheck` feature. This is complementary to policy-based access control: policies control which primitives a consumer key can reach; scope check validates that the inbound token carries the required OAuth scopes for each primitive. When you use both, a consumer must hold a key that the policy permits and present a token with the required scopes. See [OAuth 2.0 (External IdP)](/docs/api-management/authentication/oauth2-authentication) for configuration details. See [MCP proxy policies](/docs/ai-management/mcp-gateway/policies) for the full configuration reference, Dashboard UI walkthrough, and API examples. # How to block an MCP tool for all consumers Source: https://tyk.io/docs/ai-management/mcp-gateway/how-to-block-tool Block an MCP tool at the proxy so that no consumer can call it, whatever their policy allows. The tool stays on the upstream server. MCP servers often expose more tools than you want to make available through the gateway. Some tools are administrative, irreversible, or simply not ready for agent access. Rather than deploying a separate server with a reduced tool set, or remembering to exclude the tool from every consumer policy, you can block individual tools at the proxy layer. A blocked tool is rejected by Tyk before the request reaches the upstream, and filtered out of `tools/list` responses so agents cannot discover it exists. No consumer key or policy can override a definition-level block: if the tool is blocked, it is invisible and uncallable for everyone. This guide blocks the `delete_user` tool on the Mock MCP Server, then uses MCP Inspector to verify that calling it returns an error while all other tools continue to work. *** ## Before you begin * The Mock MCP Server running on `http://localhost:7878`. Set up in the [quickstart](/docs/ai-management/mcp-gateway/quickstart). * An MCP proxy named **Mock MCP Server** with authentication enabled. See [How to secure an MCP proxy](/docs/ai-management/mcp-gateway/how-to-proxy-remote-mcp). * [Node.js](https://nodejs.org/) 18 or later (to run [MCP Inspector](https://github.com/modelcontextprotocol/inspector)) *** ## Instructions ### Step 1: Block the tool 1. In the Tyk Dashboard sidebar, click **MCP**. Find **Mock MCP Server** in the list and click **Edit** to open the proxy designer. 2. Click the **Primitives** tab. Primitives tab on the Mock MCP Server proxy 3. Click **Add Primitive**. Set **Type** to **Tool** and enter `delete_user` as the name. Click **Add Primitive**. Add delete_user as a tool primitive 4. Click `delete_user` to open the middleware panel. 5. Click **Add Middleware**. 6. Select **Block List**. 7. Click **Add Middleware**. Block middleware selected for delete_user 8. Click **Save MCP Proxy**. *** ### Step 2: Verify with MCP Inspector 1. Start MCP Inspector: ```bash theme={null} npx @modelcontextprotocol/inspector ``` 2. Open the URL printed in your terminal. 3. Set **Transport Type** to `Streamable HTTP`. 4. Set **URL** to your MCP endpoint (find it under **MCP Proxy URL** in the proxy designer, then append `/mcp`). 5. Add a header: `Authorization` = `Bearer {your-api-key}`. 6. Click **Connect**. 7. Click the **Tools** tab. Notice that `delete_user` no longer appears in the tool list. Tyk filters blocked tools out of `tools/list` responses, so agents cannot discover them at all. 8. To confirm the block is enforced at the call layer, enter `delete_user` manually in the tool name field, provide any value for **user\_id**, and click **Run**. Tyk blocks the request before it reaches the upstream. The response panel shows: ```json theme={null} { "jsonrpc": "2.0", "error": { "code": -32002, "message": "Requested endpoint is forbidden", "data": { "http_code": 403 } }, "id": 6 } ``` 9. Select any other tool (`get_users`, `get_posts`, `get_products`) and click **Run**. Those calls succeed normally. Only `delete_user` is blocked. *** ## Block vs. RBAC: when to use each Both `block` and RBAC allowlists restrict which tools a consumer can call, but they operate at different layers and serve different purposes. **Use `block`** when a tool should never be reachable through this proxy, for anyone. The restriction is set in the proxy definition and cannot be overridden by a policy. It is the right choice for tools that are dangerous, irreversible, or not yet ready for agent access: `delete_user`, `drop_table`, `send_email`. **Use RBAC** when different consumers should have different access to the same set of tools. A read-only agent sees only read tools; an admin agent sees all tools. The restriction is set in a security policy and scoped per consumer. See [How to implement RBAC for an MCP proxy](/docs/ai-management/mcp-gateway/how-to-mcp-rbac). The two can be combined: block the tools that no one should ever reach, then use RBAC to scope what each consumer can see within what remains. # How to implement role-based access control for an MCP proxy Source: https://tyk.io/docs/ai-management/mcp-gateway/how-to-mcp-rbac Give different AI agents access to different tools on the same MCP proxy with Tyk policies, without separate proxy definitions. After [securing your MCP proxy](/docs/ai-management/mcp-gateway/how-to-proxy-remote-mcp), the next step is controlling what each consumer can do. With role-based access control (RBAC), a policy bound to a key determines which tools that agent can invoke. This guide creates two roles on the Mock MCP Server: * **Reader**: can only call `get_users`, `get_posts`, `get_products`, and `get_analytics` * **Admin**: can call all 15 tools You'll create a policy for each role, issue role-specific keys, then use [MCP Inspector](https://github.com/modelcontextprotocol/inspector) to verify that each key sees exactly the tools it is permitted to access. *** ## Two approaches to tool-level access control Tyk supports two complementary mechanisms for controlling what an AI agent can do on an MCP proxy. **Policy-based access control** (this guide): Tyk policies define an explicit allowlist of tools a consumer is permitted to invoke, and apply rate limits to each tool. A policy is bound to a key at issuance time and enforced at the gateway, regardless of what the agent's bearer token claims. This works with any authentication method, requires no changes to your identity provider, and lets the platform team manage access centrally without touching the IdP. **Scope-based access control**: when you use the [oauth2 security scheme](/docs/api-management/authentication/oauth2-authentication), you can declare required scopes on individual tools in the API definition. Tyk validates those scopes against the inbound token's `scope` claim at runtime, delegating fine-grained access decisions to your IdP. This approach is well suited to environments where access rules change frequently, or where the IdP is already the source of truth for permissions. The two mechanisms are complementary and can be combined. Policies control which tools a consumer can reach, and at what rate. Scope check validates what the IdP has actually granted in the token at runtime. Together they give you both platform governance and identity-driven authorization. This guide covers policy-based access control only. *** ## How it works Tyk policies control consumer access at two levels relevant to this guide: **Primitive access**: restricts which specific tools a consumer can invoke. When a key's policy includes an allowed list for tools, Tyk enforces it on both `tools/call` (blocking disallowed tool invocations) and `tools/list` (filtering the response so the agent only sees tools it can use). The upstream server is never reached for blocked calls. **Proxy access**: determines which MCP proxies the key can reach at all. Both keys in this guide point at the same proxy URL. The difference in behavior comes entirely from the policies applied to each key. For the complete policy reference, see [MCP policies](/docs/ai-management/mcp-gateway/policies). *** ## Before you begin * The Mock MCP Server running on `http://localhost:7878`. Set up in the [quickstart](/docs/ai-management/mcp-gateway/quickstart). * An MCP proxy named **Mock MCP Server** with authentication enabled. See [How to secure an MCP proxy](/docs/ai-management/mcp-gateway/how-to-proxy-remote-mcp). * [Node.js](https://nodejs.org/) 18 or later (to run [MCP Inspector](https://github.com/modelcontextprotocol/inspector)) * A Dashboard user account with policy management permissions *** ## Instructions ### Step 1: Create the Reader policy 1. In the Tyk Dashboard sidebar, click **Policies**, then click **Add Policy**. 2. On the **Access Rights** tab, find **Mock MCP Server** in the API list and click it to add it. Select Mock MCP Server from the API list 3. Scroll to **Primitive based access** within the Mock MCP Server panel and add each permitted tool: * Click **Add**, enter `get_users`, set **Type** to **Tool**, and set the status to **Allowed**. Click **Add**. * Repeat for `get_posts`, `get_products`, and `get_analytics`. Primitive based access configuration Once you add any tool with **Allowed** status, Tyk treats the list as an explicit allowlist: any tool not in the list is blocked for keys on this policy. 4. Click the **Configurations** tab and set: * **Policy Name**: `Reader` * **Policy State**: **Active** 5. Click **Create Policy**. Reader policy configuration ### Step 2: Create the Admin policy The Admin policy grants unrestricted tool access. Omitting the **Primitive based access** entries means all tools are accessible. 1. Click **Add Policy**. 2. On the **Access Rights** tab, add **Mock MCP Server**. 3. Click the **Configurations** tab and set: * **Policy Name**: `Admin` * **Policy State**: **Active** 4. Click **Create Policy**. ### Step 3: Issue role-specific keys 1. In the Dashboard sidebar, click **Keys**, then **Add Key**. 2. Under **Access rights**, click **Apply Policy** and select **Reader**. Apply Reader policy to key 3. Click the **Configurations** tab and set an **Alias** such as `reader-agent`. Set alias and create key 4. Click **Create Key** and copy the key. 5. Repeat steps 1–4 to issue a second key, selecting **Admin** as the policy and `admin-agent` as the alias. ### Step 4: Verify in MCP Inspector 1. Start MCP Inspector: ```bash theme={null} npx @modelcontextprotocol/inspector ``` 2. Open the URL printed in your terminal. #### Test the Reader key 3. Set **Transport Type** to `Streamable HTTP`. 4. Set **URL** to your MCP endpoint (find it under **MCP Proxy URL** in the proxy designer, then append `/mcp`). 5. Add a header: `Authorization` = `Bearer {reader-api-key}` and click **Connect**. 6. Click the **Tools** tab. You will see exactly four tools: `get_users`, `get_posts`, `get_products`, and `get_analytics`. Tyk has filtered the `tools/list` response based on the Reader policy's allowed list. 7. Select `get_users` and click **Run**. It succeeds. #### Test the Admin key 8. Click **Disconnect**. Replace the key in the `Authorization` header with your Admin key and click **Connect**. 9. Click the **Tools** tab. All 15 Mock MCP Server tools appear. The Admin policy applies no tool restrictions. Both keys connect to the same proxy at the same URL. The difference in tool availability is driven entirely by the policy. # How to secure an MCP proxy Source: https://tyk.io/docs/ai-management/mcp-gateway/how-to-proxy-remote-mcp Add key authentication to an MCP proxy, issue an API key, and confirm that MCP Inspector gets a 401 error without the key. Takes about ten minutes. After completing the [quickstart](/docs/ai-management/mcp-gateway/quickstart), you have a working MCP proxy, but it accepts connections from any client. This guide secures your remote MCP server so that only agents with a valid key can reach it. *** ## Before you begin * A Tyk Gateway (v5.13 or later) connected to your Tyk Dashboard * The Mock MCP Server running on `http://localhost:7878`. See the [quickstart](/docs/ai-management/mcp-gateway/quickstart). * An MCP proxy named **Mock MCP Server** already created. Also covered in the quickstart. * [Node.js](https://nodejs.org/) 18 or later (to run [MCP Inspector](https://github.com/modelcontextprotocol/inspector)) * A Dashboard user account with MCP write permissions *** ## Instructions ### Step 1: Enable authentication 1. In the Tyk Dashboard sidebar, click **MCP**, then click **Edit** next to **Mock MCP Server**. 2. In the designer, click the **Authentication** switch. 3. Select **Auth Token** as the authentication method. 4. Set the token location to **use header value** and leave the header name as `Authorization`. Auth token header configuration 5. Click **Save MCP Proxy**. The proxy now requires a bearer token on every request. Clients that connect without a valid key receive a `401 Unauthorized` response. ### Step 2: Issue an API key 1. In the Dashboard sidebar, click **Keys**, then click **Add Key**. 2. Under **Access rights**, click **Choose API** and select **Mock MCP Server**. 3. Click **Create Key**. Copy the key shown — you cannot retrieve it after navigating away. API key created ### Step 3: Verify with MCP Inspector 1. Start MCP Inspector: ```bash theme={null} npx @modelcontextprotocol/inspector ``` 2. Open the URL printed in your terminal. 3. Set **Transport Type** to `Streamable HTTP`. 4. Set **URL** to your MCP endpoint (find it under **MCP Proxy URL** in the proxy designer, then append `/mcp`). 5. Click **Connect** without adding an `Authorization` header. The connection fails with a `401 Unauthorized` error, confirming authentication is enforced. 6. Add a header: `Authorization` = `Bearer {your-api-key}` and click **Connect** again. MCP Inspector connected with API key 7. Click the **Tools** tab. All 15 Mock MCP Server tools appear. *** ## Limitations and alternatives API key authentication via a bearer token header is a straightforward way to secure an MCP proxy, but it has limitations: keys are long-lived, there is no built-in token expiry or rotation, and clients must manage the key securely. For more demanding scenarios, Tyk supports a range of [client authentication methods](/docs/api-management/client-authentication), including JWT, mutual TLS, and OAuth 2.1. For MCP specifically, Tyk extends OAuth 2.1 with Protected Resource Metadata so MCP-aware clients can discover authentication requirements automatically. See [MCP Gateway: OAuth 2.1 authentication](/docs/ai-management/mcp-gateway/oauth-2-1). # How to rate limit individual MCP tools per consumer Source: https://tyk.io/docs/ai-management/mcp-gateway/how-to-rate-limit-tools-per-consumer Apply per-tool rate limits to an MCP proxy so different consumers have different call budgets on the same tool, without creating separate proxy definitions. Not all MCP tools cost the same. A tool that runs a complex query costs far more than one returning cached data. When multiple agents share the same proxy, a single blanket rate limit either over-restricts lightweight tools or under-protects expensive ones. Tyk lets you set rate limits on individual tools, per consumer. Each agent key tracks its own independent counter: one agent exhausting their budget on a tool does not affect another agent's counter for the same tool. This guide rate limits the `get_analytics` tool on the Mock MCP Server to 3 calls per minute for a specific consumer policy, then uses MCP Inspector to verify the limit is enforced. *** ## Before you begin * The Mock MCP Server running on `http://localhost:7878`. Set up in the [quickstart](/docs/ai-management/mcp-gateway/quickstart). * An MCP proxy named **Mock MCP Server** with authentication enabled. See [How to secure an MCP proxy](/docs/ai-management/mcp-gateway/how-to-proxy-remote-mcp). * [Node.js](https://nodejs.org/) 18 or later (to run [MCP Inspector](https://github.com/modelcontextprotocol/inspector)) * A Dashboard user account with policy management permissions *** ## Instructions ### Step 1: Create a policy with a per-tool rate limit 1. In the Tyk Dashboard sidebar, click **Policies**, then click **Add Policy**. 2. On the **Access Rights** tab, find **Mock MCP Server** in the API list and click it to add it. 3. Expand the Mock MCP Server access rights block and scroll to **Set Usage Limits by MCP Primitives/Methods**. 4. Click **Add Rate Limit** and configure the limit: * Set **Rate** to `3` * Set **Per** to `60` seconds * Click **Add**, enter `get_analytics`, and set **Type** to **Tool** Add get_analytics as a tool primitive 5. Click **Add** to confirm the primitive. 6. Click the **Configurations** tab and set: * **Policy Name**: `Limited Agent` * **Policy State**: **Active** 7. Click **Create Policy**. Create the Limited Agent policy *** ### Step 2: Issue a key 1. In the Dashboard sidebar, click **Keys**, then **Add Key**. 2. Under **Access rights**, click **Apply Policy** and select **Limited Agent**. 3. Click the **Configurations** tab and set an **Alias** such as `limited-agent` to identify this key in analytics. 4. Click **Create Key** and copy the key. *** ### Step 3: Verify with MCP Inspector 1. Start MCP Inspector: ```bash theme={null} npx @modelcontextprotocol/inspector ``` 2. Open the URL printed in your terminal. 3. Set **Transport Type** to `Streamable HTTP`. 4. Set **URL** to your MCP endpoint (find it under **MCP Proxy URL** in the proxy designer, then append `/mcp`). 5. Add a header: `Authorization` = `Bearer {your-api-key}`. 6. Click **Connect**. 7. Click the **Tools** tab and select **get\_analytics**. 8. The tool requires a **metric** parameter. Enter `users` (or any of `posts`, `orders`, `revenue`). 9. Click **Run** three times in quick succession. Each call succeeds. The response panel shows the analytics data from the Mock MCP Server. 10. Click **Run** a fourth time. Tyk has exhausted the 3 calls per minute budget for this consumer and blocks the request. The response panel shows: **MCP error -32001: Streamable HTTP error: Error POSTing to endpoint:** ```json theme={null} { "jsonrpc": "2.0", "error": { "code": -32003, "message": "Rate Limit Exceeded", "data": { "http_code": 429 } }, "id": 7 } ``` 11. Click any other tool (`get_users`, `get_posts`, `get_products`) and click **Run**. Those calls succeed normally. Only the `get_analytics` counter is exhausted. *** ## How per-consumer and shared limits compose Each key on the **Limited Agent** policy has its own counter for `get_analytics`. To add a limit shared by all consumers, see [Policies versus middleware](/docs/ai-management/mcp-gateway/core-concepts#policies-versus-middleware). # Managing MCP proxies using the Dashboard Source: https://tyk.io/docs/ai-management/mcp-gateway/managing-proxies Create, edit, and delete MCP proxies in Tyk Dashboard: the proxy list, the creation wizard, the Settings and Primitives tabs, middleware, and permissions. The **MCP** section of the Tyk Dashboard is the central registry of all MCP proxies in your organization, whether they front a remote MCP server or are [generated directly from a Tyk-managed REST API](/docs/ai-management/mcps/api-to-mcp). Each proxy entry records its upstream (a remote server address or a paired Tyk API), the listen path clients use to connect, the tools and resources it exposes, and the access policies that govern it. Teams have a single authoritative place to see what MCP capabilities are available, onboard new proxies, and control who can access them. An MCP server is reachable through Tyk only after you register a proxy for it. Each agent sees only the primitives that its policy permits. See [Discovery](/docs/ai-management/mcp-gateway/core-concepts#discovery). The section gives you a searchable catalog of all registered proxies, a guided creation flow for onboarding proxies of either type, and the MCP Designer. For a proxy fronting a remote MCP server, the Designer has two tabs: **Settings** for proxy-level configuration and middleware, and **Primitives** for managing per-primitive middleware on individual tools, resources, and prompts. For a REST API to MCP proxy, the Designer adds a third **Tool mapping** tab for selecting and enriching the tools generated from the source API. For scripted or automated management, use the Dashboard API or Gateway API. See [MCP API extensions](/docs/ai-management/mcp-gateway/mcp-api-extensions) for the full endpoint reference. MCP proxy definitions use the Tyk OAS format. They are not available as Tyk Classic API definitions. For the full definition structure, see [MCP proxy definition](/docs/ai-management/mcp-gateway/mcp-proxy-definitions). *** ## Permissions Access to MCP proxy management is controlled by the `mcp` permission on the user's role. | Permission level | What the user can do | | - | - | | **Write** | Create, view, edit, and delete MCP proxies. Full access to all UI actions. | | **Read** | View the proxy list and MCP Designer. Access the definition viewer. Cannot create, edit, save, or delete. | | **Deny** | No access. The **MCP** sidebar item is not visible. | Permissions are assigned in the Dashboard under **User Management → Users**. For organization-wide access control, configure permissions on user groups rather than individual users. MCP permission setting in the Dashboard *** ## The MCP proxies list The list page shows every MCP proxy managed by this Dashboard instance. Clicking a row opens the MCP Designer. The search input at the top filters proxies by name in real time. Clear the input to return to the full list. The **Add MCP Proxy** button opens the [Create an MCP proxy](#create-an-mcp-proxy) screen. MCP proxy list *** ## Create an MCP proxy Clicking **Add MCP Proxy** on the proxy list opens the **Create MCP Proxy** screen, where you choose how to create your proxy: * **Remote MCP server**: connect to an existing MCP server by URL and proxy it through Tyk with authentication and governance. * **Tyk API**: [convert an existing Tyk OAS API into an MCP proxy](/docs/ai-management/mcps/api-to-mcp). Operations from its OpenAPI spec become MCP tools. Create MCP Proxy choice screen Each choice opens a different wizard. ### Remote MCP server This wizard collects the minimum information needed to proxy an existing MCP server. It has three steps. #### Step 1: Basic info | Field | Required | What it sets | | - | - | - | | **Name** | Yes | Display name for the proxy. Also used to identify it in policy and key configuration. Maps to `x-tyk-api-gateway.info.name`. | | **Description** | No | Free-text description for team reference. Maps to `info.description`. | The name must be unique across all MCP proxies in this Dashboard instance. Click **Continue** to proceed. Create MCP proxy, step 1: basic information #### Step 2: MCP server details | Field | Required | What it sets | | - | - | - | | **Enter MCP server URL** | Yes | The full URL where your upstream MCP server is accessible. Tyk forwards all MCP traffic to this address. Maps to `x-tyk-api-gateway.upstream.url`. | Enter the full URL of your upstream MCP server, for example `https://weather-mcp.example.com/mcp`. This is the server Tyk proxies to, not the URL clients use to connect to Tyk. Click **Continue** to proceed. Create MCP proxy, step 2: register server #### Step 3: Connect your gateways | Field | Required | What it sets | | - | - | - | | **Deployment targets** | No | One or more gateway tags to deploy this proxy to. If left blank and the status is **Active**, Tyk deploys the proxy to all gateways. | | **MCP proxy Status** | Yes | The initial status of the proxy: **Active** or **Inactive**. | Click **Finish**. The Dashboard opens the MCP Designer. Click **Save MCP Proxy** to create the proxy. The Dashboard displays "MCP proxy successfully created". The wizard creates the proxy with no authentication (keyless access). Before you deploy to production, use the MCP Designer to configure authentication, add per-primitive middleware, or set up OAuth discovery. See the [Settings tab](#settings-tab) and [Primitives tab](#primitives-tab) below. ### Tyk API This wizard generates an MCP proxy directly from a Tyk-managed REST API. It has four steps. #### Step 1: Basic info Same **Name** and **Description** fields as the remote MCP server wizard, above. #### Step 2: Select API Search for the source API by name, ID, or tags. Selecting a row expands a version picker so you can choose which version of the API to expose; the proxy is locked to that version, and switching to a different version later requires creating a new proxy. Only Tyk OAS APIs appear in this list. Tyk Classic API definitions cannot be used to generate MCP proxies. See [Requirements](/docs/ai-management/mcp-gateway/overview#requirements-and-limitations). Click **Continue** to proceed. Create MCP proxy, Select API step #### Step 3: Map endpoints to tools All valid endpoints from the source API's OpenAPI spec are mapped as tools by default. Deselect any endpoint you don't want to expose, following Tyk's [Deny by Default](/docs/api-management/security-best-practices#deny-by-default) guidance: favor building up an explicit allow-list of only the operations an agent needs, rather than leaving every operation exposed. Use the search box and HTTP method filter to narrow the list; the counter shows how many of the total endpoints are currently selected. Mapped tools inherit the source endpoint's name and description. To override a tool's name, description, or parameters, use the **Tool mapping** tab of the MCP Designer after creating the proxy. See [Tool mapping tab](#tool-mapping-tab) below. Click **Continue** to proceed. Create MCP proxy, Map endpoints to tools step #### Step 4: Connect your gateways Unlike the remote MCP server wizard, deployment targets for a REST API to MCP proxy are inherited from the source API and can't be set here. Set the initial **MCP proxy Status** (**Active** or **Inactive**). Click **Finish**. This does not create the proxy immediately: Tyk previews the generated tool catalog and takes you to the MCP Designer with the preview pre-populated. Review the tools on the [Tool mapping tab](#tool-mapping-tab), then click **Save MCP Proxy** to create the proxy. Create MCP proxy, Connect your gateways step The wizard creates the proxy with no authentication (keyless access) by default. Before deploying to production, open the [Settings tab](#settings-tab) to configure an authentication method, or the [Tool mapping tab](#tool-mapping-tab) to rename tools and parameters before saving. *** ## The MCP Designer Clicking a proxy in the list opens the MCP Designer. For a proxy fronting a remote MCP server, the MCP Designer has two tabs: **Settings** and **Primitives**. For a REST API to MCP proxy, the Designer inserts a third tab, **Tool mapping**, between them. MCP Designer, showing the read-only Source API panel on a REST API to MCP proxy ### Settings tab The **Settings** tab covers two areas: core proxy configuration and proxy-level middleware. **Core configuration**: name, upstream server URL, and gateway assignment. For a REST API to MCP proxy, a read-only **Source API** panel replaces the upstream and gateway fields, because the proxy inherits both from the source API. To edit these fields, make your changes and click **Save MCP Proxy**. The Dashboard triggers a gateway reload automatically. **Authentication**: the authentication method applied to all inbound requests. Select a method from the **Authentication type** dropdown. See [Authentication](/docs/api-management/client-authentication) for all supported methods and configuration options. **Proxy-level middleware**: middleware that applies to all requests through this proxy, regardless of which primitive is invoked. The following options are available in the Settings tab: | Middleware | What it does | Maps to | | - | - | - | | **CORS** | Configures cross-origin resource sharing headers for browser-based MCP clients. | `middleware.global.cors` | | **Transform Request Headers** | Adds, removes, or modifies HTTP headers on every request forwarded to the upstream. | `middleware.global.transformRequestHeaders` | | **Transform Response Headers** | Adds, removes, or modifies HTTP headers on every response returned to clients. | `middleware.global.transformResponseHeaders` | | **Context Variables** | Enables Tyk context variables (request metadata such as IP, key ID, and path) for use in header transforms and plugins. | `middleware.global.contextVariables` | | **Traffic Logs** | Configures how request and response data is captured in analytics. Enabled by default on new MCP proxies. | `middleware.global.trafficLogs` | | **Plugin Config / Bundle** | Configures custom plugin drivers and bundle sources for gateway-side plugin execution. | `middleware.global.pluginConfig` | These options map to `x-tyk-api-gateway.middleware.global` in the proxy definition. For full configuration details, see [MCP middleware: proxy level](/docs/ai-management/mcp-gateway/mcp-middleware#dashboard-settings-tab-proxy-level). ### Tool mapping tab The **Tool mapping** tab appears only on REST API to MCP proxies. It lists every operation available from the source API on the left; only the operations you select are exposed as tools on this proxy. A counter shows how many of the total operations are currently exposed, and a search box filters the list. Tool mapping tab, operation list and detail pane Click an operation to open its detail pane and configure: | Field | What it does | | - | - | | **Tool Name** | Overrides the tool's caller-facing name. Defaults to the name Tyk derived from the operation (see [MCP Gateway: Core Concepts](/docs/ai-management/mcp-gateway/core-concepts#tool-naming-and-discovery)). | | **Tool Description** | Overrides the tool's caller-facing description. | | **Parameters table** | Lists the operation's path, query, header, and body parameters (Name, In, Required, Description). Each parameter has an inline editor to override its caller-facing name and description, which is useful for improving how an LLM interprets the tool, or for resolving a parameter name collision. Leave a field blank to use the original name or description. | The checkbox next to each operation in the left-hand list controls whether it's exposed: checking it adds the operation as a tool, unchecking it hides the tool without deleting your name, description, or parameter overrides. The detail pane shows an **Exposed** or **Hidden** pill reflecting this state. Click **Save MCP Proxy** to apply your changes. These map to `x-tyk-mcp-server.primitives[]` in the proxy definition. See [REST API to MCP x-tyk-mcp-server extension](/docs/ai-management/mcp-gateway/api-to-mcp-definitions) for the full field reference. ### Primitives tab The **Primitives** tab lists every tool, resource, and prompt you have manually registered for this proxy. Each entry shows the primitive's name, its type (Tool, Resource, or Prompt), and the number of middleware rules applied to it. Use the type filter and search input to narrow the list. **Adding a primitive** Click **Add Primitive** to open the add primitive modal. Select the type (Tool, Resource, or Prompt) and enter the primitive name: this must match the name the upstream MCP server uses when advertising that primitive. Names cannot contain whitespace and must be unique within their type. Adding a primitive creates an entry in `x-tyk-api-gateway.middleware.mcpTools`, `mcpResources`, or `mcpPrompts` (depending on type) in the proxy definition. **Adding middleware to a primitive** Click a primitive to open its detail view, then click **Add Middleware**. The following middleware is available for primitives: | Middleware | Maps to | | - | - | | **Required Scopes** | `security` and `scopeCheck` | | **Token Exchange** | `exchange` | | **Allow list** | `allow` | | **Block list** | `block` | | **Rate limit** | `rateLimit` | | **Ignore authentication** | `ignoreAuthentication` | | **Request size limit** | `requestSizeLimit` | | **Virtual endpoint** | `virtualEndpoint` | | **Go post-plugin** | `postPlugins` | | **Circuit breaker** | `circuitBreaker` | | **Enforce timeout** | `enforceTimeout` | | **Do not track** | `doNotTrackEndpoint` | | **Track** | `trackEndpoint` | | **Request header transform** | `transformRequestHeaders` | | **Response header transform** | `transformResponseHeaders` | Each middleware option maps to the corresponding configuration block inside the primitive's entry in the proxy definition. See [MCP middleware](/docs/ai-management/mcp-gateway/mcp-middleware) for what each option does and how it is configured. *** ## Editing the full definition The Dashboard UI covers most proxy configuration. To access advanced options not yet exposed in the UI, such as upstream OAuth, per-primitive token exchange overrides, and traffic management, edit the proxy's underlying definition directly. Open the editor via **Actions → View MCP Proxy Definition** on the MCP Designer. View MCP Proxy Definition The MCP proxy definition is an OpenAPI document with an `x-tyk-api-gateway` vendor extension containing all Tyk-specific configuration. The key sections are: | Section | What it configures | | - | - | | `x-tyk-api-gateway.server.authentication` | Authentication method (bearer token, JWT, OAuth, mTLS) and settings. | | `x-tyk-api-gateway.server.authentication.securitySchemes[name].oauth2.protectedResourceMetadata` | PRM for OAuth 2.1 discovery: the `/.well-known/oauth-protected-resource` endpoint. | | `x-tyk-api-gateway.upstream` | Upstream URL, load balancing, upstream authentication, and mTLS. For a REST API to MCP proxy, `upstream.url` holds an adapter target (for example `tyk://a1b2c3d4e5f647a8b9c0d1e2f3a4b5c6/mcp`) instead of a remote `https://` URL. See [The upstream adapter target](/docs/ai-management/mcp-gateway/api-to-mcp-definitions#the-upstream-adapter-target). | | `x-tyk-mcp-server` | REST API to MCP proxies only. Holds the tool catalog: which source operations are exposed, and any name, description, or parameter overrides. See [REST API to MCP x-tyk-mcp-server extension](/docs/ai-management/mcp-gateway/api-to-mcp-definitions). | | `x-tyk-api-gateway.middleware.mcpTools` | Per-tool middleware: access control, rate limits, timeouts, circuit breakers, request transformation. | | `x-tyk-api-gateway.middleware.mcpResources` | Per-resource middleware: same options as tools, keyed by resource URI or URI pattern. Not used by REST API to MCP proxies, since REST APIs have no resource or prompt primitives. | | `x-tyk-api-gateway.middleware.mcpPrompts` | Per-prompt middleware: same options as tools, keyed by prompt name. Not used by REST API to MCP proxies. | | `x-tyk-api-gateway.middleware.operations` | Method-level middleware applying to all calls of a given JSON-RPC method. | | `x-tyk-api-gateway.middleware.global` | API-wide middleware applying to all requests. | After editing, click **Save MCP Proxy** to save and redeploy. Changes are applied to all connected gateways automatically. ### Common edits after initial setup **Configuring authentication**: The wizard creates the proxy with no authentication (keyless access). To set a method, open the Settings tab and select from the **Authentication type** dropdown. To use the external IdP integration, which includes scope check, PRM, and token exchange, select **OAuth 2.0**. See [Authentication](/docs/api-management/client-authentication) for all supported methods. **Enabling PRM for OAuth discovery**: Open the Settings tab, select **OAuth 2.0** as the authentication type, and enable the **Protected Resource Metadata** toggle. Set the resource URL and add at least one authorization server URL. See [OAuth 2.0 authentication](/docs/api-management/authentication/oauth2-authentication) for full configuration details. **Restricting which tools clients can call**: Use the Primitives tab: add the tool as a primitive, then add **Allow list** middleware to it. For how allowlist mode works, see [MCP middleware: access control](/docs/ai-management/mcp-gateway/mcp-middleware#access-control). **Applying rate limits to a specific tool**: Use the Primitives tab: open the tool primitive and add **Rate limit** middleware. For definition-based configuration, see [MCP middleware: traffic management](/docs/ai-management/mcp-gateway/mcp-middleware#traffic-management). **Configuring upstream OAuth**: Add an `authentication.oauth.clientCredentials` block to `x-tyk-api-gateway.upstream` to have Tyk obtain and forward OAuth tokens to your upstream MCP server. See [MCP Gateway: OAuth 2.1 authentication](/docs/ai-management/mcp-gateway/oauth-2-1#upstream-oauth). **Adding CORS or global header transforms**: Configure these in the Settings tab under the middleware section. Changes apply to all requests through the proxy. For a complete explanation of every field in the definition, see [MCP proxy definition](/docs/ai-management/mcp-gateway/mcp-proxy-definitions). *** ## Delete an MCP proxy 1. In the sidebar, click **MCP**. 2. Open the proxy you want to delete. 3. Click **Actions → Delete MCP Proxy** and confirm. Deletion removes the proxy definition from the Dashboard and undeploys it from all connected gateways. Associated API keys and policies are not removed automatically; remove the access right from any keys scoped to this proxy, or delete those keys separately. Deleting an MCP proxy also removes it from any versioning hierarchy it belongs to. If the deleted proxy was a versioned child, the version entry is removed from the base proxy's definition. # MCP Gateway Access Logs Source: https://tyk.io/docs/ai-management/mcp-gateway/mcp-access-logs MCP-specific fields available in Tyk Gateway structured access logs, including JSON-RPC method, primitive type, primitive name, and error code. When Tyk Gateway processes an MCP request, it adds four MCP-specific fields to the structured access log record for that request. These fields let you filter, aggregate, and analyze MCP traffic in your log management tooling using the same access log pipeline you use for REST APIs. For an overview of all MCP observability signals, see [MCP observability](/docs/ai-management/mcp-gateway/mcp-observability). ## Prerequisites Access logging must be enabled in your Tyk Gateway configuration. Set `access_logs.enabled` to `true` in `tyk.conf`. See [Enabling Access Logs](/docs/api-management/logs/access-logs#enabling-access-logs). ## MCP fields The following fields are added to access log records for MCP requests. Each field is only included when it has a non-empty value; fields are omitted from the record entirely when not applicable. | Field | Type | Description | | - | - | - | | `api_type` | string | API protocol type. Always `mcp` for MCP requests. | | `mcp_method` | string | JSON-RPC method invoked, for example `tools/call` or `resources/read`. Present on all MCP requests. | | `mcp_primitive_type` | string | MCP primitive category: `tool`, `resource`, or `prompt`. Present only when a primitive was matched. | | `mcp_primitive_name` | string | Name of the specific tool, resource, or prompt invoked, for example `get_current_weather`. Present only when a primitive was matched. | | `mcp_error_code` | integer | Gateway-mapped JSON-RPC error code. Present only when the request failed at the gateway layer. Omitted when there is no error. | The `mcp_error_code` field reflects errors that occur within the gateway: authentication failures, rate limit rejections, and upstream errors. It never carries error codes from within the upstream MCP server's JSON-RPC response body. A gateway error always has a `4xx` or `5xx` HTTP status, never `200`. Tyk maps the HTTP status of a gateway error to a JSON-RPC error code: | Error code | HTTP status | Meaning | | - | - | - | | `-32700` | `400` | Parse error: the request body is not valid JSON | | `-32600` | `400`, `405` | Invalid request | | `-32601` | `404` | Method not found | | `-32602` | `400` | Invalid params: Tyk could not read the primitive name from `params` | | `-32603` | `500` and other `5xx` | Internal error | | `-32000` | Other `4xx` | Other client error | | `-32001` | `401` | Authentication required | | `-32002` | `403` | Access denied | | `-32003` | `429` | Rate limit exceeded | | `-32004` | `502`, `503`, `504` | Upstream error | The codes `-32005` and `-32006` are reserved. Tyk does not currently return them. ## Access logs when the proxy fronts a Tyk-managed REST API When an MCP proxy is [generated directly from a Tyk-managed REST API](/docs/ai-management/mcps/api-to-mcp) rather than fronting a remote MCP server, a single `tools/call` request produces two separate access log entries when access logs are enabled on the Gateway. The first entry is for the MCP proxy request itself, and carries the MCP fields described above. The second is for Tyk's internal call into the paired source REST API, dispatched through the gateway's standard request handling. That second entry has no MCP fields at all: its `api_type` reflects the source API's own type (`oas` for a Tyk OAS API), and it is otherwise indistinguishable from a request made directly against that API. ```json expandable theme={null} { "api_id": "orders-mcp", "api_name": "Orders MCP Proxy", "api_type": "mcp", "client_ip": "10.0.0.42", "latency_total": 187, "method": "POST", "mcp_method": "tools/call", "mcp_primitive_name": "get_order_status", "mcp_primitive_type": "tool", "path": "/mcp", "prefix": "access-log", "status": 200, "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736" } ``` ```json expandable theme={null} { "api_id": "orders-rest", "api_name": "Orders REST API", "api_type": "oas", "client_ip": "10.0.0.42", "latency_total": 142, "method": "GET", "path": "/orders/{id}/status", "prefix": "access-log", "status": 200, "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736" } ``` If [OpenTelemetry tracing](/docs/api-management/traces) is enabled alongside access logging, both entries carry the same `trace_id`: Tyk dispatches the internal call to the source API within the same trace as the originating MCP request, so the two entries are spans of one trace rather than unrelated hits. Without tracing enabled, there is no shared identifier between the two entries, so correlate them by timestamp. The proxy's own `latency_total` includes the time spent on the source API call, so it is always the larger of the two figures. This dual-record pattern isn't unique to access logs. The Dashboard's [MCP analytics](/docs/ai-management/mcp-gateway/mcp-analytics) charts, and the Tyk Pump analytics pipeline underneath them, follow the same rule: only the MCP proxy's own record is recorded as MCP traffic, so the source API's analytics include this internal traffic indistinguishably alongside any direct hits it receives. See [Tyk Pump](/docs/api-management/tyk-pump) for how analytics records are processed and stored. ## Configuring which fields to include By default, each record includes all available fields. To log only some fields, use an access log template. See [Access Log Templates](/docs/api-management/logs/access-logs#access-log-templates). Add `api_type` and the four `mcp_` fields to the template to keep the MCP detail. ## Example log records A successful `tools/call` request produces a record similar to the following: ```json theme={null} { "api_id": "my-weather-mcp", "api_name": "Weather MCP Proxy", "api_type": "mcp", "client_ip": "10.0.0.42", "latency_total": 312, "method": "POST", "mcp_method": "tools/call", "mcp_primitive_name": "get_current_weather", "mcp_primitive_type": "tool", "path": "/mcp", "prefix": "access-log", "status": 200 } ``` A request that fails at the gateway due to a missing or invalid key produces a record with `mcp_error_code` set. Tyk reads the JSON-RPC body before it checks the key, so the record also has the primitive fields: ```json theme={null} { "api_id": "my-weather-mcp", "api_type": "mcp", "client_ip": "10.0.0.42", "latency_total": 4, "method": "POST", "mcp_error_code": -32001, "mcp_method": "tools/call", "mcp_primitive_name": "get_current_weather", "mcp_primitive_type": "tool", "path": "/mcp", "prefix": "access-log", "status": 401 } ``` An `initialize` lifecycle call produces a record with no `mcp_primitive_type`. Its `mcp_primitive_name` is the method name: ```json theme={null} { "api_id": "my-weather-mcp", "api_type": "mcp", "client_ip": "10.0.0.42", "latency_total": 18, "method": "POST", "mcp_method": "initialize", "mcp_primitive_name": "initialize", "path": "/mcp", "prefix": "access-log", "status": 200 } ``` # MCP Analytics Source: https://tyk.io/docs/ai-management/mcp-gateway/mcp-analytics Use the Activity by MCP page in Tyk Dashboard to track traffic and errors for each MCP proxy and for each tool, resource, and prompt. MCP analytics gives you visibility into how your MCP proxies and their primitives are being used, directly in Tyk Dashboard. Analytics are organized at two levels: **proxy-level charts** compare traffic and errors across your MCP proxies, giving you a fleet-wide view; **primitive-level charts** break the data down by individual tool, resource, or prompt, showing exactly what agents are calling and where failures are concentrated. Use the filter bar to scope the view to a specific proxy, primitive type, or time window. This page is populated by [Tyk Pump](/docs/api-management/tyk-pump#dashboard-analytics-pumps), through one of two paths depending on your deployment topology. In a combined control and data plane, the `mongo-mcp-aggregate`/`sql-mcp-aggregate` pump types feed this page directly; see the [Mongo MCP Aggregate Pump](/docs/api-management/dashboard-analytics/control-plane-pumps#mongo-mcp-aggregate-pump) and [SQL MCP Aggregate Pump](/docs/api-management/dashboard-analytics/control-plane-pumps#sql-mcp-aggregate-pump) sections of Control Plane Pumps for installation and configuration. In a distributed deployment with Tyk MDCB, the Hybrid Pump has its own dedicated path; see [MCP Proxy Traffic](/docs/api-management/dashboard-analytics/data-plane-pump#mcp-proxy-traffic) for how to configure it. Either way, the `mongo-mcp`/`sql-mcp` pumps store MCP traffic logs for your own downstream querying, but don't feed this page. To access the MCP analytics page, your Tyk Dashboard user account must have both `analytics` and `mcp` permissions. ## Navigating to MCP Analytics In the Tyk Dashboard, go to **Monitoring** in the sidebar and select **Activity by MCP**. Activity by MCP ## Filters The filter bar at the top of the page applies to all charts simultaneously. Changing a filter refreshes every chart on the page. Filters | Filter | Description | | - | - | | **MCP Proxy** | Restricts all charts to a single MCP proxy. Defaults to all proxies. | | **Primitive Type** | Filters by primitive type: **Tools**, **Resources**, or **Prompts**. | | **Primitive Name** | Filters by a specific primitive name within the selected type. The field is searchable. | | **Resolution** | Sets the time bucket for chart data: **Hourly**, **Daily**, or **Monthly**. | | **Date range** | Sets the time window for all chart data, in `dd/MM/yyyy` format. | When **Primitive Type** is changed, the **Primitive Name** filter resets to show all primitives of the new type. ## Proxy-Level Charts The charts in this section aggregate activity at the proxy level. Use them to compare traffic and error rates across your MCP proxies and identify which ones need attention. ### Activity per MCP A line chart showing hit count over time, with one line per MCP proxy. Use this chart to compare traffic volumes across proxies and identify usage trends. A proxy with disproportionately high traffic is a good candidate for tighter rate limits; a sudden spike may indicate a misbehaving client. Activity per MCP ### Errors by MCP A stacked bar chart showing error count over time, with bars stacked by MCP proxy. Use this chart to identify which proxies are generating errors and whether spikes correlate with specific time periods. Persistent errors on one proxy suggest a configuration or upstream issue; a brief, time-bounded burst may indicate a client retry loop or a transient upstream outage. Errors by MCP ## Primitive-Level Charts The charts in this section break down activity to the individual primitive level: tools, resources, and prompts. Use them to move from knowing that a proxy has a problem to knowing exactly which tool, resource, or prompt is the cause. ### Most Used Primitives A horizontal stacked bar chart showing total hits ranked by primitive, highest first. Use this chart to identify which tools, resources, or prompts agents call most frequently. High-volume tools are the best candidates for per-tool rate limits and circuit breaker configuration. Most Used Primitives ### Most Failing Primitives A horizontal stacked bar chart showing total errors ranked by primitive. Use this chart to pinpoint which primitives have the highest failure rates and may require investigation or circuit breaker configuration. Most Failing Primitives ### Slowest Primitives A horizontal stacked bar chart showing average latency in seconds, ranked by primitive. Use this chart to identify performance bottlenecks in your upstream MCP server. Consistently slow tools are good candidates for per-tool timeouts, which prevent a single slow tool from stalling an entire agent session. Slowest Primitives ### Error Status Codes by Primitive A stacked bar chart breaking down HTTP error status codes by primitive. Use this chart to diagnose the type of errors occurring at the primitive level and determine whether failures are originating at the gateway or the upstream MCP server. Error Status Codes by Primitive Analytics data is only recorded for MCP proxies that have analytics recording enabled. If charts show no data for a proxy, verify that analytics recording is configured correctly for that proxy. # MCP API extensions Source: https://tyk.io/docs/ai-management/mcp-gateway/mcp-api-extensions Reference for the MCP proxy endpoints in the Tyk Gateway API and Tyk Dashboard API: CRUD operations, versioning, response shapes, and validation. Tyk extends both the Tyk Gateway API and the Tyk Dashboard API with a dedicated set of endpoints for managing MCP OAS definitions. These endpoints are separate from the standard OAS API endpoints. MCP proxies are stored and managed through their own resource paths and are excluded from the standard `/tyk/apis` and `/api/apis` listings. For the full OpenAPI specifications of the Gateway API and Dashboard API, see [Tyk APIs](/docs/tyk-apis). *** ## Tyk Gateway API extensions The Tyk Gateway API is the admin interface exposed directly by Tyk Gateway. MCP management endpoints are accessible at `/tyk/mcps` and require the gateway's admin secret in the `X-Tyk-Authorization` header. Changes made via the Gateway API take effect only after a gateway reload. The MCP endpoints write the proxy definition to disk and return immediately; they do not trigger an automatic reload. **Authentication**: `X-Tyk-Authorization: {gateway-secret}` **Base URL**: `{gateway-host}` (typically `http://localhost:8080`) *** ### List MCP proxies Returns all MCP OAS definitions loaded on this gateway instance. Standard Tyk OAS APIs are excluded from this response. | Property | Value | | - | - | | Method | `GET` | | URL | `/tyk/mcps` | | Auth | `X-Tyk-Authorization` | | Request body | None | | Query parameters | None | **Response**: `200 OK` ```json theme={null} [ { "openapi": "3.0.3", "info": { "title": "Weather MCP proxy", "version": "2025-11-25" }, "paths": { ... }, "x-tyk-api-gateway": { ... } } ] ``` An empty array is returned if no MCP proxies are configured. *** ### Get an MCP proxy Returns the full Tyk OAS API definition for a single MCP proxy. | Property | Value | | - | - | | Method | `GET` | | URL | `/tyk/mcps/{apiID}` | | Auth | `X-Tyk-Authorization` | | Request body | None | **Path parameters** | Parameter | Description | | - | - | | `apiID` | The API ID of the MCP proxy to retrieve. | **Query parameters** | Parameter | Required | Description | | - | - | - | | `expand` | No | Set to `true` to add the generated tool fields to each `x-tyk-mcp-server` entry of a REST API to MCP proxy. See [Compact and Expanded Shapes](/docs/ai-management/mcp-gateway/api-to-mcp-definitions#compact-and-expanded-shapes). Available from Tyk 5.15.0. | **Response headers** | Header | Description | | - | - | | `X-Tyk-Base-API-ID` | Present only when the retrieved proxy is a versioned child. Contains the API ID of the base (parent) proxy. | **Response**: `200 OK` ```json theme={null} { "openapi": "3.0.3", "info": { "title": "Weather MCP proxy", "version": "2025-11-25" }, "paths": { ... }, "x-tyk-api-gateway": { "info": { "id": "weather-mcp-api", "name": "Weather MCP proxy", "state": { "active": true } }, "server": { "listenPath": { "value": "/weather-mcp/", "strip": true } }, "upstream": { "url": "https://weather-mcp.example.com" } } } ``` **Error responses** | Status | Condition | | - | - | | `400 Bad Request` | The `apiID` value fails path component validation (for example, contains path traversal sequences). | | `404 Not Found` | No API exists with the given ID, or the API exists but is not an MCP proxy. | *** ### Create an MCP proxy Creates a new MCP proxy from a Tyk OAS API definition. The request body must be a valid OpenAPI 3.0.x or 3.1.x document containing an `x-tyk-api-gateway` extension. | Property | Value | | - | - | | Method | `POST` | | URL | `/tyk/mcps` | | Auth | `X-Tyk-Authorization` | | Content-Type | `application/json` | | Request body | Tyk OAS MCP definition | **Query parameters** | Parameter | Required | Description | | - | - | - | | `base_api_id` | No | The API ID of an existing MCP proxy to create this definition as a version of. If provided, `version_name` is also required. | | `version_name` | No | The version identifier for the new proxy (for example, `v2`). Required when `base_api_id` is specified. | | `set_default` | No | Set to `true` to make the new version the default version of the base proxy. Only applies when `base_api_id` is specified. | | `dryRun` | No | Set to `true` to validate the definition and return it without saving it. Available from Tyk 5.15.0. | | `expand` | No | Used with `dryRun=true`. Set to `true` to return the generated tool fields for a REST API to MCP proxy, so you can preview the tools before you save. See [Compact and Expanded Shapes](/docs/ai-management/mcp-gateway/api-to-mcp-definitions#compact-and-expanded-shapes). | **Request body**: Minimum viable MCP proxy definition ```json theme={null} { "openapi": "3.0.3", "info": { "title": "Weather MCP proxy", "version": "2025-11-25" }, "paths": { "/mcp": { "post": { "operationId": "mcpTransportPost", "responses": { "200": { "description": "JSON-RPC response" } } }, "get": { "operationId": "mcpSSEGet", "responses": { "200": { "description": "SSE stream" } } } } }, "x-tyk-api-gateway": { "info": { "name": "Weather MCP proxy", "state": { "active": true } }, "server": { "listenPath": { "value": "/weather-mcp/", "strip": true }, "authentication": { "enabled": true } }, "upstream": { "url": "https://weather-mcp.example.com" } } } ``` If no `id` is provided in `x-tyk-api-gateway.info`, the gateway generates one. **Response**: `200 OK` ```json theme={null} { "key": "weather-mcp-api", "status": "ok", "action": "added" } ``` **Error responses** | Status | Condition | | - | - | | `400 Bad Request` | Request body is not valid JSON, `x-tyk-api-gateway` extension is missing, the definition fails MCP schema validation, or OAS structure validation fails. | | `422 Unprocessable Entity` | Versioning parameters are invalid: for example, `base_api_id` refers to an API that does not exist or is not an MCP proxy. | *** ### Update an MCP proxy Replaces the definition of an existing MCP proxy in full. Partial updates are not supported; provide the complete Tyk OAS API definition in the request body. | Property | Value | | - | - | | Method | `PUT` | | URL | `/tyk/mcps/{apiID}` | | Auth | `X-Tyk-Authorization` | | Content-Type | `application/json` | | Request body | Complete Tyk OAS MCP definition | The `x-tyk-api-gateway.info.id` field in the request body must match the `{apiID}` path parameter. A mismatch returns `400 Bad Request`. **Response**: `200 OK` ```json theme={null} { "key": "weather-mcp-api", "status": "ok", "action": "modified" } ``` **Error responses** | Status | Condition | | - | - | | `400 Bad Request` | Invalid API ID, malformed request body, API ID mismatch between URL and body, the API is not an MCP proxy, or validation fails. | | `404 Not Found` | No API exists with the given ID. | *** ### Delete an MCP proxy Removes an MCP proxy definition from the gateway. | Property | Value | | - | - | | Method | `DELETE` | | URL | `/tyk/mcps/{apiID}` | | Auth | `X-Tyk-Authorization` | | Request body | None | If the deleted proxy is a versioned child, its entry is removed from the base proxy's version map. If it is a base proxy with existing versions, those children remain but lose their parent reference. **Response**: `200 OK` ```json theme={null} { "key": "weather-mcp-api", "status": "ok", "action": "deleted" } ``` **Error responses** | Status | Condition | | - | - | | `400 Bad Request` | Invalid API ID, or the API exists but is not an MCP proxy. | | `404 Not Found` | No API exists with the given ID. | | `500 Internal Server Error` | The definition files could not be deleted from disk. | *** ### Hot reload Changes made via the Gateway API are written to disk but are not applied to live traffic until the gateway reloads. After any create, update, or delete operation, issue a reload: ```bash theme={null} # Reload all gateway instances in the group GET /tyk/reload/group # Reload this gateway instance only GET /tyk/reload ``` Both endpoints require the `X-Tyk-Authorization` header. *** ## Tyk Dashboard API extensions The Tyk Dashboard API is the management interface exposed by Tyk Dashboard. It proxies operations to connected gateway instances and triggers reloads automatically, so you don't need to issue a manual reload after Dashboard API operations. The Dashboard API accepts both JSON and YAML request bodies for create and update operations. **Authentication**: Dashboard user API key (retrieved from your user profile in the Dashboard) **Base URL**: `{dashboard-host}` (typically `http://localhost:3000`) *** ### List MCP proxies Returns all MCP proxies managed by this Dashboard instance, with pagination metadata. | Property | Value | | - | - | | Method | `GET` | | URL | `/api/mcps` | | Auth | `Authorization: {dashboard-api-key}` | | Request body | None | | Query parameters | None | **Response**: `200 OK` ```json theme={null} { "mcps": [ { "openapi": "3.0.3", "info": { "title": "Weather MCP proxy", ... }, "x-tyk-api-gateway": { ... } } ], "pages": 1 } ``` The `pages` field contains the total number of pages available. *** ### Get an MCP proxy Returns the full Tyk OAS API definition for a single MCP proxy. | Property | Value | | - | - | | Method | `GET` | | URL | `/api/mcps/{apiId}` | | Auth | `Authorization: {dashboard-api-key}` | | Request body | None | **Query parameters** | Parameter | Required | Description | | - | - | - | | `expand` | No | Set to `true` to add the generated tool fields to each `x-tyk-mcp-server` entry of a REST API to MCP proxy. See [Compact and Expanded Shapes](/docs/ai-management/mcp-gateway/api-to-mcp-definitions#compact-and-expanded-shapes). Available from Tyk 5.15.0. | **Response**: `200 OK` Returns the full Tyk OAS API definition. See [Get an MCP proxy: Gateway API](#get-an-mcp-proxy) for the response shape. **Error responses** | Status | Condition | | - | - | | `400 Bad Request` | The API exists but is not an MCP proxy. | | `404 Not Found` | No API exists with the given ID. | *** ### Create an MCP proxy Creates a new MCP proxy from a Tyk OAS API definition. The Dashboard API accepts both JSON and YAML. | Property | Value | | - | - | | Method | `POST` | | URL | `/api/mcps` | | Auth | `Authorization: {dashboard-api-key}` | | Content-Type | `application/json` or `application/x-yaml` | | Request body | Tyk OAS MCP definition | **Query parameters** | Parameter | Required | Description | | - | - | - | | `base_api_id` | No | The API ID of an existing MCP proxy to create this definition as a version of. The base API must exist and must itself be an MCP proxy. | | `dryRun` | No | Set to `true` to validate the definition and return it without saving it. Available from Tyk 5.15.0. | | `expand` | No | Used with `dryRun=true`. Set to `true` to return the generated tool fields for a REST API to MCP proxy, so you can preview the tools before you save. See [Compact and Expanded Shapes](/docs/ai-management/mcp-gateway/api-to-mcp-definitions#compact-and-expanded-shapes). | **Example request** ```bash theme={null} curl -X POST ${DASH_URL}/api/mcps \ -H "Authorization: ${DASH_KEY}" \ -H "Content-Type: application/json" \ -d '{ "openapi": "3.0.3", "info": { "title": "Weather MCP proxy", "version": "2025-11-25" }, "paths": { "/mcp": { "post": { "operationId": "mcpTransportPost", "responses": { "200": { "description": "JSON-RPC response" } } }, "get": { "operationId": "mcpSSEGet", "responses": { "200": { "description": "SSE stream" } } } } }, "x-tyk-api-gateway": { "info": { "name": "Weather MCP proxy", "state": { "active": true } }, "server": { "listenPath": { "value": "/weather-mcp/", "strip": true }, "authentication": { "enabled": true } }, "upstream": { "url": "https://weather-mcp.example.com" } } }' ``` **Response**: `200 OK` ```json theme={null} { "Status": "OK", "Message": "API created", "Meta": "weather-mcp-api-id" } ``` The Dashboard triggers a gateway reload automatically. The proxy is active as soon as the response is returned. **Error responses** | Status | Condition | | - | - | | `400 Bad Request` | Validation failed, `base_api_id` refers to a non-existent or non-MCP proxy, or the definition is structurally invalid. | | `500 Internal Server Error` | An internal processing error occurred. | *** ### Update an MCP proxy Replaces the definition of an existing MCP proxy in full. | Property | Value | | - | - | | Method | `PUT` | | URL | `/api/mcps/{apiId}` | | Auth | `Authorization: {dashboard-api-key}` | | Content-Type | `application/json` or `application/x-yaml` | | Request body | Complete Tyk OAS MCP definition | **Example request** ```bash theme={null} curl -X PUT ${DASH_URL}/api/mcps/{apiID} \ -H "Authorization: ${DASH_KEY}" \ -H "Content-Type: application/json" \ -d '{ "openapi": "3.0.3", "info": { "title": "Weather MCP proxy", "version": "2025-11-25" }, "paths": { ... }, "x-tyk-api-gateway": { "info": { "id": "{apiID}", "name": "Weather MCP proxy", "state": { "active": true } }, "server": { "listenPath": { "value": "/weather-mcp/", "strip": true }, "authentication": { "enabled": true } }, "upstream": { "url": "https://weather-mcp-v2.example.com" } } }' ``` **Response**: `200 OK` ```json theme={null} { "Status": "OK", "Message": "API updated", "Meta": "{apiID}" } ``` The Dashboard triggers a gateway reload automatically. **Error responses** | Status | Condition | | - | - | | `400 Bad Request` | The API is not an MCP proxy, or validation fails. | | `404 Not Found` | No API exists with the given ID. | *** ### Delete an MCP proxy Removes an MCP proxy and triggers a gateway reload. | Property | Value | | - | - | | Method | `DELETE` | | URL | `/api/mcps/{apiId}` | | Auth | `Authorization: {dashboard-api-key}` | | Request body | None | **Example request** ```bash theme={null} curl -X DELETE ${DASH_URL}/api/mcps/{apiID} \ -H "Authorization: ${DASH_KEY}" ``` **Response**: `200 OK` ```json theme={null} { "Status": "OK", "Message": "API deleted", "Meta": "{apiID}" } ``` The Dashboard triggers a gateway reload automatically. **Error responses** | Status | Condition | | - | - | | `400 Bad Request` | The API exists but is not an MCP proxy. | | `404 Not Found` | No API exists with the given ID. | *** ### List versions of an MCP proxy Returns all versioned children of a base MCP proxy. | Property | Value | | - | - | | Method | `GET` | | URL | `/api/mcps/{apiId}/versions` | | Auth | `Authorization: {dashboard-api-key}` | | Request body | None | The `{apiId}` must refer to a base proxy, not a versioned child. Calling this endpoint on a child proxy returns `422 Unprocessable Entity`. **Response**: `200 OK` ```json theme={null} { "apis": [ { "apiId": "weather-mcp-v2", "name": "Weather MCP proxy v2" } ], "pages": 1 } ``` **Error responses** | Status | Condition | | - | - | | `400 Bad Request` | The API exists but is not an MCP proxy. | | `422 Unprocessable Entity` | The API does not exist, is not in OAS format, or is itself a versioned child rather than a base proxy. | *** ### Get the MCP definition schema Returns the JSON Schema that Tyk uses to validate MCP OAS definitions. Use this to validate definitions client-side before submitting them to the API. | Property | Value | | - | - | | Method | `GET` | | URL | `/api/schemas/apidefs/mcp` | | Auth | `Authorization: {dashboard-api-key}` | | Request body | None | **Query parameters** | Parameter | Required | Description | | - | - | - | | `mcpVersion` | No | OAS version to return the schema for. Accepts `3.0` or `3.1`. Defaults to `3.0`. | | `pretty` | No | Set to `true` to return the schema with indented formatting. | **Response**: `200 OK` Returns a JSON Schema document describing the valid structure of a Tyk OAS MCP definition. *** ## Policy API extensions MCP policies are managed through the standard Tyk policy endpoints; there are no dedicated MCP policy routes. The existing endpoints accept and validate MCP-specific fields inside each `access_rights` entry. Tyk validates that these fields are only used on policies whose access rights target MCP proxies. For a conceptual explanation of what the policy fields do and how to configure access tiers, see [MCP proxy policies](/docs/ai-management/mcp-gateway/policies). *** ### Gateway API **Authentication**: `X-Tyk-Authorization: {gateway-secret}` | Operation | Method | URL | | - | - | - | | List policies | `GET` | `/policies` | | Get a policy | `GET` | `/policies/{polID}` | | Create a policy | `POST` | `/policies` | | Update a policy | `PUT` | `/policies/{polID}` | | Delete a policy | `DELETE` | `/policies/{polID}` | **Success responses** | Operation | Status | Body | | - | - | - | | List / Get | `200 OK` | Policy object or array | | Create | `200 OK` | `{"key": "{polID}", "status": "ok", "action": "added"}` | | Update | `200 OK` | `{"key": "{polID}", "status": "ok", "action": "modified"}` | | Delete | `200 OK` | `{"key": "{polID}", "status": "ok", "action": "deleted"}` | *** ### Dashboard API **Authentication**: `Authorization: {dashboard-api-key}` | Operation | Method | URL | | - | - | - | | List policies | `GET` | `/api/portal/policies` | | Get a policy | `GET` | `/api/portal/policies/{polID}` | | Create a policy | `POST` | `/api/portal/policies` | | Update a policy | `PUT` | `/api/portal/policies/{polID}` | | Delete a policy | `DELETE` | `/api/portal/policies/{polID}` | The Dashboard API triggers a gateway reload automatically on create, update, and delete. The Gateway API requires a manual reload via `/tyk/reload` or `/tyk/reload/group`. *** ### MCP-specific fields in access rights The MCP-specific fields (`mcp_access_rights`, `json_rpc_methods_access_rights`, `mcp_primitives`, and `json_rpc_methods`) sit inside each entry in the `access_rights` object. For the field reference, see [Policy schema for MCP](/docs/ai-management/mcp-gateway/policies#policy-schema-for-mcp). *** ### Example policy request The following creates a policy that restricts a consumer to read-only JSON-RPC methods, limits them to two specific tools, and applies a per-primitive rate limit: ```json theme={null} { "name": "Weather Agent Standard Tier", "state": "active", "rate": 1000, "per": 60, "quota_max": 50000, "quota_renewal_rate": 86400, "access_rights": { "{mcp-proxy-api-id}": { "api_id": "{mcp-proxy-api-id}", "api_name": "Weather MCP Proxy", "versions": ["Default"], "limit": { "rate": 200, "per": 60 }, "json_rpc_methods_access_rights": { "allowed": ["tools/call", "tools/list", "resources/list", "resources/read"] }, "mcp_access_rights": { "tools": { "allowed": ["get_forecast", "search_weather"] }, "resources": { "blocked": ["internal://.*"] }, "prompts": {} }, "json_rpc_methods": [ { "name": "tools/call", "limit": { "rate": 100, "per": 60 } } ], "mcp_primitives": [ { "type": "tool", "name": "get_forecast", "limit": { "rate": 20, "per": 60 } }, { "type": "resource", "name": "weather://current", "limit": { "rate": 10, "per": 60 } } ] } } } ``` *** ### Policy validation for MCP When a policy is created or updated, Tyk validates the MCP-specific fields: * **MCP fields on non-MCP APIs**: if `mcp_primitives`, `mcp_access_rights`, `json_rpc_methods`, or `json_rpc_methods_access_rights` are set against an API ID that is not an MCP proxy, the request is rejected with `400 Bad Request`. * **REST fields on MCP proxies**: fields specific to REST APIs (`allowed_urls`, `endpoints`, `field_access_rights`) are rejected when set against an MCP proxy ID. * **Primitive type values**: the `type` field in each `mcp_primitives` entry must be `tool`, `resource`, or `prompt`. Any other value is rejected. *** ## MCP proxy isolation MCP proxies are managed separately from standard Tyk OAS APIs throughout the API surface: * `GET /tyk/apis` and `GET /api/apis` do not include MCP proxies in their responses. * `GET /tyk/mcps` and `GET /api/mcps` only return MCP proxies; standard OAS APIs do not appear. * Create and update operations on `/tyk/mcps` or `/api/mcps` reject definitions that are not valid MCP proxies. * Get and delete operations on `/tyk/mcps/{id}` or `/api/mcps/{id}` return `404` or `400` if the API ID refers to a non-MCP definition. This separation ensures that MCP proxy configuration and standard API configuration cannot be accidentally cross-applied. *** ## Validation Both APIs apply the same validation rules when creating or updating an MCP proxy. ### Required structure Every MCP proxy definition must be a valid OpenAPI 3.0.x or 3.1.x document containing an `x-tyk-api-gateway` vendor extension at the root level. Definitions without this extension are rejected with `400 Bad Request`. ### MCP schema validation The definition is validated against Tyk's MCP JSON schema. This schema enforces the structure of the `x-tyk-api-gateway` extension for MCP proxies (including the `mcpTools`, `mcpResources`, and `mcpPrompts` middleware maps) before any further processing. ### Authentication metadata If `x-tyk-api-gateway.server.authentication.securitySchemes[name].oauth2.protectedResourceMetadata` is present and enabled, Tyk validates the PRM configuration. For MCP proxies specifically, at least one entry in `authorizationServers` is required. ### Middleware restrictions Some middleware options are silently ignored when configured on MCP primitives (entries in `mcpTools`, `mcpResources`, or `mcpPrompts`). The schema accepts these fields for forward compatibility, but Tyk does not apply them at runtime: | Middleware | Reason | | - | - | | `transformRequestMethod` | Changing the HTTP method is not applicable to MCP's fixed POST/GET transport. | | `transformResponseBody` | MCP responses must be returned unmodified to preserve JSON-RPC 2.0 protocol compliance. | | `urlRewrite` | URL rewriting conflicts with MCP's single-endpoint transport (`/mcp`). | | `cache` | Cache keys are derived from the URL path, which is identical for all MCP requests (`/mcp`). | | `mockResponse` | Mock responses are incompatible with MCP's streaming JSON-RPC transport. | Global middleware settings that are also not supported for MCP OAS definitions: | Setting | Reason | | - | - | | `server.batchProcessing` | Batch HTTP processing is incompatible with the MCP transport model. | | `middleware.global.cache` | Caching is not supported for MCP APIs. Neither global nor per-primitive `cache` middleware has any effect on MCP traffic. | *** ## Gateway API vs Dashboard API | Aspect | Gateway API (`/tyk/mcps`) | Dashboard API (`/api/mcps`) | | - | - | - | | **Authentication** | `X-Tyk-Authorization: {secret}` header | `Authorization: {api-key}` header | | **Content types accepted** | `application/json` | `application/json`, `application/x-yaml` | | **List response format** | JSON array of OAS definitions | `{"mcps": [...], "pages": N}` | | **Reload on change** | Manual: must call `/tyk/reload` or `/tyk/reload/group` | Automatic | | **Versioning parameters** | `base_api_id`, `version_name`, `set_default` | `base_api_id` | | **Version listing** | Not available | `GET /api/mcps/{apiId}/versions` | | **Schema endpoint** | Not available | `GET /api/schemas/apidefs/mcp` | | **Multi-gateway propagation** | Applies to this gateway instance only | Propagates to all connected gateways | # MCP Gateway Metrics Source: https://tyk.io/docs/ai-management/mcp-gateway/mcp-metrics Monitor MCP proxy traffic with OpenTelemetry custom metrics. Includes MCP-specific dimensions and worked examples for common monitoring use cases. When Tyk Gateway proxies MCP traffic, it makes four MCP-specific fields available as `metadata` dimension sources in custom OTel metric instruments. Use these dimensions to monitor tool call volumes, track latency per primitive, classify gateway errors, and correlate usage to individual sessions, all through the same observability infrastructure you use for your REST APIs. For an overview of all MCP observability signals, see [MCP observability](/docs/ai-management/mcp-gateway/mcp-observability). ## MCP fields reference The following fields are derived from the JSON-RPC payload and available as `metadata` dimension sources in custom metrics. | Field | Description | Example values | | - | - | - | | `mcp_method` | JSON-RPC method invoked | `tools/call`, `initialize`, `resources/read`, `prompts/get` | | `mcp_primitive_type` | MCP primitive category | `tool`, `resource`, `prompt` | | `mcp_primitive_name` | Name of the specific tool, resource, or prompt | `get_current_weather`, `search_documents` | | `mcp_error_code` | Gateway-mapped JSON-RPC error code; empty string on success | `-32001` (auth required), `-32002` (access denied), `-32003` (rate limit exceeded), `-32004` (upstream error) | All four fields are populated only for MCP APIs. For non-MCP requests they are empty strings, so existing metric instruments are unaffected. `mcp_error_code` reflects errors mapped by the gateway layer (authentication failures, rate limit rejections, and upstream errors), not error codes in the upstream MCP server's JSON-RPC response body. See [MCP access logs](/docs/ai-management/mcp-gateway/mcp-access-logs) for the full list of gateway error codes. ## Use cases The examples below use Tyk's [custom metrics](/docs/api-management/metrics/custom-metrics) system. Each instrument is a JSON object in the `opentelemetry.metrics.api_metrics` array in `tyk.conf`. ### MCP traffic volume by method Track how many requests each JSON-RPC method receives across all MCP APIs. This shows the distribution of `tools/call`, `initialize`, `resources/read`, and other operations. ```json theme={null} { "name": "tyk.mcp.requests.by_method", "type": "counter", "description": "Request count broken down by MCP JSON-RPC method", "dimensions": [ { "source": "metadata", "key": "mcp_method", "label": "mcp_method", "default": "" }, { "source": "metadata", "key": "api_id", "label": "api_id" } ] } ``` ### Top tools by call volume Identify the most frequently invoked tools, useful for cost attribution and optimization. Add `api_id` to compare usage across multiple MCP backends. ```json theme={null} { "name": "tyk.mcp.tool_calls.total", "type": "counter", "description": "MCP tool invocations by tool name and primitive type", "dimensions": [ { "source": "metadata", "key": "mcp_primitive_name", "label": "tool_name", "default": "" }, { "source": "metadata", "key": "mcp_primitive_type", "label": "primitive_type", "default": "" }, { "source": "metadata", "key": "api_id", "label": "api_id" } ], "filters": { "methods": ["POST"] } } ``` ### Tool execution latency: upstream Measure how long the upstream MCP server takes to respond per tool. Use this to identify slow tools and performance regressions; this measurement excludes gateway overhead. ```json theme={null} { "name": "tyk.mcp.upstream.duration", "type": "histogram", "description": "Upstream latency per MCP tool", "histogram_source": "upstream", "histogram_buckets": [0.01, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10], "dimensions": [ { "source": "metadata", "key": "mcp_primitive_name", "label": "tool_name", "default": "" }, { "source": "metadata", "key": "api_id", "label": "api_id" } ], "filters": { "methods": ["POST"] } } ``` ### Total request duration with MCP labels Measure end-to-end latency (client → gateway → upstream → client) with MCP labels attached. Compare this with upstream latency to quantify gateway overhead. ```json theme={null} { "name": "tyk.mcp.request.duration", "type": "histogram", "description": "End-to-end latency per MCP tool", "histogram_source": "total", "histogram_buckets": [0.01, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10], "dimensions": [ { "source": "metadata", "key": "mcp_primitive_name", "label": "tool_name", "default": "" }, { "source": "metadata", "key": "mcp_method", "label": "mcp_method", "default": "" }, { "source": "metadata", "key": "api_id", "label": "api_id" } ] } ``` The `histogram_source` field accepts three values: `"upstream"` (upstream server latency only), `"total"` (end-to-end including gateway), and `"gateway"` (gateway processing time only, excluding upstream). Use `"gateway"` to isolate gateway overhead. ### JSON-RPC error classification Count MCP errors by their gateway-mapped JSON-RPC error code. Unlike HTTP errors, MCP errors are typically returned with HTTP 200; `mcp_error_code` is the only reliable way to detect gateway-layer failures. ```json theme={null} { "name": "tyk.mcp.errors.by_code", "type": "counter", "description": "MCP JSON-RPC errors by error code and tool", "dimensions": [ { "source": "metadata", "key": "mcp_error_code", "label": "error_code", "default": "" }, { "source": "metadata", "key": "mcp_primitive_name", "label": "tool_name", "default": "" }, { "source": "metadata", "key": "api_id", "label": "api_id" } ], "filters": { "methods": ["POST"] } } ``` Filter this instrument in your metrics backend to exclude the empty `error_code` value (successful requests), or add a `status_codes` filter if your upstream signals errors via HTTP status. ### Per-session tool usage Correlate tool call volume to individual MCP sessions using the authenticated session alias. Use this to identify heavy users, debug specific sessions, or allocate costs to teams. ```json theme={null} { "name": "tyk.mcp.tool_calls.by_session", "type": "counter", "description": "Tool calls per session and tool", "dimensions": [ { "source": "session", "key": "alias", "label": "session", "default": "unknown" }, { "source": "metadata", "key": "mcp_primitive_name", "label": "tool_name", "default": "" }, { "source": "metadata", "key": "api_id", "label": "api_id" } ], "filters": { "methods": ["POST"] } } ``` `alias` is the human-readable key alias set on the API key or OAuth token. If your sessions are identified differently (for example, via a JWT claim), use the `context` source with the appropriate `jwt_claims_` key instead. ### Multi-API MCP backend comparison Compare performance across multiple MCP backends by including `api_id` alongside tool dimensions. Use this to determine whether the same tool performs differently on different upstream MCP servers. ```json theme={null} { "name": "tyk.mcp.backend.upstream.duration", "type": "histogram", "description": "Upstream latency per tool broken down by MCP backend", "histogram_source": "upstream", "histogram_buckets": [0.05, 0.1, 0.25, 0.5, 1, 2.5, 5], "dimensions": [ { "source": "metadata", "key": "mcp_primitive_name", "label": "tool_name", "default": "" }, { "source": "metadata", "key": "api_id", "label": "api_id" } ] } ``` ### Session efficiency Measure the ratio of productive `tools/call` operations to session lifecycle calls (`initialize`). A low ratio may indicate clients that open sessions but make few tool calls, useful for detecting misconfigured AI clients or idle connections. ```json theme={null} { "name": "tyk.mcp.method.distribution", "type": "counter", "description": "Distribution of MCP method types for session efficiency analysis", "dimensions": [ { "source": "metadata", "key": "mcp_method", "label": "mcp_method", "default": "" }, { "source": "metadata", "key": "api_id", "label": "api_id" } ] } ``` To compute efficiency, query your metrics backend for the ratio of `tools/call` to `initialize` counts: ```promql theme={null} # PromQL: ratio of tool calls to session initializations per API sum by (api_id) (rate(tyk_mcp_method_distribution_total{mcp_method="tools/call"}[5m])) / sum by (api_id) (rate(tyk_mcp_method_distribution_total{mcp_method="initialize"}[5m])) ``` ## Complete configuration example Add the following to `tyk.conf`. This covers all the instruments needed for the [Grafana](https://grafana.com/) dashboard panels: ```json theme={null} { "opentelemetry": { "metrics": { "enabled": true, "api_metrics": [ { "name": "tyk.mcp.requests.total", "type": "counter", "description": "MCP request count by method, tool, API, and session", "dimensions": [ { "source": "metadata", "key": "mcp_method", "label": "mcp_method", "default": "" }, { "source": "metadata", "key": "mcp_primitive_type", "label": "primitive_type", "default": "" }, { "source": "metadata", "key": "mcp_primitive_name", "label": "tool_name", "default": "" }, { "source": "metadata", "key": "mcp_error_code", "label": "error_code", "default": "" }, { "source": "metadata", "key": "api_id", "label": "api_id" }, { "source": "session", "key": "alias", "label": "session", "default": "unknown" } ] }, { "name": "tyk.mcp.upstream.duration", "type": "histogram", "description": "Upstream MCP server latency per tool and API", "histogram_source": "upstream", "histogram_buckets": [0.01, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10], "dimensions": [ { "source": "metadata", "key": "mcp_primitive_name", "label": "tool_name", "default": "" }, { "source": "metadata", "key": "api_id", "label": "api_id" } ] }, { "name": "tyk.mcp.request.duration", "type": "histogram", "description": "End-to-end MCP request latency per tool and API", "histogram_source": "total", "histogram_buckets": [0.01, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10], "dimensions": [ { "source": "metadata", "key": "mcp_primitive_name", "label": "tool_name", "default": "" }, { "source": "metadata", "key": "mcp_method", "label": "mcp_method", "default": "" }, { "source": "metadata", "key": "api_id", "label": "api_id" } ] } ] } } } ``` The `tyk.mcp.requests.total` counter uses 6 dimensions. Keep the total dimension count at 10 or fewer per instrument to stay on the OTel SDK fast path. See [Performance Considerations](/docs/api-management/logs/access-logs#performance-considerations) for guidance. # MCP middleware Source: https://tyk.io/docs/ai-management/mcp-gateway/mcp-middleware Middleware for individual MCP tools, resources, and prompts: access control, rate limits, transforms, circuit breakers, timeouts, and custom plugins. Middleware on an MCP primitive gives you the same control over AI agent traffic that you have over REST API endpoints. You can rate limit an expensive tool, block a sensitive prompt, set a circuit breaker on an unreliable resource, or apply a custom plugin to inspect tool call arguments before they reach the upstream. > For an explanation of how middleware fits into the overall MCP proxy definition structure (the three levels, their evaluation order, and how they interact), see [MCP definitions](/docs/ai-management/mcp-gateway/mcp-proxy-definitions). *** ## Configuration paths Middleware can be configured in three ways, depending on the level at which it applies and whether you are using the Dashboard UI or editing the definition directly. ### Dashboard: Settings tab (proxy level) The **Settings** tab sets proxy-level middleware, which maps to `x-tyk-api-gateway.middleware.global`. For the options, see [Settings tab](/docs/ai-management/mcp-gateway/managing-proxies#settings-tab). ### Dashboard: Primitives tab (primitive level) The **Primitives** tab sets middleware on individual tools, resources, and prompts, which maps to `mcpTools`, `mcpResources`, or `mcpPrompts`. For the options and their fields, see [Primitives tab](/docs/ai-management/mcp-gateway/managing-proxies#primitives-tab). ### MCP definition (all levels) All middleware options (including those not exposed in the Dashboard) can be configured by editing the proxy definition directly. Open the definition editor via **Actions → View MCP Proxy Definition** in the Dashboard, or submit the definition via the API. The following options are only available this way: * `transformRequestBody`: Request body transformation (supported) * `urlRewrite`, `transformRequestMethod`: Accepted by the schema but silently ignored at runtime; they have no effect on MCP primitives. See the warnings in the [request transformation](#request-transformation) section below. * `middleware.operations`: Method-level middleware applying to all calls of a given JSON-RPC method (for example, all `tools/call` requests), evaluated before primitive-level middleware Caching and mock responses are not supported for MCP primitives. The sections below document every option with definition examples. All definition examples apply to the `mcpTools`, `mcpResources`, or `mcpPrompts` maps unless otherwise noted. *** ## How primitive middleware is resolved Middleware for MCP primitives is configured in `x-tyk-api-gateway.middleware` inside one of three maps: * `mcpTools`: Keyed by tool name (the `params.name` value in a `tools/call` request) * `mcpResources`: Keyed by resource URI or URI wildcard pattern (the `params.uri` value in a `resources/read` request) * `mcpPrompts`: Keyed by prompt name (the `params.name` value in a `prompts/get` request) When Tyk receives a `tools/call`, `resources/read`, or `prompts/get` request, it extracts the primitive identifier from the JSON-RPC body, finds the matching entry in the relevant map, and executes the configured middleware before proxying to the upstream. The `middleware.operations` map applies middleware at the JSON-RPC method level rather than the individual primitive level. Method-level middleware evaluates before primitive-level middleware. MCP proxies [generated directly from a Tyk-managed REST API](/docs/ai-management/mcps/api-to-mcp) don't populate MCP Resources or Prompts. *** ## Access control Access control middleware determines which primitives a client is allowed to invoke. It is the most commonly configured middleware for MCP proxies, because MCP servers typically expose more capabilities than you want to make available through the gateway. ### allow The `allow` middleware adds a primitive to an explicit allowlist. When any primitive within a category has `allow` enabled, Tyk switches that entire category into **allowlist mode**: only the explicitly listed primitives are accessible, and all others are rejected with a JSON-RPC error. ```json theme={null} { "middleware": { "mcpTools": { "get-weather": { "allow": { "enabled": true } }, "get-forecast": { "allow": { "enabled": true } } } } } ``` In this example, only `get-weather` and `get-forecast` are accessible. A request to any other tool name returns an error without reaching the upstream. Resources and prompts are unaffected; the three categories are evaluated independently, so allowlisting tools does not restrict resource or prompt access. Allowlist mode is the recommended approach when you have a known set of primitives to expose. It ensures that new tools added to the upstream MCP server are not automatically accessible through the gateway; you must explicitly add them to the allowlist. ### block The `block` middleware explicitly denies access to a primitive. Tyk returns a JSON-RPC error without forwarding the request to the upstream. Use `block` when all primitives should be accessible by default except a specific subset. ```json theme={null} { "middleware": { "mcpTools": { "admin-reset": { "block": { "enabled": true } } } } } ``` If no `allow` rules exist in the category, all primitives are accessible by default. Block rules apply on top of this open default. If `allow` rules are also present, block rules take precedence. ### ignoreAuthentication The `ignoreAuthentication` middleware exempts a primitive from the API's authentication checks, allowing unauthenticated access to that specific primitive while the rest of the API remains protected. ```json theme={null} { "middleware": { "mcpTools": { "server-status": { "ignoreAuthentication": { "enabled": true } } } } } ``` Use this for primitives that need to be publicly accessible (health checks, capability discovery, or public reference data) without requiring a separate unauthenticated API definition. ### scopeCheck The `scopeCheck` middleware enforces OAuth 2.0 scope requirements for a specific primitive. When enabled, Tyk extracts the scopes from the inbound token and checks them against the `security:` declarations for that primitive. Requests where the token does not carry the required scopes are rejected with a `403 Forbidden` and an RFC 6750 `WWW-Authenticate` header describing the missing scopes. ```json theme={null} { "middleware": { "mcpTools": { "read-customer": { "scopeCheck": { "enabled": true } } } } } ``` Scope enforcement for the primitive is governed by two things working together: * The `security:` field on the primitive in the [Tyk vendor extension](/docs/api-management/gateway-config-tyk-oas) — this names which scopes the token must carry. MCP primitives have no OAS path entry, so `security:` is declared in `x-tyk-api-gateway.middleware.mcpTools` (or `mcpResources` / `mcpPrompts`) alongside the other per-primitive middleware: ```json theme={null} { "middleware": { "mcpTools": { "read-customer": { "security": [{ "idpAuth": ["tools:read"] }], "scopeCheck": { "enabled": true } } } } } ``` * The API-level `oauth2.scopeCheck` configuration — `claimNames`, `scopeSource`, and `separator` control how Tyk reads scopes out of the inbound token. Setting `enabled: true` activates scope enforcement for this primitive only. Other primitives are unaffected unless they also declare `scopeCheck: { "enabled": true }`. Omitting the block or setting `enabled: false` means this primitive's own `security:` declaration does not contribute to scope enforcement. The API-level root `security:` array may still apply depending on `scopeSource` — when `scopeSource` is `"union"` (the default) or `"global"`, root security requirements are enforced regardless. `scopeCheck` requires the `oauth2` security scheme to be configured on the API. It has no effect when `externalOAuthServer` or other authentication schemes are in use. For scheme setup and scope configuration details, see [OAuth 2.0 (External IdP)](/docs/api-management/authentication/oauth2-authentication). *** ## Upstream authentication ### exchange The `exchange` block overrides the token exchange provider's `audience` and `scopes` for one primitive. Token exchange is Enterprise Edition only. For the fields, an example, and scope inference, see [Per-MCP-primitive override](/docs/api-management/authentication/token-exchange#per-mcp-primitive-override). *** ## Traffic management Traffic management middleware protects your upstream MCP server from overload and controls the quality of service for individual primitives. ### rateLimit The `rateLimit` middleware applies a rate limit to a specific primitive, counted separately from any method-level or MCP server-level rate limits. Use it when different tools have meaningfully different costs: for example, a resource-intensive tool should have a tighter limit than one that reads static metadata. ```json theme={null} { "middleware": { "mcpTools": { "execute-query": { "rateLimit": { "enabled": true, "rate": 10, "per": 60 } }, "list-tables": { "rateLimit": { "enabled": true, "rate": 200, "per": 60 } } } } } ``` The `rate` field is the maximum number of requests allowed in the time window specified by `per` (in seconds, or as a shorthand string such as `"1m"` or `"30s"`). Primitive-level rate limits are additive with method-level limits; a request must pass both. Rate limits configured in `mcpTools`, `mcpResources`, and `mcpPrompts` are shared by all consumers of the proxy. For per-consumer limits, see [Policies versus middleware](/docs/ai-management/mcp-gateway/core-concepts#policies-versus-middleware). ### requestSizeLimit The `requestSizeLimit` middleware restricts the maximum size of the JSON-RPC request body for a specific primitive. Use it for tools that accept large argument payloads, where oversized requests could cause performance problems upstream. ```json theme={null} { "middleware": { "mcpTools": { "process-document": { "requestSizeLimit": { "enabled": true, "value": 65536 } } } } } ``` The `value` field is in bytes. Requests that exceed the limit are rejected before reaching the upstream. ### circuitBreaker The `circuitBreaker` middleware monitors the failure rate for a specific primitive and temporarily stops forwarding requests when the error rate exceeds a threshold. This protects the upstream from cascading failures and gives it time to recover. ```json theme={null} { "middleware": { "mcpTools": { "search-index": { "circuitBreaker": { "enabled": true, "threshold": 0.5, "sampleSize": 20, "coolDownPeriod": 30, "halfOpenStateEnabled": true } } } } } ``` * **`threshold`**: The ratio of failed requests (0.0 to 1.0) that trips the breaker. `0.5` means the breaker trips when more than 50% of recent requests fail. * **`sampleSize`**: The number of requests in the evaluation window. The threshold is checked after each window. * **`coolDownPeriod`**: Seconds to wait with the breaker open before attempting recovery. * **`halfOpenStateEnabled`**: When `true`, allows a small number of probe requests through during the cool-down period to test whether the upstream has recovered, rather than waiting for the full period to elapse before reopening. Circuit breakers are most valuable for tools that call external services or perform expensive operations where failure is likely to persist, rather than being transient. ### enforceTimeout The `enforceTimeout` middleware sets the maximum time Tyk waits for the upstream to respond to a specific primitive. Use it on slow tools, so that one slow call does not stall the agent's session. ```json theme={null} { "middleware": { "mcpTools": { "generate-report": { "enforceTimeout": { "enabled": true, "duration": "10s" } } } } } ``` Set `duration` as a duration string, such as `"500ms"` or `"10s"`. The `duration` field is available from Tyk 5.14.0. The older `value` field sets whole seconds and is deprecated. If the upstream does not respond in time, Tyk returns `504 Gateway Timeout` with the JSON-RPC error code `-32004`. ### cache The `cache` field is not supported for MCP primitives. Setting it has no effect. See the capability matrix at the end of this page. The `cache` field is accepted in the configuration schema but does not activate caching for MCP primitives. Any `cache` configuration you set on an entry in `mcpTools`, `mcpResources`, or `mcpPrompts` is silently ignored at runtime. The limitation is architectural: Tyk's cache middleware derives cache keys from the HTTP URL path, which is the same for every MCP request (`/mcp`). It does not inspect the JSON-RPC request body, so it cannot distinguish a `resources/read` call for `weather://current` from a `tools/call` to `get_forecast`; they resolve to the same cache key. Caching MCP traffic meaningfully would require cache key derivation from the JSON-RPC method and primitive identifier, which is not currently implemented. *** ## Request transformation Request transformation middleware modifies requests before they reach the upstream MCP server. You can add or remove headers, rewrite the upstream URL, or replace the request body. ### transformRequestHeaders The `transformRequestHeaders` middleware adds, removes, or modifies HTTP headers on the request forwarded to the upstream. ```json theme={null} { "middleware": { "mcpTools": { "query-database": { "transformRequestHeaders": { "enabled": true, "add": [ { "name": "X-Caller-Id", "value": "$tyk_context.request_id" }, { "name": "X-Tool-Name", "value": "query-database" } ], "remove": ["X-Internal-Debug"] } } } } } ``` Use this to inject authentication credentials your upstream expects, add tracing identifiers, or strip headers that should not reach the upstream. ### transformRequestBody The `transformRequestBody` middleware transforms the JSON-RPC request body before it is forwarded to the upstream, using a Go template. This allows you to reshape the request, for example to translate between different argument schemas or to inject values from the gateway context. ```json theme={null} { "middleware": { "mcpTools": { "search": { "transformRequestBody": { "enabled": true, "format": "json", "body": "" } } } } } ``` The template receives the full JSON-RPC request as input and must produce a valid JSON-RPC 2.0 request as output to maintain protocol compliance with the upstream. ### urlRewrite The `urlRewrite` field is not supported for MCP primitives. Setting it has no effect. The field is accepted by the configuration schema for forward compatibility but is silently ignored at runtime. URL rewriting is incompatible with MCP's single-endpoint transport; all traffic flows through `/mcp` regardless of which primitive is invoked. ### transformRequestMethod The `transformRequestMethod` field is not supported for MCP primitives. Setting it has no effect. The field is accepted by the configuration schema for forward compatibility but is silently ignored at runtime. MCP always uses `POST` for JSON-RPC messages and `GET` for SSE streams; the HTTP method cannot be changed at the primitive level. *** ## Response transformation ### transformResponseHeaders The `transformResponseHeaders` middleware adds, removes, or modifies HTTP headers on the response returned to the client. ```json theme={null} { "middleware": { "mcpResources": { "public://data/*": { "transformResponseHeaders": { "enabled": true, "add": [ { "name": "Cache-Control", "value": "public, max-age=300" } ] } } } } } ``` Response body transformation (`transformResponseBody`) is not available for MCP primitives. MCP responses are JSON-RPC 2.0 messages and must be returned to the client unmodified to maintain protocol compliance. Response body transformation remains available for entries in `middleware.operations` if you need to transform at the method level, but the same protocol compliance constraint applies, so use with care. *** ## Testing and development ### mockResponse The `mockResponse` field is not supported for MCP primitives. Setting it has no effect. Mock responses require Tyk to construct a complete HTTP response body before it reaches the client, which is incompatible with the streaming JSON-RPC transport MCP uses. See the capability matrix at the end of this page. The `mockResponse` field is accepted in the configuration schema but does not intercept or replace responses for MCP primitives. ### virtualEndpoint The `virtualEndpoint` middleware executes a JavaScript function in place of the upstream proxy. Use it to implement simple primitives directly in the gateway, for example a tool that aggregates data from a Tyk context variable, performs a simple calculation, or returns a dynamically constructed response without needing a dedicated upstream service. ```json theme={null} { "middleware": { "mcpTools": { "echo": { "virtualEndpoint": { "enabled": true, "functionName": "echoTool", "body": "", "proxyOnError": false } } } } } ``` The JavaScript function receives the request object and must return a response object in JSON-RPC 2.0 format. Set `proxyOnError` to `true` to fall back to the upstream if the virtual endpoint function throws an error. *** ## Observability ### trackEndpoint and doNotTrackEndpoint By default, Tyk records analytics for all requests. These two middleware options let you override tracking behavior at the primitive level. `trackEndpoint` enables detailed analytics for a primitive that might otherwise be excluded: ```json theme={null} { "middleware": { "mcpTools": { "execute-query": { "trackEndpoint": { "enabled": true } } } } } ``` `doNotTrackEndpoint` excludes a primitive from analytics logs and dashboards. Use this for high-volume or sensitive primitives where capturing every request creates noise or a compliance concern: ```json theme={null} { "middleware": { "mcpTools": { "health-check": { "doNotTrackEndpoint": { "enabled": true } } } } } ``` *** ## Plugins ### postPlugins The `postPlugins` field executes one or more custom plugin functions after the main middleware chain completes, immediately before the request is proxied to the upstream. Use custom plugins when the built-in middleware capabilities are insufficient, for example to validate request arguments against an external schema, to enrich the request with data from a third-party service, or to implement custom access control logic. ```json theme={null} { "middleware": { "mcpTools": { "execute-query": { "postPlugins": [ { "enabled": true, "functionName": "validateQuerySchema", "path": "/opt/tyk/plugins/query-validator.so" } ] } } } } ``` Plugins are loaded from the path specified or from a bundle configured in the global `pluginConfig` section. See [Custom plugins](/docs/api-management/plugins/overview) for the full plugin development guide. *** ## Resource URI matching Resources in the `mcpResources` map are matched against the `params.uri` value in incoming `resources/read` requests. Tyk resolves the match in this order: 1. **Exact match**: If the request URI matches a key exactly, that entry's middleware is applied. 2. **Wildcard match**: If no exact match is found, Tyk checks for entries containing `*`. When multiple patterns match, the longest prefix wins. 3. **No match**: If neither an exact nor wildcard match is found, the request is handled by the default middleware chain (all primitives are accessible unless the category is in allowlist mode). For example, given these entries: ```json theme={null} { "mcpResources": { "file:///config/database.json": { "rateLimit": { "enabled": true, "rate": 10, "per": 60 } }, "file:///config/*": { "rateLimit": { "enabled": true, "rate": 100, "per": 60 } }, "file:///*": { "allow": { "enabled": true } } } } ``` A request for `file:///config/database.json` matches the exact entry and gets a limit of 10 requests per minute. A request for `file:///config/settings.json` matches the `file:///config/*` pattern and gets a limit of 100 requests per minute. A request for `file:///logs/app.log` matches the `file:///*` fallback and is allowed with no primitive rate limit. *** ## Middleware capability reference The following table summarises every middleware capability available for MCP proxies and where it can be configured. | Middleware | Field | Dashboard: Settings tab | Dashboard: Primitives tab | Definition | | - | - | - | - | - | | Allowlist | `allow` | — | Yes | Yes | | Blocklist | `block` | — | Yes | Yes | | Ignore authentication | `ignoreAuthentication` | — | Yes | Yes | | Scope check | `scopeCheck` | — | Yes | Yes | | Token exchange (per-primitive) | `exchange` | — | Yes | Yes | | Rate limiting | `rateLimit` | — | Yes | Yes | | Request size limit | `requestSizeLimit` | — | Yes | Yes | | Circuit breaker | `circuitBreaker` | — | Yes | Yes | | Enforce timeout | `enforceTimeout` | — | Yes | Yes | | Cache | `cache` | — | — | No, disabled for protocol compliance | | Transform request headers (global) | `middleware.global.transformRequestHeaders` | Yes | — | Yes | | Transform request headers (primitive) | `transformRequestHeaders` | — | Yes | Yes | | Transform request body | `transformRequestBody` | — | — | Yes | | URL rewrite | `urlRewrite` | — | — | No, silently ignored for protocol compliance | | Transform request method | `transformRequestMethod` | — | — | No, silently ignored for protocol compliance | | Transform response headers (global) | `middleware.global.transformResponseHeaders` | Yes | — | Yes | | Transform response headers (primitive) | `transformResponseHeaders` | — | Yes | Yes | | Transform response body | `transformResponseBody` | — | — | No, disabled for protocol compliance | | Mock response | `mockResponse` | — | — | No, disabled for protocol compliance | | Virtual endpoint | `virtualEndpoint` | — | Yes | Yes | | Track endpoint | `trackEndpoint` | — | Yes | Yes | | Do not track | `doNotTrackEndpoint` | — | Yes | Yes | | Post plugins | `postPlugins` | — | Yes | Yes | | CORS | `middleware.global.cors` | Yes | — | Yes | | Context variables | `middleware.global.contextVariables` | Yes | — | Yes | | Traffic logs | `middleware.global.trafficLogs` | Yes | — | Yes | | Plugin config / bundle | `middleware.global.pluginConfig` | Yes | — | Yes | # MCP Gateway Observability Overview Source: https://tyk.io/docs/ai-management/mcp-gateway/mcp-observability An overview of the observability signals Tyk Gateway emits for MCP traffic: metrics dimensions, structured access log fields, distributed tracing, and the Dashboard analytics. Tyk Gateway emits three categories of observability signal for MCP traffic: custom metrics dimensions, structured access log fields, and distributed tracing spans. All three are enriched with the same set of MCP-specific fields, letting you monitor tool call volumes, track latency per primitive, classify errors, and correlate usage across sessions, through the same observability infrastructure you use for your REST APIs. ## Prerequisites OpenTelemetry must be enabled on your Tyk Gateway. See [OpenTelemetry configuration](/docs/api-management/traces) for setup instructions. ## MCP fields Tyk derives four fields from the JSON-RPC payload of each MCP request: `mcp_method`, `mcp_primitive_type`, `mcp_primitive_name`, and `mcp_error_code`. For their values in access logs, see [MCP fields](/docs/ai-management/mcp-gateway/mcp-access-logs#mcp-fields). For their values as metric dimensions, see [MCP metrics](/docs/ai-management/mcp-gateway/mcp-metrics). ## Observability Signals | Signal | What it covers | Doc | | - | - | - | | **Metrics** | Custom OTel metric instruments with MCP dimensions for counters and histograms | [MCP metrics](/docs/ai-management/mcp-gateway/mcp-metrics) | | **Access logs** | Structured per-request log records with MCP fields included when non-empty | [MCP access logs](/docs/ai-management/mcp-gateway/mcp-access-logs) | | **Distributed tracing** | Spans stamped with MCP attributes, with trace context carried in the JSON-RPC body as well as HTTP headers | [Distributed tracing](#distributed-tracing), below | ## Distributed tracing When [OpenTelemetry tracing](/docs/api-management/traces) is enabled, Tyk stamps every MCP request's span with MCP-specific attributes and propagates trace context over both the standard HTTP `traceparent` header and the MCP JSON-RPC body, so a trace stays intact even through MCP clients or servers that don't preserve custom headers. ### Span attributes | Attribute | Description | | - | - | | `mcp.method.name` | JSON-RPC method invoked | | `mcp.tool.name`, `mcp.resource.name`, or `mcp.prompt.name` | Name of the specific primitive, keyed by its type | | `mcp.trace_source` | Which channel(s) carried the inbound trace context: `none`, `header`, `meta` (the JSON-RPC body's `params._meta` field), or `both` | ### Trace context propagation Not every MCP client library preserves custom HTTP headers, so the MCP specification allows a client to carry its W3C trace context inside the JSON-RPC request body instead, under `params._meta`. Tyk reads both channels, in a configurable, first-match-wins order set under `opentelemetry.traces.mcp.read_sources` in the gateway config. The default order, the HTTP header first and then the body, matches Tyk's existing header-based behavior, so tracing works unchanged if you don't set this. Whichever channel Tyk resolves the inbound trace context from, it writes its own current trace context back into the outbound JSON-RPC body before forwarding the request, so a downstream MCP server that reads the body rather than the header joins the same trace. This is the body-channel equivalent of the `traceparent` header Tyk already injects on ordinary proxied requests. This applies to every MCP proxy. For a [REST API to MCP proxy](/docs/ai-management/mcps/api-to-mcp), the trace continues into the call to the source REST API. See [Access logs when the proxy fronts a Tyk-managed REST API](/docs/ai-management/mcp-gateway/mcp-access-logs#access-logs-when-the-proxy-fronts-a-tyk-managed-rest-api). ## Dashboard Analytics Alongside these OpenTelemetry signals, Tyk Dashboard has a dedicated **Activity by MCP** analytics page, covering proxy-level and primitive-level traffic and error charts. See [MCP Analytics](/docs/ai-management/mcp-gateway/mcp-analytics). For a [REST API to MCP proxy](/docs/ai-management/mcps/api-to-mcp), these charts show only the proxy's own traffic. The internal call to the source REST API counts as that API's traffic. See [Access logs when the proxy fronts a Tyk-managed REST API](/docs/ai-management/mcp-gateway/mcp-access-logs#access-logs-when-the-proxy-fronts-a-tyk-managed-rest-api). # MCP proxy definition Source: https://tyk.io/docs/ai-management/mcp-gateway/mcp-proxy-definitions Structure of a Tyk MCP proxy definition: the OpenAPI document, MCP primitives and JSON-RPC methods, and the x-tyk-api-gateway and x-tyk-mcp-server extensions. ## Overview An MCP proxy definition is the configuration object that tells Tyk how to front an MCP server. It is built on the **[Tyk OAS API definition](/docs/api-management/gateway-config-tyk-oas)** format (an OpenAPI 3.0.x or 3.1.x document extended with the `x-tyk-api-gateway` vendor extension) and adds the MCP-specific structures that allow Tyk to inspect JSON-RPC traffic and apply middleware at the method and primitive level. This page explains the structure of an MCP proxy definition, how MCP concepts (primitives, methods, operations) map to it, and which parts of the extension are specific to MCP. If you are not familiar with Tyk OAS API definitions, read [Tyk OAS](/docs/api-management/gateway-config-tyk-oas) first. This page focuses on the MCP-specific aspects and assumes knowledge of the base format. ## Structure Overview An MCP proxy definition has two parts that work together: * **The OpenAPI specification**: Describes the MCP server's transport endpoints and, optionally, each JSON-RPC method as a documented operation. Tyk uses this to understand the API's shape and to present it in the Developer Portal. * **The `x-tyk-api-gateway` extension**: Contains all gateway configuration: the listen path, upstream URL, authentication, and the middleware maps that govern individual tools, resources, and prompts. The two parts share the same file or API object: ```json theme={null} { "openapi": "3.0.3", "info": { "title": "Weather MCP proxy", "version": "2025-11-25" }, "paths": { ... }, "x-tyk-api-gateway": { "info": { ... }, "server": { ... }, "upstream": { ... }, "middleware": { ... } } } ``` The `x-tyk-api-gateway` extension has four top-level sections: | Section | What it configures | | - | - | | `info` | API name, active state, and internal identifier | | `server` | Client-facing settings: listen path, authentication, IP access control, custom domain | | `upstream` | Upstream MCP server: target URL, load balancing, upstream rate limits, mTLS | | `middleware` | Request processing: global, per-method, and per-primitive middleware | The sections below explain each part and the MCP-specific patterns within them. ## MCP Concepts in the Definition Three core MCP concepts shape how you write an MCP proxy definition: primitives, JSON-RPC methods, and transport endpoints, see [What is MCP?](/docs/ai-management/mcp-gateway/core-concepts#what-is-mcp). Understanding them before reading the definition structure makes the configuration decisions much clearer. In the definition, method-level middleware goes in `middleware.operations`, and each primitive type has its own map: `mcpTools`, `mcpResources`, and `mcpPrompts`. ## The OpenAPI Specification Portion The OpenAPI specification in an MCP proxy definition documents the server's HTTP interface. For MCP, this has a standard structure that you can treat as a template. ### Transport Paths At minimum, the `paths` object documents the two transport endpoints: ```json theme={null} { "paths": { "/mcp": { "post": { "summary": "Send a JSON-RPC message", "operationId": "mcpTransportPost", "parameters": [ { "name": "MCP-Protocol-Version", "in": "header", "required": true, "schema": { "type": "string", "example": "2025-11-25" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/JSONRPCRequest" } } } }, "responses": { "200": { "description": "JSON-RPC response or SSE stream", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/JSONRPCResponse" } }, "text/event-stream": { "schema": { "type": "string" } } } }, "202": { "description": "Accepted (notification, no response body)" } } }, "get": { "summary": "Open an SSE stream", "operationId": "mcpSSEGet", "responses": { "200": { "description": "Server-sent events stream", "content": { "text/event-stream": { "schema": { "type": "string" } } } } } } } } } ``` The `operationId` values (`mcpTransportPost`, `mcpSSEGet`) are referenced internally by Tyk for the transport endpoints. These values are fixed; do not change them. ### Method Paths In addition to the transport paths, you can document each JSON-RPC method as a separate path. This is optional for gateway operation but makes the MCP proxy browsable in the Tyk Developer Portal: ```json theme={null} { "paths": { "/mcp/tools/call": { "post": { "summary": "Invoke a tool", "operationId": "tools/callPOST", "x-mcp-method": "tools/call", ... } }, "/mcp/resources/read": { "post": { "summary": "Read a resource", "operationId": "resources/readPOST", "x-mcp-method": "resources/read", ... } } } } ``` These paths are a documentation and governance interface. They present each JSON-RPC method as a distinct, typed operation, making MCP proxies discoverable alongside REST and GraphQL APIs in your Developer Portal. The path structure (`/mcp/{namespace}/{action}`) and the `operationId` convention (`{method}POST`) are what tie the OpenAPI spec to the `middleware.operations` map in the `x-tyk-api-gateway` extension. The method paths do not correspond to real HTTP endpoints. All traffic still flows through `POST /mcp`. The method paths exist solely for documentation, schema validation, and middleware configuration purposes. ## The x-tyk-api-gateway Extension The `x-tyk-api-gateway` extension contains all gateway configuration. For MCP proxies, it has the same four top-level sections as any Tyk OAS API definition, with MCP-specific content in the `middleware` section. ### info, server, and upstream The `info`, `server`, and `upstream` sections work identically to a standard Tyk OAS API definition. They configure the API's identity, its client-facing interface, and its upstream connectivity: ```json theme={null} { "x-tyk-api-gateway": { "info": { "name": "Weather MCP proxy", "state": { "active": true } }, "server": { "listenPath": { "value": "/weather/", "strip": true }, "authentication": { "enabled": true, "securitySchemes": { "bearerAuth": { "enabled": true } } } }, "upstream": { "url": "https://weather-mcp.example.com" } } } ``` With this configuration, clients connect to Tyk at `https://my-gateway.example.com/weather/mcp`. Tyk authenticates the request, applies any configured middleware, and proxies it to `https://weather-mcp.example.com/mcp`. Tyk serves both the `POST` and `GET` transport endpoints under the same listen path. There are no MCP-specific fields in these three sections. You configure authentication, TLS, load balancing, upstream rate limits, and all other standard gateway capabilities exactly as you would for a REST API. See [Tyk OAS](/docs/api-management/gateway-config-tyk-oas) for the full field reference for these sections. For an MCP proxy [generated directly from a Tyk-managed REST API](/docs/ai-management/mcps/api-to-mcp), `upstream.url` holds an adapter target instead of a remote server's url. See [The upstream adapter target](/docs/ai-management/mcp-gateway/api-to-mcp-definitions#the-upstream-adapter-target) for what this value means and why it takes this form. The example above uses `bearerAuth` as the security scheme, a simple bearer token check. For full OAuth 2.1 compliance (token validation, scope enforcement, Protected Resource Metadata, and token exchange), use the `oauth2` scheme instead. See [MCP OAuth 2.1](/docs/ai-management/mcp-gateway/oauth-2-1). ### The middleware Section The `middleware` section is where MCP proxy definitions diverge from standard Tyk OAS API definitions. It contains the same `global` block for API-wide middleware, but adds two new concepts: an `operations` map keyed by JSON-RPC method, and three primitive maps: `mcpTools`, `mcpResources`, and `mcpPrompts`. This section covers where each middleware option lives in the definition; for what each option actually does, see [MCP middleware](/docs/ai-management/mcp-gateway/mcp-middleware). ```json theme={null} { "middleware": { "global": { ... }, "operations": { ... }, "mcpTools": { ... }, "mcpResources": { ... }, "mcpPrompts": { ... } } } ``` Each is explained below. A REST API to MCP proxy only populates `mcpTools`. `mcpResources` and `mcpPrompts` are unused, since a REST API has no resource or prompt primitives to expose. Its tool catalog is generated from the source API's operations rather than hand-written. See [REST API to MCP x-tyk-mcp-server extension](/docs/ai-management/mcp-gateway/api-to-mcp-definitions). #### global: API-Wide Middleware Global middleware applies to every request on the API. It is configured identically to a standard Tyk OAS API (CORS, traffic logs, header transformations, custom plugins, and so on). There is nothing MCP-specific here. #### operations: Method-Level Middleware The `operations` map lets you configure middleware that applies to every invocation of a JSON-RPC method, regardless of which specific primitive is targeted. It is keyed by the operation ID of the method path in the OpenAPI spec, which follows the convention `{json-rpc-method}{HTTP-method}`: | JSON-RPC method | Operation ID key | | - | - | | `tools/call` | `tools/callPOST` | | `tools/list` | `tools/listPOST` | | `resources/read` | `resources/readPOST` | | `resources/list` | `resources/listPOST` | | `prompts/get` | `prompts/getPOST` | | `prompts/list` | `prompts/listPOST` | | `initialize` | `initializePOST` | For an example, see [Operation middleware](/docs/ai-management/mcp-gateway/core-concepts#operation-middleware). #### mcpTools: Per-Tool Middleware The `mcpTools` map configures middleware for individual tools. Each key is the tool name as it appears in the `params.name` field of a `tools/call` request: ```json theme={null} { "middleware": { "mcpTools": { "get-weather": { "allow": { "enabled": true }, "rateLimit": { "enabled": true, "rate": 100, "per": 60 } }, "execute-query": { "allow": { "enabled": true }, "requestSizeLimit": { "enabled": true, "value": 8192 } } } } } ``` For how `allow` and `block` work, including allowlist mode, see [Access control](/docs/ai-management/mcp-gateway/mcp-middleware#access-control). #### mcpResources: Per-Resource Middleware The `mcpResources` map configures middleware for individual resources or URI patterns. Each key is matched against the `params.uri` field of a `resources/read` request. Keys can be exact URIs or wildcard patterns using `*`: ```json theme={null} { "middleware": { "mcpResources": { "weather://stations/london": { "allow": { "enabled": true }, "rateLimit": { "enabled": true, "rate": 100, "per": 60 } }, "weather://stations/*": { "allow": { "enabled": true }, "rateLimit": { "enabled": true, "rate": 20, "per": 60 } } } } } ``` Tyk resolves matches in priority order: exact matches take precedence over wildcard matches. When multiple wildcard patterns match, the longest matching prefix wins. #### mcpPrompts: Per-Prompt Middleware The `mcpPrompts` map configures middleware for individual prompts. Each key is the prompt name as it appears in the `params.name` field of a `prompts/get` request: ```json theme={null} { "middleware": { "mcpPrompts": { "weather-summary": { "allow": { "enabled": true } }, "weather-alert": { "allow": { "enabled": true }, "transformRequestHeaders": { "enabled": true, "add": [{ "name": "X-Prompt-Tier", "value": "premium" }] } } } } } ``` ## REST API to MCP x-tyk-mcp-server Extension An MCP proxy [generated directly from a Tyk-managed REST API](/docs/ai-management/mcps/api-to-mcp) has one further structure: `x-tyk-mcp-server`, a vendor extension alongside `x-tyk-api-gateway` rather than nested inside it, holding the tool catalog Tyk derives from the source API's OpenAPI operations. See [REST API to MCP x-tyk-mcp-server extension](/docs/ai-management/mcp-gateway/api-to-mcp-definitions) for the full field reference, the allow-list selection rule, tool name validation limits, and worked examples. ## Middleware Precedence Tyk runs global middleware, then operation middleware, then primitive middleware. For details, see [Evaluation order](/docs/ai-management/mcp-gateway/core-concepts#evaluation-order). All three middleware levels apply to all consumers of the proxy. For per-consumer control, use security policies. See [Policies versus middleware](/docs/ai-management/mcp-gateway/core-concepts#policies-versus-middleware). ## A Complete Example The following definition configures a weather MCP proxy with bearer token authentication, method-level and tool-level rate limiting, and allowlists for tools, resources, and prompts. ```json theme={null} { "openapi": "3.0.3", "info": { "title": "Weather MCP proxy", "version": "2025-11-25" }, "paths": { "/mcp": { "post": { "operationId": "mcpTransportPost", "summary": "Send a JSON-RPC message", "parameters": [ { "name": "MCP-Protocol-Version", "in": "header", "required": true, "schema": { "type": "string" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object" } } } }, "responses": { "200": { "description": "JSON-RPC response or SSE stream" } } }, "get": { "operationId": "mcpSSEGet", "summary": "Open an SSE stream", "responses": { "200": { "description": "Server-sent events stream" } } } } }, "x-tyk-api-gateway": { "info": { "name": "Weather MCP proxy", "state": { "active": true } }, "server": { "listenPath": { "value": "/weather/", "strip": true }, "authentication": { "enabled": true, "securitySchemes": { "bearerAuth": { "enabled": true } } } }, "upstream": { "url": "https://weather-mcp.example.com" }, "middleware": { "global": { "trafficLogs": { "enabled": true } }, "operations": { "tools/callPOST": { "rateLimit": { "enabled": true, "rate": 500, "per": 60 } } }, "mcpTools": { "get-weather": { "allow": { "enabled": true }, "rateLimit": { "enabled": true, "rate": 100, "per": 60 } }, "get-forecast": { "allow": { "enabled": true }, "rateLimit": { "enabled": true, "rate": 50, "per": 60 } } }, "mcpResources": { "weather://stations/*": { "allow": { "enabled": true } } }, "mcpPrompts": { "weather-summary": { "allow": { "enabled": true } } } } } } ``` What this definition does: * The API listens on `/weather/` and proxies to `https://weather-mcp.example.com`. Clients connect to `{gateway_host}/weather/mcp`. * Bearer token authentication is required on all requests. * All `tools/call` requests are rate limited to 500 per minute at the method level. * Only two tools are accessible (`get-weather` and `get-forecast`). Any other tool name is rejected. Each tool has its own tighter rate limit. * Resources matching `weather://stations/*` are accessible. * Only the `weather-summary` prompt is accessible. * Traffic logs are enabled for all requests. This example uses `bearerAuth` for simplicity. For full OAuth 2.1 compliance, including token validation against an external IdP, per-primitive scope enforcement, Protected Resource Metadata, and RFC 8693 token exchange, replace `bearerAuth` with the `oauth2` scheme. See [MCP OAuth 2.1](/docs/ai-management/mcp-gateway/oauth-2-1) for a complete worked example. ## Supported MCP Spec Features The following table documents which MCP protocol capabilities Tyk currently implements and how each maps to the proxy definition. | Capability | MCP spec version introduced | Tyk support | Notes | | - | - | - | - | | **Tools** (`tools/list`, `tools/call`) | Pre-2025-03-26 | ✅ Full | Per-tool middleware via `mcpTools`. Tool-level access control, rate limiting, timeouts, circuit breakers. | | **Resources** (`resources/list`, `resources/read`) | Pre-2025-03-26 | ✅ Full | Per-resource middleware via `mcpResources`. URI wildcard patterns supported. | | **Prompts** (`prompts/list`, `prompts/get`) | Pre-2025-03-26 | ✅ Full | Per-prompt middleware via `mcpPrompts`. | | **Streamable HTTP transport** (`POST /mcp`, `GET /mcp`) | 2025-03-26 | ✅ Full | The only supported transport. See [Transport](/docs/ai-management/mcp-gateway/core-concepts#transport). | | **Legacy HTTP+SSE transport** (separate POST and `/sse` endpoints) | Pre-2025-03-26 | ❌ Not supported | Replaced by Streamable HTTP in the MCP specification. | | **Sampling** (`sampling/createMessage`) | Pre-2025-03-26 | ✅ Pass-through | Tyk proxies sampling messages. Method-level middleware via `operations` applies; primitive-level middleware does not (sampling is client-side). | | **Roots** (`roots/list`) | Pre-2025-03-26 | ✅ Pass-through | Tyk proxies roots messages unchanged. | | **Elicitation** (`elicitation/create`) | 2025-03-26 | ✅ Pass-through | Tyk proxies elicitation messages unchanged. | | **Protected Resource Metadata (PRM)** | 2025-03-26 | ✅ Full | Tyk serves `/.well-known/oauth-protected-resource` automatically. Configured under `authentication.securitySchemes[name].oauth2.protectedResourceMetadata` from Tyk 5.14.0. See [OAuth 2.1 authentication](/docs/ai-management/mcp-gateway/oauth-2-1). | | **stdio transport** | Pre-2025-03-26 | ❌ Not supported | Tyk is a network-based gateway. Use a stdio-to-HTTP bridge for local MCP servers. | **MCP specification version:** Tyk implements the `2025-11-25` revision of the MCP specification. ## Summary | Concept | Where it lives in the definition | | - | - | | MCP primitives (tools, resources, prompts) | `middleware.mcpTools`, `middleware.mcpResources`, `middleware.mcpPrompts` | | JSON-RPC method middleware | `middleware.operations`: keyed by `{method}POST` | | API-wide middleware | `middleware.global` | | Transport endpoints (`POST /mcp`, `GET /mcp`) | `paths./mcp.post`, `paths./mcp.get` in the OpenAPI spec | | Listen path, authentication, upstream URL | `x-tyk-api-gateway.server`, `x-tyk-api-gateway.upstream` | | API to MCP tool catalog and overrides | `x-tyk-mcp-server` (REST API to MCP proxies only) | # MCP Gateway: OAuth 2.1 Authentication Source: https://tyk.io/docs/ai-management/mcp-gateway/oauth-2-1 Configure OAuth 2.1 for MCP proxies in Tyk Gateway: PRM discovery, inbound Bearer token validation, RFC 8693 token exchange, and upstream OAuth. *** ## MCP Auth Model MCP authorization operates on two distinct planes. **Inbound authorization** governs how MCP clients (AI agents, LLM frameworks, and applications) authenticate to Tyk Gateway. Tyk validates the credential on every request before it reaches your upstream MCP server. All [authentication methods](/docs/api-management/client-authentication) supported by Tyk apply here: Bearer tokens, API keys, JWT, and mutual TLS. For OAuth 2.1 compliance, configure the `oauth2` security scheme. It publishes the Protected Resource Metadata discovery document, enforces per-operation scopes, and enables RFC 8693 token exchange — all from a single scheme declaration. See [OAuth 2.0 (External IdP)](/docs/api-management/authentication/oauth2-authentication). **Upstream authorization** governs how Tyk authenticates to your upstream MCP server when that server requires an OAuth token. Tyk obtains the token from the authorization server using the client credentials flow and injects it into every proxied request. Your upstream receives a properly authorized request without any involvement from the original caller. The two planes are configured independently — Bearer tokens on the inbound side can be combined with client credentials on the upstream side. *** ## Protected Resource Metadata **Protected Resource Metadata (PRM)** is the standardized discovery mechanism defined in [RFC 9728](https://www.rfc-editor.org/rfc/rfc9728). It gives OAuth clients a machine-readable document describing a protected resource: which authorization servers can issue tokens for it, and which OAuth scopes it supports. The MCP specification recommends that every MCP server expose a PRM document so that clients can discover the correct authorization server before making their first request. Without it, clients must be pre-configured with authorization server URLs — an approach that becomes fragile as deployments grow and authorization infrastructure changes. Tyk serves the PRM document natively. When PRM is enabled on an [MCP OAS definition](/docs/ai-management/mcp-gateway/mcp-proxy-definitions), Tyk intercepts GET requests to the well-known path and serves the metadata document. The endpoint is unauthenticated by design — clients need it before they have a token. ### The discovery flow ```mermaid theme={null} sequenceDiagram autonumber participant C as MCP Client participant T as Tyk Gateway participant A as Authorization Server participant U as Upstream MCP Server C->>T: POST /mcp (no token) T-->>C: 401 Unauthorized Note over T,C: WWW-Authenticate: Bearer resource_metadata=https://gateway.example.com/weather-mcp/.well-known/oauth-protected-resource C->>T: GET /.well-known/oauth-protected-resource T-->>C: 200 OK — PRM document Note over T,C: resource · authorization_servers: [auth.example.com] · scopes_supported C->>A: POST /oauth/token (client credentials grant) A-->>C: 200 OK · access_token · token_type: Bearer C->>T: POST /mcp · Authorization: Bearer access_token Note over T: Validate Bearer token · apply middleware T->>U: POST /mcp · Authorization: Bearer upstream-token U-->>T: Response T-->>C: Response Note over C,U: Request authorised and proxied ``` The `WWW-Authenticate` header Tyk sends on authentication failure is a standard Bearer challenge extended with the `resource_metadata` parameter defined in RFC 9728. Any OAuth 2.1-compliant client library handles this automatically. ### Configuring PRM PRM is configured within the `oauth2` security scheme block in the Tyk Vendor Extension. The scheme name (`idpAuth` in the example below) must match the scheme declared with `type: oauth2` in the OAS `components.securitySchemes` section — see [OAuth 2.0 (External IdP)](/docs/api-management/authentication/oauth2-authentication) for the full scheme setup. ```json theme={null} { "x-tyk-api-gateway": { "server": { "authentication": { "enabled": true, "securitySchemes": { "idpAuth": { "enabled": true, "protectedResourceMetadata": { "enabled": true, "resource": "https://gateway.example.com/weather-mcp/", "authorizationServers": ["https://auth.example.com"], "autoDeriveScopes": true } } } } } } } ``` The PRM endpoint is served at `{listen-path}/{wellKnownPath}`. With the default path and a listen path of `/weather-mcp/`, the endpoint is available at `/weather-mcp/.well-known/oauth-protected-resource`. For every PRM field, its default, and the automatic migration from the pre-5.14 location, see [Protected Resource Metadata](/docs/api-management/authentication/oauth2-authentication#protected-resource-metadata). *** ## Scope enforcement Scope enforcement checks that the bearer token carries the scopes required by the matched operation or MCP primitive — translating what the authorization server granted into access decisions at the gateway. Configure it under `scopeCheck` in the `oauth2` scheme block: ```json theme={null} { "x-tyk-api-gateway": { "server": { "authentication": { "securitySchemes": { "idpAuth": { "enabled": true, "scopeCheck": { "enabled": true, "claimNames": ["scope", "scp"], "separator": " ", "scopeSource": "union" } } } } } } } ``` The required scopes for each operation come from the `security:` array in your OAS definition. For MCP primitives, which have no OAS path entry, declare scopes in the Tyk Vendor Extension under `middleware.mcpTools`, `middleware.mcpResources`, or `middleware.mcpPrompts`: ```json theme={null} { "x-tyk-api-gateway": { "middleware": { "mcpTools": { "create-report": { "security": [{ "idpAuth": ["tools:write"] }] } } } } } ``` When a request fails scope enforcement, Tyk returns `403 Forbidden` with `WWW-Authenticate: Bearer error="insufficient_scope"`. Scope enforcement runs after JWT signature validation — if the token is invalid, the request is rejected at the JWT auth step before scope check is reached. For the `scopeCheck` fields, the `scopeSource` modes, and per-operation and per-primitive exemptions, see [Scope enforcement](/docs/api-management/authentication/oauth2-authentication#scope-enforcement). *** ## Upstream OAuth When the upstream MCP server requires OAuth, Tyk handles token acquisition transparently. It acts as an OAuth client — obtaining a token from the upstream's authorization server using the client credentials flow and attaching it to every proxied request. The original MCP client never needs to supply upstream credentials. Tyk caches acquired tokens and refreshes them before they expire, so the upstream sees a consistent stream of valid credentials without a token request on every MCP call. Upstream OAuth is available in Tyk Enterprise Edition only. ### Client credentials flow Client credentials is the OAuth flow for machine-to-machine communication — no user is involved, Tyk acts as the client. OAuth 2.1 retains this flow specifically for server-to-server scenarios. ```mermaid theme={null} sequenceDiagram autonumber participant C as MCP Client participant T as Tyk Gateway participant A as Authorization Server participant U as Upstream MCP Server C->>T: POST /mcp · Authorization: Bearer inbound-token Note over T: Validate inbound token · check token cache alt Token not cached or expired T->>A: POST /oauth/token Note over T,A: grant_type: client_credentials · client_id · client_secret · scopes A-->>T: 200 OK · access_token · expires_in: 3600 Note over T: Cache upstream token else Token cached Note over T: Use cached upstream token end T->>U: POST /mcp · Authorization: Bearer upstream-token U-->>T: Response T-->>C: Response Note over C,U: Request processed upstream ``` ### Configuring upstream OAuth Upstream OAuth is configured in the `upstream.authentication` section of the API definition: ```json theme={null} { "x-tyk-api-gateway": { "upstream": { "url": "https://weather-mcp.example.com", "authentication": { "enabled": true, "oauth": { "enabled": true, "allowedAuthorizeTypes": ["clientCredentials"], "clientCredentials": { "clientId": "tyk-gateway-client", "clientSecret": "your-client-secret", "tokenUrl": "https://auth.example.com/oauth/token", "scopes": ["mcp:read", "mcp:write"] } } } } } } ``` | Field | Required | Description | | - | - | - | | `clientId` | Yes | The OAuth client ID issued by the authorization server for this gateway instance. | | `clientSecret` | Yes | The client secret associated with the client ID. | | `tokenUrl` | Yes | The token endpoint of the upstream's authorization server. | | `scopes` | No | The scopes to request when obtaining the token. The authorization server grants only the scopes it recognises and the client is permitted. | | `extraMetadata` | No | Keys to extract from the token response and pass to the upstream as additional context. | *** ## Token exchange The [MCP authorization specification](https://modelcontextprotocol.io/specification/2025-06-18/basic/authorization#access-token-privilege-restriction) requires that an MCP server **MUST NOT** pass through the token it received from the MCP client when making requests to upstream APIs. The upstream token must be a separate token issued by the upstream authorization server. **Token exchange** ([RFC 8693](https://www.rfc-editor.org/rfc/rfc8693)) is how Tyk satisfies this requirement while preserving the caller's identity. Tyk presents the validated inbound token to an authorization server and receives a backend-scoped token in return. The inbound agent token never reaches the upstream. This matters for MCP because: * **Spec compliance** — The MCP spec explicitly forbids passing through the inbound token. Token exchange satisfies this requirement while maintaining a traceable delegation chain. * **Audience compliance** — MCP servers must validate that tokens were issued specifically for them as the intended audience ([RFC 8707](https://www.rfc-editor.org/rfc/rfc8707.html)). Token exchange produces a token audienced to the upstream service without requiring clients to request multiple tokens. * **Separation of trust** — The AI agent's credential stays scoped to the gateway trust domain; the upstream receives a narrowly-scoped credential appropriate to its own. ```mermaid theme={null} sequenceDiagram autonumber participant C as MCP Client participant T as Tyk Gateway participant I as Authorization Server participant U as Upstream MCP Server C->>T: POST /mcp · Authorization: Bearer agent-token Note over T: Validate inbound token · enforce scopes T->>I: POST /token (RFC 8693 exchange) Note over T,I: subject_token=agent-token · audience=upstream-service I-->>T: 200 OK · access_token (upstream-scoped) T->>U: POST /mcp · Authorization: Bearer upstream-token U-->>T: Response T-->>C: Response Note over C,U: Inbound token never forwarded to upstream ``` Token exchange is Enterprise Edition only and is configured within the `oauth2` security scheme. For full configuration details — including provider setup, caching, and per-primitive overrides — see [Token exchange](/docs/api-management/authentication/token-exchange). Do not configure `upstream.authentication.oauth` alongside token exchange. They serve the same purpose — authenticating Tyk to the upstream — and configuring both produces a conflict. Use token exchange when you want to propagate a delegated credential derived from the inbound token. Use `upstream.authentication.oauth` when Tyk should authenticate with its own static client credentials independent of who the original caller was. *** ## Composing features Each feature on this page is independent. The example below uses all of them, but you can enable any subset depending on your requirements. **JWT authentication** validates the inbound token's signature. In Tyk 5.14.0 this is required alongside the `oauth2` scheme because the `oauth2` scheme reads token claims but does not verify the signature itself. It is the baseline for everything else. **PRM** enables dynamic discovery — clients that arrive without a token learn where to obtain one. Enable it if your MCP clients are OAuth 2.1-compliant and should discover the authorization server automatically. Omit it if your clients are pre-configured with the authorization server URL. **Scope enforcement** (`scopeCheck`) checks that the token carries the scopes required by the matched operation or MCP primitive. Use it when the IdP owns access decisions — the authorization server grants specific scopes and Tyk enforces them at the gateway. If you prefer Tyk's policy engine to control primitive access (a platform-owned model where keys are issued with policy-level permissions), omit `scopeCheck` and rely on policies instead. The two approaches are mutually exclusive per primitive: using both creates conflicting ownership of access decisions. **Token exchange** replaces the inbound agent token with an upstream-scoped token before forwarding. The MCP specification requires that the upstream never receives the original token — token exchange is how you satisfy that requirement while preserving the delegation chain. If you are using [Upstream OAuth](#upstream-oauth) with static client credentials instead, token exchange can be omitted. **PRM and scope enforcement are particularly complementary.** PRM advertises which scopes clients need to request; `scopeCheck` enforces at runtime that the presented token actually carries them. When `autoDeriveScopes` is enabled, both are driven by the same `security:` declarations in your OAS definition — so the scopes a client is told to request and the scopes Tyk enforces are derived from the same source and can't drift out of sync. Enabling PRM without `scopeCheck` means scopes are advertised but not enforced at the gateway. Enabling `scopeCheck` without PRM means enforcement works, but clients need to know the required scopes upfront rather than discovering them dynamically. Common configurations: | Goal | Features to enable | | - | - | | Validate tokens; use Tyk policies for primitive access | JWT auth | | Add client-side discovery | JWT auth + PRM | | Add IdP-owned scope enforcement | JWT auth + PRM + scopeCheck | | Full MCP spec compliance with delegated upstream identity | JWT auth + PRM + scopeCheck + token exchange | *** ## The complete OAuth 2.1 flow The end-to-end flow has two phases. The authorization server appears in both — first when the MCP client obtains its agent token, then when Tyk exchanges it for an upstream-scoped token. **Phase 1 — Discovery** 1. The MCP client makes a request to the MCP endpoint without a token. 2. Tyk returns `401 Unauthorized` with a `WWW-Authenticate` header pointing to the PRM well-known URL. 3. The client fetches the PRM document and learns which authorization server to use and which scopes are supported. 4. The client authenticates to the authorization server (authorization code flow, device flow, etc.) and receives an agent-scoped access token. **Phase 2 — Authenticated request** 5. The client sends the request with `Authorization: Bearer `. 6. Tyk validates the token signature (JWT auth) and enforces scopes (`oauth2` scheme). 7. Tyk POSTs an RFC 8693 token exchange to the authorization server, presenting the agent token as `subject_token` and requesting a token audienced to the upstream MCP server. 8. The authorization server returns an upstream-scoped access token. 9. Tyk replaces the `Authorization` header with the exchanged token and forwards the request to the upstream MCP server. 10. The upstream responds; Tyk returns the response to the client. The agent's original token never reaches the upstream MCP server. The MCP client and the upstream each receive a token issued specifically for their trust boundary. *** ## A complete configuration example The following configuration for a weather MCP proxy enables all four features — PRM discovery, JWT signature validation, scope enforcement, and RFC 8693 token exchange: ```json expandable theme={null} { "openapi": "3.0.3", "info": { "title": "Weather MCP proxy", "version": "2025-11-25" }, "components": { "securitySchemes": { "jwtAuth": { "type": "http", "scheme": "bearer", "bearerFormat": "JWT" }, "idpAuth": { "type": "oauth2", "flows": { "authorizationCode": { "authorizationUrl": "https://auth.example.com/authorize", "tokenUrl": "https://auth.example.com/token", "scopes": { "tools:read": "Read access to MCP tools", "tools:write": "Write access to MCP tools" } } } } } }, "security": [ { "jwtAuth": [], "idpAuth": ["tools:read"] } ], "paths": { "/mcp": { "post": { "operationId": "mcpTransportPost", "responses": { "200": { "description": "JSON-RPC response" } } }, "get": { "operationId": "mcpSSEGet", "responses": { "200": { "description": "SSE stream" } } } } }, "x-tyk-api-gateway": { "info": { "name": "Weather MCP proxy", "state": { "active": true } }, "server": { "listenPath": { "value": "/weather-mcp/", "strip": true }, "authentication": { "enabled": true, "securitySchemes": { "jwtAuth": { "enabled": true, "signingMethod": "rsa", "jwksURIs": [{ "url": "https://auth.example.com/.well-known/jwks.json" }], "identityBaseField": "sub" }, "idpAuth": { "enabled": true, "scopeCheck": { "enabled": true, "claimNames": ["scope", "scp"], "separator": " ", "scopeSource": "union" }, "protectedResourceMetadata": { "enabled": true, "resource": "https://gateway.example.com/weather-mcp/", "authorizationServers": ["https://auth.example.com"], "autoDeriveScopes": true }, "tokenExchange": { "enabled": true, "providers": [ { "name": "idp-prod", "issuers": ["https://auth.example.com"], "tokenEndpoint": "https://auth.example.com/token", "clientAuth": { "method": "client_secret_basic", "clientId": "tyk-gateway", "clientSecret": "env://EXCHANGE_CLIENT_SECRET" }, "defaultTarget": { "audience": "https://weather-mcp.example.com", "scopes": ["mcp:read", "mcp:write"] } } ] } } } } }, "upstream": { "url": "https://weather-mcp.example.com" } } } ``` In this configuration: * MCP clients that arrive without a token receive a `401` with a `WWW-Authenticate` header pointing to the PRM document. * Clients that follow the discovery flow obtain a token from `https://auth.example.com` using the `authorizationCode` flow and present it as a Bearer token. * Tyk validates the token signature via the `jwtAuth` scheme (JWKS endpoint), then `scopeCheck` enforces that the token carries `tools:read` before the request proceeds. * Tyk exchanges the validated agent token for an upstream-scoped token audienced to `https://weather-mcp.example.com`. The original agent token never reaches the upstream MCP server. In Tyk 5.14.0, the `oauth2` scheme does not validate JWT signatures itself. The `jwtAuth` scheme in this example handles signature validation — configure JWT authentication on the API alongside the `oauth2` scheme so that inbound tokens are verified before scope enforcement runs. For the static client credentials variant — where Tyk authenticates to the upstream with its own credentials independent of the inbound token — see [Upstream OAuth](#upstream-oauth). *** ## Per-primitive configuration The complete example above configures each feature at the API level, applying uniformly to all primitives. Both scope enforcement and token exchange support per-primitive overrides when individual tools need different access requirements or different upstream credentials. ### Multiple exchange providers The `providers` array accepts more than one entry. Tyk selects a provider for each request by matching the inbound token's `iss` claim against each provider's `issuers` list. Use this when an MCP proxy accepts tokens from more than one authorization server, for example your own IdP and a partner's. ```json expandable theme={null} "tokenExchange": { "enabled": true, "providers": [ { "name": "idp-prod", "issuers": ["https://auth.example.com"], "tokenEndpoint": "https://auth.example.com/token", "clientAuth": { "method": "client_secret_basic", "clientId": "tyk-gateway", "clientSecret": "env://EXCHANGE_CLIENT_SECRET" }, "defaultTarget": { "audience": "https://weather-mcp.example.com", "scopes": ["mcp:read", "mcp:write"] } }, { "name": "partner-idp", "issuers": ["https://auth.partner.example"], "tokenEndpoint": "https://auth.partner.example/token", "clientAuth": { "method": "client_secret_post", "clientId": "tyk-gateway-partner", "clientSecret": "env://PARTNER_EXCHANGE_SECRET" }, "defaultTarget": { "audience": "https://weather-mcp.example.com", "scopes": ["mcp:read"] } } ] } ``` For the provider fields and multi-tenant issuer matching, see [Provider fields](/docs/api-management/authentication/token-exchange#provider-fields). ### Per-primitive scope and exchange overrides The `defaultTarget` in each provider applies uniformly to every primitive. When individual tools need a different audience, a narrower set of scopes, or stricter scope enforcement than the API-level default, configure overrides directly on the primitive in the `middleware.mcpTools` map: ```json theme={null} "middleware": { "mcpTools": { "get-forecast": { "security": [{ "idpAuth": ["tools:read"] }], "scopeCheck": { "enabled": true } }, "delete-station": { "security": [{ "idpAuth": ["tools:write", "admin:stations"] }], "scopeCheck": { "enabled": true }, "exchange": { "enabled": true, "audience": "https://station-admin.example.com", "scopes": ["admin:stations"] } } } } ``` * `get-forecast` requires `tools:read`. Scope enforcement rejects tokens that don't carry that claim. The exchange uses the provider's `defaultTarget` audience and scopes unchanged. * `delete-station` requires both `tools:write` and `admin:stations`. The `exchange` override requests a token audienced specifically to `https://station-admin.example.com` — a narrower credential than the standard weather MCP token — carrying only the `admin:stations` scope. For the full `scopeCheck` and `exchange` field reference, see [MCP middleware](/docs/ai-management/mcp-gateway/mcp-middleware). # Tyk MCP Gateway Source: https://tyk.io/docs/ai-management/mcp-gateway/overview Tyk MCP Gateway implements the MCP 2025-11-25 specification from v5.13, proxying and governing remote MCP servers with authentication, rate limiting, access control, key management, and observability at the gateway level. MCP Gateway The Model Context Protocol (MCP) is the open standard for connecting AI applications to external tools, data sources, and workflows. Tyk Gateway v5.13 and later implements the MCP **`2025-11-25`** specification. See [Requirements and limitations](#requirements-and-limitations) for the full version and licensing matrix. As MCP servers move into shared cloud infrastructure, they face the same operational challenges REST APIs faced a decade ago: who can call what, how often, with what credentials, and with what visibility. Tyk Gateway addresses these challenges natively, sitting between MCP clients and the servers or APIs behind them, to enforce authentication, access policies, rate limits, and traffic governance on every JSON-RPC request. This applies whether an MCP proxy fronts a remote MCP server or is [generated directly from a Tyk-managed REST API](/docs/ai-management/mcps/api-to-mcp). *** ## What is MCP? MCP uses a client-server model: an **MCP client** (an AI agent or framework) connects to an **MCP server** that exposes tools, resources, and prompts through JSON-RPC 2.0 messages over HTTP. For the full protocol reference, see [MCP Gateway: Core Concepts](/docs/ai-management/mcp-gateway/core-concepts) or the [MCP specification](https://modelcontextprotocol.io/specification/2025-11-25). *** ## The problem with ungoverned MCP Remote MCP servers are HTTP services. Like any HTTP service, they need authentication, rate limiting, access control, and observability to be operated reliably at scale. Without a gateway layer, each individual server must address these concerns on its own (if at all), leading to: **Inconsistent security.** Each MCP server implements its own authentication, or none at all. No central place exists to enforce who can access which tools, rotate credentials, or revoke access. **No visibility.** No standard way exists to see which AI agents are calling which tools, how often, and whether calls are succeeding. Troubleshooting failures or planning capacity requires digging into individual server logs. **Ungoverned proliferation.** MCP servers can appear across teams without oversight. No registry exists of what is available, no approval process, and no way to apply organization-wide policies consistently. **Fragile direct connections.** AI agents connecting directly to MCP servers have no protection if a server is slow or unavailable. Rate limits, circuit breakers, and timeouts must be rebuilt on every server independently. *** ## Where Tyk fits Tyk Gateway sits in front of your MCP servers and Tyk-managed REST APIs, proxying all MCP traffic through a centrally managed gateway layer. The same governance applies whether an MCP proxy fronts a remote MCP server or is [generated directly from a Tyk-managed REST API](/docs/ai-management/mcps/api-to-mcp). AI clients connect to Tyk at a configured listen path; Tyk authenticates the request, applies the configured middleware chain, and forwards the request to the upstream MCP server or REST API. The Tyk Dashboard serves as the registry layer, the central catalog of every MCP proxy in your organization, with the access policies and observability that govern how each one is used. Where Tyk MCP Gateway fits Tyk understands the MCP protocol. It parses JSON-RPC 2.0 request bodies to identify the method being called and the specific tool, resource, or prompt being accessed. This means you can apply policies at the level of individual MCP primitives (rate limiting a particular tool, blocking access to a specific resource, or setting a timeout on a slow tool) rather than treating all MCP traffic as an opaque HTTP stream. Tyk proxies both MCP transport endpoints, `POST /mcp` and `GET /mcp`. For details, see [Transport](/docs/ai-management/mcp-gateway/core-concepts#transport). *** ## How Tyk represents MCP proxies Tyk models each MCP proxy as a **[Tyk OAS API definition](/docs/ai-management/mcp-gateway/mcp-proxy-definitions)**, an OpenAPI document extended with the `x-tyk-api-gateway` vendor extension. This is the same format used for REST APIs, so MCP proxies share the same configuration model, tooling, and management APIs as the rest of your Tyk estate, whether the proxy fronts a remote MCP server or is generated directly from a Tyk-managed REST API. REST API to MCP proxies also carry an `x-tyk-mcp-server` vendor extension, which defines which REST operations become MCP tools and how they're presented to agents. See [MCP proxy definitions](/docs/ai-management/mcp-gateway/mcp-proxy-definitions) for the full schema. You create and manage MCP proxy definitions through the Tyk Dashboard or the Gateway API. No changes to your upstream MCP server, or the source REST API, are required. MCP proxy definitions require Tyk OAS format. When a proxy is generated from a REST API, the source must also be a Tyk OAS REST API: GraphQL APIs and Tyk Classic API definitions aren't supported as a source. See [REST API to MCP](/docs/ai-management/mcps/api-to-mcp) for details. *** ## What Tyk MCP Gateway provides ### Authentication and key management Tyk authenticates every MCP request before it reaches your upstream server. All authentication methods supported for REST APIs work identically for MCP: bearer tokens, API keys, JWT, OAuth 2.0, and mTLS. You issue and manage API keys through the Tyk Dashboard or API, and every key is associated with a security policy that defines what it can access and at what rate. This means your MCP servers don't need to implement their own authentication. Tyk handles credential verification, token validation, and key lifecycle centrally: rotation, expiration, and revocation. The [MCP specification](https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization) mandates OAuth 2.1 as the authorization framework and requires MCP servers to implement **Protected Resource Metadata** (PRM), a discovery document that tells OAuth-aware clients which authorization server to use and which scopes the resource supports. Tyk implements PRM natively: it serves the `/.well-known/oauth-protected-resource` endpoint automatically and returns the correct `WWW-Authenticate` challenge on unauthenticated requests, so compliant MCP clients can self-configure without any pre-configuration. See [OAuth 2.1 authentication](/docs/ai-management/mcp-gateway/oauth-2-1) for the full implementation details. ### Access control and policy enforcement Security policies give each consumer its own access rules and limits. For MCP proxies, a policy can control which proxies, JSON-RPC methods, tools, resources, and prompts a key can use, with rate limits at each level. See [MCP Gateway policies](/docs/ai-management/mcp-gateway/policies). This is what makes it practical to serve many different AI agents from a single MCP proxy. A read-only analyst agent and a privileged administrator agent can share the same upstream server but operate within completely different entitlements, each enforced at the gateway without any changes to the upstream. Tyk also filters discovery responses, so each agent sees only the primitives that it can call. See [Discovery](/docs/ai-management/mcp-gateway/core-concepts#discovery). ### Service registry The MCP section of the Tyk Dashboard is the central registry of every MCP proxy in your organization. See [Managing MCP proxies](/docs/ai-management/mcp-gateway/managing-proxies). To publish these MCP proxies in the Tyk AI Studio AI Portal and issue keys to AI Studio Apps, see [Tyk Dashboard MCP Integration](/docs/ai-management/ai-studio/tyk-mcp-integration). ### Traffic management Tyk applies rate limits, timeouts, circuit breakers, and request size limits to MCP traffic, down to the individual tool, resource, or prompt. See [Traffic management](/docs/ai-management/mcp-gateway/mcp-middleware#traffic-management) and [MCP Gateway policies](/docs/ai-management/mcp-gateway/policies). ### Analytics Tyk records analytics for every MCP request and exposes them in the Tyk Dashboard under **Monitoring → Activity by MCP**. Analytics are captured at two levels. **Proxy-level charts** show total request volume, error counts, and HTTP error code distribution across all your MCP proxies. Use these to compare traffic and error rates between proxies and identify trends over time. **Primitive-level charts** break the data down by individual tool, resource, or prompt: call volumes over time, most frequently called primitives, highest error rates, and slowest average latency. These charts show exactly which tools AI agents are calling, which are failing, and which are your performance bottlenecks, without any additional instrumentation. Both levels of data appear alongside your REST and GraphQL API analytics, giving you a unified view of your entire API estate. See [MCP observability](/docs/ai-management/mcp-gateway/mcp-observability). ### Observability Beyond the Dashboard analytics page, Tyk emits MCP-specific observability signals that integrate with your existing monitoring infrastructure. **Structured access logs** include four MCP-specific fields on every logged request: the JSON-RPC method invoked (`mcp_method`), the primitive type (`mcp_primitive_type`), the primitive name (`mcp_primitive_name`), and a gateway-mapped error code when the request fails at the gateway layer (`mcp_error_code`). These fields let you filter and aggregate MCP traffic in your log management tooling using the same pipeline you use for REST APIs. See [MCP access logs](/docs/ai-management/mcp-gateway/mcp-access-logs). **OpenTelemetry metrics**: when OTel is enabled on the gateway, Tyk emits four MCP-specific metric instruments covering request counts (with dimensions for method, primitive type, tool name, and error code), method distribution, upstream latency per tool, and end-to-end request latency. These metrics can be scraped by [Prometheus](https://prometheus.io/) and used to build dashboards in [Grafana](https://grafana.com/) or your preferred metrics platform. See [MCP metrics](/docs/ai-management/mcp-gateway/mcp-metrics) and [How to build a Grafana dashboard for MCP traffic](/docs/ai-management/mcp-gateway/how-to-grafana-mcp-dashboard). *** ## How Tyk compares See how Tyk MCP Gateway compares to other API and MCP gateways: * [Tyk vs Kong on MCP](https://tyk.io/tyk-mcp-vs-kong-mcp) * [Tyk vs Gravitee on MCP](https://tyk.io/tyk-mcp-vs-gravitee-mcp) * [Tyk vs Traefik on MCP](https://tyk.io/tyk-mcp-vs-traefik-mcp) * [Tyk vs WSO2 on MCP](https://tyk.io/tyk-mcp-vs-wso2-mcp) ## Requirements and limitations ### Requirements | Requirement | Detail | | - | - | | Tyk Gateway version | v5.13 or later for pass-through MCP proxies. REST API to MCP proxying requires v5.15 or later. | | API definition format | Tyk OAS only. Tyk Classic API definitions do not support MCP. | | API definition extension | The `x-tyk-api-gateway` vendor extension is required in every MCP proxy definition. | | Licensing | Proxies fronting a remote MCP server are available on all Tyk Gateway licenses. Individual features, such as upstream OAuth and token exchange, require Tyk Enterprise Edition. A [REST API to MCP proxy](/docs/ai-management/mcps/api-to-mcp) requires Tyk Enterprise Edition for the proxy type itself. | ### Supported transports Tyk MCP Gateway supports only the **Streamable HTTP** transport (`POST /mcp` and `GET /mcp`). It does not support stdio or the legacy HTTP+SSE transport. For details, see [Transport](/docs/ai-management/mcp-gateway/core-concepts#transport). ### REST API to MCP proxies Tyk Gateway can also generate an MCP proxy directly from a Tyk-managed REST API, without building or hosting a separate MCP server. See [REST API to MCP](/docs/ai-management/mcps/api-to-mcp). This capability requires **Tyk Enterprise Edition**. Only Tyk OAS REST APIs already onboarded to Tyk are supported as a source: GraphQL APIs and Tyk Classic API definitions cannot be converted to MCP tools. These proxies support only the `POST /mcp` transport; they do not expose `GET /mcp`, SSE streaming, or server-initiated notifications. ### MCP specification version Tyk supports the MCP **`2025-11-25`** specification. For the full protocol reference, see the [MCP specification](https://modelcontextprotocol.io/specification/2025-11-25). # MCP Gateway Policies Source: https://tyk.io/docs/ai-management/mcp-gateway/policies Configure Tyk security policies for MCP proxies: per-tool access and rate limits, JSON-RPC method restrictions, and how Tyk merges multiple policies. A Tyk security policy defines the access rules and usage limits for a consumer. For MCP proxies, policies go beyond the standard rate limit and quota controls available for REST APIs. They let you control access and apply rate limits at the level of individual tools, resources, and prompts, and restrict which JSON-RPC protocol methods a consumer can use at all. *** ## What policies are for A policy is a reusable template applied to one or more API keys. Rather than configuring limits and access rights on each key individually, you define them once in a policy and issue keys that inherit those rules automatically. When you update the policy, every key bound to it picks up the change. For MCP proxies, policies serve three purposes: **Controlling access**: a policy determines which MCP proxies a consumer key can reach. Without an entry in the policy's access rights, the consumer receives `403 Forbidden` regardless of what key they present. **Governing MCP capabilities**: beyond proxy-level access, policies let you restrict which JSON-RPC methods a consumer can use and which specific tools, resources, and prompts they can invoke. This lets you give different consumers different views of the same MCP proxy without creating separate proxy definitions. **Enforcing usage limits**: policies apply rate limits at several levels: across the whole policy, per MCP proxy, per JSON-RPC method, and per named primitive. Each consumer key tracks its own independent counters. *** ## What MCP policies control ### Access control Tyk evaluates access control at three levels, in order: **Proxy access**: the policy's access rights list determines which MCP proxies the key can reach. A key can only call a proxy listed in its access rights. **JSON-RPC method access** (`json_rpc_methods_access_rights`): controls which protocol-level operations the consumer may use. For example, you can allow `tools/call` and `tools/list` while blocking `sampling/createMessage`. Use an `allowed` list to restrict to specific methods, or a `blocked` list to exclude specific methods while permitting all others. **Primitive access** (`mcp_access_rights`): controls which specific tools, resources, and prompts the consumer can invoke. Each primitive type (tools, resources, prompts) has its own `allowed` and `blocked` list. Values are Go regular expressions, so `"internal_.*"` matches any tool whose name starts with `internal_`. A non-empty `allowed` list acts as an explicit allowlist; `blocked` entries are excluded from whatever is otherwise permitted. Policy rules apply in addition to the proxy's own `allow` and `block` middleware. A policy cannot give a key access to a primitive that the proxy blocks. ### Rate limiting Rate limits can be applied at four levels within a policy entry for an MCP proxy: **Policy global**: the top-level `rate` and `per` fields on the policy apply across all APIs the key accesses. **Per MCP proxy**: the `limit` field inside an access rights entry applies a rate limit specific to calls to that proxy, independent of the consumer's overall policy rate. **Per JSON-RPC method** (`json_rpc_methods`): sets a rate limit for calls using a specific method name, such as `tools/call`. The counter applies across all tools invoked via that method. **Per primitive** (`mcp_primitives`): sets a rate limit scoped to a specific named tool, resource, or prompt. A consumer who exhausts their limit on `generate_report` is blocked from calling that tool while remaining free to call others. All applicable limits are checked independently on every call. Whichever is exhausted first blocks the request. For example, a call to `get_report` counts against both the `tools/call` method limit and the `get_report` primitive limit, if both are set. Method and primitive limits (`json_rpc_methods` and `mcp_primitives`) are rate limits only. They do not support quotas or throttling. The proxy's own middleware rate limit also applies. It is shared by all consumers. See [Policies versus middleware](/docs/ai-management/mcp-gateway/core-concepts#policies-versus-middleware). ### Quotas A quota sets a maximum total number of calls over a renewal period (daily, weekly, or monthly). A consumer who exhausts their quota receives `429 Too Many Requests` until the period resets. Quotas are configured at the policy level using `quota_max` and `quota_renewal_rate`. See [Quotas](/docs/api-management/request-quotas) for details. *** ## Configuring MCP policies ### Using the Tyk Dashboard 1. In the Tyk Dashboard sidebar, click **Policies** then **Add Policy**. MCP policy list 2. On the **Access Rights** tab, find your MCP proxy in the list and click it to add it to the policy. 3. Expand the proxy's access rights block. You will see sections for primitive rate limits and access control. 4. To configure **primitive rate limits**, click **Add Rate Limit**. Set the **Rate** and **Per** (in seconds) values, then click **Add Primitive** to associate a named tool, resource, or prompt with that limit. Add multiple primitives to the same group if they share a limit; create separate groups for different limits. 5. To configure **access control** for tools, resources, and prompts, use the **Primitive based access** section within the access rights block. Add a name, select the type, and set it to **Allowed** or **Blocked**. 6. On the **Configurations** tab, set the policy name, key expiry, and global rate limit. 7. Click **Create Policy**. ### Using the Dashboard API Create or update a policy via `POST /api/portal/policies` (create) or `PUT /api/portal/policies/{policy-id}` (update). The MCP-specific fields sit inside the `access_rights` entry for each MCP proxy. The following example creates a policy that grants access to a weather MCP proxy, restricts the consumer to read-only methods, limits them to specific tools, and applies per-primitive rate limits: ```json expandable theme={null} { "name": "Weather Agent Standard Tier", "state": "active", "rate": 1000, "per": 60, "quota_max": 50000, "quota_renewal_rate": 86400, "access_rights": { "{mcp-proxy-api-id}": { "api_id": "{mcp-proxy-api-id}", "api_name": "Weather MCP Proxy", "versions": ["Default"], "limit": { "rate": 200, "per": 60 }, "json_rpc_methods_access_rights": { "allowed": ["tools/call", "tools/list", "resources/list", "resources/read"] }, "mcp_access_rights": { "tools": { "allowed": ["get_forecast", "search_weather"] }, "resources": { "blocked": ["internal://.*"] }, "prompts": {} }, "json_rpc_methods": [ { "name": "tools/call", "limit": { "rate": 100, "per": 60 } } ], "mcp_primitives": [ { "type": "tool", "name": "get_forecast", "limit": { "rate": 20, "per": 60 } }, { "type": "resource", "name": "weather://current", "limit": { "rate": 10, "per": 60 } } ] } } } ``` See [Policies](/docs/api-management/policies) for more details. *** ## Policy schema for MCP The MCP-specific fields appear inside each entry in the `access_rights` object, alongside the standard `limit` and `versions` fields. ### Access rights entry | Field | Type | Description | | - | - | - | | `api_id` | string | The ID of the MCP proxy this entry applies to. | | `api_name` | string | Display name of the proxy. | | `versions` | array | Always `["Default"]` for MCP proxies. | | `limit` | object | Per-proxy rate limit for this consumer. Contains `rate` (integer) and `per` (seconds). | | `mcp_access_rights` | object | Primitive-level allow/block lists. See below. | | `json_rpc_methods_access_rights` | object | Method-level allow/block list. Contains `allowed` (array of strings) and `blocked` (array of strings). | | `mcp_primitives` | array | Per-primitive rate limits. Each entry targets one named tool, resource, or prompt. See below. | | `json_rpc_methods` | array | Per-method rate limits. Each entry targets one JSON-RPC method name. See below. | ### `mcp_access_rights` object Controls which primitives the consumer can invoke. Each of the three sub-objects follows the same structure. | Field | Type | Description | | - | - | - | | `tools.allowed` | array of strings | Explicit allowlist of tool names. If non-empty, only listed tools are accessible. Supports Go regular expressions. | | `tools.blocked` | array of strings | Tools to block. Applied after `allowed`. Supports Go regular expressions. | | `resources.allowed` | array of strings | Explicit allowlist of resource URIs. | | `resources.blocked` | array of strings | Resource URIs to block. | | `prompts.allowed` | array of strings | Explicit allowlist of prompt names. | | `prompts.blocked` | array of strings | Prompt names to block. | Leave a sub-object empty (`{}`) to apply no restrictions for that primitive type. ### `mcp_primitives` array Each entry defines a rate limit for one named primitive. | Field | Type | Required | Description | | - | - | - | - | | `type` | string | Yes | Primitive type. Accepted values: `tool`, `resource`, `prompt`. | | `name` | string | Yes | Name of the primitive as exposed by the MCP server. Case-sensitive. | | `limit.rate` | integer | Yes | Maximum calls allowed per time window. Set to `0` for unlimited. | | `limit.per` | integer | Yes | Time window in seconds. Set to `0` for unlimited. | Entries are matched by `type` and `name` together. A tool named `weather` and a resource named `weather` are independent entries with independent counters. ### `json_rpc_methods` array Each entry defines a rate limit for one JSON-RPC method. | Field | Type | Required | Description | | - | - | - | - | | `name` | string | Yes | The JSON-RPC method name, for example `tools/call` or `resources/read`. | | `limit.rate` | integer | Yes | Maximum calls using this method per time window. | | `limit.per` | integer | Yes | Time window in seconds. | ### Top-level policy fields | Field | Type | Description | | - | - | - | | `rate` | integer | Global rate limit across all APIs in the policy. | | `per` | integer | Time window for the global rate limit, in seconds. | | `quota_max` | integer | Maximum total calls in the quota period. Set to `-1` for unlimited. | | `quota_renewal_rate` | integer | Quota renewal period in seconds. Common values: `86400` (daily), `604800` (weekly). | | `key_expires_in` | integer | Key lifetime in seconds from creation. Set to `0` for no expiry. | *** ## When multiple policies apply A consumer key can have multiple policies applied to it. Tyk merges MCP-specific fields as follows: * **Rate limits**: the most permissive limit wins. If two policies define a limit for the same primitive, the higher `rate` value is used. * **`mcp_access_rights` and `json_rpc_methods_access_rights`**: `allowed` lists are merged by union (the consumer gains access to the combined set). `blocked` lists are also unioned, so a primitive blocked in any policy remains blocked. * **Proxy access**: the consumer gains access to the union of all proxies listed across all their policies. A policy with no MCP access rules does not widen access. For example, if policy A allows four tools and policy B has no `mcp_access_rights`, the key can call only those four tools. A primitive that any policy blocks stays blocked, even if another policy allows it. *** ## Applying a policy to a consumer A policy takes effect when it is applied to an access key. In the Tyk Dashboard, go to **Keys**, click **Add Key**, select the policy from the **Apply Policy** dropdown, and generate the key. Issue the key to the consumer; they include it in the `Authorization` header of every MCP request. See [Policies](/docs/api-management/policies) for full details. # MCP Gateway quickstart Source: https://tyk.io/docs/ai-management/mcp-gateway/quickstart Create your first MCP proxy in Tyk Dashboard, connect it to the Tyk Mock MCP Server, and test tool calls with MCP Inspector. Takes about five minutes. An MCP proxy sits between an AI agent and a remote MCP server, routing requests, giving you visibility over every tool call, and letting you apply governance policies without touching the upstream server. You'll create a proxy to the [Tyk Mock MCP Server](https://github.com/TykTechnologies/tyk-mock-mcp-server), connect to it with [MCP Inspector](https://github.com/modelcontextprotocol/inspector), and verify that tool calls are routing correctly through Tyk. *** ## Before you begin * A running Tyk Gateway (v5.13 or later) connected to your Tyk Dashboard. See [Self-managed](/docs/getting-started/quick-start) * A Dashboard user account with MCP write permissions * Go 1.22 or later, or Docker (to run the Mock MCP Server) * Node.js 18 or later (to run MCP Inspector). If you don't have it, download it from [nodejs.org](https://nodejs.org/en/download). *** ## Instructions ### Step 1: Start the Mock MCP Server The Mock MCP Server is the upstream your proxy will route traffic to. It exposes 15 tools across six categories (users, posts, products, analytics, utilities, and streaming) and requires no configuration or credentials. 1. Start the Mock MCP Server using Go or Docker: ```bash theme={null} git clone https://github.com/TykTechnologies/tyk-mock-mcp-server.git cd tyk-mock-mcp-server go build -o tyk-mock-mcp-server . ./tyk-mock-mcp-server ``` ```bash theme={null} docker run -p 7878:7878 ghcr.io/tyktechnologies/tyk-mock-mcp-server:latest ``` 2. Confirm the server is running on `http://localhost:7878`. Leave it running. Your Tyk Gateway must be able to reach `localhost:7878`. If your gateway runs in Docker or on a remote host, replace `localhost` with the appropriate hostname or IP address. *** ### Step 2: Create the MCP proxy 1. In the Tyk Dashboard sidebar, click **MCP**, then click **Add MCP Proxy**. Create MCP proxy This opens the **Create MCP Proxy** screen, where you choose how to create your proxy. 2. Click the **Remote MCP server** card to connect to an existing MCP server by URL. Create MCP Proxy choice screen This opens the three-step creation wizard. 3. **Name your proxy.** Enter `Mock MCP Server`. Tyk derives the listen path from the name automatically. Click **Continue**. Name your MCP proxy 4. **Set the upstream URL.** Enter `http://localhost:7878/mcp`. Click **Continue**. Set the upstream URL 5. **Connect gateways.** Select your gateway instances, or leave blank to deploy to all gateways. Click **Finish**, then click **Save MCP Proxy**. Deploy to gateways The Dashboard displays "MCP proxy successfully created". *** ### Step 3: Find your MCP endpoint 1. Click **Edit** to open the proxy designer. 2. Find the **MCP Proxy URL** at the top of the page and append `/mcp` to get your MCP endpoint. MCP Proxy URL For example, if the Dashboard shows `https://my-gateway.example.com/mock-mcp-server`, your MCP endpoint is: ``` https://my-gateway.example.com/mock-mcp-server/mcp ``` 3. Note this URL down; you'll enter it into MCP Inspector in the next step. *** ### Step 4: Connect with MCP Inspector MCP Inspector is a browser-based tool for testing MCP servers. It handles the session handshake, lists available tools, and lets you call them interactively. 1. Start MCP Inspector: ```bash theme={null} npx @modelcontextprotocol/inspector ``` MCP Inspector downloads automatically on first run. 2. Open the URL printed in your terminal. 3. Set **Transport Type** to `Streamable HTTP`. 4. Set **URL** to your MCP endpoint from Step 3. 5. Click **Connect**. MCP Inspector connect *** ### Step 5: Call a tool 1. Click the **Tools** tab. You'll see all 15 Mock MCP Server tools listed: Tyk has proxied the `tools/list` response from the upstream. 2. Select **get\_users** and click **Run**. The Mock MCP Server responds with a sample user list. The request travelled from MCP Inspector → Tyk Gateway → Mock MCP Server → back through Tyk → MCP Inspector. Your proxy is working. *** ### Step 6: View the call in analytics 1. In the Tyk Dashboard sidebar, go to **Monitoring** → **Activity by MCP**. 2. Check that the `tools/call` request appears under **Primitives Traffic** and **Most Used Primitives**, with `get_users` listed as the invoked tool. The `initialize` handshake from MCP Inspector appears separately with no primitive name, as expected for a session lifecycle call. Analytics data is written by Tyk Pump asynchronously. Allow a few seconds after making a call before checking the analytics page. If no data appears, verify that analytics recording is enabled and that Tyk Pump is running and connected to your storage backend. *** ## Troubleshooting **Connection refused in MCP Inspector**: Check that your Tyk Gateway is running and that the MCP endpoint URL is correct. Confirm the Mock MCP Server is running on port `7878`. **No tools listed**: The proxy connected but the upstream is not reachable. Confirm the Mock MCP Server is running. If your gateway runs in Docker, replace `localhost` in the upstream URL with `host.docker.internal`. *** ## What's next You have a working MCP proxy routing traffic to the Mock MCP Server. The next step is to secure it, adding authentication so only authorized agents can connect. **[How to secure an MCP proxy →](/docs/ai-management/mcp-gateway/how-to-proxy-remote-mcp)** After that, the series continues with: * **Restrict tool access**: Configure a tool allowlist so agents can only call the tools you have approved. See [Block an MCP Tool](/docs/ai-management/mcp-gateway/how-to-block-tool). * **Create access tiers**: Use policies to define different levels of access for different agents. See [MCP proxy policies](/docs/ai-management/mcp-gateway/policies). * **Set up token exchange**: Use RFC 8693 token exchange so the inbound agent token is replaced with a backend-scoped token before reaching the upstream MCP server. See [Token exchange](/docs/api-management/authentication/token-exchange). * **Understand the concepts**: See [MCP Gateway: Core Concepts](/docs/ai-management/mcp-gateway/core-concepts) for the mental model behind sessions, middleware levels, and policies. # REST API to MCP Source: https://tyk.io/docs/ai-management/mcps/api-to-mcp Generate an MCP proxy directly from a Tyk-managed REST API's OpenAPI specification in Tyk Gateway, without building or hosting a separate MCP server. ## Availability | Component | Version | Editions | | :- | :- | :- | | Gateway | Available since [v5.15.0](/docs/developer-support/release-notes/gateway) | Enterprise | ## What Is REST API to MCP Tyk Gateway can generate an MCP proxy directly from a Tyk-managed REST API's OpenAPI specification, turning its operations into MCP tools without a separate MCP server to build or host. Every MCP proxy in Tyk Gateway does one of two things: it fronts a **remote MCP server** you've built and hosted elsewhere, or it's generated this way, directly from a Tyk-managed REST API. This page covers the second case. To generate a proxy this way, you reference an existing [Tyk OAS API](/docs/ai-management/mcp-gateway/mcp-proxy-definitions), and Tyk derives an MCP tool for each REST operation you choose to expose. No changes to the source REST API are required: you don't touch its OpenAPI spec, its code, or its existing consumers. Only a Tyk OAS REST API already onboarded to Tyk can be the source. GraphQL APIs and Tyk Classic API definitions aren't supported. See [Current Limitations](#current-limitations) below. This provides: * **A tool catalog**: derived automatically from the source API and kept in sync on every gateway reload. See [Tool Catalog](#tool-catalog) below. * **Multiple proxies from a single API**: each with its own tool selection, enrichment, and policies, such as a read-only proxy for a reporting agent and a separate write-enabled proxy for an operations agent. See [How to slice one API into multiple MCP proxies](/docs/ai-management/mcp-gateway/how-to-slice-one-api-into-multiple-mcp-proxies). * **A distinct security identity for the proxy**: independent of the keys and policies your existing REST consumers use. See [Proxy Identity and Security](#proxy-identity-and-security) below. ### How a Tool Call Is Handled Calling a tool sends a JSON-RPC `tools/call` request to the MCP proxy, which Tyk translates into an ordinary REST request against the paired API and wraps the response back into the format the agent expects. ```mermaid theme={null} graph LR A[Agent] -->|"tools/call" JSON-RPC request| B[MCP Proxy] B -->|Ordinary REST request| C[Source REST API] C -->|REST response| B B -->|MCP result| A ``` ## Proxy Identity and Security The MCP proxy is itself a distinct consumer of the source REST API, with its own credential and security policy, independent of the keys and policies your existing REST consumers use. This matters because agents call APIs differently from humans and services: an agent decides autonomously which operations to invoke, can be manipulated into calling tools it shouldn't through prompt injection, and produces less predictable traffic. Govern that traffic with its own tool allowlists, rate limits, and RBAC, without touching your source API. ## Tool Catalog Tyk builds the tool catalog by reading the source API's OpenAPI operations. ### Naming Each operation's `operationId` becomes the tool name; operations without one get a deterministic name derived from their HTTP method and path instead. See [Tool naming and discovery](/docs/ai-management/mcp-gateway/core-concepts#tool-naming-and-discovery) for how names are derived and collisions resolved. ### Filtering With an Allow List All operations become tools by default. To narrow that down, create an explicit allow list in the `x-tyk-mcp-server` extension, listing only the operations you want exposed as `allow: true` entries, through whichever interface you use to manage the proxy (see [Creating and Managing a Proxy](#creating-and-managing-a-proxy) below). ### Overriding Names and Descriptions for Agents OpenAPI specs are usually written for human developers or system-to-system integration, not for an agent deciding which tool to call. A cryptic `operationId` or an undocumented parameter can leave a perfectly functional operation hard for an agent to use well. You can override a tool's and each parameter's name and description directly at the proxy layer, independently of the source API's OpenAPI document, making an existing API agent-ready without editing its spec. This configuration lives in the `x-tyk-mcp-server` vendor extension on the MCP proxy's own OAS definition, alongside the `x-tyk-api-gateway` extension every MCP proxy has. See [REST API to MCP x-tyk-mcp-server extension](/docs/ai-management/mcp-gateway/api-to-mcp-definitions) for the full schema. ### Staying in Sync The catalog is derived from the source API's OpenAPI specification at gateway load time rather than stored as a fixed snapshot, so changes to the source operations are picked up on the next gateway reload. Without an allow list, new operations become tools automatically; with one, you need to add them yourself, since only what's explicitly allowed is exposed. ## Creating and Managing a Proxy An MCP proxy generated this way is still just a [Tyk OAS API definition](/docs/ai-management/mcp-gateway/mcp-proxy-definitions) with the `x-tyk-mcp-server` extension added, so any interface that manages a Tyk OAS API definition can create and manage one: * **Tyk Dashboard**: a guided wizard walks you through selecting the source API, choosing which operations to expose, and overriding tool and parameter names and descriptions, with a preview before you save. See [Managing MCP proxies](/docs/ai-management/mcp-gateway/managing-proxies). * **Tyk Operator**: declare the OAS document, including the `x-tyk-mcp-server` extension, in a `ConfigMap` referenced by a `TykMcpProxyDefinition` custom resource, managed the same way as any other Tyk API in a GitOps workflow. See [Tyk Operator: MCP proxies](/docs/product-stack/tyk-operator/mcp-proxy#managing-a-proxy-generated-from-a-tyk-managed-rest-api). * **Tyk Gateway API and Dashboard API**: create, update, and delete the OAS definition directly, including a dry-run mode that previews the expanded tool catalog without persisting it. See [MCP Gateway API extensions](/docs/ai-management/mcp-gateway/mcp-api-extensions). The interface you use doesn't change how the proxy behaves at runtime. The tool catalog and enrichment overrides apply the same way regardless of how the definition was authored. ## Current Limitations The following limitations apply in this release: | Limitation | Detail | | - | - | | Source API format | The source must be a Tyk OAS API already onboarded to Tyk. GraphQL APIs and Tyk Classic API definitions aren't supported as a source. | | One proxy, one source | An MCP proxy pairs with exactly one source REST API. You can't combine operations from multiple REST APIs behind a single proxy. The reverse, slicing one REST API's operations across several MCP proxies, is supported: see [How to slice one API into multiple MCP proxies](/docs/ai-management/mcp-gateway/how-to-slice-one-api-into-multiple-mcp-proxies). | | Request body types | Only JSON and form-urlencoded request bodies are currently supported. An operation with a multipart, XML, or binary request body is still exposed as a tool, but its body isn't included in the tool's schema, so calling it can't carry the original request body. | | Response size | Upstream responses are capped at 1 MiB and truncated beyond that. The cap isn't configurable. | | Transport | Only `POST /mcp` is supported. `GET /mcp`, SSE streaming, and server-initiated notifications aren't available. | | Primitives | A proxy generated this way only ever produces tools. Resources and prompts aren't applicable, since a REST operation has no equivalent primitive. | | Behavioral hints | `readOnlyHint`, `destructiveHint`, `idempotentHint`, and `openWorldHint` can be set directly in the `x-tyk-mcp-server` extension, for example via Tyk Operator or the API, but the Tyk Dashboard's wizard and designer don't yet expose a UI control for them. | # Tyk MCP Servers Source: https://tyk.io/docs/ai-management/mcps/overview The MCP servers Tyk offers: Tyk Docs MCP, Tyk Dashboard MCP, and REST API to MCP in Tyk Gateway. Use MCP Gateway to govern any MCP server. Tyk offers three MCP servers for AI assistants and agents: * **Tyk Docs MCP** lets an AI assistant search and read the Tyk documentation. * **Tyk Dashboard MCP** lets an AI assistant query and manage your Tyk deployment in plain language. * **REST API to MCP** turns your own Tyk-managed REST APIs into MCP tools, inside Tyk Gateway. To govern MCP servers, use [MCP Gateway](/docs/ai-management/mcp-gateway/overview). It sits in front of any MCP server reachable over HTTP, whether a vendor runs it or your own team does. ## Compare Tyk MCP Servers | MCP server | Use it to | Where it runs | | :- | :- | :- | | [Tyk Docs MCP](/docs/ai-management/mcps/tyk-docs-mcp) | Search and read the Tyk docs | Hosted by Tyk at `https://tyk.io/docs/mcp` | | [Tyk Dashboard MCP](/docs/ai-management/mcps/dashboard-api-to-mcp) | Query and manage your Tyk deployment | On your machine, through `npx` | | [REST API to MCP](/docs/ai-management/mcps/api-to-mcp) | Expose your Tyk OAS APIs as MCP tools, with Tyk policies applied | In Tyk Gateway | ## Tyk Docs MCP Tyk Docs MCP connects an AI assistant to the live Tyk documentation. The assistant can then answer questions about Tyk from current content, with links to the relevant docs sections. Tyk hosts the server, so you only add its URL to your assistant: ```bash theme={null} npx add-mcp https://tyk.io/docs/mcp ``` See [Tyk Docs MCP](/docs/ai-management/mcps/tyk-docs-mcp) for manual configuration and supported assistants. ## Tyk Dashboard MCP Tyk Dashboard MCP exposes the Tyk Dashboard API to an AI assistant. You can ask questions such as "Which APIs are active?" or "What is the rate limit on API X?". It includes the Tyk Dashboard OpenAPI specification, so you don't need to supply one. The tool is open source: see the [tyk-dashboard-mcp repository](https://github.com/TykTechnologies/tyk-dashboard-mcp). See [Tyk Dashboard MCP](/docs/ai-management/mcps/dashboard-api-to-mcp) for the configuration and examples. ## REST API to MCP REST API to MCP generates an MCP server from a Tyk OAS API that is already in Tyk. Tyk Gateway turns each REST operation you select into an MCP tool, so you don't build or host a separate MCP server. The generated server is an MCP proxy, so the same MCP Gateway policies, rate limits, and analytics apply to it. Use this option to make your production APIs available to agents under central governance. See [REST API to MCP](/docs/ai-management/mcps/api-to-mcp) for how it works and its current limitations. ## Govern MCP Servers With MCP Gateway [MCP Gateway](/docs/ai-management/mcp-gateway/overview) adds authentication, per-tool access control, rate limits, and observability to MCP traffic. It supports the MCP `2025-11-25` specification from Tyk Gateway v5.13. To manage MCP proxies in Kubernetes, see [Manage MCP Servers with Tyk Operator](/docs/product-stack/tyk-operator/mcp-proxy). ## Publish MCP Servers to Developers The Tyk Developer Portal can publish MCP proxies as products for API consumers: * [View MCP Documentation in the Developer Portal](/docs/portal/mcp-documentation): how MCP products and their tools appear in the Live Portal. * [Test MCP Tools with the Embedded MCP Inspector](/docs/portal/mcp-inspector-playground): call a product's tools before writing agent code. * [Access Protected MCP Proxies with OAuth 2.1](/docs/portal/mcp-oauth-access): get credentials for OAuth 2.1-protected MCP proxies. # AI Management Source: https://tyk.io/docs/ai-management/overview Tyk's AI management capabilities: AI Studio for LLM and application management, and MCP Gateway for governing AI agent access to MCP servers, including MCP servers generated from your REST APIs. As LLMs become part of enterprise systems, teams need a way to govern them. Tyk provides two solutions. **AI Studio** manages the LLMs and AI applications you build. **MCP Gateway** governs AI agent access to MCP servers. It can also turn your own REST APIs into MCP servers. ## AI Management Capabilities Tyk provides two solutions for AI management: ### [AI Studio](/docs/ai-management/ai-studio/overview) Tyk AI Studio manages and deploys AI applications for platform teams. It provides: * **LLM and model management** to connect LLM vendors and models, commercial and in-house, and control which Teams and Users can access each one * **Centralised governance** with role-based access control and compliance tracking * **Cost management** through usage monitoring and budgeting tools * **Credential management** with unified access controls for AI vendor credentials * **A curated AI service catalogue and Chat interface** for building and running AI applications [Explore AI Studio](/docs/ai-management/ai-studio/overview) ### [MCP Gateway](/docs/ai-management/mcp-gateway/overview) Tyk MCP Gateway puts Tyk's API governance layer directly in front of remote MCP servers. This covers everything from GitHub Copilot and Slack to internal tools built by your own teams. It provides: * **Authentication and key management** with full OAuth 2.1 compliance, including Protected Resource Metadata discovery so MCP clients can self-configure * **Access control** at the individual tool, resource, and prompt level, so you can allowlist exactly which MCP primitives each agent can call * **Traffic management** including per-tool rate limiting, timeouts, circuit breakers, and request size limits * **Unified credential management**, so agents authenticate to Tyk once while Tyk handles per-vendor upstream credentials * **Observability** with per-tool analytics alongside the rest of your API traffic in the Tyk Dashboard Direct connections from AI agents to remote MCP servers bypass every organisational control you have. Routing that traffic through Tyk makes it managed, auditable, and policy-enforced. [Explore MCP Gateway](/docs/ai-management/mcp-gateway/overview) ### How they work together Tyk's two AI management capabilities are complementary: * **AI Studio** governs the LLM traffic and AI applications you build. * **MCP Gateway** governs AI agent traffic to MCP servers. These can be remote servers or servers that Tyk generates from your REST APIs. Together, they cover AI traffic in both directions: the applications you create, and the tools your agents call. ### Which one do I need? * **Are you building and hosting your own AI applications or chat interfaces?** Use **AI Studio**. It connects to LLM vendors, runs a Chat interface, and manages budgets. It also controls which Users and Teams can access which LLMs, Tools, and Data Sources. * **Do you need to govern AI agent calls to MCP servers?** Use **MCP Gateway**. It sits in front of any MCP server reachable over HTTP. That includes vendor servers such as Jira or Slack, and servers your own team runs. It adds authentication, per-tool access control, rate limits, and observability. * **Do you run MCP proxies on Tyk Gateway and want AI Studio users and Apps to use them?** Use both, with the [Tyk MCP integration](/docs/ai-management/ai-studio/tyk-mcp-integration). AI Studio imports the proxies from the Tyk Dashboard and publishes them in the AI Portal. It also creates a Tyk key for each App. The Tyk Gateway continues to handle all MCP traffic. * **Do you want to expose your own Tyk-managed REST API as MCP tools?** Use **MCP Gateway** with [REST API to MCP](/docs/ai-management/mcps/api-to-mcp). Tyk generates an MCP server from the API's OpenAPI description, so you don't build or host one. * **Do you want an AI assistant to manage your Tyk deployment or search the Tyk docs?** Connect it to the ready-to-use MCP servers for [Tyk Dashboard](/docs/ai-management/mcps/dashboard-api-to-mcp) and [Tyk Docs](/docs/ai-management/mcps/tyk-docs-mcp). These aren't mutually exclusive. A common setup uses AI Studio to build and govern an internal AI application. Its agents then call out through MCP Gateway to remote MCP servers, and to your own APIs exposed with REST API to MCP. ## Next steps 1. Explore the [AI Studio documentation](/docs/ai-management/ai-studio/overview) 2. Learn how [MCP Gateway](/docs/ai-management/mcp-gateway/overview) governs AI agent traffic to remote MCP servers 3. [Request a demo](https://tyk.io/ai-demo/) to see the platform in action # Create a new client type of an OAuth2.0 Identity Provider Source: https://tyk.io/docs/api-reference/oauth20-providers/create-a-new-client-type-of-an-oauth20-identity-provider /swagger/5.15/enterprise-developer-portal-swagger.yaml post /oauth-providers/{provider_id}/client-types Create a new client type of an OAuth2.0 Identity Provider # Delete a client type for an OAuth2.0 Identity Provider Source: https://tyk.io/docs/api-reference/oauth20-providers/delete-a-client-type-for-an-oauth20-identity-provider /swagger/5.15/enterprise-developer-portal-swagger.yaml delete /oauth-providers/{provider_id}/client-types/{client_type_id} Delete a client type for an OAuth2.0 Identity Provider. If the client type is used in any API Products, the endpoint will return 400 error. To force remove the client, specify `?force=true`. In in this case,the portal will remove the client type, de-associate it from any API Products where it is used and reject any access requests with such API Products. # Delete an OAuth2.0 Identity Provider Source: https://tyk.io/docs/api-reference/oauth20-providers/delete-an-oauth20-identity-provider /swagger/5.15/enterprise-developer-portal-swagger.yaml delete /oauth-providers/{provider_id} Delete an OAuth2.0 provider. The OAuth2.0 provider and all related client types will be removed. If the provider is used in any API Products, the endpoint will return 400 error. To force remove the provider, specify `?force=true`. In in this case,the portal will remove the provider, all its clients, de-associate it from any API Products where it is used and reject any access requests with such API Products. # Get a client type's data Source: https://tyk.io/docs/api-reference/oauth20-providers/get-a-client-types-data /swagger/5.15/enterprise-developer-portal-swagger.yaml get /oauth-providers/{provider_id}/client-types/{client_type_id} Get a client type's data # List all client types for an OAuth2.0 Identity Provider Source: https://tyk.io/docs/api-reference/oauth20-providers/list-all-client-types-for-an-oauth20-identity-provider /swagger/5.15/enterprise-developer-portal-swagger.yaml get /oauth-providers/{provider_id}/client-types List all client types for an OAuth2.0 provider # Update a client type for an Identity Provider Source: https://tyk.io/docs/api-reference/oauth20-providers/update-a-client-type-for-an-identity-provider /swagger/5.15/enterprise-developer-portal-swagger.yaml put /oauth-providers/{provider_id}/client-types/{client_type_id} Update a client type configuration such as its name, allowed grant types, allowed response types, and so on. Any existing credentials with this client type won't be updated, new and pending access requests with this client type will assume the new settings. # Attach a category to a post Source: https://tyk.io/docs/api-reference/posts/attach-a-category-to-a-post /swagger/5.15/enterprise-developer-portal-swagger.yaml post /posts/{post_id}/categories Attach a category to a specific post. # Attach a tag to a post Source: https://tyk.io/docs/api-reference/posts/attach-a-tag-to-a-post /swagger/5.15/enterprise-developer-portal-swagger.yaml post /posts/{post_id}/tags Attach a tag to a specific post. # Create a new post Source: https://tyk.io/docs/api-reference/posts/create-a-new-post /swagger/5.15/enterprise-developer-portal-swagger.yaml post /posts Create a new post. # Delete a post Source: https://tyk.io/docs/api-reference/posts/delete-a-post /swagger/5.15/enterprise-developer-portal-swagger.yaml delete /posts/{post_id} Delete a specific post by its ID. # Detach a category from a post Source: https://tyk.io/docs/api-reference/posts/detach-a-category-from-a-post /swagger/5.15/enterprise-developer-portal-swagger.yaml delete /posts/{post_id}/categories/{category_id} Detach a category from a specific post. # Detach a tag from a post Source: https://tyk.io/docs/api-reference/posts/detach-a-tag-from-a-post /swagger/5.15/enterprise-developer-portal-swagger.yaml delete /posts/{post_id}/tags/{tag_id} Detach a tag from a specific post. # Get a post by ID Source: https://tyk.io/docs/api-reference/posts/get-a-post-by-id /swagger/5.15/enterprise-developer-portal-swagger.yaml get /posts/{post_id} Get a specific post by its ID. # List all posts Source: https://tyk.io/docs/api-reference/posts/list-all-posts /swagger/5.15/enterprise-developer-portal-swagger.yaml get /posts List all posts in the portal. # List categories for a post Source: https://tyk.io/docs/api-reference/posts/list-categories-for-a-post /swagger/5.15/enterprise-developer-portal-swagger.yaml get /posts/{post_id}/categories List all categories associated with a specific post. # List tags for a post Source: https://tyk.io/docs/api-reference/posts/list-tags-for-a-post /swagger/5.15/enterprise-developer-portal-swagger.yaml get /posts/{post_id}/tags List all tags associated with a specific post. # Update a post Source: https://tyk.io/docs/api-reference/posts/update-a-post /swagger/5.15/enterprise-developer-portal-swagger.yaml put /posts/{post_id} Update a post's data such as title, content, status, and more. # Create a new SSO profile Source: https://tyk.io/docs/api-reference/sso-profiles/create-a-new-sso-profile /swagger/5.15/enterprise-developer-portal-swagger.yaml post /sso_profiles Create a new SSO profile # Delete an SSO profile Source: https://tyk.io/docs/api-reference/sso-profiles/delete-an-sso-profile /swagger/5.15/enterprise-developer-portal-swagger.yaml delete /sso_profiles/{profile_id} Delete an SSO profile # Get an SSO profile Source: https://tyk.io/docs/api-reference/sso-profiles/get-an-sso-profile /swagger/5.15/enterprise-developer-portal-swagger.yaml get /sso_profiles/{profile_id} Get an SSO profile by ID # List all SSO profiles Source: https://tyk.io/docs/api-reference/sso-profiles/list-all-sso-profiles /swagger/5.15/enterprise-developer-portal-swagger.yaml get /sso_profiles List all SSO profiles # Update an SSO profile Source: https://tyk.io/docs/api-reference/sso-profiles/update-an-sso-profile /swagger/5.15/enterprise-developer-portal-swagger.yaml put /sso_profiles/{profile_id} Update an existing SSO profile # Add a new header to a webhook Source: https://tyk.io/docs/api-reference/webhooks/add-a-new-header-to-a-webhook /swagger/5.15/enterprise-developer-portal-swagger.yaml post /webhooks/{webhook_id}/headers Adds a new header to an existing webhook. # Create a new webhook Source: https://tyk.io/docs/api-reference/webhooks/create-a-new-webhook /swagger/5.15/enterprise-developer-portal-swagger.yaml post /webhooks Creates a new webhook configuration. # Delete a header by ID for a specific webhook Source: https://tyk.io/docs/api-reference/webhooks/delete-a-header-by-id-for-a-specific-webhook /swagger/5.15/enterprise-developer-portal-swagger.yaml delete /webhooks/{webhook_id}/headers/{header_id} Removes a header from a webhook. # Delete a webhook by ID Source: https://tyk.io/docs/api-reference/webhooks/delete-a-webhook-by-id /swagger/5.15/enterprise-developer-portal-swagger.yaml delete /webhooks/{webhook_id} Removes a webhook using its unique identifier. # Get a header by ID for a specific webhook Source: https://tyk.io/docs/api-reference/webhooks/get-a-header-by-id-for-a-specific-webhook /swagger/5.15/enterprise-developer-portal-swagger.yaml get /webhooks/{webhook_id}/headers/{header_id} Retrieves the details of a specific header associated with a given webhook. Useful for inspecting custom headers configured for webhook delivery. # Get a webhook by ID Source: https://tyk.io/docs/api-reference/webhooks/get-a-webhook-by-id /swagger/5.15/enterprise-developer-portal-swagger.yaml get /webhooks/{webhook_id} Retrieves a webhook using its unique identifier. # List all headers for a webhook Source: https://tyk.io/docs/api-reference/webhooks/list-all-headers-for-a-webhook /swagger/5.15/enterprise-developer-portal-swagger.yaml get /webhooks/{webhook_id}/headers Retrieves all headers for a specific webhook. # List all webhooks Source: https://tyk.io/docs/api-reference/webhooks/list-all-webhooks /swagger/5.15/enterprise-developer-portal-swagger.yaml get /webhooks Retrieves all configured webhooks. # Update a header by ID for a specific webhook Source: https://tyk.io/docs/api-reference/webhooks/update-a-header-by-id-for-a-specific-webhook /swagger/5.15/enterprise-developer-portal-swagger.yaml put /webhooks/{webhook_id}/headers/{header_id} Updates an existing header in a webhook. # Update a webhook by ID Source: https://tyk.io/docs/api-reference/webhooks/update-a-webhook-by-id /swagger/5.15/enterprise-developer-portal-swagger.yaml put /webhooks/{webhook_id} Updates an existing webhook's configuration using its unique identifier. # Outbound Email Configuration Source: https://tyk.io/docs/configure/outbound-email-configuration **Legacy: Tyk Classic Portal** You're viewing documentation for the **Tyk Classic Portal**, which is no longer actively maintained. If you're looking for the latest API documentation for the **new Tyk Developer Portal**, please refer to the [Postman collection](/docs/product-stack/tyk-enterprise-developer-portal/api-documentation/tyk-edp-api) or visit the [Tyk Developer Portal](/docs/portal/overview/intro) section. The Classic Portal is in maintenance mode and will be deprecated soon. For questions or support, contact us at [support@tyk.io](). ### Custom Email Templates The email templates for the Portal and system messages are located in the `portal/email_templates` directory. The Tyk Dashboard will need to be restarted for changes to take effect. ### Supported email drivers * SMTP * Mandrill * Sendgrid * Mailgun * AmazonSES To get email set up for your installation, add the following to your `tyk_analytics.conf` file: ```{.copyWrapper} theme={null} "email_backend": { "enable_email_notifications": true, "code": "{PROVIDER-NAME}", "settings": { // Client provider specific settings go here. You can find the specific field described below }, "default_from_email": "jeff@wheresmyrug.com", "default_from_name": "Jeffrey (The Dude) Lebowski" } ``` #### SMTP > Available from Tyk Dashboard version 1.7 ```{.json} theme={null} "code": "smtp", "settings": { "SMTPUsername": "email@example.com", "SMTPPassword": "examplepassword", "SMTPAddress": "smtp.example.com:587", "TLSInsecureSkipVerify": "false" }, ``` #### SMTP NoAuth > Available from Tyk Dashboard version 1.8 If `SMTPUsername` or `SMTPPassword` is omitted, Tyk assumes that authentication is not required for your SMTP server. When starting up and initialising the email driver, the Dashboard should output a log message as follows: ``` [May 6 13:46:41] INFO email: initializing SMTP email driver [May 6 13:46:41] INFO email: SMTPUsername and/or SMTPPassword not set - smtp driver configured for no-auth [May 6 13:46:41] INFO email: SMTP email driver initialized ``` #### Mandrill ```{.json} theme={null} "code": "mandrill", "settings": { "ClientKey": "xxxxxxxxx" }, ``` #### Sendgrid ```{.json} theme={null} "code": "sendgrid", "settings": { "ClientKey": "xxxxxxxxx" }, ``` #### Mailgun ```{.json} theme={null} "code": "mailgun", "settings": { "Domain": "KEY", "PrivateKey": "KEY", "PublicKey": "KEY" }, ``` #### Amazon SES ```{.json} theme={null} "code": "amazonses", "settings": { "Endpoint": "Endpoint", "AccessKeyId": "Access-key", "SecretAccessKey": "KEY" }, ``` ### Customize your Welcome Emails You can customize the welcome email that a developer recieves when they signup to your portal. You can use images and other HTML formatted content. The following video walks you through the process.