SAP API Management User Guide
SAP API Management User Guide
Example Words or characters quoted from the screen. These include field names, screen titles,
pushbuttons labels, menu names, menu paths, and menu options.
Textual cross-references to other documents.
EXAMPLE Technical names of system objects. These include report names, program names,
transaction codes, table names, and key concepts of a programming language when they
are surrounded by body text, for example, SELECT and INCLUDE.
Example Output on the screen. This includes file and directory names and their paths, messages,
names of variables and parameters, source text, and names of installation, upgrade and
database tools.
Example Exact user entry. These are words or characters that you enter in the system exactly as
they appear in the documentation.
<Example> Variable user entry. Angle brackets indicate that you replace these words and characters
with appropriate entries to make entries in the system.
7 References........................................................................................................................... 498
7.1 Analytics Command Reference ....................................................................................................... 498
API...................................................................................................................................... 498
Developers ........................................................................................................................ 500
Apps................................................................................................................................... 502
API Products ..................................................................................................................... 504
API Resources................................................................................................................... 506
SAP Customer may use SAP API Management to process and monitor personal
information in terms of relevant data protection legislation. It is the SAP
Customer’s responsibility to use the SAP API Management only in compliance
with the relevant data protection laws.
An API is a technology architecture that makes it easy for one application to 'consume' capabilities or data from
another application. By defining stable, simplified entry points to application logic and data, APIs enable
developers to easily access and reuse application logic built by other developers. In the case of 'Web APIs', that
logic and data is exposed over the network.
Since applications that consume APIs are sensitive to changes, APIs also imply a 'contract'. The contract provides
some level of assurance that, over time, the API will change in a predictable manner.
SAP API Management enables you to build APIs and if you have APIs already, expose them directly, while adding a
management and visibility layer. If you have HTTP enabled services, such as SOA-based Web services, they can
also be exposed as APIs via SAP API Management.
Companies today want to make their backend services available on the web so that these services can be
consumed by apps running on mobile devices and desktops. A company might want to expose services that
provide product pricing and availability information, sales and ordering services, order tracking services, and any
other services required by client apps.
Companies often expose services as a set of HTTP endpoints. Client app developers then make HTTP requests to
these endpoints. Depending on the endpoint, the service might then return data, formatted as XML or JSON, back
to the client app.
The client apps that consume these services can be implemented as standalone apps for a mobile device or
tablet, as HTML5 apps running in a browser, or as any other type of app that can make a request to an HTTP
endpoint and consume any response data. These apps might be developed and released by the same company
that exposed the services, or by third-party app developers who make use of publicly available services.
The following image shows this type of mJSOnodel:
SAP API Management Edge, which is built on Java, enables you to provide secure access to your services with a
well-defined API that is consistent across all of your services, regardless of service implementation. A consistent
API:
Makes it easy for app developers to consume your services.
Enables you to change the backend service implementation without affecting the public API.
An API proxy is the HTTP endpoint on SAP API Management Edge that developers use to access your backend
services. While it is possible, you typically do not make individual API proxies available. Instead, you group one or
more API proxies into an API product.
An API product is a bundle of API proxies combined with a service plan. That service plan can set access limits on
API proxies, provide security, allow monitoring and analytics, and provide additional features. API products are
also the central mechanism that SAP API Management Edge uses for authorization and access control to your
APIs.
You have a great deal of flexibility when creating API products. For example, multiple API products can share the
same API proxy. The following figure shows three API products. Notice that all products allow access to API proxy
3, but only product A allows access to API proxy 1.
You can set different properties on each API product. For example, you might make available one API product with
a low access limit, such as 1000 requests per day, for a bargain price. You then release another API product that
provides access to the same API proxy, but with a much higher access limit, for a higher price. Or, you might
create a free API product that allows read-only access to your services, and then sell an API product to the same
API proxies that allows read/write access.
When app developers decide that they want to access your services, they must first register their client app with
your API product. Upon registration, an app developer receives an API key that she must then include in every
request to an API proxy included in the API product. That key is authenticated and, if authentication is successful,
the request is allowed to access your backend service.
At any time, you can revoke the key so that the client app no longer has access to your services. Or, you can define
a time limit on a key so that the developer must refresh the key after a specific time.
You decide how to handle registration requests from developers to access your API products. By using SAP API
Management Edge Developer Services, you can automate the registration process; or you can use a manual
process to control access.
• Create one or more API proxies that map publicly available URLs to your backend services.
• Create an API product that bundles your API proxies.
• Deploy your API proxies and API product.
• Let your developers know that the API product is available.
• Once app developers know about the availability of your API product, they:
• Register their client apps with your API product.
• Receive an API key for the API product.
• Make requests to your services through API proxies (which are bundled in the API product) and pass the API
key with each request.
SAP API Management consists of the API Platform, Analytics Services, and Developer Services that together
provide a comprehensive infrastructure for API creation, security, management, and operations, as well as
powerful backend services for developing client apps.
The following figure shows SAP API Management services:
SAP API Management API Platform are all about creating and consuming APIs, whether you're building API
proxies as a service provider or using APIs, SDKs, and other convenience services as an app developer.
Analytics Services
SAP API Management Analytics Services provides powerful tools to see short and long-term usage trends of your
APIs. You can segment your audience by top developers and apps, understand usage by API method to know
where to invest, and create custom reports on business or operational-level information.
As data passes through SAP API Platform, several default types of information are collected including URL, IP,
user ID for API call information, latency, error data, and so on. You can create policies to add other information,
such as headers, query parameters, and portions of a request or response extracted from XML or JSON. This
information is collected asynchronously from the actual request/response flow and therefore has no effect on API
performance.
Developer Services
SAP API Management Developer Services provide the tools to manage the community of app developers using
your services. Developer Services offers the flexibility to work with internal and external developers and formalize
these relationships with financial models.
Developer Services provides the ability to onboard developers and create a developer portal for your publicly
available API products. App developers connect to your portal to access API documentation, forums, and blogs.
Every SAP API Platform customer can create their own developer portal, either in the cloud or on-premise. The
following figure shows the home page of the default developer portal:
SAP API Management, which is built on Java, enables you to provide secure access to your services with a well-
defined API that is consistent across all of your services, regardless of service implementation. A consistent API:
• Makes it easy for app developers to consume your services.
• Enables you to change the backend service implementation without affecting the public API.
• Enables you to take advantage of the analytics, developer portal, and other features built into SAP API
Management.
The following image shows the architecture with SAP API Management handling the requests from client apps to
your backend services:
Rather than having app developers consume your services directly, they access an API proxy created on SAP API
Management. The API proxy functions as a mapping of a publicly available HTTP endpoint to your backend
service. By creating an API proxy you let SAP API Management handle the security and authorization tasks
required to protect your services, as well as to analyze and monitor those services.
Because app developers make HTTP requests to an API proxy, rather than directly to your services, developers do
not need to know anything about the implementation of your services. All the developer needs to know is:
• The URL of the API proxy endpoint.
• Any query parameters, headers, or body parameters passed in a request.
• Any required authentication and authorization credentials.
• The format of the response, including the response data format, such as XML or JSON.
The API proxy isolates the app developer from your backend service. Therefore you are free to change the service
implementation as long as the public API remains consistent. For example, you can change a database
implementation, move your services to a new host, or make any other changes to the service implementation. By
maintaining a consistent frontend API, existing client apps will continue to work regardless of changes on the
backend.
You can use policies on the API proxy to add functionality to a service without having to make any changes to the
backend service. For example, you can add policies to your proxy to perform data transformations and filtering,
Two different audiences make use of SAP API Management and its services:
• Service providers who create API Proxies and API products to expose backend services.
• App developers who consume these API proxies and API products to create apps for mobile and desktop
devices. Client app developers also use API Platform for data persistence and management.
SAP API Platform provides tools to support both types of audiences.
As a service provider, you can use two different development methods to create, configure, and maintain API
proxies and API products:
• Make HTTP requests to the RESTful API to access API Platform services.
• Use the Management UI.
1.8 Organizations
An organization represents the highest level of the App Services data hierarchy. It contains applications (and the
entities and collections they contain) and is associated with one or more administrators. An organization can be
representative of a company, team, or project. It allows multiple applications to be shared within the organization
with other administrators.
Using the API Platform services API, you can create an organization through a form post and get an organization
by UUID or name. In addition, you can activate or reactivate an organization, generate and retrieve an
organization's client credentials, and get an organization's activity feed. You can also create an organization
application through a form post, generate and retrieve credentials for the application, and delete the application.
You can also get the applications in an organization. Additionally, you can add an admin user to an organization,
get the admin users in an organization, and remove an admin user from an organization.
Before you start building APIs with SAP API Management, you should be familiar with the organizational model of
SAP API Platform. This model defines how your APIs, API products, apps, and app developers are all related within
SAP API Platform.
The following image shows the major components of the SAP API Platform organizational model:
Organization will be created when you perform the onboarding activity. See the Installation and Onboarding Guide
for more details. Once the organization is created, you can add users to your organization, create API proxies and
API products, and register developers and apps. You can later add additional organizations as necessary.
Optional: You can make the organization name as part of URL to your API proxies and part of the URL when
making a request to the SAP API Management API. For example, a typical URL used to access an API proxy has
the form:
http://{org-name}-{env}.<host:port>/v1/weather/forecastrss
The following table describes the components of the organizational model in more detail:
Component Description
API Proxy The users in an organization create one or more API proxies. An
API proxy defines a mapping of a publicly available HTTP
endpoint to a backend service. API proxies can also be
configured to include security (such as OAuth), perform
message transformation (such as XML to JSON), limit traffic to
backend services, and perform other valuable operations on the
request, the response, and with service callouts.
SAP API Platform collects data for analytics on API proxies.
API Product The users in an organization create one or more API products,
where an API product is a bundle of API proxies combined with
a service plan. That service plan can set access limits on API
proxies, provide security, allow monitoring and analytics, and
provide additional features.
SAP API Platform collects data for analytics on API products.
App Developers create one or more client apps that consume your
APIs.
Developers must register their apps with your organization. An
App in SAP API Platform is a representation of a developer's
actual app that provides the developer with an API key to pass
in with every request to your APIs.
Because all apps are registered in your organization, you can
use SAP API Platform to monitor and collect analytic
information on the app and on its use of your APIs.
API key/OAuth token Depending on the authorization mechanism you define for your
APIs, the app passes an API key along with every request to
your APIs. If that key is valid, the request is allowed. SAP API
Platform supports different types of authentication, such as a
simple API key, two-legged OAuth, three-legged OAuth, and
others.
As an API provider, you must define a way for developers to
register their apps. It is by registering their app that you return
to the developer the key required to access your APIs.
At the time of app registration, the developer can choose to
access a single API product or multiple API products. The
developer's actual app uses the same key to access all API
products associated with the app (the registered representation
of the developer's app in SAP API Platform).
At any time, you can revoke the key so that the developer's app
no longer has access to your APIs (even though the registered
representation of the developer's app still exists in your
organization). Or, you can define a time limit on a key so that
the developer must refresh the key after a specific time.
Every organization has a unique software development lifecycle (SDLC). It is often necessary to synchronize and
align API proxy deployment with the same processes that you use today for developing, testing, and deploying
other applications.
API Platform provides tools and RESTful APIs that enable you to integrate API proxy deployment and
management into your organization's SDLC. A common usage of the RESTful API is to write scripts or code that
programmatically deploy API proxies, or that migrate API proxies from one environment to another, as part of a
larger automated process that also deploys or migrates other applications. API Platform makes no assumptions
about your SDLC (or anyone else's, for that matter). Rather, it exposes atomic functions that can be coordinated
by your development team to automate and optimize your API development lifecycle.
Every organization on SAP API Management has at least two deployment environments that are available for API
proxies: 'test' and 'prod'. The distinction between the two environments is arbitrary — each environment is simply
identified by a different set of network addresses (URLs). The goal is to provide you with a domain in which you
can build and verify API proxies before the API is exposed to external developers.
You can leverage these environments to synchronize API proxy development processed with your SDLC. Each
environment is defined by a network address, enabling you to segregate traffic between the API proxies that you
are working on, and those that are being accessed by apps at runtime. The network addresses available for each
environment is defined in the set of VirtualHosts available in that environment.
Inbound server SSL is automatically enabled for each environment. The default VirtualHost is pre-defined in each
environment during onboarding. The secure VirtualHost can be created. Default defines an HTTP address, while
secure defines an HTTP/S address, with pre-configured server-side SSL. In an API proxy configuration, you
indicate which VirtualHosts the ProxyEndpoint should listen on. When promoting to prod, you typically disable
HTTP by removing the default VirtualHost from the API proxy configuration. See the Installation and Onboarding
Guide for more information.
Environments also provide segregation of data and resources. You can, for example, set up different caches in
test and prod, which can be accessed only by API proxies executing in that environment. Additionally, API keys
that are issued in the test environment are not valid in the prod environment, and vice-versa.
The UI provides browser-based tooling that lets you perform most of the tasks necessary to create, configure, and
manage API proxies and API products. There are still a few tasks that require you to use the RESTful APIs, though.
The following image shows the Management UI that you can use to create and configure an API proxy:
The UI simplifies many interactions with platform in the context of a browser-based tool. In the UI, you can:
• Create API proxies
• Create API products
• Manage developers, apps, and other parts of your organization
• Configure your test and production environments
• Access the Console
• Access App Services
• Implement JavaScript
An organization administrator can add a new user on SAP API Management Platform. The new user is
automatically added to the administrator's organization.
When the administrator creates new user, you are automatically added to the administrator's organization with
the role determined by the administrator. This is typically the way you will be added as a new user to an existing
organization.
The SAP API Management Platform is a RESTful API that enables you to access SAP API Management using any
HTTP client. The API enables programmatic scripting to perform development tasks, such as deployment of API
proxies. The RESTful API also provides access to low-level capabilities that are not exposed by the management
UI for reasons of usability. The API is designed to be lightweight and to impose few restrictions on the client code
that consumes it.
As a RESTful API, the SAP API Management Platform follows a pattern in which capabilities are exposed as API
'resources'. API 'resource' is a term derived from the web application description language (WADL) specification.
According to the WADL specification, a RESTful application can be described as a set of resources.
Each resource, in turn, defines a set of methods that act on it. Some examples of the resources exposed by the
SAP API Management API are API proxies, API products, apps, and developers.
Following RESTful principles, you can call HTTP GET, POST, PUT, and DELETE methods on any of the API
resources.
o GET: Retrieves a list of resources, or the profile of a specific resource.
Your organization name is used in the base path for the requests to the SAP API Management Platform API. You
can locate your organization name under User Settings in the SAP API Management UI.
To retrieve a list of API proxies in your organization, you would call GET on:
http://<host:port>/v1/organizations/apibuilders/apis
Many resources are segregated according to environments. Two environments are provided by default: test and
prod. An example of a resource that is scoped by environment is Cache. A default Cache, called 'mycache' is set
up in every environment. You can list Caches by calling GET on the Cache resource as follows:
https://<host:port>/v1/organizations/apibuilders/environments/test/caches
http://<host:port>/v1/organizations/apibuilders/environments/prod
Passing Credentials
The API enforces HTTP Basic Authentication. You always need to pass in your username and password for your
account. These can be passed in as a Base64 encoded header, or as parameters (as demonstrated below) in an
HTTP client. The following is an example of an HTTP Basic Authentication header:
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
To consume the SAP API Management API you require an HTTP client. Many examples in the documentation
provide sample API requests using cURL, a widely-used HTTP client. If you need to install cURL, you can download
it from http://curl.haxx.se.
If you cut and paste a cURL command from the doc to your terminal, you must replace the following variables in
the command with information for your SAP API Management account:
• email: The email for your account
• password: The password for your account in an account
• myorg: The name of your organization
• host:port : The address of the system where the SAP API Management API Platform is installed.
Example
$ curl -k http://<host:port>/v1/organizations/{org_name}/apis -u myname:mypass
If you are using the SAP API Management samples, set the values for your organization, username, and password
in the file /setup/setenv.sh. Once you have done so, you can run the simplified deploy and invoke scripts
provided for each sample API proxy.
Note
Calls to the management API support gzip compression on responses. If you set 'Accept-Encoding: gzip,
deflate' in your API calls, any response greater than 1024 bytes gets returned in gzip format.
Every organization using SAP API Management automatically has at least two environments they can use to
develop, test, and deploy APIs: 'test' and 'prod'. Use the test environment to develop and test your APIs before
making them publicly available. Only your internal developers can access APIs deployed to the test environment.
Deploy your APIs to the prod environment to make them publicly available to app developers.
2.4 Testing
SAP API Platform provides a trace tool that lets you debug end-to-end request and response flows. The trace
results display request and response headers and payloads, policy execution, variable values, and any errors that
may have occurred during the flow.
Key data points for use in troubleshooting:
• Timestamps: Use timestamps to see how long each step takes to execute. Comparing timestamps helps you
isolate the policies that are taking the longest to execute that are slowing down your API calls.
• Base path: By verifying the base path, you can ensure that a policy is routing the message to correct server.
• Results of policy execution: These results let you see if the message is being altered as expected, such as if
the message is being transformed from XML to JSON, or if the message is being cached.
Each Trace session is broken down into the following major steps:
• Original request received from client: Displays the verb and URI path of the request from the client app,
headers, body data, and query parameters.
• Request sent to your backend service: Displays the request message sent to the backend service by the API
proxy.
• Response returned by the backend service: Displays the response headers and payload returned by the
backend service.
• Final response sent to client: The response message returned to the requesting client app once the
response flow has executed.
You expose APIs on SAP API Management by implementing API proxies. An API proxy is a bundle of XML
configuration files and code (such as JavaScript) that implements the facade for your backend HTTP services. API
proxies decouple the developer-facing API from your backend services, shielding developers from code changes
and enabling you to innovate at the SAP API Management without impacting internal applications and
development teams. As development teams make backend changes, developers continue to call the same API
without any interruption.
API proxies manage request and response messages using a 'pipeline' processing model that defines 'Flows'. To
customize the behavior of your API, you attach Policies to request and response Flows.
In an API proxy configuration, there are two types of endpoints:
• ProxyEndpoint: This configuration manages interactions with apps that consume your API. You configure the
ProxyEndpoint to define the URL of your API. You usually attach Policies to the ProxyEndpoint to enforce
security, quota checks, and other types of access control and rate-limiting.
• TargetEndpoint: This configuration manages interactions with your backend services on behalf of consumer
apps. You configure the TargetEndpoint to forward request messages to the proper backend service. You
usually attach Policies to the TargetEndpoint to ensure that response messages are properly formatted for
the app that made the initial request.
You can visualize API proxies as shown by the graphic below. A basic request and response exchange between an
app (HTTP client) and a backend service is managed in an API proxy by a ProxyEndpoint and TargetEndpoint.
An API proxy consists of a bundle of XML configuration files and code (such as JavaScript and Java). SAP API
Management provides several ways for you to create API proxies, including:
• Using the SAP API Management UI to define an API proxy in a Graphical User Interface (GUI).
• Creating XML files, along with any other supporting files, that define your API proxy and then importing them
into SAP API Management.
• Using the SAP API Management's API to create your API proxies by making a series of REST requests to SAP
API Management.
SAP API Management enables you to control API behavior without writing any code by using policies. A policy is
like a module that implements a specific, limited management function as part of the proxy request/response
flow. Policies are designed to let you add common types of management capabilities to an API easily and reliably.
Policies provide features like security, rate-limiting, transformation, and mediation capabilities, saving you from
having to code and maintain this functionality on your own.
API proxies manage request and response messages using a pipeline processing mode, where the pipeline
consists of a sequence of flows. You attach SAP API Management policies to different flows in the pipeline,
depending on the type of policy and the action that you want to perform.
1. PreFlow
PreFlows always execute first, and the logic you attach in the PreFlow applies to all calls made to the API proxy.
They are useful when you need to make sure that a policy or code executes before anything else happens. For
example, you usually don't want an API proxy to waste any resources on an unauthenticated user. Also, you don't
want to service an app that has exceeded its quota. To support these requirements, you put security and quota
policies in the PreFlow segment. That way, you don't need to worry about a condition failing to evaluate. The
policies will always execute before any other processing takes place.
2. Conditional Flow
API proxy programming starts to get interesting when you implement 'branching' logic for an API. For example,
you might want to convert XML to JSON only when the requesting app is running on a mobile device; or create a
new HTTP response header when the /foo API resource is called; or you might want to return a targeted ad based
on the data in the user's request. You can do this by setting up conditional flows.
3. PostFlow
As with PreFlow, the logic you attach to the PostFlow applies to all calls made to the API proxy. PostFlow is useful
when you need to log some data, send a notification that something happened, transform the message format,
and so on.
A route determines the path of a request from the ProxyEndpoint to the TargetEndpoint. Included in the route is
the URL used to access the API ProxyEndpoint and the URL of the backend service defined by the TargetEndpoint.
After you create an API proxy on SAP API Management, the default URL that an app uses to access the proxy has
the form:
http://{org-name}-{env-name}.<host:port>/{base-path}/{resource-path}
https://{org-name}-{env-name}.<host:port>/{base-path}/{resource-path}
where:
{org-name} is your organization name. This name is created when you create an account on SAP API
Management.
{env-name} is the SAP API Management environment name. By default, all SAP API Management organizations
created in the cloud are provisioned with two environments: 'test' and 'prod'. When deploying an API proxy, you
can choose to deploy it to one or both environments.
{base-path} and {resource-path} are defined when you create the API proxy.
When a request comes in to SAP API Management, SAP API Management parses the URL to direct the request to
the correct ProxyEndpoint. For example, the following URL is used to access an API proxy on SAP API
Management:
http://myOrg-prod.<host:port>/v1/weather/forecastrss
A virtual host defines the domains and ports on which an API proxy is exposed. A virtual host also defines whether
the API proxy is accessed by using the HTTP protocol, or by the encrypted HTTPS protocol.
The second part of the URL, /v1/weather, is determined by the <BasePath> element in the ProxyEndpoint. The
base path must be unique to the API proxy for the environment so that two API proxies do not have the same base
path.
The third part of the URL, /forecastrss, is a resource defined by the API proxy with the corresponding Conditional
Flow defined by the <Flows>tag.
Direct URL
A ProxyEndpoint can directly invoke a backend service, bypassing any named TargetEndpoint configuration. For
example, the following<RouteRule> always makes an HTTP call to http://api.mycompany.com/myAPI:
<RouteRule name="default">
<URL>http://api.mycompany.com/myAPI</URL>
</RouteRule>
However, because there is no TargetEndpoint, you can only add policies to the flows defined by the
ProxyEndpoint.
Single target
In a single target definition, the ProxyEndpoint references a single TargetEndpoint definition by name, as shown in
the figure above:
<RouteRule name="default">
<TargetEndpoint>default</TargetEndpoint>
</RouteRule>
Conditional targets
The <RouteRule> tag lets you direct a request to a target based on a condition. You can use flow variables, query
parameters, HTTP headers, message content, or contextual information such time of day and locale to determine
the target endpoint. For example, you might include a geographical area, such as US and UK, in a request URL.
You can then route a request to a target endpoint based on the region.
The following route rule evaluates an HTTP header in a request. If the HTTP header routeTo has the
value TargetEndpoint1, then the request is forwarded to the TargetEndpoint named TargetEndpoint1. If not, then
the request is forwarded to TargetEndpoint2.
<RouteRule name="MyRoute">
<Condition>request.header.routeTo = "TargetEndpoint1"</Condition>
<TargetEndpoint>TargetEndpoint1</TargetEndpoint>
</RouteRule>
<RouteRule name="default">
<TargetEndpoint>TargetEndpoint2</TargetEndpoint>
</RouteRule>
If you have multiple route rules, create one as the 'default', that is, as a route rule with no condition. Ensure that
the default route rule is defined last in the list of conditional Routes because rules are evaluated top-down in the
ProxyEndpoint.
Null route
A null route supports scenarios in which the request message does not need to be forwarded to a TargetEndpoint.
This is useful when the ProxyEndpoint performs all of the necessary processing, for example by using JavaScript
to call an external service.
The following example defines a null route:
<RouteRule name="GoNowhere"/>
When you make a request to an API proxy, you can pass any or all of the following information, depending on the
way the API proxy is configured:
• Request headers
• Query params
• Form data
• XML or JSON payloads
• Resource URIs
The same is true for the response received by SAP API Management from the backend service. By default, all data
received in the response is passed unchanged to the app that originated the request.
A client app then makes a GET request to the API proxy by using the following cURL command:
curl -X GET http://myOrg-prod.<host:port>/v1/weather/forecastrss?w=12797282
Notice that this request contains the resource "forecastrss" and one query param, "w". SAP API Management
parses the request as shown below and assigns parts of the request to flow variables:
{request.verb} {proxy.basepath}/{proxy.pathsuffix}?{request.querystring}
Note
There are many different flow variables created during the processing of a request and response.
{request.verb} {target.basepath}/{proxy.pathsuffix}?{request.querystring}
Notice how the resource and query params specified in the request are automatically included in the request to
the backend server. From the definition of the TargetEndpoint, the request then has the form:
Like query params, any headers or form params that you include in the request to the API proxy are passed on to
the backend server. For example, you make the request below that includes a header:
In both examples, the headers and form data are passed unchanged to the backend service. The headers are
represented by flow variables such asrequest.headers.count and request.headers.names. The form data is
represented by flow variables such as request.formparam.countand request.formparam.names.
The same is true for data in the response. As part of processing the response, the API proxy might want to modify
the data before returning it to the requesting app.
SAP API Management defines several policies that you can use to process the request and response data. These
policies include:
• Assign Message policy: Creates or modifies HTTP request or response messages during an API proxy flow.
Also creates and populates new flow variables.
• Extract Variables policy: Extract content from messages, including headers, URI paths, payloads, and query
parameters, for use in a condition statement. The policy then applies a text pattern to message content and
upon finding a match sets a designated variable.
• JSON to XML policy and XML to JSON policy: Converts messages from JavaScript Object Notation (JSON) to
the extensible markup language (XML) format, or vice versa.
• Java Callout policy, JavaScript policy, Python Script policy, Regular Expression Protection policy: These
policies let you write a script to access flow variables containing request and response data.
Every organization has a unique software development lifecycle (SDLC). It is often necessary to synchronize and
align API proxy deployment with the same processes that you use today for developing, testing, and deploying
other applications.
API Services provides tools and RESTful APIs that enable you to integrate API proxy deployment and
management into your organization's SDLC. A common usage of the RESTful API is to write scripts or code that
programmatically deploy API proxies, or that migrate API proxies from one environment to another, as part of a
larger automated process that also deploys or migrates other applications. API Services makes no assumptions
about your SDLC (or anyone else's, for that matter). Rather, it exposes atomic functions that can be coordinated
by your development team to automate and optimize your API development lifecycle.
API Services APIs are documented in the API Reference.
Environments
Every organization on SAP API Management has at least two deployment environments that are available for API
proxies: 'test' and 'prod'. The distinction between the two environments is arbitrary — each environment is simply
identified by a different set of network addresses (URLs). The goal is to provide you with a domain in which you
can build and verify API proxies before the API is exposed to external developers.
You can leverage these environments to synchronize API proxy development processed with your SDLC. Each
environment is defined by a network address, enabling you to segregate traffic between the API proxies that you
are working on, and those that are being accessed by apps at runtime. The network addresses available for each
environment is defined in the set of VirtualHosts available in that environment.
<HTTPProxyConnection>
<BasePath>/v0/weather</BasePath>
<Properties/>
<VirtualHost>default</VirtualHost>
<VirtualHost>secure</VirtualHost>
</HTTPProxyConnection>
By deleting the default VirtualHost from the ProxyEndpoint configuration, you create an API proxy that listens
only on HTTPS and not on HTTP.
<HTTPProxyConnection>
<BasePath>/v0/weather</BasePath>
<Properties/>
<VirtualHost>secure</VirtualHost>
</HTTPProxyConnection>
You can see which VirtualHosts are available in an environment by selecting Environments in the management UI
main menu.
Environments also provide segregation of data and resources. You can, for example, set up different caches in
test and prod, which can be accessed only by API proxies executing in that environment. Additionally, API keys
that are issued in the test environment are not valid in the prod environment, and vice-versa.
When you create an API proxy you'll need to decide which environment you'll be working in. You can choose to
create a new API proxy on production, but that is not recommended as you may expose an API to developers
before it's ready. In general you want to start by creating an API proxy in testwhich, after testing, you then
'promote' to prod.
Note
Depending on your role, you may not be able to deploy to all environments. For example, the 'user' role
can only deploy to the testenvironment. If you're an administrator you can deploy to any environment.
As you work on an API proxy, API Services saves iterations of your configuration as revisions. When you deploy an
API proxy, you choose a specific revision to deploy. Typically, you deploy the most recent revision, and, if
necessary, revert to the previous revision number. You can choose where to deploy those revisions. For instance,
you can promote a revision to prod to allow developers to start working with your API. At the same time, you may
be iterating multiple revisions on test, where you're adding features or fine-tuning policies. Then, when you're
ready, you can deploy the new revision to prod, overwriting the existing revision on that environment. Using this
method, you can always have a live revision of your API available to developers while you're developing.
Promotion to prod
When an API proxy has been fully implemented and tested, it is ready to be promoted to 'prod'. The revision of the
API proxy in test will be used to overwrite the revision of the API proxy deployed on prod.
API Services provides capabilities to ensure seamless deployment of API proxies, minimizing the impact on apps
and end users during the deployment procedure.
Scripting deployment
The SAP API Management UI enables you to deploy API proxies to prod directly from the API proxy builder.
However, in many situations the requirements for security, reliability, and consistency will mandate that
development teams script deployment procedures. To do so, you can write code and scripts that invoke the
RESTful API exposed by API Services.
Environment resources
For additional control during promotion, it is recommended that you only iterate on API proxies in test, and make
as few changes as necessary to API proxies deployed in prod.
To do so, you need to ensure that certain resources associated with each environment are configured in such a
way that they can remain static in an API proxy configuration.
• Target URLs: It is common for API proxies to call different backend URLs during testing and production. You
can use TargetServer configurations to create environment-independent TargetEndpoint configurations.
• Caches and Key/value maps: Both persistence resources are scoped by environment. You should ensure that
naming conventions are used to enable API proxies to store data without requiring configuration changes
during promotion.
• ServiceCallout targets: Service callouts may use different targets depending on the environment, if, for
example, a ServiceCallout in the test environment consumes a demo service.
To make API proxy configurations environment-independent, you can also use conditional statements.
Conditional statement built with theenvironment.name variable can be used to evaluate the current environment
before enforcing a policy or before routing to a URL on the backend.
There are several concepts that are common ideas with a unique meaning in SAP API Management.
Term Definition
API An 'application programming interface' is an architecture that makes it easy for one
application to 'consume' capabilities or data from another application.
By defining stable, simplified entry points to application logic and data, APIs enable developers
to easily access and reuse application logic built by other developers. In the case of 'Web APIs',
that logic and data is exposed over the network. Since applications that consume APIs are
sensitive to changes, APIs also imply a 'contract'. The contract provides some level of
assurance that, over time, the API will change in a predictable manner.
API proxy A facade on SAP API Management for one or more APIs, generic HTTP services, or
applications (such as Node.js).
An API proxy is implemented as a set of configuration files, policies, and code that rely on a set
of resources provided by SAP API Management. API proxies can be generated and configured
using the SAP API Management UI, or they can be implemented locally in a text editor or IDE.
The facade provided by an API proxy decouples the developer-facing API from 'backend'
services, shielding developers from code changes and enabling innovation at the SAP API
Management without impacting your internal development teams. As development teams
make backend changes, developers continue to call the same interface uninterrupted. SAP API
Management enables you to expose multiple interfaces to the same API, freeing you to
customize the signature of an API to meet the needs of various developer niches
simultaneously.
API base path APIs defined by network addresses and URIs. An API is made up of a 'base path' and a set of
and resources 'API resources'. Every API proxy defines a base path and, optionally, multiple API resource
paths. You can think of an API simply as a set of URIs, all of which share a common base path.
To make it easier to manage your APIs, SAP API Management augments these raw URIs with
display names and descriptions. SAP API Management enables you to attach policies and code
to URIs, enabling fine-grained control and management of the behavior of your APIs.
API product A collection of API resources (URIs) combined with a quota, or 'service plan', which is
published to app developers at design time. API products can in turn be bundled into API
packages for monetization.
An API key is bound to one or more API products, enforcing a binding between an app and the
bundle of URIs that the app is permitted to consume.
API package A collection of API products that are presented to developers as a bundle, and typically
associated with a rate plan defined in monetization.
app An abbreviation of 'application'. The term 'app' has come to refer to mobile applications that
consume APIs. Developers implement apps in a variety of programming languages, and using
various technologies and platforms. Developers who want to consume APIs register apps in an
API provider's organization on SAP API Management.
When the app is registered, SAP API Management generates an API key and secret that
identify the app. The developer embeds the API key in the app, which presents the key when
environment A runtime execution context for API proxies. An API proxy must be deployed to an
environment before the API it exposes is accessible over the network. By default,
organizations are provisioned with two environments: 'test' and 'prod'.
The 'test' environment is typically used for deploying API proxies during development.
The 'prod' environment is typically used for promoting API proxies from the test environment
after they have been fully developed and tested.
organization A container for all the objects in an SAP API Management account, including API proxies, API
products, API packages, apps, and developers.
A user account is required for each organization for which you are a member. (Most users will
have an account in only one organization.) You need to supply your credentials (username and
password) and the name of your organization with each API request you submit.
policy A processing step that executes as an atomic, reusable unit of logic within an API proxy
processing flow.
Typical policy-based functionality includes transforming message formats, enforcing access
control, calling remote services for additional information, masking sensitive data from
external users, examining message content for potential threats, caching common responses
to improve performance, and so on.
Policies may be conditionally executed based on the content or context of a request or
response message. For example, a transformation policy may be executed to customize a
response format if the request message was sent from a smartphone.
API resource A RESTful concept, a resource path is a uniform resource identifier (URI) that identifies the
path network path to a given resource.
revision A numbered, version-controlled package of configuration and policies bundled into an API
Proxy. This term is distinguished from 'version', which is the developer-facing API interface.
See version above.
The purpose of this document is to provide a set of standards and best practices for developing with SAP API
Management. The topics that are covered here include design, coding, policy use, monitoring, and debugging. The
information has been gathered by the experience of developers working with SAP API Management to implement
successful API programs. This is a living document and will be updated from time to time.
Framework-style coding
Framework-style coding involves storing API proxy resources in your own version control system for reuse across
local development environments. For example, to reuse a policy, story it in source control so that developers can
sync to it and use it in their own proxy development environments.
• To enable DRY ("don't repeat yourself"), where possible, policy configurations and scripts should implement
specialized, reusable functions. For example, a dedicated policy to extract query parameters from request
messages could be called ExtractVariables.ExtractRequestParameters. A dedicated policy to inject
CORS headers could be called AssignMessage.SetCORSHeaders. Those policies could then be stored in
your source control system and added to each API proxy that needs to extract parameters or set CORS
headers, without requiring you to create redundant (and hence less manageable) configurations.
• Clean up unused policies and resources (JavaScript, Java, XSLT, etc.) from API proxies, especially large
resources that have the potential to slow down import and deploy procedures.
Naming Conventions
• The Policy name attribute and the XML policy file name must be identical.
• The Script and ServiceCallout policy name attribute and the name of the resource file should be identical.
• DisplayName should accurately describe the policy’s function to someone who has never worked with that
API proxy before..
• Name policies according to their function, for
example AssignTargetAuthHeader or AssignMessage.TargetAuthHeader,RaiseFault.InvalidUser.
• Use proper extensions for resource files, .js for JavaScript, .py for python, and .jar for Java JAR files.
• Variable names should be consistent. If you choose a style, such as camelCase or under_score, use it
throughout the API proxy.
• Use variable prefixes, where possible, to organize variables based on their purpose, for
example, Consumer.username and Consumer.password.
Construct Flows in an organized manner. Multiple Flows, each with a single condition, are preferable to multiple
conditional attachments to the same PreFlow and Postflow.
As a 'failsafe', create a default API proxy with a ProxyEndpoint BasePath of /. This can be used to redirect base
API requests to a developer site, to return a custom response, or perform another action more useful than
returning the default CLASSIFICATION_ERROR.
Use TargetServer resources to decouple TargetEndpoint configurations from concrete URLs, supporting
promotion across environments.
If you have multiple RouteRules, create one as the 'default', that is, as a RouteRule with no condition. Ensure that
the default RouteRule is defined last in the list of conditional Routes. RouteRules are evaluated top-down in
ProxyEndpoint.
To prevent memory issues in SAP API Management, message payload size is restricted to 3MB.
Exceeding those sizes results in a protocol.http.TooBigBody error.
Following are the recommended strategies for handling large message sizes in SAP API Management:
• Stream requests and responses. Note that when you stream, policies no longer have access to the message
content.
• In SAP API Mangement deployments, edit the message processor http.properties file to increase the limit
in the HTTPResponse.body.buffer.limit parameter. Be sure to test before deploying the change to
production.
Fault Handling
• Leverage FaultRules to handle all fault handling. (RaiseFault policies are used to stop message Flow and send
processing to the FaultRules Flow.)
• Within the FaultRules Flow, use AssignMessage policies to build the fault response, not RaiseFault policies.
Conditionally execute AssignMessage policies based on the fault type that occurs.
• Always includes a default 'catch-all' fault handler so that system-generated faults can be mapped to
customer-defined fault response formats.
• If possible, always make fault responses match any standard formats available in your company or project.
• Use meaningful, human-readable error messages that suggest a solution to the error condition.
Key/Value Maps
• Use key/value maps only for limited data sets. They are not designed to be a long-term data store.
• Consider performance when using key/value maps as this information is stored in the Cassandra database.
Response Caching
• Do not populate the response cache if the response is not successful or if the request is not a GET. Creates,
updates, and deletes should not be cached. <SkipCachePopulation>response.status.code != 200 or
request.verb != “GET”</SkipCachePopulation>
• Populate cache with a single consistent content type (for example, XML or JSON). After retrieving a
responseCache entry, then convert to the needed content type with JSONtoXML or XMLToJSON. This will
prevent storing double, triple, or more data.
• Ensure that the cache key is sufficient to the caching requirement. In many cases, the request.querystring can
be used as the unique identifier.
• Do not include the API key (client_id) in the cache key, unless explicitly required. Most often, APIs secured
only by a key will return the same data to all clients for a given request. It is inefficient to store the same value
for a number of entries based on the API key.
• Set appropriate cache expiration intervals to avoid dirty reads.
• Ideally, the response cache policy should be attached to the ProxyEndpoint response PostFlow, before any
format translations (XMLToJSON, JSONToXML)
• The response cache policy to lookup the cache entry should occur in the ProxyEndpoint request PreFlow.
Avoid implementing too much logic, other than cache key generation, before returning a cache entry.
Otherwise, the benefits of caching are minimized.
• In general, you should always keep the response cache lookup as close to the client request as possible.
Conversely, you should keep the response cache population as close to the client response as possible.
JavaScript
• Use JavaScript if it’s more intuitive than SAP API Management policies (for example, when
setting target.url for many different URI combinations).
• Complex payload parsing such as iterating through a JSON object and Base64 encoding/decoding.
• JavaScript policy has a time limit, so infinite loops are blocked.
Java
• Use Java if performance is the highest priority, or if the logic cannot be implemented in JavaScript.
• Include Java source files in source code tracking.
Python
• Do not use Python unless absolutely required. Python scripts can introduce performance bottlenecks for
simple executions, as it is interpreted at runtime.
JavaScript
• JavaScript on the API Platform supports XML via E4X.
Java
• When accessing message payloads, try to
use context.getMessage() vs. context.getResponseMessage or context.getRequestMessage. This ensures
that the code can retrieve the payload, in both request and response flows.
• Import libraries to the SAP API Management organization or environment and do not include these in the JAR
file. This reduces the bundle size and will let other JAR files access the same library repository.
• Import JAR files using the SAP API Management resources API rather than including them inside the API
proxy resources folder. This will reduce deployment times and allow the same JAR files to be referenced by
multiple API proxies. Another benefit is class loader isolation.
• Do not use Java for resource handling (for example, creating and managing thread pools).
• Use @IOIntensive annotation for all Java classes. This will cause the class to run in a separate thread pool.
Otherwise it runs in an I/O thread, which is in the core thread pool and has the potential to block the CPU.
Python
• Throw meaningful exceptions and catch these properly for use in SAP API Management fault responses
AccessEntity Policy
For better performance, look up apps by uuid instead of app name.
Logging
Use a common syslog policy across bundles and within the same bundle. This will keep a consistent logging
format.
Monitoring
Cloud customers are not required to check individual components of SAP API Management (Routers, Message
Processors, etc.). SAP API Management’s Global Operations team is thoroughly monitoring all of the
components, along with API health checks, given health check requests by the customer.
Trace
The trace tool in the SAP API Management UI is useful for debugging runtime API issues, during development or
production operation of an API.
Security
• Use IP address restriction policies to limit access to your test environment. Whitelist the IP addresses of you
development machines or environments.
• Always apply content protection policies (JSON and or XML) to API proxies that are deployed to production.
ServiceCallouts
• Don't make ServiceCallouts to other API proxies in the same organization, including recursive callouts back
into the same API proxy.
• Build a ServiceCallout request message using the AssignMessage policy, and populate the request object in a
message variable. (This includes setting the request payload, path, and method.)
• The URL that is configured within the policy requires the protocol specification, meaning the protocol portion
of the URL, https:// for example, cannot be specified by a variable. Also, you must use separate variables for
the domain portion of the URL and for the rest of the URL. For example: https://{domain}/{path}
• Store the response object for a ServiceCallout in a separate message variable. You can then parse the
message variable and keeps the original message payload intact for use by other policies.
SAP API Management enables you to quickly expose backend services as APIs. You do this by creating an API
proxy that provides a facade for the backend service that you want to expose. You only need to provide the
network address for the backend service, along with some information that API Platform uses to model the API
that will be exposed to developers.
The API proxy that you create on SAP API Platform decouples your backend service implementation from the API
that developers consume. This shields developers from future changes to your backend services. As you update
backend services, developers, insulated from those changes, can continue to call the API uninterrupted.
This topic shows you how to create a simple API proxy that runs on SAP API Management.
The easiest way to create an API proxy is using the API proxy builder tool, which is available in the SAP API
Management UI.
1. Log in into the SAP API Management UI.
2. From the main menu, select APIs > API Proxies.
A list of all API proxies in your organization displays.
3. To create a new API proxy, select add (+) API Proxy button.
The New API Proxy form is displayed.
Use this form to provide API Platform with the information it needs to generate an API proxy and, optionally,
to add some minimal features to the API that is exposed.
This form enables you to create an API proxy from the following sources:
o An existing HTTP service (this could be a JSON or XML API)
o An existing API proxy bundle
o A WSDL file
o An API proxy with no API backend ("No target")
o A Node.js application
The following sections describe how to create an API proxy using each source.
You can use this capability to import any API proxies that you or other developers have configured.
1. In the New API Proxy dialog box, under Choose Your Starting Point section:
1. Select the API Bundle.
2. Select Choose File.
3. Navigate to the ZIP file containing the API proxy configuration
2. Under Identify Your API Proxy, enter a descriptive name for your API.
3. Select Build
In response, you should see an acknowledgment that your new API proxy was successfully imported. API
Platform automatically deploys the imported API proxy to the 'test' environment in your organization. The API
exposed by the API proxy is available to be invoked.
You can copy an existing API proxy to a new API proxy, or backup and existing API proxy to a set of XML files as an
API proxy bundle. Once exported to a bundle, you can import the API proxy to a new proxy, as described above.
You can specify that one proxy is the target endpoint of another, effectively connecting the two proxies in a proxy
chain.
You might find this useful when you have a proxy that offers some discrete low-level functionality that one or more
other proxies will consume. For example, a proxy that exposes create/read/update/delete operations with a
backend data store could be the target proxy for multiple other proxies that expose the data to clients.
To minimize network overhead when calling one proxy from another, you can specify that one proxy is the local
target endpoint of the other. This kind of connection, called proxy chaining, gives you a local connection between
two proxies. This local connection is more efficient because it bypasses network features such as load balancers,
routers, and message processors. When you specify a proxy as a local target endpoint, processing flows to that
proxy as it would to another kind of target.
Note:
Proxies you want to connect in this way must be in the same organization and environment. When the proxy
you're connecting with is outside this scope, consider connecting to it as an external resource using
the HTTPTargetConnection element.
You connect proxies by specifying that one is a local target endpoint of the other. You can create a local
connection between proxies in two ways:
• By specifying the name of the target proxy and a ProxyEndpoint name
• By specifying a path to the target proxy endpoint
You can specify the target proxy by name. You might find that this is most useful when you're creating the
connection from the start and developing the proxies together. If you don't know the name (or the name might
change), consider connecting with the target proxy's endpoint path, as described below.
When you connect to a target proxy by name, you specify the proxy's name and the name of its ProxyEndpoint.
The following example specifies a target proxy called data-manager, along with the ProxyEndpoint name
exposed by data-manager.
<TargetEndpoint name="datamanager">
<PreFlow name="PreFlow">
<!-- PreFlow policies -->
</PreFlow>
<PostFlow name="PostFlow">
<!-- PostFlow policies -->
</PostFlow>
<LocalTargetConnection>
<APIProxy>data-manager</APIProxy>
<ProxyEndpoint>default</ProxyEndpoint>
</LocalTargetConnection>
</TargetEndpoint>
You can specify the target proxy by its endpoint path. You might want to do it this way when you don't know the
proxy name, or when the name might change.
If your proxy is simply the consumer of the target proxy -- such as when you're not developing both -- the path
might be the most reliable way to connect. For example, if the proxy you're connecting to is developed and
maintained by another team, you might want to connect using a reliable endpoint path.
The following example specifies a target proxy at /v1/streetcarts/foodcarts/data-manager, where the
host is assumed to be the same as the current proxy
<TargetEndpoint name="datamanager">
<PreFlow name="PreFlow">
<!-- PreFlow policies -->
You can create proxy chaining connections using the SAP API Management Edge console.
1. Open the proxy that will be consuming the target proxy.
2. In the Navigator, click the plus sign next to Target Endpoints.
3. In the New Target Endpoint dialog, enter the name of the target endpoint.
4. Beneath the Target Endpoint Name box, select one of the following:
• Proxy Chaining to select from a list of proxies already in the organization and environment.
1. In the Proxy Name dropdown, select the target proxy.
2. In the Proxy Endpoint box, enter the target proxy endpoint path you want to connect to.
• Path Chaining to enter the target proxy base path, such a /mypath/myproxy/myendpoint.
5. Click Add.
You can create two kinds of SOAP proxies in SAP API Management. One generates a RESTful interface to the
backend SOAP service and the other performs a "pass through" of the SOAP message to the backend. For details,
see Exposing a SOAP service as an API proxy.
When you add an API proxy for an existing backend service or import an existing API bundle, the New API
Proxy page displays an Add Features section in which you can add features to your API such as security and
support for CORS.
Note
If you import an API bundle, then you are responsible for configuring security in the bundle. The UI does
not prompt you to add security when importing the bundle.
Check Security with API Keys to add simple API key verification to the API proxy that you are defining. In
response, the SAP API Management adds a VerifyAPIKey policy and an AssignMessage policy to your API proxy.
The VerifyAPIKey policy validates API keys presented by requesting apps. The AssignMessage policy strips the
API key, supplied in the API call as a query parameter, from the request forwarded to the backend server.
If you select Secure with OAuth v2.0 Access Tokens, SAP API Management will automatically add two policies to
your API proxy: one policy to verify an access token and another policy to strip the access token from the
message before forwarding it to your backend service. To learn how to obtain an access token, see OAuth.
When you check Secure with API Keys, the New API Proxy page displays an additional checkbox:
Impose Quota per Developer. Check this to add a Quota policy to your API proxy that enforces a limit on the traffic
to your API from individual apps.
CORS (Cross-origin resource sharing) is a standard mechanism that allows a Web browser to make direct
requests to another domain. The CORS standard defines a set of HTTP headers that Web browsers and servers
use to implement cross-domain communication.
You can add support for CORS to your API by selecting the Enable Direct Browser Access for your API checkbox
under Add Features. For more detailed information about CORS support, including adding CORS preflight support
to a proxy, see Adding CORS Support to an API proxy.
Flows are the basic building blocks of API proxies. Flows enable you to program the behavior of an API by letting
you configure the sequence in which policies and code are executed by an API proxy.
For a conceptual overview of flows, see Understanding flows.
SAP API Management comes with many different types of predefined policies to implement security, manage
traffic, and manipulate messages. In addition, policies let you add your own custom code to completely customize
message processing.
For example:
• Attach an OAuth security policy to the request PreFlow of the ProxyEndpoint. Because the ProxyEndpoint's
request PreFlow is the first flow in the pipeline, you can immediately reject a request if it violates your security
policies.
• Attach a JSON to XML conversion policy to the response PostFlow of the TargetEndpoint to convert a
response from JSON to XML.
• Attach a JavaScript policy to a Conditional Flow of the ProxyEndpoint to execute JavaScript code to process
the request
Once you have created a conditional flow, it is available for Policy attachment. When you select New > Policy after
you create the flow, you will see an additional option in the list of flows. As shown below, when adding a Quota
policy, you now have the option to attach the Policy to the flow called Flow-1, which you just created.
By attaching the Policy to Flow-1, you are configuring the API proxy to enforce the Quota Policy only for requests
submitted using the GET verb. The Quota will not be enforced for POSTs, PUTs, etc.
The following ProxyEndpoint definition shows the underlying source XML with a policy named quota-2 on
the request PreFlow of the ProxyEndpoint:
<ProxyEndpoint name="default">
<PreFlow name="PreFlow">
<Request>
<Step>
<Name>quota-2</Name>
</Step>
Any policies attached to the PreFlow or PostFlow are always executed. However, the policies in a conditional flow
are executed only if the flow's condition evaluates to true.
During the processing of a request and response, only one conditional flow is executed per segment--the first flow
whose condition evaluates to true. That means you can have one conditional flow executed as part of each of the:
For example, the following ProxyEndpoint definition shows a conditional flow that is executed by the
ProxyEndpoint on any HTTP GET request to the API proxy:
<ProxyEndpoint name="default">
<PreFlow>
<Request/>
<Response/>
</PreFlow>
<Flows>
<Flow name="Flow-1">
<Condition>request.verb="GET"</Condition>
<Request/>
<Response/>
</Flow>
</Flows>
<PostFlow>
In an API proxy, you can define a conditional flow that corresponds to a specific resource:
<ProxyEndpoint name="default">
<PreFlow>
<Request/>
<Response/>
</PreFlow>
<Flows>
<Flow name="Flow-1">
<Condition>(proxy.pathsuffix MatchesPath "/reports")</Condition>
<Request/>
<Response/>
</Flow>
<Flow name="Flow-2">
<Condition>(proxy.pathsuffix MatchesPath "/forecasts")</Condition>
<Request/>
<Response/>
</Flow>
</Flows>
<PostFlow>
<Request/>
<Response/>
</PostFlow>
...
</ProxyEndpoint>
In this brief example, you set up a flow that executes only when the request message is an HTTP GET.
To add a conditional flow, select the Develop view in the API proxy builder. Select New > Conditional Flow.
The New Conditional Flow form enables you name the flow and to add a condition. In this example, you add a
condition that evaluates the HTTP of the request message. You add a condition that will evaluate to true if the
HTTP verb is GET (as opposed to PUT, POST, etc.)
The form also enables you to add the flow to the ProxyEndpoint named default or the TargetEndpoint
named default.
Select the Proxy endpoint default option.
The new flow, called Flow-1, now appears in the Navigator menu.
Now observe the XML configuration for the ProxyEndpoint. Select Flow-1 in the Navigator menu.
You will see the following configuration.
<PreFlow name="PreFlow">
<Request/>
<Response/>
</PreFlow>
<Flows>
<Flow name="Flow-1">
<Request/>
<Response/>
<Condition>request.verb="GET"</Condition>
</Flow>
Conditional statements are a common control structure in all programming languages. Like a programming
language, API proxy configuration supports conditional statements for Flows, Policies, and RouteRules. By
defining conditional statements, you define dynamic behavior for your API. This dynamic behavior lets you do
things like converting XML into JSON only for mobile devices, or routing to a backend URL based on the
content type or HTTP verb of the request message.
This topic shows you how to use conditions to dynamically apply API management features at runtime,
without writing any code.
Conditional behavior is implemented in API proxies by using a combination of conditions and variables. A
conditional statement is created using a Condition element. The following is an empty condition:
<Condition></Condition>
To create a conditional statement, you add a conditional operator and a variable to create the following structure:
<Condition>{variable.name}{operator}{"value"}</Condition>
Supported conditional operators include = (equals), != (not equal), and > (greater than). For readability, you can
also write the conditionals as text: equals, notequals, greaterthan.
When working with URI paths you can use ~/ or MatchesPath. You can also use conditions to evaluate regular
expressions.
Variables
Conditions do their work by evaluating the values of variables. A variable is a property of an HTTP transaction
executed by an API proxy, or a property of an API proxy configuration itself. Whenever an API proxy gets a
request from an app, API Platform populates a long list of variables that are associated with things like system
time, the app's network information, HTTP headers on messages, the API proxy configuration, policy
executions and so on. This creates a rich context that you can use to setup conditional statements.
Variables always use a dotted notation. For example, HTTP headers on the request message are available as
variables called request.header.{header_name}. So to evaluate the Content-type header, you could use the
variablerequest.header.Content-type. For example request.header.Content-
type ="application/json" indicates that the variable value should be JSON.
Recommendation
API Platform automatically stores all HTTP headers and query parameters as variables that can be
accessed using request.header and request.queryparam variable prefixes.
To enable dynamic behavior, you can attach Conditions to Flows, Steps, and RouteRules.
When you attach a condition to a Flow, you create a 'conditional Flow'. Conditional Flows execute only when
the condition evaluates to true. You can attach as many Policies as you want to a conditional Flow. A
conditional Flow enables you to craft highly specialized processing rules for request or response messages
that meet certain criteria.
For example, to create a Flow that executes only when the request verb is a GET:
<Flows>
<Flow name="ExecuteForGETs">
<Condition>request.verb="GET"</Condition>
</Flow>
</Flows>
As shown in the example below, you can apply the condition to the Policy Step itself. The following Condition
causes the VerifyApiKey Policy to be enforced only if a request message is a POST.
<PreFlow name="PreFlow">
<Request>
<Step>
<Condition>request.verb equals "POST"</Condition>
<Name>VerifyApiKey</Name>
Once you have defined such conditional Flows, you can attach Policies to them, enabling an API proxy to
enforce one set of policies for GET requests, and another set of policies for POST requests.
Recommendation
The XML To JSON policy type defines a set of reasonable defaults, which means that you only need to add
configuration elements to craft XML into specific JSON structures.
Since you want to convert responses from XML to JSON, you need to configure a conditional response Flow to
perform the conversion. For example, to convert all responses from XML to JSON before they are returned to
the client app, configure the following ProxyEndpoint response Flow.
<Flows>
<Flow name="Convert-for-devices">
<Response>
<Step><Name>ConvertToJSON</Name></Step>
</Response>
</Flow>
</Flows>
When you invoke the API using the standard request, the response is formatted in JSON.
However, your goal is to only convert Weather reports into JSON when the requesting client is a mobile device. To
enable such dynamic behavior, you must add a conditional statement to the Flow.
The following example shows a single conditional flow named Convert-for-devices, configured in the
ProxyEndpoint response Flow. Add the Condition as an element to the entity to which the condition applies. In this
example, the condition is a component of the Flow. Therefore, the Flow will execute whenever the statement
evaluates to true.
<Flows>
<Flow name="Convert-for-devices">
<Condition>(request.header.User-Agent = "Mozilla")</Condition>
<Response>
<Step><Name>ConvertToJSON</Name></Step>
</Response>
</Flow>
</Flows>
For each request received from an app, API Platform stores the values of all HTTP headers present as variables. If
the request contains an HTTP header called User-Agent, that header and its value are stored as a variable called
request.header.User-Agent.
Given the ProxyEndpoint configuration above, API Platform checks the value of the request.header.User-
Agent variable to see whether the condition evaluates to true.
If the condition does evaluate to true, that is, the value of the variable request.header.User-
Agent equalsMozilla, then the conditional Flow executes and the XMLtoJSON policy called ConvertToJSON is
enforced. If not, the Flow is not executed, and the XML response is returned unmodified (in XML format) to
the requesting app.
Sample Conditions
Conditional Flow
<!-- this entire flow is executed only if the response verb is a GET-->
<Flow name="GetRequests">
<Condition>response.verb="GET"</Condition>
RESTful services are collections of API resources. An API resource is a URI path fragment that identifies some
entity that developers can access by calling your API. For example, if your service backend provides weather
reports and weather forecasts, your API might define two API resources: /reports and /forecasts.
Recommendation
The term resource is used in the Web Application Description Language (WADL) specification. This is just
for convenience. It doesn't necessarily imply any endorsement of WADL. According to WADL, a RESTful
API consists of a base path and any number of resource paths. Resources are sometimes called API
With an API proxy URL mapped to the base URL of the backend service (when you create the proxy), you can add
conditional flows to specific resources, such as the /reports and /forecasts resources mentioned earlier.
Let's say you wanted to have SAP API Management "do something" when calls come in to
the /reports or /forecasts resources. At this point you're not telling SAP API Management what to do, just that it
should be listening for calls to those resources. You do this with conditions. In your SAP API Management API
proxy, you can create conditional flows for /reports and /forecasts. For conceptual purposes, the following API
proxy XML shows what those conditions might look like.
<Flows>
<Flow name="reports">
<Description/>
<Request/>
<Response/>
<Condition>(proxy.pathsuffix MatchesPath "/reports") and
(request.verb = "GET")</Condition>
</Flow>
<Flow name="forecasts">
<Description/>
<Request/>
<Response/>
Those conditions say, "When a GET request comes in with /reports and /forecasts in the URL, SAP API
Management will do whatever you (the API developer) tell it to, through the policies you attach to those flows.
Now here's an example of telling SAP API Management what to do when a condition is met. In the following API
proxy XML, when a GET request is sent to https://<host>:<port>/mygreatweatherforecast/reports, SAP API
Management executes the "XML-to-JSON-1" policy in the response.
<Flows>
<Flow name="reports">
<Description/>
<Request/>
<Response>
<Step>
<Name>XML-to-JSON-1</Name>
</Step>
</Response>
<Condition>(proxy.pathsuffix MatchesPath "/reports") and
(request.verb = "GET")</Condition>
</Flow>
In additional to those optional conditional flows, each API proxy also comes with two default flows:
a <PreFlow> executed before your conditional flows, and a <PostFlow> executed after your conditional flows.
Those are useful for executing policies when any call is made to an API proxy. For example, if you want to verify an
app's API key with every call, regardless of the backend resource being accessed, you could put a Verify API Key
policy on the <PreFlow>.
Defining conditional flows to backend resources in an API proxy is completely optional. However, those
conditional flows give you the ability to apply fine-grained management and monitoring.
You will be able to:
For example, imagine that you need to apply different types of management to /developers than to /apps.
To do so, you add two API resources: /developers and /apps.
In the Develop view of the API proxy builder, select New > Resource.
In the Navigator menu, you can see that two flows have been created: Apps and Developers.
http://{org-name}-{env}.<host:port>/{proxy_path}/apps
will cause the condition to evaluate to true, and this flow, along with any associated policies, will execute.
You can further refine resource definitions by specifying the HTTP verb associated with a call:
For example you may need to treat the "create app" method differently than "list apps". To do so, specify the
HTTP verb associated with the API resource. In this example, you need to manage the Create App method, so
select the POST method.
Select Add.
Adding this API resource results in a new flow. The new flow is added to the ProxyEndpoint for the API proxy that
you are building. If you look at the ProxyEndpoint configuration, you will see that the following flow configuration
has been added:
<Flow name="CreateApp">
<Description>Creates an app</Description>
<Request/>
<Response/>
<Condition>(proxy.pathsuffix MatchesPath "/apps") and (request.verb =
"POST")</Condition>
</Flow>
For example, the following condition uses a Java regular expression to recognize calls made to the /apps resource
with or without a trailing forward slash (/apps or /apps/**):
<Condition>(proxy.pathsuffix JavaRegex "/apps(/?)") and (request.verb =
"POST")</Condition>
In some cases, you will have hierarchical API resources. For example, the Developer Services API provides a
method for listing all apps that belong to a developer. The URI path is:
/developers/{developer_email}/apps
You may have resources where a unique ID is generated for each entity in a collection, which is sometimes
annotated as follows:
/genus/:id/species
This path applies equally to the following two URIs:
/genus/18904/species
/genus/17908/species
To represent this structure in an API resource, you can use wildcards. For example:
/developers/*/apps
And
/genus/*/species
will resolve these hierarchical URIs as API resources appropriately.
In some cases, especially for deeply hierarchical APIs, you may simply want to resolve everything below a certain
URI fragment. To do so, use a double asterisk wildcard in your resource definition. For example, if you define the
following API resource:
/developers/**
That API resource will resolve the following URI paths:
/developers/{developer_email}/apps
/developers/{developer_email}/keys
/developers/{developer_email}/apps/{app_id}/keys
The benefit of defining API resources is that you gain the ability to apply policies to requests that invoke those
specific URIs, providing granular control over the data and services that your API proxy exposes. Additionally, SAP
API Management collects operation metrics specific to the API resources you define. By defining specific API
resources, you gain the visibility required to identify performance bottlenecks or error conditions as they affect
specific calls against your API.
Resources can be used to control access to specific assets or objects in your API. If you disable an API resource,
or if you add a security policy to it, you are effectively blocking all the apps that call that resource.
Flow variables are named references that hold state associated with an API transaction processed by SAP API
Management. They exist within the context of an API proxy flow, and they track state in an API transaction the way
named variables track state in a software program. Flow variables store information such as:
• The IP address, headers, URL path, and payload sent from the requesting app
• System information such as the date and time when SAP API Management receives a request
• Data derived when a policy executes. For example after a policy executes that validates an OAuth token, SAP
API Management creates flow variables that hold information like the name of the requesting application.
• Information about the response from the target system
Some variables are "built-in" to SAP API Management and are automatically populated whenever an API request
is received. They are available throughout an API transaction. You can also create your own custom variables
using policies like AssignMessage or in JavaScript, Node.js, and Java code. As you'll see, variables have scope,
and where they are accessible depends in part on when they are created in the API proxy flow. In general, when a
variable is created, it is available to policies and code that execute later in the API transaction flow.
Flow variable are used in policies and conditional flows. Policies can retrieve state from flow variables and use
them to do their work. For example, a VerifyAccessToken policy can retrieve the token to be verified from a flow
variable and then perform the verification on it. As another example, a JavaScript callout can retrieve flow
variables and encode the data contained within those variables. Conditional flows can reference flow variables to
direct the flow of an API through SAP API Management, kind of like the way a switch statement works in
Let's look at examples of how variables are used in each of these contexts.
Some policies take flow variables as input. For example, the following AssignMessage policy takes the value of the
flow variable client.ip and puts it in a request header called My-Client-IP. If added to the request flow, this policy
sets a header that is passed to the backend target. If set on the response flow, the header would be sent back to
the client app.
<AssignMessage name="set-ip-in-header">
<AssignTo createNew="false" transport="http" type="request">request</AssignTo>
<Set>
<Headers>
<Header name="My-Client-IP">{client.ip}</Header>
</Headers>
</Set>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</AssignMessage>
For another example, when a Quota policy executes, several flow variables are populated with policy-related
values. One of these variables is called ratelimit.my-quota-policy.used.count (where my-quota-
policy is the name of the quota policy you're interested in). You might later execute a conditional flow that says
"if the current quota count is below 50% of maximum, and it's between 9 am and 5 pm, enforce a different quota."
This condition might depend on the value of the current quota count and on a flow variable called system.time,
which is one of the built-in SAP API Management variables.
Conditional flows evaluate flow variables and enable proxies to behave dynamically. Conditions are typically used
to change the behavior of flows, steps, and route rules. Here's a conditional flow that evaluates the value of the
variable request.verb in a proxy flow step. In this case, if the request verb is POST, the VerifyApiKey policy is
executed. This is a common pattern used in API proxy configurations.
<PreFlow name="PreFlow">
<Request>
<Step>
<Condition>request.verb equals "POST"</Condition>
Using the JavaScript policy, you can execute JavaScript code from within the context of an API proxy flow.
JavaScript that is executed by this policy uses the SAP API Management JavaScript Object Model, which provides
your custom code access to request, response, and context objects associated with the API proxy flow in which
your code is executing. For example, this code sets a response header with the value obtained from the flow
variable target.name.
context.setVariable("response.header.X-SAP-Target",
context.getVariable("target.name"));
This techniqe of using JavaScript to read and set variables is similar to the work you can do with the
AssignMessage policy (shown previously). It's just another way to accomplish the same kinds of things on SAP
API Management. The key to remember is that JavaScript executed by the JavaScript policy has access to all the
flow variables that are exist and are in scope within the API proxy flow.
By requiring the SAP API Management-access module, you can set and access flow variables from within Node.js
code that is deployed to SAP API Management.
Here's a simple example where a variable called custom.foo is set to the value Bar. Once set, this new variable
becomes available to any policies or other code that occurs in the proxy flow after the Node.js code executes.
var http = require('http');
var sap = require('sap-access');
Variable scope is related to the flow or overall "life cycle" of an API proxy call.
To understand flow variable scope, it's important to understand or visualize the way messages flow through an
API proxy. An API proxy consists of a series or message processing steps organized as a flow. At every step in a
proxy flow, the proxy evaluates information available to it and decides what to do next. Along the way, the proxy
may execute policy code or perform conditional branching.
Keep this flow structure in mind as we begin to explore flow variables through the rest of this topic.
As soon as you can visualize how messages flow through a proxy, as described previously, you can begin to
understand variable scope. By scope, we mean the point in the proxy flow life cycle when a variable is first
instantiated. For example, if you have a policy attached to the ProxyEndpoint request segment, that policy will not
be able to access any variables that are scoped to the TargetEndpoint request segment. The reason for this is that
the TargetEndpoint request segment of the flow has not executed yet, so the API proxy hasn't had a chance to
populate variables in that scope.
The following table lists the complete set of variable scopes and indicates when in the proxy flow they become
available.
always available As soon as the proxy receives a request. These variables are
available through the entire proxy flow life cycle.
For example, there's a built-in SAP API Management variable called client.ip. This variable has "proxy request"
scope. It is automatically populated with the IP address of the client that called the proxy. It is populated when a
request first hits the ProxyEndpoint and remains available through the entire proxy flow life cycle.
There's another built-in variable called target.url. This variable's scope is "target request". It is populated in the
TargetEndpoint request segment with the request URL sent to the back-end target. If you try to
access target.url in the ProxyEndpoint request segment, you will receive a NULL value. If you try to set this
variable before it is in scope, the proxy does nothing—does not generate an error and does not set the variable.
Note
It's possible to configure some policies to either throw an error or return NULL when an undefined
variable is accessed. Refer to individual policy reference pages for details.
Here's a simple example that demonstrates how to think about variable scope. Suppose you want to copy the
entire contents of a request object (headers, parameters, body) and assign it to the response payload to be sent
back to the calling app. You can use the AssignMessage policy for this task. The policy code looks like this:
<AssignMessage name="CopyRequestToResponse">
<AssignTo type="response" createNew="false">response</AssignTo>
<Copy source="request"/>
</AssignMessage>
All built-in variables in SAP API Management follow a dot-notation naming convention. This convention makes it
easier to determine the purpose of the variable. For example system.time.hour and request.content.
Note
This dot-notation convention is strictly for naming purposes. For example, request.content does not
refer to a parent variable or object called "request". You can name custom variables anything you wish.
There is no requirement to include a dot. SAP API Management considers following this naming
convention a best practice whenever you create your own custom flow variables. It can be useful to use
the dots to organize your custom variables. For example approval.code and approval.status both
might refer to an approval feature within the flow. SAP API Management uses prefixes like request, target,
system, and response to organize relevant variables appropriately.
When you reference a variable in a policy, you must enclose it in curly braces. For example, this simple
AssignMessage policy takes the value of the variable client.ip and puts it in a request header called Client-
IP.
<AssignMessage name="set-ip-in-header">
<AssignTo createNew="false" transport="http" type="request">request</AssignTo>
<Set>
<Headers>
<Header name="Client-IP">{client.ip}</Header>
</Headers>
</Set>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</AssignMessage>
In conditional flows, the curly braces are not necessary. For example, this condition evaluates the
variable request.header.accept.
<Step>
<Condition>request.header.accept = "application/json"</Condition>
<Name>XMLToJSON</Name>
</Step>
Flow variables have a well-defined data type, such as string, long, integer, boolean, and collection. You can find the
data types listed for each built-in SAP API Management flow variable in the Variables reference. For policy-created
variables, refer to the specific policy reference topic for data type information. Finally, variables you create
manually assume the type given when they were created, and depend on the types of values that are allowed. For
example, variables created in Node.js code are restricted to number, String, boolean, null, or undefined.
Many policies create flow variables as part of their normal execution. The Policy reference documents all of these
policy-specific variables. As you work with proxies and policies, be sure to consult the Policy reference to find out
which variables are created and what they are used for. For example, the Quota policy creates a set of variables,
that contain information about quota counts and limits, expiry time, and so on. See the section "Policy-specific
variables" in Quota policy for the complete list. Some policy variables are useful for debugging. You can use the
Trace tool, for instance, to see which variables were set at a particular instance in a proxy flow.
The ExtractVariables policy lets you populate custom variables with data extracted from messages. You can
extract query parameters, headers, and other data. For example, you can parse request and response messages
using patterns to extract specific data from the messages.
In this example, ExtractVariables is used to parse a response message and store specific data taken from the
response. Two custom variables are created and assigned values. The variables are
called geocoderesponse.latitude and geocoderesponse.longitude.
<ExtractVariables name="ParseGeocodingResponse">
<Source>response</Source>
<VariablePrefix>geocoderesponse</VariablePrefix>
<JSONPayload>
<Variable name="latitude">
<JSONPath>$.results[0].geometry.location.lat</JSONPath>
</Variable>
<Variable name="longitude">
<JSONPath>$.results[0].geometry.location.lng</JSONPath>
</Variable>
</JSONPayload>
</ExtractVariables>
Again, be aware that many policies automatically create variables. You can access those variables within the
proxy flow context, and they are documented in the Policy reference under each individual policy topic.
You can access and set variables directly in JavaScript code that is executing in the context of an API proxy.
Through the SAP API Management JavaScript Object Model, JavaScript executing on SAP API Management has
direct access to proxy flow variables.
To access variables in JavaScript code, call getter/setter methods on any of these objects:
• proxyRequest
• targetRequest
• targetResponse
• proxyResponse
• context
As you can see, these object references map to the familiar segments of the proxy flow model as explained
previously in "Visualizing the flow of an API proxy."
The context object corresponds to "globally" available variables, such as system variables. For example, you can
call getVariable() on the contextobject to get the current year:
var year = context.getVariable('system.time.year');
Similarly, you can call setVariable() to set the value of a custom variable or for any writable out-of-the-box
variables. Here, we create a custom variable called organization.name.myorg and assign a value to it.
Because this variable is created with the context object, it will be available to all flow segments (essentially, this is
like creating a global variable).
You can also get/set proxy flow variables in Java code that you execute with the JavaCallout policy.
You can get, set, and delete flow variables from Node.js code deployed to SAP API Management. All you need to
do is "require" the SAP API Management-access module in your code.
You can combine policies and resources into a shared flow that you can consume from multiple API proxies, and
even from other shared flows. Although it's like a proxy, a shared flow has no endpoint. It can be used only from an
API proxy or shared flow that's in the same organization as the shared flow itself.
By capturing in one place functionality that's useful in multiple places, a shared flow helps you ensure consistency,
shorten development time, and more easily manage code.
You can call a shared flow using the Flow Callout policy. Also, by attaching a shared flow to a flow hook, you can
have the shared flow execute before a proxy or target request, or after a proxy or target response.
For example, imagine you have areas of functionality that are either used in multiple places or must be
standardized across APIs in your organization. You could have a shared flow for each category, including:
• security, with authorization code using OAuth and API key verification, as well as threat protection code.
• logging, for generating standard error messages.
• mediation, for transforming between XML and JSON message formats.
In the following illustration, two API proxies call out (with a FlowCallout policy) to a shared flow to authenticate
incoming user requests. The AuthSharedFlow has been deployed separately to the org before the proxies so that
it is available to support requests from the proxies. A shared flow can be developed and managed by a team
responsible for broad company policies, then consumed in proxies by line-of-business teams building more
specialized apps.
When developing a shared flow, you must always test it with calls sent to an API proxy. In other words, you can't
send requests directly to a shared flow as you would an API proxy. Instead, you send requests to an API proxy
which is, in turn, calling out to the shared flow.
2. Develop a shared flow by implementing policies and supporting resources, just as you would when
developing an API proxy.
A shared flow is a sequence of conditional steps. So developing one is like developing an API proxy. You can
include policies and resources you might include in a proxy.
For example, as part of your traffic management support, you might implement a Spike Arrest policy to allow
only 30 requests per second, as in the following example:
<SpikeArrest async="false" continueOnError="false" enabled="true" name="Spike-
Arrest">
<DisplayName>Spike Arrest</DisplayName>
<Properties/>
<Identifier ref="request.header.some-header-name"/>
<MessageWeight ref="request.header.weight"/>
<Rate>30ps</Rate>
</SpikeArrest>
Then, to a shared flow for traffic management, you could attach the Spike Arrest policy as a step. The policy
would execute for any API proxy that calls the shared flow.
<SharedFlow name="default">
<Step>
<Name>Spike-Arrest</Name>
</Step>
</SharedFlow>
As with API proxies, you can import a zip file containing your shared flow source artifacts (see Import a new
API Proxy for more about importing proxies). The following illustrates how to import a shared flow with
the management API:
curl -X POST -F "file=@/path/to/zip/file.zip" \
'https://api.enterprise.apigee.com/v1/o/{org_name}/sharedflows?action=import&nam
e=shared-flow-name' \
-u email:password
You can deploy a shared flow with a management API call such as the following:
curl -X POST --header "Content-Type: application/octet-stream" \
https://api.enterprise.apigee.com/v1/o/{org_name}/e/{env_name}/sharedflows/{shared_
flow_name}/revisions/{revision_number}/deployments \
-u email:password
You can also replace a currently deployed shared flow with no downtime.
Here's the request form using the management API:
curl -X POST --header "Content-Type:application/x-www-form-urlencoded" \
https://api.enterprise.apigee.com/v1/o/{org_name}/e/{env_name}/sharedflows/{shared_
flow_name}/revisions/{revision_number}/deployments?"override=true" \
-u email:password
4. Develop the consuming API proxy so that it can call the shared flow as part of its own flow.
From an API proxy, you call to a shared flow with a Flow Callout policy.
Note: To consume a shared flow, an API proxy must be deployed after the shared flow and to the same
environment as the shared flow. The shared flow has to be in place when you want to test a call to it using the
Flow Callout policy.
To consume a shared flow, you add a Flow Callout policy to the proxy or shared flow that will consume it. Like
a Service Callout policy, with which you call out to another service, a Flow Callout calls out to the shared flow.
In the following code, a Flow Callout policy calls out to a shared flow called traffic-management-shared.
<FlowCallout async="false" continueOnError="false" enabled="true" name="Traffic-
Management-Flow-Callout">
<DisplayName>Traffic Management Flow Callout</DisplayName>
<Properties/>
<SharedFlowBundle>traffic-management-shared</SharedFlowBundle>
</FlowCallout>
5. Deploy the consuming API proxy to begin using the shared flow.
6. Develop iteratively by tracing, as you would with an API proxy.
As with an API proxy, you develop a shared flow by iteratively invoking and tracing until you have the logic the
way you want it. In this case, because the shared flow doesn't run on its own, you invoke a proxy endpoint and
trace the proxy.
Here are the steps:
1. Make sure that both the shared flow and the API proxy calling it with a Flow Callout policy are in the same
organization and deployed to the same environment.
When you use the SAP API Management Edge UI to create a shared flow, you can either create one from scratch
or by importing existing flow sources as a flow bundle .zip file.
1. In the management console, select the organization within which you want to create the shared flow.
The shared flow will be available to any API proxies and shared flows deployed to an environment from this
organization. It won't be available from outside this organization.
2. Click the APIs > Shared Flows menu.
On the Shared Flows page, you can view a list of shared flows in the organization. You can edit or delete flows
in the list.
3. Click the + Shared Flow button to begin adding a new shared flow.
4. On the Build a Shared Flow page, choose how you want to created the new flow:
o Create a new flow from scratch. You'll be able to configure policies and resources as steps in the flow.
1. Select Empty Shared Flow.
2. Enter a name value. This will be the name that API proxies and other shared flows use to reference
this shared flow. The name should be descriptive to developers consuming the flow.
3. Enter a description to provide more information about what the flow does.
4. Click Next.
5. Optionally, select the environments to which you want the new flow deployed.
For example, if you'll be testing the shared flow from API proxies deployed to the test environment,
then deploy the shared flow to test.
6. Click Build and Deploy to have the new shared flow created and deployed to the environment(s) you
selected. If you selected no environment, the shared flow will be created, but not deployed.
You can call a shared flow from a proxy or from another shared flow by using the Flow Callout policy.
1. In the SAP API Management Edge management console, locate the proxy or shared flow from which you want
to call another shared flow.
2. In the Navigator, next to Policies, click the + button.
3. In the list of policies, under Extension, click Flow Callout.
4. Enter the display name and name (unique identifier), then select the shared flow that this policy will call.
5. Click Add.
6. Add the new Flow Callout policy to the proxy where you want the call to be made.
SAP API Management enables you to 'program' API behavior without writing any code, by using 'policies'. A policy
is like a module that implements a specific, limited management function. Policies are designed to let you add
common types of management capabilities to an API easily and reliably. Policies provide features like security,
rate-limiting, transformation, and mediation capabilities, saving you from having to code and maintain this
functionality on your own.
You're not limited to the set of policy types provided by SAP API Management. You can also write custom scripts
and code (such as JavaScript), that extend API proxy functionality and enable you to innovate on top of the basic
management capabilities supported by SAP API Management Policies
Policy Types
Technically, a policy is an XML-formatted configuration file. Each policy type's structure (for example, the
required and optional configuration elements) is defined by an XML schema. SAP API Management Policy types
are grouped into the following functional categories:
Traffic Management
Policies in the traffic management category enable you to control the flow of request and response messages
through an API proxy. These policies support both operational and business-level control. They give you control
over raw throughput, and can also control traffic on a per-app basis. Traffic management policy types enable you
to enforce quotas, and they also help you to mitigate denial of service attacks.
Mediation
Policies in the mediation category enable you to actively manipulate messages as they flow through API proxies.
They enable you to transform message formats, from XML to JSON (and vice-versa), or to transform one XML
Security
Policies in the security category support authentication, authorization, as well as content-based security.
Extension
Policies in the extension category enable you to tap into the extensibility of API Platform to implement custom
behavior in the programming language of your choice.
Each Policy type is documented in detail in the Policy Section. This topic demonstrates general interaction,
showing you how to create Policies, and how to attach them to Flows in an API proxy configuration.
One type of policy that is commonly used is SpikeArrest. SpikeArrest prevents sudden increases in message
traffic that might swamp your backend services.
3. Select the policy type that you want to add to the API proxy.
For example, if you want to add a SpikeArrest policy, select the Traffic Management category in the policy
dropdown menu.
4. Modify the selections in the New Policy dialog to configure and attach the policy.
If you accept the default selections, as shown below, the policy will be enforced on request messages
submitted by client apps to the ProxyEndpoint PreFlow.
Configuring Policies
When the UI generates a policy instance, it applies reasonable default values for common settings. You may need
to modify these settings to meet your requirements.
Example
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<SpikeArrest async="false" continueOnError="false" enabled="true"
name="spikearrest-1">
<DisplayName>SpikeArrest-1</DisplayName>
<FaultRules/>
<Properties/>
<Identifier ref="request.header.some-header-name"/>
<MessageWeight ref="request.header.weight"/>
<Rate>30ps</Rate>
</SpikeArrest>
You can configure a policy by directly editing its XML configuration in the Code view. For example, the peak
message rate for the Spike Arrest policy is initially set to 30 messages per second. You can change the peak rate
by changing the <Rate> element value in the XML for the policy.
You can also cut-and-paste policies into the Code view.
When you make changes to a policy definition in the Code view, the changes are reflected in the Property
Inspector. The reverse is also true — make changes in the Property Inspector and they appear in the XML in
the Code view.
Some policies expose XML elements that can have multiple subelements. For example, the AssignMessage policy
(which is used in the request or response path to generate a new message or to modify an existing message)
exposes various elements in which multiple query parameters can be specified. In these cases, the Property
Inspector displays a (+) icon. Choose the icon to add entry fields for additional subelements.
You can create and edit Policies locally, using your favorite text or XML-aware editor or IDE. This topic uses the
Quota policy type as an example of how to create, configure, attach, deploy, and test policies.
Most API proxies enforce a quota. Quotas provide control over how often a client app is permitted to invoke an API
over a given time interval. In the example below, a Quota policy is configured to limit apps to 1 request per minute.
(While this may not be realistic, it does provide a simple way to see the effects of a policy.)
In an API proxy configuration, Policy files are stored as XML files under /apiproxy/policies directory.
For example, a policy of type Quota called "QuotaPolicy" could be created as a file called QuotaPolicy.xml with the
following content:
<Quota enabled="true" continueOnError="false"
async="false" name="QuotaPolicy">
<Allow count="1"/>
<Interval>1</Interval>
<TimeUnit>minute</TimeUnit>
</Quota>
You can create a text file by hand, or you can generate the policy from an XML schema. All policies have some
settings that are specific to the policy type, and some settings that are generic across all policies.
When you attach policies in the management UI, the API proxy builder generates the policy instance from the XML
schema for the policy type you selected. Therefore, you may see elements in the policy configuration that, for
clarity, are not always included in documentation.
All policies define the following attributes:
• enabled: Indicates whether the policy is turned "on" or "off". Policies can be enabled/disabled at runtime by
changing this setting. A policy that has enabled set to false is not enforced.
• continueOnError: Defines whether the pipeline should continue processing the message if the policy fails.
When enforcing quota policies, errors likely indicate that the quota has been exceeded, and, therefore, this
attribute should be set to false.
• async: In a policy, enabling async=true tells API Plarform to run the policy inside a different thread pool,
isolated from the regular pool that is servicing the request/response Flow. This is an internal optimization that
will rarely be of use to API developers.
• name: The name that you give to this policy. This name is unique to this policy instance, and it is used to
attach the policy to the flow as a processing step.
Policies are not executed until they are attached to a Flow. You can create a Policy attachment by naming a Policy
in a Step configuration.
The choice of attachment point is critical to the behavior of your API proxy. For example, if you attach the Quota
policy to a response Flow, then the Quota would be enforced after the request message was sent to the backend
service. That would defeat the purpose of applying a Quota policy! Therefore, you need to attach the Quota policy
as a processing Step on the request Flow.
The format of a policy attachment is:
<Step>
<Name>{policy_name}</Name>
</Step>
Example
<Step>
<Name>QuotaPolicy</Name>
</Step>
Recommendation
The {policy_name} variable must be the same as the name attribute in the policy (stored under /policies)
that you want to attach. The names must match exactly, as name matching is case-sensitive.
A policy is attached to a Flow by adding the Step configuration to the appropriate request or response Flow
element in a ProxyEndpoint or TargetEndpoint configuration.
You can attach a policy to a request or response Flow. Request and response Flows are further subdivided in
to PreFlow and PostFlow.
The following example demonstrates the minimal ProxyEndpoint configuration, with no policy attachments. It
simply defines the (inbound) HTTPProxyConnection and a RouteRule.
<ProxyEndpoint name="default">
<HTTPProxyConnection>
<BasePath>/weather</BasePath>
<VirtualHost>default</VirtualHost>
</HTTPProxyConnection>
The rest of the ProxyEndpoint configuration remains the same. The only change is that you added the
PreFlow, Request, and Step elements. In the ProxyEndpoint configuration above, the Quota policy executes
Recommendation
You can also define conditional Flows that execute between the PreFlow and PostFlow phases. This is
covered in the next topic, Flow Variables and Conditions.
For policy changes to take effect, you must deploy the API proxy revision to an environment. After you attach a
policy or make changes to an existing policy, use the management UI or the management API to deploy the
changes.
To verify that a policy is enforced properly, the API must be invoked by an HTTP client. To verify this Quota
configuration, submit multiple requests to the API, exceeding the quota limit that you set in the quota policy. (The
URI path, configured as the base path setting in the ProxyEndpoint, in the request below is /weather).
http://<host:port>/weather/forecastrss?w=12797282
After you submit more than 1 request within a minute, you should see the following error message:
{"fault":{"faultstring":"policies.ratelimit.QuotaViolation","detail":{"errorcode":"pol
icies.ratelimit.QuotaViolation"}}}
This indicates that the Quota policy is being enforced by API Platform.
Note the format of the error message above. It contains a faultstring property and an errorcode property. In many
cases, you need to implement some behavior to handle these errors. For example, you may wish to issue a
customized message to a developer whose app has exceeded the Quota.
To do so, you use the FaultRule element on the Step. A FaultRule element can be attached to any policy. The
behavior of the FaultRule is defined by the Policy that you attach to the FaultRule.
Example
<Step>
<FaultRules>
<FaultRule>
<Name>QuotaLimitAlertPolicy</Name>
<Condition>(fault.name = ratelimit.QuotaLimitCheck.exceed.count)</Condition>
<FaultRule>
To meet basic management requirements, API proxies usually enforce the following policies:
Request Flow:
1. SpikeArrest
2. JSONThreatProtection
3. API key validation
4. Quota
5. JSONToXML
Response Flow:
1. XMLToJSON
2. ResponseCache
SpikeArrest
This policy smooths traffic spikes by dividing a limit that you define into intervals of 10 milliseconds. For example,
if you define a limit of 100 messages per second, the SpikeArrest policy enforces a limit of around 10 per
millisecond. The SpikeArrest limit should be close to capacity calculated for either your backend service or the API
proxy itself. The limit should also be configured for shorter time intervals, such as seconds or minutes. This policy
should be used to prevent sudden traffic bursts caused by malicious attackers attempting to disrupt a service
using a denial-of-service (DOS) attack or by buggy client applications.
See Shield APIs using SpikeArrest section in the Policy document.
Quota
This policy enforces consumption limits on client apps by maintaining a distributed 'counter' that tallies incoming
requests. The counter can tally API calls for any identifiable entity, including apps, developers, API keys, access
tokens, and so on. Usually, API keys are used to identify client apps. This policy is computationally expensive so,
for high-traffic APIs, it should be configured for longer time intervals, such as a day or month. This policy should
be used to enforce business contracts or SLAs with developers and partners, rather than for operational traffic
management.
See Rate limit API traffic using Quota section in the Policy document.
This policy enables traffic management between API Platform and your backend services. Some backend
services, such as legacy applications, may have strict limits on the number of simultaneous connections they can
support. This Policy enforces a limit on the number of requests that can be sent at any given time from API
Platform to your backend service. This number is counted across all of the distributed instances of API Platform
that may be calling your backend service. Policy limits and time duration should be configured to match the
capacity available for your backend service.
See Throttle backend connections using ConcurrentRatelimit in the Policy document.
Introduction
API proxies that run on API Platform are stateless. They enforce policies and execute scripts and code, but the
environment in which they run is populated with context that is specific to each request/response transaction.
To provide API proxies with access to data over multiple transactions, API Platform provides a persistence layer
that enables API proxies to store data. The persistence layer consists of L1 and L2 caches and a NoSQL key/value
store. These caches and the data store work together to optimize availability and performance.
As a developer, you can access this persistence layer without knowing the details of its implementation. Instead,
you use a set of policies to interact with the persistence layer at runtime. API Platform defines three policy types
that enable you to configure persistence for API proxies using configuration instead of code.
SAP API Management supports these persistence scenarios:
• A cache for serving duplicates of stored static response messages
• A general purpose caching mechanism for persisting any arbitrary objects used by your API proxies
• HTTP/1.1 compliant caching
• A highly performant NoSQL key/value store for simple data sets used by your API proxies
Response Cache
Response caching is a dedicated application of the API Platform caching mechanism. Response caching is
implemented in the ResponseCache policy, so enabling ResponseCaching for your APIs requires no coding on
your part.
Not all data is updated in real-time. Services often only update data periodically, for example, weather data
updates every 10 minutes, or product catalog prices update every 24 hours.
When ResponseCache is employed in a proxy, SAP API Management also looks at certain HTTP response caching
headers and takes appropriate actions according to the directives of those headers. For example, on responses
from backend targets, SAP API Management supports the Cache-Control header, which can be used to control
the maximum age of a cached response, among other directives. For more information, see HTTP response
caching.
A consideration for response caching is that responses larger than 256KB are not distributed across the SAP API
Management infrastructure. This is done to optimize performance.
Cache
Caching is more general purpose than ResponseCache, enabling you to persist any object that your API proxies
require over multiple request/response sessions. API Platform provides policies for populating, retrieving, and
flushing the cache at runtime. The interaction mechanism that links the API proxies with the underlying cache is
variables. You can use policies or code in your API proxies to populate and retrieve cached objects by interacting
SAP API Management supports a subset of HTTP/1.1 compliant cache headers, including the cache-control
header and entity tags. For more information, see HTTP response caching.
Key/value Map
If the data you need to store is structured or is long-lived, then use the key/value map.
Examples of situations where you would use the key/value store are:
• A map of IP addresses to country codes
• A list of IP addresses for whitelisting/blacklisting
• A mapping of long URLs to corresponding shortened URLs
API Platform provides a set of policies for interacting with the key/value store at runtime. It also exposes a
RESTful API for managing the contents of the key/value store. The API enables you, for example, to perform bulk
operations to populate the key/value store with large data sets.
Therefore, key/value maps work better for single entities that have many properties. For example:
curl -H "Content-Type:application/json" -X POST -d \
'{
"entry" : [ {
"name" : "development",
"value" : "dev.apifactory.com"
}, {
"name" : "production",
"value" : "prod.apifactory.com" } ],
"name" : "URLs"
}' \
http://<host:port>/v1/o/{org_name}/keyvaluemaps \
-u myname:mypass
The result is a key/value map that can be retrieved as JSON or XML for use at runtime by policies or code that you
write.
You can add entries to the key/value map by using the PUT verb. You only need to include the entries to be added:
curl -H "Content-Type:application/json" -X PUT -d \
The PopulateCache policy does not persist cache entries. Entries are in memory until the configured expiration
time. You can look up the value only until it expires. One limitation is that you cannot find the list of keys that are
currently in a cache.
When using KeyValueMap, the keys are persisted indefinitely. There are APIs available to retrieve the list of keys.
There is no expiration time for the keys; you must explicitly delete them.
The HTTP/1.1 specification describes standard caching headers and control mechanisms that support caching
along the HTTP request/response chain. These headers and mechanisms provide information about cached
resources and help servers determine how to manage cached data. You can refer to the spec itself for detailed
information about caching in HTTP, and there are also many blogs, articles, and other resources available on the
internet that explains HTTP caching.
The focus of this topic is to explain how SAP API Management processes and handles HTTP/1.1 headers related to
response caching.
Recommendation
SAP API Management currently supports a subset of the HTTP/1.1 caching headers and directives. Where
appropriate, we'll point out features that are not supported.
SAP API Management provides a persistence layer that allows HTTP responses and arbitrary variables to be
stored in caches. You enable and control this persistence layer with policies. SAP API Management provides
policies for storing arbitrary variables (the Cache policies) and a policy for controlling HTTP response caching (the
ResponseCache policy).
You can read an overview of the SAP API Management persistence layer in Persistence.
Recommendation
SAP API Management Platform does not perform any caching unless one or more of these policies are
attached to a proxy.
This topic concerns HTTP response caching and how the HTTP/1.1 caching headers are handled when the
ResponseCache policy is employed by a proxy. To learn about adding and configuring the ResponseCache policy,
see Reduce latency using ResponseCache.
When the ResponseCache policy is added to a proxy, HTTP responses are cached and retrieved according to how
the proxy is configured. The ResponseCache policy includes two flag elements that, when set, allow the policy to
consider HTTP cache headers. If you want to use these HTTP cache header features, you need to set these flag
elements. They are:
o UseResponseCacheHeaders: If set to true, the HTTP response headers are used when setting the "time
to live" (TTL) of the response in the cache. The Expires response header is ignored by default unless this
flag is set to true. If the max-age or s-maxage directives of the Cache-Control header are set, they take
precedence over the Expires header value.
o UseAcceptHeader: When this flag is set to true, the Accept headers in the response are used to generate
a cache key. The default is false. See "How are cache keys generated".
In addition, SAP API Management looks for and evaluates certain HTTP caching headers. SAP API
Management also considers these headers and takes appropriate action based on their directives. In some
cases, these HTTP/1.1 cache headers override whatever behavior is specified in the ResponseCache policy.
For example, if the Cache-Control header is returned from a backend server, the header's s-
maxage directive overrides the corresponding setting in the ResponseCache policy.
SAP API Management supports the following HTTP cache headers on responses received from backend
target (origin) servers:
o Cache-Control
o Expires
On client GET requests, SAP API Management supports the The If-Modified-Since header.
SAP API Management also supports Entity Tags (ETags) and their related GET request headers.
o If-Match
o If-None-Match
Finally, SAP API Management provides support for caching and returning compressed responses.
This section discusses SAP API Management support for the Cache-Control header.
Recommendation
Although the HTTP/1.1 spec allows Cache-Control headers in both client requests and origin server
responses, SAP API Management only supports the Cache-Control header on responses returned from
origin servers (backend targets). Origin servers can include both target endpoints defined in an e SAP API
Management API proxy and those created using TargetServer API calls.
When SAP API Management detects a Cache-Control response header, it looks at the header's directives and
takes appropriate processing steps.
SAP API Management supports a subset of Cache-Control response header capabilities defined in the HTTP/1.1
specification. Please note the following:
SAP API Management does not support Cache-Control headers that arrive with inbound client requests.
According to the HTTP specification, Cache-Control can either be public (shared) or private (single user).
However, SAP API Management only supports the notion of public caches.
Not all Cache-Control response directives in the HTTP/1.1 specification are supported by SAP API Management.
See "Support for Cache-Control response header directives" below for details.
The following table describes SAP API Management support for HTTP Cache-Control response header directives.
Recommendation
SAP API Management supports subset directives from the HTTP/1.1 specification on responses from
origin servers. For more detailed information on these directives, see "Cache-Control" in the HTTP/1.1
specification.
SAP API Management uses the Expires header on origin server responses to determine the time to live (TTL)
of a cached entry. As expected, this header specifies a date/time after which a response's cache entry is
considered stale. This header allows servers to signal when it's okay to return a cached value based on a time
stamp.
An entity tag (ETag) is an identifier associated with a requested resource. This identifier allows servers to
determine if the requested resource and the associated cached resource match or not. Servers can then take
appropriate actions, such as re-caching a response if it does not match or returning the cached resource if the
ETags match. When a target endpoint sends a response back to SAP API Management with an ETag, SAP API
Management caches the ETag along with the response. You can read more about Entity Tags in "Protocol
Parameters" in the HTTP/1.1 specification.
The If-Match request header allows SAP API Management to determine if a cached entity is current or not based
on if the ETag in the header matches the ETag that is cached with the requested entity. You can read more
about If-Match in "Header Field Definitions" in the HTTP/1.1 specification.
If SAP API Management receives an inbound GET request from a client that includes an If-Match header:
o If the If-Match header specifies one or more ETags, SAP API Management retrieves any unexpired cached
entries for the specified resource and compares any strong ETags on those cached entries with those
specified in the If-Match header. If a match is found, the cached entry is returned. If not, the request is
passed to the origin server.
o If the If-Match header specifies "*", the request is passed on to the origin server to ensure that any origin
caching facilities have a chance to process the request.
o Any requests other than GET that specify an If-Match header are passed on to the origin server to ensure
that any origin caching facilities have a chance to process the request.
o If a cache entry with the same request URI is found, but it contains only weak ETags, then the entry must
be revalidated by the origin server before being returned to the client.
o Any ETags returned by the origin server are returned unchanged to the client.
The If-None-Match header allows SAP API Management to determine if a cached entity is current or not based on
if the ETag in the header does not match the ETag that is cached with the requested entity.
If SAP API Management receives an inbound GET request from a client that includes an If-None-Match header:
o If the If-None-Match header specifies one or more ETags, SAP API Management retrieves any
unexpired cache entries for the specified URI and compares any strong ETags on those cached entries
with those specified in the If-None-Match header. If a match is found, SAP API Management returns a 304
Not Modified status. If no match is found, SAP API Management passes the request to the origin server.
o If the If-None-Match header specifies "*" and an unexpired cached entry for the requested URI exists,
SAP API Management returns a 304 Not Modified status.
o Requests other than a GET that include an If-None-Match header are passed on to the origin server.
o If a cache entry with the same request URI is found but contains only weak ETags, then the entry must be
revalidated by the origin server before SAP API Management returns it to the client.
o If SAP API Management receives an ETag from an origin server, the ETag is always returned unchanged
to the client.
If SAP API Management receives an If-Modified-Since header in a GET request, it is passed along to the origin
server even if a valid cache entry exists. This ensures that any updates to a resource that did not pass through
SAP API Management are accounted for. If the origin server returns a new entity, then SAP API Management
replaces the existing cache entry with the new value. If the server returns a 304 Not Modified status, SAP API
Management returns the response value if the cached response's Last-Modified header indicates that it has not
changed.
When an incoming request includes the header Accept-Encoding with values of gzip, deflate or compress,
the origin server responds with compressed data. When subsequent responses come without the Accept-
Encoding headers, they expect an uncompressed response. SAP API Management's response caching
mechanism is capable of sending both compressed and uncompressed responses depending on the incoming
headers without going back to the origin server.
When the ResponseCache flag UseAcceptHeader is set to true, SAP API Management uses the Accept, Accept-
Encoding, Accept-Language and Accept-Charset request headers when calculating the cache key. This
approach prevents a client from getting a media type they did not ask for. For example, consider if two requests
come in from the same URL, where the first request accepts gzip and the second does not. The first request will
be cached, and the cached entry will (probably) be a gzipped response. The second request will read the cached
value and may then return a gzipped entry to a client that is not capable of reading gzip.
By default, SAP API Management only caches 2xx level responses. Non-2xx responses are not cached.
Fault Handling
Many error conditions can arise while API proxies are servicing requests from apps. For example, API proxies may
encounter network issues when communicating with backend services, apps may present expired credentials,
request messages may be incorrectly formatted, and so on. In many cases, you will need to handle such errors in
a customized fashion. This topic shows you how to set up custom fault handling using the controls provided by
API Platform.
About Errors
When an API proxy encounters an error, the default behavior of the API proxy is to exit the normal processing
pipeline, meaning exit the current flow, and to enter an Error flow. Once the API proxy enters the Error flow, it
cannot return processing back to the normal flow pipeline.
By entering the Error flow, the proxy:
• Bypasses any remaining processing steps, meaning any remaining policies, in the current flow
• Bypasses any subsequent flows
• Returns a fault response to the requesting app.
This process results in a raw error message or error codes being returned to the requesting app.
For all errors other than policy errors, an API proxy immediately enters the Error flow. For policy errors, meaning
failures arising while processing a policy, the continueOnError element of a policy controls the way the API
proxy reacts to an error.
By default, the continueOnError element is false, meaning that when a fault occurs in a policy, control is
directed to the Error flow. For example, the following VerifyAPIKey policy uses the default value of
the continueOnError element:
<VerifyAPIKey async="false" continueOnError="false" enabled="true" name="verify-api-
key">
<DisplayName>Verify API Key</DisplayName>
<APIKey ref="request.queryparam.apikey"/>
</VerifyAPIKey>
If you set the continueOnError element to true, control stays in the current flow of the API proxy and the next
policy in the pipeline executes.
In many cases you want to control the response of your API proxy to an error. For example, you might want to
send a custom error message when a developer app exceeds a Quota, add more information about the error to
the response, remove information from the response not meant to be seen by the calling app, or to modify the
response in other ways to improve usability and security.
SAP API Management enables you to customize error handling by defining fault rules. A fault rule specifies two
items:
• A Condition that specifies the fault to be handled based on the pre-defined category, subcategory, or name of
the fault
• One or more policies that define the behavior of the fault rule for the corresponding Condition.
Hint
To add a fault rule you need to edit the XML configuration of the ProxyEndpoint or TargetEndpoint. You
can use the SAP API Management UI to make this edit in the Code pane of the Develop view for an API
proxy, or edit the XML file that defines the ProxyEndpoint or TargetEndpoint.
<FaultRule>
...
</FaultRule>
</FaultRules>
OR
<FaultRules>
<FaultRule>
<Step>
<Name>{policy_name}</Name>
<Condition>{(conditional statement)}</Condition>
</Step>
</FaultRule>
<FaultRule>
...
</FaultRule>
where the Condition applies to the entire fault rule or only to a specific step in the fault rule. You can define
multiple fault rules in a ProxyEndpoint or TargetEndpoint to handle multiple fault conditions.
When a FaultRule's condition evaluates to true, then the Policy named in the FaultRule will execute and any
subsequent policies with matching conditions will execute. This is different behavior from Route Rules and
Flow conditions which stop once a condition is met. In those cases, even if environment conditions match
subsequent Route Rules and Flow conditions, those Route Rules and Flows will be ignored.
Recommendation
You can learn how to configure conditions by referring to the topic Flow Variables and Conditions.
Each type of error defines a set of error codes that it creates in response to an error. For policy errors, you can
find the error codes for each policy in the policy reference, starting with the Policy Reference.
All policy error codes have the same format, as shown in the example below:
{
"code" : " {error.code} ",
"message" : " {Error message} ",
"contexts" : [ ]
}
For example, when a developer app presents and invalid consumer key, the VerifyApiKey policy returns the
following error code:
{
"code" : " InvalidApiKey ",
"message" : "The consumer key presented by the app is invalid.",
"contexts" : [ ]
}
Use the error code to define the condition the defines the fault rule to execute. The fault.name variable contains
the value of the code field of the error code. You then use the fault.name variable in the <Condition> tag, as the
following example shows:
<ProxyEndpoint name="default">
...
<FaultRules>
<FaultRule name="invalid_key_rule">
<Step>
<Name>{policy_name}</Name>
</Step>
Note
If multiple fault rules have a condition that evaluates to true, then the last of those fault rules executes.
Now that you have configured a fault rule, you need to add a policy to the rule to handle the error. This policy then
determines the action of the fault rule.
While you can put any policy in the fault rule, you commonly use the Raise Fault policy. Use the RaiseFault policy
to generates a custom response message for an error condition. RaiseFault enables you to configure an HTTP
response with payload, HTTP status code, headers, and reason phrase elements.
Note
A policy used in a fault rule is typically not used in the normal flow pipeline. However, when using the SAP
API Management UI to create a policy, the SAP API Management UI by default assigns the policy to a flow.
For example, it can assign it to the Flow PreFlow, ProxyEndpoint default. Therefore, when using the SAP
API Management UI to create a policy for a fault rule, you typically uncheck the Attach Policy checkbox,
as shown below, so that the policy is not assigned to a flow:
You can now use this policy in your fault rule. Notice how you reference the RaiseFault policy by name in the fault
rule:
<ProxyEndpoint name="default">
...
<FaultRules>
<FaultRule name="invalid_key_rule">
<Step>
<Name>fault_invalidkey</Name>
</Step>
<Condition>(fault.name = "InvalidApiKey")</Condition>
</FaultRule>
</FaultRules>
You can execute multiple policies in a fault rule, as the following example shows:
<ProxyEndpoint name="default">
...
<FaultRules>
<FaultRule name="invalid_key_rule">
<Step>
<Name>policy1</Name>
</Step>
<Step>
<Name>policy2</Name>
</Step>
<Step>
<Name>policy3</Name>
</Step>
<Condition>(fault.name = "InvalidApiKey")</Condition>
</FaultRule>
</FaultRules>
</ProxyEndpoint>
The policies execute in the order defined. For example, you can use the Message Logging policy, the Extract
Variables policy, the AssignMessage policy, or any other policy in the fault rule. Note that processing of the fault
rule stops immediately if either of these situations occur:
• Any policy in the fault rule causes an error
• Any of the policies in the fault rule is of type RaiseFault
As a best practice, you should define a rules that determine the error responses from your APIs. In that way, you
deliver consistent and helpful information your clients.
The example Raise Fault policy below uses the <Payload>, <StatusCode>, and <ReasonPhase> tags to define
the custom error response sent back to the client:
<RaiseFault name="fault_invalidkey">
<FaultResponse>
<Set>
The DefaultFaultRule acts an exception handler for any error that is not explicitly handled by a FaultRule. If no
FaultRules are configured in an API proxy, then the DefaultFaultRule will handle all faults that occur. Default fault
handling can be enabled by configuring DefaultFaultRule as a child element of a ProxyEndpoint or a
TargetEndpoint.
The TargetEndpoint configuration below is configured with a DefaultFaultRule. The FaultRule indicates that when
an error condition is encountered during message processing, a policy called ReturnError executes.
<TargetEndpoint name="default">
<DefaultFaultRule name="fault-rule">
<Step>
<Name>ReturnError</Name>
</Step>
</DefaultFaultRule>
<HTTPTargetConnection>
<URL>http://weather.yahooapis.com</URL>
</HTTPTargetConnection>
</TargetEndpoint>
DefaultFaultRule is typically used to return a generic error message for any unexpected error. For example,
you might configure the DefaultFaultRule to return a message that contains support contact information. This
Recommendation
Set the flag AlwaysEnforce to true on DefaultFaultRule. This enables the DefaultFaultRule to process any
faults captured by more specific FaultRules. In this case, you can customize the error response (by
adding an HTTP header, for example) on the ProxyEndpoint.
An example of a simple Policy that you might use with a DefaultFaultRule is shown below. The policy is of type
AssignMessage, and generates a simple text response for any predefined error condition:
<AssignMessage name="ReturnError">
<Set>
<Payload type="text/plain">SERVICE UNAVAILABLE. PLEASE CONTACT SUPPORT:
[email protected].</Payload>
</Set>
</AssignMessage>
Include the <AlwaysEnforce> element in the <DefaultFaultRule> tag to execute the default fault rule for
every error, even if another fault rule has already been executed. The default fault rule is always the last fault rule
to execute:
<DefaultFaultRule name="fault-rule">
<Step>
<Name>ReturnGenericError</Name>
</Step>
<AlwaysEnforce>true</AlwaysEnforce>
</DefaultFaultRule>
One use of the default fault rule is to determine the type of error that occurs when you otherwise cannot
determine it. For example, your API proxy is failing for an error that you cannot determine. Use the default fault
The examples shown so far all use a fault rule on the ProxyEndpoint or TargetEndpoint to handle any policy errors
as part of the Error flow. That is because the default value of the continueOnError element of a policy is false,
meaning that when an error occurs in a policy, control is directed to the Error flow. Once in the Error flow, you
cannot return control back to the normal pipeline and you typically return some form of error message to the
calling app.
However, if you set the continueOnError element to true for a policy, control stays in the current flow and the
next policy in the pipeline executes after the policy that caused the error. The advantage to handling the error in
the current flow is that you might have a way to recover from the error to complete processing of the request.
Shown below is a VerifyAPIKey policy named verify-api-key with the continueOnError element set to true:
<VerifyAPIKey async="false" continueOnError="true" enabled="true" name="verify-api-
key">
<DisplayName>Verify API Key</DisplayName>
<APIKey ref="request.queryparam.apikey"/>
</VerifyAPIKey>
If the API key is missing or invalid, then the VerifyAPIKey policy sets the verifyapikey.verify-api-key.failed variable
to true, but processing continues in the current flow.
You then add VerifyAPIKey policy as a step in the PreFlow of the ProxyEndpoint:
Notice how the next step in the PreFlow uses a condition to test for the existence of an error. If an error occurred
in the VerifAPIKey policy, then the policy named FaultInFlow policy executes. Otherwise, the FaultInFlow policy is
skipped. The FaultInFlow policy can do many things, such as logging the error, attempting to fix the error, or
performing some other action.
You can use the RaiseFault policy at any time in a flow to trigger an error. When a RaiseFault policy executes, it
terminates the current flow and transfers control to the Error flow.
One use of the RaiseFault policy is to test for a specific condition that another policy might not detect. In the
example above, you added a <Condition> tag to a PreFlow <Step> tag that caused the policy FaultInFlow to
execute if the condition is met. If FaultInFlow is a RaiseFault policy, then control transfers to the Error flow. Or, you
might insert a RaiseFault policy in a flow to debug and test your fault rules.
When a RaiseFault policy triggers an error, you can use the following fault rule and condition to process it:
<FaultRule name="raisefault_rule">
<Step>
<Name>{policy_name}</Name>
</Step>
<Condition>(fault.name = "RaiseFault")</Condition>
</FaultRule>
The configuration shown in the previous section works for application-level errors. To return custom responses
for transport-level (that is, HTTP) errors, you must configure a Property on the TargetEndpoint that enables the
TargetEndpoint to process HTTP response codes.
By default, HTTP response codes in the 2xx-3xx range are treated as 'success'. HTTP response codes 4xx-5xx are
treated as 'failure'. Any response from the backend service with an HTTP response code 400-500 automatically
invokes the ErrorFlow. The ErrorFlow automatically returns an error message directly to the requesting client.
To create custom responses to HTTP error codes, you need to override this default behavior. In some cases you
might need to return custom errors for HTTP codes 400 and 500. For example, you may need to ensure that all
backend service URLs are obfuscated from requesting clients.
To do so, you must first configure the TargetEndpoint to treat HTTP response codes 4xx and 5xx as success
codes. By treating those codes as success codes, the TargetEndpoint takes over processing of the response
message (rather than pushing the response message into the default ErrorFlow). This enables you to define
FaultRules on HTTP error codes that invoke specific policies.
To treat HTTP error codes as success, set the success.codes property on the TargetEndpoint in your API proxy.
<TargetEndpoint name="default">
<HTTPTargetConnection>
<Properties>
<Property name="success.codes">4XX, 500</Property>
</Properties>
<URL>http://weather.yahooapis.com</URL>
</HTTPTargetConnection>
</TargetEndpoint>
You can then use HTTP response codes 400-499 and 500 to define conditional policy execution that returns a
customized response message to the requesting app.
For example, apply the following configuration to a ProxyEndpoint or TargetEndpoint response Flow.
<Response>
<Step>
<Condition>(response.status.code = 400) or (response.status.code =
500)</Condition>
<Name>ReturnError</Name>
The Flow configuration above causes the AssignMessage policy called ReturnError to generate a response
message whenever the TargetEndpoint encounters an HTTP response code of 400 or 500.
FaultRule Processing
Any number of FaultRules can be defined on ProxyEndpoints and TargetEndpoints. When an error occurs, only the
first FaultRule whose condition evaluates to true is enforced.
FaultRules are evaluated in the following order:
Request Path:
3. Fault in ProxyRequest: FaultRules defined at ProxyEndpoint execute
4. Fault in Routing: FaultRules defined at ProxyEndpoint execute
5. Fault in TargetRequest: FaultRules defined at TargetEndpoint execute
6. Fault in outbound request to target URL: FaultRules defined at TargetEndpoint execute
Response Path:
7. Fault in TargetResponse: FaultRules defined at TargetEndpoint execute
8. Fault in ProxyResponse: FaultRules defined at ProxyEndpoint execute
9. Fault in returning response to ProxyEndpoint: FaultRules defined at ProxyEndpoint execute
Policy attachments in a FaultRule are enforced in the order in which the Steps are attached to the FaultRule.
To enable fault handling for an API proxy, fault handlers must be configured to identify and categorize predefined
exception conditions, in turn enabling API Platform to execute policies that manage the exception.
Fault Taxonomy
API Platform organizes faults into the following categories and subcategories.
An error is always accompanied by a text description of the reason for the failure. When the system raises a fault,
a set of attributes are populated to assist in troubleshooting. A fault includes the following information:
This topic explains how to use these pattern matching operators in conditional statements in SAP API
Management Edge:
• Matches operator
• JavaRegex operator
• MatchesPath operator
Conditional statements are used in conditional flows, routes, and steps. You can read more about conditional
statements in the Conditions reference.
Let's look at the "Matches" or "~" conditional operator first. These two operators are the same -- the English
version, "Matches", is considered to be a more readable option.
Summary: The "Matches" operator gives you two possiblities. Either match the string literally, or do a wildcard
match with "*". As you might expect, the wildcard matches zero or more characters. Let's see how this works.
The following XML shows a Step condition. It executes the SomePolicy policy when the condition evaluates to
true. In this example, we test the variable proxy.pathsuffix, a built-in variable in SAP API Management Edge that
stores the path suffix of the request. Note, however, you can test the value of any flow variable that contains a
string. So, in this case, if the base path of the incoming request is /animals, and the request is /animals/cat, then
the path suffix is the literal string "/cat".
<PreFlow name="PreFlow">
<Request>
<Step>
<Condition>(proxy.pathsuffix Matches "/cat")</Condition>
<Name>SomePolicy</Name>
</Step>
</Request>
<Response/>
</PreFlow>
Does the policy execute? Yes, because the proxy path suffix matches "/cat" exactly. It will not execute if the suffix
is /bat or /dog or "/" or anything else.
Now, consider this conditional statement where we use the wildcard character "*":
<Condition>(proxy.pathsuffix Matches "/*at")</Condition>
API call:
GET http://artomatic-test.apigee.net/matchtest/cat
Does the policy execute? Yes, because the wildcard matches any character, and "/cat" is a match.
API Call:
GET http://artomatic-test.apigee.net/matchtest/bat
Does the policy execute? Yes, because the wildcard matches any character, "/bat" is a match.
API Call:
GET http://artomatic-test.apigee.net/matchtest/owl
Does the policy execute? Certainly not -- although the wildcard matches the "o", the letters "wl" are not matched.
Now, lets move the wildcard to the end of the suffix:
<Condition>(proxy.pathsuffix Matches "/cat*")</Condition>
API call:
GET http://artomatic-test.apigee.net/matchtest/cat
Does the policy execute? Yes, because the wildcard matches zero or more of any characters.
API Call:
GET http://artomatic-test.apigee.net/matchtest/bat
Does the policy execute? No, "/bat" is not a match.
API call:
GET http://artomatic-test.apigee.net/matchtest/cat123
Does the policy execute? Yes, the wildcard matches zero or more of any characters, therefore "123" produces a
match.
API call:
GET http://artomatic-test.apigee.net/matchtest/cat/bird/mouse
Does the policy execute? Yes, because the wildcard matches zero or more of any characters, so "/bird/mouse"
produces a match. Note how an expression like this can get you into trouble because it matches everything after
the literal characters!
Does the policy execute? No, the wildcard matches any letter (regardless of case), but the lowercase "a" does not
match "A".
API call:
GET http://artomatic-test.apigee.net/matchtest/bAt
Does the policy execute? Yes, the case matches.
Use the percent "%" character to escape reserved characters. For example:
<Condition>(proxy.pathsuffix Matches "/c%*at")</Condition>
API call:
GET http://artomatic-test.apigee.net/matchtest/cat
Does the policy execute? No, the Matches operator is looking for the literal string "c*at".
API call:
GET http://artomatic-test.apigee.net/matchtest/c*at
Does the policy execute? Yes, this path, although a bit unusual, matches.
As you can see, the "Matches" operator is great for simple situations. But you can use another operator, the
"JavaRegex" or "~~" operator. These two are the same operator, except JavaRegex is considered to be more
readable. It's called JavaRegex because it allows regular expression pattern matching, and SAP API Management
Edge follows the same rules as the classes in the java.util.regex package in the Java language. The way the
JavaRegex operator works is very different from the Matches operator, so it's important not to confuse the two!
Note:
• If you're used to doing Regex in Perl scripts, it's important to note that the JavaRegex operator in SAP API
Management Edge tests the entire subject string. For example, if the subject is "abc" and the regex is "[a-z]" ,
Summary: The "JavaRegex" operator lets you use regular expression syntax in conditional statements.
The following code shows a Step condition. It executes the SomePolicy policy if the condition evalutes to true. In
this example, we test the variable proxy.pathsuffix, a built-in variable in SAP API Management Edge that stores the
path suffix of the request. Note, however, you can test the value of any flow variable that contains a string. So, in
this case, if the base path of the incoming request is /animals, and the request is /animals/cat, then the path
suffix is the literal string "/cat".
<PreFlow name="PreFlow">
<Request>
<Step>
<Condition>(proxy.pathsuffix JavaRegex "/cat")</Condition>
<Name>SomePolicy</Name>
</Step>
</Request>
<Response/>
</PreFlow>
Question: What proxy path suffix will cause SomePolicy to execute? Just like with the Matches operator, there's
only one possibility in this case.
API call:
GET http://artomatic-test.apigee.net/matchtest/cat
Does the policy execute? Yes, because the proxy path suffix matches "/cat" exactly. It will not execute if the suffix
is /bat or /dog or anything else.
Now, let's create a regular expression using "*" quantifier. This quantifier matches zero or more of the preceeding
character.
<Condition>(proxy.pathsuffix JavaRegex "/c*t")</Condition>
API call:
GET http://artomatic-test.apigee.net/matchtest/cat
Does the policy execute? No! The "*" quantifier matches zero or more of the preceeding character, which is a "c".
API Call:
GET http://artomatic-test.apigee.net/matchtest/ccccct
Does the policy execute? Yes, because the wildcard matches zero or more of the preceeding character.
API call:
GET http://artomatic-test.apigee.net/matchtest/cat
Does the policy execute? Yes. The "?" quantifier matches zero or one occurance of the preceeding character,
which is an "a".
API Call:
GET http://artomatic-test.apigee.net/matchtest/ct
Does the policy execute? Yes. The "?" quantifier matches one or none of the preceeding character. In this case,
there is no "a" character, so the condition evaluates to true.
API Call:
GET http://artomatic-test.apigee.net/matchtest/caat
Does the policy execute? No. The "?" quantifier matches one of the preceeding character, which is an "a".
Next, we use the "[abc]" or "grouping" style of regex expression. It matches the characters "a" or "b" or "c".
<Condition>(proxy.pathsuffix JavaRegex "/[cbr]at)</Condition>
API call:
GET http://artomatic-test.apigee.net/matchtest/cat
Does the policy execute? Yes. We're using regular expressions here, and the "[cbr]" expression matches a "c", "b",
OR "r". These calls are also matches:
GET http://artomatic-test.apigee.net/matchtest/bat
GET http://artomatic-test.apigee.net/matchtest/rat
But this is not a match:
GET http://artomatic-test.apigee.net/matchtest/mat
API call:
The MatchesPath operator can also be specified like this "~/". It looks a little bit like the Matches (~) and the
JavaRegex (~~) operators. But MatchesPath is entirely different.
Just remember that this operator looks at a path as a series of parts. Therefore, if the path is: /animals/cats/wild,
you can think of the path as consisting of the parts "/animals", "/cats", and "/wild".
The MatchesPath operator lets you use two wildcard notations: a single asterisk (*) and a double asterisk (**).
The single asterisk matches one path element. The double asterisk matches one or many path elements.
Let's look at an example. In this example, we test the variable proxy.pathsuffix, a built-in variable in SAP API
Management Edge that stores the path suffix of the request. Note, however, you can test the value of any flow
variable that contains a string.
<PreFlow name="PreFlow">
<Request>
<Step>
<Condition>(proxy.pathsuffix MatchesPath "/animals/*)</Condition>
<Name>SomePolicy</Name>
</Step>
</Request>
<Response/>
</PreFlow>
API call:
GET http://artomatic-test.apigee.net/matchtest/animals/
Does the policy execute? Yes, the path does have another path element (the part after "/animals/"), but it's just
empty.
API Call:
GET http://artomatic-test.apigee.net/matchtest/animals/cats
Does the policy execute? Yes, because the path has at least one element that comes after "/animals"
API Call:
GET http://artomatic-test.apigee.net/matchtest/animals/cats/wild
Does the policy execute? Yes, because the path has more than one element that comes after "/animals"
Mixing asterisks
You can use combinations of the single (*) and double (**) asterisk to further refine your path matching.
<PreFlow name="PreFlow">
<Request>
<Step>
<Condition>(proxy.pathsuffix MatchesPath
"/animals/*/wild/**)</Condition>
<Name>SomePolicy</Name>
</Step>
</Request>
API call:
All of these API calls will produce a match:
GET http://artomatic-test.apigee.net/matchtest/animals/cats/wild/
and
GET http://artomatic-test.apigee.net/matchtest/animals/dogs/wild/austrailian
and
GET http://artomatic-test.apigee.net/matchtest/animals/birds/wild/american/finches
Examples
SAP API Management Edge developers commonly want to handle both of these path suffixes: "/cat" and "/cat/".
This is because some users or clients might call your API with the extra slash on the end of the path, and you need
to be able to handle that in your conditional statements.
If you prefer, you can achieve this without using Regex like this:
<PreFlow name="PreFlow">
<Request>
<Step>
<Condition>((proxy.pathsuffix = "/cat") OR (proxy.pathsuffix =
"/cat/")</Condition>
<Name>SomePolicy</Name>
</Step>
</Request>
<Response/>
</PreFlow>
This is a good option. It is clear and readable.
You can do the same thing with Regex, however, like this. The parentheses are used to group the regex part of the
statement, but they are not required.
<Condition>(proxy.pathsuffix JavaRegex "/cat(/?)"</Condition>
API Calls:
GET http://artomatic-test.apigee.net/matchtest/cat
or
GET http://artomatic-test.apigee.net/matchtest/cat/
In all of the examples in this topic, we show how to match one of the built-in flow variables: proxy.pathsuffix. It's
good to know that you can do pattern matching on any arbitrary string or flow variable, whether or not it's a built-
in flow variable like proxy.pathsuffix.
If for example you have a condition that tests an arbitrary string, perhaps a string returned in a backend payload,
or a string returned from an authentication server lookup, you can use matching operators to test it. If you use
JavaRegex, the regular expression will be compared against the entire subject string. If the subject is "abc" and
the regular expression is "[a-z]", there is no match, because "[a-z]" matches exactly one alpha character. The
expression "[a-z]+" works, as does "[a-z]*", and "[a-z]{3}.
Let's look at a concrete example. Suppose the authentication server returns a list of roles as a comma-delimted
string: "editor, author, guest".
To test the presence of the editor role, this construction will not work, because "editor" is only part of the entire
string.
<Condition>returned_roles ~~ "editor"</Condition>
However, this construction will work:
<Condition>returned_roles ~~ ".*\beditor\b.*")</Condition>
It works because it takes into account word breaks and any other parts of the string with the .* prefix and suffix.
In this example, you can also test for "editor" with the Matches operator:
<Condition>returned_roles ~~ "*editor*")</Condition>
However, in cases where you need more precision, JavaRegex is often a better choice.
Many policy types defined by SAP API Management rely on resources. Resources are the files that implement the
code or configuration to be executed by a policy when attached to an API proxy. In some cases, as with JavaScript
and JavaCallout, a policy simply defines an attachment point in an API proxy where some code should execute. A
JavaScript or JavaCallout policy is a pointer to a resource.
Note
In the management UI, resources scoped to an API proxy are listed in the Scripts section of the
Navigation pane.
In addition to storing resources at the proxy level, API Services also provides repositories for these resources at
the organization and the environment level. By storing resources at the organization or the environment level, you
enable reuse and sharing of code and configuration across the API proxies deployed in your organization and
across different environments.
Note
The example API calls in this topic use cURL. You can also use the SmartDocs management API reference
topic SmartDocs to make the same calls.
Resource types
Note
You can also add resources at the API proxy scope in the SAP API Management UI, in the proxy editor
Develop view.
For example, all JavaScript files available across an organization are stored under:
/organizations/{org_name}/resourcefiles/jsc
JavaScript stored in the /organizations collection is available to any API proxy running in any environment.
You can list all available resources by calling GET on the collection:
$ curl https://<host:port>/v1/organizations/{org_name}/resourcefiles/{resource_type}
The following request lists all JavaScript resources at the organization level:
$ curl https://<host:port>/v1/organizations/myorg/resourcefiles/jsc
The following request lists all JavaScript resources at the environment level, in the environment called prod:
$ curl https://<host:port>/v1/organizations/myorg/environments/prod/resourcefiles/jsc
The following request lists all JavaScript resources in an API proxy revision (the most specific level):
$ curl
https://<host:port>/v1/organizations/myorg/apis/weatherapi/revisions/6/resourcefiles/j
sc
Sample response:
<List>
<Item>JavaScriptMashUp</Item>
<Item>JavaScriptClient</Item>
</List>
Note
When updating an existing resource in a deployed API proxy, you must redeploy the API proxy after to
ensure the resource changes are picked up. Newly added resources do not require API proxy
redeployment.
Let's assume that you have a simple snippet of JavaScript that you need to make available to API proxies across
your organization. The following sample JavaScript sets the HTTP request path to the value of
the proxy.basepath variable. It's just one example of a resource that you might need to put in the repository.
request.setHeader("RequestPath", flow.getVariable("proxy.basepath"));
To create a resource, you call the POST method, submitting the body of the resource file, and identifying the
resource's name and type as query parameters.
To make the JavaScript available to API proxies running in any environment in your organization:
Sample response:
{
"name" : "pathSetter",
"type" : "jsc"
}
You can also upload resources as files from your local machine as follows. It's important to use -F for the binary
upload in cURL in order for the environment- and organization-scoped JavaScript files to be accessible by the
JavaScript policy.
$ curl -X POST -H "Content-type:multipart/form-data" -F [email protected] \
https://<host:port>/v1/organizations/myorg/resourcefiles?"name=pathSetter&type=jsc" \
-u email:password
The JavaScript resource named pathSetter is now available to be referenced by policies of type JavaScript
running in any environment in the organization.
For example, to attach the JavaScript to the Request PostFlow, create a policy called PathSetterPolicy.xml that
references the filepathSetter.js:
You can add compiled Java resources as JAR files using multiple options in cURL, such as -T, --data-binary, or -
F option (not the -d option). For example:
SAP API Management resolves resource names from the most specific to the most general scope. Resource
names are resolved "up the chain", from the API proxy level, to the environment level, to the organization level.
https://<host:port>/v1/organizations/myorg/resourcefiles/jsc/pathSetter
https://<host:port>/v1/organizations/myorg/environments/prod/resourcefiles/jsc/pathSet
ter
Now imagine that an API proxy is configured with the following Policy:
<Javascript name='PathSetterPolicy' timeLimit='200'>
<ResourceURL>jsc://pathSetter.js</ResourceURL>
</Javascript>
Hint
The policy reference cannot explicitly resolve to a repository. The first resource whose name matches the
resource name in the policy is resolved.
So, when the API proxy is deployed in the environment prod, the Policy will resolve the pathSetter.js resource:
/organizations/myorg/environment/prod/resourcefiles/jsc/pathSetter
/organizations/myorg/resourcefiles/jsc/pathSetter
You can view a resource body by calling the GET method on it:
Sample response:
request.setHeader("RequestPath", flow.getVariable("proxy.basepath"));
JMS Integration
Overview
If you use Java Message Service (JMS) with Java Naming and Directory Interface (JNDI), you can make RESTful
calls from JMS to backend services through SAP API Management.
This document describes how to configure SAP API Management to work with a JMS host and how to create an
API proxy that handles incoming JMS messages.
Regardless of the JMS provider you use—for example, whether you’re using Apache ActiveMQ or JBoss HornetQ
(or neither)—the SAP API Management supports only Java Naming and Directory Interface (JNDI) to connect to
the JMS provider. If a JMS provider doesn’t support JNDI, it can't be used with SAP API Management.
Use Case
You can send messages from JMS queues to an SAP API Management API resource. For example, you might need
an API proxy endpoint to handle incoming JMS messages from multiple JMS queues, apply logic to convert JMS
messages to HTTP, forward the request to a target endpoint, and return the response as JMS.
To use JMS with SAP API Management, you configure the JMS connection details by creating a JMS host . The
JMS host then can be referenced from JMS API proxy endpoints by using
the <JMSHost> or <JMSResponseHost> tags. All JMS API proxies share the same JMS host.
Name Description
ConnectionFactory Property used to select the registry service provider as the initial context and
specifies the class name of the initial context factory for the provider. Note that it
is not used by the provider.
You might need to remove a JMS host associated with an environment. To do this, execute the following API call:
curl –u : “http://{host}:8080/v1/organizations/environments/jmshosts/{jmshost_name}” -
X DELETE
The ProxyEndpoint and JmsProxyConnection elements define a set of JMS transport properties. These properties
can be used to set network configurations to connect to the JMS provider. The SAP API Management JMS API
proxy endpoint supports only receiving messages from a JMS queue. Other JMS operations are not supported.
Ensure that you define the attribute proxyType="jmsConnection" in order to create JMS proxy endpoints.
Also, ensure that you have the JMS provider-specific client library in the classpath.
The following table provides the description of all JmsProxyConnection properties that are available for JMS
implementation.
JmsProxyConnection JMS network details associated with the API proxy. You can Yes
dynamically set to subscribe/unsubscribe to a given queue by
defining an attribute state=”on/off”. By default it is “on”.
Destination Queue path to which the subscribe listens to the messages. Yes
DefaultResponseQueue Name of the JMS queue where response from target is published. No
JMSResponseHost JMS response host defined for the JMS proxy. If specified, all No
responses are sent to the queues over this host.
Note
All HTTP headers matching standard JMS headers will be set “as is” and other HTTP headers will be set
as JMS properties in the response message used by the JMS proxy.
You can use the AssignMessage policy to specify the following headers in a JMS proxy.
X-SAP-Ignore-JMSResponse - By default, the API proxy puts the response on the JMS response queue specified
in the JMSReplyTo header. However, if you want the backend service to handle putting the response on the queue
specified in JMSReplyTo—or something else outside of the API proxy such as a Java callout or another API
proxy—add the X-SAP-Ignore-JMSResponse header and set it to true:
<Header name="X-SAP-Ignore-JMSResponse">true</Header>
CORS (Cross-origin resource sharing) is a standard mechanism that allows JavaScript XMLHttpRequest (XHR)
calls executed in a web page to interact with resources from non-origin domains. CORS is a commonly
implemented solution to the "same-origin policy" that is enforced by all browsers. For example, if you make an
XHR call to the Twitter API from JavaScript code executing in your browser, the call will fail. This is because the
domain serving the page to your browser is not the same as the domain serving the Twitter API. CORS provides a
solution to this problem by allowing servers to "opt-in" if they wish to provide cross-origin resource sharing.
Recommendation
Most modern browsers support CORS.For an in-depth description of CORS; see the Cross-Origin
Resource Sharing W3C Recommendation.
The following JQuery code calls the Yahoo Weather API. If executed from within the context of a browser (a web
page), the call will fail because of the same-origin policy:
<script>
var url = "http://weather.yahooapis.com/forecastrss?w=12797282";
$(document).ready(function(){
$("button").click(function(){
$.ajax({
type:"GET",
url:url,
async:true,
dataType: "xml",
success: function(xml) {
// Parse the response.
// Do other things.
},
Recommendation
In the simplest case, you can return CORS headers to the client and the cross-origin request will work.
More complicated cases exist where a "preflight" request is required. You can read about preflight CORS
requests in Cross-Origin Resource Sharing W3C Recommendation, as well as in numerous articles and
blogs. See also "Handling CORS preflight requests" below
You can add CORS support to an API proxy by attaching an "Add CORS" policy to the API proxy when you create
it. To add this policy, select the Browser Access checkbox in the Add API Proxy dialog, as shown in the following
figure.
When you select this checkbox, a policy called Add CORS is automatically added to the system and attached to
the TargetEndpoint response preflow, as shown in the following figure:
The Add CORS policy is implemented as an AssignMessage policy, which adds the appropropriate headers to the
response. Here is the XML for the Add CORS policy:
<AssignMessage async="false" continueOnError="false" enabled="true" name="Add-
CORS">
<DisplayName>Add CORS</DisplayName>
<FaultRules/>
<Properties/>
<Add>
<Headers>
<Header name="Access-Control-Allow-Origin">*</Header>
<Header name="Access-Control-Allow-Headers">origin, x-requested-with,
accept</Header>
You need to manually create a new Assign Message policy and copy the code for the Add CORS policy listed in the
previous section into it. Then, attach the policy to the response preflow of the TargetEndpoint of the API proxy.
You can modify the header values as needed. For more information on creating and attaching policies, see Policy
Attachment and Enforcement.
CORS preflight refers to sending a request to a server to verify if it supports CORS. Typical preflight responses
include which origins the server will accept CORS requests from, a list of HTTP methods that are supported for
CORS requests, headers that can be used as part of the resource request, the maximum time preflight response
will be cached, and others. If the service does not indicate CORS support or does not wish to accept cross-origin
requests from the client's origin, the cross-origin policy of the browser will be enforced and any cross-domain
requests made from the client to interact with resources hosted on that server will fail.
Typically, CORS preflight requests are made with the HTTP OPTIONS method. When a server that supports CORS
receives an OPTIONS request, it returns a set of CORS headers to the client to indicate its level CORS support. As
a result of this handshake, the client knows what it is allowed to request from the non-origin domain.
For more information on preflight, refer to the Cross-Origin Resource Sharing W3C Recommendation. There are
in addition numerous blogs and articles on CORS that you can refer to.
SAP API Management does not include a CORS preflight solution out of the box, but it is possible to implement, as
described in this section. The objective is for the proxy to evaluate an OPTIONS request in a conditional flow. The
proxy can then send an appropriate response back to the client.
Let's look at a sample flow, and then discuss the parts that handle the preflight request:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ProxyEndpoint name="default">
<Description/>
<Flows>
<Flow name="OptionsPreFlight">
<PreFlow name="PreFlow">
<Request/>
<Response/>
</PreFlow>
<HTTPProxyConnection>
<BasePath>/v1/cnc</BasePath>
<VirtualHost>default</VirtualHost>
<VirtualHost>secure</VirtualHost>
</HTTPProxyConnection>
<RouteRule name="NoRoute">
<Condition>request.verb == "OPTIONS"</Condition>
</RouteRule>
<RouteRule name="default">
<TargetEndpoint>default</TargetEndpoint>
</RouteRule>
<PostFlow name="PostFlow">
<Request/>
<Response/>
</PostFlow>
</ProxyEndpoint>
The key parts of this ProxyEndpoint are as follows:
• A RouteRule is created to a NULL target with a condition for the OPTIONS request. Note that there is no
TargetEndpoint specified. If the OPTIONS request is received, the proxy immediately returns the CORS
headers in a response to the client (bypassing the actual default "backend" target). For details on flow
conditions and RouteRule, see Flow variables and conditions.
<RouteRule name="NoRoute">
<Condition>request.verb == "OPTIONS"</Condition>
</RouteRule>
• An OptionsPreFlight flow is created that adds an Add CORS policy, containing the CORS headers, to the flow if
an OPTIONS request is received.
Recommendation
RouteRules are evaluated in the order specified in the ProxyEnpoint configuration. You should always
have the default (no condition) Route at the end. Otherwise, if at the top, it will always match and never
evaluate the other Route possibilities.
This topic explains how to create API proxies for SOAP-based web services. You can create two kinds of SOAP
proxies in SAP API Management Edge. One generates a RESTful interface to the backend SOAP service and the
other performs a "pass through" of the SOAP message to the backend. Both techniques are described in this
topic.
This section explains how to create a RESTful SOAP API proxy with the REST to SOAP to REST option in the
Create New Proxy dialog.
Overview
The REST to SOAP to REST option processes the WSDL to generate a RESTful API proxy. SAP API Management
Edge determines from the WSDL the service's supported operations, input parameters, and so on. SAP API
Management Edge "guesses" which HTTP method to use for each operation. Typically, SAP API Management
Edge translates operations into GET requests, which have the advantage of being cacheable. SAP API
Management Edge also sets up the backend target endpoint, which can vary per SOAP operation.
Proxy Base Path The Proxy Base Path is a URI fragment that uniquely identifies the API that is
exposed by this API proxy. API Services uses the Base Path URI to match and route
incoming request messages to the proper API proxy. (The Base Path is appended to
the domain of the API, which is automatically generated based on
your organization name and the environment where the API proxy is deployed.) It's a
best practice to include a version number in the project name, for
example, /v1/weather. This will determine how your API is invoked by consumer
apps.
Note: The Proxy Base Path defaults to the value specified for Proxy Name converted
to all lower case unless you explicitly edit the content in the Proxy Base Path field.
5. Click Next.
6. In the WSDL page, select the API proxy type REST to SOAP to REST.
Note
A table appears listing the operations that SAP API Management "discovered" in the WSDL file. You can
select and configure which operations you wish to incorporate into your API proxy.
Recommendation
Operations on the callback porttype cannot be converted to REST resources because API Platform does
not support asynchronous operations for this purpose.
7. Select from the Port Type column which set of operations you wish to use. In WSDL, port type elements
define the operations that you can call on a web service.
Note
SAP API Management makes a "best guess" in determining the HTTP method to use for each operation. GET
is generally preferred because GET requests can be cached.
9. Optionally change the REST API path for an operation. The path will be used as the resource name in the API
proxy URL.
Note
Any parameters for an operation are listed in the REST API Parameters column. For example, the weather
API shown in the previous figure includes a ZIP parameter for certain operations. In the API proxy, you
specify that value as a query parameter.
10. Click through the rest of the wizard to add security, select virtual hosts, and deployment environment.
11. In the Build page, click Build and Deploy. SAP API Management Edge generates and deploys the new API
proxy based on the WSDL.
12. Go to the summary page for the new API proxy. Note that a set of resources have been constructed based on
the operations discovered in the WSDL file.
Recommendation
On the proxy's Overview page, the Resources list provides a detailed description of the new API, its
operations, and parameters. You can think of this representation as the API's reference documentation.
SAP API Management generates this view of the API model automatically for you. Simply expand a
resource to see its description and information about its input parameters, data types. Also listed are any
enumeration facets that apply to an input parameter. Enumeration facets specify the list of the
acceptable values for an input parameter.
When SAP API Management generates an API proxy based on a WSDL, the resulting proxy is actually a complex
flow that includes policies for transforming data extracting and setting variables, manipulating messages, adding
threat protection, and more. After you generate a proxy based on a WSDL, take a look at the resulting flow in the
Develop view of the API management UI. There, you can see exactly which policies have been added.
For example, the following figure shows the Target Endpoint Preflow part of a SOAP-based proxy. On the
request side, an AssignMessage policy is used to set the target URL. On the response side, policies execute to
transform the response from XML to JSON, extract the SOAP body part of the response into a variable, and set
the response message. These policies (and others) are added automatically when you create the proxy.
OpenAPI Spec: To view the auto-generated OpenAPI Spec for this proxy,
visit http(s)://[proxy_domain]/[proxy_base_path]/openapi.json. However, the conversion is not
always accurate, since not all the rules of an XML schema can be represented in an OpenAPI Spec.
This section explains how to create a pass-through proxy with the Pass-Through Proxy option in the Create New
Proxy dialog.
Overview
The Pass-Through Proxy option lets you to create a proxy that passes the SOAP message in a request to the
backend service "untouched", making it very easy to create a proxy for a SOAP-based web service. Behind the
scenes, SAP API Management handles any transformations and other flow activities for you automatically. For
example, if the request happens to be in JSON format, SAP API Management takes steps to convert it to a valid
XML SOAP message with correct namespaces before POSTing it to the service. Similarly, when the service
returns an XML-based SOAP response, SAP API Management translates it back to JSON before returning it to the
client. In addition, SAP API Management sets up the backend target endpoint, which can vary per SOAP
operation.
Note:
You might wish to choose Pass-Through if the WSDL operations support a lot of unbounded parameters. It's
easier for SAP API Management to translate a WSDL containing bounded parameters to a proxy, because they are
finite and therefore can be represented by a finite set of query parameters or form variables.
For this type of proxy, SAP API Management Edge hosts the WSDL and creates a flow in the proxy to let you
access it. The address to this SAP API Management Edge-hosted
WSDL, http(s)://[proxy_domain]/[proxy_base_path]?wsdl, becomes the new service endpoint URL for
clients calling the SOAP service through the proxy.
Basic Steps
Proxy Base Path The Proxy Base Path is a URI fragment that uniquely identifies the API that is
exposed by this API proxy. API Services uses the Base Path URI to match and route
incoming request messages to the proper API proxy. (The Base Path is appended to
the domain of the API, which is automatically generated based on
your organization name and the environment where the API proxy is deployed.) It's a
best practice to include a version number in the project name, for
example, /v1/weather. This will determine how your API is invoked by consumer
apps.
5. Click Next.
6. In the WSDL page, select the API proxy type Pass-Through SOAP.
Note
A table appears listing each WSDL operation and its corresponding SOAP payload. This is the payload
that is "passed through" to the backend SOAP service.
7. Select from the Port Type column which set of operations you wish to use. In WSDL, port type elements
define the operations that you can call on a web service.
8. Click through the rest of the wizard to add security, select virtual hosts, and deployment environment.
9. In the Build page, click Build and Deploy. SAP API Management Edge generates and deploys the new API
proxy based on the WSDL.
In the proxy's Overview page, the Resources list provides a detailed description of the new "pass-through" API
proxy. You can think of this representation as the API's reference documentation. SAP API Management
generates this view of the API model automatically for you. Simply expand a resource to see its description. The
SOAP message body that is POSTed to the backend service is captured in the model view, as shown in this figure.
Note that the method used for Pass-Through proxies is POST. This is the only method supported by the SOAP
protocol.
When SAP API Management generates a pass-through proxy, the resulting proxy is actually a complex flow that
includes policies for transforming data, extracting and setting variables, manipulating messages, adding threat
protection, and more. After you generate the pass-through proxy, take a look at the resulting flow in the Develop
view of the API management UI. There, you can see exactly which policies have been added.
For example, the following figure shows the Target Endpoint Preflow part of a pass-through proxy. On the request
side, an AssignMessage policy is used to set the target URL. On the response side, policies execute to transform
the response from XML to JSON, extract the SOAP body part of the response into a variable, and set the response
message. These policies (and others) are added automatically when you create the proxy.
Note
When you face any issue with the request and response, refer the "SAP NOTE 0002115216".
SAP API Management Edge-hosted WSDL: To see the SAP API Management Edge-hosted WSDL generated for
this type of proxy, go to http(s)://[proxy_domain]/[proxy_base_path]?wsdl.
The previous sections covered the creation of a SOAP-to-REST API proxy using the API proxy wizard in SAP API
Management Edge. However, if you want more fine-grained control over the SOAP-to-REST transformation, you
can bypass the automation provided by the wizard and build a proxy by manually adding and configuring policies
to get the behavior you want.
After reading this topic you will know how to enable streaming HTTP requests and responses to and from API
proxies deployed to SAP API Management.
By default, HTTP streaming is disabled and HTTP request and response payloads are written to a buffer in
memory before they are processed by the API proxy pipeline. You can change this behavior by enabling
streaming. With streaming enabled, request and response payloads are streamed without modification to the
client app (for responses) and the target endpoint (for requests).
If your API proxy handles very large requests and/or responses, you may wish to enable streaming. For example,
you may wish to enable a streaming response flow if you have a Node.js application deployed on SAP API
Management that returns output over time, such as a Comet-style application. Or, you may wish to enable
streaming for any application that accepts or returns a very large amount of data.
Note
If your API requests or returns a large amount of data, you may see this HTTP error:
{"fault":"{\"detail\":{\"errorcode\":\"protocol.http.TooBigBody\"},\"faultstring
\":\"Body buffer overflow\"}"}
If you see this error, we recommend that you enable streaming. If you continue to see the error after you
enable streaming, consider removing any policies that require access to the request or response payload.
When streaming is enabled, policies that require access to the request or response payload, such as XSLT
transformations and XML to JSON policies cannot be run and are bypassed.
To enable request streaming you need to add the request.streaming.enabled property to the ProxyEndpoint
and TargetEndpoint definitions in the proxy bundle and set it to true. Similarly, set
the response.streaming.enabled property to enable response streaming.
This topic provides a quick overview of proxy deployment. You can deploy proxies using the Management UI,
command-line scripts, or with APIs.
When you create an API proxy you'll need to decide which environment you'll be working in. You can choose to
create a new API proxy on production, but that is not recommended as you may expose an API to developers
before its ready. In general you want to start by creating an API proxy in test which, after testing, you then
'promote' to prod.
As you work on an API proxy, API Platform saves iterations of your configuration as revisions. When you deploy an
API proxy, you choose a specific revision to deploy. Typically, you deploy the most recent revision, and, if
necessary, revert to the previous revision number. You can choose where to deploy those revisions. For instance,
you can promote a revision to prod to allow developers to start working with your API. At the same time, you may
be iterating multiple revisions on test, where you're adding features or fine-tuning policies. Then, when you're
ready, you can deploy the new revision to prod, overwriting the existing revision on that environment. Using this
method, you can always have a live revision of your API available to developers while you're developing
Promotion to Prod
When an API proxy has been fully implemented and tested, it is ready to be promoted to 'prod'. The revision of the
API proxy in test will be used to overwrite the revision of the API proxy deployed on prod.
API Platform provides capabilities to ensure seamless deployment of API proxies, minimizing the impact on apps
and end users during the deployment procedure.
Scripting Deployment
The SAP API Management management UI enables you to deploy API proxies to prod directly from the API proxy
builder. However, in many situations the requirements for security, reliability, and consistency will mandate that
development teams script deployment procedures. To do so, you can write code and scripts that invoke the
RESTful API exposed by API Platform.
Environment Resources
For additional control during promotion, it is recommended that you only iterate on API proxies in test, and make
as few changes as necessary to API proxies deployed in prod.
To do so, you need to ensure that certain resources associated with each environment are configured in such a
way that they can remain static in an API proxy configuration.
Target URLs: It is common for API proxies to call different backend URLs during testing and production. You can
use TargetServer configurations to create environment-independent TargetEndpoint configurations. See Load
Balancing Across Backend Servers.
Understanding Deployment
A proxy must be deployed before it can be invoked. Generally, it's up to you when you deploy. When you are
working in a test environment, you may deploy iteratively many times. On the other hand, the decision to deploy a
proxy from the test environment to a production environment usually depends on lifecycle rules established by
your development team.
Deploy or redeploy a proxy when you:
• Create a new proxy (deployment happens automatically)
• Modify an existing proxy
• Create a new revision of a proxy
• Create a new version of a proxy
• Push a proxy from one environment to another, such as from a test environment to a production
environment.
• Delete and recreate a keystore.
You deploy a proxy to an environment. All organizations in SAP API Management, by default, have two
environments called test and prod. These environments are merely designed to provide you with one area to work
on and test API changes, and another area where APIs are exposed to apps. The following figure shows a proxy
that is deployed to the test environment, as indicated by the green dot.
How you deploy a proxy depends on where you are developing the proxy. If you are working in the UI, you can
easily deploy a proxy with just a couple of mouse clicks. A new proxy is automatically deployed when you create it;
you don't have to do anything special. The procedure for redeploying an existing proxy is almost as simple. Just
select which deployment environment to deploy to, and the management UI takes care of the rest. For more
information, see Deploying proxies in the UI.
If you are developing proxies and related components offline (that is, working with proxy XML files and other code
directly on your file system), SAP API Management provides a convenient command-line deployment tool that
you can use. You can also obtain a sample shell script that you can configure and run to upload and deploy your
proxy files. For more information, see Deploying proxies from the command line.
Finally, you can use the SAP API Management API to deploy proxies. The deployment APIs exposes atomic
functions that your development team can coordinate to automate and optimize your API development lifecycle.
See Deploy API proxies using the management API.
Revisions let you manage API proxy updates as you create and deploy them to an environment. Revisions are
sequentially numbered, enabling you to revert changes by deploying a previous revision of your API proxy. Only
one revision of an API proxy can be deployed in an environment at a given time.
Typically, an existing revision must be undeployed before a new one can be deployed. Other advanced options
include overwriting a deployed revision or opting not to increment a revision at all. For example, sometimes when
you make minor changes, you might not want to increment the revision. These advanced options can be
accomplished through direct calls to the SAP API Management API. See Deploy API proxies using the
management API.
You can deploy a revision of an API proxy into the prod environment, while continuing to create new revisions of
that API proxy in the test environment. When you are ready, you can "promote" the higher revision of your API
proxy from the test environment over the prior revision of the API proxy in the prod environment.
For more information on revisions, see Deploy API proxies using the management API. See also Deploying proxies
in the UI.
While a revision usually represents a relatively minor update, made in the course of a development cycle, the
version of an API proxy should change relatively infrequently. Typically, a version reflects a significant change in
Note
Don't confuse the version of an API (that is, the public interface) with the revision of an API proxy (that is,
the internal number associated with a configuration). The two numbers are unrelated, and the revision
number of an API proxy is totally opaque to apps that consume your API.
As an API provider, you need to determine when it's appropriate to release a new version. For more information,
see the next section, "Versioning best practices."
Keep the following best practices in mind when you consider versioning:
• Never release an API without a version.
• Make the version mandatory.
• Specify the version with a "v" prefix. Place the prefix to the far left in the URL so that it has the highest scope,
e.g., /v1/dogs.
• Use a single ordinal number, such as v1, v2, and so on.
• Make the version part of the API base path
• Maintain at least one version back.
• Set up a reasonable deprecation policy. Give developers plenty of time and warning before deprecating
features. Depending on your developer's platform, that can be six months or two years. For example, mobile
apps take longer to rev than web apps.
Note
Do not use the dot notation, like v1.2 for an API proxy version. This implies a granularity of versioning that
doesn't work well with APIs.
All organizations in SAP API Management, by default, have two environments: test and prod. The naming is
arbitrary. These environments are merely designed to provide you with one area to work on and test API changes,
and another area where APIs are exposed to apps.
Note
Depending on your role, you may not be able to deploy to all environments. Users can only deploy to
the test environment. If you're an administrator you can deploy to any environment.
You can deploy multiple revisions of an API. It's common to have a revision in prod while another revision is
in test as it's being tested or developed. As long as the API proxy base path stays the same, each environment can
only have one deployed revision of an API. For example, you could have revision 1 deployed in test and revision 20
deployed in prod. You can view deployment of all revisions on the Overview page of the API proxy editor.
When you create a new revision of an API proxy without changing its base path, then deploy it to an environment
in which it's already deployed, the previous version is undeployed and the new revision is deployed in its place.
Note that deployment through the management UI might impact inbound calls. To handle and transition inbound
calls more gracefully during deployment, use the management API.
1. In the API proxy editor, select the revision you want to deploy.
2. Choose Deployment > {environment} and respond to the confirmation dialog.
If the API proxy base path is the same as another deployed revision in that environment, the former revision is
undeployed and the new revision is deployed in its place.
For deploying multiple revisions in the same environment, see the next section.
Note
You can also undeploy a revision by performing the previous steps on an already deployed revision,
indicated by a green dot next to the environment name.
You can deploy multiple revisions of an API proxy in a single environment by changing the proxy's base path,
saving the proxy as a new revision, and deploying the new revision.
For example, this is a great way to create multiple versions of an API proxy by specifying /v1, /v2, /v3, etc. in the
base path. You could deploy all of those revisions to a single environment (such as test). Each proxy could be
completely different, with different flows, policies, and configurations, and you could make API calls to each in the
test environment.
To create and deploy a new API proxy revision by changing the base path
1. Go to the Develop page. In the Navigator, select one of the Proxy Endpoint flows (such as the default item or
PreFlow).
2. Change the value of the <BasePath> element.
3. Select Project > Save as New Revision.
At this point, you can make any flow, policy, or other configuration changes you want to the API proxy and
choose Save.
4. Deploy the new revision by selecting Deployment > {environment}.
On the Overview page, you can see your multiple revisions, all with different base paths, deployed to the same
environment.
The SAP API Management Python deploy tool works with the SAP API Management API to import and deploy API
proxies. The tool is available as part of the API Platform Samples distribution on GitHub.
Use the SAP API Management Python tool to import (upload) and deploy your API in one simple process.
The deploy tool must be run from the base directory in the distribution of the API Platform Samples distribution,
where the base directory is the parent directory of the setup and tools directory.
For example:
$ python tools/deploy.py -n weatherapi -u [email protected]:foo -o myCo -e test -d
weatherapi -p /
This command zips your files, pushes them to your organization on SAP API Management, and deploys them to
the specified environment.
The deploy tool automatically discovers the current revision of your API proxy, undeploys the existing revision,
and deploys an incremented revision of the API proxy.
You can use this tool to upload the API proxy to an on-premises version of SAP API Management by specifying
the -h flag:
$ python tools/deploy.py -n weatherapi -u [email protected]:foo -o myCo -e test -d
weatherapi -p / -h https://192.168.11.111:8080
In this example, you specify the IP address of the SAP API Management server. If you have created a DNS record
for the management server, you can specify a URL in the form https://ms_URL:8080.
The complete list of flags for the command are:
• -n: The name of your API proxy.
• -u: The username and password for your account in an organization in SAP API Management.
• -o: The name of the organization in which you have an account.
• -e: The environment to which the API proxy should be deployed (test or prod).
• -d: The path to the directory containing your API proxy files. Your API proxy files must be stored under a
directory named "apiproxy". This value is the path of the directory that contains the "apiproxy" directory, and
not to the path to the "apiproxy" directory itself.
• -p: The URI path used as a pattern match to route incoming message to this API proxy deployment. In most
cases, you can set this value to '/', unless you have advanced deployment and routing requirements. The
primary path used for API proxy routing is defined in the API proxy's ProxyEndpoint configuration file.
The shell script described in this section is included with the API Platform Samples distribution. This section
assumes that you have obtained the shell script.
The easiest approach is to run the deploy script provided with the sample API proxy. The shell scripts wrap the
SAP API Management Python deploy tool.
From the /simplyProxy directory run:
$ sh deploy.sh
You should see:
Enter your password for user {myname} in the SAP API Management Enterprise
organization {org_name}, followed by [ENTER]:
Enter your password for user Your USERNAME on enterprise.sap.com in the SAP API
Management organization Your ORG followed by [ENTER]:
it means that you need to modify the /setup/setenv.sh file in the platform samples distribution.
On success, the deploy tool ZIPs up the files under /apiproxy, imports the package to your organization on SAP
API Management, and then deploys the API proxy to the 'test' environment.
Your API proxy is ready to be invoked.
Every organization has a unique software development lifecycle (SDLC). It is often necessary to synchronize and
align API proxy deployment with the processes used for backend services.
The API methods demonstrated in this topic can be used to integrate API proxy management into your
organization's SDLC. A common usage of this API is to write scripts or code that deploy API proxies, or that
The following steps walk you through simple interactions with the APIs.
Get an API
You can call the GET method on any API proxy in your organization. This call returns a list of all available
revisions of the API proxy.
$ curl -u myname:mypass -H "Accept: application/json"
http://<host:port>/v1/o/{org_name}/apis/weatherapi
Sample Response:
{
"name" : "weatherapi",
"revision" : [ "1" ]
}
The only detail returned by this method is the name of the API proxy along with the associated 'revision', which
has an associated number. API proxies consist of a bundle of configuration files. Revisions provide a lightweight
mechanism for managing your updates of the configuration as you iterate. Revisions are sequentially numbered,
enabling you to revert changes by deploying a previous revision of your API proxy. Also, you can deploy a revision
of an API proxy into the prod environment, while continuing to create new revisions of that API proxy in the test
environment. When you are ready, you can 'promote' the higher revision of your API proxy from the test
environment over the prior revision of the API proxy in the prod environment.
In this example, there is only one revision because the API proxy was just created. As an API proxy moves through
the lifecycle of iterative configuration and deployment, the revision number increments by integers. Using direct
API calls to deploy, you can optionally increment the revision number of the API proxy. Sometimes when you
make minor changes, you might not want to increment the revision.
Note
Don't confuse the version of an API (that is, the public interface) with the revision of an API proxy (that is,
the internal number associated with a configuration). The two numbers are unrelated, and the revision
number of an API proxy is totally opaque to apps that consume your API.
The API version (for example, api.company.com/v1) should change very infrequently. When you do increment the
API version, it signifies to developers that there has been a significant change in the signature of the external
interface exposed by the API.
The API proxy revision is merely an incremented number associated with an API proxy configuration. API Platform
maintains revisions of your configurations so that you can revert a configuration when something goes wrong. By
default, an API proxy's revision is automatically incremented every time you deploy an API proxy. This behavior
can be overridden in the management UI and in the API.
To obtain the detailed profile of an API proxy configuration, you call the GET method on a specific revision
number.
For example, you can call the GET method on API proxy revision 1 to get a detailed view.
$ curl -u myname:mypass -H "Accept:application/json"
http://<host:port>/v1/o/{org_name}/apis/weatherapi/revisions/1
Sample Response
{
"configurationVersion" : {
"majorVersion" : 4,
"minorVersion" : 0
},
"contextInfo" : "Revision 1 of application weatherapi, in organization
{org_name}",
"createdAt" : 1343178905169,
"createdBy" : "[email protected]",
"lastModifiedAt" : 1343178905169,
"lastModifiedBy" : "[email protected]",
"name" : "weatherapi",
"policies" : [ ],
"proxyEndpoints" : [ ],
"resources" : [ ],
"revision" : "1",
"targetEndpoints" : [ ],
"targetServers" : [ ],
"type" : "Application"
}
These API proxy configuration elements are documented in detail in the API proxy configuration reference.
Recommendation
As you've seen, you deploy the API revision to an environment, so the first step in deploying API proxy
revisions is to verify the list of environments in your organization.
Sample Response:
[ "test", "prod" ]
Explore Deployments
A "deployment" is a revision of an API proxy that has been deployed in an environment. An API proxy that is in the
'deployed' state is accessible over the network, at the addresses defined in the VirtualHost for that environment.
Recommendation
It is often useful to check to see in which environment (and if!) your API is deployed. For example, you
might find requests to your API proxy are failing. One troubleshooting step is to ensure that the API proxy
is deployed as expected.
API proxies cannot be invoked until they have been deployed. API Platform exposes RESTful APIs that provide
control over the deployment process.
The following APIs are called on your behalf by the Python deploy tool. The deploy tool provides support for
packaging and importing API proxies that you develop locally, and it also manages undeployment of existing API
Note
Using this approach, there will inevitably be some lag between the time when the first package is
undeployed and the next one is deployed. During this interval, calls from apps may be rejected with an
HTTP code 5xx. If this is a problem, as it usually is in production deployments, use the seamless
deployment option, described below.
Seamless Deployment
To minimize the potential for downtime during deployment, use the override option on the deployment method,
and set it to true.
You cannot deploy one revision of an API proxy on top of another. The first must always be undeployed. By
settingoverride to true, you indicate that one revision of an API proxy should be deployed over the currently
deployed revision. The result is that the deployment sequence is reversed--the new revision is deployed, and once
the deployment is complete, the already deployed revision is undeployed.
$ curl -X POST -H "Content-type:application/x-www-form-urlencoded" \
http://<host:port>/v1/o/{org_name}/environments/{env-
name}/apis/{api_name}/revisions/{revision_number}/deployments?"override=true" \
-u myname:mypass
You can further optimize deployment by setting the delay parameter. The delay parameter specifies a time
interval, in seconds, before which the previous revision should be undeployed. The effect is that in-flight
transactions have a time interval in which to complete before the API proxy processing their transaction is
undeployed. Following is what occurs with override=true and the delay parameter set:
• Revision 1 is handling requets.
• Revision 2 is being deployed in parallel.
• When Revision 2 is fully deployed, new traffic is sent to Revision 2. No new traffic is sent to Revision 1.
• However, Revision 1 may still be processing existing transactions. By setting the delay parameter (for
example, 15 seconds), you give Revision 1 15 seconds to finish processing existing transactions.
• After the delay interval, Revision 1 is undeployed.
$ curl -X POST -H "Content-type:application/x-www-form-urlencoded" \
When override=true is used along with a delay, HTTP 5xx responses during deployment can be eliminated. This is
because both API proxy revisions will be deployed simultaneously, with the older revision undeployed after the
delay.
This returns the same result as above for all API proxies deployed in all environments.
Since the API is RESTful, you can simply use the POST method, along with a JSON or XML payload, against the
same resource to create an API proxy.
A profile for your API proxy is generated. The default representation of an API proxy is in JavaScript object
notation (JSON). Below is the default JSON response to the POST request above, which created an API proxy
called 'weatherapi'. A description of each element in the profile follows:
{
"configurationVersion" : {
"majorVersion" : 4,
Note
Keep in mind that the response payload merely contains a representation of an API resource — you can
create an API proxy using JSON or XML, and you can also retrieve representations of the API proxy as
XML or JSON, depending on your needs.
The API proxy profile that is generated demonstrates the complete structure of an API proxy:
• APIProxy revision: The sequentially numbered iteration of the API proxy configuration, as maintained by
API Platform
• APIProxy name: The unique name of the API proxy
• ConfigurationVersion: API Platform version to which the API proxy configuration conforms
• CreatedAt: Time when the API proxy was generated, formatted in UNIX time
• CreatedBy: Email address of the user who created the API proxy
• DisplayName: A user-friendly name for the API proxy
• LastModifiedAt: Time when the API proxy was updated, formatted in UNIX time
• LastModifiedBy: Email address of the user who updated the API proxy
• Policies: A list of policies that have been added to this API proxy
• ProxyEndpoints: A list of named ProxyEndpoints
• Resources: A list of resources (JavaScript, Python, XSLT) available to be executed in this API proxy
• TargetServers: A list of named TargetServers (that can be created using the management API), used in
advanced configurations for load balancing purposes
• TargetEndpoints: A list of named TargetEndpoints
Note that many of the elements of the API proxy configuration created using the simple POST method above are
empty. In the following topics, you will learn how to add and configure the key components of an API proxy.
Security Guidelines
The SAP Management API relies on HTTP Basic Authentication. You need to provide a username and password
for each API call.
In some situations, it is not practical to collect the password when the script runs. For example, you may need to
run a cron job that fires when no administrators are present. In these situations, you need to make the password
available to the script without any human intervention.
Follow these guidelines:
1. Centralize credentials in a single file that is used as a source for the programs and scripts that you write
2. Protect the credentials source file to the extent possible using file system security and permissions
3. Create an automation client with highly restricted permissions on specific resources in your organization.
Node.js adds more programmability to the API platform. Running on SAP API Management, Node.js apps take
advantage of SAP API Management's enterprise-grade operations like traffic management, security, deployment
tools, revision control, logging, and analytics. Furthermore, you can leverage thousands of third-party Node.js
modules in your APIs.
This topic explains the simplest way to wrap a Node.js application in an API proxy using the management UI.
Chances are, the first Node.js app you ever created was an HTTP server that responds to requests with "Hello
World!" The simplest way to try out Node.js is to do something very similar. With just a few mouse clicks, you'll
have a functioning, proxied Node.js HTTP server running on SAP API Management. After that, you can use the
code editor in the UI to modify the Node.js app, add additional Node.js files, add policies, and so on.
This section explains how to create an API proxy that interacts with a Node.js HTTP server. The Node.js HTTP
server code is already written for you and is automatically deployed to SAP API Management when you follow
these simple steps.
1. Log in to the SAP API Management UI.
2. From the APIs menu, select API Proxies.
3. In the API Proxies summary page, click +API Proxy.
4. In the New API proxy dialog, select New Node.js.
Note
Use the Node.js Sample "Integrated API BaaS" option only when SAP API Management's API BaaS
component is installed.
5. From the Node.js Server Type options, select Node.js Sample "Hello World".
6. Provide a Name for the proxy. You can just enter Hello.
7. Provide a Project Base Path. If you specified Hello as the display name, then the path /hello is populated
automatically.
8. Add a version number /v1 to the path. API versioning is a best practice. The new Project Base Path is:
/v1/hello
9. Optionally, provide a Description.
When you call the hello proxy, the Node.js application executes automatically, responding with "Hello, World!".
Note that unless you specified otherwise, the Node.js application is deployed to the environment called test.
Here's the basic call using Curl (substitute your hostname and port).
$ curl http://{hostname}:{port}/v1/hello
Hello, World!
Let's look at the Node.js code that was added to the API proxy. Go to the summary page for the Hello World proxy
and choose Develop.
This opens the Develop view which includes a code editor. You can edit the code there directly.
This topic explains how to deploy a Node.js application from your local system to SAP API Management. In this
topic, we'll discuss how to use a command-line tool called SAP API Managementtool to deploy Node.js
applications to SAP API Management.
You can deploy an existing Node.js API application, including any dependent Node.js modules, from your local
system to SAP API Management using a command-line utility called SAP API Managementtool. The utility
automatically bundles the application and its dependencies into an API proxy and deploys it on SAP API
Management.
For example, let's say you used Express to create a web application in Node.js. The application runs as an HTTP
server that listens for HTTP requests, processes those requests, returns data, and so on. When you use SAP API
Managementtool to deploy a Node.js application to SAP API Management, it's wrapped in a proxy and executes
within the context of the API platform. You can then call your application through its new proxy URL, and you can
add value to it by "dressing it" with standard SAP API Management features like OAuth security, quota policies,
threat protection policies, conditional flows, caching, and many others.
When you run the SAP API Managementtool utility with the deploynodeapp option, it:
Before you begin, you need to install the SAP API Management tool utility.
You can install SAP API Management tool through npm.
The SAP API Management tool module and its dependencies are designed for Node.js and is available
through npm using the following command:
$ sudo npm install -g apigeetool
Example
$ curl http://{hostname}:{port}/myNodeApp
Hello, My Node App!
If you wish, log in to you’re your SAP API Management account and go to the API Proxies page of the
management UI. You will see your new proxy listed there.
If your Node.js application depends on installed modules, SAP API Management tool handles them by zipping the
node_modules folder and adding it to the proxy bundle. No additional action is necessary. The same is true for any
directories that contain additional source code. The SAP API Management tool utility zips them and deploys them
with the bundle.
You cannot edit files in these zipped directories on the SAP API Management UI's editor. If you need to change
them, you can export your project, edit the files locally, and then redeploy using SAP API Management tool or by
importing the exported project using the management UI. See also "Exporting and importing a proxy with Node.js
code".
For basic usage information on the SAP API Management tool utility's input parameters, enter:
$ apigeetool deploynodeapp -h
Usage: deploynodeapp -n [name] -o [organization] -e [environment]
-d [directory name] -m [main script file]
-u [username] -p [password]
-b [base path] -l [Management server url] -z [zip file] -i -h
-o SAP API Management organization name
-e SAP API Management environment name
-n SAP API Management proxy name
-d SAP API Management proxy directory
-m Main script name: Should be at the top level of the directory
-u SAP API Management user name
-p SAP API Management password
-b Base path (optional, defaults to /)
-L Management Server hostname and port
-z ZIP file to save (optional for debugging)
-i import only, do not deploy
-h Print this message
Another way to integrate an existing Node.js application into an API proxy is to add the application when you
create the proxy. You can do this entirely through the management UI and the New API Proxy dialog.
Note
If you upload multiple Node.js files, you need to specify which one is the main file. (The main file is the one
that you would invoke from the command line with the node command.)
4. Give the proxy a name. In this example, we are calling it hellonode.
5. Add the version /v1 to the Project Base Path. Versioning your API is a best practice.
6. Choose Build.
7. Choose Develop to enter the Develop view.
8. Open the TargetEndpoint file in the code editor.
9. Be sure the <ScriptTarget> element specifies the main Node.js file, as follows:
<ScriptTarget>
<ResourceURL>node://server.js</ResourceURL>
<Properties/>
</ScriptTarget>
10. Choose Save.
Another way to add Node.js code to a proxy is to add it directly, either through the UI or by uploading it from your
local filesystem. You can also specify which Node.js file is the main file, which is the file invoked when the proxy is
deployed.
Note
Only one Node.js source file is designated to be the main file. The main file is the one you would execute
from the command line to run a Node.js application. The main file is specified in the proxy's target
endpoint definition file using an element called <ScriptTarget>, as explained in Invoking an imported
Node.js file and in Adding Node.js to an existing API proxy. In these out-of-the-box examples, the correct
target endpoint definition is created for you.
To create a new Node.js resource file:
1. In the Develop view, select New Script from the New menu.
2. In the Add Script dialog, select the file type Node and name the script.
3. Choose Add.
Note
Recall that the Proxy Endpoint defines how clients call your API. When a client calls the API with the new
base path, processing is routed to the Target Endpoint, where the main Node.js file is specified.
1. Under Proxy Endpoints in the Navigator, choose the name of the proxy endpoint (usually called default).
2. In the Code editor, edit the <HttpProxyConnection> element by changing the <BasePath> to whatever
name you wish. For example, if the current <BasePath> is v1/hello and you wanted it to be v1/my-node-
file, change the <BasePath> element like this:
<BasePath>/v1/my-node-file</BasePath>
3. Choose Save.
4. Invoke the proxy using the new base path, like this:
$ curl http://{hostname}:{port}/v1/my-node-file
Hello, World!
After you deploy a proxy containing Node.js code to SAP API Management, you can always export the proxy back
to your system, work on it there, and then re-import it back using the management UI. This sort of round-trip
development technique is commonly used.
1. From the API proxy summary page, choose Develop.
2. In the Develop page, select Download Current Revision.
3. Unzip the downloaded file on your system.
Note
The Download function does not unzip any directories that were zipped when the proxy was deployed, like
node_modules or other folders with source code in them. You'll need to unzip them manually once the
proxy is downloaded to your system.
You can import the proxy bundle back into SAP API Management by selecting Import Into New Revision from the
same menu.
You can view the output of this console.log message in the trace tool. Simply call your API in the trace tool and
open the Script Output panel of the final response, as shown below.
The trace tool is useful for general proxy debugging. For detailed information on using the trace tool, see Using the
Trace tool.
You can embed console.log statements in your Node.js code and view the output in the trace tool. For example,
the following statement prints the username of the user who is logging in to access the proxy:
console.log('Logging in as %s', config.username);
Assert Supported
Buffer Supported
Domain Supported
Events Supported
http Supported The virtual host and path for incoming requests is
specified in the API Proxy, not by the HTTP
module. See "Understanding support for the http
and https modules" for more information.
module Supported
path Supported
module Supported
punycode Supported
querystring Supported
module Supported
STDIO Supported Standard output and error are routed to a log file
within the SAP API Management infrastructure.
There is no standard input for scripts running on
SAP API Management. However, you can pass
arguments using the ScriptTarget element of
TargetEndpoint. See Advanced ScriptTarget
configuration for more information.
string_decoder Supported
timers Supported
url Supported
util Supported
vm Supported
zlib Supported
All Node.js applications running in SAP API Management must use the http or https module to listen for incoming
requests. If you were to deploy a script that doesn't listen for incoming requests, it would simply execute and exit.
The listen method of the http and https modules in Node.js takes a port number as a parameter. For example:
svr.listen(process.env.PORT || 9000, function() {
console.log('The server is running.');
});
This "port" argument is required in Node.js, but SAP API Management ignores this parameter. Instead, the API
proxy in which the Node.js script runs specifies the "virtual host" that it listens on, and the Node.js application
uses those same virtual hosts, just like any other SAP API Management proxy.
Every environment in SAP API Management has at least one virtual host. The virtual host defines the HTTP
settings for connection with the SAP API Management organization. All API proxies in an environment share the
same virtual hosts. By default, two virtual hosts are available for each environment: default and secure.
The SAP API Management tool deploynodeapp command generates an SAP API Management proxy wrapper
around the Node.js application. When deployed, the Node.js application listens on the default virtual host defined
for the environment.
SAP API Management supports the Node.js tls module. This module uses OpenSSL to provide Transport Layer
Security (TLS) and/or Secure Socket Layer (SSL) encrypted stream communication. You can use the tls module
to create secure connections to backend services from Node.js applications running on SAP API Management.
To understand how the tls module works on SAP API Management, it's important to understand how virtual hosts
are used on SAP API Management. Every environment in SAP API Management has at least one virtual host. The
virtual host defines the HTTP settings for connection with the SAP API Management organization. All API proxies
in an environment share the same virtual hosts. By default, two virtual hosts are available for each environment:
default and secure.
Now, let's look at how SAP API Management handles TLS (SSL) communication for incoming and outgoing
requests on Node.js applications:
SAP API Management does not support the "cluster" module, which allows Node.js applications to control when
additional copies of an application are started and stopped, and to communicate with them. In the parlance of the
"cluster" module, all Node.js applications are considered to be the "master."
However, SAP API Management does deploy multiple instances of each application — two in most cases, although
the system may be configured to run more if necessary.
That means that Node.js applications running inside SAP API Management, like all Node.js applications, must
assume that they will be processing many different requests "in parallel" using a single thread of control. However,
the application must not assume that it is the only copy running in the world, though it also must not assume that
there is some way to communicate with the other copies.
In the <TargetEndpoint> definition, the <ScriptTarget> element takes additional optional parameters
besides <ResourceURL>. You can also pass command-line arguments and environment variables to a Node.js
script using the <EnvironmentVariables> and <Arguments> parameters:
<TargetEndpoint name="default">
<ScriptTarget>
<ResourceURL>node://hello.js</ResourceURL>
<EnvironmentVariables>
<EnvironmentVariable name="NAME">VALUE</EnvironmentVariable>
</EnvironmentVariables>
<Arguments>
<Argument>ARG</Argument>
</Arguments>
</ScriptTarget>
</TargetEndpoint>
The SAP API Management-access module lets you access API proxy flow variables and caches from within
Node.js application code.
The SAP API Management-access module is integrated into the SAP API Management platform. When you deploy
Node.js code to SAP API Management, this module is available to you. You simply need to require it in any Node.js
code that you deploy. For example:
var access=require('sap-access');
You can also download SAP API Management-access for local development and testing. The SAP API
Management-access packaged module is available through npmjs.org.
When you deploy a Node.js application to SAP API Management, you can access any of the supported "out-of-the-
box" flow variables, flow variables created by policies, and any flow variables that you create yourself from within
your Node.js code. Flow variables are created and exist within the context of an API proxy running on SAP API
Management.
getVariable
Parameters:
• httpRequest: The request object that comes from the http module.
• name: (String) The name of the variable to retrieve.
Returns:
A string or a number, depending on the type that was set using setVariable(), when it was created by you
elsewhere, or when a policy created it. If you are accessing one of the out-of-the-box SAP API Management
variables, you can find a list of types in the Variables Reference. For variable types created by policies, refer to the
specific policy reference topic.
Example
var sap = require('sap-access');
// "httpRequest" must be a request object that came from the http module
var val1 = sap.getVariable(request, 'TestVariable');
var val2 = sap.getVariable(request, 'request.client.ip');
setVariable
Sets a variable. Some variables are read-only, and the setVariable() method throws an exception if you try to set
one of them. To determine which variables are read-only, see the Variables Reference.
Parameters:
• dhttpRequest: The request object that comes from the http module.
• name: (String) The name of the variable to retrieve.
• value: Can be a number, String, boolean, null, or undefined.
Example
var sap = require('sap-access');
sap.setVariable(request, 'TestVariable', 'bar');
// This will throw an exception because client.ip is read-only.
sap.setVariable(request, 'client.ip');
The setIntVariable() method is a convenience method that first coerces the value parameter to an integer,
and then sets it.
Parameters:
• httpRequest: The request object that comes from the http module.
• name: (String) The name of the variable to set.
• value: The value parameter must be a string or number.
Example
var sap = require('sap-access');
// Convert "123" to an integer and set it
sap.setIntVariable(request, 'TestVariable', '123');
// Use something that's already a number
sap.setIntVariable(request, 'TestVariable2', 42);
deleteVariable
Deletes a named variable. It is an error to delete a read-only variable. For a complete list of read-only variables,
see the Variables Reference.
deleteVariable(httpRequest, name);
Parameters:
• httpRequest: The request object that comes from the http module.
• name: (String) The name of the variable to delete.
Example
sap.deleteVariable(request, 'TestVariable');
// This will throw an exception because client.ip is a read-only variable.
sap.deleteVariable(request, 'client.ip');
The sap-access module lets you access the SAP API Management distributed cache from your Node.js code.
getCache
Parameters:
cache-name - The name of the cache to access.
Returns:
A cache object.
Example
var sap = require('sap-access');
var cache = sap.getCache('cache');
getCache
Parameters:
{parameter: 'value'} - (Optional) A configuration object. The object can be empty, or it can contain the following
optional parameters:
• resource: The name of an SAP API Management "cache resource" where the cache data is stored. Cache
resources are used to fine-tune memory allocation and other cache parameters. If not specified, a default
resource will be used. If the cache resource does not exist, then the method throws an error.
• scope: Specifies whether cache entries are prefixed to prevent collisions. Valid values are global, application,
and exclusive.
o global: All cache entries may be seen by all Node.js applications in the same SAP API Management
"environment."
o application: All cache entries may be seen by all Node.js caches that are part of the same SAP API
Management application.
o exclusive: (Default) Cache entries are only seen by Node.js caches in the same application that have
the same name. This is the default.
Returns:
A custom cache object.
Example
var sap = require('sap-access');
var customCache = sap.getCache('MyCustomCache',
{ resource: 'MyCustomResource'} );
put
Parameters:
• key: (Required) A string that uniquely identifies the item in the cache.
• data: (Required) A string, Buffer, or object that represents the data to cache. Any other data type will result in
an error. For convenience, objects will be converted into a string using "JSON.stringify".
• ttl: (Optional) The maximum time to persist the data in the cache, in seconds. If not specified then a default
TTL will be used.
• callback: (Optional) If specified, a function that will be called once the data is safely in the cache. It will be
called with an Error object as the first parameter if there is an insertion error, and otherwise it will be called
with no parameters.
Example
var sap = require('sap-access');
var cache = sap.getCache();
// Insert a string with a timeout of 120 seconds
cache.put('key2', 'Hello, World!', 120);
// Insert a string and get notified when insert is complete
cache.put('key4', 'Hello, World!', function(err) {
// "err" will be undefined unless there was an error on insert
});
Parameters:
• key (required): A string that uniquely identifies the item in the cache.
• callback (required): A function that will be called when the data is available. If there is cached data, it is
returned in the second parameter.
o error - An Error object. If there is an error while retrieving from the cache, then an Error object will be set
here. Otherwise this parameter will be set to "undefined".
o data - The data retrieved, if any. It will be one of four values:
o If a string was inserted, it will be a string.
o If a Buffer was inserted, it will be a Buffer.
o If an object was inserted, it will be a string containing the JSON version of the object as produced by
"JSON.stringify".
o If nothing was found, then it will be "undefined".
Example
var sap = require('sap-access');
var cache = sap.getCache();
cache.get('key', function(err, data) {
// If there was an error, then "err" will be set
// "data" is the item that was retrieved
// It will be a Buffer or a String depending on what was inserted.
});
remove
cache.remove('key', function(error));
Invalidate a cached item. Once a key is invalidated, subsequent get() requests will return "undefined" unless
another value is inserted.
Parameters:
• key (Required): A string that uniquely identifies the item in the cache to invalidate.
• callback (Required): A callback function that will be called with an Error object as the first parameter if there
is an error.
Example
var sap = require('sap-access');
var cache = sap.getCache();
cache.remove('key', function(err) {
The sap-access module lets you access the SAP API Management quota service from your Node.js code.
Methods
apply
Modifies the settings on a Quota object. Use this method to increment or decrement the quota, change time
intervals, and make other configurations.
Usage
var sap = require('sap-access');
var quota = sap.getQuota();
quota.apply({parameters}, callback);
Example
var sap = require('sap-access');
var quota = sap.getQuota();
function quotaResult(err, r) {
if (err) { console.error('Quota failed'); }
}
Parameters
The apply() method takes two parameters, an object and a function:
o identifier (string, required): A unique identifier of the quota bucket. In practice it might be an application
ID, IP address, or username.
o timeUnit (string, required): How long the quota bucket will accumulate until it is reset. Valid values are
"minute," "hour," "day," "week," and "month."
o allow (number, required): The maximum value for the quota bucket. This value will be combined with the
current value to return whether the quota has succeeded.
o interval (number, optional): Combined with the "timeUnit" to determine how long before the quota is
reset. The default is 1. Set to a larger value to allow quotas such as "two hours," "three weeks," and so on.
o weight (number, optional): The value to increment the quota by. Default is 1.
5. The second argument is a callback function with these two arguments:
o The first argument is an Error object if the quota cannot be incremented, or undefined if the operation
succeeded.
o The second is an object that contains the following fields:
o used (number): The current value of the quota bucket.
o allowed (number): The maximum value of the quota bucket before the quota is considered to be
exceeded. The same value was passed as "allow" in the request object.
o isAllowed (boolean): If there is room left in the quota -- true as long as "used" is less than or equal to
"allowed."
o expiryTime (long): The timestamp, in milliseconds since 1970 format, when the quota bucket will be
reset.
o timestamp (long): The timestamp at which the quota was updated.
Example
< var sap = require('sap-access');
var quota = sap.getQuota();
function quotaResult(err, r) {
if (err) { console.error('Quota failed'); }
}Put your example here>
reset
To reset the quota to zero, call quota.reset(). This method takes two parameters:
• A JSON object with these fields:
o identifier (string, required): A unique identifier of the quota bucket. In practice it might be an application
ID, IP address, or username.
o timeUnit (string, required): How long the quota bucket will accumulate until if it is reset. Valid values are
"minute," "hour," "day," "week," and "month."
o interval (number, optional): Combined with the "timeUnit" to determine how long before the quota is
reset. The default is 1. Set to a larger value to allow reset times such as "two hours," "three weeks," and so
on.
• A callback function:
o The callback takes an Error object as the first parameter if the reset fails.
The sap-access module lets you store sensitive data, such as passwords for backend services, in an encrypted
format on SAP API Management.
To support local development and testing, the SAP API Management-access module works in a "local mode" with
no dependencies on SAP API Management; however, when the module is used with an API proxy that is deployed
to SAP API Management, the "local" functionality is replaced by native SAP API Management functionality. For
example, the full compliment of flow variables are accessible in deployed mode, while only a small subset are
available when you run the Node.js application locally. For a list of these local-mode variables, see "Running in
local mode", below.
Again, on the SAP API Management platform, a much larger set of pre-defined variables is supported. Refer to the
Variables Reference for the complete list.
It's a good practice to make sure any Node.js code you add to a proxy works before you deploy it to SAP API
Management. This topic discusses ways to debug proxies that include Node.js applications after they are
deployed.
Note
The Node.js Logs button does not appear for non-Node.js API proxies.
In the Logs page, you can select a time range of logs to view, as shown below. The logs record HTTP method calls,
success or failure of calls, console.log messages, and so on. Enter a search string in the search field to display all
log entries that contain the string.
The trace tool is useful for general proxy debugging. For detailed information on using the trace tool, see Using the
Trace tool.
You can embed console.log statements in your Node.js code and view the output in the trace tool. For example,
the following statement prints the username of the user who is logging in to access the proxy:
console.log('Logging in as %s', config.username);
assert Supported
buffer Supported
domain Supported
events Supported
http Supported The virtual host and path for incoming requests is
specified in the API Proxy, not by the HTTP
module. See "Understanding support for the http
and https modules" for more information.
module Supported
path Supported
module Supported
punycode Supported
querystring Supported
module Supported
STDIO Supported Standard output and error are routed to a log file
within the SAP API Management infrastructure.
There is no standard input for scripts running on
SAP API Management. However, you can pass
arguments using the ScriptTarget element of
TargetEndpoint. See Advanced ScriptTarget
configuration for more information.
stream Supported
string_decoder Supported
timers Supported
url Supported
util Supported
vm Supported
zlib Supported
All Node.js applications running in SAP API Management must use the http or https module to listen for incoming
requests. If you were to deploy a script that doesn't listen for incoming requests, it would simply execute and exit.
The listen method of the http and https modules in Node.js takes a port number as a parameter. For example:
svr.listen(process.env.PORT || 9000, function() {
console.log('The server is running.');
});
This "port" argument is required in Node.js, but SAP API Management ignores this parameter. Instead, the API
proxy in which the Node.js script runs specifies the "virtual host" that it listens on, and the Node.js application
uses those same virtual hosts, just like any other SAP API Management proxy.
Every environment in SAP API Management has at least one virtual host. The virtual host defines the HTTP
settings for connection with the SAP API Management organization. All API proxies in an environment share the
same virtual hosts. By default, two virtual hosts are available for each environment: default and secure.
The SAP API Management tool deploynodeapp command generates an SAP API Management proxy wrapper
around the Node.js application. When deployed, the Node.js application listens on the default virtual host defined
for the environment.
SAP API Management supports the Node.js tls module. This module uses OpenSSL to provide Transport Layer
Security (TLS) and/or Secure Socket Layer (SSL) encrypted stream communication. You can use the tls module
to create secure connections to backend services from Node.js applications running on SAP API Management.
To understand how the tls module works on SAP API Management, it's important to understand how virtual hosts
are used on SAP API Management. Every environment in SAP API Management has at least one virtual host. The
virtual host defines the HTTP settings for connection with the SAP API Management organization. All API proxies
in an environment share the same virtual hosts. By default, two virtual hosts are available for each environment:
default and secure.
Now, let's look at how SAP API Management handles TLS (SSL) communication for incoming and outgoing
requests on Node.js applications:
SAP API Management does not support the "cluster" module, which allows Node.js applications to control when
additional copies of an application are started and stopped, and to communicate with them. In the parlance of the
"cluster" module, all Node.js applications are considered to be the "master."
However, SAP API Management does deploy multiple instances of each application — two in most cases, although
the system may be configured to run more if necessary.
That means that Node.js applications running inside SAP API Management, like all Node.js applications, must
assume that they will be processing many different requests "in parallel" using a single thread of control. However,
the application must not assume that it is the only copy running in the world, though it also must not assume that
there is some way to communicate with the other copies.
In the <TargetEndpoint> definition, the <ScriptTarget> element takes additional optional parameters
besides <ResourceURL>. You can also pass command-line arguments and environment variables to a Node.js
script using the <EnvironmentVariables> and <Arguments> parameters:
<TargetEndpoint name="default">
<ScriptTarget>
<ResourceURL>node://hello.js</ResourceURL>
<EnvironmentVariables>
<EnvironmentVariable name="NAME">VALUE</EnvironmentVariable>
</EnvironmentVariables>
<Arguments>
<Argument>ARG</Argument>
</Arguments>
</ScriptTarget>
</TargetEndpoint>
Trace is a tool for troubleshooting and monitoring API proxies running on SAP API Management. Trace lets you
probe the details of each step through an API proxy flow.
Trace is simple to use. You start a trace session and then make an API call to the SAP API Management, and read
the results.
1. Select API Proxies from the APIs menu.
2. Select an API proxy from the API Proxies page.
3. Be sure the API you wish to trace is deployed.
4. Choose Trace to go to the Trace tool view.
5. Use the Deployment to Trace dropdown menu to select which deployment environment and proxy revision
you wish to trace.
6. Choose Start Trace Session. When the Trace session is active, the API proxy records details of each step in
the processing pipeline. While the Trace session is running, messages and contextual data are captured from
live traffic.
Note
One Trace session can support 10 request/response transactions through the selected API proxy. If there
are 2 per router, then 20 request/response transactions are supported. Trace sessions automatically
stop after 10 minutes if you don't manually stop it.
8. When you've captured a sufficient number of requests, choose Stop Trace Session.
9. A list of captured request/response transactions displays in the left menu. Choose on any of the transactions
to view detailed results.
To read a trace, just follow the arrows: the request flow steps are shown along the top and response flow steps
along the bottom of the map.
The tool's transaction map uses icons to mark each notable step that occurs during an API proxy transaction,
including policy execution, conditional steps, and transitions. Hover over any icon to see summary information.
The phase details section of the tool lists information about the proxy's internal processing, including variables
that were set or read, request and response headers, and much more. Choose any icon to see the phase
details for that step.
Here's a sample trace tool map with the main proxy processing segments labeled:
Any good map needs a legend. The following table describes the intent of the icons you will see in the transaction
map. These icons mark each of the notable processing steps throughout the proxy flow.
Transaction map icons
The client app that sends a request to the ProxyEndpoint of the API proxy.
The circles mark transitional endpoints in the proxy flow. They are there when a request
comes in from the client, when the request goes to the target, when the response
comes back from the target, and when the response goes back to the client.
The tall bars indicate the beginning of a flow segment in the API proxy flow. Flow
segments are: ProxyEndpoint request, TargetEndpoint request, TargetEndpoint
response, and ProxyEndpoint response. A segment includes the PreFlow, Conditional
Flows, and PostFlow.
See Flows Configuration for more information.
The short bars are called "executions." You'll see these bars when Analytics actions
occur in the background. Hover over these bars to see what kind of data is being stored
in Analytics.
A policy. Each type of policy has a unique icon. This one is for the AssignMessage
policy. These icons let you see where policies are executed in the proper order and if
they are successful or not. You can choose a policy icon to see the results of its
execution and if they are expected or not. For example, you can see if the message was
transformed properly or if it is being cached.
Properly executing policies are clearly indicated by check-marks. In the case of an
error, a red exclamation mark is displayed on the icon.
Tip: Pay attention to the tooltip or the time line to see if any policy is taking longer than
expected.
Disabled. Appears on a policy icon when a policy is disabled. A policy can be disabled
with the public API. See API proxy configuration reference.
Error. Appears on a policy icon when the Policy Step condition evaluates to false
(see Flow Variables and Conditions), or on the RaiseFault policy icon whenever a
RaiseFault policy executes.
Skipped. Appears on a policy icon when the policy was not executed because the step
condition evaluated to false. See Flow Variables and Conditions for more information.
The Phase Details part of the tool tells you a lot about the state of your proxy at each processing step. Here are
some of the details provided in the Phase Details. Choose any icon in the trace tool to see details for the selected
step, or use the Next/Back buttons to move from one step to another.
Note
Trace captures message content. If your message payloads contain sensitive information, then you
should enable data masking. For instructions, see Data masking.
Variables Read Lists the flow variables that were read by a policy.
See also Introduction to Flow Variables.
Variables Read and Assigned Lists the flow variables that were read and assigned a
value by a policy.
Trace lets you see a lot of internal details about an API proxy. For example:
• You can see at a glance which policies are executing correctly or failing.
• Let's say you noticed through one of the Analytics dashboards that one of your APIs is experiencing an
unusual decrease in performance. Now, you can use Trace to help identify where the bottleneck is occurring.
Trace gives the time, in milliseconds, which it takes for each processing step to complete. If you find one step
is taking too long, you can take corrective action.
• By looking at the phase details, you can check headers that are being sent to the backend, view variables set
by policies, and so on.
• By verifying the base path, you can ensure that a policy is routing the message to correct server.
Show Disabled Policies Show any disabled policies. A policy can be disabled
with the public API. See API proxy configuration
reference.
Show Skipped Phases Show any phases that were skipped. A skipped phase
occurs when policy was not executed because the
step condition evaluated to false. See Flow Variables
and Conditions for more information.
Automatically Compare Selected Phase Compares the selected phase to the previous one.
Turn this off to see only the selected phase.
You can download an XML file of the trace results for viewing offline. The file shows the complete details of the
listening session including the contents of all headers, variables and policies.
To download raw trace output, choose Download Trace Session.
The Offline Trace tool lets you view and analyze trace sessions that were previously saved. A saved trace session
is essentially a "recording" of a trace session, and can be useful for cases where troubleshooting and further
analysis is required. The UI for the Offline Trace tool is similar to the "live" Trace tool. To learn about the Trace
Tool UI and on saving trace sessions, see Using a Trace tool.
1. Select APIs > API Proxies from the main SAP API Management menu.
2. On the API Proxies page, choose Offline Trace.
In the Offline Trace tool, choose Choose File and select a downloaded trace file from your system.
Troubleshooting
To enable root-case analysis, filters enable you to target specific calls that may be causing problems. For
example, you may need to zero in on requests that have specific content or requests coming from specific
partners or apps.
• HTTP headers - limits the trace to only calls that contain a specific header. This is a good way of helping you
troubleshoot issues. You can send a header to your app developer and ask them to include it in the call that is
To add a filter:
1. Open the Filter section of the Trace page.
2. Enter a name and value into either the Header or Query fields. Blank fields are not evaluated.
You can add more filters by choosing the Add Filter button. You can delete filters by choosing the (X) button
next to the filter.
Because the management API is RESTful, response messages can be interpreted as a combination of an HTTP
response code and an SAP API Management -specific error message.
For example, if you try to create a company entity with the same name as an existing company, the response is:
404
{
"code": "messaging.config.beans.ApplicationDoesNotExist",
"message": "APIProxy named WeatherApi does not exist in organization mycompany",
"contexts": []
}
An explanation of important HTTP response codes follows:
SAP API Management provides a "history" feature that can be helpful in troubleshooting problems as well as
managing API usage. The history feature enables you to view the operations (create, update, read, delete, deploy,
undeploy) that have been performed on your APIs and API products over time. You can see who performed each
operation, when the operation was performed, the request URI, and the response code. For update operations,
you can also view the request body that was as passed in the API call.
3. You can change the date range for the history to the last day, week, 2 months, 3 months, or year, by selecting
from the menu next to "Showing data for last".
2. You can change the date range for the history to the last day, week, 2 months, 3 months, or year, by selecting
from the menu next to Date Range.
3. You can view the request body for update operations by choosing Show in the Request Body column for the
operation.
When you don't want to use the included shared cache, you can create and configure your own cache. You can use
the cache you create beneath caching policies, rather than using the the shared cache.
Note
Under ordinary circumstances, you don't need to configure your own cache. Only configure a cache when
you need to customize the cache settings and optimize performance.
You can create multiple cache resources in each environment. When you're configuring a caching policy, you
specify whether the policy should use the included shared cache or a cache you created.
For data segregation, the scope of a cache is limited to the environment in which you created the cache. (For
example, API proxies running in a 'test' environment cannot access data in a cache running in 'prod'.) Once you
create a cache, policies can populate it with any serializable data.
These steps describe how to create or edit a cache using the management console.
1. In the management UI, choose the APIs menu, then choose Environment Configuration.
2. In the Environment dropdown, select the environment for which you want to configure caches, such as test
or prod.
3. Go to the Caches tab.
4. Choose Edit.
5. Under Caches, at the right side, choose the +Cache button to add a new cache.
The button displays the New Cache dialog.
6. In the New Cache form, enter property values for the new cache. The following table describes the settings.
Property Default
Description Notes
Name Value
Expiration Timeout in Sets how cache entries will be expired. Populate Cache
Type Seconds Entry time to live can be a specified policyand Response Cache
number of seconds after creation, a policy both override these
specified time of day each day, or a expiration settings with their
specified date. own for cache entries they
create.
7. Choose Save.
There are often situations where you want to store key/value pairs of data for longer term and access that data at
runtime with your API proxies.
For example, you could store the latitude and longitude of a location of a conference (using key names like conLAT
and conLON), retrieve those keys in an API proxy call, and pass the latitude and longitude data into the message
body of the request or response (or to a mapping API). And if the location of the conference happened to change
the following year, all you would have to do is update the values without having to touch your API proxy logic,
which gets the data using the same key names.
You store one or more key/value pairs of data in a grouping called a 'map', or 'key/value map'.
Caution:
Key/value maps aren't designed to store sensitive data such as usernames and passwords.
There may be different scopes at which you want to store key/value data. For example, if only one API proxy
requires data in a key/value map, you can create the key/value map at the API proxy scope, where only that API
proxy can access the data. Or you may want all API proxies in your test environment to have access to a key/value
map, in which case you'd create a key/value map at the environment scope.
Note:
When creating and managing key/value maps in the management UI, which this topic covers, you're creating
them at the environment scope.
or information about how to create and manage key/value maps at other scopes, such as organization or proxy
scopes (as well as the environment scope), see the following topics:
Management API: Persist Data Using KeyValueMap.
Policy: Configuring the KeyValueMapOperation Policy. The policy is also how you access key/value data at
runtime.
These steps describe how to create or edit a key/value map in the management UI. Key/value maps created this
way are at the environment scope. For example, if you create a key/value map in the 'test' environment, API
proxies running in the 'prod' environment won't have access to the key/value map.
1. In the management UI, select APIs > Environment Configuration.
2. Select the environment for which you want to configure key/value maps, such as test or prod.
3. Go to the Key Value Maps tab.
4. Click +Key Value Map to create an new one, or expand an existing key/value map and click Edit.
5. Click the +Entry button to add a new key/value pair.
Key N/A The key name that you'll use to access the data value in
your API proxies.
In organizations with Core Persistence Services (see
below), key names cannot be larger than 2 KB.
Value N/A The value of the key. Enter any combination of numbers,
letters, or special characters. There is no size limitation.
7. Choose Save.
To view or modify maps with more than 150 keys, the UI directs you to use the SAP API Management's API.
SAP API Platform enhances the availability of your API by providing built-in support for load balancing and failover
across multiple backend server instances.
TargetServer configurations decouple concrete endpoint URLs from TargetEndpoint configurations. Each
TargetServer is referenced by name in a TargetEndpoint HTTPConnection. Instead of defining concrete URL in the
configuration, you can configure one or more named TargetServers.
A TargetServer definition consists of a name, a host and a port, with an additional element to indicate whether the
TargetServer is enabled or disabled.
You can use the SAP API Management Edge UI to create and manage target servers.
For example:
• Name: target1
• Host: 1.mybackendservice.com
• Port: 80
• Enabled: Selected
Repeat these steps to add and enable more target servers.
You can use Edge management APIs to create, delete, update, get, and list target servers. For more information,
see TargetServers.
$ curl -H "Content-Type:text/xml" -X POST -d \
'<TargetServer name="target1">
<Host>1.mybackendservice.com</Host>
<Port>80</Port>
<IsEnabled>true</IsEnabled>
</TargetServer>' \
-u email:password
https://<managment_server_ip:8080>/v1/o/{org_name}/environments/test/targetservers
Sample Response:
{
"host" : "1.mybackendservice.com",
"isEnabled" : true,
"name" : "target1",
"port" : 80
}
After you create the first TargetServer, then create a second TargetServer. By defining two TargetServers, you
provide two URLs that a TargetEndpoint can use for loadbalancing:
Sample Response:
{
"host" : "2.mybackendservice.com",
"isEnabled" : true,
"name" : "target2",
"port" : 80
}
Retrieve a list of TargetServers in an environment:
$ curl -u email:password
https://<managment_server_ip:8080>/v1/o/{org_name}/environments/test/targetservers
Sample response:
[ "target2", "target1" ]
There are now two TargetServers available for use by API proxies deployed in the test environment. To load
balance traffic across these TargetServers, you configure the HTTP connection in an API proxy's target endpoint
to use the TargetServers.
There is no limit on the number of TargetServers that you can set up in an environment or reference from a
TargetEndpoint
Now that you have two TargetServers available, you can modify the TargetEndpoint HTTP connection setting to
reference those two TargetServers by name.
<TargetEndpoint name="default">
<HTTPTargetConnection>
<LoadBalancer>
<Server name="target1" />
<Server name="target2" />
</LoadBalancer>
<Path>/test</Path>
</HTTPTargetConnection>
</TargetEndpoint>
Note
Retries are triggered by I/O exceptions and HTTP time outs. Retries are not triggered by HTTP error
codes (4xx, 5xx).
You can tune availability by using options for load balancing and failover at the load balancer and TargetServer
level.
Available options for LoadBalancers are:
Algorithm
Sets the algorithm used by LoadBalancer. The available algorithms are RoundRobin, Weighted, and
MaximumFailures, each of which is documented below.
Round robin
The default algorithm,RoundRobin forwards a request to each TargetServer in the order in which the servers are
listed in the target endpoint HTTP connection.
For example:
<TargetEndpoint name="default">
<HTTPTargetConnection>
<LoadBalancer>
<Algorithm>RoundRobin</Algorithm>
<Server name="target1" />
<Server name="target2" />
</LoadBalancer>
<Path>/test</Path>
</HTTPTargetConnection>
</TargetEndpoint>
Weighted
The weighted load balancing algorithm enables you to configure proportional traffic loads for your TargetServers.
The weighted LoadBalancer distributes request to your TargetServers in direct proportion to each TargetServer's
weight. Therefore, the weighted algorithm requires you to set a weight attribute for each TargetServer. For
example:
<TargetEndpoint name="default">
Least Connection
LoadBalancers configured to use the least connection algorithm route outbound requests to the TargetServer
with fewest open HTTP connections.
<TargetEndpoint name="default">
<HTTPTargetConnection>
<LoadBalancer>
<Algorithm>LeastConnection</Algorithm>
<Server name="target1" />
<Server name="target2" />
</LoadBalancer>
</HTTPTargetConnection>
<Path>/test</Path>
</TargetEndpoint>
Maximum Failures
The maximum number of failed requests from the API proxy to the TargetServer that results in the request being
redirected to another TargetServer. As configured below, target1 will be removed from rotation after 5 failed
requests.
<TargetEndpoint name="default">
<HTTPTargetConnection>
<LoadBalancer>
<Algorithm>RoundRobin</Algorithm>
<Server name="target1" />
<MaxFailures>5</MaxFailures>
Note
If you configure MaxFailures without also configuring a HealthMonitor, then eventually all of your
TargetServers will be removed from rotation. If you configure MaxFailures, always configure an
associated HealthMonitor.
The MaxFailures default is 0. This means that SAP API Management Edge always tries to connect to the
target for each request and never removes the target server from the rotation.
Retry
Retry the request once to a different server after an I/O error (not an HTTP status code 500).
<RetryEnabled>true</RetryEnabled>
IsFallback
One (and only one) TargetServer can be set as the 'fallback' server. The fallback TargetServer is not included in
load balancing routines until all other TargetServers are identified as unavailable by the load balancer. When the
load balancer determines that all TargetServers are unavailable, all traffic is routed to the fallback server. For
example:
<TargetEndpoint name="default">
<HTTPTargetConnection>
<LoadBalancer>
<Algorithm>RoundRobin</Algorithm>
<Server name="target1" />
<Server name="target2" />
<Server name="target3" />
<IsFallback>true</IsFallback>
</LoadBalancer>
<Path>/test</Path>
</HTTPTargetConnection>
</TargetEndpoint>
The configuration above results in round robin load balancing between targets 1 and 2 until both targets 1 and 2
are unavailable. When targets 1 and 2 are unavailable, all traffic is routed to target 3.
Path
Path defines a URI fragment that will be appended to all requests issued by the TargetServer to the backend
server.
If you are using a TargetServer to define the backend service, and the backend service requires the connection to
use the HTTPS protocol, then you must enable SSL in the TargetServer definition. This is necessary because
the <Host> tag does not let you specify the connection protocol. Shown below is the TargetServer definition for
one-way SSL where SAP API Management Edge makes HTTPS requests to the backend service:
<TargetServer name="target1">
<Host>weather.yahooapis.com</Host>
<Port>443</Port>
<IsEnabled>true</IsEnabled>
<SSLInfo>
<Enabled>true</Enabled>
</SSLInfo>
</TargetServer>
If the backend service requires two-way, or mutual, SSL, then you configure the TargetServer by using the same
SSL configuration settings as TargetEndpoints:
<TargetServer name="TargetServer 1">
<IsEnabled>true</IsEnabled>
<Host>www.example.com</Host>
<Port>443</Port>
<SSLInfo>
<Ciphers/>
<ClientAuthEnabled>true</ClientAuthEnabled>
<Enabled>true</Enabled>
<IgnoreValidationErrors>false</IgnoreValidationErrors>
<KeyAlias>keystore-alias</KeyAlias>
<KeyStore>keystore-name</KeyStore>
<Protocols/>
<TrustStore>truststore-name</TrustStore>
</SSLInfo>
</TargetServer >
For information on the <SSLInfo> properties, such as <Ciphers>, <ClientAuthEnabled>, etc., see the information
on setting those properties for a Virtual Host.
For complete instructions on configuring outbound SSL, see Configuring SSL to the Backend Service.
Health monitoring enables you to enhance load balancing configurations by actively polling the backend service
URLs defined in the TargetServer configurations. The HealthMonitor acts as a simple client that invokes a
backend service over TCP or HTTP. A TCP client simply ensures that a socket can be opened. You configure the
HTTP client to submit a valid HTTP request to the backend service. You can define HTTP GET, PUT, POST, or
DELETE operations. Typically, you define a simple GET request that simply shows that the backend service is
available.
You create a HealthMonitor by setting one up in a TargetEndpoint's HTTPConnection configuration. A simple
HealthMonitor defines an IntervalInSec combined with either a TCPMonitor or an HTTPMonitor.
TCPMonitor
The configuration below defines a HealthMonitor that polls each TargetServer by opening a connection on port 80
every 5 seconds.
• If the connection fails or takes more than 10 seconds to connect, then the failure count increments by 1 for
that TargetServer.
• If the connection succeeds, then the failure count for the TargetServer is reset to 0.
You can add a HealthMonitor as a child element of the TargetEndpoint's HTTPTargetConnetion element, as
shown below:
<TargetEndpoint name="default">
<HTTPTargetConnection><HealthMonitor>
<IsEnabled>true</IsEnabled>
<IntervalInSec>5</IntervalInSec>
<TCPMonitor>
<ConnectTimeoutInSec>10</ConnectTimeoutInSec>
<Port>80</Port>
</TCPMonitor>
</HealthMonitor>
HTTPMonitor
A sample HealthMonitor that uses an HTTPMonitor will submit a GET request to the backend service once every
five seconds. The sample below adds an HTTP Basic Authorization header to the request message. The Response
configuration defines settings that will be compared against actual response from the backend service. In the
example below, the expected response is an HTTP response code 200 and a custom HTTP header ImOK whose
value isYoureOK. If the response does not match, then the request will treated as a failure by the load balancer
configuration.
Note
All of the Request and Response settings in an HTTP monitor will be specific to the backend service that
must be invoked.
<HealthMonitor>
<IsEnabled>true</IsEnabled>
<IntervalInSec>5</IntervalInSec>
<HTTPMonitor>
<Request>
<ConnectTimeoutInSec>10</ConnectTimeoutInSec>
<SocketReadTimeoutInSec>30</SocketReadTimeoutInSec>
<Port>80</Port>
<Verb>GET</Verb>
<Path>/healthcheck</Path>
<Headers>
<Header name="Authorization">Basic 12e98yfw87etf</Header>
</Headers>
</Request>
<SuccessResponse>
<ResponseCode>200</ResponseCode>
<Headers>
<Header name=”ImOK”>YoureOK</Header>
</Headers>
</SuccessResponse>
</HTTPMonitor>
</HealthMonitor>
Virtual Hosts
Virtual hosts let multiple domain names connect to the same host. A virtual host on SAP API Management defines
the domains and Router ports on which an API proxy is exposed, and, by extension, the URL that apps use to
access an API proxy. A virtual host also defines whether the API proxy is accessed by using the HTTP protocol, or
by the encrypted HTTPS protocol. In SAP API Management Edge, a virtual host is identified by a name. By default,
when you first create an SAP API Management Edge organization, you get two virtual hosts in each environment:
• default - http://[org]-[environment].sap.net (port 80)
• secure - https://[org]-[environment].sap.net (port 443)
https://myorg-prod.<host>:<port>/v1/{proxy-base-path}/{resource-path}
However, a domain name containing "host:port" may not be what you want to expose to your customers. A virtual
host can map your own domain name to your organization, letting developers access your API through a domain
specific to your company, for example:
https://api.myCompany.com/v1/{proxy-base-path}/{resource-path}
Note that creating a virtual host does not also make the domain name accessible. You must still create a DNS
record for the domain.
There are no default organizations, environments, or virtual hosts created for you. After you complete the SAP
API Management installation process, your first action is typically to create an organization, environment, and
virtual host through the "onboarding" process.
Note:
To perform onboarding, please check section 3.7 Onboard an Organization topic in the SAP API Management
Installation Onboarding Guide.
For example, if you use the default values in the setup-org.sh script, you create:
• A user of your choosing to function as the organization administrator
• An organization named example
• An environment in the organization named prod
• A virtual host in the environment named default that allows HTTP access on port 9001
• No host alias
After running the onboarding script, you can later add any number of organizations, environments, and virtual
hosts to your installation.
Virtual hosts are opened on the Router node. Therefore, you have to ensure that the port that you specify for the
virtual host is open on the Router node. You can use a command in the form below to open a port:
$ iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport 9001 -j ACCEPT --
verbose
http://<router-ip>:9001/{proxy-base-path}/{resource-path}
Note that this URL uses the IP address of the Router and the virtual host port on the Router to access your APIs.
Typically, you do not publish your APIs to customers with an IP address and port number. Instead, you define a
DNS entry for the router and port. For example:
http://myAPI.myCo.com/{proxy-base-path}/{resource-path}
If you define the DNS entry, then you also must create a host alias for the virtual host that matches the domain
name of the DNS entry. From the example above, you would specify a host alias of myAPI.myCo.com when you
create the virtual host.
Note also that the URL uses the HTTP protocol. To use the encrypted HTTPS protocol, you must create a virtual
host that references a keystore. A keystore contains the certificate and private key required to support HTTPS.
You can use the SAP API Management UI to see the virtual hosts defined in an environment:
1. Login to the management UI at http://<ms-ip>:9000 , where <ms-ip> is the IP address of the Management
Server node.
2. In the management UI menu, select APIs > Environment Configuration.
3. Select the environment, such as prod or test. The virtual hosts defined for the environment appear.
If the virtual host is configured to use a keystore or truststore, select the Show button to see more
information.
You can also use the SAP API Management APIs to view information about virtual hosts. For example, the List
Virtual Hosts API returns a list of all virtual hosts:
Sample response:
[
To see information about a specific virtual host, use the Get Virtual Host API:
Sample response:
{
"hostAliases" : [sapdocs-prod.<host:port> ],
"interfaces" : [ ],
"name" : "default",
"port" : "9001"
}
If the virtual host is configured to use SSL, a lock icon appears next to the name of the virtual host. That means an
SSL certificate, key, and certificate chain has been uploaded to SAP API Management and associated with the
virtual host.
To see information about the available certificates:
1. Login to the management UI.
2. In the SAP API Management UI menu, select Admin > SSL Certificates.
3. Expand the keystores until you see the certificate.
An API proxy references the virtual hosts that it supports in its ProxyEndpoint definition. When you create a new
API proxy, SAP API Management automatically configures its ProxyEndpoint to use all available virtual hosts.
After SAP API Management notifies you that your new virtual host has been created, any new API proxies that you
create automatically reference the virtual host.
Note
If you create a new API proxy that should not be accessible over a particular virtual host, then you must
edit the API proxy to remove that virtual host from its ProxyEndpoint.
If you created any API proxies before requesting the virtual host, then you must edit the API proxy to add the new
virtual hosts to its ProxyEndpoint. Otherwise, the API proxy is not accessible by the virtual host.
If you are developing your API proxies in XML, edit the XML file for the ProxyEndpoint to add or remove a virtual
host.
<HTTPProxyConnection>
<BasePath>/oauth10a/client_credential</BasePath>
<VirtualHost>default</VirtualHost>
<VirtualHost>secure</VirtualHost>
<VirtualHost>MyVirtualHost</VirtualHost>
</HTTPProxyConnection>
7. Save the API proxy. If the API proxy has been deployed, saving it redeploys it with the new setting.
Organization users are given explicit permission by the organization administrator to create, read, edit, and/or
delete entities in an SAP API Management organization. Permissions are role-based, where a role conveys a
specific, targeted set of permissions. This permission scheme is also called role-based access control, or RBAC
for short.
Organization users are typically members of your API team who develop and test APIs, run reports, and perform
other API admin tasks. Do not confuse organization users with app developers, the consumers of your APIs. The
process of onboarding app developers and managing their access to your APIs is an entirely separate topic.
Also, note that topic applies to API management, not API BaaS, which has its own user management framework.
Organization users can interact with the following entities. The degree of interaction permitted depends on the
role or roles that are assigned to the user by the organization administrator.
• API proxies
• API products
• Developer apps
• Developers
• Environments (Trace tool sessions and deployments)
• Custom reports (Analytics)
Before you and your team can start using SAP API Management, you need to have an account and an
organization. Once you have an account and an organization, if you're an administrator, you have access to the
Admin tab where you can add and modify users. As part of adding or modifying users, you set the user's role.
The Organization Users table on the Admin > Organization Users page lists all of the users attached to the
current organization. For each user you can see:
Note
By default, all users associated with an organization can view details about other organization users, such
as email address, first name, and last name. Only users with the Organization Administrator role can add
or update other organization users.
• Name: The name of the user you entered when you created the user.
• Primary email: The email address you entered when you created the user.
• Role: The role of the user, which determines the degree of access. By default, all users have a user role that
gives them full access to all features in SAP API Management.
Adding Users
Users of API Platform are members of the API team who develop and test the API, or run reports—not external
developers. To add an organization user:
1. In the SAP API Management management UI, while logged in as an organization administrator, select Admin
> Organization Users.
2. Choose + User. The "Add a User" screen appears.
3. Enter the user's First Name, Last Name, and Email.
4. Select the Role you want to offer to the users.
5. Choose Save.
The First Name, Last Name, and Email Address fields are editable, so if needed, you can change what you initially
entered for the user. You can also change the role selection if needed.
You can add one or more roles to a user when you create a new user or if you edit an existing user.
Note
If a user has multiple roles assigned, the greater permission takes precedence. For example, if one role
doesn't allow the user to create API proxies, but another role does, then the user can create API proxies.
In general, it is not a common use case to assign users multiple roles.
Note
This only removes the user from the current account. If the user is a member of multiple accounts, they
remain in the system.
An org admin can edit the first name, last name, and email address fields in the management UI.
Administrators can also change the user's role.
Assign Roles
This topic discusses role-based access control for SAP API Management organizations and explains how to create
roles and assign users to them. You must be an organization administrator to perform the tasks described here.
Roles are essentially CRUD-based permission sets. CRUD means "create, read, update, delete". For example, a
user may be given a role that permits her to read or "get" details about a protected entity, but not permission to
update or delete it. The organization administrator is the highest-level role, and can perform any CRUD operation
on protected entities, which include:
• API proxies
• API products
• Developer apps
• Developers
• Environments (Trace tool sessions and deployments)
• Custom reports (Analytics)
Getting started
In SAP API Management, user roles form the basis of role-based access, meaning that you can control what
functions a person can access by assigning them a role (or roles). Here are a few things you need to know about
roles:
Each SAP API Management Edge organization comes with a few built-in roles that you can assign to
administrative users:
• Organization Administrator - Super user. Has full CRUD access to resources in the organization. In an SAP
API Management Edge installation, the most powerful role is the System Administrator Role, which also has
access to system-level functions that the Organization Administrator doesn't.
• Read-only Organization Administrator - Has read-only access to resources in the organization.
• Operations Administrator - Deploys and tests APIs; has read-only access to other resources.
• Business User - Creates and manages API products, developers, developer apps, and companies; creates
custom reports on API usage; has read-only access to other resources.
• User - Creates API proxies and tests them in the test environment; has read-only access to other resources.
The built-in roles control the level of access in both the management UI and the management API.
To see the permissions set for each built-in role (as an Organization Administrator or a Read-only Organization
Administrator), select Admin > Organization Roles > name_of_role in the management UI.
For more information about how resource paths map to permissions, see "About permission setting" in Creating
roles with the API.
When a Developer Portal is provisioned for you, another role is added to your organization called Developer
Administrator. This role, which includes a single user called devadmin+{org_name}@apigee.com, is solely for the
purpose of connecting your Developer Portal to your SAP API Management Edge organization. Because the portal
displays your SAP API Management Edge developer apps, API products, and so on, it must stay in sync with your
SAP API Management Edge organization by making management API calls that require authentication. The
devadmin "user" has the necessary permissions.
You can add one or more roles to a user when you create a new user or if you edit an existing user.
Note
If a user has multiple roles assigned, the greater permission takes precedence. For example, if one role
doesn't allow the user to create API proxies, but another role does, then the user can create API proxies.
In general, it is not a common use case to assign users multiple roles.
1. Select Admin > Organization Users.
2. Either choose + User or choose an existing user.
3. Choose in the Roles field, and a dropdown appears.
4. Select a role to add.
5. Repeat steps 3 and 4 to add additional roles to the user if you want.
SAP API Management provides a set of default roles, out-of-the-box, and they are listed below.
• Business user
• Operations administrator
• Organization administrator
• User
The table shows you the levels of protection for resources. In this context, resources refer to "entities" that users
can interact with through the SAP API Management UI and API.
• The first column lists the general names of resources that users interact with. It also includes some other
things like API Proxies, Products, Deployments, etc. This column reflects the names of things as you see them
in the management UI.
• The second column lists the paths used to access resources through the management API.
• The third column lists the operations the role can perform on each resource and path. The operations are
GET, PUT, and DELETE. In the UI, these same operations are referred to as View, Edit, and Delete. Just keep in
mind that the UI and API uses different terms for these operations.
You can assign roles through management APIs or through the management UI. Either way, you're working with
CRUD permissions, although the API and UI use slightly different terminology.
The management UI refers to the same CRUD operations, but with different wording:
• View: Enables a user to view protected resources. Typically, you can view resources one at a time, or view a
list of resources.
• Edit: Enables a user to update a protected resource.
• Create: Enables a user to create a protected resource.
• Delete: Enables a user to delete an instance of a protected resource. Note: You can only delete a specific
instance of a resource. You cannot, for example, delete ALL API proxies, only a specific one.
Custom roles let you apply fine-grained permissions to these SAP API Management entities such as API proxies,
products, developer apps, developers, and custom reports.
This topic explains how to create custom roles in the management UI. Only an organization administrator can
create custom roles. Custom roles allow the admin to fine-tune which permissions to grant on specific resources.
For example, you can create a custom role that only grants users permission to view certain resources.
Note
SAP API Management also includes a set of pre-defined roles. For an introduction to roles and the
permissions granted to roles, see Manage users and roles. We recommend that you review that topic
before creating custom roles.
You can create custom roles to fine-tune access to these SAP API Management entities:
• API proxies
• API products
• Developer apps
• Developers
• Environments (Trace tool sessions and deployments)
• Custom reports (Analytics)
You can achieve even more granularity by applying role based access to specific instances of an entity. For
example, you can apply role-based access to all API products or to specific ones.
Precedence
More granular permissions take precedence over less granular ones. For example, permissions applied to a
specific developer app take precedence over a less-granular permission applied to all developer apps.
You can set some custom role permissions on an entity as a collection (e.g., all API products) or on a single
instance of an entity (e.g., one specificproduct).
If you set permissions on an instance, a privileged user can perform the permitted operations on that instance
only. If set on a collection (e.g., all API proxies), the user can perform the operations on any instance in the
collection.
You can also enable deploy and trace options on both collections and instances of APIs and caches. These
operations are also environment specific. That is, you can allow a role to deploy only to the prod environment.
An org administrator can create custom roles through the management UI.
1. Go to Admin > Organization Roles.
2. Choose + Custom Role.
3. Use the New Custom Role dialog to create the custom role.
This topic discusses how to create custom roles and assign roles to users through the management API. We also
show how to test role assignments through the API.
Create a 'development' role to enable developers to view, create, and update API proxies.
The permissions that can be set on collections are GET and PUT.
The permissions that can be set on individual members of a collection are GET, PUT, and DELETE. For the
'development' role, we add GET and PUT permissions on APIs. GET enables users to view any APIs, including API
proxy configuration files, associated policies, Javascript, XSLT files, and so on. The PUT permission on APIs
enables developers to create, modify, import, export, deploy and undeploy API proxies.
The path attribute specifies the resource on which you set the permissions. For example, /applications, /apps,
/apiproducts, /developers, or /reports.
Create a 'testing' role to enable quality engineers to view API proxies and their contents (including, for example,
policies).
GET enables users to view any APIs, including their configuration files, as well as any associated policies,
JavaScript, XSLT files, and so on. By adding this permission to the 'testing' role, we enable quality engineers to
view the contents of the APIs that they are testing. Users in this role will not, however, be able to create, modify,
import, export, deploy and undeploy API proxies.
$ curl -u myname:mypass
https://<host:port>/v1/o/{org_name}/userroles/testing/permissions -H "Content-
type:application/json" -X POST -d'{"path" : "/applications","permissions" : [ "get"
]}'
The minimum set of permissions that have to be set to allow the user to log in to the SAP API Management UI are:
$ curl -u myname:mypass
https://<host:port>/v1/o/{org_name}/users/[email protected]/userroles -H "Content-
type:application/json" -X POST -d'{"role" : [ {"name" : "testing"} ] }'
Impersonate the user and make a request to API Services to view API proxies. The user should be able to view
APIs, along with their contents.
Impersonate the user and make a request to API Services to create an API proxy. The request will be rejected by
API Services, as the role 'testing' does not permit the user to create APIs.
$ curl -u myname:mypass
https://<host:port>/v1/o/{org_name}/users/[email protected]/userroles -H "Content-
type:application/json" -X POST -d'{"role" : [ {"name" : "development"} ] }'
Impersonate the user and repeat the request to the API Platform to create an API proxy. The request will be
successful, as the role 'development' does permit the user to create APIs.
As an organization administrator, you can check the list of user roles for a user at any time:
$ curl -u myname:mypass
https://<host:port>/v1/o/{org_name}/users/[email protected]/userroles
This topic offers a basic overview of OAuth 2.0 on SAP API Management.
OAuth 2.0
There are many books, blogs, and sites devoted to OAuth 2.0. We highly recommend that you begin by reviewing
the IETF OAuth 2.0 specification. Here's the definition of OAuth 2.0 from the OAuth 2.0 IETF specification itself:
"The OAuth 2.0 authorization framework enables a third-party application to obtain limited access to an HTTP
service, either on behalf of a resource owner by orchestrating an approval interaction between the resource owner
and the HTTP service, or by allowing the third-party application to obtain access on its own behalf."
The main thing you need to know is that OAuth 2.0 provides a way for apps to gain limited access to a user's
protected resources (think of bank account or any other sensitive information a user might wish to access from an
app) without the need for the user to divulge her login credentials to the app.
Note
Let's say you found an app that lets you access multiple bank accounts. Maybe the app is used to help
with your taxes, or for managing your budget. You have three bank accounts that you want to manage
with the app, and you have a different username and password for each one. Now, for the app to access
your bank accounts, it needs those sensitive credentials. Basically, you're giving this sensitive information
to the app. Do you trust the app to possess your passwords and usernames? What if the app is hacked?
Now, you've got to remember change your bank credentials for each account. This is the fundamental
problem that OAuth 2.0 solves. Read on to learn how.
Here is the general flow for the OAuth 2.0 security framework. We'll discuss this flow in more detail in this topic,
starting with a diagram, which illustrates a lot about how OAuth 2.0 works. If you're unfamiliar with the terms used
in this diagram, read this section for a quick introduction.
You can protect any API proxies through SAP API Management with OAuth 2.0. It includes an authorization server
implementation, and as such, can generate and validate access tokens. Developers begin by registering their
apps with SAP API Management. Registered apps can request access tokens through any of the four grant
type interactions.
SAP API Management provides a multi-faceted OAuthV2 policy that implements the details of each grant type,
making it relatively easy to set up OAuth on SAP API Management. For example, you can configure a policy that
receives a request for an access token, evaluates all required credentials, and returns an access token if the
credentials are valid.
If you want to see how it fits together, check out the end-to-end tutorial. The tutorial steps through the process of
configuring the OAuth 2.0 policy, requesting an access token, and calling a protected API.
Note that any resource servers that your secure API proxy calls should be behind a firewall (that is, the resources
must not be accessible through any means besides the API proxy or another API that is well secured).
Think of grant types as different paths or interactions an app can take to gain an access token. Each grant type
addresses one or more use cases, and you'll need to select which grant type(s) to use based on your own needs.
In general, each grant type has advantages and disadvantages, and you'll need to weigh the tradeoffs based on
your business use cases. One important consideration is the "trustworthiness" of the apps that will be accessing
your data. Generally, third-party apps are less trustworthy than apps that are developed and used within an
enterprise.
SAP API Management supports the four main OAuth 2.0 grant types:
• authorization code -- Considered the most secure grant type. Before the authorization server issues an
access token, the app must first receive an authorization code from the resource server. You've seen this flow
anytime your app opens a browser to the resource server's login page and invites you log in to your actual
account (for example, Facebook or Twitter).
If you successfully log in, the app will receive an authorization code that it can use to negotiate an access
token with the authorization server. Typically, this grant type is used when the app resides on a server rather
than on the client. This grant type is considered highly secure because the client app never handles or sees
the user's username or password for the resource server (that is, for example, the app never sees or handles
your Twitter credentials). This grant type flow is also called "three-legged" OAuth.
• implicit -- Considered a simplified version of authorization code. Typically this grant type is used when the
app resides on the client. For example, the app's code is implemented in a browser using JavaScript or
another scripting language (instead of residing and running on a separate web server). In this grant type flow,
the authorization server returns an access token directly when the user is authenticated, rather than issuing
an authorization code first. Implicit grants can improve app responsiveness in some cases, but this advantage
needs to be weighed against possible security implications as described in the IETF specification.
• resource owner password credentials -- In this flow, the client is issued an access token when the user's
username/password are validated by the authorization server. This flow is recommended for highly trusted
applications. An advantage of this flow over, say, basic authentication, is that the user only presents his
username/password once. From then on, the access token is used.
An access token is a long string of characters that serves as a credential used to access protected resources.
Resources tokens (also called bearer tokens) are passed in Authorization headers, like this:
The resource server understands that the access token "stands in" for credentials like username and password. In
addition, the access tokens can be issued with restrictions, so that, for example, the app can read but not write or
delete data on the resource server. Note that an access token can be revoked if, for instance, the app is
compromised. In this case, you will need to get a new access token to continue using the app; however, you will
not have to change your username or password on the protected resources server (for example, Facebook or
Twitter).
Access tokens generally have an expiration (for security reasons). Some grant types allow the authorization
server to issue an refresh token, which allows the app to fetch a new access token when the old one expires. For
more details on access and refresh tokens, refer to the IETF OAuth 2.0 specification.
Through the mechanism of scopes, OAuth 2.0 can grant an app limited access to protected resources. For
example, an app may have access only to specific resources, may be able to update resources, or may only be
granted read-only access. Under so-called "three-legged" OAuth flows, the user typically specifies the level of
access through a consent page (for example, a web page where the user selects the scope with a checkbox of
other mechanism).
All clients (apps) must register with the OAuth 2.0 authorization server from which they intend to request access
tokens. When you register an app, you receive back a set of keys. One is a public key called the client identifier,
and the other is a secret key called the client secret. Without these keys, an app cannot issue requests for
authorization codes or access tokens to the authorization server. Note that while the IETF OAuth specification
calls these keys client ID and client secret, the SAP API Management UI calls them the Consumer ID and
Consumer secret. They are equivalent.
Which OAuth 2.0 grant type flow you chose to implement depends on your specific use case, as some grant types
are more secure than others. Your choice of grant types depends on the trustworthiness of the client app and
requires very careful consideration, as described in the following table:
B2B Highly trusted apps, written by internal developer Client credentials Typically, the app
(extranet), or developers with a trusted business relationship is also the resource
intranet, with the API provider. owner
other Apps that need to access resources on their own Requires Client ID
behalf. and Client secret
keys
Requires app to be
registered with
service provider
Intranet Trusted apps written by internal or trusted third- Password Requires client Id
sites, party developers. Implicit and secret, plus
portals A good example is logging in to your company HR username and
site to make insurance selections, submit reviews, password
or change personal information. Requires app to be
registered with
service provider
B2C There is an individual end user (mobile user) Implicit Requires app to be
involved, and user credentials are stored on the registered with the
mobile device. service provider.
User credentials
are stored on the
device running the
app.
It is relatively simple to 'step up' your API security scheme from API key validation to OAuth client credentials.
Both schemes use the same consumer key and secret to validate the client app. The difference is that client
credentials provides an extra layer of control, since you can easily revoke an access token when needed, without
requiring you to revoke the app's consumer key. To work with the default OAuth endpoints, you can use any
consumer key and secret generated for app in your organization to retrieve access tokens from the token
endpoint. (You can even enable client credentials for apps that already have consumer keys and secrets.) For
details on API key validation, see API keys
With the client credentials grant type, an app sends it's own credentials (the Client ID and Client Secret) to a
GenerateAccessToken endpoint on SAP API Management. If the credentials are valid, it returns an access token
to the client app.
This topic offers a general description of the OAuth 2.0 client credentials grant type and discusses how to
implement this flow on SAP API Management.
Most typically, this grant type is used when the app is also the resource owner. For example, an app may need to
access a backend cloud-based storage service to store and retrieve data that it uses to perform its work, rather
than data specifically owned by the end user. This grant type flow occurs strictly between a client app and the
authorization server. An end user does not participate in this grant type flow.
Roles
Roles specify the "actors" that participate in the OAuth flow. Let's do a quick overview of the client credentials
roles to help illustrate where SAP API Management fits in. For a complete discussion of OAuth 2.0 roles, see
the IETF OAuth 2.0 specification.
• Client App -- The app that needs access to the user's protected resources. Typically, with this flow, the app
runs on server rather than locally on the user's laptop or device.
• SAP API Management -- In this flow, SAP API Management is the OAuth authorization server. It's role is to
generate access tokens, validate access tokens, and pass authorized requests for protected resources on to
the resource server.
• Resource Server -- The backend service that stores the protected data that the client app needs permission
to access. If you are protecting API proxies hosted on SAP API Management, then SAP API Management is
also the resource server.
Here is a summary of the steps required to implement the client credentials code grant type where SAP API
Management serves as the authorization server. Remember, with this flow, the client app simply presents its
client ID and client secret, and if they are valid, SAP API Management returns an access token.
Prerequisite: The client app must be registered with SAP API Management to obtain the client ID and client secret
keys. See Registering client apps for details.
Note
Although you can pass the client_id and client_secret values as query parameters as shown above, it's a
good practice to pass them as a base64 URL encoded string in the Authorization header. To do this, you
need to use a base64 encoding tool or utility to encode the two values together with colon separating
them. Like this: aBase64EncodeFunction(clientidvalue:clientsecret). So, the example above would be
encoded like this:
result = aBase64EncodeFunction(ns4fQc14Zg4hKFCNaSzArVuwszX95X:ZIjFyTsNgQNyxI) // Note the colon
separating the two values.
The result of base64 encoding the above string is:
bnM0ZlFjMTRaZzRoS0ZDTmFTekFyVnV3c3pYOTVYOlpJakZ5VHNOZ1FOeXhJOg==
Then, make the token request like this:
As the authorization server, SAP API Management processes requests for access tokens. As the API developer,
you need to create a proxy with a custom flow to handle token requests and add and configure an OAuthV2 policy.
This section explains how to configure that endpoint.
<OAuthV2 name="GetAccessToken">
<Operation>GenerateAccessToken</Operation>
<ExpiresIn>3600000</ExpiresIn>
<SupportedGrantTypes>
<GrantType>client_credentials</GrantType>
The API call to obtain the access token is a POST and includes an Authorization header with the base64 encoded
client_id + client+secret and the query parameter grant_type=client_credentials. It can also include optional
parameters for scope and state. For example:
To protect your API with OAuth 2.0 security, you need to add an OAuthV2 policy with the VerifyAccessToken
operation. This policy checks that incoming requests have a valid access token. If the token is valid, SAP API
Management processes the request. If it is not valid, SAP API Management returns an error.
To call an API that is protected with OAuth 2.0 security, you need to present a valid access token. The correct
pattern is to include the token in an Authorization header, as follows: Note that the access token is also referred to
as a "bearer token".
Authorization code is one of the most commonly used OAuth 2.0 grant types. The authorization code flow is a
"three-legged OAuth" configuration. In this configuration, the user authenticates himself with the resource server
and gives the app consent to access his protected resources without divulging username/passwords to the client
app.
This topic offers a general description and overview of the OAuth 2.0 authorization grant type flow and discusses
how to implement this flow on SAP API Management.
Use cases
This grant type is intended for apps that are written by third-party developers who do not have a trusted business
relationship with the API provider. For example, developers who register for public API programs should not
generally be trusted. With this grant type, the user's credentials on the resource server are never shared with the
app.
Code sample
You can find a complete, working sample implementation of the authorization code grant type on SAP API
Management in the api-platform-samples repo on GitHub. See the oauth-advanced sample in the api-platform-
samples/sample-proxies directory.
Flow diagram
Here is a summary of the steps required to implement the authorization code grant type where SAP API
Management serves as the authorization server. Remember, the key to this flow is that the client never gets to see
the user's credentials on the resource server.
Prerequisite: The client app must be registered with SAP API Management to obtain the client ID and client secret
keys.
Note
It is important to note that the client app never sees this information. It is handled server-side and
negotiated between the login app and SAP API Management.
6. SAP API Management sends the authorization code back to the client
SAP API Management sends a 302 redirect with the auth code attached as a query parameter to the client.
7. The client retrieves the authorization code and requests an access code from SAP API
Management
Now with a valid auth code, the client can request an access token from SAP API Management. It does this by
POSTing the client ID and client secret keys (obtained when the app was registered on SAP API Management), the
grant type, and scope. By including the client ID and secret keys SAP API Management can verify that the client
app is the one that was registered. For example:
$ curl https://{org_name}-
test.<host:port>/my_oauth_proxy/accesstoken?code=Xyz123&grant_type=authorization_code
-X POST -d 'client_id=bBGAQrXgivA9lKu7NMPyoYpKNhGar6K&client_secret=hAr4GngA9vAyvI4'
As the authorization server, SAP API Management needs to process a number of OAuth requests: for access
tokens, auth codes, refresh tokens, login page redirects, etc. There are two fundamental steps to configure these
endpoints:
• Creating custom flows
• Adding and configuring OAuthV2 policies
You typically configure this grant type flow so that each step or "leg" of the flow is defined by a flow in the SAP API
Management proxy. Each flow has an endpoint and a policy that performs the OAuth-specific task required, such
as generating an authorization code or an access token. For example, as shown in the XML
below,the /oauth/authorizationcode endpoint has an associated policy called GenerateAuthCode (which is an
OAuthV2 policy with the GenerateAuthorizationCode operation specified).
The easiest way to show the flow configuration is with an XML example. See the in-line comments for information
about each flow. This is an example -- names of flows and paths can be configured however you wish.
<Flows>
<Flow name="RedirectToLoginApp">
<!--
Publish this URI to developers to use for their 'login' link
-->
<Condition>proxy.pathsuffix == "/oauth/authorize"</Condition>
<Request>
<Step><Name>RedirectToLoginPage</Name></Step>
</Request>
</Flow>
<Flow name="GetAuthCode">
Each endpoint has a policy associated with it. Let's see examples of the policies.
Login redirect
This is the /oauth/authorize path. The attached policy is responsible for redirecting the user to a login app, where
the end user can safely authenticate and authorize the client app to access his protected resources without
divulging his username and password to the client app. You can accomplish this with a service callout policy,
JavaScript, Node.js, or other means.
The API call to do the request is a GET and requires the query parameters client_id, response_type, redirect_uri,
scope, and state.
$ curl http://myorg-
test.<host:port>/oauth/authorize?client_id={consumer_key}&response_type=code&redirect_
uri={redirect_uri}&scope=scope1%20scope2&state={some_string}
The API call to obtain the authorization code is a GET and requires the query parameters client_id, response_type,
and optionally scope and state, as shown in this example:
$curl http://myorg-
test.<host:port>/oauth/authorizationcode?client_id={consumer_key}&response_type=code&s
cope=scope1%20scope2&state={some_string}
<OAuthV2 name="GetAccessToken">
<Operation>GenerateAccessToken</Operation>
<ExpiresIn>360000000</ExpiresIn>
<SupportedGrantTypes>
<GrantType>authorization_code</GrantType>
</SupportedGrantTypes>
<GrantType>request.queryparam.grant_type</GrantType>
<GenerateResponse/>
</OAuthV2>
The API call to obtain the access code is a POST and must include the client_id, client_secret, grant_type=code,
and, optionally, scope. For example:
Attach a VerifyAccessToken policy (OAuthV2 policy with the VerifyAccessToken operation specified) to the
beginning of any flow that accesses a protected API, so that it is executed whenever a request for a protected
resources comes in. SAP API Management checks to be sure each request has a valid access token. If not, an
error is returned.
<OAuthV2 async="false" continueOnError="false" enabled="true"
name="VerifyAccessToken">
<DisplayName>VerifyAccessToken</DisplayName>
<ExternalAuthorization>false</ExternalAuthorization>
<Operation>VerifyAccessToken</Operation>
<SupportedGrantTypes/>
<GenerateResponse enabled="true"/>
<Tokens/>
</OAuthV2>
To call an API that is protected with OAuth 2.0 security, you need to present a valid access token. The correct
pattern is to include the token in an Authorization header, as follows: Note that the access token is also referred to
as a "bearer token".
The resource owner password (or "password") grant type is mostly used in cases where the app is highly trusted.
In this configuration, the user provides his resource server credentials (username/password) to the client app,
which sends them in an access token request to SAP API Management. An identity server validates the
credentials, and if they are valid, SAP API Management proceeds to mint an access token and returns it to the
app.
This topic offers a general description and overview of the OAuth 2.0 resource owner password grant type flow
and discusses how to implement this flow on SAP API Managment.
Use cases
This grant type is intended for highly trusted or privileged apps because the user is required to give his resource
server credentials to the app. Typically, the app provides a login screen where the user enters her credentials.
Flow diagram
The following flow diagram illustrates the resource owner password grant type flow with SAP API Management
serving as the authorization server.
Here is a summary of the steps required to implement the password grant type where SAP API Management
serves as the authorization server.
Prerequisite: The client app must be registered with SAP API Management to obtain the client ID and client secret
keys.
Here is a sample POST request, which includes the required parameters for this grant type:
3. SAP API Management receives the request and processes the login credentials
A typical pattern is to use an ExtractVariables policy to extract the username and password from the request and
save them as flow variables. Then, use a Service Callout or JavaScript policy to call the identity service, sending in
the credentials. This could be an LDAP service or any service that you wish to use to validate the credentials.
If the identity service validates the credentials, and returns a 200 response, then SAP API Management will
continue processing the request; otherwise, it stops processing and returns an error to the client app.
<OAuthV2 name="GetAccessToken">
<Operation>GenerateAccessToken</Operation>
<ExpiresIn>360000000</ExpiresIn>
<SupportedGrantTypes>
<GrantType>password</GrantType>
</SupportedGrantTypes>
<GrantType>request.queryparam.grant_type</GrantType>
<UserName>login</UserName>
<PassWord>password</PassWord>
<GenerateResponse/>
</OAuthV2>
For convenience, all organizations on SAP API Management come preconfigured with a set of OAuth 2.0
endpoints that implement the client credentials grant type. This topic explains how to protect an API using this
default configuration.
The client credentials grant type defines a procedure for issuing access tokens in exchange for app credentials.
These app credentials are the consumer key and secret pair that SAP API Management issues for each app that is
registered in an organization.
You can easily add OAuth verification to an API when you create a new API proxy.
1. Log in to your SAP API Management account.
2. Select APIs > API Proxies.
3. Choose + API Proxy.
4. Fill out the New API Proxy dialog.
5. Select the radio button next to Secure with OAuth v2.0 Access Tokens.
When you select this option, two policies will be attached to the newly created API proxy, one to verify access
tokens and another to strip the access token after it has been verified.
Note that the Publish API Product checkbox becomes selectable and is automatically selected. Check this if you
want to automatically generate a product when you build the new API proxy. The autogenerated product will be
created with an association to the new API proxy. If you have an existing product with which you want to associate
this new API, be sure to clear this checkbox so that you don't create an unnecessary product.
Each organization (even a free trial org) on SAP API Management is provisioned with an OAuth token endpoint.
The endpoint is preconfigured with policies in the API proxy called oauth. You can begin using the token endpoint
as soon as you create an account on SAP API Management.
Publish this URI to developers who need to obtain access tokens. App developers configure their apps to call this
endpoint, presenting their consumer key and secret pairs to obtain access tokens.
For example, if your organization name is "apimakers", the URL would be:
https://apimakers-test.<host:port>/oauth/client_credential/accesstoken
Tip
By default, out-of-the-box OAuth endpoints are only deployed in the test environment. Before they are
available in prod, you must explicitly deploy the API proxy called oauth to prod.
To participate in OAuth 2.0 flows on SAP API Management, client apps must be registered.
What is registration?
Registration allows SAP API Management (the authorization server) to uniquely identify your app. When you
register your app, you receive back two keys: a client ID and client secret. The app needs these keys when
negotiating for access tokens with the authorization server.
Quick steps
For development and testing, you can use one of the pre-registered developer apps to obtain keys.
This topic shows you how to obtain client credentials (also called developer keys) for development and testing
purposes using an out-of-the-box developer app and product. For production situations, the steps are similar,
however you would use your own developer apps, products, and other entities.
To participate in any OAuth 2.0 flow, all client apps must be registered with SAP API Management (the
authorization server). When you register your app, you will be assigned two keys: the Consumer ID and Consumer
Secret. The Consumer ID is a public key and Consumer Secret must never be made public. These client credential
keys allow SAP API Management to uniquely identify the client app.
Terminology: The IETF OAuth 2.0 specification refers to client credentials as the client identifier and client secret.
The SAP API Management management UI refers to them as the Consumer ID and the Consumer Secret. These
terms are synonymous.
Quick steps
These quick steps show you how to obtain developer keys for one of the out-of-the-box apps that are configured
when you created your SAP API Management organization. You can use these keys mainly for development and
testing:
1. Log in to your SAP API Management account.
2. Select Publish > Developer Apps to open the Developer Apps overview page.
3. Choose Weather App to open the Weather App overview page. Notice that the developer associated with the
app is Nicolai Tesla. This app and developer were provisioned by default when your organization was created.
All developer apps must have a developer associated with them.
4. In the Products section, next to the Premium Weather API product, choose Show to expose the Consumer ID
and Consumer Secret values.
Tip
It's important to be sure that the product associated with the keys is enabled for the same environment
where the API you are securing is deployed. If not, you will receive this error when the access token is
validated: Invalid API call as no apiproduct match found.
You can also obtain the consumer key and secret for an app by calling the management API. First, get the list of
apps in your organization by making the following API call:
$ curl https://<host:port>/v1/o/{org_name}/apps \
-u myname:mypass
You can retrieve an app's profile by making a simple GET call on the app ID:
$ curl https://<host:port>/v1/o/{org_name}/apps/{app_id} \
-u myname:mypass
For example:
$ curl https://<host:port>/v1/o/{org_name}/apps/da496fae-2a04-4a5c-b2d0-709278a6f9db \
-u myname:mypass
The API call returns the profile of the app you specified. For example, an app profile for weatherapp has the
following JSON representation:
{
"accessType" : "read",
"apiProducts" : [ ],
"appFamily" : "default",
"appId" : "da496fae-2a04-4a5c-b2d0-70928a6f9db",
"attributes" : [ ],
"callbackUrl" : "http://weatherapp.com",
"createdAt" : 1380290158713,
"createdBy" : "[email protected]",
"credentials" : [ {
"apiProducts" : [ {
As the authorization server, SAP API Management needs to have appropriate OAuth endpoints set up so that
clients can request authorization codes and access tokens. This topic offers a quick introduction to endpoints.
An OAuth endpoint is a URL that is exposed by SAP API Management in your organization. OAuth defines token
endpoints, authorization endpoints, and refresh endpoints. Apps call these endpoints to get access tokens, to
refresh access tokens, and, in some cases, to get authorization codes. These endpoints refer to specific OAuth
2.0 policies that execute when the endpoint is called.
Here's an example. In this flow, the GenerateAccessToken policy is executed when the proxy path
matches /token.
<Flow name="generate-access-token">
<Description/>
Here's an example API call to the /token endpoint on SAP API Management.
$ curl -i -H 'ContentType: x-www-form-urlencoded' -X POST 'https://docs-
test.<host:port>/oauth/token' -d 'grant_type=client_credentials' -H 'Authorization:
Basic c3FIOG9vSGV4VHo4QzAySVg5T1JvNnJoZ3ExaVNyQWw6WjRsanRKZG5lQk9qUE1BVQ'
The quickest way to see how endpoints are set up is to examine the default "oauth" proxy. This proxy is installed
for you when you create a new SAP API Management organization. It sets up OAuth endpoints that support the
client credentials grant type. Let's take a look.
You'll see in this view the policies and flows that are configured to support this OAuth grant type flow.
The default oauth proxy is only supports the client credentials grant type, and is mainly provisioned to support
examples. For your OAuth 2.0 implementation, it's a common practice to create your own OAuth endpoint proxy
where you define your specific set of conditional flows and attach OAuthV2 policies.
The OAuth proxy that you create does not make any backend calls. Instead, the OAuth proxy acts as a standalone
service. Once you have set up the conditional flows and attached the policies, app developers can call the URLs
exposed by your API proxy to get access tokens, refresh access tokens, and, in the case of the authorization code
grant type, authorization codes.
In this topic, we show you how to request access tokens and authorization codes, configure OAuth 2.0 endpoints,
and configure policies for each supported grant type.
Note
These examples show the most basic configurations possible. In particular, the OAuthV2 policy includes
many optional configurable elements that are not shown in this topic.
This section explains how to request an access token using the authorization code grant type flow. For an
introduction to OAuth 2.0 grant types, see Introduction to OAuth 2.0.
Sample request
$ curl -i -H 'ContentType: x-www-form-urlencoded' -X POST 'https://docs-
test.<host:port>/oauth/accesstoken' -d
'code=I9dMGHAN&grant_type=authorization_code&redirect_uri=http://example-callback.com'
-H 'Authorization: Basic
c3FIOG9vSGV4VHo4QzAyg5T1JvNnJoZ3ExaVNyQWw6WjRsanRKZG5lQk9qUE1BVQ'
Required parameters
By default, these parameters must be x-www-form-urlencoded and specified in the request body (as shown in
the sample above); however, it is possible to change this default by configuring the <GrantType>, <Code>,
and <RedirectUri> elements in the OAuthV2 policy that is attached to this /accesstoken endpoint.
Optional parameters
• state - A string that will be sent back with the response. Typically used to prevent cross-site request forgery
attacks.
• scope - Allows you to filter the list of API products with which the minted token can be used.
Authentication
You must pass the Client ID and Client Secret either as a Basic Authentication header (Base64-encoded) or as
form parameters client_id andclient_secret. You obtain these values from a registered developer app.
Sample endpoint
Here's a sample endpoint configuration for generating an access token. It'll execute the GenerateAccessToken
policy, which must be configured to support the authorization_code grant type.
...
<Flow name="generate-access-token">
<Description/>
<Request>
<Step>
<FaultRules/>
<Name>GenerateAccessToken</Name>
</Step>
</Request>
<Response/>
<Condition>(proxy.pathsuffix MatchesPath "/token") and
(request.verb = "POST")</Condition>
</Flow>
...
Sample policy
This is a basic GenerateAccessToken policy that is configured to accept the authorization_code grant type.
Returns
With <GenerateResponse> enabled, the policy returns a JSON response that includes the access token, as
shown below. Note that theauthorization_code grant type supports minting both access and refresh tokens. For
example:
{
"issued_at": "1420262924658",
"scope": "READ",
"application_name": "ce1e94a2-9c3e-42fa-a2c6-1ee01815476b",
"refresh_token_issued_at": "1420262924658",
"status": "approved",
"refresh_token_status": "approved",
"api_product_list": "[PremiumWeatherAPI]",
"expires_in": "1799",
"developer.email": "[email protected]",
"organization_id": "0",
"token_type": "BearerToken",
"refresh_token": "fYACGW7OCPtCNDEnRSnqFlEgogboFPMm",
"client_id": "5jUAdGv9pBouF0wOH5keAVI35GBtx3dT",
"access_token": "2l4IQtZXbn5WBJdL6EF7uenOWRsi",
"organization_name": "docs",
"refresh_token_expires_in": "0",
"refresh_count": "0"
}
If <GenerateResponse> is set to false, the policy does not return a response. Instead, it populates the following
set of flow variables with data pertaining to the access token grant.
oauthv2accesstoken.{policy-name}.access_token
oauthv2accesstoken.{policy-name}.expires_in
oauthv2accesstoken.{policy-name}.refresh_token
oauthv2accesstoken.{policy-name}.refresh_token_expires_in
oauthv2accesstoken.{policy-name}.refresh_token_issued_at
For example:
oauthv2accesstoken.GenerateAccessToken.access_token
oauthv2accesstoken.GenerateAccessToken.expires_in
oauthv2accesstoken.GenerateAccessToken.refresh_token
oauthv2accesstoken.GenerateAccessToken.refresh_token_expires_in
oauthv2accesstoken.GenerateAccessToken.refresh_token_issued_at
oauthv2accesstoken.GenerateAccessToken.refresh_token_status
This section explains how to request an access token using the client credentials grant type flow.
Sample request
$ curl -i -H 'ContentType: x-www-form-urlencoded' -X POST 'https://docs-
test.<host:port>/oauth/accesstoken' -d 'grant_type=client_credentials' -H
'Authorization: Basic c3FIOG9vSGV4VHoAyg5T1JvNnJoZ3ExaVNyQWw6WjRsanRKZG5lQk9qUE1BVQ'
Required parameters
By default, the required grant_type parameter must be x-www-form-urlencoded and specified in the request body
(as shown in the sample above); however, it is possible to change this default by configuring
the <GrantType> element in the OAuthV2 policy that is attached to this /accesstokenendpoint. For example, you
could elect to pass the parameter in a query parameter.
• grant_type - Must be set to the value client_credentials.
Optional parameters
• state - A string that will be sent back with the response. Typically used to prevent cross-site request forgery
attacks.
• scope - Allows you to filter the list of API products with which the minted token can be used.
Authentication
You must pass the Client ID and Client Secret either as a Basic Authentication header (Base64-encoded) or as
form parameters client_id andclient_secret. You obtain these values from the registered developer app
associated with the request.
Sample endpoint
Here's a sample endpoint configuration for generating an access token. It'll execute the GenerateAccessToken
policy, which must be configured to support the client_credentials grant type.
Sample policy
This is a basic GenerateAccessToken policy that is configured to accept the client_credentials grant type.
<OAuthV2 async="false" continueOnError="false" enabled="true"
name="GenerateAccessToken">
<DisplayName>GenerateAccessToken</DisplayName>
<Operation>GenerateAccessToken</Operation>
<SupportedGrantTypes>
<GrantType>client_credentials</GrantType>
</SupportedGrantTypes>
<GenerateResponse enabled="true"/>
</OAuthV2>
Returns
With <GenerateResponse> enabled, the policy returns a JSON response. Note that with
the client_credentials grant type, refresh tokens are not supported. Only an access token is minted. For example:
{
"issued_at": "1420260525643",
"application_name": "ce1e94a2-9c3e-42fa-a2c6-1ee01815476b",
"scope": "READ",
"status": "approved",
"api_product_list": "[PremiumWeatherAPI]",
"expires_in": "1799",
"developer.email": "[email protected]",
"organization_id": "0",
"token_type": "BearerToken",
"client_id": "5jUAdGv9pBouF0wOH5keAVI35GBtx3dT",
"access_token": "XkhU2DFnMGIVL2hvsRHLM00hRWav",
If <GenerateResponse> is set to false, the policy does not return a response. Instead, it populates the following
set of flow variables with data pertaining to the access token grant.
oauthv2accesstoken.{policy-name}.access_token
oauthv2accesstoken.{policy-name}.expires_in
For example:
oauthv2accesstoken.GenerateAccessToken.access_token
oauthv2accesstoken.GenerateAccessToken.expires_in
This section explains how to request an access token using the resource owner password credentials (password)
grant type flow.
Sample request
$ curl -i -H 'ContentType: x-www-form-urlencoded' -X POST 'https://docs-
test.<host:port>/oauth/token -d 'grant_type=password&username=the-user-
name&password=the-users-password' -H 'Authorization: Basic
c3FIOG9vSGV4VHo4QzAySVg5T1JvNnJoZ3ExaVNyQWw6WjRsanRKZG5lQk9qUE1BVQ'
Required parameters
By default, these parameters must be x-www-form-urlencoded and specified in the request body (as shown in the
sample above); however, it is possible to change this default by configuring the <GrantType>, <Username>,
and <Password> elements in the OAuthV2 policy that is attached to this /token endpoint.
User credentials are typically validated against a credential store using an LDAP or JavaScript policy.
• grant_type - Must be set to the value password.
• username - The resource owner's user name.
• password - The resource owner's password.
Authentication
You must pass the Client ID and Client Secret either as a Basic Authentication header (Base64-encoded) or as
form parameters client_id andclient_secret. You obtain these values from the registered developer app
associated with the request.
Sample endpoint
Here's a sample endpoint configuration for generating an access token. It'll execute the GenerateAccessToken
policy, which must be configured to support the password grant type.
...
<Flow name="generate-access-token">
<Description/>
<Request>
<Step>
<FaultRules/>
<Name>GenerateAccessToken</Name>
</Step>
</Request>
<Response/>
<Condition>(proxy.pathsuffix MatchesPath "/token") and
(request.verb = "POST")</Condition>
</Flow>
...
Sample policy
This is a basic GenerateAccessToken policy that is configured to accept the password grant type.
Returns
With <GenerateResponse> enabled, the policy returns a JSON response. Note that with the password grant type,
both an access token and refresh token are minted. For example:
{
"issued_at": "1420258685042",
"scope": "READ",
"application_name": "ce1e94a2-9c3e-42fa-a2c6-1ee01815476b",
"refresh_token_issued_at": "1420258685042",
"status": "approved",
"refresh_token_status": "approved",
"api_product_list": "[PremiumWeatherAPI]",
"expires_in": "1799",
"developer.email": "[email protected]",
"organization_id": "0",
"token_type": "BearerToken",
"refresh_token": "IFl7jlijYuexu6XVSSjLMJq8SVXGOAAq",
"client_id": "5jUAdGv9pBouF0wOH5keAVI35GBtx3dT",
"access_token": "I6daIgMSiUgYX1K2qgQWPi37ztS6",
"organization_name": "docs",
"refresh_token_expires_in": "0",
"refresh_count": "0"
}
If <GenerateResponse> is set to false, the policy does not return a response. Instead, it populates the following
set of flow variables with data pertaining to the access token grant.
oauthv2accesstoken.{policy-name}.access_token
oauthv2accesstoken.{policy-name}.expires_in
oauthv2accesstoken.{policy-name}.refresh_token
oauthv2accesstoken.{policy-name}.refresh_token_expires_in
oauthv2accesstoken.{policy-name}.refresh_token_issued_at
oauthv2accesstoken.{policy-name}.refresh_token_status
For example:
oauthv2accesstoken.GenerateAccessToken.access_token
oauthv2accesstoken.GenerateAccessToken.expires_in
oauthv2accesstoken.GenerateAccessToken.refresh_token
This section explains how to request an access token using the implicit grant type flow.
Sample request
curl -X POST -H 'ContentType: x-www-form-urlencoded' 'https://docs-
test.<host:port>/oauth/implicit?response_type=token&client_id=ABC123&redirect_uri=http
://callback-example.com'
Required parameters
By default, these parameters must be query parameters (as shown in the sample above); however, it is possible to
change this default by configuring the <ResponseType>, <ClientId>, and <Redirect_Uri> elements in the OAuthV2
policy that is attached to this /token endpoint.
User credentials are typically validated against a credential store using an LDAP service callout or JavaScript
policy.
• response_type - Must be set to the value token.
• client_id - The client ID of a registered developer app.
• redirect_uri - This parameter is mandatory if a Callback URI was not provided when the client developer app
was registered. If a Callback URL was provided at client registration, it will be compared to this value and must
match exactly.
Optional parameters
• state - A string that will be sent back with the response. Typically used to prevent cross-site request forgery
attacks.
• scope - Allows you to filter the list of API products with which the minted token can be used.
Authentication
You must pass the Client ID and Client Secret either as a Basic Authentication header (Base64-encoded) or as
form parameters client_id and client_secret. You obtain these values from the registered developer app
associated with the request.
Sample policy
This is a basic GenerateAccessTokenImplicitGrant policy that processes token requests for the implicit grant type
flow.
Returns
With <GenerateResponse> enabled, the policy returns a 302 Location redirect in the response header. The
redirect points to the URL specified in theredirect_uri parameter and is appended with the access token and token
expiration time. Note that the implicit grant type does not support refresh tokens. For example:
https://callback-example.com#expires_in=1799&access_token=In4dKm4ueoGZRbIYJhC9yZCmTFw5
If <GenerateResponse> is set to false, the policy does not return a response. Instead, it populates the following
set of flow variables with data pertaining to the access token grant.
oauthv2accesstoken.{policy-name}.access_token
oauthv2accesstoken.{policy-name}.expires_in
Sample request
curl -X POST -H 'ContentType: x-www-form-urlencoded' 'http://myorg-
test.<host:port>/oauth/authorize?client_id={consumer_key}&response_type=code'
where an OAuthV2 GenerateAuthorizationCode policy is attached at the /oauth/authorize proxy endpoint (see
the sample endpoint below).
Required parameters
By default, these parameters must be query parameters (as shown in the sample above); however, it is possible to
change this default by configuring the <ResponseType>, <ClientId>, and <Redirect_Uri> elements in the OAuthV2
policy that is attached to this /authorize endpoint.
• response_type - Must be set to the value code.
• client_id - The client ID of a registered developer app.
Optional parameters
• redirect_uri - If a full (not partial) Callback URI is specified in the registered client app, this parameter is
optional; otherwise, it is required. The callback is the URL where SAP API Management sends the newly
minted auth code.
• state - A string that will be sent back with the response. Typically used to prevent cross-site request forgery
attacks.
• scope - Allows you to filter the list of API products with which the minted token can be used.
Authentication
Does not require basic authentication, however the client ID of the registered client app must be supplied in the
request.
Sample endpoint
Here's a sample endpoint configuration for generating an authorization code:
...
<Flow name="generate-auth-code">
<Description/>
<Request>
<Step>
<FaultRules/>
<Name>GenerateAuthorizationCode</Name>
Sample policy
This is a basic GenerateAuthorizationCode policy.
Returns
With <GenerateResponse> enabled, the policy returns ?code query parameter to the redirect_uri (Callback URI)
location with the authorization code attached. It is sent via a 302 browser redirect with the URL in the Location
header of the response. For example: ?code=123456.
If <GenerateResponse> is set to false, the policy does not return a response. Instead, it populates the following
set of flow variables with data pertaining to the authorization code.
oauthv2authcode.{policy-name}.code
oauthv2authcode.{policy-name}.scope
oauthv2authcode.{policy-name}.redirect_uri
oauthv2authcode.{policy-name}.client_id
For example:
oauthv2authcode.GenerateAuthorizationCode.code
oauthv2authcode.GenerateAuthorizationCode.scope
oauthv2authcode.GenerateAuthorizationCode.redirect_uri
oauthv2authcode.GenerateAuthorizationCode.client_id
A refresh token is a credential you use to obtain an access token, typically after the access token has expired or
becomes invalid. A refresh token is returned in the response when you receive an access token.
To request a new access token using a refresh token:
Sample request
curl -X POST 'https://myorg-test.<host:port>/my_oauth_endpoint/refresh_accesstoken' -d
'grant_type=refresh_token&refresh_token=my-refresh-token' -H "Content-type:
application/x-www-form-urlencoded"
Required parameters
By default, these parameters must be x-www-form-urlencoded and specified in the request body (as shown in the
example above); however, it is possible to change this default for the grant type by configuring
the <GrantType> element in the OAuthV2 policy that is attached to this/accesstoken endpoint.
User credentials are typically validated against a credential store using an LDAP or JavaScript policy.
• grant_type - Must be set to the value refresh_token.
• refresh_token - The refresh token associated with the access token you wish to renew.
Optional parameters
• state - A string that will be sent back with the response. Typically used to prevent cross-site request forgery
attacks.
• scope - Allows you to filter the list of API products with which the minted token can be used.
Authentication
You must pass the Client ID and Client Secret either as a Basic Authentication header (Base64-encoded) or as
form parameters client_id andclient_secret.
Here's a sample endpoint configuration for generating an access token using a refresh token. It'll execute the
RefreshAccessToken policy.
...
<Flow name="generate-refresh-token">
<Description/>
<Request>
<Step>
<FaultRules/>
<Name>RefreshAccessToken</Name>
</Step>
</Request>
<Response/>
<Condition>(proxy.pathsuffix MatchesPath "/refresh") and
(request.verb = "POST")</Condition>
</Flow>
Sample policy
This is a basic RefreshAccessToken policy that is configured to accept the refresh_token grant type.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<OAuthV2 async="false" continueOnError="false" enabled="true"
name="RefreshAccessToken">
<DisplayName>RefreshAccessToken</DisplayName>
<ExternalAuthorization>false</ExternalAuthorization>
<Operation>RefreshAccessToken</Operation>
<GenerateResponse enabled="true"/>
</OAuthV2>
Returns
With <GenerateResponse> enabled, the policy returns a JSON response containing the new access token. Note
that the refresh_accesstokengrant type supports minting both access and new refresh tokens. For example:
{
"issued_at": "1420301470489",
"application_name": "ce1e94a2-9c3e-42fa-a2c6-1ee01815476b",
"scope": "READ",
"refresh_token_issued_at": "1420301470489",
"status": "approved",
"refresh_token_status": "approved",
"api_product_list": "[PremiumWeatherAPI]",
"expires_in": "1799",
"developer.email": "[email protected]",
"token_type": "BearerToken",
"refresh_token": "8fKDHLryAD9KFBsrpixlq3qPJnG2fdZ5",
"client_id": "5jUAdGv9pBouF0wOH5keAVI35GBtx3dT",
"old_access_token_life_time": "285832",
"access_token": "jmZ2Hqv3iNsABUtAAsfWR3QGNctw",
"organization_name": "docs",
"refresh_token_expires_in": "0",
"refresh_count": "2"
}
If <GenerateResponse> is set to false, the policy does not return a response. Instead, it populates the following
set of flow variables with data pertaining to the access token grant.
oauthv2accesstoken.{policy-name}.access_token
oauthv2accesstoken.{policy-name}.expires_in
oauthv2accesstoken.{policy-name}.refresh_token
For example:
oauthv2accesstoken.GenerateAccessToken.access_token
oauthv2accesstoken.GenerateAccessToken.expires_in
oauthv2accesstoken.GenerateAccessToken.refresh_token
oauthv2accesstoken.GenerateAccessToken.refresh_token_expires_in
oauthv2accesstoken.GenerateAccessToken.refresh_token_issued_at
oauthv2accesstoken.GenerateAccessToken.refresh_token_status
When you make an API call to request a token or auth code, it's a good practice to pass the client_id and
client_secret values as a base64 URL encoded string in the Authorization header. To do this, you need to use a
base64 encoding tool or utility to encode the two values together with colon separating them.
For example:
result = aBase64EncodeFunction(ns4fQc14Zg4hKFCNaSzArVuwszX95X:ZIjFyTsNgQNyxI)
SAP API Management generates and distributes OAuth access tokens, refresh tokens, and authorization codes to
apps. SAP API Management stores those tokens and codes and uses them to authorize consumer apps.
When it generates these OAuth artifacts, it also generates a profile that contains metadata related to the token or
code. For example, the default access token profile contains name/value pairs that define expiration time, the
associated app and developer, and so on.
The JSON representation of an SAP API Management access token looks like the following:
{
"issued_at" : "1372170159093",
"application_name" : "ccd1803b-b557-4520-bd62-ddd3abf8e501",
"scope" : "READ",
"status" : "approved",
"api_product_list" : "[FreeProduct]",
"expires_in" : "3599",
"developer.email" : "[email protected]",
"organization_id" : "0",
"refresh_token" : "82XMXgDyHTpFyXOaApj8C2AGIPnN2IZe",
"client_id" : "deAVedE0W9Z9U35PAMaAJYphBJCGdrND",
"access_token" : "shTUmeI1geSKin0TODcGLXBNe9vp",
"organization_name" : "apifactory",
"refresh_count" : "0"
}
Sometimes its useful to add custom attributes to an access token. For example, you might wish to embed a
department name, a customer ID, or, more technically, a session identifier. You can also get and set these custom
attributes at runtime using policies (as explained below).
You can configure custom token attributes directly in the OAuthV2 policy that generates the tokens or auth
codes.
<Attributes>
Where display is set to true, custom attributes are returned in the response, where they may be viewable by the
app end user.
Where display is set to false, custom attributes are stored in the data store, but are not returned in the response
message.
For example, to add the User-Agent associated with the request to an access token:
<OAuthV2 name="GenerateAccessToken">
<Operation>GenerateAccessToken
</Operation>
<ExpiresIn>1000</ExpiresIn>
<GenerateResponse />
<SupportedGrantTypes>
<GrantType>client_credentials</GrantType>
</SupportedGrantTypes>
<GrantType>request.queryparam.grant_type</GrantType>
<Attributes>
<Attribute name="user-agent" ref="request.header.user-agent"
display="false"></Attribute>
</Attributes>
</OAuthV2>
In some situations, you will need to update the profile of an access token at runtime while an API call is being
processed on SAP API Management. To help with this, SAP API Management provides policies for getting and
setting token attributes. Use these policies when you need tokens to be updated at runtime, such as at the time
when the token or code is generated by it.
The AccessToken element value is set to the name of the variable where the access token can be located: either in
the request message, or in some other variable where it might be populated by an ExtractVariables policy.
You can also use SAP API Management APIs to manage a token's profile.
In some cases, apps are required to explicitly revoke or invalidate tokens, for example, when a user logs out of an
OAuth-enabled app. If you revoke a token, it can be re-approved anytime before it expires.
You can also revoke/approve client IDs associated with products and developer apps.
The procedure for token revocation is defined by the OAuth 2.0 Token Revocation specification.
SAP API Management provides an InvalidateToken operation that enables you to configure a dedicated token
revocation endpoint. By publishing the URI of this endpoint, you enable app developers to invalidate tokens issued
by it.
Token expiration is independent of the state of the token (approved or revoked). If a refresh token has expired,
you cannot use it to refresh an access token.
Here's an example configuration for the OAuthV2 policy and the InvalidateToken operation. In this case, both the
access token and its associated refresh token are revoked. Technically, they are both revoked because the
cascade flag is set to true. For more information about how the cascade flag works, see the Token element's
attributes section below.
<OAuthV2 name="InvalidateToken">
<Operation>InvalidateToken</Operation>
<Tokens>
<Token type="accesstoken" cascade="true">flow.variable</Token>
</Tokens>
</OAuthV2>
<Tokens>/<Token> element
Identifies the flow variable that specifies the token to be revoked. If developers are expected to submit a
revocation request using a query parameter named access_token, for example, the correct flow variable will
be: request.queryparam.access_token. To require the token in an HTTP header, for example, set this value
to request.header.access_token.
• type (required, string): The token type identified by the variable specified. Supported values
are accesstoken and refreshtoken:
o To revoke an access token, specify type accesstoken.
o To revoke both the access and refresh tokens, specify type refreshtoken. When it sees type refreshtoken,
SAP API Management assumes the token is a refresh token. If that refresh token is found, then it is
revoked. If that refresh token is not found, then SAP API Management checks to see if it is an access
token. If the access token exists, then it is revoked.
Note: If you pass an already invalidated token to an InvalidateToken policy, the policy doesn't return an
error, although you might expect it to. Such an operation has no effect.
• cascade (optional, boolean, default: true) The primary use of this attribute is to revoke a refresh token
without revoking its associated access token. Consider these cases:
o Revoke a refresh token only and do not revoke its associated access token. To do this, set the <Token>
type to refreshtoken and set cascade to false.
o Revoke both the access token and the refresh token. To do this, set the <Token> type to accesstoken.
The value of cascade can be eithertrue (the default) or false. If you set it to true, then both the access
token and the refresh token are revoked. If you set it to false, the access token is revoked, and the refresh
token is unusable. See the Note below for more explanation.
o Revoke an access token and do not revoke its associated refresh token. Not supported. See the Note
below for more explanation.
Note: For security reasons, it is not possible to use a refresh token to refresh an access token that has been
revoked. A refresh token can only be used to refresh an access token that has expired. Therefore, you cannot use
the cascade attribute to revoke only an access token. For example, if you set the <Token> type to accesstoken,
and set cascade=false, the access token is revoked (as expected); however, the associated refresh token is
unusable. It cannot be used to refresh the revoked access token. The primary use case for the cascade attribute is
when you want to only revoke a refresh token. In that case, set the <Token> type to refreshtoken, and
set cascade=false. The refresh token will be revoked, but it's associated access token will remain valid (until it
expires or is revoked).
Use the ValidateToken operation to "re-approve" a revoked token. That is, when you apply this operation, the
status of the targeted access or refresh token is changed from 'revoked' to 'approved'. You can validate any
revoked token that has not already expired.
<OAuthV2 name="ValidateToken">
<Operation>ValidateToken</Operation>
<Tokens>
<Token type="refreshtoken" cascade="true">flow.variable</Token>
</Tokens>
</OAuthV2>
Attributes
• type (required, string) The token type identified by the variable specified. Supported values
are accesstoken and refreshtoken.
This section describes how to enable retrieval and revocation of OAuth 2.0 access tokens by end user ID, app ID,
or both.
App IDs are automatically added to an OAuth access token. Therefore, after you enable token access for an
organization as described below, you can access tokens by app ID.
To retrieve and revoke OAuth 2.0 access tokens by end user ID, an end user ID must be present in the access
tokens. The procedure below describes how add an end user ID to an existing token.
By default, when SAP API Management generates an OAuth 2.0 access token, the token has the format shown
below:
{
"issued_at" : "1421847736581",
"application_name" : "a68d01f8-b15c-4be3-b800-ceae8c456f5a",
"scope" : "READ",
"status" : "approved",
"api_product_list" : "[PremiumWeatherAPI]",
"expires_in" : "3599",
"developer.email" : "[email protected]",
"organization_id" : "0",
"token_type" : "BearerToken",
"client_id" : "k3nJyFJIA3p62DWOkLO6OJNi87GYXFmP",
"access_token" : "7S22UqXGJDTuUADGzJzjXzXSaGJL",
There is no field for end user ID in the default OAuth access token. To enable retrieval and revocation of OAuth 2.0
access tokens by end user ID, you have to configure the OAuth 2.0 policy to include the user ID in the token, as
described in the procedure below. Note that if you only want to retrieve and revoke OAuth 2.0 access tokens by
app ID, then there is no need to enable access by end user ID.
The end user ID is the string that SAP API Management uses as the developer ID, not the developer's email
address. You can determine the developer's ID from the developer's email address by using Get Developer. After
you configure SAP API Management to include the end user ID in the token, it is included as the app_enduserfield,
as shown below:
{
"issued_at" : "1421847736581",
"application_name" : "a68d01f8-b15c-4be3-b800-ceae8c456f5a",
"scope" : "READ",
"app_enduser" : "6ZG094fgnjNf02EK",
"status" : "approved",
"api_product_list" : "[PremiumWeatherAPI]",
"expires_in" : "3599",
"developer.email" : "[email protected]",
"organization_id" : "0",
"token_type" : "BearerToken",
"client_id" : "k3nJyFJIA3p62DWOkLO6OJNi87GYXFmP",
"access_token" : "7S22UqXGJDTuUADGzJzjXzXSaGJL",
"organization_name" : "myorg",
"refresh_token_expires_in" : "0",
"refresh_count" : "0"
}
This topic explains how to use the UI and APIs to revoke or approve API keys for products in developer apps and
for developer apps.
Note
If you need to revoke an access token, you can do that directly by calling a properly configured OAuthV2
endpoint.
You can revoke the key associated with a specific API product through the management UI. The effect is that the
API resources defined in that API product will no longer be accessible unless the key is re-approved.
1. Log in to your SAP API Management account.
2. From the main menu, select Publish > Developer apps.
3. From the list of apps, select the one that contains the key you wish to revoke.
4. In the Developer app page, choose Edit.
5. In the Products section, choose Revoke to revoke the key for the product you wish to revoke.
Tip: You can use the Get Developer App Details API to get the JSON representation of a developer app to discover
the approval status of products in that app. In the following JSON representation of a developer app, you can see
where the API Product called "Weather-Product" has been revoked:
{
"accessType": "",
"appFamily": "default",
"appId": "6ed3a4d1-4733-439a-80a4-0d71149ec9ad",
"attributes": [
{
"name": "DisplayName",
"value": "AnotherTestApp"
},
{
You can approve a previously revoked consumer key for an API product in a developer app through the
management UI. The client app will once again be able to access the APIs in that product.
1. Log in to your SAP API Management account.
SAP API Management provides APIs that let you manage API key status, depending on your use case. In the
developer app JSON below, the location of each approve/revoke flag is indicated for each of these three cases:
(1) Revoking/approving keys for specific API products in a developer app. This API does exactly what the UI
operations described previously in this topic do
(2) Revoking/approving specific key for a developer app. Revoking the key renders it unusable for the app to use it
to access an API. Any access tokens associated with a revoked app key will remain active, but SAP API
Management checks the status of the app key first. If the status is set to "revoked," SAP API Management will not
allow the call go through.
(3) Revoke/approve the API key status of an entire developer app. A revoked app cannot access any API products
and cannot invoke any API managed by SAP API Management.
{
"accessType": "",
"appFamily": "default",
"appId": "6ed3a4d1-4733-439a-80a4-0d71149ec9ad",
"attributes": [
{
"name": "DisplayName",
"value": "AnotherTestApp"
},
{
"name": "Notes",
"value": ""
}
],
"callbackUrl": "",
"createdAt": 1415728893126,
"createdBy": "[email protected]",
"credentials": [
{
"apiProducts": [
As an app developer, you need to include an access token in any request to SAP API Management for a protected
resource (an API that is protected with a VerifyAccessToken policy). Note that access tokens are also called
"bearer tokens."
When you put a VerifyAccessToken policy at the front of your API proxy flow, apps must present a valid access
token (also called a "bearer token") to consume your API. To do this, the app sends the access token in the
request as an "Authorization" HTTP header.
For example:
$ curl -H "Authorization: Bearer ylSkZIjbdWybfs4fUQe9BqP0LH5Z" http://{org-name}-
{env}.<host:port>/weather/forecastrss?w=12797282
When you call an API proxy on SAP API Management that has OAuth security, it is responsible for validating
access tokens. Think of it as the gatekeeper -- no API call can pass through that does not have a valid access
token.
To configure token validation, place an OAuthV2 policy with the VerifyAccessToken operation at the very
beginning of the API proxy flow (the beginning of the ProxyEndpoint Preflow). If placed there, access tokens will
be verified before any other processing takes place, and if a token is rejected, SAP API Management stops
processing and returns an error back to the client.
1. Log in to your SAP API Management account.
2. From the main menu, select APIs > API Proxies.
3. From the list, select the proxy you wish to protect.
4. In the overview page, choose DEVELOP.
5. From the New Policy menu, select OAuth v2.0.
6. Fill out the policy form. Be sure the Attach Policy is checked, the flow is PreFlow, Proxy Endpoint default,
and the segment is Request.
7. Choose Add.
The default policy is already configured with the VerifyAccessToken operation, so you do not have to do anything
further:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<OAuthV2 async="false" continueOnError="false" enabled="true" name="OAuth-v20-1">
<DisplayName>OAuth v2.0 1</DisplayName>
<FaultRules/>
<Properties/>
<Attributes/>
<ExternalAuthorization>false</ExternalAuthorization>
<Operation>VerifyAccessToken</Operation>
<SupportedGrantTypes/>
<GenerateResponse enabled="true"/>
<Tokens/>
</OAuthV2>
This topic discusses how to use OAuth 2.0 scopes on SAP API Management.
What is scope?
OAuth 2.0 scopes provide a way to limit the amount of access that is granted to an access token. For example, an
access token issued to a client app may be granted READ and WRITE access to protected resources, or just READ
access. You can implement your APIs to enforce any scope or combination of scopes you wish. So, if a client
receives a token that has READ scope, and it tries to call an API endpoint that requires WRITE access, the call will
fail.
In this topic, we'll discuss how scopes are assigned to access tokens and how SAP API Management enforces
OAuth 2.0 scopes. After reading this topic, you'll be able to use scopes with confidence.
When SAP API Management generates an access token, it may assign a scope to that token. To understand how
this happens, you must first be familiar with these SAP API Management entities: API products, developers, and
developer apps. We recommend that you review this material if you need to before continuing.
An access token is a long string of random-looking characters that allows it to verify incoming API requests (think
of it as a stand-in for typical username/password credentials). Technically, the token is a key that refers to a
collection of metadata that that looks like this:
{
"issued_at" : "1416962591727",
"application_name" : "0d3e1d41-a59f-4d74-957e-d4e3275d4781",
"scope" : "A",
"status" : "approved",
"api_product_list" : "[scopecheck1-bs0cSuqS9y]",
"expires_in" : "1799",
"developer.email" : "[email protected]",
"organization_id" : "0",
"token_type" : "BearerToken",
"client_id" : "eTtB7w5lvk3DnOZNGReBlvGvIAeAywun",
The token's metadata includes the actual access token string, expiry information, identification of the developer
app, developer, and products associated with the token. You'll also notice that the metadata also includes
"scope".
You can name your scopes anything you wish. In simple cases, it is fine to use simple names like READ, WRITE, or
DELETE. In more complex scenarios where there are multiple API products, each with multiple resources which
each support multiple distinct actions, a WRITE on one resource is not equivalent to a WRITE on another resource.
In these cases, it's a best practice to assign each scope a unique name, in the form of an URN. Examples of URNs
include: https://www.examplecompany.com/private_catalog.readonly andurn:examplecompany:product_price:u
pdate.
Learn more about URNs in RFC3986.
When you create a developer app and add products to it, SAP API Management looks at all of the products in the
developer app and creates a list of all of the scopes for those products (the app's master or global scope list -- a
union of all recognized scopes).
Note
There is a case where the master list is overridden. It is possible to create a developer app using the SAP
API Management API. Using the API, you can specify OAuth scopes for the app. App-specific scopes
override the master list of scopes taken from the products that are included in the app. Note that the SAP
API Management UI does not let you specify app-specific scopes. It is only possible if you use the API to
create an app.
When a client app requests an access token from SAP API Management, it can optionally specify which scopes it
would like to have associated with that token. For example, the following request asks for the scope "A". That is,
the client is asking that the authorization server (SAP API Management) generate an access token that has scope
"A" (giving the app authorization to call APIs that have scope "A"). The app sends a POST request like this:
curl -i -X POST -H Authorization: Basic Mg12YTk2UkEIyIBCrtro1QpIG -H content-
type:application/x-www-form-urlencoded http://myorg-
test.<host:port>/oauth/token?grant_type=client_credentials&scope=A
Note
If the value of the scope parameter matches none of the recognized scopes, then a token is still
generated; however, that token will not be granted any scopes (it's scope metadata will be empty).
What if the client does not attach a scope parameter? In this case, SAP API Management generates a token that
includes all of the scopes recognized by the developer app. It's important to understand that the default behavior
is to return an access token that contains the union of all scopes for all of the products included in the developer
app.
Let's say a developer app recognizes these scopes: A B C D. This is the app's master list of scopes. It could be that
one product in the app has scope A and B, and a second one has scope C and D, or any combination. If the client
does not specify a scope parameter (or if it specifies scope parameter with no value) the token will be granted all
four scopes: A, B, C, and D. Again, the token receives a set of scopes that is the union of all the scopes recognized
by the developer app.
There is one more case where the default behavior is to return an access token with all of the recognized scopes,
and that is when the GenerateAccessToken policy (the SAP API Management policy that generates access
tokens) does not specify a <Scope> element. For example, here's a GenerateAccessToken policy
where <Scope> is specified. If that <Scope> element is missing (or if it is present but empty), then the default
behavior is executed.
First, remember that on SAP API Management, access tokens are validated with the OAuthV2 policy (typically
placed at the very beginning of a proxy flow). The policy must have the VerifyAccessToken operation specified.
Let's look at this policy:
Note the <Scope> element. It is used to specify which scopes the policy will accept.
Note
If more than one scope is specified (for example, <Scope>A B C</Scope>), then the policy will succeed if
the access token includes any one of those scopes (like a logical 'OR' evaluation). If you want to enforce
an 'AND' type of operation, where multiple scopes on a token are enforced, you can do that by creating
multiple VeryifyAccessToken policies, each with a single distinct scope.
In this example, the policy will succeed only if the access token includes scope "A". If this <Scope> element is
omitted or if it has no value, then the policy ignores the scope of the access token.
Now, with the ability to validate access tokens based on scope, you can design your APIs to enforce specific
scopes. You do this by designing custom flows with scope-aware VerifyAccessToken policies attached to them.
Let's say your API has a flow defined for the endpoint /resourceA:
<Flow name="resourceA">
<Condition>(proxy.pathsuffix MatchesPath "/resourceA") and (request.verb =
"GET")</Condition>
<Description>Get a resource A</Description>
<Request>
When this flow is triggered (a request comes in with /resourceA in the path suffix), the OAuthV2-
VerifyAccessTokenA policy is called immediately. This policy verifies that the access token is valid and it looks to
see what scope(s) the token supports. If the policy is configured as the example below, with <Scope>A</Scope>,
the policy will only succeed if the access token has scope "A". Otherwise, it will return an error.
To summarize, API developers are responsible for designing scope enforcement into their APIs. They do this by
creating custom flows to handle specific scopes, and attaching VerifyAccessToken policies to enforce those
scopes.
Code examples
Finally, let's take a look at some example API calls to help illustrate how tokens receive scopes and how scopes are
enforced.
Default case
Let's say you have a developer app with products, and that the union of those products' scopes are: A, B, and C.
This API call requests an access token, but does not specify a scope query parameter.
curl -X POST -H content-type:application/x-www-form-urlencoded http://wwitman-
test.<host:port>/scopecheck1/token?grant_type=client_credentials
Now, let's say you have an API endpoint that has scope "A" (that is, it's VerifyAccessToken requires scope "A").
Here's the VerifyAccessToken policy:
<OAuthV2 async="false" continueOnError="false" enabled="true" name="OAuthV2-
VerifyAccessTokenA">
<DisplayName>Verify OAuth v2.0 Access Token</DisplayName>
<ExternalAuthorization>false</ExternalAuthorization>
<Operation>VerifyAccessToken</Operation>
<Scope>A</Scope>
<GenerateResponse enabled="true"/>
</OAuthV2>
It succeeds because the VerifyAccessToken policy that is triggered when the endpoint is called requires scope A,
and the access token was granted scopes A, B, and C -- the default behavior.
In this case, the generated token will be given scopes A and X, because both A and X are a valid scopes.
Remember that the developer app recognizes scopes A, B, C, and X. In this case, you're filtering the list of API
products based on these scopes. If a product has scope A or X, you can configure API endpoints that will enforce
these scopes. If a product does not have scope A or X (let's say it has B,C, and Z), then the APIs that enforce
scopes A or X cannot be called with the token.
The GET call triggers succeeds and it returns a response. For example:
{
"hello" : "Tue, 25 Nov 2014 01:35:53 UTC"
}
It succeeds because the VerifyAccessToken policy requires scope A or X, and the access token includes scope A
and X. Of course, if the <Scope>element were set to "B", this call would fail.
Summary
• It's important to understand how SAP API Management handles OAuth 2.0 scopes. Here are key takeaway
points:
• A developer app "recognizes" the union of all scopes defined for all of its products.
• When an app requests an access token, it has the chance to specify which scopes it would like to have. It's up
to SAP API Management (the authorization server) to figure out which scopes it will actually assign to the
In this topic, we'll discuss how to use externally generated access and refresh tokens and authorization codes in
SAP API Management.
A common use case is where you have an existing OAuth system in place, and you would like to use the tokens
generated by that system with SAP API Management. On the other hand, if you want to take advantage of SAP API
management features like SAP API Management Analytics, the developer app ecosystem, developer portal, and
so on, you need to use tokens that were generated with SAP API Management's OAuth system. This topic explains
how to configure SAP API Management to work with third-party (non-SAP API Management) OAuth systems.
To use tokens from third-party OAuth systems in SAP API Management, you need to do these things:
• Configure the OAuthV2 policy that generates tokens with the <ExternalAuthorization> element set to true. If
this element is false or not present, then SAP API Management validates the client_id and client_secret
normally against the SAP API Management authorization store.
• Set the internal flow variable oauth_external_authorization_status to true. If this value is false (or if the
variable is not present), SAP API management assumes that the third-party authorization failed and returns
an error message.
Typically, this variable is set to true or false based on a service callout to a third-party authorization service. You
can look at the service callout response and set the variable accordingly. Take a look at the ServiceCallout
policy for details. Another technique for setting this variable is to use an AssignMessage policy with the
AssignVariable element, like this:
<AssignMessage name="AssignMessage-SetVariable">
<DisplayName>Assign Message - Set Variable</DisplayName>
Note
Setting these elements is a common option when using <ExternalAuthorization>; however, you can also
use these elements independently. For example, you can leave <ExternalAuthorization> as false (the
default) so that the client_id and client_secret values are validated against SAP API Management, but still
use an external access token from another system.
• Set the <StoreToken> element in OAuthV2 to true. If this is false, then the token will not be persisted.
For example, here we will mint an SAP API Management access token given that another valid token (from a third-
party or legacy system) is provided in the query parameter request.queryparam.external_access_token.
<OAuthV2 name="OAuth-v20-Store-External-Token">
<DisplayName>OAuth v2.0 1</DisplayName>
<Attributes/>
<ExternalAccessToken>request.queryparam.external_access_token</ExternalAccessToken>
<ExternalAuthorization>true</ExternalAuthorization>
<Operation>GenerateAccessToken</Operation>
<GenerateResponse enabled="true">
<Format>FORM_PARAM</Format>
</GenerateResponse>
<ReuseRefreshToken>false</ReuseRefreshToken>
<StoreToken>true</StoreToken>
<SupportedGrantTypes>
<GrantType>client_credentials</GrantType>
</SupportedGrantTypes>
<Tokens/>
</OAuthV2>
curl https://testmyapi-test.<host:port>/oauth-
delegated/generatetoken?external_access_token=123456 \
-d 'client_id=sxnS7SddD6494Akbqk74ej4SmvvqjL0O&grant_type=client_credentials'
In this case, SAP API Management will generate an access token, with an access token of 123456. The token
metadata might look something like this. Notice the access_token property is 123456. And, as you can see, this
token is wired up with SAP API Management-specific properties that will enable it to work with developers,
developer apps, and products registered on SAP API Management.
{
"issued_at" : "1415467907287",
"application_name" : "9d3f4de-e501-4836-9bdd-f55e1d4b923",
"scope" : "WRITE",
"status" : "approved",
"api_product_list" : "[PremiumWeatherAPI]",
"expires_in" : "1799",
"developer.email" : "[email protected]",
"organization_id" : "0",
"token_type" : "BearerToken",
"client_id" : "sxnS7Sdd6494Akb74ej4SmvvqjL0O",
"access_token" : "123456"
"organization_name" : "testmyapi",
"refresh_token_expires_in" : "0",
"refresh_count" : "0"
}
For a final example, you might call an API like this, with 123456 as the bearer token:
curl
'https://docs-test.<host:port>/oauth-
delegated/music?func=getSong&artist=radiohead&fmt=json'
-H 'Authorization:Bearer 123456'
In theory, you could apply this pattern with any third-party OAuth 2 authorization service, like Google or Twitter.
When using the authorization code grant type, you must specify a callback URL when you register your developer
app. The callback URL typically specifies the URL of an app that is designated to receive an authorization code on
behalf of the client app. In addition, this URL string is used for validation. The client is required to send this URL to
SAP API management when requesting authorization codes and access tokens, and the redirect_uri parameter
must match the one that is registered. See also Requesting access tokens and authorization codes.
For example:
http://myorg-
test.<host:port>/weather/oauth/authorizationcode?client_id=123456&response_type=code&r
edirect_uri=http://example.com/callbacak&scope=scope1%20scope2&state=abc
There is a use case for specifying multiple callback URLs in a single proxy application. For example, you may want
to authenticate for multiple domains. For instance:
• http://myexample.com/callback
• http://myexample.uk/callback
• http://myexample.ja/callback
SAP API Management does not support specifying multiple callback URLs or using wildcard characters when a
developer app is registered. To accomplish this use case, you can specify an empty callback URL when you
register a developer app, and then put a logic in a JavaScript policy to validate incoming redirect URIs.
You may be required to verify that an app end user authorized an app. You can use the SAP API Management
Audit API to do so.
OAuthV2 policy
OAuthV2 is a multi-faceted policy for performing OAuth 2.0 grant type operations. This is the primary policy used
to configure OAuth 2.0 endpoints on SAP API Management.
Samples
VerifyAccessToken
This OAuthV2 policy configuration (with the VerifyAccessToken operation) verifies that an access token
submitted to SAP API Management is valid. When this policy operation is triggered, it looks for a valid access
token in the request. If the access token is valid, the request is allowed to proceed. If invalid, all processing stops
and an error is returned in the response.
<OAuthV2 async="false" continueOnError="false" enabled="true" name="OAuth-v20-2">
<DisplayName>OAuth v2.0 2</DisplayName>
<Operation>VerifyAccessToken</Operation>
<AccessTokenPrefix>Bearer</AccessTokenPrefix> <!-- Optional, default is Bearer -->
</OAuthV2>
Note that only bearer (access) tokens are supported. MAC tokens are not supported.
Apps must pass the access token in the Authorization HTTP request header. For example:
$ curl -H "Authorization: Bearer ylSkZIjbdWybfsUQe9BqP0LH5Z" http://{org-name}-
{env}.<host:port>/weather/forecastrss?w=12797282
Element reference
The policy reference describes the elements and attributes of the OAuthV2 policy.
The way you configure this policy, and the elements you need to specify, depend on which operation you want the
policy to perform. For example, if you are implementing the authorization code grant type, then you will require
four separate OAuthV2 policies to perform authorization code generation, access code generation, access code
validation, and refresh token generation. This reference lists all of the elements that can be used with this policy.
The sample policy shown below is one of many possible configurations. This sample shows an OAuthV2 policy
configured for the GenerateAccessToken operation. It includes required and optional elements. Refer to the
element descriptions in this section for details.
<OAuthV2 name="GenerateAccessToken">
Element reference
The policy reference describes the elements and attributes of the OAuthV2 policy.
The way you configure this policy, and the elements you need to specify, depend on which operation you want the
policy to perform. For example, if you are implementing the authorization code grant type, then you will require
four separate OAuthV2 policies to perform authorization code generation, access code generation, access code
validation, and refresh token generation. This reference lists all of the elements that can be used with this policy.
The sample policy shown below is one of many possible configurations. This sample shows an OAuthV2 policy
configured for the GenerateAccessToken operation. It includes required and optional elements. Refer to the
element descriptions in this section for details.
<OAuthV2 name="GenerateAccessToken">
<Operation>GenerateAccessToken</Operation>
<ExpiresIn>1000</ExpiresIn>
<GenerateResponse />
<SupportedGrantTypes>
<GrantType>authorization_code</GrantType>
</SupportedGrantTypes>
Element reference
The policy reference describes the elements and attributes of the OAuthV2 policy.
The way you configure this policy, and the elements you need to specify, depend on which operation you want the
policy to perform. For example, if you are implementing the authorization code grant type, then you will require
four separate OAuthV2 policies to perform authorization code generation, access code generation, access code
validation, and refresh token generation. This reference lists all of the elements that can be used with this policy.
The sample policy shown below is one of many possible configurations. This sample shows an OAuthV2 policy
configured for the GenerateAccessToken operation. It includes required and optional elements. Refer to the
element descriptions in this section for details.
<OAuthV2 name="GenerateAccessToken">
<Operation>GenerateAccessToken</Operation>
<ExpiresIn>1000</ExpiresIn>
<GenerateResponse />
<SupportedGrantTypes>
<GrantType>authorization_code</GrantType>
</SupportedGrantTypes>
<GrantType>request.queryparam.grant_type</GrantType>
<Code>request.queryparam.code</Code>
<ClientId>request.queryparam.client_id</ClientId>
<RedirectUri>request.queryparam.redirect_uri</RedirectUri>
<Scope>request.queryparam.scope</Scope>
</OAuthV2>
<OAuthV2> attributes
name The internal name of the policy. Characters you can use in the N/A Required
name are restricted to: A-Z0-9._\-$ %. However, the SAP API
Management UI enforces additional restrictions, such as
automatically removing characters that are not alphanumeric.
Optionally, use the <DisplayName> element to label the policy in
the management UI proxy editor with a different, natural-
language name.
continueOnError Set to false to return an error when a policy fails. This is false Optional
expected behavior for most policies.
Set to true to have flow execution continue even after a policy
fails.
async Note: This attribute does not make the policy execute false Optional
asynchronously.
When set to true, policy execution is offloaded to a different
thread, leaving the main thread free to handle additional
requests. When the offline processing is complete, the main
thread comes back and finishes handling the message flow. In
some cases, setting async to true improves API proxy
performance. However, overusing async can hurt performance
with too much thread switching.
To use asynchronous behavior in API proxies, see JavaScript
callouts.
<DisplayName> element
Use in addition to the name attribute to label the policy in the management UI proxy editor with a different,
natural-language name.
Presence: Optional
Type: String
<AccessToken> element
<AccessToken>request.header.access_token</AccessToken>
By default, VerifyAccessToken expects the access token to be sent in an Authorization header. You can change
that default using this element. For example request.queryparam.access_token indicates that the access token
should be present as a query parameter.
If presented in the header, it must be an Authorization header and be sent as a Bearer token. For example:
-H "Authorization: Bearer Rft3dqrs56Blirls56a"
Currently, Bearer is the only supported prefix.
Default: request.header.access_token
Presence: Optional
Type: String
<AccessTokenPrefix> element
<AccessTokenPrefix>Bearer</AccessTokenPrefix>
By default, VerifyAccessToken expects the access token to be sent in an Authorization header as a Bearer token.
For example:
Default: Bearer
Presence: Optional
Type: String
<AppEndUser> element
<AppEndUser>request.queryparam.app_enduser</AppEndUser>
In cases where the app end user ID must be sent to the authorization server, this element lets you specify where
SAP API Management should look for the end user ID. For example, it could be sent as a query parameter or in an
HTTP header.
For example request.queryparam.app_enduser indicates that the AppEndUser should be present as a query
parameter, as, for example, [email protected]. To require the AppEndUser in an HTTP header,
for example, set this value to request.header.app_enduser.
Providing this setting enables you to include an app end user ID in the access token. This feature is useful if you
want to be able to retrieve or revoke OAuth 2.0 access tokens by end user ID.
Default: N/A
Presence: Optional
Type: String
<Attributes/Attribute>
<Attributes>
<Attribute name=”attr_name1” ref=”flow.variable”
display="true|false">value1</Attribute>
<Attribute name=”attr_name2” ref=”flow.variable”
display="true|false">value2</Attribute>
</Attributes>
Use this element to add custom attributes to an access token or authorization code. For example, you may wish to
embed a user ID or session identifier in an access token that can be extracted and checked at runtime.
This element takes a value from a flow variable or a default value which is specified in the policy. If both are
specified, the value specified in the flow variable is taken. The optional display attribute can be set to true to false.
If set to true, the attribute will not be shown in the response. Default value is false.
Default: N/A
Presence: Optional
<ClientId>request.queryparam.client_id</ClientId>
In several cases, the client app must send the client ID to the authorization server. This element lets you specify
where SAP API Management should look for the client ID. For example, it could be sent as a query parameter or in
an HTTP header.
The variable request.queryparam.client_id indicates that the client_id should be present as a query parameter, as,
for example, ?client_id=AfGlvs9. To require the ClientId in an HTTP header, for example, set this value
to request.header.client_id.
Presence: Optional
Type: String
<Code> element
<Code>request.queryparam.code</Code>
In the authorization grant type flow, the client must submit an authorization code to the authorization server (SAP
API Management). This element lets you specify where SAP API Management should look for the authorization
code. For example, it could be sent as a query parameter, HTTP header, or form parameter (the default).
The variable, request.queryparam.auth_code indicates that the authorization code should be present as a query
parameter, as, for example, ?auth_code=AfGlvs9. To require the authorization code in an HTTP header, for
example, set this value to request.header.auth_code.
Presence: optional
Type: String
<ExpiresIn>10000</ExpiresIn>
Enforces the expiry time of access tokens, refresh tokens, and authorization codes in milliseconds. The expiry
time value is a system generated value plus the <ExpiresIn> value. If <ExpiresIn> is set to -1, the token or code is
given an infinite lifetime. If <ExpiresIn> is not specified, the system applies a default value configured at the
system level.
The expiry time can also be set at runtime using a reference to a flow variable. The flow variable can be retrieved
from a header, query parameter, or form parameter (default). Or, it can be a hard-coded value.
For example request.queryparam.expires_in indicates that the expiry value should be present as a query
parameter, as, for example, ?expires_in=360000. To require the value to come from an HTTP header, for
example, set this value to request.header.expires_in.
The following stanza specifies a flow variable and a default value as well. Note that the flow variable value takes
precedence over the specified default value.
<ExpiresIn ref="flow.variable">
{default_value}
</ExpiresIn>
Default: If not specified, the system applies a default value configured at the system level.
Presence: Optional
Type: Integer
<ExternalAccessToken>request.queryparam.external_access_token</ExternalAccessToken>
Tells SAP API Management where to find an external access token (an access token not generated by SAP API
Management).
The variable request.queryparam.external_access_token indicates that the external access token should be
present as a query parameter, as, for example, ?external_access_token=12345678. To require the external
access token in an HTTP header, for example, set this value to request.header.external_access_token.
<ExternalAuthorization> element
<ExternalAuthorization>true</ExternalAuthorization>
If this element is false or not present, then SAP API Management validates the client_id and client_secret normally
against the SAP API Management authorization store. Use this element when you want to work with third-party
OAuth tokens.
Default: false
Presence: Optional
Type: Boolean
<GenerateResponse> element
<GenerateResponse enabled='true'/>
Default: false
Presence: Optional
Type: string
<GenerateErrorResponse> element
<GenerateErrorResponse enabled='true'/>
If set to true, the policy generates and returns a response if the ContinueOnError attribute is set to true.
If false (the default), no response is sent. Instead, a set of flow variables are populated with values related to the
policy's function.
Default: false
Presence: Optional
Type: string
<GrantType>
<GrantType>request.queryparam.grant_type</GrantType>
Tells the policy where to find the grant type parameter that is passed in a request. Per the OAuth 2.0 specification,
the grant type must be supplied with requests for access tokens and authorization codes. The variable can be a
header, query parameter, or form parameter (default). Or, it can be a hard-coded value.
For example request.queryparam.grant_type indicates that the Password should be present as a query
parameter, as, for example, ?grant_type=password. To require the grant type in an HTTP header, for example, set
this value to request.header.grant_type.
Presence: Optional
Type: string
Valid values: A variable, as explained above, or a hard-coded grant type of: client_credentials, implicit,
authorization_code, or password
<Operation>GenerateAuthorizationCode</Operation>
Default: If <Operation> is not specified, SAP API Management looks at the list
of <SupportedGrantTypes>. Only operations on those grant types will be successful. In other
words, you can omit <Operation> if you specify a <GrantType> in
the <SupportedGrantTypes> list. If neither <Operation> nor <SupportedGrantTypes> are
specified, the default grant type is authorization_code. That is, authorization_code grant type
requests will succeed, but all others will fail.
Presence: Optional
Type: String
<PassWord> element
<PassWord>request.queryparam.password</PassWord>
In cases where the app user's password must be sent to the authorization server, this element lets you specify
where SAP API Management should look for the password. For example, it could be sent as a query parameter, in
an HTTP header, or a form parameter (default).
For example request.queryparam.password indicates that the password should be present as a query parameter,
as, for example, ?password=changeit. To require the password in an HTTP header, for example, set this value
to request.header.password.
Presence: Optional
Type: String
<RedirectUri> element
<RedirectUri>request.queryparam.redirect_uri</RedirectUri>
Specifies where SAP API Management should look for the redirect_uri parameter in the request.
• (required) If a Callback URL is registered with the developer app that is associated with the request's client
keys, and if the request_uri is present in the request, then the two must match exactly. If they do not match,
an error is returned.
• (optional) If a Callback URL is registered, and the request_uri is missing from the request, then SAP API
Management redirects to the registered Callback URL.
• (required) If a Callback URL is not registered, then the request_uri is required. Note that in this case, SAP API
Management will accept ANY URL. This case can present a security issue, and therefore should only be used
with trusted client apps. If client apps are not trusted, then the best practice is to always require the
registration of a Callback URL.
You can send this parameter in a query parameter or in a header. The
variable request.queryparam.redirect_uri indicates that the RedirectUri should be present as a query parameter,
as, for example, ?redirect_uri=login.myapp.com. To require the RedirectUri in an HTTP header, for example, set
this value to request.header.redirect_uri.
Presence: Optional
Type: String
<RefreshToken> element
<RefreshToken>request.queryparam.refreshtoken</RefreshToken>
When requesting an access token using a refresh token, you must supply the refresh token in the request. This
element lets you specify where SAP API Management should look for the refresh token. For example, it could be
sent as a query parameter, HTTP header, or form parameter (the default).
The variable request.queryparam.refreshtoken indicates that the refresh token should be present as a query
parameter, as, for example, ?refresh_token=login.myapp.com. To require the RedirectUri in an HTTP header, for
example, set this value to request.header.refresh_token.
Presence: Optional
Type: String
<RefreshTokenExpiresIn> element
<RefreshTokenExpiresIn>1000</RefreshTokenExpiresIn>
Enforces the expiry time of refresh tokens in milliseconds. The expiry time value is a system generated value plus
the <RefreshTokenExpiresIn>value. If <RefreshTokenExpiresIn> is set to -1, the refresh token is given an infinite
lifetime. If <RefreshTokenExpiresIn> is not specified, the system applies a default value configured at the system
level.
The expiry time can also be set at runtime using a reference to a flow variable. The flow variable can be retrieved
from a header, query parameter, or form parameter (default). Or, it can be a hard-coded value.
For example request.queryparam.expires_in indicates that the expiry value should be present as a query
parameter, as, for example, ?expires_in=360000. To require the value to come from an HTTP header, for
example, set this value to request.header.expires_in.
The following stanza specifies a flow variable and a default value as well. Note that the flow variable value takes
precedence over the specified default value.
<RefreshTokenExpiresIn ref="flow.variable">
{default_value}
</RefreshTokenExpiresIn>
Default: If not specified, the system applies a default value configured at the system level.
Presence: Optional
Type: Integer
<ResponseType> element
<ResponseType>request.queryparam.response_type</ResponseType>
This element informs SAP API Management which grant type the client app is requesting. It is used only with the
authorization code and implicit grant type flows.
By default, SAP API Management looks for the response type value in a response_type query parameter. If you
wish to override this default behavior, use the <ResponseType> element to configure a flow variable containing
the response type value. For example, if you set this element to request.header.response_type, SAP API
Management looks for the response type to be passed in the request header.
Presence: Optional. Use this element if you wish to override the default behavior.
Type: String
Valid Either code (for the authorization code grant type) or token (for the implicit grant type)
values:
<ReuseRefreshToken> element
<ReuseRefreshToken>true</ReuseRefreshToken>
When set to true, the existing refresh token is reused until it expires. If false, a new refresh token is issued by SAP
API Management when a valid refresh token is presented.
Presence: optional
Type: boolean
<Scope> element
<Scope>request.queryparam.scope</Scope>
If this element appears in a "VerifyAccessToken" policy, then it is used to specify which scopes the policy should
enforce. In this type of policy, the value must be a "hard coded" scope name -- you can't use variables. For
example:
<Scope>A B</Scope>
Default: No scope
Presence: Optional
Type: String
<State> element
<State>request.queryparam.state</State>
In cases where the client app must send the state information to the authorization server, this element lets you
specify where SAP API Mangement should look for the state values. For example, it could be sent as a query
parameter or in an HTTP header. The state value is typically used as a security measure to prevent CSRF attacks.
For example request.queryparam.state indicates that the state should be present as a query parameter, as, for
example, ?state=HjoiuKJH32. To require the state in an HTTP header, for example, set this value
to request.header.state.
Default: No state
Presence: Optional
Type: String
<StoreToken> element
<StoreToken>true</StoreToken>
Default: false
Presence: Optional
Type: Boolean
<SupportedGrantTypes>/<GrantType> element
<SupportedGrantTypes>
<GrantType>authorization_code</GrantType>
<GrantType>client_credentials</GrantType>
<GrantType>implicit</GrantType>
<GrantType>password</GrantType>
</SupportedGrantTypes>
Specifies the grant types supported by an OAuth token endpoint on SAP API Management. An endpoint may
support multiple grant types (that is, a single endpoint can be configured to distribute access tokens for multiple
grant types.) For more on endpoints, see Understanding OAuth endpoints. The grant type is passed in token
requests in a grant_type parameter.
If no supported grant types are specified, then the only allowed grant types are authorization_code and implicit.
See also the <GrantType>element (which is a higher-level element that is used to specify where SAP API
Management should look for the grant_type parameter that is passed in a client request. SAP API Management
will make sure that the value of the grant_type parameter matches one of the supported grant types).
Type: String
<Tokens>/<Token> element
The <Token> element identifies the flow variable that defines the source of the token to be revoked. If developers
are expected to submit access tokens as query parameters named access_token, for example,
use request.queryparam.access_token.
<UserName> element
<UserName>request.queryparam.user_name</UserName>
In cases where the app user name must be sent to the authorization server, this element lets you specify where
SAP API Management should look for the end user name. For example, it could be sent as a query parameter or in
an HTTP header.
For example request.queryparam.username indicates that the username should be present as a query parameter,
as, for example, ?username=joe. To require the UserName in an HTTP header, for example, set this value
to request.header.username.
Presence: Optional
Type: String
Once a token endpoint is set up for an API proxy, a corresponding OAuthV2 policy that specifies
the VerifyAccessToken operation is attached to the Flow that exposes the protected resource.
For example, to ensure that all requests to an API are authorized, the following policy enforces access token
verification:
<OAuthV2 name="VerifyOAuthAccessToken">
<Operation>VerifyAccessToken</Operation>
</OAuthV2>
The policy is attached to the API resource to be protected. To ensure that all requests to an API are verified,
attach the policy to the ProxyEndpoint request PreFlow, as follows:
<PreFlow>
<Request>
<Step><Name>VerifyOAuthAccessToken</Name></Step>
</Request>
</PreFlow>
The following optional elements can be used to override the default settings for the VerifyAccessToken operation.
Name Description
Scope A space-delimited list of scopes. Verification will succeed if at least one of the scopes listed is
present in the access token. For example, the following policy will check the access token to
ensure that it contains at least one of the scopes listed. If READ or WRITE is present,
verification will succeed.
<OAuthV2 name="ValidateOauthScopePolicy">
<Operation>VerifyAccessToken</Operation>
<Scope>READ WRITE</Scope>
</OAuthV2>
AccessToken The variable where the access token is expected to be located. For
examplerequest.queryparam.accesstoken. By default, the access token is expected to be
presented by the app in the Authorization HTTP header, according to the OAuth 2.0
specification. Use this setting if the access token is expected to be presented in a non-
standard location, such as a query parameter, or an HTTP header with a name other than
Authorization.
For each grant type, the policy makes assumptions about the location or required information in request
messages. These assumptions are based on the the OAuth 2.0 specification. If your apps need to deviate from the
OAuth 2.0 specification, then you can specify the expected locations for each parameter. For example, when
handling an authorization code, you can specify the location of the authorization code, the client ID, the redirect
URI, and the scope. These can be specified as HTTP headers, query parameters, or form parameters.
The example below demonstrates how you can specify the location of required authorization code parameters as
HTTP headers:
...
<GrantType>request.header.grant_type</GrantType>
<Code>request.header.code</Code>
<ClientId>request.header.client_id</ClientId>
<RedirectUri>request.header.redirect_uri</RedirectUri>
<Scope>request.header.scope</Scope>
...
Or, if necessary to support your client app base, you can mix and match headers and query parameters:
...
<GrantType>request.header.grant_type</GrantType>
<Code>request.header.code</Code>
<ClientId>request.queryparam.client_id</ClientId>
<RedirectUri>request.queryparam.redirect_uri</RedirectUri>
<Scope>request.queryparam.scope</Scope>
...
The flow variables defined in this table are populated when the respective OAuth policies are executed, and hence
are available to other policies or applications executing in the API proxy flow.
VerifyAccessToken operation
These variables are set when the VerifyAccessToken policy operation executes.
API product variables will be populated automatically if the API products are configured with valid environment,
proxies, and API resources (derived from the proxy.pathsuffix). Explicitly setting flow.resource.name variable is
not required.
Where the API products are not configured with valid environments and API proxies, then flow.resource.name
must explicitly be set to populate API product variables in the flow.
Variables Description
developer.id The ID of the developer associated with the registered client app.
developer.app.name The name of the developer associated with the registered client
app.
scope The scope (if any) associated with the access token.
apiproduct.<custom_attribute_name> A named custom attribute of the API product associated with the
registered client app.
apiproduct.name The name of the API product associated with the registered client
app.
App-specific variables
app.name
app.id
app.accessType
app.callbackUrl
app.status
app.scopes
app.appFamily
app.apiproducts
app.appParentStatus
app.appType
app.appParentId
app.created_at
app.last_modified_at
app.last_modified_by
app.{custom_attributes}
developer.id
developer.userName
developer.firstName
developer.lastName
developer.email
developer.status
developer.apps
developer.created_by
developer.created_at
developer.last_modified_at
developer.last_modified_by
company.id
company.displayName
company.apps
company.appOwnerStatus
company.created_by
company.created_at
company.last_modified_at
company.last_modified_by
company.{custom_attributes}
These variables are set when the GenerateAuthorizationCode policy operation executes successfully:
Variable Description
oauthv2authcode.{policy_name}.redirect_uri The redirect URI associated with the registered client app.
GenerateAccessToken
These variables are set when the GenerateAccessToken policy operation executes successfully for the
authorization code, password, and client credentials grant type flows:
Variable Description
GenerateAccessTokenImplicitGrant
These variables are set when the GenerateAccessTokenImplicit policy operation executes successfully for the
implicit grant type flow:
Variable Description
RefreshAccessToken operation
These variables are set when the RefreshAccessToken policy operation executes successfully:
Variable Description
GenerateErrorResponse
Variable Description
Error codes
For OAuth-related HTTP error codes, see OAuth HTTP status code reference.
What
Gets attributes of access tokens, refresh tokens, and authorization codes and populates variables with the values
of those attributes. This policy type can be useful when you need to configure dynamic, conditional behavior
based on a value in a token or code. Whenever token validation occurs, variables are automatically populated with
the values of token attributes. However, in cases where token validation has not occured, you can use this feature
to explicity populate variables with the attribute values of a token.
Where
This policy can be attached in the following locations. See the Samples section below for specific attachment
guidance in different situations.
Samples
Access token
This example shows how to retrieve profile information for an access token and use it to populate a set of
variables. In this case, the policy expects to find the access token in a query parameter called access_token. Given
the access token, the policy looks up the token's profile and populates a set of variables with the profile data. The
variables will be prefixed with oauthv2accesstoken.
<GetOAuthV2Info name="GetTokenAttributes">
<AccessToken ref="request.queryparam.access_token"></AccessToken>
</GetOAuthV2Info>
You can then access the variables using JavaScript or another means. For example, to retrieve the scope(s)
associated with an access token using JavaScript:
For example:
<GetOAuthV2Info name="GetAuthCodeAttributes">
<AuthorizationCode ref="request.queryparam.code"></AuthorizationCode>
</GetOAuthV2Info>
Refresh token
<GetOAuthV2Info name="GetTokenAttributes">
<RefreshToken ref="{variable name}"/>
</GetOAuthV2Info>
For example:
<GetOAuthV2Info name="GetTokenAttributes">
<RefreshToken ref="request.queryparam.refresh_token"></RefreshToken>
</GetOAuthV2Info>
Static
In some rare cases you may need to get the profile of a statically configured token (one that is not accessible
through a variable). You can do this by providing the value of the access token as an element.
<GetOAuthV2Info name="GetTokenAttributes">
<AccessToken>shTUmeI1geSKin0TODcGLXBNe9vp</AccessToken>
</GetOAuthV2Info>
You can do this with all other token types (client ID, authorization code, and refresh tokens) as well.
The element reference describes the elements and attributes of the GetOAuthV2Info policy.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<GetOAuthV2Info async="false" continueOnError="false" enabled="true"
name="GetOAuthV2Info-1"
<DisplayName>Get OAuth v2.0 Info 1</DisplayName>
<AccessToken ref={some-variable}></AccessToken>
</GetOAuthV2Info
<GetOAuthV2Info> attributes
Name The internal name of the policy. Characters you can use in the NA Required
name are restricted to: A-Z0-9._\-$ %. However, the SAP API
Management management UI enforces additional restrictions,
such as automatically removing characters that are not
alphanumeric.
Optionally, use the <DisplayName> element to label the policy in
the management UI proxy editor with a different, natural-
language name.
continueOnError Set to false to return an error when a policy fails. This is False Optional
expected behavior for most policies.
Set to true to have flow execution continue even after a policy
fails.
async Note: This attribute does not make the policy execute False Optional
asynchronously.
When set to true, policy execution is offloaded to a different
thread, leaving the main thread free to handle additional
requests. When the offline processing is complete, the main
thread comes back and finishes handling the message flow. In
some cases, setting async to true improves API proxy
<DisplayName> element
Use in addition to the name attribute to label the policy in the management UI proxy editor with a different,
natural-language name.
<DisplayName>Policy Display Name</DisplayName>
Default: N/A
If you omit this element, the the value of the policy'sname attribute is
used.
Presence: Optional
Type: String
<AccessToken> element
Retrieves the profile for an access token. You pass in a either a variable that contains the access token string or a
literal token string (rare case). In this example, the access token is retrieved from a query parameter passed in a
request.
<AccessToken ref="request.queryparam.access_token"></AccessToken>
Presence: Optional
Type: String
Valid values: Either a flow variable containing an access token string, or a literal string.
Retrieves the profile for an authorization code. You pass in a either a variable that contains the auth code string or
a literal token string (rare case). In this example, the auth code is retrieved from a query parameter passed in a
request. For a list of variables populated by this operation, see "Flow variables".
<AuthorizationCode ref="request.queryparam.authorization_code"></AuthorizationCode>
Presence: Optional
Type: String
Valid values: Either a flow variable containing an auth code string, or a literal string.
<ClientId> element
Retrieves information related to a client ID. In this example, the client ID is retrieved from a query parameter
passed in a request. For a list of variables populated by this operation, see "Flow variables".
<ClientId>ref="request.queryparam.client_id"></ClientId>
Presence: Optional
Type: String
Valid values: Either a flow variable containing an auth code string, or a literal string.
Retrieves the profile for a refresh token. You pass in a either a variable that contains the refresh token string or a
literal token string (rare case). In this example, the refresh token is retrieved from a query parameter passed in a
request. For a list of variables populated by this operation, see "Flow variables".
<RefreshToken ref="request.queryparam.refresh_token"></RefreshToken>
Presence: Optional
Type: String
Valid values: Either a flow variable containing an refresh token string, or a literal string.
Flow variables
The GetOAuthV2Info policy populates these variables, and is typically used in cases where you need the profile
data, but where a grant or validation has not occurred yet. .
Client ID variables
Schema
What
Lets you add or update custom attributes associated with an access token, refresh token, or authorization code.
Custom attributes might include things like department name, a customer ID, or a session identifier.
You can only add or modify custom attributes. You cannot use this policy to change fields like scope, status,
expires_in, developer_email, client_id, org_name, or refresh_count. If an attribute already exists, this policy
updates it. If it does not exist, the policy adds it. The access token referenced must be valid and in an approved
state.
Where
This policy can be attached in the following locations.
Samples
Below is an example policy used to update an OAuth 2.0 access token. The example below locates the access
token on the request message by looking for a query parameter called access_token. When an access token is
presented by a client app, the policy below will locate the access token in the query parameter. It will then update
the access token's profile in two ways: it will added a custom property called department.id to the profile. It will
also modify the access token's scope property to the value READ, WRITE.
Note
If an attribute already exists in the access token profile, then it will be updated with the new value in the
policy. If an attribute does not exist, then the attribute will be added to the access token's profile.
Element Reference
The element reference describes the elements and attributes of the SetOAuthV2 policy.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<SetOAuthV2Info async="false" continueOnError="false" enabled="true"
name="SetOAuthV2Info-1">
<DisplayName>Set OAuth v2.0 Info 1</DisplayName>
<AccessToken ref={some-variable}></AccessToken>
<Attributes/>
</SetOAuthV2Info
<SetOAuthV2Info> attributes
name The internal name of the policy. Characters you can use in the N/A Required
name are restricted to: A-Z0-9._\-$ %. However, the SAP API
Management UI enforces additional restrictions, such as
automatically removing characters that are not alphanumeric.
continueOnError Set to false to return an error when a policy fails. This is false Optional
expected behavior for most policies.
Set to true to have flow execution continue even after a policy
fails.
async Note: This attribute does not make the policy execute false Optional
asynchronously.
When set to true, policy execution is offloaded to a different
thread, leaving the main thread free to handle additional
requests. When the offline processing is complete, the main
thread comes back and finishes handling the message flow. In
some cases, setting async to true improves API proxy
performance. However, overusing async can hurt performance
with too much thread switching.
To use asynchronous behavior in API proxies, see JavaScript
callouts.
DisplayName> element
Use in addition to the name attribute to label the policy in the management UI proxy editor with a different,
natural-language name.
<DisplayName>Policy Display Name</DisplayName>
Default: N/A
If you omit this element, the the value of the policy'sname attribute is
used.
Presence: Optional
Type: String
Identifies the variable where the access token is located. For example, if the access token is attached to request
message as a query parameter, specify request.queryparam.access_token. You can use any valid variable that
references the token. Or, could pass in the literal token string (rare case).
<AccessToken ref="request.queryparam.access_token"></AccessToken>
Default: N/A
Presence: Required
Type: String
Attributes
Attribute Description
<Attributes> element
A set of attributes in the access token profile that will be modified or augmented.
Default: N/A
Presence: Required
Type: N/A
<Attributes>/<Attribute> element
Default: N/A
Presence: Optional
Type: N/A
Attributes
Flow variables
What
OAuth v1.01 defines a standard protocol that enables app users to authorize apps to consume APIs on their
behalf, without requiring app users to disclose their passwords to the app in the process. SAP API Management
enables you to protect APIs in a way that ensures that an app uses has authorized the app to consume an API.
SAP API Management also provides policy-based functionality for configuring the endpoints that app developers
can use to obtain access tokens.
Where
This policy can be attached in the following locations, but see the notes following the table for specific guidance.
Usage notes
SAP API Management provides an OAuth v1.0a policy type that enables you to authorize apps with OAuth 1.0a.
The OAuthV1 policy type is responsible for generating request tokens, generating access tokens, and verifying
access tokens based on the OAuth 1.0a specification.
Once you have configured OAuth policies on your API, apps must obtain access tokens to consume them. To do
so, the app must exchange a request token for an access token. Rather than relying on a single password as the
master key for every app that accesses an API, OAuth uses this token to provide “delegated authentication”
between APIs and apps. The resource owner can issue access tokens with restricted scope and limited lifetime,
and revoke them independently.
On token requests, SAP API Management OAuth 1.0a only supports HMAC-SHA signature algorithm for
the oauth_signature_method header parameter, as described in the OAuth 1.0a specification.
The name attribute for this policy is restricted to these characters: A-Z0-9._\-$ %. However, the Management UI
enforces additional restrictions, such as automatically removing characters that are not alphanumeric.
A request token is used by a consumer app to obtain authorization from the app end user, and is then presented
to the 'token endpoint' to be exchanged for an access token. A request token is generated from a valid consumer
key. Here are examples of the simple and comprehensive forms for generating request tokens.
Simple form
<OAuthV1 name="OAuthV1-GenerateRequestToken-1">
<Operation>GenerateRequestToken</Operation>
</OAuthV1>
Comprehensive form
<OAuthV1 name="OAuthV1-GenerateRequestToken-1">
<Operation>GenerateRequestToken</Operation>
<URL ref="flow.variable">value</URL>
<GenerateResponse enabled="true">
<Format>FORM_PARAM | XML</Format>
</GenerateResponse>
<GenerateErrorResponse enabled="true">
<Format>FORM_PARAM | XML</Format>
<Realm>http://oauth.sap.com/oauth/1/</Realm>
</GenerateErrorResponse>
</OAuthV1>
The <URL> element allows proper OAuthV1 signature calculation when running behind Elastic Load Balancers
(ELBs). The ref attribute takes precedence when both the ref attribute and a text value are specified. If ref is not
provided, or if the flow variable given in ref is NULL, then the text value will be considered for generating the
signature. For example:
<URL ref="secretURL">https://example-test.<host:port>/oauth/access_token</URL>
On failure, a request returns the appropriate response status code with an error message.
Simple form
<OAuthV1 name="OAuthV1-GenerateAccessToken-1">
<Operation>GenerateAccessToken</Operation>
</OAuthV1>
Comprehensive form
<OAuthV1 name="OAuthV1-GenerateAccessToken-1">
<Operation>GenerateAccessToken</Operation>
<URL ref="flow.variable">{value}</URL>
<GenerateResponse enabled="true">
<Format>FORM_PARAM | XML</Format>
</GenerateResponse>
<GenerateErrorResponse enabled="true">
<Format>FORM_PARAM | XML</Format>
<Realm>http://oauth.sap.com/oauth/1/</Realm>
</GenerateErrorResponse>
</OAuthV1>
The <URL> element allows proper OAuthV1 signature calculation when running behind Elastic Load Balancers
(ELBs). The ref attribute takes precedence when both the ref attribute and a text value are specified. If ref is not
provided, or if the flow variable given in ref is NULL, then the text value will be considered for generating the
signature. For example:
On failure, a request returns the appropriate response status code with an error message.
The following policy associates a token verification code with a request token. To receive an access token, both a
verification code and a request token are required.
Note
To use this policy, a verification code must be generated as a separate step outside of SAP API
Management. The verifier value must be a unique, random string.
The verification code fits into the basic OAuth flow as follows: After an app user's credentials are authenticated by
a service provider, the service provider must inform the consumer app that the credentials were accepted,
implying that the request token can be exchanged for an access token. This is usually done via a 302 redirect.
Separately, the service provider must send a verification code to SAP API Management, and it internally
associates this verifier to the request token.
Later, when the app exchanges the request token for an access token, it must pass both the request token and the
verifier code. SAP API Management then checks that the verifier code is correct, ensuring that the user who
authenticated and granted access to the service is the same user who is asking the app to retrieve an access
token. For detailed information on this message flow, see the OAuth 1.0a specification.
Comprehensive form
<OAuthV1 name="OAuthV1-GenerateVerifier-1">
<Operation>GenerateVerifier</Operation>
<RequestToken ref="request.header.requesttoken"/>
<AppUserId ref="request.header.appuserid"/>
<VerifierCode ref="request.header.verifiercode"/>
<GenerateResponse enabled="true">
<Format>FORM_PARAM | XML</Format>
</GenerateResponse>
<Attributes>
<Attribute name="ver-attr1">ver-attr1</Attribute>
<Attribute name="ver-attr2" ref="request.header.ver-attr2"></Attribute>
<Attribute name="ver-attr3" display="false">ver-attr3</Attribute>
</Attributes>
4.3 TLS/SSL
TLS (Transport Layer Security, whose predecessor is SSL) is the standard security technology for establishing an
encrypted link between a web server and a web client, such as a browser or an app. An encrypted link ensures that
all data passing between the server and the client remains private. To use SSL, a client makes a secure request to
the server by using the encrypted https:// protocol, instead of the unencrypted http:// protocol.
SAP API Management supports one-way SSL and two-way SSL. One-way SSL enables the SSL client to verify the
identity of the SSL server. For example, an app running on an Android phone (client) can verify the identity of SAP
API Management APIs (server).
SAP API Management also supports a stronger form of authentication using two-way, or client, SSL. You typically
implement two-way SSL to enhance security end-to-end and protect your data from client attacks such as client
spoofing or man-in-the middle attacks. In two-way SSL, the client verifies the identity of the server followed by the
server verifying the identity of the client.
SSL terminology
You should be familiar with some important terms and concepts before configuring SSL:
Term Definition
SSL certificate A digital file that identifies an entity in an SSL transaction. A certificate, or cert,
can be used to identify the SSL server and SSL client, depending on the SSL
configuration.
Certificate chain Often you will not have a certificate signed by your CA's root private key. Instead,
you have your cert along with one or more intermediate certs that form a chain.
The last intermediate cert in the chain is typically signed by the CA's root private
key.
CertificateAuthority(CA) A trusted entity, such as Symantec or VeriSign, used to issue certs and to validate
the authenticity of a cert. One type of cert, called a self- signed cert, does not
require a CA.
Public key Used to encrypt data sent from an SSL client to an SSL server. The public key is
included in the cert. All SSL clients have a copy of the server's public key.
Private key Used on the SSL server to decrypt data. Only the SSL server has the private key -
it is not shared with SSL clients.
Keystore Contains the SSL certificate and private key used to identify the entity during SSL
handshaking.
Truststore Contains trusted certificates on an SSL client used to validate an SSL server's
certificate presented to the client.
Server Name Indication Allows multiple HTTPS targets to be served off the same IP address and port
(SNI) without requiring those targets to use the same certificate.
One-way SSL
The following figure shows SSL handshaking for one-way authentication between an SSL client and SSL server.
SAP API Management is the server hosting the SSL endpoint, where the SSL endpoint corresponds to an API
proxy deployed to a virtual host. The client is an app attempting to access the API proxy. In this scenario, SAP
API Management has the keystore containing the certificate and private key.
• SAP API Management as the SSL client
SAP API Management acts as the client that accesses a backend service. In this case, the backend service
corresponds to the server hosting an SSL endpoint. The backend server therefore has a keystore that
contains its certificate and private key.
Two-way SSL
The following figure shows the SSL handshaking for two-way SSL authentication between a client and server:
In two-way SSL:
• The client and server both have their own keystores. The client's keystore contains its cert and private key,
and the server's keystore contains its cert and private key.
• The client has a copy of the server's cert in its truststore. During SSL handshaking, the client compares the
cert in its truststore to the cert send from the server to verify the identity of the server.
• The server has a copy of the client's cert in its truststore. During SSL handshaking, the server compares the
cert in its truststore to the cert send from the client to verify the identity of the client.
• The SSL server presents its certificate to the SSL client to authenticate itself. The client then verifies the
identity of the server prior to sending its cert to the server.
In two-way SSL, SAP API Management can be either the server or the client:
• SAP API Management as the server
SAP API Management is the server hosting the SSL endpoint, where the SSL endpoint corresponds to an API
proxy. The client is an app attempting to access the API proxy. In this scenario, SAP API Management has a
keystore containing the certificate and private key, and a truststore containing the client's cert and CA chain.
• SAP API Management as the client
SAP API Management acts as a client that accesses a backend service. In this case, the backend service
corresponds to the server hosting the SSL endpoint. The backend server therefore has a keystore that
contains its certificate and private key.
SAP API Management must also define a keystore that contains the certificate needed to validate itself to the
backend service, and a truststore containing the cert from the backend server.
The important thing to remember is that SAP API Management is flexible enough to support two-way SSL
regardless of how you decide to configure it.
SAP API Managment supports the use of Server Name Indication (SNI) from system to target endpoints. Java 1.6
or 1.7 is required.
With SNI, which is an extension of TLS/SSL, multiple HTTPS targets can be served off the same IP address and
port without requiring those targets to use the same certificate.
No system-specific configuration is required. If your target environment is configured for SNI, SAP API
Management supports it.
If an TLS certificate expires, or if your system configuration changes such that the certificate is no longer valid,
then you need to update the certificate. The process of updating a certificate depends on your deployment of
Edge: cloud or on-premises.
Note:
• You cannot update an existing keystore to add a new certificate. You must create a new keystore when
updating a certificate.
• You can optionally choose to delete the existing keystore and then create a new one with the same name.
However, for the time from when the certificate expired until you create the new keystore, you cannot service
requests.
• If the keystore is used for two-way TLS between SAP API Management Edge and the backend service, and you
are using SAP API Management Edge, then after deleting and recreating the keystore with the same name,
you must restart the SAP API Management Edge Message Processors.
• If you configured the virtual host or the TargetEndpoint to use a reference to the keystore or truststore, you
can update the reference to point to a different keystore or truststore to update the TLS cert. That means
Cloud customers do not have to contact SAP API Management Support and Cloud customers do not need to
restart a Router or Message Processor. However, Cloud customers must contact SAP API Management
Support if they require an update to the virtual host.
Typically, you create a new keystore before the current certificate expires, and then update your virtual hosts or
target endpoints to use the new keystore so that you can continue to service requests without interruption due to
an expired certificate. You can then delete the old keystore after ensuring that the new keystore is working
correctly.
To check when a certificate is due to expire, go to the Admin > SSL Certificates menu in the SAP API
Management Edge UI. You can also configure that page to indicate if a certificate is due to expire in 10, 15, 30, or
90 days.
The way you update an TLS certificate in a keystore is based on your SAP API Management Edge deployment
type: cloud or Private Cloud.
7. Cloud deployment
For a cloud-based deployment of SAP API Management Edge:
1. Create a new keystore as described in KeyStores and TrustStores.
2. Upload a new JAR file containing the new certificate and private key to the keystore.
3. For inbound connections, meaning an API request into SAP API Management Edge, contact SAP Support to
update the virtual host configuration to reference the the new keystore and key alias.
4. For outbound connections, meaning from SAP API Management to a backend server:
1. Update the TargetEndpoint configuration for any API proxies that referenced the old keystore and key
alias to reference the new keystore and key alias.
If your TargetEndpoint references a TargetServer, update the TargetServer definition to reference the
new keystore and key alias.
2. If the keystore and truststore are referenced directly from the TargetEndpoint definition, then you must
redeploy the proxy.
If the TargetEndpoint references a TargetServer definition, and the TargetServer definition references the
keystore and truststore, then no proxy redeployment is necessary.
5. After you have confirmed that your new keystore is working correctly, delete the old keystore with the expired
cert and key as described above.
On-premises deployment
If the TargetEndpoint references a TargetServer definition, and the TargetServer definition references the
keystore and truststore, then no proxy redeployment is necessary.
3. If the keystore is used for two-way TLS between SAP API Management Edge and the backend service, and
you deleted/recreated the keystore with the same name, you must restart the SAP API Management
Edge Message Processors.
5. After you have confirmed that your new keystore is working correctly, delete the old keystore with the expired
cert and key as described above.
The way you update an TLS certificate in a truststore is based on your SAP API Management Edge deployment
type: cloud or Private Cloud.
Cloud Deployment
For a cloud-based deployment of SAP API Management Edge:
1. Upload a new cert to the truststore as described in Keystores and Truststores. There is no need to delete the
old cert.
2. For both inbound or outbound connections, contact SAP Support.
3. Confirm that your updated truststore is working correctly.
On-premises deployment
For an on-premises deployment of SAP API Management Edge:
1. Upload a new cert to the truststore as described in Keystores and Truststores. There is no need to delete the
old cert.
2. For inbound connections, meaning an API request into SAP API Management Edge, restart the Routers, one
at a time. No proxy redeployment required.
SAP API Management provides all Cloud customers with a cert when they create an account so that the customer
can get up and running quickly with SAP API Management Edge. All Cloud customers get a copy of the same SAP
API Management-provided cert.
Based on when you obtained your cert, the SAP API Management cert will expire on either February 23, 2016 or
April 8, 2016. SAP API Management will be updating all keystores before those dates to upload a new cert and
private key.
However, if you have uploaded the SAP API Management cert to a truststore, you must add the new SAP API
Management cert to your truststore before it expires. You do not have to delete the old SAP API Management
cert, you only have to upload the new one.
Shown below is the new cert:
-----BEGIN CERTIFICATE-----
MIIFHzCCBAegAwIBAgIISzef6agJ+w4wDQYJKoZIhvcNAQELBQAwgbQxCzAJBgNV
BAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRow
GAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjEtMCsGA1UECxMkaHR0cDovL2NlcnRz
LmdvZGFkZHkuY29tL3JlcG9zaXRvcnkvMTMwMQYDVQQDEypHbyBEYWRkeSBTZWN1
cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IC0gRzIwHhcNMTYwMTEzMTcyNTU0WhcN
MTkwNDA5MDYzNzEwWjA6MSEwHwYDVQQLExhEb21haW4gQ29udHJvbCBWYWxpZGF0
ZWQxFTATBgNVBAMMDCouYXBpZ2VlLm5ldDCCASIwDQYJKoZIhvcNAQEBBQADggEP
ADCCAQoCggEBALRAjJBUiGcKTEye40tpQjqGnAYn+LgpfS8Wkhh5nUZFvJBbEVDe
heH4Agc1LILOExEtKj/bGRhhFQzojSfTmz3LuGA8oVnzzOamYDvzkTkK5yO+Yd2C
FXgEOQhphcaZms2Z1Kl9cn1fQRl/+KUbiKgV/piu4079cnPqR8uME94mWnHpRurd
ZJqfOxpz+144RbTNaSJdQdiPQ1vzxmLQFFN2SrbWx4OXni/C5QJ0S14uplZHgw+j
Ae/LGAiaJR7nirot3QEk7qdYRF6g86OvrpToDbG6vKSyuIXoOT33oBJnjfFQRkq+
29VcMWwWLe6lmToGpp0xkNxdeyFB0oyQqFsCAwEAAaOCAawwggGoMAwGA1UdEwEB
/wQCMAAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA4GA1UdDwEB/wQE
AwIFoDA3BgNVHR8EMDAuMCygKqAohiZodHRwOi8vY3JsLmdvZGFkZHkuY29tL2dk
aWcyczEtMTc4LmNybDBTBgNVHSAETDBKMEgGC2CGSAGG/W0BBxcBMDkwNwYIKwYB
BQUHAgEWK2h0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9y
eS8wdgYIKwYBBQUHAQEEajBoMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5nb2Rh
ZGR5LmNvbS8wQAYIKwYBBQUHMAKGNGh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRk
eS5jb20vcmVwb3NpdG9yeS9nZGlnMi5jcnQwHwYDVR0jBBgwFoAUQMK9J47MNIMw
ojPX+2yz8LQsgM4wIwYDVR0RBBwwGoIMKi5hcGlnZWUubmV0ggphcGlnZWUubmV0
If you are updating a truststore on SAP API Management Edge, use the Upload a Certificate to a Truststore:
$ curl -X POST -H "Content-Type: multipart/form-data" -F file="@newapigeecert.pem" \
https://api.enterprise.apigee.com/v1/o/{org_name}/environments/{env_name}/keystores/my
Truststore/certs?alias=myTruststore \
-u email:password
where the -F option specifies the path to the PEM file.
SAP API Management has several entry points that you might want to secure with SSL. In addition, system add-
ons, such as the Developer Services portal, have entry points that can be configured to use SSL.
For the Developer Services portal, you are completely responsible for configuring SSL. That means you not only
have to obtain the SSL certificate and private key, but you also have to configure SAP API Management to use
SSL.
The following images shows the places in an SAP API Management installation where you can configure SSL:
1 API Management The management UI is a browser-based tool that API developers use to
developer UI perform most of the tasks necessary to create, configure, and manage
API proxies and API products.
2 API management All system services can be configured through the management API, a
Developer API REST-based API. That means you can use these APIs to create,
configure, and manage API proxies and API products, create and
manage apps and app developers, and to perform many other types of
operations.
3 API Client API Apps access your APIs by making requests to API proxies through
(app) virtual hosts on the SAP API Management Router.
4 SAP API Target An API proxy functions as a mapping of a publicly available endpoint on
Management endpoint system to a target endpoint, which is often defined by an endpoint on
5 Router Message A Router handles all system incoming API traffic, determines the API
Processor proxy that handles the request, balances requests across available
Message Processors, and dispatches the request.
The following image shows a scenario where the API client accesses SAP API Management through a load
balancer, rather than accessing the Router directly:
Note
Load balancers often cannot be configured to support two-way SSL.
When using a load balancer, you can configure SSL between the API client and the load balancer and, if necessary,
between the load balancer and the Router, as the following table describes:
6 API Load Apps access your APIs by making requests to API proxies through a load
Client Balancer balancer. The load balancer forwards the request to an SAP API
(app) Management Router.
You can configure SSL on the entry point of the load balancer. The way you
configure SSL is based on the load balancer.
7 Load Router Depending on your configuration, you might configure SSL access to the
Balancer Router from the load balancer. In that case, you configure SSL just as if the
load balancer was not present.
Or, if the load balancer and Router are in the same security domain, SSL
configuration may not be necessary. However, that is dependent on your
network configuration.
The following image show the two places where the portal uses SSL:
To configure TLS, you have to configure the following on SAP API Management Edge:
• Repositories for TLS keys and certs:
o Keystores: Contains an TLS certificate and private key used to identify the entity during TLS
handshaking. When you create the keystore and upload the TLS cert, you specify an alias name used to
reference the cert/key pair.
o Truststores: contains certificates used to verify certificates received as part of TLS handshaking. A
truststore is not required. It is typically used to validate self-signed certificates received from the TLS
server, or certificates that are not signed by a trusted CA.
Configuring SSL
The following table describes the locations where you configure SSL access:
3 API Client API Enable SSL on API access through the use of virtual hosts on the
(app) Router.
4 SAP API Target Enable SSL between SAP API Management and a backend service
Management endpoint provider.
5 Router Message Enable SSL for communication between a Router and Message
Processor Processor.
See the Operations Guide for more.
If your installation included a load balancer, then you might also have to replace the configuration for #3 above to
configure SSL between the app and load balancer, and between the load balancer and the Router:
6 App Load Enable SSL on the load balancer. This process is determined by your load
Balancer balancer.
7 Load Router If necessary, enable SSL on the Router for requests from the load balancer.
Balancer Use the same process as you do for configuring SSL for a virtual host.
If the load balancer and Router are in the same security domain, SSL
configuration may not be necessary. However, that is dependent on your
network configuration.
A virtual host defines the domains and ports on which an API proxy is exposed, and, by extension, the URL that
apps use to access an API proxy.
A virtual host also defines whether the API proxy is accessed by using the HTTP protocol, or by the encrypted
HTTPS protocol that uses SSL. When configuring a virtual host to use HTTPS and SSL, you create a virtual host
and configure the virtual host to use a keystore and truststore.
Note
If your installation uses a load balancer, and the load balancer is responsible for handling encrypted
traffic, then you still need to create the virtual host. However, your network configuration will determine
whether or not the virtual host has to support SSL between the load balancer and the Router.
Before you create a virtual host, you should have the following information:
The publicly facing domain name of the virtual host. For example, you should know if the publicly facing name
is api.myCompany.com,myapi.myCompany.com, etc. That information is used when you create the virtual host
and also when you create the DNS record for the virtual host.
• For one-way SSL, you need to create a keystore where the keystore contains the following:
o SSL certificate as a PEM file - either a certificate signed by a certificate authority (CA), or a chain of
certificates where the last certificate is signed by a CA.
o Private key as a PEM file. SAP API Management supports key sizes up to 2048 bits. A passphrase is
optional.
• For two-way SSL, you need a keystore just like you do with one-way SSL and, depending on how you
configure two-way SSL, you might also need a client certificate and a truststore to hold that certificate and
the certificate's CA chain.
To create a virtual host, create an XML object that defines the virtual host. For example, the following XML object
defines a virtual host that uses the HTTP protocol:
<VirtualHost name="myVHost">
Notice that the virtual host contains a name property. You use the value of the name property to configure an API
proxy to use the virtual host.
You can then access an API proxy through this virtual host by making a request to:
http://<routerIP>:<port>/{proxy-base-path}/{resource-path}
https://<routerIP>:<port>/{proxy-base-path}/{resource-path}
where:
• http or https: If the virtual host is configured to supports SSL, use HTTPS. If the virtual host does not
support SSL, use HTTP.
• <routerIP>:<port> is the IP address and port number of the virtual host.
• {proxy-base-path} and {resource-path} are defined when you create the API proxy.
Typically, you do not publish your APIs to customers with an IP address and port number. Instead, you define a
DNS entry for the Router and port. For example:
http://api.myCompany.com/{proxy-base-path}/{resource-path}
https://api.myCompany.com/{proxy-base-path}/{resource-path}
If you define the DNS entry, then you must create a host alias for the virtual host that matches the domain name
of the DNS entry. From the example above, you would specify a host alias of api.myCompany.com.
<VirtualHost name="myVHost">
<HostAliases>
<HostAlias>api.myCompany.com:9005</HostAlias>
</HostAliases>
<Interfaces/>
<Port>9005</Port>
</VirtualHost>
The next XML object uses the <SSLInfo> element to define a virtual host for a one-way SSL configuration over
HTTPS:
<VirtualHost name="mySSLVHost">
<HostAliases>
In this example, the <Enabled> element is set to true to enable one-way SSL, and the <KeyStore> and
<KeyAlias> elements specify the keystore and key used by the SSL connection.
The value of the <TrustStore> element depends on your configuration. If your configuration requires a truststore,
then specify a value for the <TrustStore> element. Otherwise, leave it empty.
The following table lists the XML elements that you use to configure a virtual host:
VirtualHost Specifies the name of the virtual host. You use that name to None Yes
reference the virtual host when configuring an API proxy.
The characters that you can use in the name attribute are
restricted to: A-Z0-9._\-$ %.
Port Specifies the port number used by the virtual host. Ensure None Yes
that the port is open on the SAP API Management Router.
If you specify a port in a <HostAlias> element, then the port
number specified by <Port> must match it.
While it is not required, it is a best practice to use a different
port for each virtual host.
Note: A router can listen to only one HTTPS connection per
virtual host, on a specific port, with the specified cert.
Therefore, multiple virtual hosts cannot use the same port
number if SSL termination occurs on the router at the
specified port.
HostAliases
HostAlias The publicly visible DNS name of the virtual host on the None No
Router, optionally including the port number.
You must create a DNS record for the virtual host that
matches the host alias.
Interfaces
Interface Specifies the network interfaces that you want <Port> to be None All
bound to. If you omit this element, the port is bound on all interfaces
interfaces.
For example, to specify to bind the port only to en0:
<Interfaces>
<Interface>en0</Interface>
</Interfaces>
Determine the interfaces available on your system by running
the "ifconfig -a" command.
SSLInfo
Enabled Enables one-way SSL. You must have defined a keystore False no
containing the cert and private key.
KeyAlias The alias specified when you uploaded the JAR file containing None Yes if
the cert and private key to the keystore. Enabled
is true
Truststore The name of the truststore that contains the certificate or None No
certificate chain used for two-way SSL.
<Ciphers>
<Cipher>TLS_RSA_WITH_3DES_EDE_CBC_SHA</Cipher>
<Cipher>TLS_RSA_WITH_DES_CBC_SHA</Cipher>
</Ciphers>
<Protocols>
<Protocol>TLSv1</Protocol>
<Protocol>SSLv2Hello</Protocol>
</Protocols>
To create a virtual host that uses the HTTP protocol, perform the following:
1. Create the virtual host by using the Create a Virtual Host API, where <ms-IP> is the IP address or domain
name of the Management Server node:
Note
All virtual hosts are automatically added to all new API proxies. Therefore, if you create a new API proxy
that should not be accessible over a particular virtual host, then you must edit the API proxy to remove
that virtual host from its ProxyEndpoint.
After updating an API proxy to use the virtual host, and creating the DNS record for the host alias, access the API
proxy as shown below:
http://api.myCompany.com/v1/{project-base-path}/{resource-path}
For example:
http://api.myCompany.com/v1/weather/forecastrss?w=12797282
When you create the keystore, you specify the keystore name and key alias. You need that information to
create the virtual host.
2. Create the virtual host by using the Create a Virtual Host API, where <ms-IP> is the IP address or domain
name of the Management Server node.
Note
If you are performing two-way SSL with the client, then set <ClientAuthEnabled> to true. The client must
be configured correctly for two-way SSL, meaning SAP API Management has a truststore containing the
client's cert and certificate chain.
3. Create a DNS record for the virtual host that matches the host alias.
4. If you have any existing API proxies, add the virtual host to the <HTTPConnection> element in the
ProxyEndpoint. The virtual host is added automatically to all new API proxies.
Note
All virtual hosts are automatically added to all new API proxies. Therefore, if you create a new API proxy
that should not be accessible over a particular virtual host, then you must edit the API proxy to remove
that virtual host from its ProxyEndpoint.
After updating an API proxy to use the virtual host, and creating the DNS record for the host alias, you can access
the API proxy as shown below:
https://apiSSL.myCompany.com/v1/{project-base-path}/{resource-path}
For example:
https://apiSSL.myCompany.com/v1/weather/forecastrss?w=12797282
$ curl -X DELETE \
http://<ms-
IP>:8080/v1/o/{org_name}/environments/{env_name}/virtualhosts/{vhost_name} \
-u myname:mypass
In API proxy functions as a mapping of a publicly available endpoint to your backend service. A virtual host defines
the way that the public facing API proxy is exposed to an app. For example, the virtual host determines if the API
proxy can be accessed by using SSL. When you configure an API proxy, edit its ProxyEndpoint definition to
configure the virtual hosts that is uses.
The TargetEndpoint is the outbound equivalent of the ProxyEndpoint. A TargetEndpoint functions as an HTTP
client from SAP API Management to a backend service. When creating an API proxy, you can configure it to use
zero or more TargetEndpoints.
Note
Node.js: If your proxy target is a Node.js application, you can use the Node.js tls module to create secure
connections to backend services. You make outgoing requests with the tls module the same way you
would normally in Node.js. Basically, you need to add client-side keys and certificates (.pem files) to the
resources/node directory and load them inside your script.
Configuring a TargetEndpoint
To configure a TargetEndpoint, edit the XML object that defines the TargetEndpoint. You can edit
the TargetEndpoint by editing the XML file that defines the TargetEndpoint in your API proxy, or edit it in the
management UI.
<TargetEndpoint name="default">
<Description/>
<FaultRules/>
<Flows/>
<HTTPTargetConnection>
<Properties/>
<URL>https://weather.yahooapis.com</URL>
</HTTPTargetConnection>
<PreFlow name="PreFlow">
<Request/>
<Response/>
</PreFlow>
<PostFlow name="PostFlow">
<Request/>
<Response/>
</PostFlow>
</TargetEndpoint>
7. Make any changes and save the proxy. If the API proxy has been deployed, saving it redeploys it with the new
setting.
Notice that the TargetEndpoint definition contains a name property. You use the value of the name property to
configure the ProxyEndpoint definition of an API proxy to use the TargetEndpoint.
TargetEndpoints can be configured to reference a TargetServer, rather than the explicit target URL.
A TargetServer configuration decouples concrete endpoint URLs from TargetEndpoint configurations.
TargetServers are used to support load balancing and failover across multiple backend server instances.
<TargetEndpoint name="default">
...
<HTTPTargetConnection>
<LoadBalancer>
<Server name="target1" />
<Server name="target2" />
</LoadBalancer>
<Path>/test</Path>
</HTTPTargetConnection>
...
</TargetEndpoint>
To configure one-way SSL access from SAP API Management (SSL client) to the backend server (SSL server)
does not require any additional configuration. It is up to the backend server to configure SSL correctly.
You only need to make sure that the <URL> element in the TargetEndpoint definition, or the <Host> element in a
TargetServer definition, references the backend service by the HTTPS protocol.
If you want to support two-way SSL between SAP API Management (SSL client) and the backend server (SSL
server):
• Create a keystore and upload the cert and private key. This cert and private key is typically supplied by the
backend server.
• Create a truststore that contains the cert and CA chain that you received from the backend server.
• Update the TargetEndpoint of any API proxies that reference the backend server to configure SSL access.
When you create the keystore, you specify the keystore name and key alias. You need that information to
configure the TargetEndpoint.
2. Create a truststore , and upload the cert and CA chain, as described in KeyStores and TrustStores.
When you create the truststore, you specify the truststore name. You need that information to configure the
TargetEndpoint.
3. Use the SAP API Management UI to update the TargetEndpoint definition for the API proxy (or, if you define
the API proxy in XML, edit the XML files for the proxy):
1. Login to the management UI.
2. In the SAP API Management UI menu, select APIs.
3. Select the name of the API proxy to update.
4. Select the Development tab.
5. Under Target Endpoints, select default.
6. In the code area, edit the <HTTPTargetConnection> element to add the <SSLInfo> element. Make
sure to specify the correct keystore and key alias and set both
the <Enabled> and <ClientAuthEnabled> elements to true:
<TargetEndpoint name="default">
…
<HTTPTargetConnection>
<SSLInfo>
<Enabled>true</Enabled>
<ClientAuthEnabled>true</ClientAuthEnabled>
<KeyStore>myKeystore</KeyStore>
<KeyAlias>myKey</KeyAlias>
<TrustStore>myTrustStore</TrustStore>
</SSLInfo>
<URL>https://myservice.com</URL>
</HTTPTargetConnection>
…
</TargetEndpoint>
Note
If your TargetEndpoint references a TargetServer instead of a specific URL, update the TargetServer
definition to reference the new keystore and key alias. For example:
<TargetServer name="target1">
...
<SSLInfo>
<Enabled>true</Enabled>
<ClientAuthEnabled>true</ClientAuthEnabled>
You do not have to save the API proxy if you update a TargetServer definition.
7. Save the API proxy. If the API proxy has been deployed, saving it redeploys it with the new setting.
Enabling SNI
SAP API Management supports the use of Server Name Indication (SNI) from message processors to target
endpoints. Java 1.6 or 1.7 is required.
To be backward compatible with your existing target backends, SAP disabled SNI by default. If your target
backend is configured to support SNI, you can enable this feature by setting the following property
to true in /<inst-root>/sap4/conf/sap/management-server/system.properties:
jsse.enableSNIExtension=true
You must then restart the Message Processors using the command:
/<inst-root>/sap4/bin/sap-service message-processor restart
To configure functionality that relies on public key infrastructure (SSL and SAML, for example) you need to create
keystores and truststores that provide the necessary keys and digital certificates.
Keystores and truststores define repositories of security certificates used for SSL encryption. The main difference
between the two is where they are used in the SSL handshaking process:
• A keystore contains an SSL certificate and private key.
In one-way SSL, when a client connects to the SSL endpoint on the server, the server's keystore presents the
server's certificate (public cert) to the client. The client then validates that certificate with a certificate
authority.
Certificates can be issued by a certificate authority (CA), or they can be self-signed by the private key that you
generate. If you have access to a CA, follow instructions provided by your CA for generating keys and issuing
certificates. If you do not have access to a CA, you can generate a self-signed certificate using one of the many
publicly available free tools, such as openssl.
A truststore is similar to a keystore except that it contains only certs, as a PEM files, but no private keys. If the cert
is part of a chain, then the truststore must contain all certs in the chain as individual PEM files.
SAP API Management provides an API that you use to create keystores and truststores. The actual APIs are the
same. The difference is that when you create a keystore, you pass a JAR file that contains the cert and private key.
When you create a truststore, you pass only the cert as a PEM file.
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
or:
Then the files are compatible with the PEM format and you can use them in a keystore or truststore without
converting them to a PEM file.
-----BEGIN CERTIFICATE-----
(Your Primary SSL certificate)
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
(Intermediate certificate)
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
(Root certificate or intermediate certificate signed by a root certificate)
-----END CERTIFICATE-----
Note
When using a truststore, if you have a chain of certs, you must upload the chain as individual PEM files.
Check your environment for any existing keystores by using the List Keystores and Truststores API:
$ curl -X GET \
https://<host:port>/v1/o/{org_name}/environments/{env_name}/keystores \
-u email:password
The returned array is empty until you create your first keystore.
Check the contents of the keystore by using the Get a Keystore or Truststore API.
You can also view this information in the SAP API Management UI:
1. Login to the management UI http://<ms-ip>:9000 , where <ms-ip> is the IP address of the Management
Server node.
2. In the management UI menu, select Admin > SSL Certificates.
Create a JAR file with your private key, certificate, and a manifest. The JAR file must contain the following files and
directories:
/META-INF/descriptor.properties
myCert.pem
myKey.pem
Note
A keystore JAR can contain only one certificate. If you have a certificate chain, all certs in the chain must
be appended into a single PEM file, where the last certificate is signed by a CA. The certs must be
appended to the PEM file in the correct order, meaning:
cert -> intermediate cert(1) -> intermediate cert(2) -> … -> root
In the directory containing your key pair and certificate, create a directory called /META-INF. Then, create a file
called descriptor.properties in/META-INF with the following contents:
certFile={myCertificate}.pem
keyFile={myKey}.pem
Generate the JAR file containing your key pair and certificate:
$ jar -cf myKeystore.jar myCert.pem myKey.pem
Create a keystore
A keystore is specific to an environment in your organization, for example the test or prod environment.
Therefore, if you want to test the keystore in a test environment before deploying it to your production
environment, you must create it in both environments.
To create a keystore in an environment, you only need to specify the keystore name to the Create a Keystore or
Truststore API:
$ curl -H "Content-Type: text/xml" \
https://<host:port>/v1/o/{org_name}/environments/{env_name}/keystores \
-d '<KeyStore name="myKeystore"/>' -u email:password
Sample response:
{
"certs" : [ ],
"keys" : [ ],
"name" : "myKeystore"
}
After you create a named keystore in an environment, you can upload your JAR files that contain a cert and
private key by using the Upload a JAR file to a Keystore API:
$ curl -X POST -H "Content-Type: multipart/form-data" \
-F file="@myKeystore.jar" \
"https://<host:port>/v1/o/{org_name}/environments/{env_name}/keystores/{myKeystore}/ke
ys?alias={key_alias}&password={key_pass}" \
-u email:password
$ curl
https://<host:port>/v1/o/{org_name}/environments/{env_name}/keystores/myKeystore \
Sample response:
{
"certs" : [ "myCertificate" ],
"keys" : [ "myKey" ],
"name" : "myKeystore"
}
Create a truststore
The APIs that you use to create a truststore are the same as used to create a keystore. The only difference is that
you pass the cert file as a PEM file instead of a JAR file.
Note
You often create a truststore on SAP API Management as part of configuring two-way SSL between SAP
API Management and a backend server. In this case, when you configure the truststore on SAP API
Management you upload a cert file that you received from the entity hosting the backend server.
If the cert is part of a chain, then you must upload all certs in the chain separately to the truststore. The final
certificate is typically signed by the certificate issuer. For example, in the truststore, you upload a client
certificate, client_cert_1, and the client certificate issuer's certificate, ca_cert.
During two-way SSL authentication, client authentication succeeds when the server sends client_cert_1 to the
client as part of the SSL handshaking process.
Alternatively, you have a second cert, client_cert_2, signed by the same cert, ca_cert. However, you do not
upload client_cert_2 to the truststore. The truststore still contains client_cert_1 and ca_cert.
When the server passes client_cert_2 as part of SSL handshaking, the request succeeds. This is because SAP API
Management allows SSL verification to succeed when client_cert_2 does not exist in the truststore but was signed
by the a cert that exists in the truststore. If you remove the CA certificate,ca_cert, from the truststore then SSL
verification fails.
Create an empty truststore in the environment by using Create a Keystore or Truststore, the same API that you
use to create a keystore:
$ curl -X POST -H "Content-Type: text/xml" -d \
'<KeyStore name="myTruststore"/>' \
https://<host:port>/v1/o/{org_name}/environments/{env_name}/keystores \
-u email:password
You can delete a keystore or truststore by using the Delete a Keystore or Truststore API:
$ curl -X DELETE \
https://<host:port>/v1/o/{org_name}/environments/{env_name}/keystores/myKeystoreName \
-u email:password
Sample response:
{
"certs" : [ ],
"keys" : [ ],
"name" : "myKeystoreName"
}
If you delete and recreate a keystore or truststore that is being used by a virtual host, then you must redeploy
your API proxies. See Understanding deployment.
You can use the Get a Cert from a Keystore or Truststore API to view details about SSL certificates in the
keystore, such as expiration date and issuer. First, obtain the name of the certificate in which you are interested.
This example fetches information for the keystore called "freetrial".
$ curl https://<host:port>/v1/o/{org_name}/environments/{env_name}/keystores/freetrial
\
-u email:password
Sample response:
{
Then, use the value of the certs property to get the certificate details:
$ curl
https://<host:port>/v1/o/{org_name}/environments/{env_name}/keystores/freetrial/certs/
wildcard.sap.net.crt \
-u email:password
Sample response:
{
"certInfo" : [ {
"expiryDate" : "Wed, 23 Apr 2014 20:50:02 UTC",
"isValid" : "Yes",
"issuer" : "CN=Go Daddy Secure Certificate Authority - G2,
OU=http://certs.godaddy.com/repository/, O="GoDaddy.com, Inc.",
L=Scottsdale, ST=Arizona, C=US",
"subject" : CN=*.example.sap.net, OU=Domain Control Validated",
"subjectAlternativeNames" : ["*.example.sap.net","*.example.sap.net" ],
"validFrom" : "Tue, 15 Apr 2014 09:17:03 UTC",
"version" : 3
} ],
"name" : "example.sap.net.crt"
}
You can also view this information in the SAP API Management UI:
1. Login to the management UI at http://<ms-ip>:9000 , where <ms-ip> is the IP address of the Management
Server node.
2. In the SAP API Management UI menu, select Admin > SSL Certificates.
In the SAP API Management UI, you can specify how far in advance SAP API Management indicates that a
certificate is going to expire. By default, the UI highlights any certificates scheduled to expire in the next 10 days.
If an SSL certificate expires, then you need to update the certificate. The process of updating a certificate
depends on your deployment of SAP API Management: cloud or on-premises.
• You can optionally choose to delete the existing keystore and then create a new one with the same name.
However, for the time from when the certificate expired until you create the new keystore, you cannot service
requests.
Typically, you create a new keystore before the current certificate expires, and then update your virtual hosts
or target endpoints to use the new keystore so that you can continue to service requests without interruption
due to an expired certificate. You can then delete the old keystore after ensuring that the new keystore is
working correctly.
To check when a certificate is due to expire, go to the Admin > SSL Certificates menu in the management UI.
You can also configure that page to indicate if a certificate is due to expire in 10, 15, 30, or 90 days.
If the TargetEndpoint references a TargetServer definition, and the TargetServer definition references the
keystore and truststore, then no proxy redeployment is necessary.
5. After you have confirmed that your new keystore is working correctly, delete the old keystore with the expired
cert and key as described above.
SSL (Secure Sockets Layer) is the standard security technology for establishing an encrypted link between a web
server and a web client, such as a browser or app. An encrypted link ensures that all data passing between the
web server and the client remains private. To use SSL, a client makes a secure request to the web server by using
the secure https:// protocol, instead of the insecure http:// protocol.
The following image show the two places where the portal uses SSL:
1. For communication between the portal and the SAP API Management Edge API.
The portal does not function as a stand-alone system. Instead, much of the information used by the portal is
actually stored on SAP API Management. When necessary, the portal makes an HTTP or HTTPS request to
the management API to retrieve information or to send information.
When you create your portal, one of the first steps you must perform is to specify the URL of the
management API. Depending on how the management API is configured, that URL can use SSL.
2. For communication between developers and the portal.
When you use the Developer Services portal to deploy your APIs, your developers log in to the portal to
register apps and receive API keys. The login credentials and the API key are proprietary information that you
want to send over HTTPS to ensure their security. This type of proprietary information should be sent over
HTTPS.
The portal require the portal to be behind a load balancer, as shown below.
• session.cookie_secure - (Optional) Specifies that cookies can only be sent over secure connections. However,
this means that all content must be served over HTTPS. If this setting is enabled, the site will not work over
HTTP. Set this property as:
ini_set('session.cookie_secure', true);
• gc_maslifetime and cookie_lifetime: (Optional) gc_lifeteime specifies the number of seconds after which data
can potentially be cleaned up, andcookie_lifetime specifies the lifetime of the cookie in seconds. Set these
properties as:
ini_set('session.gc_maxlifetime', 3600);
ini_set('session.cookie_lifetime', 3600);
For better performance, load balancers are sometimes configured to perform SSL termination. With SSL
termination, load balancers decrypt messages sent over https:// and forward the messages to backend servers
over http://. That saves backend servers the overhead of decrypting https://messages themselves.
If load balancers forward unencrypted http messages to servers in the same data center, security is not an issue.
However, if load balancers forward messages over http:// to servers outside the data center, such as your SAP
API Management developer portal, the messages are unencrypted, which opens a security hole.
If your developer portal sits behind load balancers that are using SSL termination, and you want all traffic served
over https://, the website pages will need to contain https:// links only and you will need to add the following code
to your developer portal sites/default/settings.php file. Because the load balancer does not automatically
transform the content of the HTML pages, the code ensures that all links passed to the client start with https://.
To configure SSL with load balancers, add the following lines to the sites/default/settings.php file:
$_SERVER['HTTPS'] = 'on';
$base_url = "https://myurl.com";
$can_detect_ssl = FALSE;
API keys provide a simple mechanism for authenticating apps. SAP API Platform generates API keys for apps, and
enables you to add API key-based authentication to your APIs using policies. Using SAP API Platform, you can
issue, administer and validate API keys without writing any code. This topic shows you how to add API key
validation to an API. To learn about API key management, start with the Developer Services
Note
API keys go by many names. You may see them referred to as 'API keys', 'app keys', and 'consumer keys'.
All of these names are synonymous.
When apps are registered with SAP API Management Developer Services, a consumer key and secret pair is
generated for the app. SAP API Management API Platform stores the consumer key for future validation. The app
developer embeds the consumer key in the client app. The client app must present the consumer key for each
request. API Platform validates the consumer key before permitting the app's request.
API key validation is the simplest form of app-based security that you can configure for an API. Apps simply
present an API key, and SAP API Platform checks to see that the API key is in an approved state for the resource
being requested. For this reason the security associated with API keys is limited. API keys can easily be extracted
from app code and used to access an API. You may find that API keys work better as unique app identifiers than as
security tokens.
Policy Configuration
You can set up API key validation for an API by attaching a policy of type ValidateAPIKey. The only required setting
for a ValidateAPIKey policy is the expected location of the API key in the client request. The API proxy will check
the location that you specify, and extract the API key. If the API key is not present in the expected location, then an
error is thrown and the request is rejected. API keys can be located in a query parameter, a form parameter, or an
HTTP header.
For example, the policy configuration below defines the expected key location as a query parameter
named apikey. A successful request must present the API key as a query parameter appended to the request, for
example,?apikey=Y7yeiuhcbKJHD790.
Policy Attachment
The policies must be attached to an API proxy Flow as processing Steps. By applying the policy to the request
PreFlow, API keys are verified on every request received by the API proxy from a client app. After verification, the
API key is stripped from the outbound request.
Attach the policies to the ProxyEndpoint of the API proxy to be protected as follows:
<ProxyEndpoint name="default">
<PreFlow>
<Request>
<Step><Name>ValidateAPIKey</Name></Step>
<Step><Name>StripApiKey</Name></Step>
</Request>
</PreFlow>
After you attach the policy, deploy the API proxy.
As an admin in your organization, you can retrieve any app's API key as follows:
$ curl http://<host:port>/v1/o/{myorg}/developers/{developer_email}/apps/{app_name}
-u myname:mypass
Note
Remember to substitute your organization for {myorg} and your username and password for
myname:mypass.
The app profile that is returned for this call provides the consumer key (API key) and secret. The consumer key
value is the value you use for the API key in your request to the protected API.
For example, a request that does not include an API key results in an authorization failure.
$ curl http://<host:port>/weather/forecastrss?w=12797282
The failure message indicates that the policy checked for an API key but did not find a valid key:
OAuth Failure : Could not resolve the app key with variable
request.queryparam.apikey
When the consumer key for the app is included as a query parameter, the expected result is successful
authorization:
$ curl http://{org_name}-
test.<host:port>.net/weather/forecastrss?w=12797282&"apikey=PulSCqMnXGchW0pC0s5o9ng
HVTWMeLqk"
The expected result is a successful response from the weather service.
Modifying the value of the API key value in the request results in an authorization failure:
$ curl http://<host:port>/weather?forecastrss?w=12797282&"apikey=PulSCqMnXGchW0"
Results in:
OAuth Failure : Consumer Key is Invalid
Remember, as an admin for your organization, you can retrieve the consumer key for any app registered in an
organization:
$ curl http://<host:port>/v1/o/{myorg}/developers/{developer_email}/apps/{app_name}
-u myname:mypass
4.5 SAML
The Security Assertion Markup Language (SAML) specification defines formats and protocols that enable
applications to exchange XML-formatted information for authentication and authorization.
SAP API Management API Services enables you to authenticate and authorize apps that are capable of presenting
SAML tokens. A SAML token is a digitally signed fragment of XML that presents a set of "assertions". These
assertions can be used to enforce authentication and authorization.
To use SAML terminology, API Services can function as a service provider (SP) or an Identity Provider (IP). When
API Services validates SAML tokens on inbound requests from apps, it acts in the role of SP. (API Services can
The SAML policy type enables API proxies to validate SAML assertions that are attached to inbound SOAP
requests. The SAML policy validates incoming messages that contain a digitally-signed SAML assertion, rejects
them if they are invalid, and sets variables that allow additional policies, or the backend services itself, to further
validate the information in the assertion.
To validate SAML tokens, you need to make digital certificates available to the SAML policy by creating at least
one TrustStore. TrustStores are scoped to environments in your organizations. Thus, you can configure different
trust chains in test and prod, ensuring that test SAML tokens cannot be used in prod, and vice-versa.
For details on SAML validation, See Authenticate and authorize using SAML 2.0.
Last-mile security protects the backend services that are proxied by API Platform. The primary goal of last-mile
security is to prevent so-called "end-run" attacks, where an app developer discovers the URL for a backend
service and bypasses any API proxies to directly hit the backend URL.
Following are the primary options for setting up last-mile security:
• Client SSL
or
• Outbound authentication
Client SSL
The primary mechanism for securing the last-mile is client SSL, which is also known as 'mutual authentication'.
See Client-SSL to backend servers.
Outbound Authentication
Last-mile security can also be enforced by requiring the API proxy to present a credential to the backend service.
For example, you may wish to have an API proxy present an API key to your backend service. You could also have
an API proxy obtain and present an OAuth client credentials access token.
API keys can be applied to outbound requests from API proxies to backend services. This assumes that the
backend service is an API that is capable of issuing and validating API keys.
If you do set up an API proxy to present an API key on outbound requests, you must store the API key in a place
where it can be retrieved by the API proxy at runtime. One location available for storing API keys is a key/value
map. See Persist data using KeyValueMap.
You can use the AssignMessage policy type to add the API key as an HTTP header, query parameter, or payload
element to the outbound request. See Generate or modify messages using AssignMessage.
Note
To avoid exposing API keys over network, always configure server-side SSL on your backend services for
outbound transactions that use API keys.
OAuth client credentials can be used to add a layer of revocability to API keys. If your backend services support
OAuth client credentials, you can configure an API proxy to present a client credentials access token for each
request.
The API proxy must be configured to perform a callout to obtain the access token from your token endpoint. The
API proxy is also required to cache the access token, to prevent it from obtaining a new access token for each call.
Note
Your backend services must be capable of issuing and validating access tokens using the client
credentials grant type for this to work.
Recommendation
Always configure server-side SSL on your backend services for transactions that use access tokens.
A number of approaches can be used to implement outbound client credentials.
You can modify this sample to call your token endpoint to obtain an access token. This sample uses JavaScript to
attach the token to the outbound request as an HTTP Authorization header. You could also use AssignMessage
for this purpose.
Message content is a significant attack vector used by malicious API consumers. API Platform provides a set of
Policy types to mitigate the potential for your backend services to be compromised by attackers or by malformed
request payloads.
JSON attacks attempt to use structures that overwhelm JSON parsers to crash a service and induce application-
level denial-of-service attacks.
Such attacks can be mitigated using the JSONThreatProtection Policy type.
See Minimize vulnerabilities using JSONThreatProtection.
XML attacks attempt to use structures that overwhelm XML parsers to crash a service and induce application-
level denial-of-service attacks.
Such attacks can be mitigated using the XMLThreatProtection Policy type.
See Minimize API Vulnerabilities Using XML Threat Protection .
Some content-based attacks use specific constructs in HTTP headers, query parameters, or payload content to
attempt to execute code. An example is SQL-injection attacks. Such attacks can be mitigated using the
RegularExpressionProtection Policy type.
See Evaluate message content using RegularExpressionProtection.
Overview
SAP API Management enables developers to capture message content to enable runtime debugging of APIs calls.
In many cases, API traffic contains sensitive data, such credit cards or personally identifiable health information
(PHI) that needs to filtered out of the captured message content.
To meet this requirement, SAP API Management defines 'mask configurations' that enable you to specify data
that will be filtered out of trace sessions. Masking configurations can be set globally (at the organization-level) or
locally (at the API proxy level). Role-based capabilities govern which users have access to the data that is defined
as sensitive.
Note
Data masking is only enabled when a trace session (also called a 'debug' session) is enabled for an API
proxy. If no trace session is enabled on an API proxy, then the data will not be masked.
Note
The name of the mask must be default.
<MaskDataConfiguration name="default">
<XPathsRequest>
<XPathRequest>/sap:Greeting/sap:User</XPathRequest>
</XPathsRequest>
<XPathsResponse>
<XPathResponse>/sap:Greeting/sap:User</XPathResponse>
</XPathsResponse>
<JSONPathsRequest>
<JSONPathRequest>$.store.book[*].author</JSONPathRequest>
</JSONPathsRequest>
<JSONPathsResponse>
<JSONPathResponse>$.store.book[*].author</JSONPathResponse>
</JSONPathsResponse>
<XPathsFault>
<XPathFault>/sap:Greeting/sap:User</XPathFault>
</XPathsFault>
<JSONPathsFault>
<JSONPathFault>$.store.book[*].author</JSONPathFault>
</JSONPathsFault>
<Variables>
<Variable>request.header.user-agent</Variable>
<Variable>request.formparam.password</Variable>
</Variables>
</MaskDataConfiguration>
Recommendation
If you use ServiceCallout to make a request, the information in that request is not masked with the normal
Maskconfig configuration. If you wish to mask ServiceCallout request information, add flow to the variable
ServiceCallout.request to the <Variables> element of the Maskconfig configuration.
Mask configurations are defined as XML- or JSON-formatted files that you upload and download using the
RESTful management API.
To see existing mask configurations, you can simply call the API resource /maskconfigs in your organization:
$ curl http://<host:port>/v1/o/{org_name}/maskconfigs \
-u myemail:mypass
To see mask configurations defined for specific API proxies, you can call the /maskconfigs API:
$ curl http://<host:port>/v1/o/{org_name}/apis/{api_name}/maskconfigs \
-u myemail:mypass
To see a specific mask configuration, specify the name of the mask:
$ curl http://<host:port>/v1/o/{org_name}/maskconfigs\default \
-u myemail:mypass
----------------------------------------------
$ curl http://<host:port>/v1/o/{org_name}/apis/{api_name}/maskconfigs\default \
-u myemail:mypass
To create a mask configuration, use the POST verb to submit a payload that defines the mask configuration:
$ curl -H "Content-type:text/xml" -X POST -d \
'<MaskDataConfiguration name="default">
<XPathsRequest>
<XPathRequest>/sap:Greeting/sap:User</XPathRequest>
</XPathsRequest>
<XPathsResponse>
<XPathResponse>/sap:Greeting/sap:User</XPathResponse>
</XPathsResponse>
<JSONPathsRequest>
<JSONPathRequest>$.store.book[*].author</JSONPathRequest>
</JSONPathsRequest>
<JSONPathsResponse>
<JSONPathResponse>$.store.book[*].author</JSONPathResponse>
A developer builds an app that makes requests to your APIs to access your backend services. The following image
shows the relationship of a developer to an app and to an API:
Publishing is the process of making your APIs available to app developers for consumption. SAP API Management
supports a flexible publishing model that gives you complete control over the publishing process.
The first task in publishing is to create an API product. An API product is a collection of API resources that are
offered as a package to app developers for consumption. Create API products by using the SAP API Management
API or UI.
In this figure, your API consists of two products, each containing three API resources.
As an API provider, you are responsible for building the APIs and API products to handle access control, usage
restrictions, and any other business requirements. For example, you might:
• Release a free API product that allows read-only access to its API resources.
• Release a second API product for a low price that allows read/write access to the same API resources as the
free version but with a low access limit, such as 1000 requests per day.
• Release a third API product for a higher price that allows read/write access the the same API resource but
with a high access limit.
The important thing to remember is that SAP API Management gives you the flexibility to create API products that
match the business requirements of your APIs.
For more information on creating API products, see Creating API products.
A developer creates the apps that consume your APIs. Developers must be registered on SAP API Platform before
they can register an app and receive an API key.
Through the app registration process, you control who has access to your APIs. At any time, you can delete an
app developer, which invalidates all API keys associated with that developer, therefore denying that developer
access to your APIs.
Before an app can access your APIs, the app must be registered on SAP API Management. However, only a
registered developer can register an app on SAP API Management.
Note
SAP API Management does not require that you to let the developer associate multiple API products with
an app. Your publishing plan can be structured such that the developer can select only a single API
product. Or, you can automatically assign a default API product to all apps so that the developer does not
even get to choose one.
In response to registering the app on SAP API Management, it assigns a unique API key to the app. The app must
pass that API key as part of every request to an API resource. The key is authenticated and, if valid, the request is
granted. At any time, you as the service provider can revoke the key so that the app can no longer access your
APIs.
As an API provider, you decide how you want to register apps. You could:
• Use a manual process that requires a developer to contact your organization to register their app. In
response, you would send the developer the API key, possibly by email.
• Use the SAP API Management API to integrate app registration functionality and key delivery into your
website.
• Use the SAP API Management Developer Services portal which has built in support for app registration and
API key delivery.
Note
As a best practice, there is a 1-1 correlation between the app that the developer registers on SAP API
Management and the actual client app that they build. However, this correlation is not enforced by SAP
API Management. For example, a developer registers a single app on SAP API Management, associated
that app with an API product, and receives back an API key. The developer is free to use the API key from
any client app.
For more information, see Registering apps.
An important consideration for publishing API products is providing documentation and a developer feedback
mechanism. Developer portals with social publishing features are increasingly being used for communication with
the development community. This includes communicating static content, such as API documentation and terms-
of-use, as well as dynamic community-contributed content such as blogs and forums, as well as customer
support features.
SmartDocs
SmartDocs lets you document your APIs on the Developer Services portal in a way that makes the API
documentation fully interactive. Interactive documentation with SmartDocs means portal users can:
• Read about the API
• Send a live request to the API
• View a live response returned from the API
For example, the following figure shows an API documented on the portal by using SmartDocs. This API provides
weather information for a specific location:
SmartDocs represents your APIs by using a model, where the model contains all the information about your APIs.
The portal extracts information about your APIs from the model to render the documentation pages on the portal
as Drupal nodes, where each Drupal node corresponds to a page of documentation on the portal.
The general steps that you follow to use SmartDocs are:
1. Configure the Drupal SmartDocs module on the portal.
2. Create a SmartDocs model.
3. Add APIs to the model from a WADL file, Swagger definition, or manually.
4. Render the model as a collection of Drupal nodes. Each Drupal node contains information about a single API.
For example, if a resource in your API supports both a POST and a PUT request, SmartDocs creates a
separate Drupal node for the POST and PUT.
5. Publish the Drupal nodes. Once published, your portal users can view and interact with your API.
6. Edit the Drupal nodes, either before or after you publish them. You can edit the Drupal nodes by using the
Drupal editor or by editing the original WADL file or Swagger definition. When you are done editing the WADL
file or Swagger definition, import it back into the model as a new revision, then render and publish your
changes.
7. Enable SSL. Because SmartDocs can send authentication credentials to your backend as part of making a
request to your APIs, you should enable SSL on your portal to ensure that those credentials are secure. In the
portal production and test environments, SAP API Management provides the SSL certificate required to make
SAP API Management implemented SmartDocs as a custom Drupal module. Use the following procedure to
configure the SmartDocs module.
Note
If you are connecting the portal to SAP API Management for the Private Cloud, then you must ensure that
SmartDocs was installed on the Edge Management Server at the time you installed SAP API Management
Edge. For more information, see the "Install and Configuration Guide" in the documentation for the SAP API
Management for the Private Cloud.
where managment_server_ip is the IP address or your Management Server. The response will be in the
form:
{
"authUrl": "https://< managment_server_ip:8080>/v1/users/{user}/authenticate",
"proxyUrl": "https://apiconsole-prod.sap.net/smartdocs/v1/sendrequest"
An API product is a collection of API resources (URIs) combined with a service plan and presented to developers
as a bundle. The API product can also include some metadata specific to your business for monitoring or
analytics. Refer What is an API and Understanding API proxies for more details.
You can think of API products as your product line. You can create different products to provide features for
different use cases. So instead of just giving developers a list of resources, you can bundle specific resources
together to create a product that solves a specific user need. For instance, you can create a product that bundles
a number of mapping resources to let developers easily add maps to their applications.
API products are also a good way to control access to a specific bundle of resources. For example, you can bundle
resources that can only be accessed by internal developers, or bundle resources that can only be accessed by
paying customers.
The API resources bundled in a product can come from one or more APIs, so you can mix and match resources to
create specialized feature sets.
You can set different properties on each API product. For example, you might make available one API product with
a low access limit, such as 1000 requests per day, for a bargain price. You then release another API product that
provides access to the same resources, but with a much higher access limit, for a higher price. Or, you might
Apps are how developers access your API products. When a developer registers an app, they select the API
products to associate with the app, and SAP API Management generates an API key for the app. By default, a
single key provides access to all API products associated with the app. When the app makes a request, SAP API
Management first verifies that the API key is valid and fails the request if not.
To learn how to create apps, see Registering apps
Developers build the apps that access your APIs. However, a developer must first be registered in your
organization before they can register an app.
To learn how to register developers, see Adding developers to your organization.
Create an API product in the SAP API Management UI. You must create your API products using the SAP API
Management before you can make them available on your developer portal.
Recommendation
You can set up an API product with no resources to make it easier to get up and running quickly. Just
create a single API product and provide the base path along with a wildcard for the resource. The wildcard
will be interpreted by the system at runtime as meaning that any requested resource in the URI tree below
the wildcard is permitted. See the procedure below for more information on using a wildcard in an API
product definition.
This section explains a few key concepts related to API products. It's helpful to familiarize yourself with these
concepts before you create a new API product.
Keys
When you register a developer's app in your organization, the app must be associated with at least one API
product. As a result of pairing an app with one or more API products, SAP API Management assigns the app a
unique consumer key. When the app makes a request to an API resource in an API product, the request must
include its unique API key.
API key enforcement doesn't happen automatically. You must enforce API key checking in your API proxies with a
policy, such as the Verify API Key policy. Without some type of key enforcement policy, anyone can make calls to
your APIs. For more information, see Enforce access control using VerifyAPIKey.
By default, all key requests to an API product from an app are automatically approved. You can instead choose to
approve keys manually. If you set this option in the SAP API Management UI when creating the product, you will
have to approve key requests that come in from any app that adds the API product. For more information,
see Registering Apps
Quotas
You can control the traffic flow for each API product by setting up a quota. Quotas can protect your backend
servers for high traffic, and differentiate your product line. For example, you might want to bundle resources with
a high quota as a premium product and use the same bundle with a lower quota as a basic product. A quota can
help protect your servers from being overwhelmed if a product is particularly popular. See Rate limit API traffic
using Quota for more.
Scope
As an added level of security, you can define any OAuth scopes that must be present in access tokens sent
through the product. When you're creating a product, you need to be aware of all the scopes your organization
uses. The scopes you add to a product must match existing scopes or the product is not secure.
For more information about using scopes with OAuth policies, see Authorize requests using OAuth 2.0.
Note
Wildcards (/** and /*) are supported. The double asterisk wildcard indicates that all sub-URIs are
included. A single asterisk indicates that only URIs one level down are included.
An app developer chooses the API product to access when the developer registers the app. The developer then
receives a key that the app must pass on every request to a resource defined by the product.
However, enforcement of the key is performed at the API proxy level, not by the API product itself. Therefore, you
must ensure that all API proxies, and the corresponding resources defined by those API proxies, implement some
form of key validation. For example, you can define an API proxy to perform key validation by using the
VerifyAPIKey policy. Or, an API proxy could use OAuth 2.0 as defined by the OAuth v2.0 policy. For more, see API
keys and OAuth.
When you have API proxy resource files (such as JavaScript or Java JARs) stored at the environment or
organization scope, the validation framework no longer requires you to also include those resources at the API
proxy level in a proxy bundle for import to pass validation. Resource validation now occurs at deploy time, not at
import time.
You can configure API proxies to time out after a specified time (with a 504 gateway timeout status). The primary
use case is for Private Cloud customers who have API proxies that take longer to execute than the timeout
configured on the load balancer, router, and message processor. For example, if the message processor times out
first at 2 minutes, you can configure an API proxy to time out after 3 minutes. The following API proxy
configuration overrides the SAP API Management Edge system timeout with the specified value in milliseconds
for only this proxy:
<ProxyEndpoint name="default">
<HTTPProxyConnection>
Deleting Resources
You can delete resources that you've added to an API product. You might want to do this if a resource is
malfunctioning or requires more development. When deleted, that resource is no longer part of the API product.
Any app that uses the API product can no longer access the deleted resource. Deleted resources are removed
from the product but are not deleted from the system, so they can still be used by other products.
To delete a resource
• In the API Resource Paths for Product section of the product details window, locate the resource you want to
disable, and then choose Delete in the Actions column.
When defining resource paths in API Product, you can include wildcards in multiple places in a resource path. For
example, /team/*/invoices/** allows API calls with any one value after /team and any resource paths
after invoices/. An allowed URI on an API call would
be proxyBasePath/team/finance/invoices/company/a.
If after this release your existing API Product resource paths stop working as expected, set the following property
on your organization to revert to the previous
behavior: features.enableStandardWildCardMatchForAPIProductResources = true
When setting a JSON payload using an Assign Message or Raise Fault policy, users were sometimes required to
use workarounds to ensure a JSON message was properly formatted at runtime, such as beginning the payload
with a backslash "\" or specifying a variablePrefix and variableSuffix on the Payload element, even if no variables
were used in the message.
With this enhancement, no workarounds are needed to ensure proper JSON message formatting, and variables
can be specified using curly braces without creating invalid JSON. For example, the following inserts the value of
message.content in the JSON message:
<Payload contentType="application/json">{"Message: " : "{message.content}"}</Payload>
If you used a workaround, your code will continue to work as is. You can also use variablePrefix and variableSuffix
instead of curly braces to indicate variables.
Developers access your APIs through apps. When the developer registers an app, they receive a single API key
that allows them to access all of the API products associated with the app. However, developers must be
registered before they can register an app.
Developers typically have several ways of registering:
• By accessing a form that uses the SAP API Management API to register the developer. See Using the
Management API to Publish APIs for more.
• By a back-end administrator using the SAP API Management UI, described below.
In the SAP API Management UI, select Publish > Developers to open the Developers page. You can see the apps
they've created and the keys assigned to the developer. From this page, you can also manage the developer's
information or delete them from your org.
Note
If you use the Developer Services portal, SAP API Management recommends that you create, edit, and
delete developers on the portal itself, not in the SAP API Management UI. For more information,
1. Login to the SAP API Management.
2. Choose Publish > Developers in the menu.
3. Choose the (+) Developer button.
4. Enter the first name of your developer.
5. Enter the last name of your developer.
6. Enter the developer's email. This is the email address you use when sending keys and notifications to this
developer.
7. Add any custom attributes for the developer. For each custom attribute:
8. Choose (+) Add Custom Attribute.
9. Enter the attribute name and value.
10. Select Save.
11. If you are using the Developer Services portal, synchronize the portal with the changes to SAP API
Management as described below. When the new developer first logs in to the portal, they must use the
password recovery process on the portal to set their portal password.
Note
If you use the Developer Services portal, SAP API Management recommends that you create, edit, and
delete developers on the portal itself, not in the SAP API Management UI.
Note
If you use the Developer Services portal, SAP API Management recommends that you create, edit, and
delete developers on the portal itself, not in the SAP API Management UI. For more information,
see Manage Users and Roles.
1. Login to the SAP API Management UI.
2. Choose Publish > Developers in the menu.
3. Locate the developer to delete in the list of developers.
4. If the number of Apps for the developer is zero, then the Delete button is enabled.
o Select the Delete button to delete the user.
o Confirm that you want to delete the developer.
5. If the number of Apps for the developer is not zero, then the Delete button is disabled. You must first delete all
apps associated with the developer before you can delete the developer.
o Choose the developer's entry in the Developers page.
o Under Apps on the developer's page, select the app name.
o Select Delete on the app's page, and confirm the deletion.
o After deleting all the developer's apps, you can delete the developer.
If you are using the Developer Services portal, synchronize the portal with the changes to SAP Management UI as
described below.
If you are using a Developer Services portal to publish your APIs, changes made to developers through the SAP
API Management UI are not pushed down to the portal. Therefore, you must log in to the portal as a portal
administrator and synchronize the portal with SAP API Management for those changes to appear on the portal.
Registering Apps
This topic explains how to register and manage apps by using the SAP API Management UI.
Overview
Developers register apps to access your API products. When a developer registers an app, the developer selects
the API products to associate with the app and SAP API Management generates an API key. Each app has a single
API key that provides access to all API products associated with the app.
Apps allow you to control who can access your APIs. You can revoke an app's key, preventing it from accessing all
API products. Or you can revoke access to a single API product associated with the app.
You can see all of your organization's apps in the SAP API Management UI on the Publish > Developer
Apps summary page. This page displays performance data for each app, and general information on app keys.
You can select a specific app from the table to get more detailed information, including the API products that app
can access and the resources those products expose. You can also see the key associated with the app.
Often, developers register their apps through your developer portal. However, if you do not use a portal or if you
want to maintain complete control over the app registration process, you can register apps by using the SAP API
Management UI. For example, you want to register apps for your internal development teams or on behalf of a
developer without access to your portal. When you register an app, you decide which API products to associate
with it. When the app is registered, SAP API Management automatically generates an API key to grant access to
the selected API products. It is then up to you to determine how to pass that key to the app developer.
1. Any additional API products you associate with the app use the same key.
2. To register an app:
3. Login to the SAP API Management UI.
4. Choose the Publish tab, then Developer Apps.
5. Choose (+) Developer App on the Developer Apps page.
6. Enter an application name in the Display name field.
7. Select a developer from the Developer list.
An app must be associated with a registered developer. If the developer does not appear in the list, you can
register them. See Adding developers to your organization for more.
8. If necessary, enter the Callback URL.
A callback URL is the location of a resource that belongs to the app. For example, if you are using OAuth, this
could be the location of a login screen where users enter their username and password. This value s not
required for all API products.
9. Optionally, add a descriptive note for the app.
10. Add any custom attributes for the app. For each custom attribute:
o Choose (+) Add Custom Attribute.
o Add the attribute name and value.
11. Choose Save.
Your app is added to the apps list on the Developer Apps page.
To edit an app:
1. Login to the SAP API Management UI.
2. Choose the Publish tab, then Developer Apps.
3. Select an app in the Developer Apps summary table.
4. Choose Edit.
5. Edit the app's display name and callback URL, as needed.
6. Add, remove, or change a note, as needed.
7. Add, remove, or change any custom attributes, as needed.
You give an app access to your APIs by associating API products with the app. If you want to limit an app's access,
you can temporarily revoke access to an API product, or permanently cut off access to a product by deleting the
API product from the app.
Note
When you create an API product, you can also set its access mode to Internal only or Private. API
products marked Internal only or Private do not appear to developers on the developer portal. To get
access to these products, you manually add them to a developer's app from the SAP API Management UI.
You can expand the app's access to your APIs by associating the app with additional API products:
1. Login to the SAP API Management UI.
2. Choose the Publish tab, then Developer Apps.
3. Select an app in the Developer Apps summary table.
4. On the Developer App page, choose Edit.
5. In the Products section of the Edit Developer App page, choose + Product, select the product you want to
add to the app, and choose the check mark icon.
6. Choose Save. The product is added to the app.
In this procedure, you revoke access to this product and the resources it contains. You can re-enable access at
any time.
1. Login to the SAP API Management UI.
2. Choose the Publish tab, then Developer Apps.
3. Select an app in the Developer Apps summary table.
4. On the Developer App page, choose Edit.
5. In the Products section of the Edit Developer App page, choose Revoke next to the product.
The Revoke button changes to Approve in case you want to make the app part of that product again.
6. Choose Save.
If you specified automatic key approval when you created the API product, a key is automatically approved for use
by an app. If you specified manual key approval when creating the API product, you need to approve the key
manually in the SAP API Management UI before the key can be used by the app to access the product.
In this procedure, you manually approve a product in an app.
1. Login to the SAP API Management UI.
2. Choose the Publish tab, then Developer Apps.
3. If any app is waiting for key approval, Key requested appears in the Key column of the page.
4. Select an app in the Developer Apps summary table with a pending key request.
5. On the Developer App page, choose Edit.
6. In the Products section of the Edit Developer App page, choose Approve next to the product.
7. Choose Save.
In some cases, you may need to regenerate a new consumer key for an app. For instance, you might do this if the
security of the original keys is compromised. Note that if you simply remove products from an app, and then add
the products back, the old consumer keys are reused. To regenerate new consumer keys:
1. Login to the SAP API Management UI.
2. Choose the Publish tab, then Developer Apps.
3. Select the app in the Developer Apps summary table for which you want to generate new consumer keys.
4. On the Developer App page, choose Regenerate Key.
5. In the pop-up, choose Regenerate Consumer Key.
6. Choose Save.
This topic covers the definition of API products. API products enable developers to register apps that consume
APIs using API keys and OAuth access tokens. API products are designed to enable you to 'bundle' API resources
and then publish those bundles to different groups of developers. For example, you may need to publish one set of
API resources to your partner developers, while you publish another bundle to external developers. API products
enable you to perform this bundling on-the-fly, without requiring any changes to your APIs themselves. An
additional benefit is that developer accesses can 'upgraded' and 'downgraded' without requiring developers to
obtain new consumer keys for their apps.
Note
This topic demonstrates provisioning API products, apps, and developers using the SAP API Management
API. You can also provision API products, developers, and apps using the SAP API Management UI.
You can configure API products using the SAP API Management UI or the SAP API Management API. The API
enables you to create and manage API products programmatically.
To set up a minimal API product using the SAP API Management API, POST a payload to the /apiproducts
resource in your organization.
The following request creates an API product called weather_free. The API product provides access to all APIs
exposed by the API proxy called weatherapi that is deployed in the test environment. The approval type is set to
auto--any request for access will be approved.
Caution
Remember to change the values for myname, mypass, and org_name to match the settings for your
account.
approvalType Specifies how API keys are approved to access the N/A Yes
APIs defined by the API product. If set tomanual, the
key that is generated for app is in the 'pending'
state. Such keys won't work until they have been
explicitly approved. If set toauto, all keys are
generated in the 'approved' and work right away.
proxies Named API proxies to which this API product is N/A No. If not
bound. By specifying proxies, you can bind the API defined,apiRe
resources listed in the API product to specific API sources must
proxies, preventing developers from accessing be explicitly
those URIs via other API proxies. defined,
andflow.reso
urce.namevar
iable set in
AssignMessa
ge policy.
environments Named environments (for example 'test' or 'prod") N/A No. If not
to which this API product is bound. By specifying defined, api
one or more environment, you can bind the API Resources m
resources listed in the API product to specific ust be
environment, preventing developer from accessing explicitly
those URIs via API proxies in another environment. defined,
This setting is used, for example, to prevent URIs andflow.reso
protected by API proxies in 'prod' from being urce.namevar
accessed by API proxies deployed in 'test'. iable set in
quota Number of requests permitted per app over the time N/A No
interval specified.
quotaTimeUnit The time unit (minute, hour, day, or month) over N/A No
which quotas are counted.
approvalType Specifies how API keys are approved to access the N/A Yes
APIs defined by the API product. If set tomanual, the
key that is generated for app is in the 'pending'
state. Such keys won't work until they have been
explicitly approved. If set toauto, all keys are
generated in the 'approved' and work right away.
quotaTimeUnit The time unit (minute, hour, day, or month) over N/A Yes
which quotas are counted.
A note on scopes
A scope is a concept drawn from OAuth and maps roughly to the concept of a 'permission'. On SAP API
Management, scopes are completely optional. You can use scopes to achieve finer-grained authorization. Every
consumer key issued to an app is associated with a 'master scope'. The master scope is the set of all scopes in all
API products for this the app has been approved. For apps approved to consume multiple API products, the
master scope is the union of all scopes defined in the API products for which the consumer key has been
approved.
Registering Developers
All apps belong to either developers or companies. Therefore, to create an app, you first need to register a
developer or company.
Note
This section describes how to register apps for developers. You can use the Companies API to set up a
company group and the Company Developers API to add developers to the company.
You can register a developer using the SAP API Management UI or using the SAP API Management API.
Developers are registered in an organization by creating a profile. Note that the developer email that is included in
the profile is used as the unique key for the developer throughout SAP API Management. Arbitrary attributes can
be added to the developer profile as needed. The attributes are not interpreted by SAP API Management, but can
be of use in custom analytics, custom policy enforcement, and so on.
For example, to register a profile for a developer whose email address is [email protected]:
$ curl -H "Content-type:application/json" -X POST -d \
'{"email" : "[email protected]",
Every app that is registered on SAP API Platform is associated with a developer and an API product. When an app
is registered on behalf of a developer, SAP API Platform generates a "credential" (a consumer key and secret pair)
that identifies the app. The app then must pass these credentials as part of every request to an API product
associated with the app.
The following request registers an app for the developer you created above: [email protected]. When
registering an app you define a name for the app, a callbackUrl, and a list of one or more API products:
$ curl -H "Content-type:application/json" -X POST -d \
'{
"apiProducts": [ "weather_free"],
"callbackUrl" : "login.weatherapp.com",
"name" : "weatherapp"}' \
http://<host:port>/v1/o/{org_name}/developers/[email protected]/apps \
-u myname:mypass
Get the Consumer Key (the API Key) for the App
The credentials for an app, (API product, consumer key and secret) are returned as part of the app profile. An
administrator of an organization can retrieve the consumer key at any time.
The app profile displays the value of the consumer key and secret, the status of the consumer key, as well as any
API product associations for the key. As an admin, you can retrieve the consumer key profile at any time using the
GET method:
$ curl -X GET -H "Accept: application/json" \
http://<host:port>/v1/o/{org_name}/developers/[email protected]/apps/weatherapp/k
eys/HQg0nCZ54adKobpqEJaE8FefGkdKFc2J \
-u myname:mypass
Setting approval type to manual enables you to control which developers can access the resources protected by
API products. When API products have key approval set to manual, consumer keys must be explicitly approved.
Keys can be explicitly approved using the following method call:
$ curl -X POST -H "Content-type:appilcation/octet-stream" \
http://<host:port>/v1/o/{org_name}/developers/[email protected]/apps/weatherapp/k
eys/HQg0nCZ54adKobpqEJaE8FefGkdKFc2J?"action=approve" \
-u myname:mypass
Sample Response
{
"apiProducts" : [ {
"apiproduct" : "weather_free",
"status" : "approved"
} ],
"attributes" : [ ],
"consumerKey" : "HQg0nCZ54adKobpqEJaE8FefGkdKFc2J",
"consumerSecret" : "1eluIIdWG3JGDjE0",
"status" : "approved"
}
The association of an API product with a consumer key also has a status. For API access to be successful, the
consumer key must be approved, and the consumer key must be approved for the appropriate API product. The
association of a consumer key with an API product can be approved as follows:
$ curl -X POST -H "Content-type:application/octet-stream" \
Note
API product settings are enforced by matching policies, such as VerifyAPIKey, OAuthV2, and Quota. Until
those policies are attached to API proxies, API products and quotas will not be enforced by SAP API
Management.
For API products to be enforced, one of the following policy types must be attached to the API proxy flow:
• VerifyAPIKey: Takes a reference to an API key, verifies that it represents a valid app, and matches the API
product. See Enforce access control using VerifyAPIKey for more.
• OAuthV1, “VerifyAccessToken” operation: Verifies the signature, validates an OAuth 1.0a access token and
“consumer key”, and matches the app to the API product. See Authorize requests using OAuth 1.0a for more.
• OAuthV2, “VerifyAccessToken” operation: Verifies that the OAuth 2.0 access token is valid, matches the
token to the app, verifies that the app is valid, and then matches the app to an API product. See Authorize
requests using OAuth 2.0 for more.
• GetAPIProduct: Enables policies to use API product metadata without necessarily verifying a token.
Once policies and API products are configured, the following process is executed by SAP API Management:
1. A request is received by SAP API Management and routed to the appropriate API proxy.
2. A policy is executed that verifies the API key or OAuth access token presented by the client.
3. SAP API Management resolves the API Key or access token to an app profile.
4. SAP API Management resolves the list (if any) of API products associated with the app.
5. The first API product that matches is used to populate Quota variables.
6. If no API product matches the API key or access token, then the request is rejected.
7. SAP API Management enforces URI-based access control (environment, API proxy, and URI path) based on
the API product settings, along with Quota settings.
SAP API Management Analytics Services collects and analyzes a wealth of information that flows through APIs.
This information is gathered, analyzed, and provided to you immediately, in real time. How is your API traffic
trending over time? Who are your top developers? When is API response time fastest? Slowest? Are you
attracting more developers?
The answers to questions like these help you improve your APIs, attract the right app developers, troubleshoot
problems, and, ultimately, make better business decisions related to your API program.
Let's say your API has gained wide adoption. It's popular. You have attracted a number of talented, creative app
developers and people are downloading and installing their apps. Obviously, the API team is very interested in how
the API is performing, how it's being used, and how to plan for improvements.
To plan those improvements, the API team needs to know as much as they can about how the API is used in the
real world. How is it performing? Who is using it? What are the traffic patterns? They need insight. They need to
know:
• What are our top apps? You need to know who/which apps are using your API.
• Who are our best app developers? Your best users and developers might be operating with you across
multiple apps and devices, such as website, mobile apps, video game consoles, and tablets.
• Which API methods are most popular? Your API is a product; you want to understand its usage to help pivot
your business and make future investment decisions.
• How much API capacity will be needed next year? Capacity planning is difficult. What if your API goes viral
and you have millions of users? You need trending usage data to help make these decisions. In this context,
you want to see indicators in the trend charts like the number of requests (the load hitting the backend
systems), volume of data (especially for API responses), and so on.
• Why is the API down? There’s probably not one thing to tell you why an API is down, but the shape of your
graphs can help. Do your charts show catastrophic failure or a slow lead-in to failure?
Through a continual process of collecting, analyzing, and visualizing API metrics, Analytics Services helps your
API team act to improve their APIs. Out-of-the-box, Analytics Services supports and encourages this pattern of
collect, analyze, visualize, and act.
Analytics Services collects and analyzes a broad spectrum of data that flows across APIs. For example, while your
API is deployed, the analytics system is constantly counting and analyzing metrics like the number of messages
received, number of developers, response times, errors, number of apps in use, request size, and many others.
For a good introduction to metrics and how you can use them, see Use the analytics API to measure API program
performance. For a complete listing of metrics, see Analytics Dimensions and Metrics.
You've stored and collected metrics on system performance, you've collected error logs, you've collected user
data, and you've collected many other kinds of data related to your business systems and the applications that
run on them. Often this data is collected and stored in data warehouses where it is organized and possibly
analyzed in predictable ways according to traditional models like ETL (extract, transform, load).
With the rapid adoption of APIs and a mobile apps economy, understanding what to measure is less predictable
than it once was. Third-party app developers have access to your APIs. Users are on the go. They have smart
phones, tablets, and other mobile devices. Some may never use a browser. In this rapidly shifting environment,
you need to know exactly how, when, and where they are interacting with your APIs. You need to know how your
APIs are performing right now, in real time.
SAP API Management encourages API teams to put analytics up front. Think of analytics as your API's peer, as an
integral part of your API program from the beginning, not as something you consider or decide to add later in your
API program.
Analytics can provide key information at the beginning of your API program to help you improve your API and the
experience of app developers who use it. As your API program matures, analytics lends insight that can inform key
business decisions.
Analytics Services provides several visualization tools, including the Dashboard, custom reports and tools that
visualize trends in API proxy performance. For now, let's take a quick look at three of these tools: the
Dashboard, proxy resource performance view, and custom reports.
The Dashboard
The analytics Dashboard gives an overall view of your entire API program. You can toggle the dashboard between
the API program view, which gives you a sense of overall API performance, and API top performer view, which tells
you about your top performing APIs, apps, developers, and API products. You can select a time interval (hour,
day, week, month) over which the data is plotted or specify a custom timespan. You can also mouse over any
point on a plot to see in greater detail what was happening at that point.
You also can track performance metrics for individual URIs (resources) for a specific API proxy. This view lets you
plot trends in traffic, response time, and other metrics for each individual resource.
Custom reports
The custom report feature lets you select, combine, filter, and drill down into specific API metrics. You can
generate reports that contain the exact data that you want to see. Reports can be viewed in the UI, exported to
CSV files. You can schedule reports to be generated daily and emailed to you or to others. In addition, you
can create your own analytics dashboard and populate it with custom reports that you select.
Using the Analytics Services API, you can access a wide variety of operational and business data that flows across
your APIs. For example, using REST calls, you can determine which APIs are performing well or poorly, which
developers are delivering the highest value traffic, and which apps are causing the most issues for your backend
services.
Info
The analytics dashboard is implemented using the REST API.
You can use the REST API when you need to automate certain analytics functions, such as retrieving metrics
periodically using an automation client or script. You can also use the API to build your own visualizations in the
form of custom widgets that you can embed in portals or custom apps. The API can also be used to provide
custom analytics to certain app developers or communities of app developers.
Here's an example analytics REST API call:
$ curl
http://<host:port>/v1/o/{org_name}/environments/test/stats/apis?"select=sum(message
_count)&timeRange=8/24/2013%2000:00~9/25/2013%2000:00&timeUnit=day" \
-u myname:mypass
This call tells you how many request messages were received on a daily basis by all API proxies between
8/24/20xx and 9/25/20xx. The response provides a snapshot of the request message throughput to all APIs for
traffic received between 8/24/20xx and 9/25/20xx
To read all about the REST API for analytics, see Use the analytics API to measure API program performance.
When you think of app developers as your customers, you'll want to make sure they have the tools and
information available to them to make the best use of your API. Ultimately, you want the people who use their
apps (and your products and services) to be happy.
• Performance: Is the API slow right now? Which API methods are typically slow or slow at the moment?
• Availability: Is the API up or down right now? When will the API be back up? Why was the API down?
• Quota: Does your API have a quota? And as the app developer, how am I doing against the quota? Am I
violating the quota?
You can also create custom reports and share them with your app developers. For more information, see Build
custom reports.
Finally, the analytics REST API can be made available to selected app developers. This API lets them access
analytics data for a wide array of metrics. See Use the analytics API to measure API program performance.
All Organization Administrators are automatically subscribed to receive daily analytics summary reports through
email.
Users in the Organization Administrator role can opt in and out of receiving daily analytics reports in the
management UI. Select username > User Settings, and select or deselect the Receive daily analytics summary
report option.
Organization Administrators can also use the /stats/preferences/dailysummaryreport API to unsubscribe (opt
out) from receiving daily analytics reports, or subscribe (opt in).
For example, to opt out, use:
https://<host:port>/v1/organizations/{org}/stats/preferences/reports/dailysummaryrepor
t?optin=false
You can use Edge APIs to export and import custom reports from one org environment to another. This useful
technique lets you reuse custom report designs that you like in different orgs and environments. Furthermore,
you can store the design (a simple JSON text file) in your CSV.
From the app developer to the business owner, API analytics help everyone improve.
• API Team - The API team is tapping into internal systems to create interesting APIs. The API team wants to
know how the API program is doing overall, how individual APIs are doing, and how to improve their APIs.
• App Developers - By sharing analytics information with app developers, you get better apps. These
developers are innovating with your API and building creative apps that help drive revenue to your enterprise.
Analytics help app developers know how their apps are doing and how much they are contributing to the
bottom line of your enterprise. App developers want to know how they can improve their apps. Ultimately,
everyone wants happy end users.
• Ops Team - Equally, the operations team wants to understand traffic patterns and anticipate when to add
backend resources or make other critical adjustments.
• Business Owner - The business owner wants to see how her API investment is paying off and where to invest
API dollars in the future. Ultimately, the business owner wants to improve her business.
API Dashboards
These dashboards highlight invaluable information about your API's health and performance.
• API Proxy Performance
API Proxy Performance tracks metrics like latency, API proxy errors, transactions per second and cache
errors.
Developer Dashboard
These dashboards help you understand your API traffic patterns and adoption from multiple perspectives.
• Developer Engagement
The Developer Engagement dashboard tells you which of your registered app developers are generating the
most API traffic.
• Business Transactions
Business Transactions tracks specific patterns in your API traffic and shows correlations between patterns
from different API proxies.
The Custom Reports tool and related dashboards let you generate and view reports based on metrics and
dimensions you choose.
• Create Custom Reports
Custom reports allows you to generate plots and charts from a broad range of API metrics including total
response time, traffic flows, errors, cache hits and many others.
• Reports Dashboard
Reports Dashboard allows you to see the results of the customized reports
• Reports
Reports allows you to place up to four custom report dashboards in one page.
Analytics dashboards help you see and detect changes in your API ecosystem at a glance. The ability to see what
has changed over time helps you identify problems and take corrective action quickly.
For a quick overview of Analytics Services, who uses them, and why, see Analytics Services overview.
This topic explains how some of the common features you'll find in all the dashboards. After reading this topic,
you will understand:
• The general layout of all dashboards
• Common features all dashboards share and how to use them
• A few tricks and tips that will help you get the most out of the analytics dashboards
Has there been a sudden spike or drop off in API traffic? Which app developers are most successful? What is the
adoption rate of your API among developers? Which API methods are most popular? The SAP API Platform
Analytics dashboards are designed specifically to answer questions like these.
In the background, SAP API Management collects information as data passes through your APIs. The dashboards
provide a powerful way to use this data immediately. If you see something of interest in a graph or chart, an
anomaly or sudden change, you can then drill deeper to uncover as much detail as you require. If you notice that a
particular developer is experiencing a lot of errors or a sudden drop in traffic, you can contact that developer
proactively. Dashboards give you insight into your APIs that allows you to take action.
Yes, many dashboards let you select which metrics to analyze, date ranges, data aggregation intervals, and many
other variables. If the built-in dashboards do not suit your needs, you can create custom reports, which are
dashboards you create by selecting the analytic dimensions and metrics that you wish to analyze. Custom reports
let you "drill down" into your API's analytic data until you achieve the granularity you require.
Most of the Analytics dashboards are organized and function much like the one below. If you understand how to
use this dashboard, you'll be comfortable navigating the others.
• Data range and aggregation settings - Let you select the of dates for which to display data and the
aggregation or "granularity" of data to display.
• Graph syles - All dashboards include one or more graphical charts, including line graphs, bar graphs, and pie
charts.
Note
When you select a smaller aggregation interval the larger the dataset the dashboard is working with.
Performance tends to increase when you select a larger aggregation interval. For example, performance
is greater if you select By Day rather than By Minute.
Dashboards have a set of common features, including time range and data aggregation settings, view togbgles,
choose and drag zooming on charts, mouse-over hover for more details on charts and other regions, and
Note
When you select a smaller aggregation interval the larger the dataset the dashboard is working with.
Performance tends to increase when you select a larger aggregation interval. For example, performance
is greater if you select By Day rather than By Minute.
Here's another dashboard that includes additional features that you'll see in some other dashboards:
• Refresh button - Updates the dashboard with the latest data.
• Export data to a file - Select the data format from the Export menu.
• Feature selections - Lets you show or hide certain features of the dashboard like investigating anomolies and
showing moving averages.
• Dropdown menu for metric selection - Let's you pick the data dimension that you wish to plot.
• Plot selectors - Lets you select which set of data you wish to plot. In the example below, you can select which
API proxy you wish to plot.
In addition to the Investigate Anomalies checkbox, there are two checkboxes displayed for the APIs on the API
Proxies page or for an API on its detail page.
Check this checkbox to view a moving average for the Select this checkbox (on the API Proxies page) to
API. You can check this checkbox for multiple APIs view the number of times that the moving average for
to view a moving average that includes the set of the API exceeded the +-20% limit.
these APIs. A moving average is a series of averages
taken over sucessive subsets of a complete set of
data. It's especially useful in viewing trends. The
moving average is displayed as a band whose limits
are +-20% of the calculated moving average data
points.
When an analytics report illustrates an average, as well as minimum and maximum values, we display an
accompanying dispersion box plot, as called out in the custom report below.
At a glance, a dispersion box plot enables you to see the central tendency and dispersion of your data. A
dispersion box plot surfaces the five key numbers when it comes to illustrating averaged analytics data:
The SAP API Management dashboard is the first thing you see when you log in to SAP API Management. It gives
you end-to-end visibility to monitor, measure, and manage the success of your API program.
The SAP API Management dashboard includes three views:
• Proxy Traffic - Monitors how your APIs are growing, the engagement of your developers, and the rates of
developer adoption.
• Developer Engagement - Gives a quick sense of how developers are engaged with your APIs.
• Developer Apps - Breaks down API traffic by developer app. Shows you which apps are receiving the most
traffic.
To go to this dashboard at any time, select Dashboard from the main SAP API Management menu.
Metric Description
API traffic All the API traffic for an organization over the
selected period of time. Traffic, also called
"throughput", represents the number of API requests
and responses seen by an API organization.
Notice that the details chart also identifies and lists statistics for the APIs that have the most and least traffic and
most and least errors over the selected period.
The API Proxy Performance dashboard tracks how much time API proxies spend processing requests and
responses. This dashboard lets you visualize the network latency between SAP API Management and backend
servers.
Traffic
Metric Description
Total Traffic The total number of API requests received by SAP API Management for an
API environment in an organization.
Traffic Success The total number of requests that resulted in a successful response. Error
responses do not count.
Traffic Errors The total number of all API requests that are unsuccessful, that is, the
request does not deliver a response as desired by the end user.
Metric Description
Average Response Time The average of the Total Response Time measured for all API calls made to
an SAP API Management organization environment. The Total Response
Time is the amount of time it takes for an API call to SAP API Management
to return (in milliseconds).
Or, put another way, total response time is the time measured from when an
entire API call is received on SAP API Management to the time SAP API
Management begins sending a response back to the client app.
This chart measures the average for all proxies. For individual proxies, see
the Average Response Time by Proxy chart below.
Average Proxy Response Time This value is calculated as the average of the Total Response Time minus
the Target Response Time for all API calls made to an SAP API Management
organization environment.
It's basically a measure of how much time the API calls spend flowing
through SAP API Management itself (in milliseconds).
Average Target Response The average number of milliseconds that it takes from the point the last
Time byte of a request is sent from SAP API Management to a backend target to
the time SAP API Management receives the last byte of the response.
It's basically measuring how much time the API call spends on the target
system.
<Proxy name> For the specified API proxy, the number of recorded API requests and
responses.
• Traffic by Proxy
Metric Description
<Proxy name> For the specified API proxy, the number of recorded API requests and
responses.
Metric Description
<Proxy name> For the specified API proxy, the average of the Total Response Time
measured for all API calls made to an SAP API Management environment.
The Total Response Time is the amount of time it takes for an API call to
SAP API Management to return (in milliseconds).
Hover over the graph to see the total amount of time spent on the proxy
side and the target side, as well as the average.
You can view metrics for all proxies or drill into specific proxies using the Proxy dimension dropdown menu at the
top of the dashboard.
Choose this icon to sort the selected metric:
The Target Performance dashboard helps you visualize traffic patterns and performance metrics for API proxy
backend targets.
• Traffic by Target
Metric Description
All Targets Traffic Measures the total amount of traffic that passes from SAP API
Management to all backend targets.
<Target name> Measures the total amount of traffic that passes from SAP API
Management to the specified backend target.
Metric Description
Total Traffic Measures the total amount of traffic that passes from SAP API
Management to all backend targets. Same as All Targets Traffic.
Success The total number of all requests to backend targets that are unsuccessful
(that do not return an error).
• Response Time
Metric Description
Average Time The average of the Total Response Time measured for all API calls made to
an SAP API Management organization environment. The Total Response
Time is the amount of time it takes for an API call to SAP API Management
to return (in milliseconds).
Or, put another way, total response time is the time measured from when an
entire API call is received on SAP API Management to the time SAP API
Management begins sending a response back to the client app.
Average Target Time The average number of milliseconds that it takes from the point the last
byte of a request is sent from SAP API Management to a backend target to
the time SAP API Management receives the last byte of the response.
It's basically measuring how much time the API call spends on the target
system.
Average Proxy Time This value is calculated as the Total Response Time minus the Target
Response Time.
It's basically a measure of how much time the API call spends flowing
through SAP API Management itself (in milliseconds).
• Target Errors
Metric Description
Total Errors Measures the total number of errors sent from backend targets to SAP API
Management.
3XX Errors Measures the total number of HTTP 3XX sent from backend targets to SAP
API Management.
4XX Errors Measures the total number of HTTP 4XX errors sent from backend targets
to SAP API Management.
5XX Errors Measures the total number of HTTP 5XX sent from backend targets to SAP
API Management.
Metric Description
Total Payload Size The total payload size for all requests and responses between SAP API
Management and backend targets.
Request Payload Size The total payload size for all requests sent from SAP API Management to
backend targets.
Response Payload Size The total payload size for all responses sent from backend targets to SAP
API Management.
You can view metrics for all proxies or drill into specific proxies using the Target IP dimension dropdown menu at
the top of the dashboard.
This dashboard uses standard controls, like the date and data aggregation selectors, hovering over graphs for
more context, and so on.
The Traffic Composition dashboard measures the relative contribution of your top APIs, apps, developers, and
products to your overall API program.
Use the report to detect business problems such as lower traffic trends or diminishing contribution from key apps
and developers. Based on this data, you can decide what corrective action to take. You can also get early
notification of new entities that contribute to API traffic, and take actions to respond — for example, you can
determine which new developers are highly contributing and include them in nurturing programs.
This dashboard has two measurement modes, which you select with the Overview and By Dimension buttons.
Metric Description
Overview Gives you a quick glance at traffic patterns for proxies, developer apps,
products, and developers. For example, use this view to see which proxy,
app, product, or developer is generating the most traffic.
By Dimension Let's you drill in to see a more detailed view of proxy, developer app,
product, and developer traffic.
Choose Overview to display this mode. This mode presents a set of straight-forward graphs showing traffic
patterns proxies, developer apps, developers, and products.
The following figure shows part of the traffic composition overview page:
Metric Description
Top 10 Proxies Traffic Shows the top 10 proxies measured by API traffic.
Top 10 Apps Traffic Shows the top 10 developer apps measured by API traffic.
Top 10 Products Traffic Shows the top 10 products measured by API traffic.
Top 10 Developers Traffic Shows the top 10 developers measured by API traffic.
2. Select the dimension instance to examine. For example, if the dimension is Developers, select a developer from
the dropdown list, or select All to see metrics on all developers.
If you select All for a dimension, the dashboard offers charts that compare all entities together. For example, the
Traffic by Dimension chart compares API proxy traffic for all API proxies in the organization.
Charts you will see in this mode include:
• Traffic composition
• Traffic by dimension
• Top 10 monthly composition
• Traffic composition
Shows the traffic for all entities of the selected dimension or all entities combined over the selected time interval.
All Dimensions Traffic Shows the traffic for all of the selected dimension in one chart. Dimensions
can include API proxies, developer apps, developers, or products.
Use the dropdown menus to select (a) dimensions to examine (proxies, developer apps, developers, or products),
and (b) specific entities to measure (either a specific entity like a proxy, or all proxies, for example).
This dashboard uses standard controls, like the date and data aggregation selectors, hovering over graphs for
more context, and so on.
The Business Transactions Dashboard lets you monitor and visually compare traffic for specific API patterns
across multiple API proxies. This information helps you understand changes in API traffic that might be caused by
specific business, marketing, or partner events.
For example, suppose that your marketing team hosts a program that drives customers to a specific site. The URI
pattern for that site will experience an increase in traffic, giving the team a way to measure the impact of the
program in real time.
Metric Description
Error Rate The fraction of all API requests that are unsuccessful,
that is, the request does not deliver a response as
desired by the end user.
Average Data Exchange The size of request and response. That is, the amount
of data that is transferred in both directions as a
request for an API and as a response that is
generated and delivered to the calling entity.
Patterns begin with a forward slash and can include the asterisk (*) wildcard as part of the pattern.
For example, given a proxy base path of /v1/inventory and resource paths of:
• /1
• /abc/123/dec
• /abc/456/dec
This dashboard uses standard controls, like the date and data aggregation selectors, hovering over graphs for
more context, and so on.
The Cache Performance dashboard lets you see at a glance the value of your SAP API Management cache. The
dashboard helps you visualize the benefit of the cache in terms of lower latency and reduced load backend
servers.
For information about cache management, see Manage caches for an environment.
Metric Description
Average cache hit rate The rate of calls hitting the cache measured against
total API traffic.
All cache hits The sum of calls that hit the cache.
Average time with cache The average amount of time for an API call when it
hits the cache.
Average time without cache The average amount of time for an API call when it
does not hit the cache.
Cache improvement Compares the average time with cache and average
time without cache, giving you an idea of the overall
effect of the cache on API performance.
Cache hits by app Sum of calls hitting the cache broken down by
developer app.
You can measure cache performance for all API proxies in your organization, or you can select individual ones.
The Latency Analysis dashboard can alert you to any latency issues your API proxies may be experiencing. It
displays latency measurements down to the window of a minute, highlighting the median, 95th percentile, and
99th percentile values.
The median value tells you the point at which half of your traffic is experiencing latency that is less than this value
and half of your traffic is experiencing latency that is greater than this value. For example, if the median response
time latency for your selected API proxy is 62 ms, it means that half of the responses from this API proxy take less
than 62 ms. It also means that half of the responses from this API proxy take more than 62 ms.
The 95th percentile and 99th percentile values tell you the point at which 95% and 99% of your traffic is
experiencing latency that is less than these values. Or rather more importantly, it can point out outlying behavior,
telling you that 5% and 1% of your traffic is experiencing latency values that are out-of-range.
Metric Description
Response Time Total number of milliseconds it took to respond to a call. This time
includes the API proxy overhead and your target server time.
Target Response Time Number of milliseconds it took your target server to respond to a call. This
number tells you how your own servers are behaving.
Request Processing Latency Number of milliseconds from the time when a call reaches the selected
API proxy to the time when SAP API Management sends the call to your
target server.
Add the request and response latencies to calculate the final overhead the
API proxy added to the call.
Response Processing Latency Number of milliseconds from the time when the API proxy receives your
target server’s response to the time when SAP API Management sends
the response to the original caller.
Add the request and response latencies to calculate the final overhead the
API proxy added to the call.
Select the API proxy for which you want to display latency values:
This dashboard uses standard controls, like the date aggregation selector, hovering over graphs for more context,
and so on. To learn more, see Using the analytics dashboards section for more information.
The Developer Engagement dashboard tells you which of your registered app developers are generating the most
API traffic. For each of your developers, you can find out who is generating the most API traffic and the most
errors. For example, if a particular developer's app is generating a lot of errors relative to other developers, you
can pro-actively address the problem with that developer.
• Engagement
Metric Description
Total Developers The total number of developers associated with APIs deployed to an
organization.
Developers with Apps The total number of developers associated with apps in an organization.
Active Developers The number of developers generating any amount of API traffic.
Developers may exist in the organization and have apps, but if their apps
are not making any API calls, they are not active.
Highly Active Developers The number of developers generating API traffic exceeding 50
transactions per second.
• Active Developers
"Active developers" means the number of developers generating any amount of API traffic. Developers may
exist in the organization and have apps, but if their apps are not making any API calls, they are not active.
Proxy Name The name of the API proxy associated with the app.
Developer Email The email address of the developer who registered the app.
Traffic The amount of traffic generated by the app for the selected time period.
TPH The transactions per hour generated by the app for the selected time
period.
Errors The total number of errors generated by the app for the selected time
period.
Error Rate The error percentage calculated by dividing total errors by total traffic for
the selected time period.
Actions Choose the Analyze button to see more details about an app.
Proxies used by <App Name> Measures all APIs that have traffic generated by the selected app.
Traffic level of other apps Measures the API traffic flowing through all apps using the same set of APIs
using the same proxies as the currently selected app.
Other Apps by Developer Measures other apps generating traffic registered by the same developer as
the developer of the selected app.
Other Apps using the same Measures other apps, from the same developer or not, that use the same
Proxies set of APIs used by the selected app.
You can view metrics for all proxies or drill into specific proxies using the Metric dropdown menu at the top of the
dashboard.
This dashboard uses standard controls, like the date and data aggregation selectors, hovering over graphs for
more context, and so on
Custom Report
A custom report dashboard is a dashboard that lets you visualize API analytics data from a previously created
custom report. A custom report is a way to specify precisely what you want to measure across your API program.
For instance, you can measure all API traffic generated from a specific client IP address.
Recommendation
You can arrange up to four custom report dashboards in a single custom reports dashboard.
Custom report dashboards are similar in look and feel to other dashboards; however, the data that is displayed
depends on which metrics and drilldown dimensions you selected when you created a corresponding custom
report. See Custom reports dashboard for details.
1. Choose Analytics in the main menu. The landing page lists all the available custom reports.
• Dispersion charts
Shows the range of values over the selected time period for certain metrics.
The Custom Reports dashboard lets you place up to four custom report dashboards on one page. This dashboard
is intended to give you a "real time" view of your custom report metrics. The time-scale for this dashboard ranges
from 5 minutes to one hour. The dashboard can include any custom reports that you previously created —
including reports that use custom variables, drill-downs, metric correlations, and filters.
The data displayed in this dashboard depends on the selected custom reports. You can pick from any custom
reports that were previously created for your organization.
• Select Custom Reports Dashboard from the Analytics menu to view and configure the custom reports
dashboard. Use the dropdown menus to select up to four custom reports to add to the dashboard. Choose
the checkmark to add the selected report.
Note
Custom dashboard configurations are persisted as cookies. This means that each user in your
organization can have a different custom report dashboard instance. It also means that each user can
maintain different instances from browser to browser.
• Choose a report name to display the full custom report dashboard. To change a report, select the Edit icon
next to any report name:
By adding custom reports, you can create a set of charts that provide insight into every aspect of your API
program.
8. Choose your drilldown dimensions, such as an SAP API Platform API Proxy. Every dimension you add (by
choosing + Drilldown) constrains the data set used to generate the reports. In effect, you are presenting more
and more specific data with each drilldown.
9. You can further narrow the data displayed by adding filters to your report definition. In the Filter section of the
page, choose + Filter Condition. Select the entity you want to filter on, and construct an expression with the
Operator and Value to include or exclude data in the report. For example, you could add a filter that excludes
data for the weather API proxy or developer [email protected].
Custom metrics
When building a custom report, you can choose from these metrics:
Metric Description
Average transactions per second The number of API requests and resulting responses
per second.
Cache hit The number of API requests that are serviced from
the API platform cache. The request for the cached
data is not forwarded to the backend target.
Request processing latency The length of time it takes the proxy to complete an
end-to-end transaction.
Response processing latency The time it takes for the proxy to process a request
measured in milliseconds.
Target response time The time it takes from when a request is sent from to
the backend target and when it is received from the
backend.
Total response time The total time for an app to receive a response from
an API request. This is the sum of the request
processing latency of the proxy, request processing
latency of the customer endpoint, response
generation latency of the customer end point, and
the response processing latency of the proxy. It also
includes the latency introduced by the network layer
as the request and response can go through multiple
networks before it reaches its destination.
Drilldown Dimensions
You can select from a large number of custom drilldown dimensions. Drilldown dimensions let you specify which
dimensions to measure in your custom report. SAP API Management Analytics collects data on a wide range of
dimensions. In addition, you can also select any custom dimensions that have been created in your organization.
See Analytics reference.
When you have completed building your custom report, the data is populated immediately. The graph is defaulted
to plot the first metric you chose for the tab in your custom report. If you want to see different metrics, or
compare them against each other, follow these steps:
1. Choose the report name to view the graphs of the selected report.
2. Choose the Edit button to edit the display name, dimensions, and measures.
3. Choose Save.
You also have the option to delete a report by choosing the Delete button.
You can export a saved custom report to CSV format. Each report includes an export menu where you can select
a format for the export.
This topic covers the SAP API Management Analytics Services API. SAP API Management records a wide variety
of operational and business data that flows across APIs. The metrics derived from this data are useful for
operational monitoring and business monitoring. Using Analytics Services, you can, for example, determine which
APIs are performing well or poorly, which developers are delivering the highest value traffic, and which apps are
causing the most issues for your backend services.
To help access this data easily, SAP API Management Analytics Services exposes a RESTful API. You can use this
API when you need to automate certain Analytics functions, such as retrieving metrics periodically using an
automation client or script. You can also use the API to build your own visualizations in the form of custom
widgets that you can embed in portals or custom apps.
SAP API Management Analytics Services is based on the concept of 'dimensions'. A dimension is an entity that
SAP API Management automatically monitors and measures. The measurements that Analytics collects are called
'statistics'. In the API, this is abbreviated as /stats.
For this reason, the base URL that you invoke to retrieve statistics for dimensions is the following:
<host>:<port>/v1/o/{org_name}/environments/{env_name}/stats
To create a working request, substitute your organization name for the variable {org_name}. Substitute the
environment name ('test' or 'prod') for the variable {env_name}.
For example:
<host>:<port>/v1/o/apimakers/environments/prod/stats
This is the base URL that you invoke get statistics. To identify the dimension, you need to add the name of the
dimension as a URI variable to this base URL.
The following dimensions are supported:
• /apis
• /apiproducts
• /apps
• /devs
Recommendation
In this topic, you will get metrics for the set of built-in dimensions. The next topic, Analyze API message
content using custom analytics, shows you how to define and work with custom dimensions.
You will find that if you submit one of these requests, you will get the following error:
{
"code" : "Missing select parameter",
"message" : "Missing select parameter",
"contexts" : [ ]
}
Now you need to add a select statement to the base URL for the chosen dimension. You create the select
statement using query parameters.
Query parameters define:
• Metrics: The attribute of the chosen dimension used to calculate statistics.
• Functions: The calculation run against the metric defined for the dimension.
• TimeRange: The time interval over which data should be analyzed.
Note
Data older than six months from the current date is not accessible by default. If you want to access data
older than six months, contact SAP.
Recommendation
For complete reference on these parameters, see Build custom reports.
Let us suppose that you want to get statistics across your API proxies that are deployed in the test environment.
You want to find out how many request messages were received by all API proxies between 8/24/2013 and
9/25/2013. You want to find out a daily count for messages that were received. To do so, you create a select
statement on the/stats/apis resource.
The example below demonstrates who you would construct a request for these statistics. The select statement
defines the function sum for the metric message_count on the dimension apis deployed in the test environment.
Note
The timestamp, 1379548800000, is in Unix timestamp format. There are many Unix timestamp
conversion tools available on the Internet that you can use to decode these timestamps.
To get statistics for other dimensions, specify a different dimension as the URI parameter. For example, you can
specify the apps dimensions to retrieve statistics for consumer apps. The following report shows the total
throughput (messages received) from any apps for the specified time interval:
$ curl
<host>:<port>/v1/o/{org_name}/environments/test/stats/apps?"select=sum(message_coun
t)&timeRange=01/24/2013%2000:00~09/25/2013%2000:00&timeUnit=day" \
-u myname:mypass
----------------------------------------------------------------------------------
{
Note
Statistics can be retrieved for apps only when apps can be individually identified by an API key (also called
a 'consumer key') or by an OAuth access token. Therefore, only use the /apps dimension for APIs that
enforce security policies (API Key or OAuth).
For each dimension, Analytics Services records pre-defined statistics for a set of relevant metrics. Metrics are
attributes of dimensions that can be measured, such as total_response_time and request_size. In the examples
above, you used the metric message_count, which os one of a set of metrics supported by the /apisdimension.
Metrics are specific to each dimension. For example, for the dimension /stats/devs, Analytics Services records
the following metrics message_count, error_count, app_count, user_count. These provide statistics on the
number of messages submitted by the developer's app(s), the number of errors generated by the developer's
app(s), the number of apps the developer has registered, and the count of app end users associated with the
developer's app(s).
Because these metrics are available out-of-the-box, they are referred to as "computed metrics" or "pre-
aggregated metrics". Analytics Services provides you with a 'menu' of pre-computed metrics for each dimension.
Since the metrics are already computed, you can retrieve large data sets very quickly.
Analytics Services also defines a set of dimensions that have no associated pre-computed metrics--for those
dimensions, metrics are calculated on demand, when you make a request to Analytics Services.
Examples of dimensions whose statistics are computed on-demand are:
• /stats/access_token: Statistics based on OAuth access tokens presented by client apps.
• /stats/client_id: Statistics based on API keys presented by client apps.
• /stats/client_ip: Statistics based on the IP addresses of client apps.
• /stats/target_url: Statistics based on the URL of the target backend service.
• /stats/request_verb: Statistics based on the HTTP verb of the request message.
In this example, you use a dynamic dimension: target_url. Your goal is to determine how many requests to
backend services result in errors. The report that you generate would be useful when communicating with the
team responsible for backend services or when performing root-case analysis when an app developer reports
issues when calling your APIs, and you suspect that the issue is related to failing backend services.
The is_error metric defines any message that results in an HTTP 4xx or 5xx HTTP status code. The sample
request below defines the dimension target_url, the function count, and the metric is_error. The response will
detail how many errors were returned by all target URLs called by API proxies deployed in the 'test' environment:
$ curl
<host>:<port>/v1/o/{org_name}/environments/test/stats/target_url?"select=count(is_e
rror)&timeRange=8/08/2013%2000:00~9/15/2013%2000:00&timeUnit=week \
-u myname:mypass
----------------------------------------------------------------------------------
{
"environments" : [ {
"dimensions" : [ {
"metrics" : [ {
"name" : "count(is_error)",
"values" : [ {
"timestamp" : 1344211200000,
"value" : "44.0"
}, {
"timestamp" : 1344816000000,
Many times when getting statistics, you only want to get results for a subset of the total set of metrics. Usually,
you need to get the results for the "top 10", for example, the "top 10 slowest APIs", the "top 10 most active apps".
You can do this using the topk query parameter as part of the request.
For example you may be interested to know who your top developers are, measured by throughput, or what your
worst performers (i.e., 'top slowest') target APIs are by latency.
The topk (meaning 'top k' entities) enables reporting on the entities associated with the highest value for a given
metric. This enables you to filter statistics for a list of entities that exemplify a particular condition. For example, to
find which target URL was the most error prone over the last week, the topk parameter is appended to the
request, with a value of 1.
In the example below
$ curl
<host>:<port>/v1/o/{org_name}/environments/test/stats/target_url?"select=count(is_e
rror)&timeRange=8/08/2013%2000:00~8/15/2013%2000:00&timeUnit=week&sortby=count(is_e
rror)&topk=1" -u myname:mypass
Sample Response
{
"environments" : [ {
"dimensions" : [ {
"metrics" : [ {
"name" : "message_count",
"values" : [ {
"timestamp" : 1345420800000,
"value" : "14.0"
}, {
"timestamp" : 1344816000000,
Filtering results
For greater granularity, you can filter results to enable 'drill-down' on a dimension of interest. When using filters,
you must use dynamic dimensions as filter properties. Computer metrics (/apis, /devs, /apps, etc.) cannot be
used as filters.
For example, let's suppose that you need to retrieve a count of errors from backend services filtered by the HTTP
verb of the request. Your goal is find out how many POST and PUT requests are generating errors per backend
service. To do so, you use the dimension target_url along with the filter request_verb.
$ curl
<host>:<port>/v1/o/{org_name}/environments/test/stats/target_url?"select=count(is_e
rror)&timeRange=8/08/2013%2000:00~8/15/2013%2000:00&timeUnit=week&filter=(request_v
erb&20in&20'POST','PUT')" \
-u myname:mypass
Paginating results
In production environments, some request to the Analytics Services API return very large data sets. To make it
easy to display large data sets in the context of a UI-based application, the API natively supports pagination.
To paginate results, use the offset and limit query parameters.
For example, the following request would be likely to return a large data set, since it retrieves metrics for all errors
on all APIs in the product environment for the last week.
The following API calls are made by the dashboards in the Management UI. They are provided here for your
reference.
$ curl
<host>:<port>/v1/o/{org_name}/environments/test/stats/?'select=message_count&timeRa
nge=7/14/2012%2013:00~8/13/2012%2013:00&sort=ASC&sortby=message_count&timeUnit=hour
' -u myname:mypass
$ curl
'<host>:<port>/v1/o/{org_name}/environments/test/stats/apis?select=message_count,er
ror_count,&timeRange=7/14/2012%2013:00~8/13/2012%2013:00&sort=ASC&topk=5&sortby=mes
sage_count&timeUnit=hour' -u myname:mypass
$ curl
'<host>:<port>/v1/o/{org_name}/environments/test/stats/apiproducts?select=message_c
ount,app_count,developer_count&timeRange=7/14/2012%2013:00~8/13/2012%2013:00&sort=A
SC&topk=5&sortby=app_count&timeUnit=hour' -u myname:mypass
$ curl
'<host>:<port>/v1/o/{org_name}/environments/test/stats/apps?select=message_count,er
ror_count,user_count&timeRange=7/14/2012%2013:00~8/13/2012%2013:00&sort=ASC&topk=5&
sortby=user_count&timeUnit=hour' -u myname:mypass
In addition to the analytics available online through SAP API Management, all organization administrators are
automatically subscribed to receive daily analytics summary reports through email. You can unsubscribe (opt
out) of receiving daily analytics reports through a link in the actual report that is emailed to you. You can also opt
in or opt out of daily summary reports using these API calls:
Opt out of receiving a daily summary report:
$ curl -u myname:mypass
<host>:<port>/v1/o/{myorg}/stats/preferences/reports/dailysummaryreport?optin=false
Opt in to receiving a daily summary report:
$ curl -u myname:mypass
<host>:<port>/v1/o/{myorg}/stats/preferences/reports/dailysummaryreport?optin=true
Retrieve list of users who have opted in or opted out:
$ curl -u myname:mypass
<host>:<port>/v1/o/{myorg}stats/preferences/reports/dailysummaryreport/users
Introduction
This topic presents a tour demonstrating how to use policies to extract custom data from a request and feed that
data to the SAP API Platform Analytics system. Then, we show how to create a custom analytics report based on
that data, which appears as custom dimensions. In addition, this topic explains how to create custom analytics
variables (dimensions) using a UI tool called Solution Builder.
In Use the analytics API to measure API program performance, you learned how to use the RESTful API exposed
by Analytics Services to get statistics on a variety of entities monitored by SAP API Management.
In this topic, you will learn how to use the Analytics Services API combined with Policies to analyze data that is
unique to your app and API traffic. Most of the data that is key to your business is found in the payload content
moving back and forth from apps to your backend services. Using Analytics Services, you can define custom
dimensions that SAP API Management uses to collect, analyze, and provide reports on that data.
This topic demonstrates the usage of custom analytics against the Yahoo Weather API. The goal of the exercise is
to create a custom dimension called location that enables you to collect statistics on the number of requests
received for weather reports for different locations. Once you have defined the custom dimension called location,
you can use the capabilities of the Analytics Services API to retrieve and filter statistics that the SAP API
Management collects. The custom dimension location will also be made available in the Management UI, enabling
you to create reports for this dimension using the API SAP API Platform's UI-based tools.
The Yahoo Weather API returns XML-formatted responses. You request a weather report for particular location
by providing a WOEID, which stand for "where on Earth ID". The WEOID for Palo Alto, CA is 12797282. To get a
weather forecast for Palo Alto, you submit the following request to the Yahoo Weather API:
$ curl http://weather.yahooapis.com/forecastrss?w=12797282
To collect custom analytics, you need to call the API using an API proxy. The API proxy will inspect the request and
response messages from your app to the Yahoo API. You are provided with a pre-configured API proxy in the test
environment of your organization. The API proxy is called weatherapi. You can invoke that API proxy to obtain a
proxied response from the the Yahoo Weather API.
You can invoke the proxied version of the Yahoo Weather API using the following command. As usual, substitute
your organization name on SAP API Management for the variable {org_name}.
$ curl http://{org-name}-{env}.<host:port>/weather/forecastrss?w=12797282
The interesting part of the response message, the weather report and forecast, is shown below. (Note that the
response, except for specifics such as timestamps, is exactly the same between the direct API call to the weather
backend and the proxied API call.)
ExtractVariables policy
The weather response contains potentially valuable information. However, SAP API Management doesn't yet
'know' how to feed this message content into Analytics Services for processing. To enable this, SAP API Platform
provides the ExtractVariables policy, which parses message payloads with JSONPath or XPath expressions and
feeds the content into Analytics Services.
There are many tools available online that you can use to construct XPath expressions for your XML documents.
There also many tools available for JSONPath.
See Extract message content using ExtractVariables.
To extract the information of interest from the weather report in this case, you use an XPath expression. For
example, to extract the value of the city, the XPath expression is:
/rss/channel/yweather:location/@city
Note how this XPath expression reflects the structure of the XML nodes. also, note the prefixyweather is defined
by a namespace:
xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0
To enable the XML message to be parsed properly, you use both the XPath and the namespace definition in the
policy.
You will include this XPath expression in the ExtractVariables Policy. Once the XPath has been evaluated, the
Policy needs a place to store the value that results from the evaluation. For this, the Policy uses variables. You can
Naming restrictions
See the naming restrictions for custom analytics variables in the Creating custom analytics variables with the
Solution Builder section.
• The following naming restrictions apply to custom analytics variables:
• Names cannot be multiple-word (no spaces).
• No quotation marks, underscores, hyphens, or periods.
• No special characters.
Example
The following ExtractVariables Policy configuration demonstrates how you can define these custom variables.
Note that the VariablePrefix is weather, and that each <Variable> tag has a name attribute that maps to the list of
custom variables that you need to have populated. Each variable in turn has an associated XPath expression that
will populate the variable with the appropriate value for each response message.
To create the Policy, under /apiproxy/policies, create a file called ParseWeatherReport.xml with the
following content:
<ExtractVariables name="ParseWeatherReport">
<!-- Parse the XML weather report using XPath. -->
<VariablePrefix>weather</VariablePrefix>
<XMLPayload>
<Namespaces>
<Namespace
prefix="yweather">http://xml.weather.yahoo.com/ns/rss/1.0</Namespace>
</Namespaces>
<Variable name="location" type="string">
<XPath>/rss/channel/yweather:location/@city</XPath>
</Variable>
<Variable name="condition" type="string">
<XPath>/rss/channel/item/yweather:condition/@text</XPath>
</Variable>
<Variable name="forecast_today" type="string">
<XPath>/rss/channel/item/yweather:forecast[1]/@text</XPath>
StatisticsCollector policy
The next step is to create another Policy that reads these values and sends them to Analytics Services for
processing. The StatisticsCollector Policy type is used to do this. In the StatisticsCollector Policy, you define a
Statistic by providing a pointer to each of the custom variables defined in the ExtractVariables Policy. You can also
provide a default value for custom variable, which will be forwarded to Analytics Services if the variables cannot be
resolved on a response. (In the example below, the default values are Earth, Sunny, Rainy, and Balmy.)
Under /apiproxy/policies, create a file called AnalyzeWeatherReport.xml with the following content:
<StatisticsCollector name="AnalyzeWeatherReport">
<Statistics>
<Statistic name="location" ref="weather.location" type="string">Earth</Statistic>
<Statistic name="condition" ref="weather.condition"
type="string">Sunny</Statistic>
<Statistic name="forecast_today" ref="weather.forecast_today"
type="string">Rainy</Statistic>
<Statistic name="forecast_tomorrow" ref="weather.forecast_tomorrow"
type="string">Balmy</Statistic>
</Statistics>
</StatisticsCollector>
To make things work properly, Policies must be attached to the API proxy Flow in the appropriate location. In this
use case, the Policies must execute after the response has been received from the Yahoo Weather API and before
the response is sent to the request client. To accomplish this, the Policies must be attached to the ProxyEndpoint
response Flow, so that they will be enforced on outbound response messages, before the response is returned to
the calling client app.
The example ProxyEndpoint configuration below first executes the Policy called 'ParseWeatherReport' to parse
the response message. The ParseWeatherReport evaluates the XPath expressions and populates appropriate
variables. The policy called 'AnalyzeWeatherReport' then forwards those values to Analytics Services.
<ProxyEndpoint name="default">
<Flows>
<Flow name="default">
<Response>
<Step><Name>ParseWeatherReport</Name></Step>
After you have made these changes, you need to import and deploy the API proxy that you have configured.
After you deploy your changes, you need to populate some data in Analytics Services. You can do this by running
the following commands, each of which uses a WOEID for a different geographic location.
Palo Alto:
$ curl http://{org-name}-{env}.<host:port>/weather/forecastrss?w=12797282
Shanghai:
$ curl http://{org-name}-{env}.<host:port>/weather/forecastrss?w=2151849
London:
$ curl http://{org-name}-{env}.<host:port>/weather/forecastrss?w=44418
Wiliamsburg:
$ curl http://{org-name}-{env}.<host:port>/weather/forecastrss?w=2520841
Now that you have populated some data, you can use the RESTful API exposed by Analytics Services to get
statistics on your new custom dimensions, in the same way that you use the API to get statistics on the out-of-
the-box dimensions.
You can also generate custom reports using the Management UI at. You will find that a new dimension called
location is available in the UI for you to use in generating reports.
Note
TimeRange parameter must be modified to include the time interval when data was collected.
In the example request below, the custom dimension is called location. This request builds a custom report for
locations based on the sum of message counts submitted for each location.
As usual, substitute your organization name for the variable {org_name}, and substitute the username and
password for your account on SAP API Management for myname:mypass:
$ curl
<host>:<port>/v1/o/{org_name}/environments/test/stats/location?"select=sum(message_
count)&timeRange=11/19/2012%2000:00~11/21/2012%2000:00&timeUnit=day"
-u myname:mypass
-----------------------------------------------------------------------------------
{
"environments" : [ {
"dimensions" : [ {
"metrics" : [ {
"name" : "sum(message_count)",
"values" : [ {
"timestamp" : 1353369600000,
"value" : "4.0"
} ]
} ],
"name" : "London"
}, {
"metrics" : [ {
"name" : "sum(message_count)",
"values" : [ {
"timestamp" : 1353369600000,
"value" : "19.0"
} ]
} ],
"name" : "Palo Alto"
}, {
"metrics" : [ {
Solution builder lets you create custom analytics variables through an easy-to-use management UI dialog.
Note
You may wish to read the previous section "Parsing payloads using Policies", which explains how the
ExtractVariables and StatisticsCollector policies work hand-in-hand to feed custom variables to the
Analytics system. As you'll see, the UI follows this same pattern, but provides a convenient way for you to
configure things entirely through the management UI. If you wish, try the Yahoo Weather API tutorial
presented previously in this topic using the UI instead of editing and attaching policies manually.
Caution
Naming restrictions for custom analytics variables
o The following naming restrictions apply to custom analytics variables:
Note
The Solution Builder creates new ExtractVariables and StatisticsCollector policies and gives them unique
names. The Solution Builder does not let you go back and change these policies once they are created in a
given proxy revision. If you wish to make changes, you can edit the generated policies directly the policy
editor.
1. Go to the Overview page for your proxy in the SAP API Platform UI.
2. Choose Develop.
3. On the Develop page, select Custom Analytics Collection from the Tools menu. The Solution Builder dialog
appears.
4. In the Solution Builder dialog, you first configure two policies: ExtractVariables and StatisticsCollector. Then,
you configure where to attach those policies.
5. Specify the data you wish to extract:
o Location Type: Select the type of data you wish to collect and where to collect it from. You can select
data from the request or response side. For example, Request: Query Parameter or Response: XML Body.
o Location Source: Identify the data you wish to collect. For example, the name of the query parameter or
the XPath for XML data in the response body.
6. Specify a variable name (and type) that the StatisticsCollector policy will use to identify the extracted data.
You can use any name. If you omit the name, the system selects a default for you.
Note
The name you pick will appear in the Custom Dimensions dropdown menu in the Custom Report builder
UI, as we'll see later in this section.
7. Pick where in the API proxy flow you wish to attach the generated policies ExtractVariables and
StatisticsCollector. For guidance, see "Attaching policies to the ProxyEndpoint response Flow". To make
things work properly, Policies must be attached to the API proxy Flow in the appropriate location. You need to
attach the polices at a stage in the flow where the variables you are trapping are in scope (populated).
8. Choose +Collector to add more custom variables.
9. When you're done, choose Build Solution.
10. Save and deploy the proxy.
This topic discusses how to create custom collections or "aggregates" of SAP API Platform analytics data.
SAP API Management Analytics Services automatically collects a set of pre-computed metrics. You can query this
collected data to discover important information about how your API is performing. For example, the
metric message_count keeps track of how many requests an API receives. Because this data is pre-aggregated
(not mined on demand), it makes for fast processing time. To read more about computed metrics, see Analytics
reference.
If you you have needs that exceed the automatically collected analytics data, you can also create custom
aggregations. When you create a new custom aggregation, you can specify the metrics and dimensions that you
wish to compute, and SAP API Platform collects and stores that data for you in the background, while your API is
being used. Just as with the out-of-the-box pre-computed metrics, custom aggregations make access to the data
much faster and more efficient than it would be to compute and return it on the fly.
You can use any of the four standard Analytics Services functions with any custom aggregate metrics. The
functions aresum, avg, max, and min. For more information on metrics and functions, see Analytics reference.
SAP API Platform provides an API for creating custom aggregations of metric data. A custom aggregate can
include up to three dimensions and five metrics, which you specify in the request payload. Here's an example of
the POST command used to create a custom aggregate:
You can start and stop a custom aggregate's activity. When you stop an aggregation, the stored data up to that
time is not deleted. After stopping an aggregation, you have up to 15 days to reactive it. After 15 days, the stored
data is retained; however, you cannot restart the same aggregate. You need to create a new aggregate in that
case.
When you activate or deactivate an aggregate, there is typically a time lag between when the command is issued
and when it takes effect.
To stop a custom aggregate from collecting data, use this PUT call:
$ curl -H "Content-type:application/json" -X PUT -d \
'{
“status” : “inactive”
}' \
<host>:<port>/v1/o/stats/customaggregates/{custom_agg_display_name} \
-u myname:mypass
Just as with other SAP API Platform statistical metrics, you can query custom aggregate metrics using
the select query parameter. To drill into an aggregate data set, you simply need to provide the name of the
custom aggregate as another query parameter, t, which specifies the unique name of the aggregate table stored
in the database. For example, the following query returns the sum of response times stored in an aggregate with
the unique name custom_agg_UUID.
$ curl -H "Content-type:application/json" -X GET -d \
<host>:<port>/v1/o/stats/apiproxy?select=sum(response_time)&t="custom_agg_UUID" \
-u myname:mypass
Note
Every aggregate has a unique name expressed by the value of the name attribute that is returned in the
response when you create a new aggregate or retrieve an aggregate or list of aggregates through the
API.The name is a UUID, a string of numbers and letters, which is assigned when the aggregate is created.
In the following example, we simply use "custom_agg_UUID", but an acutal UUID would look something
like this: my_custom_agg_250c1e623-e559-46b5-953e-bb532c245d3e.
For detailed information on using the select parameter to query SAP API Platform statistical dimensions, see
"Dynamic Dimensions".
Just as with other SAP API Management Analytics, you can use the filter query parameter with custom
aggregates. Filtering lets you "drill down" on a dimension. For example, to filter on API proxies that starts with "m":
$ curl -H "Content-type:application/json" -X GET -d \
<host>:<port>/v1/o/stats/apiproxy?select=sum(response_time)&t="custom_agg_UUID" \
&filter=(apiproxy LIKE 'm%') -u myname:mypass
For detailed information using the filter parameter, see "Filtering Results" and "Report Filters".
Data visualization is an important troubleshooting tool. SAP API Management is always collecting and analyzing
data for your APIs, and visualization is the most powerful way to unlock, compare, contrast, and assess that data.
So, let's say you've been hearing from customers (perhaps via support calls, social media sites, or user forums)
that one of your APIs is slow. Visualization can help. Where do you begin?
To discover which API is underperforming, one approach is to compare the average response times of all your
APIs to see if one of them is out of line.
1. Select API Proxies from the APIs menu.
2. In the Performance section of the API Proxies page, select Average Response Time from the Performance
menu.
3. Select a range of dates to evaluate.
4. Select which APIs you wish to evaluate.
5. In the plot, look for sudden spikes or gradual increases in response time.
If you suspect which API is causing a problem, you can create a custom report that includes charts and plots
comparing specific metrics that you select. For example, you can visualize the maximum latency time by app and
resource.
1. Select Custom Reports from the Analytics menu.
2. In the Custom Reports page, choose + Custom Report.
3. Fill out the Custom Report basics, select your sampling rate, and the environment you wish to test.
4. In the Y-Axis Measures section, select Total Response Time and Max for the Aggregate Function:
The new latency report will show you the response times by API and then by each resource within an API. By
combining this information with what you know about your network architecture, you can quickly find issues that
may be related to your infrastructure.
Drill down
You can drill down on the worst performing API (the one with the highest latency).
Now that you know which resource is performing badly, you can examine your network to see if there's a service
issue, or you can add a 3rd dimension like Developer App to see which apps are impacted by this slow resource, or
developer to figure out which developers are impacted by the slow resource.
As you can see, SAP API Platform Analytics Services includes multiple ways to approach a specific problem, and
visualization plays an important role in any troubleshooting process.
As you review your analytics, you may see an entity value of (not set) displayed, including the parenthesis, for
your API Proxies, Product, Developer, and Developer Apps dimensions. This may or may not be an issue.
See below for possible explanations of why you are seeing a (not set) entity.
• You see a (not set) entity for the API Proxies dimension.
This means that a call to an API proxy reached the SAP API Management routers, but was malformed, never
reached the proxy, and the message processor returned a 404 status code with a classification error. This
means that there are some callers that are making malformed calls.
• You see an (not set) entity for the Product dimension entity.
This means that not all of your API proxies and developer apps are using products.
• You see an (not set) entity for the Developer dimension.
This means that some of your traffic is being generated by unregistered developers. This traffic may originate
with an internal-use or public API.
• You see a (not set) entity for the Developer Apps dimension.
This means that some of your traffic is being generated by unregistered apps. This traffic may originate with
an internal-use or public API.
This section provides a list a preconfigured URIs for specific applications of SAP API Management Analytics
Services. The requests below assume the environment is 'prod'. If you require analytics on another environment
(such as 'test'), modify /environments/prod to/environments/test.
API
Requests by API
$ curl -u myname:mypass
https://<host:port>/v1/o/{myorg}/environments/prod/stats/apis?select=sum(message_co
unt)&timeRange=9/24/2012%2000:00~10/25/2012%2000:00&timeUnit=day
Avg. Total Response Time by API
$ curl -u myname:mypass
https://<host:port>/v1/o/{myorg}/environments/prod/stats/apis?select=avg(total_resp
onse_time)&timeRange=9/24/2012%2000:00~10/25/2012%2000:00&timeUnit=day
Max Total Response Time by API
$ curl -u myname:mypass
https://<host:port>/v1/o/{myorg}/environments/prod/stats/apis?select=max(total_resp
onse_time)&timeRange=9/24/2012%2000:00~10/25/2012%2000:00&timeUnit=day
Min Total Response Time by API
$ curl -u myname:mypass
https://<host:port>/v1/o/{myorg}/environments/prod/stats/apis?select=min(total_resp
onse_time)&timeRange=9/24/2012%2000:00~10/25/2012%2000:00&timeUnit=day
Avg. Target Response Time by API
$ curl -u myname:mypass
https://<host:port>/v1/o/{myorg}/environments/prod/stats/apis?select=avg(target_res
ponse_time)&timeRange=9/24/2012%2000:00~10/25/2012%2000:00&timeUnit=day
Max Target Response Time by API
$ curl -u myname:mypass
<host>:<port>/v1/o/{myorg}/environments/prod/stats/apis?select=max(target_response_
time)&timeRange=9/24/2012%2000:00~10/25/2012%2000:00&timeUnit=day
Min Target Response Time by API
$ curl -u myname:mypass
<host>:<port>/v1/o/{myorg}/environments/prod/stats/apis?select=min(target_response_
time)&timeRange=9/24/2012%2000:00~10/25/2012%2000:00&timeUnit=day
Errors by API
Developers
Apps
API Products
API Resources
This topic is a reference. To learn how to use the dimensions and metrics that are detailed in this reference, start
with the Analytics Services overview.
Analytics services exposes APIs for three types of dimensions:
• Dedicated dimensions: Analytics that are computed in aggregate based on pre-defined dimensions and
metrics, with no detailed drill-down available. These are used primarily to populate default dashboards and
operational performance graphs in the management UI.
• Dynamic dimensions: Analytics for a pre-defined set of dimensions that are computed only when you build
custom reports. As is explained below, these require you to specify a function, for example, the average,
minimum value, or maximum value, to calculate metrics against a dimension, such as the response time of an
API proxy.
• Custom dimensions: Analytics that you use to build reports for data that is specific to your business, and
which is not measured by the Analytics above. Custom Analytics require the definition and population of
custom variable as well as requiring a function to be defined. For instructions on building reports for custom
dimensions, see Analyze API message content using custom analytics.
• Virtual dimensions: The Analytics system generates virtual dimensions from the user-agent, timestamp, and
IP associated with each API call. Virtual dimensions are provided out of the box.
Dedicated dimensions
Dedicated dimensions are associated with aggregate, precomputed metrics. For speed and scale, Analytics
Services automatically calculates these metrics. This makes them very simple to use, but limits their flexibility.
For example, functions are not supported against dedicated dimensions because the dimensions have been pre-
aggregated; they have 'built-in' functions. For this reason, dedicated dimensions do not appear as available
options in the Management UI during report creation. Rather, dedicated dimensions are used to generate
operational dashboards in the Management UI. You can access the same dedicated dimensions to build your own
dashboards using the Analytics API.
The 'select' query parameter for dedicated dimensions accepts a metric name but does not support a function
(since the function is already specified for the associated pre-computed metric).
Computed metrics
Computed metrics are pre-defined (metric + function) calculations that are used to generate reports for
dedicated dimensions. Computed metrics enable the system to provide operational analytics in a way that is
highly optimized. Computed metrics are used to populate dashboards in the API management UI.
Metrics
Dynamic Dimensions
Dynamic dimensions are a set of pre-defined dimensions that are not associated with precomputed metrics. The
metrics are computed at the time that you make a request for a report. This provides you with more flexibility to
slice-and-dice the measurements that are recorded by Analytics services.
Dynamic dimensions enable you to specify a function and a raw metric in the select parameter. Dynamic
dimensions are used to generate custom reports.
Example
select=sum(message_count)
or
select=avg(total_response_time)
Note
Dynamic dimensions should not be confused with custom dimensions. Custom dimensions are derived
business-specific message content that is unique to a particular API. Custom dimensions are defined
<host>:<port>/v1/o/{org_name}/environments/{env_name}/stats/client_id?select={funct
ion}({metric})&timeRange={startTime~endTime}&timeUnit
<host>:<port>/v1/o/{org_name}/environments/{env_name}/stats/client_ip?select={funct
ion}({metric})&timeRange={startTime~endTime}&timeUnit
Dynamic dimensions
Virtual dimensions
The Analytics system generates virtual dimensions from the user-agent, timestamp, and IP associated with each
API call. Virtual dimensions are provided out of the box. You cannot create new virtual dimensions. The virtual
dimensions include:
Name Description
City IP address
Country IP address
Timezone IP address
Report Filters
A filter is expressed as a query parameter in an API request to build a report. Filters can be applied to any API
request.
Filter on API proxies with the name books or music:
filter=(apiproxy IN 'books','music')
Filter on API proxies with names that start with "m":
filter=(apiproxy LIKE 'm%')
Filter on response codes that do not start with "m":
filter=(apiproxy NOT LIKE 'm%')
Filter on response codes between 400 and 599:
filter=(responsecode IN '4xx','5xx')
Filter on response code 500:
filter=(responsecode EQ 500)
Filter on metrics for non-error messages:
filter=(is_error EQ 0)
Token Description
in Include in list
eq Equals, ==
like Returns true if the string pattern matches the supplied pattern.
not like Returns false if the string pattern matches the supplied pattern.
similar to Returns true or false depending on whether its pattern matches the
given string. It is similar to LIKE, except that it interprets the pattern
using the SQL standard's definition of a regular expression.
not similar to Returns false or true depending on whether its pattern matches the
given string. It is similar to NOT LIKE, except that it interprets the
pattern using the SQL standard's definition of a regular expression.
and Lets you use 'and' logic to include more than one filter expression. The
filter includes data that meets all the conditions.
Or Lets you use 'or' logic to evaluate different possible filter expressions.
The filter includes data that meets at least one of the conditions.
As a developer working with the SAP API Management, your primary development activities involve configuring
API proxies that function as proxies for APIs or backend services. This section is a reference of all configuration
elements available to you when building API proxies.
If you are learning how to build API proxies, it is recommended that you begin with the topic Build a simple API
proxy.
ProxyEndpoint Configuration Settings for the inbound HTTP connection (from requesting apps to
SAP API Management), request and response flows, and policy
attachments. See ProxyEndpoint.
TargetEndpoint Configuration Settings for the outbound HTTP connection (from SAP API
Management to the backend service), request and response flows, and
policy attachments. See TargetEndpoint.
Resources Scripts, JAR files, and XSLT files referenced by policies to execute
custom logic. See Resources.
Base Configuration Primary configuration settings for an API proxy. See Base
Configuration.
This section explains the configuration files and directory structure of an API proxy.
• Base Configuration.
• ProxyEndpoint
• TargetEndpoint.
• Advanced TargetEndpoint Configuration
• Policies
• Flows
• Resources
Base Configuration
/apiproxy/weatherapi.xml
The base configuration for an API proxy, which defines the name of the API proxy. The name must be unique
within an organization.
Sample configuration:
<APIProxy name="weatherapi">
</APIProxy>
API Proxy
name The name of the API proxy, which must be unique within an N/A Yes
organization. The characters you are allowed to use in the
name are restricted to the following: A-Z0-9._\-$ %.
revision The revision number of the API proxy configuration. You do N/A No
not need to explicitly set the revision number, since SAP
API Management automatically tracks the current revision
of the API proxy.
DisplayName A user-friendly name that may be different from the name N/A No
attribute of the API proxy configuration.
Policies A list of policies in the /policies directory of this API proxy. N/A No
You will normally only see this element when the API proxy
was created using the SAP API Platform management UI.
This is simply a 'manifest' setting, designed to provide
visibility into the contents of the API proxy.
ProxyEndpoint
/apiproxy/proxies/default.xml
The ProxyEndpoint configuration defines the inbound (client-facing) interface for an API proxy. When you
configure a ProxyEndpoint, you are setting up a network configuration that defines how client applications ('apps')
should invoke the proxied API.
The following sample ProxyEndpoint configuration would be stored under /apiproxy/proxies:
<ProxyEndpoint name="default">
<PreFlow/>
<Flows/>
<PostFlow/>
<HTTPProxyConnection>
<BasePath>/weather</BasePath>
<VirtualHost>default</VirtualHost>
</HTTPProxyConnection>
<FaultRules/>
<DefaultFaultRule/>
<RouteRule name="default">
ProxyEndpoint
name The name of the ProxyEndpoint. Must be unique within the N/A Yes
API proxy configuration, when (in rare cases) multiple
ProxyEndpoints are defined. The characters you are allowed
to use in the name are restricted to the following: A-Z0-9._\-
$ %.
PreFlow Defines the policies in the PreFlow flow of a request or N/A Yes
response.
Flows Defines the policies in the conditional flows of a request or N/A Yes
response.
PostFlow Defines the policies in the PostFlow flow of a request or N/A Yes
response.
HTTPProxyConnection Defines the network address and URI path associated with the API proxy
BasePath A required string that uniquely identifies the URI path used by / Yes
SAP API Management to route incoming messages to the
proper API proxy.
The BasePath is a URI fragment (for example/weather)
appended to the base URL for an environment (for
example, http://apifactory.net) by a requesting
client.
BasePath must be unique within an environment. Uniqueness
is validated by API Platform when an API proxy is generated
or imported.
FaultRules Defines how the ProxyEndpoint reacts to an error. A fault rule N/A No
specifies two items:
• A Condition that specifies the fault to be handled based
on the pre-defined category, subcategory, or name of the
fault
• One or more policies that define the behavior of the fault
rule for the corresponding Condition
RouteRule Defines the destination of inbound request messages after processing by the
ProxyEndpoint request pipeline. Usually, the RouteRule points to a named
TargetEndpoint configuration, but it can also point directly to a URL.
Name Required attribute, which provides a name for the RouteRule. N/A Yes
The characters you are allowed to use in the name are
restricted to the following: A-Z0-9._\-$%. For
example, Cat2 %_ is a legal name.
A named TargetEndpoint refers to a configuration file under /apiproxy/targets to which the RouteRule
forwards a request after processing by the ProxyEndpoint.
For example, the following RouteRule refers to the configuration /apiproxy/targets/myTarget.xml:
<RouteRule name="default">
<TargetEndpoint>myTarget</TargetEndpoint>
</RouteRule>
Conditional Routes
RouteRules can be chained to support dynamic routing at runtime. Inbound requests can be routed to named
TargetEndpoint configurations, directly to URLs, or to a combination of the two, based on HTTP headers,
message content, query parameters, or contextual information such time of day, locale, etc.
Conditional RouteRules work like other conditional statements on SAP API Management. See Conditions
reference and Variables reference.
For example, the following RouteRule combination first evaluates the inbound request to verify the value of an
HTTP header. If the HTTP header routeTo has the value TargetEndpoint1, then the request is forwarded to the
TargetEndpoint named TargetEndpoint1. If not, then the inbound request is forwarded to
http://api.mycompany.com/v2.
<RouteRule name="MyRoute">
<Condition>request.header.routeTo = "TargetEndpoint1"</Condition>
<TargetEndpoint>TargetEndpoint1</TargetEndpoint>
</RouteRule>
<RouteRule name="default">
<URL>http://api.mycompany.com/v2</URL>
</RouteRule>
A null RouteRule can be defined to support scenarios in which the request message does not need to be
forwarded to the TargetEndpoint. This is useful when the ProxyEndpoint performs all of the necessary processing,
for example by using JavaScript to call an external service or retrieving data from a lookup to the API Platform'
key/value store.
For example, the following defines a null Route:
<RouteRule name="GoNowhere"/>
Conditional null Routes can be useful. In the following example, a null Route is configured to execute when an
HTTP header request.header.X-DoNothing have a value other than null.
<RouteRule name="DoNothingOnDemand">
<Condition>request.header.X-DoNothing != null</Condition>
</RouteRule>
Remember, RouteRules can be chained, so a conditional null Route would typically be one component of a set of
RouteRules designed to support conditional routing.
A practical use of a conditional null Route would be in support of caching. By using the value of the variable that is
set by the Cache policy, you can configure an API proxy to execute the null Route when an entry is served from the
cache.
<RouteRule name="DoNothingUnlessTheCacheIsStale">
<Condition>lookupcache.LookupCache-1.cachehit is true</Condition>
</RouteRule>
TargetEndpoint
TargetEndpoint is the outbound equivalent of the ProxyEndpoint. A TargetEndpoint functions as an HTTP client to
a backend service or API--it sends requests and receives responses. An API proxy can contain zero or more
TargetEndpoints. (ProxyEndpoints can be configured to call URLs directly --an API proxy with no TargetEndpoints
TargetEndpoint Configuration
/targets/default.xml
The TargetEndpoint defines the outbound connection from SAP API Management to a backend service.
Sample TargetEndpoint configuration:
<TargetEndpoint name="default">
<PreFlow/>
<Flows/>
<PostFlow/>
<HTTPTargetConnection>
<URL> (Back-end URL) </URL>
</HTTPTargetConnection>
<FaultRules/>
<DefaultFaultRule/>
<ScriptTarget/>
<LocalTargetConnection/>
</TargetEndpoint>
TargetEndpoint
name The name of the TargetEndpoint, which must be unique N/A Yes
within the API proxy configuration. The name of the
TargetPoint is used in the ProxyEndpoint RouteRule to
direct requests for outbound processing. The
characters you are allowed to use in the name are
restricted to the following: A-Z0-9._\-$ %.
PreFlow Defines the policies in the PreFlow flow of a request or N/A Yes
response.
Flows Defines the policies in the conditional flows of a request N/A Yes
or response.
PostFlow Defines the policies in the PostFlow flow of a request or N/A Yes
response.
HTTPTargetConnection
ScriptTarget
ResourceURL Defines the resource type (node) and the name of the N/A Yes
main Node.js script that implements TargetEndpoint
functionality.
<ResourceURL>node://server.js</ResourceURL>
ScriptTarget is an alternative to
HTTPTargetConnection. (A TargetEndpoint can define
either an HTTPTargetConnection or a ScriptTarget, but
not both.)
TargetEndpoints often need to manage HTTP connections with heterogenous backend infrastructure. For this
reason, a number of advanced configuration settings are supported.
Note:
Because SAP API Management Edge originally supported SSL, you will see some instances in the SAP API
Management Edge UI and in the SAP API Management Edge XML that use the term "SSL". For example, the menu
entry in the SAP API Management Edge UI that you use to view certs is called SSL Certificates. The XML tag that
you use to configure a virtual host to use TLS is named<SSLInfo>.
SSLInfo
Enabled Indicates whether SSL is enabled for the Endpoint true Yes
KeyStore A keystore containing private keys used for outbound N/A Yes (if
client authentication ClientAuthEnable
d is true)
KeyAlias The key alias of the private key used for outbound client N/A Yes (if
authentication ClientAuthEnable
d is true)
You can also dynamically set TLS/SSL details to support flexible runtime requirements. For example, if your proxy
connects to two potentially different targets (a test target and a production target), you can have your API proxy
programmatically detect which environment it's calling and dynamically set references to the appropriate
keystore and truststore.
In the following example of how the <SSLInfo> tag would be set in a TargetEndpoint configuration, the values can
be supplied at runtime, for example, by a Java Callout, a JavaScript policy, or an Assign Message policy. Use
whichever message variables contain the values you want to set.
Variables are allowed in only the following elements.
<SSLInfo>
<Enabled>{myvars.ssl.enabled}</Enabled>
<ClientAuthEnabled>{myvars.ssl.client.auth.enabled}</ClientAuthEnabled>
<KeyStore>{myvars.ssl.keystore}</KeyStore>
<KeyAlias>{myvars.ssl.keyAlias}</KeyAlias>
<TrustStore>{myvars.ssl.trustStore}</TrustStore>
</SSLInfo>
Note:
Variable replacement of TLS/SSL values can only be used for a TargetEndpoint. Any attempt to use variables in
any other context, such as virtual host configuration or message logging, will cause validation failures.
When configuring a TargetEndpoint that uses HTTPS, you have to consider the case when the TLS/SSL cert
expires, or a change to the system configuration requires you to update the cert. In an SAP API Management Edge
installation, when configuring TLS/SSL by using static values or by using flow variables, there is a chance that you
will have to restart the Message Processors.
However, you can optionally configure the TargetEndpoint to use a reference to the keystore or truststore instead.
The advantage to using a reference is that you can update the reference to point to a different keystore or
truststore to update the TLS/SSL cert without having to restart Message Processors.
Note:
You can only use a reference to the keystore and truststore; you cannot use a reference to the alias. When you
change the reference to a keystore, ensure that the alias name of the cert is the same as in the old keystore.
For example, shown below is a TargetEndpoint that uses a reference to the keystore:
<SSLInfo>
<Enabled>true</Enabled>
<ClientAuthEnabled>false</ClientAuthEnabled>
<KeyStore>ref://keystoreref</KeyStore>
<KeyAlias>myKeyAlias</KeyAlias>
</SSLInfo>
Use the following POST API call to create the reference named keystoreref:
curl -X POST -H "Content-Type:application/xml"
https://api.enterprise.sap.com/v1/o/{org_name}/e/{env_name}/references \
-d '<ResourceReference name="keystoreref">
<Refers>myTestKeystore</Refers>
<ResourceType>KeyStore</ResourceType>
</ResourceReference>' -u email:password
The reference specifies the name of the keystore and its type.
Use the following GET API call to view the reference:
curl -X GET
https://api.enterprise.sap.com/v1/o/[org_name}/e/{env_name}/references/keystoreref -u
uname:password
To later change the reference to point to a different keystore, ensuring that the alias has the same name, use the
following PUT call:
curl -X PUT -H "Content-Type:application/xml"
https://api.enterprise.sap.com/v1/o/{org_name}/e/{env_name}/references/keystoreref \
-d '<ResourceReference name="keystoreref">
<Refers>myNewKeystore</Refers>
<ResourceType>KeyStore</ResourceType>
</ResourceReference>' -u email:password
TargetEndpoints support load balancing across multiple named TargetServers using three load balancing
algorithms.
For detailed instructions, refer to Load balance API traffic across multiple backend servers
Policies
The /policies directory in an API proxy contains all policies available to be attached to Flows in the API proxy.
Policy
name The internal name of the policy. Characters you can N/A Yes
use in the name are restricted to: A-Z0-9._\-$ %.
However, the SAP API Management Edge UI
enforces additional restrictions, such as
automatically removing characters that are not
alphanumeric.
Optionally, use the <DisplayName> element to label
the policy in the management UI proxy editor with a
different, natural-language name.
async Note: This attribute does not make the policy false No
execute asynchronously. In most cases, leave this
with the default of false.
When set to true, policy execution is offloaded to a
different thread, leaving the main thread free to
handle additional requests. When the offline
processing is complete, the main thread comes back
and finishes handling the message flow. In some
cases, setting async to true improves API proxy
performance. However, overusing async can hurt
performance with too much thread switching.
Step
Flows
ProxyEndpoint and TargetEndpoint define a pipeline for request and response message processing. A processing
pipeline consists of a request flow and a response flow. Each request flow and response flow is subdivided into a
PreFlow, one or more optional 'conditional' or 'named' Flow, and a PostFlow.
• PreFlow: Always executes. Executes before any conditional Flows.
• PostFlow: Always executes. Executes after any conditional Flows.
Additionally, the ProxyEndpoint defines a PostClientFlow which executes after the request is returned to the
requesting client app. Only MessageLogging policies can be attached to the PostClientFlow. The PostClientFlow is
currently used primarily for measuring the time interval between the start and end timestamps for the response
message.
Here's an example of a PostClientFlow with a message logging policy attached.
...
<PostFlow name="PostFlow">
<Request/>
<Response/>
</PostFlow>
<PostClientFlow>
<Request/>
<Response>
<Step>
<Name>Message-Logging-1</Name>
</Step>
</Response>
</PostClientFlow>
...
The API proxy processing pipeline executes Flows in the following sequence:
Request Pipeline:
1. Proxy Request PreFlow
2. Proxy Request Conditional Flows (Optional)
3. Proxy Request PostFlow
4. Target Request PreFlow
5. Target Request Conditional Flows (Optional)
Response Pipeline:
1. Target Response PreFlow
2. Target Response Conditional Flows (Optional)
3. Target Response PostFlow
4. Proxy Response PreFlow
5. Proxy Response Conditional Flows (Optional)
6. Proxy Response PostFlow
7. PostClientFlow Response (Optional)
Only those Flows with policy attachments need to be configured in ProxyEndpoint or TargetEndpoint
configurations. PreFlow and PostFlow need only be specified in a ProxyEndpoint or TargetEndpoint configuration
when a policy needs to be enforced during PreFlow or PostFlow processing.
In contrast to conditional flows, the ordering of PreFlow and PostFlow elements is not important--the API proxy
will always execute each at the appropriate point in the pipeline, regardless of where they appear in the Endpoint
configuration.
Conditional Flows
ProxyEndpoints and TargetEndpoints support an unlimited number of conditional flows (also known as 'named
flows').
The API proxy tests for the condition specified in the conditional flow and, if the condition is met, the processing
steps in the conditional flow are executed by the API proxy. If the condition is not met, then the processing steps
in the conditional flow are bypassed. Conditional flows are evaluated in the order defined in the API proxy and the
first one whose condition is met is executed.
By defining conditional flows, you gain the ability to apply processing steps in an API proxy based on:
• Request URI
• HTTP verb (GET/PUT/POST/DELETE)
• Value of a query param, header, and form param
• Many other types of conditions
For example, the following conditional statement defines an API resource /accesstoken. Any inbound request
with the URI path suffix /accesstoken will cause this flow to be executed, along with any policies that are attached
to the flow. Thus, this API resource functions as an OAuth token endpoint. If the inbound request URI does not
include the path suffix /accesstoken, then the flow does not execute (although another conditional flow might).
<Flows>
<Flow name="TokenEndpoint">
<Condition>proxy.pathsuffix MatchesPath "/accesstoken"</Condition>
<Request>
<Step>
<Name>GenerateAccessToken</Name>
</Step>
Step processing
The sequential ordering of conditional Flows is enforced by SAP API Management. Conditional Flows execute from
top to bottom. The first conditional Flow whose condition evaluates to true is executed, and only one conditional
Flow is executed.
For example, in the following Flow configuration, any inbound request that does not include the path
suffix /first or/second will cause the ThirdFlow to execute, enforcing the policy called Return404.
<Flows>
<Flow name="FirstFlow">
<Condition>proxy.pathsuffix MatchesPath "/first"</Condition>
<Request>
Resources
"Resources" are scripts, code, and XSL transformations that can be attached to Flows using policies.
Four resource types are supported:
• Compiled JavaScript: Stored under the /jsc directory
• Python scripts: Stored under the /py directory
• XSL transformations: Stored under the /xsl directory
Resources can be stored in an API proxy, an environment, or an organization. In each case, a resource is
referenced by name in a Policy. API Platform resolves the name by moving from the API proxy, to environment to
organization level.
A resource stored at the organization level can be referenced by Policies in any environment. A resource stored at
the environment level can be referenced by Policies in that environment. A resource stored at the API proxy level
can be referenced only by Policies in that API proxy.
Conditions enable API proxies to behave dynamically at runtime. Conditions define operations on variables, which
are evaluated by the SAP API Management processing pipeline. Conditional statements are boolean and always
evaluate to true or false.
SAP API Management specifies a set of commonly used variables. For a complete list, see Variables reference.
Custom variables can also be used in conditional statements. For instructions, see on setting custom variables;
see Extract message content using ExtractVariables
Policy enforcement
Using conditional statements, you can control the enforcement of policies. A common use case is conditional
transformation of response messages, based on HTTP header or message content.
For example, to conditionally transfrom XML to JSON based on the Accept header:
<Step>
<Condition>request.header.accept = "application/json"</Condition>
<Name>XMLToJSON</Name>
</Step>
Flow execution
Using conditional statements, you can control the execution of named flows in ProxyEndpoints and
TargetEndpoints. Note that only 'named' flows can be executed conditionally. Preflows and postflows (both
request and response) on ProxyEndpoints and TargetEndpoints execute for every transaction, and thus provide
unconditional 'failsafe' capabilities.
For example, to execute a conditional request flow based on the HTTP verb of the request message, and
conditional response flow based on a (potential) HTTP error code:
<Flow name="GetRequests">
<Condition>response.verb = "GET"</Condition>
<Request>
<Step>
<Condition>request.path MatchesPath "/statuses/**"</Condition>
<Name>StatusesRequestPolicy</Name>
</Step>
</Request>
<Response>
<Step>
<Condition>(response.status.code = 503) or (response.status.code =
400)</Condition>
<Name>MaintenancePolicy</Name>
</Step>
</Response>
Routes
Using conditional statements, you can control the target endpoint invoked by proxy endpoint configuration. A
route rule forwards a request to a particular target endpoint. When more than one target endpoint is available, the
route rule is evaluated for its condition and, if true, the request is forwarded to the named target endpoint.
For example, to conditionally route messages to designated target endpoints based on Content-Type:
<RouteRule name="target">
<Condition>target-variable = "targets"</Condition>
<TargetEndpoint>targets</TargetEndpoint>
</RouteRule>
<RouteRule name="default">
<TargetEndpoint>default</TargetEndpoint>
</RouteRule>
See Create dynamic API flows using conditions for more information.
Path Expressions
Path expressions are used for matching URI paths., using "*" to represent a single path element and "**" to
represent multiple URI levels.
For example:
% is treated as escape character. The pattern hello %{user%}{symbol} matches hello {user}! but not
hello world!.
Conditions can be categorized as follows:
• Operators: Wildcard patterns used in conditions.
Operators
= Equals, Is Equals to
|| Or Or
( Groups an expression
The following table shows the behavior when operands evaluate to null.
Operands
Data types are defined for variables, so values can be adapted as needed for comparison. For example, the
response status code = "404" is not a valid comparison because the response status code is an integer and not a
string.
The system is configured to adapt operands to a common data type before comparing them. For example, if the
response status code is 404, the expression response.status.code = "400" and the response.status.code = 400
are equivalent.
For numeric operands, the data type is interpreted as integer unless the value is terminated as follows:
• "f" or "F" (float, for example, 3.142f, 91.1F)
• "d" or "D" (double, for example, 3.142d, 100.123D)
• "l" or "L" (long, for example, 12321421312L)
In these cases, the system performs the adaptations shown in the following table.
Note
The dash character ( - ) in this table implies that the comparison is not performed, so the comparison is
false.
Object
Literals
Null, true, and false are the literals available in conditions. For example:
• request.header.host is null
• flow.cachehit is true
Samples
<RouteRule name="default">
<Condition>request.header.content-type = "text/xml"</Condition>
<TargetEndpoint>XmlTargetEndpoint</TargetEndpoint>
</RouteRule>
-----------------------------------------------------------------------------------
<Step>
<Condition>response.status.code is 503</Condition>
<Name>MaintenancePolicy</Name>
</Step>
-----------------------------------------------------------------------------------
<Flow name="GetRequests">
<Condition>response.verb="GET"</Condition>
<Request>
The HTTPTargetConnection element in TargetEndpoint configurations defines a set of HTTP transport properties.
You can use these properties to set transport-level configurations.
Properties are set on TargetEndpoint HTTPTargetConnection elements as shown below:
<TargetEndpoint name="default">
<HTTPTargetConnection>
<URL>http://weather.yahooapis.com</URL>
<Properties>
<Property name="supports.http10">true</Property>
<Property name="request.retain.headers">User-Agent,Referer,Accept-
Language</Property>
<Property name="retain.queryparams">apikey</Property>
</Properties>
</HTTPTargetConnection>
</TargetEndpoint>
Default
Property Name Description
Value
keepalive.timeout.millis 60000 Timeout for the target connection in the connection pool. if
the connection is in the pool beyond the specified limit, then
the connection is closed.
Note
The io.timeout.millis value larger than 55000ms will
be overridden by the default value of 55000ms set
on the system.
The increase of the timeout value on the
system(more than 55000ms) cannot be performed
because of the below reasons:
o To wait for more than a minute for an API
response would usually lead to bad experience
for the end user.
o It has a performance impact on the platform
and this would compromise SLA guarantees.
supports.http10 true If this is true and the client sends a 1.0 request, the target is
also sent a 1.0 request. Otherwise 1.1 request is sent to
target.
supports.http11 true If this is true and the client sends a 1.1 request, the target is
also sent a 1.1 request, otherwise 1.0 request is sent to
target.
use.proxy.tunneling true If this is set to true, and proxy configurations are specified in
http.properties (on-premises deployments only), then
target connections are set to use the specified via tunnel. If
the target uses SSL, then this property is ignored, and the
message is always sent via a tunnel.
request.streaming.enabled false When true, HTTP request payloads are not read into buffer.
The request payload streams as-is to the target endpoint.
The request payload will not be available for policy
enforcement in the Target Endpoint request flows.
response.streaming.enabled false When true, HTTP response payloads are not read into buffer.
The response payload streams as-is to the client. The
response payload will not be available for policy
enforcement.
success.codes N/A By default, SAP API Management treats HTTP code 4XX or
5XX as errors, and it treats HTTP code 1XX, 2XX, 3XX as
success. This property enables explicit definition of success
codes, for example, 2XX,1XX, 505 treats any 100, 200 and
505 HTTP response codes as success.
request.retain.headers.ena true By default, SAP API Management always retains all HTTP
bled headers on outbound messages. When set to true, all HTTP
headers present on the inbound request are set on the
outbound request.
request.retain.headers N/A Defines specific HTTP headers from the request that should
be set on the outbound request to the target service. For
example, to 'passthrough' the User-Agent header, set the
value ofrequest.retain.headers to User-Agent. Multiple HTTP
response.retain.headers.en true By default, SAP API Management always retains all HTTP
abled headers on outbound messages. When set to true, all HTTP
headers present on the inbound response from the target
service are set on the outbound response before it is passed
to the ProxyEndpoint.
response.retain.headers N/A Defines specific HTTP headers from the response that
should be set on the outbound response before it is passed
to the ProxyEndpoint. For example, to 'passthrough'
the Expires header, set the value
of response.retain.headers to Expires. Multiple HTTP
headers are specified as a comma-separated list, for
example, Expires,Set-Cookie. This property overrides
response.retain.headers.enabled. If
response.retain.headers.enabled is set to false,
any headers specified in the
response.retain.headers property are still set on the
outbound message.
retain.queryparams.enabled true By default, SAP API Management always retains all query
parameters on outbound requests. When set to true, all
query parameters present on the inbound request are set on
the outbound request to the target service.
ProxyEndpoint HTTPTargetConnection elements define a set of HTTP transport properties. These properties can
be used to set transport-level configurations.
Properties are set on ProxyEndpoint HTTPProxyConnection elements as follows:
<ProxyEndpoint name="default">
Default
Property Name Description
Value
allow.http10 true If this is true and the client app sends a 1.0 request, the
target is also sent a 1.0 request. If false, then an HTTP
1.1 request is sent to target.
allow.http11 true If this is true and the client app sends a 1.1 request, the
target is also sent a 1.1 request. If false, then an HTTP
1.0 request is sent to target.
allow.http.method.* OPTIONS, BY default, all HTTP methods are allowed. Use this
GET, setting To disable any HTTP method by setting the
HEAD, value for the property name, for example,
POST, PUT, name="allow.http.method.POST" to false. For example,
DELETE, <Property
TRACE, name="allow.http.method.PUT">false</Pro
PATCH perty>
If the incoming request's method is not allowed, then
the HTTP status code 405, "Method Not Allowed" will
be returned, along with an Allow header whose value is
the list of all methods that are allowed.
X-Forwarded-For false When set to true, the virtual host's PI address is added
to the outbound request as the value of the HTTP X-
Forwarded-For header.
allow.POST.without.content.len false When set to false, if the request method is POST and is
gth not chunked, not compressed and the content-length
header is missing, then the HTTP response code 411
"Length Required" is returned. When set to true, for the
same scenario, the content-length is assumed to be
zero, and the request is processed without parsing the
payload.
allow.PUT.without.content.leng false When set to false case: If the request method is PUT
th and is not chunked, not compressed and the content-
length header is missing, then the HTTP response code
411 "Length Required" is returned. When set to true, for
the same scenario, the content-length is assumed to be
zero, and the request is processed without parsing the
payload.
This topic discusses the SAP API Management Edge JavaScript Object Model. It's important you understand this
model if you intend to use the JavaScript policy to add custom JavaScript to an API proxy.
As an API developer you are undoubtedly familiar with JavaScript. SAP API Management enables you to leverage
your background with JavaScript to implement custom API behavior without having to change the code of your
APIs or backend services.
SAP API Management can be used as a managed container for executing your custom JavaScript. You write the
custom logic, and SAP API Management provides the container, security, management, monitoring, and analytics.
The benefit of this approach is that it lets you offload common functions like rate limiting, API key provisioning,
OAuth authorization, transformations, which frees you to focus on coding the API behavior that is the most
innovative and interesting.
You can combine SAP API Management's out-of-the-box policies with your own custom JavaScript to implement
custom behavior securely and reliably.
This section is intended to be an overview and a reference.
Overview
If you have a good grasp of JavaScript, you just need to become familiar with SAP API Management's object
model. JavaScript that executes in a browser relies on the "browser object model", or BOM. JavaScript that
executes on SAP API Management relies on a message-oriented object model. This object model defines request,
response, and context objects with associated properties. This section describes these objects and their
properties.
SAP API Management relies on Rhino, which is an open-source implementation of JavaScript written in Java. SAP
API Management also uses E4X, which is an extension of JavaScript that adds support for XML.
When your JavaScript is executed in an API proxy Flow, a scope is created for the execution.
A set of object references is created in the scope:
context.proxyRequest An object that represents the inbound request headers, query parameters,
message to the ProxyEndpoint (from the method, body, url
requesting app to the API proxy)
context.targetRequest An object that represents the outbound request headers, query parameters,
message from the TargetEndpoint (from the method, body, url
API proxy to the backend service).
context.targetResponse An object that represents the inbound target headers, content, status
response message (from the backend service
to the API proxy)
context.proxyResponse An object that represents the outbound proxy headers, content, status
response message (from the API proxy to the
requesting app)
Context
The context object has global scope. It is available everywhere within the API proxy flow. It has four child
objects: proxyRequest, proxyResponse, targetRequest, targetResponse. These child objects are
scoped to the ambient request and response, either the proxy request and response or the target request and
response. For example, if the JavaScript policy executes in the proxy endpoint part of the flow, then
the context.proxyRequest and context.proxyResponse objects are in scope. If the JavaScript runs in a target flow,
then the context.targetRequest and context.targetResponse objects are in scope.
The context object also has properties and methods, which are described in detail in this topic. For example, the
following JavaScript code example uses the context.flow property and calls the get/setVariable() methods
on context.
if (context.flow=="PROXY_REQ_FLOW") {
var username = context.getVariable("request.formparam.user");
context.setVariable("USER.name", username);
}
These methods interact directly with flow variables. The context.flow property value is the current flow scope. In
the proxy request flow, it's set to the constant PROXY_REQ_FLOW. If in the target response flow, it's set
to TARGET_RESP_FLOW. This constant is handy for executing scope-specific code. The getter lets you get flow
variables and the setter lets you set flow variables. These variables are generally available in the proxy flow and
can be consumed by other policies.
The request and response objects are "shorthand" references to the ambient request and response, either the
proxy request and response or the target request and response. The objects these variables refer to depend upon
the context in which the JavaScript policy executes. If the JavaScript runs in the flow of a proxy endpoint, then the
request and response variables refer to context.proxyRequest and context.ProxyResponse. If the JavaScript runs
in a target flow, then the variables refer to the context.targetRequest and context.targetResponse.
The JavaScript object model includes a print() function that you can use to output debug information to the SAP
API Management Edge Trace tool.
The crypto object lets you perform basic cryptographic hashing functions in JavaScript.
Note:
The crypto functions support hashing only -- there is no support for 2-way encryption.
The crypto object has global scope. It is available everywhere within the API proxy flow. Crypto lets you work with
these hash objects:
• SHA-1
• SHA256
• SHA512
• MD5
Note:
SAP API Management recommends that you use the crypto object to perform basic cryptographic functions in
your JavaScript programs running on SAP API Management Edge.
You can create SHA-1 objects, update them, and convert them to hex and base64 values.
Create a new SHA-1 object
var _sha1 = crypto.getSHA1();
Parameters
• value - (String) Any string value.
Example
Update an SHA-1 object:
_sha1.update("salt_value");
_sha1.update("some text");
You can create SHA-256 objects, update them, and convert them to hex and base64 values.
Create a new SHA-256 object
var _sha256 = crypto.getSHA256();
Parameters
• value - (String) Any string value.
Example
Update an SHA-256 object:
_sha256.update("salt_value");
_sha256.update("some text");
You can create SHA-512 objects, update them, and convert them to hex and base64 values.
Create a new SHA-512 object
var _sha512 = crypto.getSHA512();
Example
Update an SHA-512 object:
_sha512.update("salt_value");
_sha512.update("some text");
You can create MD5 objects, update them, and convert them to hex and base64 values.
Create a new MD5 object
var _md5 = crypto.getMD5();
Parameters
• value - (String) Any string value.
Example
Update an MD5 object:
_md5.update("salt_value");
_md5.update("some text");
Syntax
crypto.dateFormat(format, [timezone], [time])
Parameters
• format - (String) A string-formatted date. For example: 'YYYY-MM-DD HH:mm:ss.SSS'
• timezone - (String, optional) A time zone. Default: UTC
• time - (Number, optional) A Unix timestamp value to format. Default: current time
Examples
Get the current time, down to milliseconds:
var _now = crypto.dateFormat('YYYY-MM-DD HH:mm:ss.SSS');
Examples
var _hash1 = crypto.getHash('MD5');
try {
//get values to use with hash functions
var salt = context.getVariable("salt") || 'SomeHardCodedSalt';
var host = context.getVariable("request.header.Host");
var unhashed_token = "";
//convert to base64
var base64_token = sha512.digest64();
// set headers
context.setVariable("request.header.now", now);
context.setVariable("request.header.token", base64_token);
} catch(e) {
throw 'Error in Javascript';
}
Note
Any writable pre-defined variable and any custom variable can be dynamically set from JavaScript. For a
complete list of pre-defined variables, see Variables reference.
removeVariable(): Removes a variable from the context.
var org = context.removeVariable('organization.name.myorg');
Context Properties
Messages
As shown below, a complete API proxy Flow encompasses four distinct phases, each of which has an associated
message object:
• proxyRequest: The inbound request message received from the requesting client.
• targetRequest: The outbound request message sent to the backend service.
• proxyResponse: The outbound response message returned to the requesting client.
• targetResponse: The inbound request message received from the backend service.
Request messages
The context provides access to objects that represent request messages. For each HTTP transaction the
executes in an API proxy, two request message objects are created: one 'inbound' (the request from the client)
and one 'outbound' (the request generated by the API proxy and submitted to the backend target.)
url The url property is a read/write convenience property that combines scheme, host,
port, path and query parameters for the targetRequest.
The complete URL of the request is composed of the following properties:
• protocol: The protocol of the URL (for example, HTTP, HTTPS)
• port: The port (for example, :80, :443)
• host: The host of the URL (for example, www.example.com)
• path: The path of the URI (for example, /v1/weather)
When getting url, a URL is returned in the following format:
protocol://host:port/path?queryParams
Examples
context.targetRequest.url = 'http://www.example.com/path?q1=1'
context.targetRequest.protocol ='https';
Examples
For this HTTP request:
POST /v1/blogs HTTP/1.1
Host: api.example.com
Content-Type: application/json
Authorization: Bearer ylSkZIjbdWybfs4fUQe9BqP0LH5Z
The following JavaScript:
context.proxyRequest.headers['Content-Type'];
context.proxyRequest.headers['Authorization'];
will return the following values
application/json
Bearer ylSkZIjbdWybfs4fUQe9BqP0LH5Z
queryParameters The request message query parameters as a mapping of String => List.
Examples
"?city=PaloAlto&city=NewYork"
can be accessed as:
context.proxyRequest.queryParams['city']; // == 'PaloAlto'
context.proxyRequest.queryParams['city'][0] // ==
'PaloAlto'
context.proxyRequest.queryParams['city'][1]; // == 'NewYork'
context.proxyRequest.queryParams['city'].length; // == 2
method The HTTP verb (GET, POST, PUT, DELETE. PATCH, etc.) associated with the request
Examples
For this request:
POST /v1/blogs HTTP/1.1
Host: api.example.com
Content-Type: application/json
Authorization: Bearer ylSkZIjbdWybfs4fUQe9BqP0LH5Z
The following JavaScript:
context.proxyRequest.method;
will return the following value
POST
Examples
For an XML body:
<customer number='1'>
<name>Fred<name/>
<customer/>
To access the elements of the XML object as follows:
var name = context.targetRequest.asXML.name;
To access XML attributes attributes, use the @ notation.
var number = context.targetRequest.body.asXML.@number;
For a JSON request body:
{
"a": 1 ,
"b" : "2"
}
var a = context.proxyRequest.body.asJSON.a; // == 1
var b = context.proxyRequest.body.asJSON.b; // == 2
To read form parameters:
"vehicle=Car&vehicle=Truck"
----------------------------------------------------
v0 = context.proxyRequest.body.asForm['vehicle'][0];
v1 = context.proxyRequest.body.asForm['vehicle'][1];
SAP API Management generates two response objects: one for the ProxyEndpoint and one for the
TargetEndpoint.
Note
Before the targetRequest PreFlow has executed, the response object has a value of undefined.
headers The HTTP headers of the response message as a mapping of String => List.
Examples
var cookie = context.targetResponse.headers['Set-Cookie'];
status The status code with status message as a property. Both status code and status message
are available as properties.
Examples
var status = context.targetResponse.content.status; // 200
var msg = context.targetResponse.content.status.message; //
"OK"
Examples:
For an XML response:
"<customer number='1'>
<name>Fred<name/>
<customer/>"
You can access the elements of the XML object as follows:
var name = context.proxyResponse.content.asXML.name;
You can access the attributes of the XML object using the @ sign notation.
var number = context.proxyResponse.content.asXML.@number;
For JSON response:
{
"a": "1" ,
"b": "2"
}
var a = context.targetResponse.content.asJSON.a; // == 1
var b = context.targetResponse.content.asJSON.b; // == 2
The JavaScript HTTP Client can be used to make multiple parallel, asynchronous HTTP requests to any URL. This
makes it useful for developing composite services, as well as for consolidating multiple backend calls into a single
API method. You can use the HTTP client as an alternative to the ServiceCallout policy.
The HTTP Client exposes two methods: get() and send().
get()
A convenience method for simple HTTP GETs, with no support for HTTP headers.
Example:
var exchange = httpClient.get("http://www.example.com");
send()
Enables full configuration of the request message using the request object to contain the properties of the HTTP
request.
The httpClient request object is identical in type to the request object generated by a standard Flow.
var myRequest = new Request();
myRequest.url = "http://www.example.com";
var exchange = httpClient.send(myRequest);
Alternatively:
var headers = {'X-SOME-HEADER' : 'some value' };
var myRequest = new Request("http://www.example.com","GET",headers);
var exchange = httpClient.send(myRequest);
or
var headers = {'Content-Type : 'application/xml' };
var myRequest = new Request("http://www.example.com","POST",headers,"");
var exchange = httpClient.send(myRequest);
The calls to get() and send() immediately return an object that can used later to get the actual HTTP response, or
to check whether the response has timed out.
Example:
var ex1 = httpClient.get("http://www.example.com?api1");
var ex2 = httpClient.get("http://www.example.com?api2");
The returned object can be accessed later during flow processing, for example by another JavaScript policy:
ex1.waitForComplete(); // Thread is paused until the response is returned or
error or step time limit has been reached.
ex2.waitForComplete(100); // Thread is paused for a maximum of 100 ms.
if (status == 200) {
context.setVariable('userCheck.trace', 'user exists');
}
else if (status == 404) {
context.setVariable('userCheck.trace', 'user does not exist');
For example, to use httpClient to make a call to retrieve an OAuth access token:
function getAccessToken() {
var bodyObj = {
'grant_type': translatorApi.grantType,
'scope': translatorApi.scopeUrl,
'client_id': translatorApi.clientId,
'client_secret': translatorApi.clientSecret
};
if (exchange.isSuccess()) {
var responseObj = exchange.getResponse().content.asJSON;
if (responseObj.error) {
throw new Error(responseObj.error_description);
}
return responseObj.access_token;
} else if (exchange.isError()) {
throw new Error(exchange.getError());
}
}
Policy attachment
JavaScript is attached to API proxy Flow configuration using the Javascript Policy type.
See Customize an API using JavaScript.
Authorization Code
Invalid Key
HTTP/1.1 401 Unauthorized {"ErrorCode" : "invalid_request", "Error" :"Invalid
client id : AVD7ztXReEYyjpLFkkPiZpLEjeF2aYAz. ClientId is Invalid"}
Missing Key
HTTP/1.1 400 Bad Request
{"ErrorCode" : "invalid_request", "Error" :"The request is missing a required
parameter : client_id"}
Generate AccessToken
No Redirect URI
HTTP/1.1 400 Bad Request
{"ErrorCode" : "invalid_request", "Error" :"Required param : redirect_uri"}
Invalid Client ID
HTTP/1.1 401 Unauthorized
{"ErrorCode" : "invalid_client", "Error" :"Client identifier is required"}
Invalid GrantType
HTTP/1.1 400 Bad Request
{"ErrorCode" : "invalid_request", "Error" :"Unsupported grant type :
client_credentials_invalid"}
No Username
HTTP/1.1 400 Bad Request
{"ErrorCode" : "invalid_request", "Error" :"Required param : username"}
No Password
HTTP/1.1 400 Bad Request
{"ErrorCode" : "invalid_request", "Error" :"Required param : password"}
No AuthCode
HTTP/1.1 400 Bad Request
{"ErrorCode" : "invalid_request", "Error" :"Required param : code"}
Implicit
Invalid Client ID
HTTP/1.1 401 Unauthorized
{"ErrorCode" : "invalid_request", "Error" :"Invalid client id :
AVD7ztXReEYyjpLFkkPiZpLEjeF2aYAz. ClientId is Invalid"}
No Client ID
HTTP/1.1 400 Bad Request
{"ErrorCode" : "invalid_request", "Error" :"The request is missing a required
parameter : client_id"}
No Redirect URI
HTTP/1.1 400 Bad Request
{"ErrorCode" : "invalid_request", "Error" :"Redirection URI is required"}
Refresh Token
Invalid RefreshToken
HTTP/1.1 400 Bad Request
{"ErrorCode" : "invalid_request", "Error" :"Invalid Refresh Token"}
Invalid Scope
HTTP/1.1 400 Bad Request
{"ErrorCode" : "invalid_request", "Error" :"Invalid Scope"}
Invalid Client ID
HTTP/1.1 401 Unauthorized
{"ErrorCode" : "invalid_client", "Error" :"Client identifier is required"}
No Client ID
HTTP/1.1 401 Unauthorized
{"ErrorCode" : "invalid_client", "Error" :"Client identifier is required"}
Verify AccessToken
Invalid AccessToken
HTTP/1.1 401 Unauthorized
{"fault":{"faultstring":"Invalid Access
Token","detail":{"errorcode":"keymanagement.service.invalid_access_token"}}}
Invalid Scope
HTTP/1.1 403 Forbidden
{"fault":{"faultstring":"Required scope(s) :
VerifyAccessToken.scopeSet","detail":{"errorcode":"steps.oauth.v2.InsufficientScope
"}}}
No Auth Header
HTTP/1.1 401 Unauthorized
{"fault":{"faultstring":"Invalid access
token","detail":{"errorcode":"oauth.v2.InvalidAccessToken"}}}
SAP API Management encapsulates OAuth 1.0a and OAuth 2 capabilities in a set of policies. The life cycle
management of tokens and secrets, including generation, validation, and storage, is managed by SAP API
Management on behalf of your backend services.
This section specifies the flow variables defined by OAuth policies. The variables can be used to implement
custom behavior for OAuth flows. For OAuth usage, see OAuth.
The flow variables defined in this table are populated when the respective OAuth policies are executed, and hence
are available to other policies or applications executing in the API proxy flow.
• organization_name
• organization_name
• developer.id
• developer.app.name
• client_id
• grant_type
Sample policy:
<OAuthV2 name="VerifyAccessToken">
<Operation>VerifyAccessToken</Operation>
<Scope>space-separated-scopes</Scope>*
<AccessToken>flow.variable</AccessToken>*
<AccessTokenPrefix>Bearer</AccessTokenPrefix>*
</OAuthV2>
Only bearer tokens are supported. MAC tokens are not supported.
By default, the access token must be passed in the Authorization HTTP request header.
For example:
"Authorization: Bearer {PlainText_AccessToken}"
Any flow.variable can be passed as:
o HTTP Header: request.header.{variable_name}
o Query parameter: request.queryparam.{variable_name}
o Form parameter: request.formparam.{variable_name}
If the optional fields are not specified, the values are extracted per the OAuth 2.0 specification.
• oauthv2authcode.{policy_name}.code
• oauthv2authcode.{policy_name}.redirect_uri
• oauthv2authcode.{policy_name}.scope
• oauthv2authcode.{policy_name}.client_id
<OAuthV2 name="GetAuthCode">
<Operation>GenerateAuthorizationCode</Operation>
<ExpiresIn>1000<ExpiresIn>
<ResponseType>flow.variable</ResponseType>*
<ClientId>flow.variable</ClientId>*
<RedirectUri>flow.variable</RedirectUri>*
<Scope>flow.variable</Scope>*
<State>flow.variable</State>*
<Attributes>*
<Attribute name=”1” ref=”flow.variable”>value1</Attribute>
<Attribute name=”2” ref=”flow.variable”>value2</Attribute>
</Attributes>
</OAuthV2>
* Optional
Any flow.variable can be passed as:
• HTTP Header: request.header.{variable_name}
• Query parameter: request.queryparam.{variable_name}
• Form parameter: request.formparam.{variable_name}
If the optional fields are not specified, the values are extracted per the OAuth 2.0 specification.
Attribute values are derived dynamically from the specified flow variable, or statically using a default value in
the policy.
If both are specified, flow variable takes precedence.
Generate access token policy for grant types authorization code, user credentials, and client credentials
• oauthv2accesstoken.{policy_name}.access_token
• oauthv2accesstoken.{policy_name}.token_type
• oauthv2accesstoken.{policy_name}.expires_in
• oauthv2accesstoken.{policy_name}.refresh_token
Sample policy:
<OAuthV2 name="GenerateAccessToken">
<Operation>GenerateAccessToken</Operation>
<ExpiresIn>1000<ExpiresIn>
<SupportedGrantTypes>*
• oauthv2accesstoken.{policy_name}.access_token
• oauthv2accesstoken.{policy_name}.token_type
• oauthv2accesstoken.{policy_name}.expires_in
• oauthv2accesstoken.{policy_name}.refresh_token
<OAuthV2 name="GenerateAccessToken">
<Operation>GenerateAccessTokenImplicitGrant</Operation>
<ExpiresIn>1000<ExpiresIn>
<ResponseType>flow.variable></ResponseType>*
<ClientId>flow.variable></ClientId>*
<RedirectUri>flow.variable></RedirectUri>*
<Scope>flow.variable></Scope>*
<State>flow.variable></State>*
<AppEndUser>flow.variable</AppEndUser>*
<Attributes>*
<Attribute name=”1” ref=”flow.variable”>value1</Attribute>
<Attribute name=”2” ref=”flow.variable”>value2</Attribute>
</Attributes>
</OAuthV2>
* Optional
Any flow.variable can be passed as:
• HTTP Header: request.header.{variable_name}
• Query parameter: request.queryparam.{variable_name}
• Form parameter: request.formparam.{variable_name}
If the optional fields are not specified, the values are extracted per the OAuth 2.0 specification.
Attribute values are derived dynamically from the specified flow variable, or statically using a default value in
the policy.
If both are specified, flow variable takes precedence.
• oauthv2accesstoken.{policy_name}.access_token
• oauthv2accesstoken.{policy_name}.token_type
• oauthv2accesstoken.{policy_name}.expires_in
• oauthv2accesstoken.{policy_name}.refresh_token
Sample policy:
<OAuthV2 name="RefreshAccessToken">
<Operation>RefreshAccessToken</Operation>
<ExpiresIn>1000<ExpiresIn>
<GrantType>flow.variable</GrantType>*
Sample policy:
<GetOAuthV2Info name="GetClientAttributes">
<ClientId ref="{variable_name}"/>
</GetOAuthV2Info>
Sample policy:
<GetOAuthV2Info name="GetClientAttributes">
<ClientId>{client_id}</ClientId>
</GetOAuthV2Info>
• oauthv2accesstoken.{policy_name}.access_token
• oauthv2accesstoken.{policy_name}.scope
• oauthv2accesstoken.{policy_name}.refresh_token
• oauthv2accesstoken.{policy_name}.accesstoken.{custom_attribute_name}
• oauthv2accesstoken.{policy_name}.developer.id
• oauthv2accesstoken.{policy_name}.developer.app.name
• oauthv2accesstoken.{policy_name}.expires_in
oauthv2accesstoken.{policy_name}.status
Sample policy:
<GetOAuthV2Info name="GetTokenAttributes">
<AccessToken ref="{variable_name}"/>
Sample policy:
<GetOAuthV2Info name="GetTokenAttributes">
<AccessToken>{access_token}</AccessToken>
</GetOAuthV2Info>
Sample policy:
<GetOAuthV2Info name="GetAuthCodeAttributes">
<AuthorizationCode ref="{variable_name}"/>
</GetOAuthV2Info>
Sample policy:
<GetOAuthV2Info name="GetAuthCodeAttributes">
<AuthorizationCode>{authorization_code}</AuthorizationCode>
</GetOAuthV2Info>
Sample policy:
<GetOAuthV2Info name="GetTokenAttributes">
<RefreshToken ref="{variable_name}"/>
</GetOAuthV2Info>
<GetOAuthV2Info name="GetTokenAttributes">
<RefreshToken>{refresh_token}</RefreshToken>
</GetOAuthV2Info>
The flow variables defined in this table are populated when the respective OAuth policies are executed, and hence
are available to other policies or applications executing in the API proxy flow.
SAP API Management defines a set of variables that are available out-of-the-box. This section defines all the
variables that are "pre-defined" by API Platform.
Note
If you're new to flow variables or have general questions about them, see Introduction to flow variables.
For information about how variables are used in conditional flows, see Flow variables and conditions.
Flow variables have scope. By scope, we mean the point in the proxy flow life cycle when a variable is first
instantiated. For example, if you have a policy attached to the ProxyEndpoint request segment that policy will not
be able to access any variables that are scoped to the TargetEndpoint request segment. The reason for this is that
the TargetEndpoint request segment of the flow has not executed yet, so the API proxy hasn't had a chance to
populate variables in that scope.
Note
It is important to note that if you try to access a flow variable that is out of scope, you will receive a NULL
value. If you try to set a flow variable before it is in scope, the proxy does nothing; it does not generate an
error and does not set the variable.
For more information see Understanding Flow Variable Scope.
Using the variables that apply to the request message, policies may access message components including the
header, the query parameters, and form parameters, the source IP address, the HTTP message body, and so on.
The proxy receives an incoming request message, and then applies to it a series of policies, based on conditions
evaluated on the request, which can modify or transform the request. In the normal flow, the proxy then sends
the transformed request to the target.
Policies can examine request variables, then transform or reject the request based on the content of those
variables. Policies transform the request by setting the appropriate variables, for example variables
corresponding to the request headers.
client.cn Proxy String Read The common name specified in the SSL
request certificate presented by the client app.
client.email.address Proxy String Read The email address in the SSL certificate
request presented by the client app.
client.host Proxy String Read The HTTP host associated with the
request request received by the ProxyEndpoint.
client.locality Proxy String Read The locality (City) in the SSL certificate
request presented by the client.
client.port Proxy Integer Read The HTTP port associated with the
request originating client request to
ProxyEndpoint.
message.queryparams.count Proxy Integer Read The total count of all query parameters
request associated with the request sent to the
ProxyEndpoint from the client app.
http://api.apifactory.com/inve
ntors?name=nikola&surname=tesl
a
name=nikola&surname=tesla
message.uri Proxy String Read The complete URI path (following the
request domain URL) including query
parameters.
For example, where the request is:
http://api.apifactory.com/inve
ntors?name=nikola&surname=tesl
a
inventors?name=nikola&surname=tesl
a
message.version Proxy String Read/Write The HTTP version associated with the
request request sent to the ProxyEndpoint from
the client app.
messageid Proxy String Read Holds the globally unique ID for the
request request. This ID allows requests
received at the router to be tracked
after they are sent to the message
processor.
proxy.basepath Proxy String Read/Write The value of API proxy basepath that is
request sent from the client and received at the
ProxyEndpoint.
The basepath is defined as the path
component that uniquely identifies the
API proxy. The public-facing URL of an
API proxy is comprised of your
organization name, the environment
where the proxy is deployed, the
basepath, the basepath suffix, and any
query parameters.
For example, in the following request:
http://myorg-test.my
company.net/v2/weatherapi/fore
castrss?w=12797282
The basepath is /v2/weatherapi.
proxy.pathsuffix Proxy String Read The value of API proxy basepath suffix
request that is sent from the client and received
at the ProxyEndpoint.
proxy.url Proxy String Read Gets the complete URL associated with
request the proxy request received by the
ProxyEndpoint, including any query
parameters present.
request.content Proxy String Read/Write Gets or sets the payload of the request
request message.
request.formparam.{formpara Proxy String Read/Write Gets or sets the value of the specified
m_name} request form parameter in the request sent
from the client app.
request.formparam.{formpara Proxy Integer Read Count of all values for the specified
m_name}.values.count request form parameter associated with the
request.
request.headers.count Proxy Integer Read Count of all the headers in the request.
request
request.headers.names Proxy Collecti Read Names of all the headers in the request.
request on
request.queryparams.count Proxy Integer Read The count of all the query parameters in
request the request.
request.queryparams.names Proxy Collecti Read The names of all the query parameters
request on in the request.
request.verb Proxy String Read/Write The HTTP verb used for the request.
request For example: GET, PUT, DELETE
request.version Proxy String Read Gets the HTTP version of the request.
request
target.url Target String Read/Write When read, returns the complete URL
request set in the TargetEndpoint, including any
query parameters. When written, sets
the complete URL for the
TargetEndpoint.
Note: Use a JavaScript policy to set this
variable.
variable.expectedcn Proxy String Read/Write Variable exposed for the common name
request if it's running on SSL
virtualhost.aliases Proxy String_ Read Host aliases of the virtual host that is hit
request array during a particular request
virtualhost.name Proxy String Read Name of the virtual host that serves the
request originating client request
Using the variables that apply to the response message, policies may access message components including the
header, the query parameters, and form parameters, the source IP address, the HTTP message body, and so on.
The proxy receives a response message, and then applies to it a series of policies, based on conditions evaluated
on the response, which can modify or transform the response.
Policies can examine response variables, then transform or reject the request based on the content of those
variables. Policies transform the response by setting the appropriate variables, for example variables
corresponding to the response headers.
Message variables
Message variables are contextual: they refer to different message types (request, response, or error) depending
on the point within the API Proxy Flow in which they are called. The supported message variables are listed below.
Path Variables
Path variables are predefined variables that can be used to retrieve different parts of the request path.
Example
Consider the following deployment:
1. Deployment path: /dev/
2. Proxy base path: /twitter/
3. Virtual host port: 8090
4. Virtual host alias: mytwitter.com
5. Target URL: http://api.twitter.com/1/
Request from client - The client makes the request:
GET /dev/twitter/help/test.json
curl http://{host}:8090/dev/twitter/help/test.json -H 'host: mytwitter.com'
The path is visualized as :
{VERB} {proxy.basepath}/{proxy.pathsuffix}
Request is sent to target as:
GET /1/help/test.json
equivalent to: curl http://api.twitter.com/1/help/test.json
The path is visualized as:
{VERB} {target.basepath}/{proxy.pathsuffix}?{query params}
Note
You cannot use request.path because it includes the deployment path, which can change. The same
bundle should work with different deployment paths.
Configuration Variables
Configuration variables represent the configuration settings for an organization on SAP API Management. The
supported configuration variables are listed below:
Configuration
Scope Type Permission Description
variables
proxy.basepath Always Boolean Read The base path (URI) configured for the
ProxyEndpoint
proxy.name Always String Read The name attribute configured for the
ProxyEndpoint
proxy.pathsuffix Always String Read The request URI path fragment following
the URI base path URI fragment
System Variables
System variables contain system-related information. A system variable is prefixed with "_system." wherever it
is referenced. The part of the variable that appears after the prefix specifies the function in the system, such as
host name, date, time, and interfaces. The supported system variables are listed below.
system.time.dayofw Always Integer Read The day of the week portion of the
eek system.time variable.
system.pod.name Always String Read The name of the pod where the proxy
is running
system.region.name Always String Read The name of the data center region
where the proxy is running
router.uuid Always String Read The UUID of the router handling the
proxy
SSL/TLS Variables
The following variables are populated when an API proxy executes a transaction over inbound SSL/TLS. For the
variables to be populated the property propagate.additional.ssl.headers must set to true in the ProxyEndpoint
configuration.
Example
<ProxyEndpoint name="myProxy">
<HTTPProxyConnection>
<BasePath>/v1/weather</BasePath>
<VirtualHost>secure</VirtualHost>
<Properties>
<Property name="propagate.additional.ssl.headers">true</Property>
</Properties>
</HTTPProxyConnection>
The variables are designed to be at parity with the Apache web server SSL settings.
Each Policy type defines a set of policy-specific variables. For details, see each Policy type under the Policy
reference overview.
By adding an API to the API platform, you gain the ability to modify and monitor its behavior using out-of-the-box
policies. The out-of-the-box policies let you add sophisticated features to control traffic, enhance performance,
enforce security, and increase the utility of your APIs, without coding or changing backend services. Extension
policies enable you to add custom logic in the form of JavaScript, Python and XSLT to an API, tailoring it to meet
business requirements.
Following are the categories of policies that SAP API Management provides.
• Traffic management policies let you configure cache, control traffic quotas and spikes, set concurrent rate
limits, and so on.
Security policies
• Security policies let you control access to your APIs with OAuth, API key validation, and other threat
protection features.
Mediation policies
• Mediation policies let you perform message transformation, parsing, and validation, as well as raise faults and
alerts.
Extension policies
• Extension policies let you provide custom policy functionality beyond what is provided by SAP API
Management, with support for such features as a service callout, message data collection, and calling
JavaScript, and Python behavior you have created.
Using the following policies, your proxy can store and retrieve the cached data at runtime:
In the following example, an OAuth access token is written to the cache using a PopulateCache policy. The OAuth
token is retrieved for subsequent requests by a LookupCache policy. Once the access token expires, JavaScript is
used to retrieve a new access token, which is in turn cached by the PopulateCache policy.
<PopulateCache name="token-cache">
<!-- The cache to write to. -->
<CacheResource>mycache</CacheResource>
<!-- The source of the data, a variable containing the value. -->
<Source>twitter-translate.apiAccessToken</Source>
<!-- An enumeration representing a prefix for namespace scope. -->
<Scope>Exclusive</Scope>
<!-- A unique pointer to the data. Use this later to retrieve it. -->
<CacheKey>
<KeyFragment>apiAccessToken</KeyFragment>
<KeyFragment>request.queryparam.client_id</KeyFragment>
</CacheKey>
<!-- Fragments constructing the cache entry should expire after 600 seconds. -->
<ExpirySettings>
<TimeoutInSec>600</TimeoutInSec>
</ExpirySettings>
</PopulateCache>
Variables can be populated by policies or by code. The Source variable in this example is populated by the
following JavaScript call:
context.setVariable('twittertranslate.apiAccessToken',getAccessToken());
This topic lists variables and error codes related to caching policies. For more about caching, see Optimize
performance using cache.
Variables
Flow variables can be used to configure dynamic runtime behavior for policies and flows, based on HTTP headers
or message content, or the context available in the Flow. For more information about flow variables, see Variables
reference.
The following predefined Flow variables are available after you customize the behavior of the cache you define in a
LookupCache policy. For more about the policy, see LookupCache policy.
Error Codes
InvalidCacheResourceReference Invalid cache resource reference {0} in Stepdefinition {1}. Context {2}
EntryCannotBeCached Entry {0} can not be cached. Only serializable entries are cached
InvalidateCache Policy
Configures how the cached values should be purged from the cache.
Element reference
The element reference describes the elements and attributes of the InvalidateCache policy.
<InvalidateCache> Attributes
name The unique name of the policy. Use this name N/A Yes
to reference the policy within a Step definition
element. Characters you can use in the name
are restricted to: A-Z0-9._\-$ %. However,
the SAP API Management UI enforces
additional restrictions, such as automatically
removing characters that are not
alphanumeric.
async Note: This attribute does not make the policy false Optional
execute asynchronously.
When set to true, policy execution is
offloaded to a different thread, leaving the
main thread free to handle additional
requests. When the offline processing is
complete, the main thread comes back and
finishes handling the message flow. In some
cases, setting async to true improves API
proxy performance. However, overusing
async can hurt performance with too much
thread switching.
<DisplayName> Element
You can use in addition to the name attribute to label the policy in the management UI proxy editor with a
different, natural-language name.
<DisplayName>Policy Display Name</DisplayName>
Default: N/A
If you omit this element, the the value of the policy's name attribute is
used.
Presence: Optional
Type: String
This element specifies the name of the application that added the cache entry.
<APIProxyName>application_that_added_the_entry</APIProxyName>
Attributes
<CacheContext> Element
This element specifies how to construct a cache key when a Prefix element value is not specified, or to clear
cache entries added by another API proxy.
<CacheContext>
<APIProxyName ref="variable_name">application_that_added_the_entry</ApplicationName>
<TargetName ref="variable_name">endpoint_for_which_data_was_cached</TargetName>
<ProxyName ref="variable_name">proxy_for_which_data_was_cached</ProxyName>
</CacheContext>
Used to construct the CacheKey. Values for APIProxyName, ProxyName, and TargetName are mandatory when a
CacheKey prefix (that is, a custom prefix) is not used to clear cache entries added by another API proxy.
<CacheKey> Element
<CacheKey>
<Prefix>UserToken</Prefix>
<KeyFragment>apiAccessToken</KeyFragment>
<KeyFragment ref="request.queryparam.client_id" />
</CacheKey>
You use the <CacheKey> element in conjunction with Prefix and Scope. For more information, see Working with
cache keys.
<CacheResource> Element
This element specifies the cache where messages should be stored. A default cache is available.
Omit this element completely if this policy (and your corresponding PopulateCache and LookupCache policies) is
using the included shared cache.
<CacheResource>cache_to_use</CacheResource>
For more about configuring caches, see Manage caches for an environment.
<CacheKey>/<KeyFragment> Element
This element specifies a value that should be included in the cache key, creating a namespace for matching
requests to cached responses.
<KeyFragment ref="variable_name"/>
<KeyFragment>literal_string</KeyFragment>
Default: N/A
Presence: Optional
Type: N/A
This can be a key (a static name that you provide) or a value (a dynamic entry set by referencing a variable). All
specified fragments combined (plus the prefix) are concatenated to create the cache key.
You use the <KeyFragment> element in conjunction with <Prefix> and <Scope>. For more information, see
Working with Cache Keys
Attributes
Defaul
Attribute Type Required Description
t
ref string No The variable from which to get the value. Should not be used if
this element contains a literal value.
<CacheKey>/<Prefix> Element
<Prefix>prefix_string</Prefix>
Default: N/A
Presence: Optional
Type: String
You can use this value instead of <Scope> when you want to specify your own value rather than a <Scope> -
enumerated value. If defined, <Prefix> prepends the cache key value for entries written to the cache. A <Prefix>
element value overrides a <Scope> element value.
You use the <Prefix> element in conjunction with <CacheKey> and <Scope>. For more information, see
Working with cache keys.
This element specifies the name of the proxy for which the data was cached.
<ProxyName>proxy_for_which_data_was_cached</ProxyName>
Default: N/A
Presence: Optional
Type: String
Attributes
ref The variable from which to get the N/A Optional String
value. Should not be used if this
element contains a literal value.
<PurgeChildEntries> Element
true to purge cache entries that share the prefix value set by the <Prefix> element configured for this policy.
Values in other parts of the cache key, such as in <KeyFragment> elements, are not considered.
Note that the <Prefix> element must be specified. If the prefix is not set, setting true for
<PurgeChildEntries> could result in purging all entries in the cache.
Invalidating all of the cache entries of the same prefix value can be a useful way to purge multiple related entries at
once.
<PurgeChildEntries>true_to_purge_child_entries</PurgeChildEntries>
Default: false
Presence: Optional
Type: Boolean
<Scope> Element
Enumeration used to construct a prefix for a cache key when a Prefix element is not provided in the CacheKey
element.
The Scope setting determines a cache key that is prepended according to the Scope value. For example, a cache
key would take the following form when the scope is set to Exclusive:
orgName__envName__apiProxyName__deployedRevisionNumber__proxy|TargetName__ [ serialize
dCacheKey ].
If a Prefix element is present in CacheKey, it supersedes a Scope element value. Valid values include the
enumerations below.
You use the Scope element in conjunction with CacheKey and Prefix. For more information, see Working with
cache keys.
Scope Values
Global Cache key is shared across all API proxies deployed in the environment. Cache key is prepended in
the form orgName __ envName __.
If you define a <CacheKey> entry with the <KeyFragment> apiAccessToken and a
<Global> scope, each entry is stored as orgName__envName__apiAccessToken, followed by the
serialized value of the access token. For an API proxy deployed in an environment called 'test' in an
organization called 'apifactory', access tokens would be stored under the following cache
key: apifactory__test__apiAccessToken.
Exclusive Default. This is the most specific, and therefore presents minimal risk of namespace collisions
within a given cache.
Prefix is one of two forms:
• If the policy is attached to the ProxyEndpoint flow, prefix is of the form
ApiProxyName_ProxyEndpointName.
• If the policy is attached at TargetEndpoint, prefix is of the form ApiProxyName_TargetName.
Cache key prepended in the form
• orgName__envName__apiProxyName__deployedRevisionNumber__proxyNameITarget
Name
For example, the full string might look like this:
apifactory__test__weatherapi__16__default__apiAccessToken
.
This element specifies the name of the target endpoint for which the data was cached.
<TargetName>endpoint_for_which_data_was_cached</TargetName>
Default: N/A
Presence: Optional
Type: String
Attributes
ref The variable from which to get the N/A Optional String
value. Should not be used if this
element contains a literal value.
LookupCache Policy
Element reference
The element reference describes the elements and attributes of the LookupCache policy.
<LookupCache async="false" continueOnError="false" enabled="true" name="Lookup-Cache-
1">
<DisplayName>Lookup Cache 1</DisplayName>
<FaultRules/>
<Properties/>
<CacheKey>
<Prefix/>
<KeyFragment ref=""/>
</CacheKey>
<!-- Omit this element if you're using the included shared cache. -->
<CacheResource/>
<Scope>Exclusive</Scope>
At runtime, the LookupCache policy retrieves a value from the cache, assigning the value to the variable you
specify with the AssignTo element. It looks for the value based on a cache key created, through configuration that
combines the CacheKey and Scope elements. In other words, to retrieve a particular value added to the cache by
a PopulateCache policy, your LookupCache policy must have cache key-related elements configured in the same
way.
Your organization comes with a default cache. For more about the underlying data store, see Why Use a Cache?
For more about configuring caches, see Manage caches for an environment.
<LookupCache> Attributes
name The unique name of the policy. Use this name N/A Yes
to reference the policy within a Step definition
element. Characters you can use in the name
are restricted to: A-Z0-9._\-$ %. However,
the SAP API Management UI enforces
additional restrictions, such as automatically
removing characters that are not
alphanumeric.
async Note: This attribute does not make the policy false Optional
execute asynchronously.
When set to true, policy execution is
offloaded to a different thread, leaving the
main thread free to handle additional
requests. When the offline processing is
complete, the main thread comes back and
finishes handling the message flow. In some
cases, setting async to true improves API
<DisplayName> Element
You can use in addition to the name attribute to label the policy in the management UI proxy editor with a
different, natural-language name.
<DisplayName>Policy Display Name</DisplayName>
Default: N/A
If you omit this element, the the value of the policy's name attribute is
used.
Presence: Optional
Type: String
<AssignTo> Element
This element specifies the variable where the cache entry is assigned after it has been retrieved from the cache.
The variable must be writable.
<AssignTo>variable_to_receive_cached_value</AssignTo>
Default: N/A
Presence: Required
Type: String
<CacheKey> constructs the name of each piece of data stored in the cache.
CacheKey constructs the name of each piece of data stored in the cache. The cache key you define in the
PopulateCache policy is the name that you use in the LookupCache policy to get the specific entry that you
need from the cache.
At runtime, <KeyFragment> values are prepended with either the Scope element value or Prefix value. For
example, the following results in a cache key of UserToken__apiAccessToken__<value_of_client_id>:
<CacheKey>
<Prefix>UserToken</Prefix>
<KeyFragment>apiAccessToken</KeyFragment>
<KeyFragment ref="request.queryparam.client_id" />
</CacheKey>
You use the <CacheKey> element in conjunction with <Prefix> and <Scope>. For more information,
see Working with cache keys.
<CacheResource> Element
<CacheResource>cache_to_use</CacheResource>
Default: N/A
Presence: Optional
Type: String
For more about configuring caches, see Creating and Editing an Environment Cache.
This element specifies a value that should be included in the cache key, creating a namespace for matching
requests to cached responses.
<KeyFragment ref="variable_name"/>
<KeyFragment>literal_string</KeyFragment>
Default: N/A
Presence: Optional
Type: N/A
This can be a key (a static name that you provide) or a value (a dynamic entry set by referencing a variable). All
specified fragments combined (plus the prefix) are concatenated to create the cache key.
<KeyFragment>apiAccessToken</KeyFragment>
<KeyFragment ref="request.queryparam.client_id" />
You use the <KeyFragment> element in conjunction with <Prefix> and <Scope>. For more information, see
Working with Cache Keys
Attributes
Defaul
Attribute Type Required Description
t
ref string No The variable from which to get the value. Should not be used if
this element contains a literal value.
<Prefix>prefix_string</Prefix>
Default: N/A
Presence: Optional
Type: String
You can use this value instead of <Scope> when you want to specify your own value rather than a <Scope> -
enumerated value. If defined, <Prefix> prepends the cache key value for entries written to the cache. A <Prefix>
element value overrides a <Scope> element value.
You use the <Prefix> element in conjunction with <CacheKey> and <Scope>. For more information, see
Working with cache keys.
<Scope> Element
Enumeration used to construct a prefix for a cache key when a <Prefix> element is not provided in the
<CacheKey> element.
<Scope>scope_enumeration</Scope>
The <Scope> setting determines a cache key that is prepended according to the <Scope> value. For example, a
cache key would take the following form when the scope is set to Exclusive:
orgName__envName__apiProxyName__deployedRevisionNumber__proxy|TargetName__ [ serialize
dCacheKey ].
If a <Prefix> element is present in <CacheKey>, it supercedes a <Scope> element value. Valid values include
the enumerations below.
You use the <Scope> element in conjunction with <CacheKey> and <Prefix>. For more information, see
Working with cache keys.
Scope values
Global Cache key is shared across all API proxies deployed in the environment. Cache key is prepended in
the form orgName __ envName __.
If you define a <CacheKey> entry with the <KeyFragment> apiAccessToken and a
<Global> scope, each entry is stored as orgName__envName__apiAccessToken, followed by the
Exclusive Default. This is the most specific, and therefore presents minimal risk of namespace collisions
within a given cache.
Prefix is one of two forms:
• If the policy is attached to the ProxyEndpoint flow, prefix is of the form
ApiProxyName_ProxyEndpointName.
• If the policy is attached at TargetEndpoint, prefix is of the form ApiProxyName_TargetName.
Cache key prepended in the form
• orgName__envName__apiProxyName__deployedRevisionNumber__proxyNameITarget
Name
For example, the full string might look like this:
apifactory__test__weatherapi__16__default__apiAccessToken
.
LookupCache-Specific Variables
Flow variables can be used to configure dynamic runtime behavior for policies and flows, based on HTTP headers
or message content, or the context available in the Flow. For more information about flow variables, see Variables
reference.
The following predefined Flow variables are available after you customize the behavior of the cache you define in a
LookupCache policy.
Error Codes
PopulateCache Policy
Element reference
The element reference describes the elements and attributes of the PopulateCache policy.
<PopulateCache async="false" continueOnError="false" enabled="true" name="Populate-
Cache-1">
Your organization comes with a default cache. For more about the underlying data store, see Why Use a Cache?
For more about configuring caches, see Manage caches for an environment.
<PopulateCache> Attributes
name The unique name of the policy. Use this name N/A Yes
to reference the policy within a Step definition
element. Characters you can use in the name
are restricted to: A-Z0-9._\-$ %. However,
the SAP API Management UI enforces
additional restrictions, such as automatically
removing characters that are not
alphanumeric.
async Note: This attribute does not make the policy false Optional
execute asynchronously.
When set to true, policy execution is
offloaded to a different thread, leaving the
main thread free to handle additional
requests. When the offline processing is
complete, the main thread comes back and
finishes handling the message flow. In some
cases, setting async to true improves API
proxy performance. However, overusing
async can hurt performance with too much
thread switching.
<DisplayName> Element
You can use in addition to the name attribute to label the policy in the management UI proxy editor with a
different, natural-language name.
<DisplayName>Policy Display Name</DisplayName>
Default: N/A
If you omit this element, the the value of the policy's name attribute is
used.
Presence: Optional
Type: String
Default: N/A
Presence: Required
Type: N/A
<CacheKey> constructs the name of each piece of data stored in the cache.
Constructs the name of each piece of data stored in the cache. The cache key you define in the
<PopulateCache> policy is the name that you use in the <LookupCache> policy to get the specific entry that
you need from the cache.
At runtime, <KeyFragment> values are prepended with either the <Scope> element value or <Prefix> value.
For example, the following results in a cache key of UserToken__apiAccessToken__<value_of_client_id>:
<CacheKey>
<Prefix>UserToken</Prefix>
<KeyFragment>apiAccessToken</KeyFragment>
<KeyFragment ref="request.queryparam.client_id" />
</CacheKey>
You use the <CacheKey> element in conjunction with <Prefix> and <Scope>. For more information, see
Working with cache keys.
<CacheResource> Element
<CacheResource>cache_to_use</CacheResource>
Presence: Optional
Type: String
For more about configuring caches, see Creating and Editing an Environment Cache.
<ExpirySettings>/<ExpiryDate> Element
This element pecifies the date on which a cache entry should expire. Use the form mm-dd-yyyy.
<ExpirySettings>
<ExpiryDate ref="{date_variable}">expiration_date</ExpiryDate>
</ExpirySettings>
Default: N/A
Presence: Optional
Type: String
Attributes
ref The variable from which to get the N/A Optional String
value. Should not be used if this
element contains a literal value.
<ExpirySettings> Element
<ExpirySettings>
<TimeOfDay ref="time_variable">expiration_time</TimeOfDay>
<TimeoutInSec ref="duration_variable">seconds_until_expiration</TimeoutInSec>
<ExpiryDate ref="date_variable">expiration_date</ExpiryDate>
Default: N/A
Presence: Required
Type: N/A
<CacheKey>/<KeyFragment> Element
This element specifies a value that should be included in the cache key, creating a namespace for matching
requests to cached responses.
<KeyFragment ref="variable_name"/>
<KeyFragment>literal_string</KeyFragment>
Default: N/A
Presence: Optional
Type: N/A
This can be a key (a static name that you provide) or a value (a dynamic entry set by referencing a variable). All
specified fragments combined (plus the prefix) are concatenated to create the cache key.
<KeyFragment>apiAccessToken</KeyFragment>
<KeyFragment ref="request.queryparam.client_id" />
You use the <KeyFragment> element in conjunction with <Prefix> and <Scope>. For more information, see
Working with Cache Keys
Attributes
Defaul
Attribute Type Required Description
t
ref string No The variable from which to get the value. Should not be used if
this element contains a literal value.
<CacheKey>/<Prefix> Element
<Prefix>prefix_string</Prefix>
Default: N/A
Presence: Optional
Type: String
You can use this value instead of <Scope> when you want to specify your own value rather than a <Scope> -
enumerated value. If defined, <Prefix> prepends the cache key value for entries written to the cache. A <Prefix>
element value overrides a <Scope> element value.
You use the <Prefix> element in conjunction with <CacheKey> and <Scope>. For more information, see
Working with cache keys.
<Scope> Element
Enumeration used to construct a prefix for a cache key when a <Prefix> element is not provided in the
<CacheKey> element.
<Scope>scope_enumeration</Scope>
The <Scope> setting determines a cache key that is prepended according to the <Scope> value. For example, a
cache key would take the following form when the scope is set to Exclusive:
orgName__envName__apiProxyName__deployedRevisionNumber__proxy|TargetName__ [ serialize
dCacheKey ].
If a <Prefix> element is present in <CacheKey>, it supercedes a <Scope> element value. Valid values include
the enumerations below.
You use the <Scope> element in conjunction with <CacheKey> and <Prefix>. For more information, see
Working with cache keys.
Global Cache key is shared across all API proxies deployed in the environment. Cache key is prepended in
the form orgName __ envName __.
If you define a <CacheKey> entry with the <KeyFragment> apiAccessToken and a
<Global> scope, each entry is stored as orgName__envName__apiAccessToken, followed by the
serialized value of the access token. For an API proxy deployed in an environment called 'test' in an
organization called 'apifactory', access tokens would be stored under the following cache
key: apifactory__test__apiAccessToken.
Exclusive Default. This is the most specific, and therefore presents minimal risk of namespace collisions
within a given cache.
Prefix is one of two forms:
• If the policy is attached to the ProxyEndpoint flow, prefix is of the form
ApiProxyName_ProxyEndpointName.
• If the policy is attached at TargetEndpoint, prefix is of the form ApiProxyName_TargetName.
Cache key prepended in the form
orgName__envName__apiProxyName__deployedRevisionNumber__proxyNameITargetNa
me
For example, the full string might look like this:
apifactory__test__weatherapi__16__default__apiAccessToken
.
<Source> Element
This element specifies the variable whose value should be written to the cache.
<Source>source_variable</Source>
Default: N/A
Type: String
The time of day at which a cache entry should expire. Use the form HH:mm:ss. When present, this element's
sibling, <TimeoutInSec>, overrides <TimeOfDay>.
Enter time of day in the format HH:mm:ss, where HH represents the hour on a 24-hour clock. For example,
14:30:00 for 2:30 in the afternoon.
For the time of day, the default locale and time zone will vary depending on where the code is running (which isn't
knowable when you configure the policy). For information on configuring your locale, see Creating and Editing an
Environment Cache.
<ExpirySettings>
<TimeOfDay ref="time_variable">expiration_time</TimeOfDay>
</ExpirySettings>
Default: N/A
Presence: Optional
Type: String
Attributes
<ExpirySettings>
<TimeoutInSec ref="duration_variable">seconds_until_expiration</TimeoutInSec>
</ExpirySettings>
Presence: Optional
Type: Integer
Attributes
You can improve performance by caching data your proxy uses. For a simple example, see Optimize performance
using cache.
You can access the cache with policies. For reference information, see PopulateCache policy, LookupCache
policy, and InvalidateCache policy.
You might want a dedicated custom cache to:
• Reduce latency: A request satisfied from the cache gets the representation and displays it in a shorter
time. The server is more responsive to requests satisfied from the cache, which is closer to the client than the
origin server.
• Reduce network traffic: Representations are reused, reducing the impact of processing duplicate or
redundant requests. Using a cache also reduces the amount of bandwidth you use.
• Persist data across transactions: You can store session data for reuse across HTTP transactions.
• Support security: You may need "scope" access to the contents of a cache so it can only be accessed in a
particular environment or by a specific API proxy.
Data is cached in the underlying persistence store, a Cassandra (NoSQL) database. Your organization is
provisioned with a default cache that stores entries in this data store. You don't need to know about the
persistence store implementation to use caching.
The default cache works well for basic use cases, but you can also create dedicated custom caches for specific
applications. For more about creating a cache, see Manage caches for an environment.
You can create multiple caches in your organization. To support data segregation, a cache's scope is the
environment in which the cache is created. For example, API proxies running in a "test" environment cannot
Recommendation
For guidance on which type of cache or persistence to use in different situations, see Persistence.
When using a cache from a proxy, you can ensure the uniqueness of cached value keys by configuring cache keys.
A cache key, along with other values you can configure, gives you a reliable way to get out the data that you put in.
The values of configuration elements -- CacheKey/KeyFragment, Scope, and Prefix -- are concatenated to create
a unique identifier that is associated with the value you put into the cache with the PopulateCache policy. You use
this same configuration to retrieve the value with the LookupCache policy.
For reference, about these elements, see PopulateCache Policy, LookupCache policy, InvalidateCache Policy,
Reduce latency using ResponseCache
With the following cache policy configuration elements, you can create a namespace in which values are unique:
CacheKey > KeyFragment Use <CacheKey> <KeyFragment> elements combine to specify a unique
identifier for cache entries. KeyFragment values can be static literals or
set from variables.
<Scope> or <Prefix> Use the <Scope> or <Prefix> elements to namespace cache keys.
Scope enumerates a list of predefined values. The Prefix element
overrides Scope with a value of your own choosing.
These values are concatenated in the following form, with Scope> or <Prefix> values separated from
KeyFragment values by double-underscores. Multiple KeyFragment values are also separated by double
underscores.
scope | prefix__keyfragment[__keyfragment]
Using CacheKey
The <CacheKey> element specifies a unique identifier for cache entries created from a PopulateCache policy.
When you use a LookupCache policy to retrieve the cached values, you use a <CacheKey> element defined in the
same way to get the same entry.
The <CacheKey> element can include multiple <KeyFragment> elements. Values of <Key Fragment> elements
are concatenated with two underscores between them.
The following configuration creates a cache key of hello__world:
<CacheKey>
<KeyFragment>hello</KeyFragment>
You can also use a variable value in a cache key by referencing the variable in a KeyFragment element.
<KeyFragment ref="variable_name"/>
For example, to make the CacheKey value unique to the Content-Type of the request message, you do as follows:
<KeyFragment ref="request.header.Content-Type"/>
This defines a KeyFragment as the value of the context variable request.header.Content-Type. In the
configuration below, the request.header.Content-Type variable has the value application/json.
<CacheKey>
<KeyFragment>apiAccessToken</KeyFragment>
<KeyFragment ref="request.header.Content-Type" />
<KeyFragment>bar</KeyFragment>
</CacheKey>
<CacheKey>
<KeyFragment ref="request.queryparam.param1" />
<KeyFragment ref="request.queryparam.param2" />
<CacheKey>
At runtime, the cache key would include the param values concatenated, as in the following:
other_key_parts__value1__value2
Keep in mind that when you use variables to insert values from parameters, the values will be concatenated in the
order suggested by the <KeyFragment> element order. Also, note that SAP API Management will use only those
values that you specifically reference with <KeyFragment> elements. If your request query parameter lists vary,
the variations won't be accounted for in the cache key.
An alternative is to use the request.querystring variable, which inserts the entire string of parameters literally as
part of the cache key. Keep in mind that while this method accounts for all of the parameters, if the order of
parameters varies from one request to the next then the key will be different. In other words,
The <Scope> and <Prefix> elements provide a way to augment the key with a namespace prefix. The values
they represent are prepended to your cache key.
The <Scope> element is used by default. It is an enumeration whose value ranges from broad to narrow, with the
narrowest as the default. This default value is used unless you specify another value or specify a <Prefix>
element value. You can override the Scope value by using a <Prefix> element, and so specify a custom value for
namespacing.
For example, the <Scope> value "Global" -- the broadest scope -- represents the organization and environment
name. So if your proxy is deployed in an organization called 'mycompany' and an environment named 'prod', the
resulting preprended value will be the following:
Configuration Result
<Scope>Global</Scope> mycompany__prod__.
If you're using the Global scope with the cache key defined above, the result is as follows:
Configuration Result
<Scope>Global</Scope> mycompany__prod__hello__world.
<CacheKey>
<KeyFragment>hello</KeyFragment>
<KeyFragment>world</KeyFragment>
<CacheKey>
As described in LookupCache policy, the scope can be configured for increasing specificity from Global to
Exclusive. An Exclusive Scope is the most specific, and therefore represents minimal risk of namespace collisions
within a given cache. Each cache entry with an Exclusive scope is prefixed in the following form:
orgName__envName__apiProxyName__deployedRevisionNumber__proxy|TargetName__[serializedC
acheKey]
For example, a cache key created from using the Exclusive value for Scope would look like the following:
apifactory__test__weatherapi__16__default__apiAccessToken
• Quota types
• Identifying apps
• Dynamic Quota settings
• Time notation
• Configuring a Quota policy
• Policy-specific variables
• Policy-specific error codes
A Quota is an allotment of request messages that an app is allowed to submit to an API over the course of an hour,
a day, a week, or a month. To support Quota enforcement, SAP API Management maintains counters that tally the
number of requests received from individual apps. This capability enables API providers to enforce limits on the
number of API calls made by apps over an interval of time. Using Quota policies you can, for example, limit apps to
1 request per minute, or to 10,000 requests per month.
When an app reaches its Quota limit, subsequent API calls are rejected; SAP API Management returns an error
message for every request that exceeds the Quota. The Quota policy provides the ability to reset Quotas on-the-
fly, after an app has exceeded its limit.
Example
For example, if a Quota is defined as 10,000 messages per month, rate-limiting begins after the 10,000th
message. It doesn't matter whether 10,000 messages were counted on the first day or the last day of that
period; the app is blocked from making additional requests until the Quota counter automatically resets
at the end of the specified time interval, or until the Quota is explicitly reset using Reset quota counter
using ResetQuota.
Note
A variation on Quota called SpikeArrest prevents traffic spikes (or bursts) that can be caused by a sudden
increase in usage, buggy clients, or malicious attacks. For more information on SpikeArrest, see Shield
APIs using SpikeArrest.
Note
The name attribute for this policy is restricted to these characters: A-Z0-9._\-$ %. However, the
Management UI enforces additional restrictions, such as automatically removing characters that are not
alphanumeric.
Quota Types
Three types of Quota are supported. You define the Quota type as an attribute of the Quota policy.
Example
<Quota name="MyQuota" type="calendar">
Quotas are counted for individual apps. For this to work, each app requires a unique identifier that it presents with
each request. The identifier can be customized. It can be any HTTP header, query parameter, form parameter, or
message content that is unique to each consumer app.
You specify the token that will identify each app by defining a reference to a variable in the Identifier element. The
Identifier most commonly used to uniquely identify apps is the client_id. The client_id is another name for the API
key, or consumer key that is generated for an app when it is registered in an organization on SAP API
Management. You can use this identifier if you have enabled API key or OAuth authorization policies for your API.
<Identifier ref="request.header.client_id"/>
In some circumstances, Quota settings must be retrieved where no client_id is available, such as when no security
policy is in place. In those situations, you can use the AccessEntity policy type to retrieve the appropriate API
product settings.
Quota settings can be static or dynamic. The following examples demonstrate static and dynamic Quota
configurations.
In the example above the count is 10,000 client requests, over the course of 1 month.
If an API Key is used to validate an inbound request, then, assuming that the policy is named "VerifyApiKey", then
the dynamic Quota policy should be configured as follows:
<Quota name="ratelimiting.developer.quotas">
<Identifier ref="request.queryparam.apikey" />
<Interval ref="verifyapikey.VerifyApiKey.apiproduct.developer.quota.interval" />
<TimeUnit ref="verifyapikey.VerifyApiKey.apiproduct.developer.quota.timeunit" />
<Allow countRef="verifyapikey.VerifyApiKey.apiproduct.developer.quota.limit" />
</Quota>
The example above uses the variable client_id to identify the requesting app. This works as long as the request
message contains a client_id (associated with an OAuth-enabled request).
Note that the value for verifyapikey.VerifyApiKey will vary based on the name of the OAuthV2 policy of type
VerifyApiKey that is used to check the API key. If your policy is called, for example, KeyValidationPolicy, then the
variable name will be verifyapikey.KeyValidationPolicy.
Time Notation
All Quotas are set to the Coordinated Universal Time (UTC) time zone.
Quota time notation follows the international standard date notation defined in International Standard ISO 8601.
Dates are defined as year, month, and day, in the following format: YYYY-MM-DD.
For example, 2013-02-04 represents February 4, 2013.
Time of day is defined as hours, minutes, and second, in the following format: hours: minutes: seconds.
For example, 23:59:59 represents the time one second before midnight.
Note that two notations, 00:00 and 24:00, are available to distinguish the two midnights that can be associated
with one date. Therefore:
2013-02-04 24:00:00 is the same date and time as 2013-02-05 00:00:00
00:00 is usually the preferred notation.
StartTime (Optional) Use only for Quota policies of type calendar. Indicates the ISO 8601 date
and time when the Quota counter begins counting (regardless of whether
or not any requests have been received from any apps.)
Interval (Required) Specifies the interval of time (in hours, minutes, or days as defined by
TimeUnit) applicable to the Quota. For example, a value of 24 for
the Interval with aTimeUnit of hours means that the Quota is calculated
over one day (24 hours).
Valid value: integer
Note
Distributed Quota does not support seconds for the TimeUnit.
Note
If a count reference is specified, it takes precedence over the
Allow count value.
Example
The element <Allow count="2000"
countRef="request.header.allowed_quota"/> has a count header
(countRef="request.header.allowed_quota") along with the count
value of 2000.
Identifier (Optional) Variable used for uniquely identifying the client app.
Example
If the limit is 10 messages/hour and number of servers assigned
is 2, then the Quota count total is maintained for both servers.
Valid values: true or false
PreciseAtSecondsLevel The default precision for Quotas intervals is one minute. When set to true,
Quota precision is set to record at intervals of one second. Use this
setting when you have a Quota that uses minutes as the TimeUnit, and
you need to ensure that Quotas are counted and enforced by seconds.
Valid values: true or false
Synchronous This setting determines how the distributed Quota counter is updated. If
set to true, the quota counter is updated in the central repository
synchronously. This means that the update is made at the same time the
API call is quota-checked. When synchronous is set to true, you are
guaranteed that no API calls over the quota will be allowed.
Example
<Synchronous>false</Synchronous>
<AsynchronousConfiguration>
<SyncIntervalInSeconds>20</SyncIntervalInSeconds>
Alternatively, you can use the SyncMessageCount option instead, but you
cannot use both. SyncMessageCount specifies the number of requests
across all SAP API Management message processors between quota
updates. The following example specifies that the quota count is updated
every 5 requests across all API Management message processors:
<Synchronous>false</Synchronous>
<AsynchronousConfiguration>
<SyncMessageCount>5</SyncMessageCount>
</AsynchronousConfiguration>
Policy-specific Variables
The following predefined Flow variables are automatically populated when a Quota policy executes. For more
information about Flow variables, see Variables reference.
InvalidAsynchronizeConfigurationForSynchronousQuota AsynchronousConfiguration is
not valid for synchronous quota
ResponseCache can be configured to save and periodically refresh copies of response messages. As apps make
requests to the same URI, SAP API Management can be configured to return cached responses, rather than
forwarding those requests to the backend server.
ResponseCache is commonly used when backend data is updated only periodically. For example, an API that
exposes weather report data might only refresh the weather data once every ten minutes. By returning cached
responses and refreshing once every ten minutes, ResponseCache decreases the number of request reaching the
backend, and also eliminates a network hop for a significant portion of requests to the API.
There are two main benefits to ResponseCache:
• Reduced latency: The request is satisfied from the cache (removing a network hop), so the response is
returned in a shorter time, making the API more responsive.
Unlike other policies, a ResponseCache policy must be attached to both request and response paths within a
Flow.
Note
You can configure the ResponseCache proxy to also look at certain HTTP response caching headers and
take appropriate actions according to the directives of those headers. For example, on responses from
backend targets, SAP API Management supports the Cache-Control header, which can be used to control
the maximum age of a cached response, among other directives. For more information, see HTTP
response caching.
Cached response messages are returned to requesting apps based on request message keys configured in the
policy. At runtime, SAP API Management inspects request messages for a 'key' that you specify. A key is a piece
of information (such as query parameter) common to all request messages whose responses you need to cache.
When a key match occurs, SAP API Management returns the cached response, instead of forwarding the request
to the backend service.
Samples
10-minute cache
This sample shows how to have cached responses kept for 10 minutes.
Imagine that you have an API at the following URL:
http://{org-name}-{env}.<host:port>/weather/forecastrss?w=23424778
You're using the query parameter w as a cache key. SAP API Management checks the value of the query
parameter w whenever a request is received. If a valid (that is, non-expired) response is present in the cache, then
the cached response message is returned to the requesting client.
Now imagine that you have a ResponseCache policy configured as follows:
<ResponseCache name="ResponseCache">
<CacheKey>
<KeyFragment ref="request.queryparam.w" />
</CacheKey>
<ExpirySettings>
<TimeoutInSec>600</TimeoutInSec>
</ExpirySettings>
</ResponseCache>
http://{org-name}-{env}.<host:port>/weather/forecastrss?w=23424778
.
Note
HTTP headers and query parameters are automatically populated as variables when a request is received.
Any HTTP header is available as request.header.{header_name}, for example
request.header.user-agent. Any query parameter is available as
request.queryparam.{queryparam_name}, for example request.queryparam.action.
The element reference describes the elements and attributes of the Response Cache policy.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ResponseCache async="false" continueOnError="false" enabled="true" name="Response-
Cache-1">
<DisplayName>Response Cache 1</DisplayName>
<FaultRules/>
<Properties/>
<CacheKey>
<Prefix/>
<KeyFragment ref="request.uri" />
</CacheKey>
<Scope>Exclusive</Scope>
<ExpirySettings>
<ExpiryDate/>
<TimeOfDay/>
<TimeoutInSec ref="flow.variable.here">300</TimeoutInSec>
</ExpirySettings>
<CacheResource>cache_to_use</CacheResource>
<CacheLookupTimeoutInSeconds/>
<ExcludeErrorResponse/>
<SkipCacheLookup/>
<SkipCachePopulation/>
<UseAcceptHeader/>
<UseResponseCacheHeaders/>
</ResponseCache>
name The unique name of the policy. Use this name N/A Yes
to reference the policy within a Step definition
element. Characters you can use in the name
are restricted to: A-Z0-9._\-$ %. However,
the SAP API Management UI enforces
additional restrictions, such as automatically
removing characters that are not
alphanumeric.
async Note: This attribute does not make the policy false Optional
execute asynchronously.
When set to true, policy execution is
offloaded to a different thread, leaving the
main thread free to handle additional
requests. When the offline processing is
complete, the main thread comes back and
finishes handling the message flow. In some
cases, setting async to true improves API
proxy performance. However, overusing
async can hurt performance with too much
thread switching.
You can use in addition to the name attribute to label the policy in the SAP API Management UI proxy editor with a
different, natural-language name.
<DisplayName>Policy Display Name</DisplayName>
Default: N/A
If you omit this element, the the value of the policy's name attribute is
used.
Presence: Optional
Type: String
<CacheKey> Element
Note
You can further augment the cache key configured here by using values from response headers. For more
information, see ResponseCache Flow Variables.
<CacheKey>
<Prefix>string</Prefix>
<KeyFragment ref="variable_name" />
<KeyFragment>literal_string</KeyFragment>
</CacheKey>
<CacheKey> constructs the name of each piece of data stored in the cache.
CacheKey constructs the name of each piece of data stored in the cache. The cache key you define in the
PopulateCache policy is the name that you use in the LookupCache policy to get the specific entry that you
need from the cache.
At runtime, <KeyFragment> values are prepended with either the Scope element value or Prefix value. For
example, the following results in a cache key of UserToken__apiAccessToken__<value_of_client_id>:
<CacheKey>
<Prefix>UserToken</Prefix>
<KeyFragment>apiAccessToken</KeyFragment>
You use the <CacheKey> element in conjunction with <Prefix> and <Scope>. For more information,
see Working with cache keys.
<CacheLookupTimeoutInSeconds> element
This element specifies the number of seconds after which an unsuccessful cache lookup will be considered a
cache miss. If this occurs, flow resumes along the cache-miss path.
<CacheLookupTimeoutInSeconds>30</CacheLookupTimeoutInSeconds>
Default: 30
Presence: Optional
Type: Integer
<CacheResource> Element
<CacheResource>cache_to_use</CacheResource>
Default: N/A
Presence: Optional
Type: String
For more about configuring caches, see Creating and Editing an Environment Cache.
<ExcludeErrorResponse> element
Currently, by default, this policy caches HTTP responses with any possible Status code. That means both success
and error responses are cached. For example, responses with both 2xx and 3xx status codes are cached by
default.
Note
In a future release (to be determined), the default setting of this element will change to true.
<ExcludeErrorResponse>true</ExcludeErrorResponse>
Default: false
Presence: Optional
Type: Boolean
<ExpirySettings>/<ExpiryDate> element
Specifies the date on which a cache entry should expire. Use the form mm-dd-yyyy. When present, this element's
sibling, <TimeoutInSec>, overrides <ExpiryDate>.
<ExpirySettings>
<ExpiryDate ref="{date_variable}">expiration_date</ExpiryDate>
</ExpirySettings>
Default: N/A
Presence: Optional
Type: String
Attributes
ref The variable from which to get the N/A Optional String
value. Should not be used if this
element contains a literal value.
<ExpirySettings> element
This element specifies when a cache entry should expire. When present, <TimeoutInSec> overrides both
<TimeOfDay> and <ExpiryDate>.
<ExpirySettings>
<TimeOfDay ref="time_variable">expiration_time</TimeOfDay>
<TimeoutInSec ref="duration_variable">seconds_until_expiration</TimeoutInSec>
<ExpiryDate ref="date_variable">expiration_date</ExpiryDate>
</ExpirySettings>
Default: N/A
Presence: Required
Type: N/A
<CacheKey>/<KeyFragment> Element
This element specifies a value that should be included in the cache key, creating a namespace for matching
requests to cached responses.
<KeyFragment ref="variable_name"/>
<KeyFragment>literal_string</KeyFragment>
Default: N/A
Presence: Optional
Type: N/A
This can be a key (a static name that you provide) or a value (a dynamic entry set by referencing a variable). All
specified fragments combined (plus the prefix) are concatenated to create the cache key.
You use the <KeyFragment> element in conjunction with <Prefix> and <Scope>. For more information, see
Working with Cache Keys
Attributes
Defaul
Attribute Type Required Description
t
ref string No The variable from which to get the value. Should not be used if
this element contains a literal value.
<CacheKey>/<Prefix> Element
<Prefix>prefix_string</Prefix>
Default: N/A
Presence: Optional
Type: String
You can use this value instead of <Scope> when you want to specify your own value rather than a <Scope> -
enumerated value. If defined, <Prefix> prepends the cache key value for entries written to the cache. A <Prefix>
element value overrides a <Scope> element value.
You use the <Prefix> element in conjunction with <CacheKey> and <Scope>. For more information, see
Working with cache keys.
<Scope> Element
Enumeration used to construct a prefix for a cache key when a <Prefix> element is not provided in the
<CacheKey> element.
<Scope>scope_enumeration</Scope>
If a <Prefix> element is present in <CacheKey>, it supercedes a <Scope> element value. Valid values include
the enumerations below.
You use the <Scope> element in conjunction with <CacheKey> and <Prefix>. For more information, see
Working with cache keys.
Scope values
Global Cache key is shared across all API proxies deployed in the environment. Cache key is prepended in
the form orgName __ envName __.
If you define a <CacheKey> entry with the <KeyFragment> apiAccessToken and a
<Global> scope, each entry is stored as orgName__envName__apiAccessToken, followed by the
serialized value of the access token. For an API proxy deployed in an environment called 'test' in an
organization called 'apifactory', access tokens would be stored under the following cache
key: apifactory__test__apiAccessToken.
Exclusive Default. This is the most specific, and therefore presents minimal risk of namespace collisions
within a given cache.
Prefix is one of two forms:
• If the policy is attached to the ProxyEndpoint flow, prefix is of the form
ApiProxyName_ProxyEndpointName.
• If the policy is attached at TargetEndpoint, prefix is of the form ApiProxyName_TargetName.
Cache key prepended in the form
• orgName__envName__apiProxyName__deployedRevisionNumber__proxyNameITarget
Name
For example, the full string might look like this:
apifactory__test__weatherapi__16__default__apiAccessToken
.
Defines an expression that, if it evaluates to true at runtime, specifies that cache lookup should be skipped and the
cache should be refreshed.
<SkipCacheLookup>variable_condition_expression</SkipCacheLookup>
Default: N/A
Presence: Optional
Type: String
From the following example, if the bypass-cache variable is set to true in an incoming header, cache lookup is
skipped and the cache is refreshed.
<SkipCacheLookup>request.header.bypass-cache = "true"</SkipCacheLookup>
<SkipCachePopulation> element
Defines an expression that, if it evaluates to true at runtime, specifies that a write to the cache should be skipped.
<SkipCachePopulation>variable_condition_expression</SkipCachePopulation>
Default: N/A
Presence: Optional
Type: String
For example, the following would skip the cache write if the response status code was 400 or higher:
<ExpirySettings>/<TimeOfDay> element
The time of day at which a cache entry should expire. Use the form hh:mm:ss . When present, this element's
sibling, <TimeoutInSec>, overrides <TimeOfDay>.
Enter time of day in the format HH:mm:ss, where HH represents the hour on a 24-hour clock. For example,
14:30:00 for 2:30 in the afternoon.
<ExpirySettings>
<TimeOfDay ref="time_variable">expiration_time</TimeOfDay>
</ExpirySettings>
Default:
Presence: Optional
Type: String
Attributes
<ExpirySettings>/<TimeoutInSec> element
The number of seconds after which a cache entry should expire. When present, this element overrides its siblings,
<TimeOfDay> and <ExpiryDate>.
<ExpirySettings>
<TimeoutInSec ref="duration_variable">seconds_until_expiration</TimeoutInSec>
</ExpirySettings>
Default: N/A
Presence: Optional
Type: Integer
<UseAcceptHeader> element
Set to true to have a reponse cache entry's cache key appended with values from response Accept headers.
SAP API Management uses the Accept, Accept-Encoding, Accept-Language and Accept-Charset request headers
when calculating the cache key. This approach prevents a client from getting a media type they did not ask for.
For example, consider if two requests come in from the same URL, where the first request accepts gzip and the
second does not. The first request will be cached, and the cached entry will (probably) be a gzipped response. The
second request will read the cached value and may then return a gzipped entry to a client that is not capable of
reading gzip.
See ResponseCache Flow Variables for more.
<UseAcceptHeader>false</UseAcceptHeader>
Default: false
Presence: Optional
Type: Boolean
<UseResponseCacheHeaders> element
Set to true to have HTTP response headers considered when setting the "time to live" (TTL) of the response in
the cache. When this is true, SAP API Management considers the values of the following response headers,
comparing the values with those set by <ExpirySettings> when setting time to live:
• Cache-Control s-maxage
• Cache-Control max-age
• Expires
<UseResponseCacheHeaders>false</UseResponseCacheHeaders>
Default: false
Presence: Optional
Type: Boolean
The following policy configuration uses UseAcceptHeader and UseResponseCacheHeaders elements to instruct
SAP API Management to use Accept-* headers calculate cache keys and to consider HTTP response cache
headers like Cache-Control. For more information on how SAP API Management uses HTTP cache headers,
see HTTP response caching
<ResponseCache name="response_cache">
<UseAcceptHeader>true</UseAcceptHeader>
<UseResponseCacheHeaders>true</UseResponseCacheHeaders>
<CacheResource>cacheresource</CacheResource>
<CacheKey>
<KeyFragment ref="request.header.key1"/>
</CacheKey>
</ResponseCache>
The following predefined Flow variables are populated when a ResponseCache policy is executed. For more
information about Flow variables, see Variables reference.
A significant challenge to the maintenance of healthy APIs is traffic control. APIs consumed by client apps are
vulnerable to performance lags and downtime caused by the sudden influx of request messages, whether caused
by malicious attacks, buggy apps, or seasonality.
Policies of type SpikeArrest throttle the number of requests forwarded from the point in the processing Flow
where the Policy is attached as a processing Step. You can attach a SpikeArrest policy at the ProxyEndpoint
request Flow to limit inbound requests. You can also attach the SpikeArrest policy at the TargetEndpoint request
Flow to limit request forwarded to the backend service.
Unlike Quotas, spike arrests are not implemented as counts. Rather, they are implemented as a rate limit which is
based on the time the last matching message was processed.
If you specify 5 messages per minute, it means that requests can only be submitted at the rate of one per 12 sec
(1/5 minute) interval. A second request within 12 seconds on the same SAP API Management server will be
rejected. Even with a larger number (100 per second), if two requests come in nearly simultaneously to the same
SAP API Management server, one will be rejected. Each successful (non-arrested) request will update the spike
arrest's last processed count.
For more information on the Quota policy type, see Rate limit API traffic using Quota.
Note
The name attribute for this policy is restricted to these characters: A-Z0-9._\-$ %. However, the
Management UI enforces additional restrictions, such as automatically removing characters that are not
alphanumeric.
Samples
The following samples illustrate how you can use the SpikeArrest policy as a protection against traffic spikes.
Per second
It refers to 5 per second. This policy smoothes the rate to 1 request allowed every 200 milliseconds (1000 / 5).
<SpikeArrest name="SpikeArrest">
<Rate>5ps</Rate>
</SpikeArrest>
Per minute
It refers to 12 per minute. The policy smoothes the rate to 1 request allowed every 5 seconds (60 / 12).
<SpikeArrest name="SpikeArrest">
<SpikeArrest name="SpikeArrest">
<Rate>12pm</Rate>
<Identifier ref="client_id" />
<MessageWeight ref="request.header.weight" />
</SpikeArrest>
<SpikeArrest name="SpikeArrest">
<Rate ref="request.header.rate" />
</SpikeArrest>
Element reference
The element reference describes the elements and attributes of the SpikeArrest policy.
<SpikeArrest> attributes
name The unique name of the policy. Use this name N/A Yes
to reference the policy within a Step definition
element. Characters you can use in the name
are restricted to: A-Z0-9._\-$ %. However,
the SAP API Management UI enforces
additional restrictions, such as automatically
removing characters that are not
alphanumeric.
async Note: This attribute does not make the policy false Optional
execute asynchronously.
When set to true, policy execution is
offloaded to a different thread, leaving the
main thread free to handle additional
requests. When the offline processing is
complete, the main thread comes back and
finishes handling the message flow. In some
cases, setting async to true improves API
proxy performance. However, overusing
async can hurt performance with too much
thread switching.
You can use this element in addition to the name attribute to label the policy in the management UI proxy editor
with a different, natural-language name.
Default: N/A
If you omit this element, the the value of the policy's name attribute is
used.
Presence: Optional
Type: String
<Rate> element
This element pecifies the rate at which to limit traffic spikes (or bursts). Specify a number of requests that are
allowed in per minute or per second intervals. However, keep reading for a description of how the policy behaves
at runtime to smoothly throttle traffic.
<Rate>10ps</Rate>
<Rate>30pm</Rate>
<Rate ref="request.header.rate" />
Default N/A
Presence Required
Type Integer
Valid values {int}ps (number of requests per second, smoothed into intervals of
milliseconds)
{int}pm (number of requests per minute, smoothed into intervals of
seconds)
Note: In rate smoothing, the number of requests is always a whole
number greater than zero. Smoothing never involves calculating
fractions of requests.
ref A reference to the variable containing the rate setting, in the form of N/A Optional
{int}pm or {int}ps.
<Identifier> element
You can Use the <Identifier> element to uniquely identify and apply spike arrest against individual apps or
developers. You can use a variety of variables to indicate a unique developer or app, whether you're using custom
variables or predefined variables, such as those available with the Verify API Keys Using API Key Validation. See
also the Variables Reference.
Use in conjunction with <MessageWeight> for more fine-grained control over request throttling.
If you don't use this element, all calls made to the API proxy are counted for spike arrest.
<Identifier ref="client_id"/>
Default N/A
Presence Optional
Type String
Attributes
ref A reference to the variable containing the data that identifies the app or N/A Required
developer.
<MessageWeight> element
You can use in conjunction with <Identifier> to further throttle requests by specific clients or apps.
This element specifies the weighting defined for each message. Message weight is used to modify the impact of a
single request on the calculation of the Spike Arrest limit. Message weight can be set by variables based on HTTP
<MessageWeight ref="request.header.weight"/>
Default N/A
Presence Optional
Type Integer
Attributes
ref A reference to the variable containing the message weight for the N/A Required
specific app or client.
Note
• In general, you should use SpikeArrest to set a limit that throttles traffic to what your backend services can
handle.
• No counter is maintained for SpikeArrests, only a time that the last message was successfully passed through
the SpikeArrest policy.
When a Spike Arrest policy executes, the following Flow variables are populated.
For more information about Flow variables, see Variables Reference.
FailedToResolveSpikeArrestRate Failed to
resolve Spike Arrest Rate reference {0}
in SpikeArrest policy {1}
SAP API Management organizations can be configured to return an HTTP status code of 429 (Too Many
Requests) for all requests that exceed a rate limit set by a SpikeArrest policy. The default configuration returns an
HTTP status code of 500 (Internal Server Error).
Contact SAP API Management to have the features.isHTTPStatusTooManyRequestEnabled property set
to true for organizations for which you want Spike Arrest policy violations to return an HTTP status code of 429.
SAP API Management for Private Cloud customers can set this property with the following API call:
Example
You can use this policy to reset a developer's Quota counter when additional API calls are purchased.
Note
The name attribute for this policy is restricted to these characters: A-Z0-9._\-$ %. However, the
Management UI enforces additional restrictions, such as automatically removing characters that are not
alphanumeric.
Identifier name Variable used for uniquely identifying the client, for
example client_id.
Allow (Allow integer) Specifies the message count to which the Quota will
be reset.
Example
Reset Quota Examples
Reset top-level Quota.
<ResetQuota name="resetQuota">
<Quota name="request.header.quotapolicy">
<Identifier name="_default">
<Allow ref="request.header.allowquota" />
</Identifier>
</Quota>
</ResetQuota>
The ConcurrentRatelimit policy enables you to throttle inbound connections to your backend services from API
proxies running on SAP API Management. In distributed environments, app traffic may be managed by many
replicated API proxies. While each API proxy might be handling just a few connections, collectively, a set of
replicated API proxies, all of which point to the same backend service, might swamp the capacity of the service to
which they forward requests.
When the connection limit is exceeded, additional requests return HTTP response code 503:
503 Service Unavailable
Policy Attachment
The ConcurrentRatelimit policy must be attached as a Step to three Flows on a TargetEndpoint: request,
response, and DefaultFaultRule. (A validation error will be thrown at deployment time if the policy is attached to
any other Flows, including any ProxyEndpoint Flows.)
Note that when an API proxy is re-deployed, the counter values are reset.
Example
To attach a ConcurrentRatelimit policy called ConnectionThrottler to a TargetEndpoint called
MyTargetEndpoint, create the following TargetEndpoint configuration:
<TargetEndpoint name="MyTargetEndpoint">
<DefaultFaultRule name="DefaultFaultRule">
<Step><Name>ConnectionThrottler</Name></Step>
Note
Counters are reset when the API proxy is redployed.
A set of pre-defined Flow variables are populated each time the policy executes:
• concurent.ratelimit.{policy_name}.allowed.count
• concurent.ratelimit.{policy_name}.used.count
• concurent.ratelimit.{policy_name}.available.count
• concurent.ratelimit.{policy_name}.identifier
OAuth 1.0a defines a standard protocol that enables app users to authorize apps to consume APIs on their behalf,
without requiring app users to disclose their passwords to the app in the process. SAP API Management enables
Once you have configured OAuth policies on your API, apps must obtain access tokens to consume them. To do
so, the app must exchange a request token for an access token. Rather than relying on a single password as the
master key for every app that accesses an API, OAuth uses this token to provide “delegated authentication”
between APIs and apps. The resource owner can issue access tokens with restricted scope and limited lifetime,
and revoke them independently.
SAP API Management provides an OAuth 1.0a policy type that enables you to authorize apps with OAuth 1.0a. The
OAuthV1 policy type is responsible for generating request tokens, generating access tokens, and verifying access
tokens based on the OAuth 1.0a specification.
Note
The name attribute for this policy is restricted to these characters: A-Z0-9._\-$ %. However, the
Management UI enforces additional restrictions, such as automatically removing characters that are not
alphanumeric.
A request token is used by a consumer app to obtain authorization from the app end user, and is then presented
to the 'token endpoint' to be exchanged for an access token. A request token is generated from a valid consumer
key. Here are examples of the simple and comprehensive forms for generating request tokens.
Simple form
<OAuthV1 name="OAuthV1-GenerateRequestToken-1">
<Operation>GenerateRequestToken</Operation>
</OAuthV1>
Comprehensive form
<OAuthV1 name="OAuthV1-GenerateRequestToken-1">
<Operation>GenerateRequestToken</Operation>
<URL ref="flow.variable">value</URL>
<GenerateResponse enabled="true">
<Format>FORM_PARAM or XML</Format>
</GenerateResponse>
The <URL> element allows proper OAuthV1 signature calculation when running behind Elastic Load Balancers
(ELBs). The ref attribute takes precedence when both the ref attribute and a text value is specified. If ref is not
provided, or if the flow variable given in ref is NULL, then the text value will be considered for generating the
signature.
For example:
<URL ref="secretURL">https://example-test.net/oauth/access_token</URL>
On failure, a request returns the appropriate response status code with an error message.
An access token is used by the consumer to gain access to the protected resources on behalf of the user, instead
of using the user’s service provider credentials. An access token is created with a valid key, request token, and
verifier combination. Here are examples of the simple and comprehensive forms for generating access tokens.
Simple form
<OAuthV1 name="OAuthV1-GenerateAccessToken-1">
<Operation>GenerateAccessToken</Operation>
</OAuthV1>
Comprehensive form
<OAuthV1 name="OAuthV1-GenerateAccessToken-1">
<Operation>GenerateAccessToken</Operation>
<URL ref="flow.variable">{value}</URL>
<GenerateResponse enabled="true">
<Format>formparam or xml</Format>
</GenerateResponse>
The <URL> element allows proper OAuthV1 signature calculation when running behind Elastic Load Balancers
(ELBs). The ref attribute takes precedence when both the ref attribute and a text value is specified. If ref is not
provided, or if the flow variable given in ref is NULL, then the text value will be considered for generating the
signature.
Example
<URL ref="secretURL">https://example-test.net/oauth/access_token</URL>
On failure, a request returns the appropriate response status code with an error message.
The following policy associates a token verification code with a request token. To receive an access token, both a
verification code and a request token are required.
Note
To use this policy, a verification code must be generated as a separate step outside of SAP API
Management. The verifier value must be a unique, random string.
The verification code fits into the basic OAuth flow as follows: After an app user's credentials are authenticated by
a service provider, the service provider must inform the consumer app that the credentials were accepted,
implying that the request token can be exchanged for an access token. This is usually done via a 302 redirect.
Separately, the service provider must send a verification code to SAP API Management, and SAP API
Management internally associates this verifier to the request token.
Comprehensive form
<OAuthV1 name="OAuthV1-GenerateVerifier-1">
<Operation>GenerateVerifier</Operation>
<RequestToken ref="request.header.requesttoken"/>
<AppUserId ref="request.header.appuserid"/>
<VerifierCode ref="request.header.verifiercode"/>
<GenerateResponse enabled="true">
<Format>FORM_PARAM or XML</Format>
</GenerateResponse>
<Attributes>
<Attribute name="ver-attr1">ver-attr1</Attribute>
<Attribute name="ver-attr2" ref="request.header.ver-attr2"></Attribute>
<Attribute name="ver-attr3" display="false">ver-attr3</Attribute>
</Attributes>
</OAuthV1>
Parameters
Parameter Description
RequestToken (Required) Specifies the request token with which to associate the verifier.
(Required) Specifies the verifier code. This code must be generated outside
VerifierCode
of SAP API Management as a separate step.
When this policy executes, the following flow variables are populated:
• Request Token: oauthtoken.{policy_name}.oauth_token
• Verifier Code: authtoken.{policy_name}.verifier_code
• App User Id: oauthtoken.{policy_name}.app_user_id
Here are examples of the simple and comprehensive forms for verifying access tokens.
Simple form
<OAuthV1 name="OAuthV1-VerifyAccessToken-1">
<Operation>VerifyAccessToken</Operation>
</OAuthV1>
Comprehensive form
<OAuthV1 name="OAuthV1-VerifyAccessToken-1">
<Operation>VerifyAccessToken</Operation>
<URL ref="flow.variable">{value}</URL>
<GenerateErrorResponse enabled="true">
<Format>FORM_PARAM or XML</Format>
<Realm>http://oauth.example-test.com/oauth/1/</Realm>
</GenerateErrorResponse>
</OAuthV1>
The <URL> element allows proper OAuthV1 signature calculation when running behind Elastic Load Balancers
(ELBs). The ref attribute takes precedence when both the ref attribute and a text value is specified. If ref is not
provided, or if the flow variable given in ref is NULL, then the text value will be considered for generating the
signature.
If the request fails verification, the server responds with the appropriate response status code with an error
message.
Custom attributes can be optionally included in access, refresh, and verifier tokens.
<Attributes>
<Attribute name=”attr_name1” ref=”flow.variable”
display="true|false">value1</Attribute>
<Attribute name=”attr_name2” ref=”flow.variable”
display="true|false">value2</Attribute>
</Attributes>
Where the display is set to true, custom attributes are returned in the response, where they may be viewable by
the app end user.
Where the display is set to false, custom attributes are stored in the data store, but are not returned in the
response message.
For example, to add the User-Agent associated with the request to an access token:
<OAuthV1 name="GenerateAccessToken">
<Operation>GenerateAccessToken</Operation>
<ExpiresIn>1000</ExpiresIn>
<GenerateResponse />
<Attributes>
<Attribute name=”user-agent” ref=”request.header.user-agent”
display="false">NONE</Attribute>
</Attributes>
</OAuthV1>
The OAuthV1 and GetOAuthV1Info Policy types set the following variables when they execute.
GenerateRequestToken operation
• oauth_token
• oauth_token_secret
• oauth_callback_confirmed
• oauth_response
• oauth_consumer_key
• oauth_consumer_secret
GenerateAccessToken operation
• oauth_token
• oauth_token_secret
• oauth_response
• oauth_consumer_key
• oauth_consumer_secret
VerifyAccessToken operation
• oauth_token
• oauth_token_secret
• oauth_response
• oauth_consumer_key
• oauth_consumer_secret
GetOAuthV1Info
• oauth_consumer_key
• oauth_consumer_secret
RequestTokenNotResolved Could not resolve the request token with the variable {0}
AccessTokenNotResolved Could not resolve the access token with the variable {0}
OAuth 2.0 defines an authorization protocol for protected API resources. To ensure that apps are allowed to act
on behalf of users, OAuth 2.0 relies on 'access tokens'. To access protected resources, consumer apps must
obtain 'access tokens'. The OAuth 2.0 specification defines the various ways that apps can request and use
access tokens. SAP API Management provides a policy type that enables you to configure OAuth 2.0 authorization
for your APIs.
For step-by-step instructions on using the default OAuth 2.0 endpoints provided by SAP API Management
see Secure APIs with OAuth 2.0: client credentials.
Setting up OAuth 2.0 authorization for your API is a three step process:
1. Configure a token endpoint: An OAuth token endpoint defines a URI on SAP API Management. The token
endpoint is configured with a policy of type OAuthV2. In the OAuthV2 policy, the GenerateAccessToken
operation is specified. When this operation is specified, you have the option of configuring one or more grant
Note
Default OAuth 2.0 client credentials token and refresh endpoints are provisioned for every organization.
Also, a default API product is configured for every API proxy that you create in your organization.
See OAuth.
OAuth 2.0 policies are used both to generate and to validate OAuth 2.0-compliant tokens. To generate tokens on
behalf of app end users, OAuth 2.0 policies that specify the GenerateAccessToken operation are attached to a
token endpoint.
Note
Deploy a single API proxy to function as a token endpoint for all API proxies in an environment. A single
API proxy configured as a token endpoint can support multiple grant types. By setting up a single token
endpoint, you can publish a unified set of URIs that app developers can use to obtain tokens.
A token endpoint is simply a URI path that the system uses to identify requests for access tokens. On SAP API
Management, a token endpoint is a conditional Flow to which an OAuthV2 policy is attached. The OAuthV2 policy
specifies the GenerateAccessToken operation as an element.
For example, to configure a token endpoint that generates tokens on requests to the URI path /accesstoken:
<Flow name="TokenEndpoint">
<Condition>proxy.pathsuffix MatchesPath "/accesstoken"</Condition>
<Request>
<Step><Name>GenerateAccessToken</Name></Step>
</Request>
</Flow>
Note
The variable proxy.pathsuffix defines the URI fragment following the base path configured in the
ProxyEndpoint.
http://<host_name>:<port>/oauth/accesstoken
Similarly, you can configure authorization endpoints to issue authorization codes. For example:
<Flow name="AuthorizationEndpoint">
<Condition>proxy.pathsuffix == "/authorize"</Condition>
<Request>
<Step><Name>GenerateAuthCode</Name></Step>
</Request>
</Flow>
For instructions on configuring an API proxy to support authorization code, please see Secure APIs with OAuth
2.0: client credentials.
Once a token endpoint is set up for an API proxy, a corresponding OAuthV2 policy that specifies
theVerifyAccessToken operation is attached to the Flow that exposes the protected resource.
Example
To ensure that all requests to an API are authorized, the following policy enforces access token
verification:
<OAuthV2 name="VerifyOAuthAccessToken">
<Operation>VerifyAccessToken</Operation>
</OAuthV2>
The policy is attached to the API resource to be protected. To ensure that all requests to an API are verified,
attach the policy to the ProxyEndpoint request PreFlow, as follows:
<PreFlow>
<Request>
<Step><Name>VerifyOAuthAccessToken</Name></Step>
</Request>
</PreFlow>
The following optional elements can be used to override the default settings for the VerifyAccessToken operation.
Name Description
Scope A space separated list of scopes that must be present in the access token
for verification to succeed. For example, the following policy will check the
access token to ensure that it contains the scopes READ and WRITE:
<OAuthV2 name="ValidateOauthScopePolicy">
<Operation>VerifyAccessToken</Operation>
<Scope>READ WRITE</Scope>
</OAuthV2>
AccessToken The variable where the access token is expected to be located. For
examplerequest.queryparam.accesstoken. By default, the access token
is expected to be presented by the app in the Authorization HTTP header,
according to the OAuth 2.0 specification. Use this setting if the access
token is expected to be presented in a non-standard location, such as a
query parameter, or an HTTP header with a name other than
Authorization.
The OAuth 2.0 policy enables the user to specify which API calls to secure with OAuth 2.0. The OAuth policy
exposes configuration variables that enable the user to configure the behavior of the policy. SAP API Management
supports the following OAuth policies based on the OAuth 2.0 specification.
<ClientId>request.queryparam.client_id</ClientI
d>
<RedirectUri>request.queryparam.redirect_uri</R
edirectUri>
<Scope>request.queryparam.scope</Scope>
<State>request.queryparam.state</State>
<AppEndUser>request.queryparam.app_enduser</App
EndUser>
</OAuthV2>
<GrantType>request.queryparam.grant_type</Grant
Type>
</OAuthV2>
Note
The ExpiresIn element (optional) enforces the expiry time of the authorization code in milliseconds. The
expiry time of authorization code is system generated plus ExpiresIn value. If ExpiresIn is set to -1, the
system considers it as an infinite life time. If ExpiresIn is not specified, the system applies a default value
configured at the system level.
name The name of the Characters you can use in the name are All
policy. Must be restricted to: A-Z0-9._\-$ %. However, the
unique within the Management UI enforces additional restrictions,
API proxy such as automatically removing characters that
configuration are not alphanumeric.
RefreshToken Enforces the Any integer, including -1 (which indicates that All except client
ExpiresIn expiry time of refresh tokens do not expire) credentials and
refresh tokens in The expiration can also be set using a reference implicit
milliseconds. to a variable, as follows.
<RefreshTokenExpiresIn ref="flow.variable">{d
efault_value}</RefreshTokenExpiresIn>
Where display is set to true, custom attributes are returned in the response, where they may be viewable by the
app end user.
Where display is set to false, custom attributes are stored in the data store, but are not returned in the response
message.
For example, to add the User-Agent associated with the request to an access token:
<OAuthV2 name="GenerateAccessToken">
<Operation>GenerateAccessToken
</Operation>
<ExpiresIn>1000</ExpiresIn>
<GenerateResponse />
<SupportedGrantTypes>
<GrantType>client_credentials</GrantType>
</SupportedGrantTypes>
<GrantType>request.queryparam.grant_type</GrantType>
<Attributes>
<Attribute name="user-agent" ref="request.header.user-agent"
display="false"></Attribute>
</Attributes>
</OAuthV2>
Remote token stores can be used against SAP API Management. If a remote token store is used, the following
element should be configured in the GenerateAccessToken policy. When this configuration is used, SAP API
Management will generate the access token and return it to the requesting app.
<StoreToken>false</StoreToken>
If token validation has been delegated to a remote token service, then the following element must be configured,
identifying the location of the token in the request message. By specifying an ExternalAccessToken element, you
indicate that SAP API Management should not attempt to validate the token.
<ExternalAccessToken> request.header.external_access_token |
request.formparam.external_access_token | request.queryparam.external_access_token
</ExternalAccessToken>
Note that if you configure an external access token service, you must implement a ServiceCallout that enforces
the token check.
Note
Only bearer tokens are currently supported. MAC tokens are not supported. The access token must be
passed in the authorization header. For example, a sample authorization header is:
"Authorization: Bearer {access_token}"
Policy-specific Variables
Invalidating Tokens
In some cases, apps are required to explicitly revoke or invalidate tokens, for example, when a user logs out of an
OAuth-enabled app.
The procedure for token revocation is defined by the IETF Token Revocation draft specification.
The specification states:
[T]oken revocation prevents abuse of abandoned tokens and facilitates a better end-user experience since
invalidated authorization grants will no longer turn up in a list of authorization grants the authorization server might
present to the end-user.
SP API Management provides an InvalidateToken operation that enables you to configure a dedicated token
revocation endpoint. By publishing the URI of this endpoint, you enable app developers to invalidate tokens issued
by SAP API Management.
For example:
Tokens Identifies the Flow variable that defines the source of the token to be
revoked. If developers are expected to submit access tokens as query
parameters named access_token, for example,
userequest.queryparam.access_token.
• type (Optional): The token type identified by the variable specified.
Supported values areaccesstoken and refreshtoken.
• cascade (Optional): A boolean that determines whether the
revocation action will propagate to associated tokens. Supported
values are true and false. Defaults to true if not configured.
You can use the same technique to approve access tokens. The OAuthV2 policy type supports a ValidateToken
operation. The settings are the same as the InvalidateToken operation. The difference is that, by specifying the
ValidateToken operation, the status of the targeted access token or refresh token from 'revoked' to 'approved'.
<OAuthV2 name="ValidateToken">
<Operation>ValidateToken</Operation>
<Tokens>
<Token type="accesstoken" cascade="true">flow.variable</Token>
<Token type="refreshtoken" cascade="true">flow.variable</Token>
</Tokens>
</OAuthV2>
OAuthV2 is a multi-faceted policy for performing OAuth 2.0 grant type operations. This is the primary policy used
to configure OAuth 2.0 endpoints.
Place this policy on custom API proxy flows to generate access tokens, refresh tokens, authorization codes, to
perform token validation, and other operations. For example, you might put this policy on an API proxy endpoint
called /authorizationcode for apps to request authorization codes. Likewise, you might put this policy on an API
proxy endpoint called /token to generate an access token when that endpoint is called.
This OAuthV2 policy configuration (with the VerifyAccessToken operation) verifies that an access token
submitted to SAP API Management is valid. When this policy operation is triggered, SAP API Management looks
for a valid access token in the request. If the access token is valid, the request is allowed to proceed. If invalid, all
processing stops and an error is returned in the response.
Note that only bearer (access) tokens are supported. MAC tokens are not supported.
Apps must pass the access token in the Authorization HTTP request header. For example:
$ curl -H "Authorization: Bearer ylSkZIjbdWybfsUQe9BqP0LH5Z" http://{org-name}-
{env}.<host:port>/weather/forecastrss?w=12797282
For examples showing how to request access tokens for each of the supported grant types, see Requesting
access tokens and authorization codes. The topic includes examples of these operations:
• Authorization code
• Client credentials
• Implicit
• Password
• Refresh Token
• Authorization code
For examples showing how to request authorization codes, see Requesting access tokens and authorization
codes.
For examples showing how to request access tokens using a refresh token, see Requesting access tokens and
authorization codes.
Sometimes you may need to generate an access token in the response flow. For example, you may do this in
response to some custom validation done in a backend service. In this example, the use case requires both an
access token and a refresh token, ruling out the implicit grant type. In this case, we'll use the password grant type
to generate the token. As you'll see, the trick to making this work is to pass in an Authorization request header
with a JavaScript policy.
If you put this policy on the response flow, it will fail with a 401 UnAuthorized error even though the correct login
parameters are specified in the policy. To solve this problem, you need to set an Authorization request header.
The Authorization header must contain a Basic access scheme with the Base64-encoded client_id:client_secret.
You can add this header with a JavaScript policy placed just before the OAuthV2 policy, like this. The
"local_clientid" and "local_secret" variables must be previously set and available in the flow:
var client_id = context.getVariable("local_clientid");
var client_secret = context.getVariable("local_secret");
context.setVariable("request.header.Authorization","Basic
"+CryptoJS.enc.Base64.stringify(CryptoJS.enc.Latin1
.parse(client_id + ':' + client_secret)));
Element Reference
Note
The way you configure this policy, and the elements you need to specify, depend on which operation you
want the policy to perform. For example, if you are implementing the authorization code grant type, then
you will require four separate OAuthV2 policies to perform authorization code generation, access code
generation, access code validation, and refresh token generation. This reference lists all of the elements
that can be used with this policy.
The sample policy shown below is one of many possible configurations. This sample shows an OAuthV2 policy
configured for the GenerateAccessToken operation. It includes required and optional elements. Refer to the
element descriptions in this section for details.
<OAuthV2 name="GenerateAccessToken">
<Operation>GenerateAccessToken</Operation>
<ExpiresIn>1000</ExpiresIn>
<GenerateResponse />
<SupportedGrantTypes>
<GrantType>authorization_code</GrantType>
</SupportedGrantTypes>
<OAuthV2> attributes
name The internal name of the policy. Characters you can use in the name N/A Required
are restricted to: A-Z0-9._\-$ %. However, the SAP API
Management UI enforces additional restrictions, such as
automatically removing characters that are not alphanumeric.
Optionally, use the <DisplayName> element to label the policy in the
management UI proxy editor with a different, natural-language
name.
continueOnError Set to false to return an error when a policy fails. This is expected false Optional
behavior for most policies.
Set to true to have flow execution continue even after a policy fails.
async Note: This attribute does not make the policy execute false Optional
asynchronously.
When set to true, policy execution is offloaded to a different thread,
leaving the main thread free to handle additional requests. When
the offline processing is complete, the main thread comes back and
finishes handling the message flow. In some cases, setting async
to true improves API proxy performance. However, overusing async
can hurt performance with too much thread switching.
Use in addition to the name attribute to label the policy in the management UI proxy editor with a different,
natural-language name.
<DisplayName>Policy Display Name</DisplayName>
Default: N/A
If you omit this element, the the value of the policy'sname attribute is
used.
Presence: Optional
Type: String
<AccessToken> element
<AccessToken>request.header.access_token</AccessToken>
By default, VerifyAccessToken expects the access token to be sent in an Authorization header. You can change
that default using this element. For example request.queryparam.access_token indicates that the access token
should be present as a query parameter.
If presented in the header, it must be an Authorization header and be sent as a Bearer token. For example:
-H "Authorization: Bearer Rft3dqrs56Blirls56a"
Default: request.header.access_token
Presence: Optional
Type: String
<AccessTokenPrefix>Bearer</AccessTokenPrefix>
By default, VerifyAccessToken expects the access token to be sent in an Authorization header as a Bearer token.
For example:
Default: Bearer
Presence: Optional
Type: String
<AppEndUser> element
<AppEndUser>request.queryparam.app_enduser</AppEndUser>
In cases where the app end user ID must be sent to the authorization server, this element lets you specify where
SAP API Management should look for the end user ID. For example, it could be sent as a query parameter or in an
HTTP header.
For example request.queryparam.app_enduser indicates that the AppEndUser should be present as a query
parameter, as, for example, [email protected]. To require the AppEndUser in an HTTP header,
for example, set this value to request.header.app_enduser.
Providing this setting enables you to include an app end user ID in the access token. This feature is useful if you
want to be able to retrieve or revoke OAuth 2.0 access tokens by end user ID.
Default: N/A
Type: String
<Attributes/Attribute>
<Attributes>
<Attribute name=”attr_name1” ref=”flow.variable”
display="true|false">value1</Attribute>
<Attribute name=”attr_name2” ref=”flow.variable”
display="true|false">value2</Attribute>
</Attributes>
Use this element to add custom attributes to an access token or authorization code. For example, you may wish to
embed a user ID or session identifier in an access token that can be extracted and checked at runtime.
This element takes a value from a flow variable or a default value which is specified in the policy. If both are
specified, the value specified in the flow variable is taken. The optional display attribute can be set to true to false.
If set to true, the attribute will not be shown in the response. Default value is false.
Default: N/A
Presence: Optional
<ClientId> element
<ClientId>request.queryparam.client_id</ClientId>
In several cases, the client app must send the client ID to the authorization server. This element lets you specify
where SAP API Management should look for the client ID. For example, it could be sent as a query parameter or in
an HTTP header.
The variable request.queryparam.client_id indicates that the client_id should be present as a query parameter, as,
for example, ?client_id=AfGlvs9. To require the ClientId in an HTTP header, for example, set this value
to request.header.client_id.
Presence: Optional
Type: String
<Code> element
<Code>request.queryparam.code</Code>
The variable, request.queryparam.auth_code indicates that the authorization code should be present as a query
parameter, as, for example, ?auth_code=AfGlvs9. To require the authorization code in an HTTP header, for
example, set this value to request.header.auth_code.
Presence: optional
Type: String
<ExpiresIn> element
<ExpiresIn>10000</ExpiresIn>
Enforces the expiry time of access tokens, refresh tokens, and authorization codes in milliseconds. The expiry
time value is a system generated value plus the <ExpiresIn> value. If <ExpiresIn> is set to -1, the token or code is
given an infinite lifetime. If <ExpiresIn> is not specified, the system applies a default value configured at the
system level.
The expiry time can also be set at runtime using a reference to a flow variable. The flow variable can be retrieved
from a header, query parameter, or form parameter (default). Or, it can be a hard-coded value.
For example request.queryparam.expires_in indicates that the expiry value should be present as a query
parameter, as, for example, ?expires_in=360000. To require the value to come from an HTTP header, for
example, set this value to request.header.expires_in.
The following stanza specifies a flow variable and a default value as well. Note that the flow variable value takes
precedence over the specified default value.
Default: If not specified, the system applies a default value configured at the system level.
Presence: Optional
Type: Integer
<ExternalAccessToken> element
<ExternalAccessToken>request.queryparam.external_access_token</ExternalAccessToken>
Tells SAP API Management where to find an external access token (an access token not generated by SAP API
Management).
The variable request.queryparam.external_access_token indicates that the external access token should be
present as a query parameter, as, for example, ?external_access_token=12345678. To require the external
access token in an HTTP header, for example, set this value to request.header.external_access_token.
<ExternalAuthorization> element
<ExternalAuthorization>true</ExternalAuthorization>
If this element is false or not present, then SAP API Management validates the client_id and client_secret normally
against the SAP API Management authorization store. Use this element when you want to work with third-party
OAuth tokens.
Presence: Optional
Type: Boolean
<GenerateResponse> element
<GenerateResponse enabled='true'/>
If set to true, the policy generates and returns a response. If false, no response is sent. Instead, a set of flow
variables are populated with values related to the policy's function. For example, a flow variable
called oauthv2authcode.OAuthV2-GenerateAuthorizationCode.code gets populated with the newly minted auth
code.
Default: false
Presence: Optional
Type: string
<GenerateErrorResponse enabled='true'/>
If set to true, the policy generates and returns a response if the ContinueOnError attribute is set to true.
If false (the default), no response is sent. Instead, a set of flow variables are populated with values related to the
policy's function.
Default: false
Presence: Optional
Type: string
<GrantType>
<GrantType>request.queryparam.grant_type</GrantType>
Tells the policy where to find the grant type parameter that is passed in a request. Per the OAuth 2.0 specification,
the grant type must be supplied with requests for access tokens and authorization codes. The variable can be a
header, query parameter, or form parameter (default). Or, it can be a hard-coded value.
For example request.queryparam.grant_type indicates that the Password should be present as a query
parameter, as, for example, ?grant_type=password. To require the grant type in an HTTP header, for example, set
this value to request.header.grant_type.
Presence: Optional
Type: string
Valid values: A variable, as explained above, or a hard-coded grant type of: client_credentials, implicit,
authorization_code, or password
<Operation> element
<Operation>GenerateAuthorizationCode</Operation>
Default: If <Operation> is not specified, SAP API Management looks at the list
of <SupportedGrantTypes>. Only operations on those grant types will be successful. In other
words, you can omit <Operation> if you specify a <GrantType> in
the <SupportedGrantTypes> list. If neither <Operation> nor <SupportedGrantTypes> are
specified, the default grant type is authorization_code. That is, authorization_code grant type
requests will succeed, but all others will fail.
Presence: Optional
Type: String
<PassWord> element
<PassWord>request.queryparam.password</PassWord>
In cases where the app user's password must be sent to the authorization server, this element lets you specify
where SAP API Management should look for the password. For example, it could be sent as a query parameter, in
an HTTP header, or a form parameter (default).
For example request.queryparam.password indicates that the password should be present as a query parameter,
as, for example, ?password=changeit. To require the password in an HTTP header, for example, set this value
to request.header.password.
Presence: Optional
Type: String
<RedirectUri> element
<RedirectUri>request.queryparam.redirect_uri</RedirectUri>
Specifies where SAP API Management should look for the redirect_uri parameter in the request.
Presence: Optional
Type: String
<RefreshToken> element
<RefreshToken>request.queryparam.refreshtoken</RefreshToken>
When requesting an access token using a refresh token, you must supply the refresh token in the request. This
element lets you specify where SAP API Management should look for the refresh token. For example, it could be
sent as a query parameter, HTTP header, or form parameter (the default).
Presence: Optional
Type: String
<RefreshTokenExpiresIn> element
<RefreshTokenExpiresIn>1000</RefreshTokenExpiresIn>
Enforces the expiry time of refresh tokens in milliseconds. The expiry time value is a system generated value plus
the <RefreshTokenExpiresIn>value. If <RefreshTokenExpiresIn> is set to -1, the refresh token is given an infinite
lifetime. If <RefreshTokenExpiresIn> is not specified, the system applies a default value configured at the system
level.
The expiry time can also be set at runtime using a reference to a flow variable. The flow variable can be retrieved
from a header, query parameter, or form parameter (default). Or, it can be a hard-coded value.
For example request.queryparam.expires_in indicates that the expiry value should be present as a query
parameter, as, for example, ?expires_in=360000. To require the value to come from an HTTP header, for
example, set this value to request.header.expires_in.
The following stanza specifies a flow variable and a default value as well. Note that the flow variable value takes
precedence over the specified default value.
<RefreshTokenExpiresIn ref="flow.variable">
{default_value}
Default: If not specified, the system applies a default value configured at the system level.
Presence: Optional
Type: Integer
<ResponseType> element
<ResponseType>request.queryparam.response_type</ResponseType>
This element informs SAP API Management which grant type the client app is requesting. It is used only with the
authorization code and implicit grant type flows.
By default, SAP API Management looks for the response type value in a response_type query parameter. If you
wish to override this default behavior, use the <ResponseType> element to configure a flow variable containing
the response type value. For example, if you set this element to request.header.response_type, SAP API
Management looks for the response type to be passed in the request header.
Presence: Optional. Use this element if you wish to override the default behavior.
Type: String
Valid Either code (for the authorization code grant type) or token (for the implicit grant type)
values:
<ReuseRefreshToken> element
<ReuseRefreshToken>true</ReuseRefreshToken>
When set to true, the existing refresh token is reused until it expires. If false, a new refresh token is issued by SAP
API Management when a valid refresh token is presented.
Default: false
Presence: optional
Type: boolean
<Scope> element
<Scope>request.queryparam.scope</Scope>
Default: No scope
Presence: Optional
Type: String
<State> element
<State>request.queryparam.state</State>
In cases where the client app must send the state information to the authorization server, this element lets you
specify where SAP API Management should look for the state values. For example, it could be sent as a query
parameter or in an HTTP header. The state value is typically used as a security measure to prevent CSRF attacks.
For example request.queryparam.state indicates that the state should be present as a query parameter, as, for
example, ?state=HjoiuKJH32. To require the state in an HTTP header, for example, set this value
to request.header.state.
Default: No state
Presence: Optional
Type: String
<StoreToken> element
<StoreToken>true</StoreToken>
Set this element to true when the <ExternalAuthorization> element is true. The <StoreToken> element tells SAP
API Management to store the external access token. Otherwise, it will not be persisted.
Default: false
Presence: Optional
Type: Boolean
<SupportedGrantTypes>/<GrantType> element
<SupportedGrantTypes>
<GrantType>authorization_code</GrantType>
<GrantType>client_credentials</GrantType>
<GrantType>implicit</GrantType>
<GrantType>password</GrantType>
</SupportedGrantTypes>
Presence: Required
Type: String
<Tokens>/<Token> element
The <Token> element identifies the flow variable that defines the source of the token to be revoked. If developers
are expected to submit access tokens as query parameters named access_token, for example,
use request.queryparam.access_token.
<UserName> element
<UserName>request.queryparam.user_name</UserName>
In cases where the app user name must be sent to the authorization server, this element lets you specify where
SAP API Management should look for the end user name. For example, it could be sent as a query parameter or in
an HTTP header.
For example request.queryparam.username indicates that the username should be present as a query parameter,
as, for example, ?username=joe. To require the UserName in an HTTP header, for example, set this value
to request.header.username.
Presence: Optional
Type: String
Once a token endpoint is set up for an API proxy, a corresponding OAuthV2 policy that specifies
the VerifyAccessToken operation is attached to the Flow that exposes the protected resource.
For example, to ensure that all requests to an API are authorized, the following policy enforces access token
verification:
<OAuthV2 name="VerifyOAuthAccessToken">
<Operation>VerifyAccessToken</Operation>
</OAuthV2>
The policy is attached to the API resource to be protected. To ensure that all requests to an API are verified,
attach the policy to the ProxyEndpoint request PreFlow, as follows:
<PreFlow>
<Request>
<Step><Name>VerifyOAuthAccessToken</Name></Step>
</Request>
</PreFlow>
The following optional elements can be used to override the default settings for the VerifyAccessToken operation.
Name Description
Scope A space-delimited list of scopes. Verification will succeed if at least one of the scopes listed is
present in the access token. For example, the following policy will check the access token to
ensure that it contains at least one of the scopes listed. If READ or WRITE is present,
verification will succeed.
<OAuthV2 name="ValidateOauthScopePolicy">
<Operation>VerifyAccessToken</Operation>
<Scope>READ WRITE</Scope>
</OAuthV2>
AccessToken The variable where the access token is expected to be located. For
examplerequest.queryparam.accesstoken. By default, the access token is expected to be
presented by the app in the Authorization HTTP header, according to the OAuth 2.0
specification. Use this setting if the access token is expected to be presented in a non-
standard location, such as a query parameter, or an HTTP header with a name other than
Authorization.
For each grant type, the policy makes assumptions about the location or required information in request
messages. These assumptions are based on the the OAuth 2.0 specification. If your apps need to deviate from the
OAuth 2.0 specification, then you can specify the expected locations for each parameter. For example, when
handling an authorization code, you can specify the location of the authorization code, the client ID, the redirect
URI, and the scope. These can be specified as HTTP headers, query parameters, or form parameters.
The example below demonstrates how you can specify the location of required authorization code parameters as
HTTP headers:
...
<GrantType>request.header.grant_type</GrantType>
<Code>request.header.code</Code>
<ClientId>request.header.client_id</ClientId>
<RedirectUri>request.header.redirect_uri</RedirectUri>
<Scope>request.header.scope</Scope>
...
Or, if necessary to support your client app base, you can mix and match headers and query parameters:
...
<GrantType>request.header.grant_type</GrantType>
<Code>request.header.code</Code>
<ClientId>request.queryparam.client_id</ClientId>
<RedirectUri>request.queryparam.redirect_uri</RedirectUri>
<Scope>request.queryparam.scope</Scope>
...
Flow variables
The flow variables defined in this table are populated when the respective OAuth policies are executed, and hence
are available to other policies or applications executing in the API proxy flow.
VerifyAccessToken operation
These variables are set when the VerifyAccessToken policy operation executes.
API product variables will be populated automatically if the API products are configured with valid environment,
proxies, and API resources (derived from the proxy.pathsuffix). Explicitly setting flow.resource.name variable is
not required.
Where the API products are not configured with valid environments and API proxies, then flow.resource.name
must explicitly be set to populate API product variables in the flow.
Variables Description
developer.id The ID of the developer associated with the registered client app.
developer.app.name The name of the developer associated with the registered client
app.
scope The scope (if any) associated with the access token.
apiproduct.<custom_attribute_name> A named custom attribute of the API product associated with the
registered client app.
apiproduct.name The name of the API product associated with the registered client
app.
App-specific variables
app.name
app.id
app.accessType
app.callbackUrl
app.status
app.scopes
app.appFamily
app.apiproducts
app.appParentStatus
app.appType
app.created_by
app.created_at
app.last_modified_at
app.last_modified_by
app.{custom_attributes}
developer.id
developer.userName
developer.firstName
developer.lastName
developer.email
developer.status
developer.apps
developer.created_by
developer.created_at
developer.last_modified_at
developer.{custom_attributes}
company.id
company.displayName
company.apps
company.appOwnerStatus
company.created_by
company.created_at
company.last_modified_at
company.last_modified_by
company.{custom_attributes}
GenerateAuthorizationCode operation
These variables are set when the GenerateAuthorizationCode policy operation executes successfully:
Variable Description
oauthv2authcode.{policy_name}.redirect_uri The redirect URI associated with the registered client app.
GenerateAccessToken
These variables are set when the GenerateAccessToken policy operation executes successfully for the
authorization code, password, and client credentials grant type flows:
Variable Description
These variables are set when the GenerateAccessTokenImplicit policy operation executes successfully for the
implicit grant type flow:
Variable Description
RefreshAccessToken operation
These variables are set when the RefreshAccessToken policy operation executes successfully:
Variable Description
GenerateErrorResponse
Variable Description
Error codes
SAP API Management generates and manages a set of OAuth resources for apps. Depending on the OAuth
configuration for an organization, SAP API Management will generate and manage access tokens, authorization
codes, and refresh tokens. For each OAuth resource that it generates, SAP API Management also creates and
stores a profile.
The GetOauthV2Info policy type enables you to get attributes of tokens and to make them available to policies and
code executing in an API proxy. This policy type can be useful when you need to configure dynamic, conditional
behavior based on a value in an access token.
An access token has the following JSON representation on SP API Management:
{
"issued_at" : "1372170159093",
"application_name" : "ccd1803b-b557-4520-bd62-ddd3abf8e501",
"scope" : "READ",
"status" : "approved",
"api_product_list" : "[FreeProduct]",
"expires_in" : "3599",
"developer.email" : "[email protected]",
"organization_id" : "0",
"refresh_token" : "82XMXgDyHTpFyXOaApj8C2AGIPnN2IZe",
"client_id" : "deAVedE0W9Z9U35PAMaAJYphBJCGdrND",
"access_token" : "shTUmeI1geSKin0TODcGLXBNe9vp",
Samples
You can provide a reference to a variable that contains the token. The policy configuration below will obtain the
access token by reference to query parameter called access_token. The policy expects the access token to be
presented by the app as a query parameter named access_token. The policy will use that access token to retrieve
the associated profile from SAP API Management's token store. The access token's profile will then be used to
populate a set of variables.
<GetOAuthV2Info name="GetTokenAttributes">
<AccessToken ref="request.queryparam.access_token"></AccessToken>
</GetOAuthV2Info>
The oauthv2accesstoken variables are then populated with values specific to the access token.
The values of the variables could then be accessed, for example, by JavaScript. For example, to retrieve the
scope(s) associated with an access token using JavaScript:
var scope = context.getVariable(‘oauthv2accesstoken.GetTokenAttributes.scope’);
You can also retrieve attributes of an access token by using a policy of type GetOAuthV2Info and referring to a
variable set by the execution of any OAuthV2 policy.
In some rare cases you may need to get the profile a statically configured token. You can do by providing the value
of the access token as an element.
<GetOAuthV2Info name="GetTokenAttributes">
<AccessToken>shTUmeI1geSKin0TODcGLXBNe9vp</AccessToken>
</GetOAuthV2Info>
You can do this with all other token types (client ID, authorization code, and refresh tokens) as well.
<GetOAuthV2Info name="GetAuthCodeAttributes">
<AuthorizationCode ref="request.queryparam.code"></AuthorizationCode>
</GetOAuthV2Info>
Example
<GetOAuthV2Info name="GetTokenAttributes">
<RefreshToken ref="request.queryparam.refresh_token"></RefreshToken>
</GetOAuthV2Info>
Element Reference
The element reference describes the elements and attributes of the GetOAuthV2Info policy.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<GetOAuthV2Info async="false" continueOnError="false" enabled="true" name="GetOAuthV2Info-1"
<DisplayName>Get OAuth v2.0 Info 1</DisplayName>
<AccessToken ref={some-variable}></AccessToken>
</GetOAuthV2Info
name The internal name of the policy. Characters you can use in the N/A Required
name are restricted to: A-Z0-9._\-$ %. However, the SAP API
Management UI enforces additional restrictions, such as
automatically removing characters that are not alphanumeric.
Optionally, use the <DisplayName> element to label the policy in
the management UI proxy editor with a different, natural-
language name.
continueOnError Set to false to return an error when a policy fails. This is expected false Optional
behavior for most policies.
Set to true to have flow execution continue even after a policy
fails.
async Note: This attribute does not make the policy execute false Optional
asynchronously.
When set to true, policy execution is offloaded to a different
thread, leaving the main thread free to handle additional
requests. When the offline processing is complete, the main
thread comes back and finishes handling the message flow. In
some cases, setting async to true improves API proxy
performance. However, overusing async can hurt performance
with too much thread switching.
<DisplayName> element
Use in addition to the name attribute to label the policy in the management UI proxy editor with a different,
natural-language name.
<DisplayName>Policy Display Name</DisplayName>
Presence: Optional
Type: String
<AccessToken> element
Retrieves the profile for an access token. You pass in a either a variable that contains the access token string or a
literal token string (rare case). In this example, the access token is retrieved from a query parameter passed in a
request.
<AccessToken ref="request.queryparam.access_token"></AccessToken>
Presence: Optional
Type: String
Valid values: Either a flow variable containing an access token string, or a literal string.
<AuthorizationCode> element
Retrieves the profile for an authorization code. You pass in a either a variable that contains the auth code string or
a literal token string (rare case). In this example, the auth code is retrieved from a query parameter passed in a
request. For a list of variables populated by this operation, see "Flow variables".
<AuthorizationCode ref="request.queryparam.authorization_code"></AuthorizationCode>
Presence: Optional
Valid values: Either a flow variable containing an auth code string, or a literal string.
<ClientId> element
Retrieves information related to a client ID. In this example, the client ID is retrieved from a query parameter
passed in a request. For a list of variables populated by this operation, see "Flow variables".
<ClientId>ref="request.queryparam.client_id"></ClientId>
Presence: Optional
Type: String
Valid values: Either a flow variable containing an auth code string, or a literal string.
<RefreshToken> element
Retrieves the profile for a refresh token. You pass in a either a variable that contains the refresh token string or a
literal token string (rare case). In this example, the refresh token is retrieved from a query parameter passed in a
request. For a list of variables populated by this operation, see "Flow variables".
<RefreshToken ref="request.queryparam.refresh_token"></RefreshToken>
Presence: Optional
Type: String
Valid values: Either a flow variable containing an refresh token string, or a literal string.
When an access token is granted or validated by a policy, the following attributes of the access token are set as
variables. These variables are then available to other policies or code executing in the same Flow. For example,
you might need to access these variables in another policy to enable custom behavior based on the scope
associated with the access token.
Client ID Variables
These variables are populated when the <ClientId> operation executes:
oauthv2client.{policy_name}.client_id
oauthv2client.{policy_name}.client_secret
oauthv2client.{policy_name}.redirection_uris (* Note the spelling here --
'redirection_uris')
oauthv2client.{policy_name}.developer.email
oauthv2client.{policy_name}.developer.app.name
oauthv2client.{policy_name}.developer.id
oauthv2client.{policy_name}.{custom_attribute_name}
SAP API Management generates and distributes OAuth access tokens to apps. SAP API Management stores
those access tokens and uses them to authorize consumer apps. Some other types of OAuth tokens are also
generated by SAP API Management. These include refresh tokens and authorization codes.
When SAP API Management generates these OAuth artifacts, it also generates 'profile' that contains metadata
related to the token or code. For example, the default access token profile contains name/value pairs that define
expiration time, the associated app and developer, and so on.
The JSON representation of an SAP API Management access token looks like the following:
{
"issued_at" : "1372170159093",
"application_name" : "ccd1803b-b557-4520-bd62-ddd3abf8e501",
"scope" : "READ",
"status" : "approved",
"api_product_list" : "[FreeProduct]",
"expires_in" : "3599",
"developer.email" : "[email protected]",
"organization_id" : "0",
"refresh_token" : "82XMXgDyHTpFyXOaApj8C2AGIPnN2IZe",
"client_id" : "deAVedE0W9Z9U35PAMaAJYphBJCGdrND",
"access_token" : "shTUmeI1geSKin0TODcGLXBNe9vp",
"organization_name" : "apifactory",
Samples
Below is an example policy used to update an OAuth 2.0 access token. The example below locates the access
token on the request message by looking for a query parameter called access_token. When an access token is
presented by a client app, the policy below will locate the access token in the query parameter. It will then update
the access token's profile in two ways: it will added a property called department.id to the profile. It will also
modify the access token's scope property to the value READ, WRITE.
<SetOAuthV2Info name="SetOAuthV2Info">
<AccessToken ref="request.queryparam.access_token"></AccessToken>
<Attributes>
<Attribute name="department.id"
ref="request.queryparam.department_id"></Attribute>
<Attribute name="scope" ref="">READ, WRITE</Attribute>
</Attributes>
</SetOAuthV2Info>
Note
If an attribute already exists in the access token profile, then it will be updated with the new value in the
policy. If an attribute does not exist, then the attribute will be added to the access token's profile.
Element Reference
The element reference describes the elements and attributes of the SetOAuthV2 policy.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<SetOAuthV2Info async="false" continueOnError="false" enabled="true"
name="SetOAuthV2Info-1">
<DisplayName>Set OAuth v2.0 Info 1</DisplayName>
<AccessToken ref={some-variable}></AccessToken>
<SetOAuthV2Info> attributes
name The internal name of the policy. Characters you can use in the N/A Required
name are restricted to: A-Z0-9._\-$ %. However, the SAP API
Management UI enforces additional restrictions, such as
automatically removing characters that are not alphanumeric.
Optionally, use the <DisplayName> element to label the policy in
the management UI proxy editor with a different, natural-
language name.
continueOnError Set to false to return an error when a policy fails. This is expected false Optional
behavior for most policies.
Set to true to have flow execution continue even after a policy
fails.
async Note: This attribute does not make the policy execute false Optional
asynchronously.
When set to true, policy execution is offloaded to a different
thread, leaving the main thread free to handle additional
requests. When the offline processing is complete, the main
thread comes back and finishes handling the message flow. In
some cases, setting async to true improves API proxy
performance. However, overusing async can hurt performance
with too much thread switching.
Use in addition to the name attribute to label the policy in the management UI proxy editor with a different,
natural-language name.
<DisplayName>Policy Display Name</DisplayName>
Default: N/A
If you omit this element, the the value of the policy'sname attribute is
used.
Presence: Optional
Type: String
<AccessToken> element
Identifies the variable where the access token is located. For example, if the access token is attached to request
message as a query parameter, specify request.queryparam.access_token. You can use any valid variable that
references the token. Or, could pass in the literal token string (rare case).
<AccessToken ref="request.queryparam.access_token"></AccessToken>
Default: N/A
Presence: Required
Type: String
Attributes
Attribute Description
<Attributes> element
A set of attributes in the access token profile that will be modified or augmented.
Default: N/A
Type: N/A
<Attributes>/<Attribute> element
Default: N/A
Presence: Optional
Type: N/A
Attributes
Policy-specific Variables
Samples
Below is an example policy used to delete an OAuth 2.0 access token. The example below locates the access
token to delete on the request message by looking for a header called access_token.
<DeleteOAuthV2Info name="DeleteAccessToken">
<AccessToken ref="request.header.access_token"></AccessToken>
</DeleteOAuthV2Info>
Below is an example policy used to delete an OAuth 2.0 authorization code. The example below locates the auth
code to delete on the request message by looking for a query parameter called code.
<DeleteOAuthV2Info name="DeleteAuthCode">
<AuthorizationCode ref="request.queryparam.code"></AuthorizationCode>
</DeleteOAuthV2Info>
Element Reference
The element reference describes the elements and attributes of the DeleteOAuthV2Info policy.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<DeleteOAuthV2Info async="false" continueOnError="false" enabled="true"
name="DeleteOAuthV2Info-1">
<DisplayName>Delete OAuth v2.0 Info 1</DisplayName>
<AccessToken ref={some-variable}></AccessToken>
<DeleteOAuthV2Info> attributes
async Set to true to specify that the policy should be run in a thread false Optional
pool different than the pool servicing the request/response flow.
Default is false.
This setting is only used for for internal optimization.
continueOnError Most policies are expected to return an error when a failure false Optional
occurs. By setting this attribute to true, Flow execution continues
on failure.
enabled Determines whether a policy is enforced or not. If set to false, a true Optional
policy is 'turned off', and not enforced (even though the policy
remains attached to a Flow).
name The internal name of the policy. This name is referenced in Step N/A Required
elements to attach the policy to a Flow.
Note: Characters you can use in the name are restricted to: A-Z0-
9._\-$ %. The Management UI enforces additional restrictions,
such as automatically removing characters that are not
alphanumeric.
<AccessToken> element
Identifies the variable where the access token to delete is located. For example, if the access token is attached to
request message as a query parameter called "access_token", specify request.queryparam.access_token. You
can use any valid variable that references the token. Or, could pass in the literal token string (rare case).
<AccessToken ref="request.queryparam.access_token"></AccessToken>
Type: String
Attributes
ref An access token variable. Typically, retrieved from a flow variable. For N/A Optional
example: request.header.token or request.queryparam.token.
<AuthorizationCode> element
Identifies the variable where the authorization code to delete is located. For example, if the auth code is attached
to request message as a query parameter called "code", specify request.queryparam.code. You can use any valid
variable that references the token. Or, could pass in the literal token string (rare case).
<AccessToken ref="request.queryparam.access_token"></AccessToken>
Default: N/A
Type: String
Attributes
ref An access token variable. Typically, retrieved from a flow variable. For N/A Optional
example: request.header.code or request.queryparam.code.
A natural-language name that labels the policy in the management UI proxy editor. If omitted, the
policy name attribute is used.
<DisplayName>DeleteOAuthV2Info 1</DisplayName>
Presence: Optional
Type: String
Output
On success, the policy returns a 200 status.
On failure, the policy returns 404 and output similar to the following (depending on whether you are deleting an
access token or an auth code):
HTTP/1.1 404 Not Found
Content-Type: application/json
Content-Length: 144
Connection: keep-alive
{"fault":{"faultstring":"Invalid Authorization
Code","detail":{"errorcode":"keymanagement.service.invalid_request-
authorization_code_invalid"}}}
This topic provides HTTP status codes and their related reason phrases you may encounter when OAuth throws
errors in SAP API Management.
For policy-specific error codes, see:
OAuthV2 policy
OAuth v1.0a policy
Authorization Code
No Redirect URI
Invalid Key
Missing Key
No Redirect URI
Invalid Client ID
No Client ID
Invalid GrantType
No Password
No AuthCode
Implicit
Invalid Client ID
No Client ID
No Response Type
No Redirect URI
Refresh Token
Invalid RefreshToken
Invalid Scope
No Client ID
Verify AccessToken
Invalid AccessToken
Invalid Resource
Invalid Scope
The Security Assertion Markup Language (SAML) specification defines formats and protocols that enable
applications to exchange XML-formatted information for authentication and authorization.
A "security assertion" is a trusted token that describes an attribute of an app, an app user, or some other
participant in a transaction. Security assertions are managed and consumed by two types of entities:
• Identity providers: Generate security assertions on behalf of participants
• Service providers: Validate security assertions through trusted relationships with identity providers
The SAML policy type enables API proxies to validate SAML assertions that are attached to inbound SOAP
requests. The SAML policy validates incoming messages that contain a digitally-signed SAML assertion, rejects
them if they are invalid, and sets variables that allow additional policies, or the backend services itself, to further
validate the information in the assertion.
Sample
The following is a sample policy of type ValidateSAMLAssertion.
<ValidateSAMLAssertion name="SAML">
<TrustStore>TrustStoreName</TrustStore>
<ValidateSigner>true</ValidateSigner>
<RemoveAssertion>false</RemoveAssertion>
<AssertionLocation>xpath</AssertionLocation>
<Message>request</Message>
<IgnoreContentType>false</IgnoreContentType>
</ValidateSAMLAssertion>
Policy processing:
1. The policy checks the inbound message to verify that the request's media type is XML, by checking if the
content type matches the formats text/(.*+)?xml or application/(.*+)?xml. If the media type is not XML, or if
"IgnoreContentType" is not set, then the policy will raise a fault.
2. The policy will parse the XML. If parsing fails then it will raise a fault.
3. The policy will validate the XML digital signature, using the values of TrustStore and ValidateSigner as
described above. If validation fails then it will raise a fault.
4. If present, the policy will check the current timestamp against the NotBefore and NotOnOrAfter elements in
the assertion, as described in SAML Core section 2.5.1.
5. Any additional rules for processing the "Conditions" as described in SAML Core section 2.5.1.1.
Once the policy has completed without raising a fault, the developer of the proxy can be sure of the following:
• The digital signature on the assertion is valid and was signed by a trusted CA
• The assertion is valid for the current time period
• The subject and issuer of the assertion will be extracted and set in flow variables. It is the responsibility of
other policies to use these values for additional authentication, such as checking that the subject name is
valid, or passing it to a target system for validation.
• Other policies, such as ExtractVariables, may be used to parse the raw XML of the assertion for more complex
validation.
The SAML policy type supports SAML assertions that match version 2.0 of the SAML Core Specification and
Version 1.0 of the WS-Security SAML Token Profile specification.
The SAML policy type enables API proxies to attach SAML assertions to outbound XML requests. Those
assertions are then available to enable backend services to apply further security processing for authentication
and authorization.
Sample
<GenerateSAMLAssertion name="SAML">
<AssertionLocation>xpath</AssertionLocation>
<Message>request</Message>
<IgnoreContentType>false</IgnoreContentType>
<KeyStore>
<Name>keystorename</Name>
<Alias>alias</Alias>
</KeyStore>
<Subject ref="reference">subject name</Subject>
<Issuer ref="reference">issuer name</Issuer>
<Template>
<!-- A lot of XML goes here, in CDATA, with {} around
each variable -->
</Template>
</GenerateSAMLAssertion>
Policy processing:
1. If the message is not XML, and IgnoreContentType is not set to true, then raise a fault.
2. If "Template" is set, then process the template as described for the AssignMessage policy. If any variables are
missing and IgnoreUnresolvedVariables is not set, then raise a fault.
3. If "Template" is not set, then construct an assertion that includes the values of the Subject and Issuer
parameters or their references.
4. Sign the assertion using the specified key.
5. Add the assertion to the message at the specified XPath.
Note
The ValidateSAMLAssertion can only be
attached to the ProxyEndpoint request Flow.
There are many pieces of information that may be specified in a SAML assertion. The SAML assertion itself is XML
that can be parsed using the ExtractMessage policy and other mechanisms in order to implement more complex
validations.
See Extract message content using ExtractVariables.
Variable Description
saml.issueInstant IssueInstant
The Basic Authentication policy type enables you to use the lightweight Basic Authentication for last-mile
security. The policy takes the username and password defined in the policy, Base64 encodes them, and adds the
resulting value to a variable. The resulting value is in the form Basic Base64EncodedString. You typically write
this value to an HTTP header, such as th Authorization header.
The policy also lets you decode credentials stored in a Base64 encoded string into a username and password.The
username and password are commonly stored the key/value store and then read from the key/value store at
runtime. For details on using key/value store, see Persist data using KeyValueMap.
The policy also lets you decode credentials on an inbound request.
Note
This policy does not enforce Basic Authentication on a request to an API proxy. Instead, you use it to
Base64 encode/decode credentials, typically when connecting to a backend server or using a service
callout policy, such as the Call services or APIs using ServiceCallout that requires Basic Authentication.
Samples
The following samples illustrate how you can use the Basic Authentication policy to encode and decode basic auth
credentials.
Outbound encoding
In the configuration below, username and password are from the variables specified in the ref attributes on the
<User> and <Password> elements. The variables must be set by another policy before this policy executes.
Typically, the variables are populated by values that are read from a key/value map. (See Persist data using
KeyValueMap.
<BasicAuthentication name="ApplyBasicAuthHeader">
<DisplayName>ApplyBasicAuthHeader</DisplayName>
<Operation>Encode</Operation>
<IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
<User ref="BasicAuth.credentials.username" />
<Password ref="BasicAuth.credentials.password" />
<AssignTo createNew="false">request.header.Authorization</AssignTo>
This configuration results in an Authorization HTTP header being applied to the outbound request message.
(The outbound request is the message that the API proxy sends to the backend service specified in the
TargetEndpoint configuration). The <User> and <Password> are concatenated with a colon prior to Base64
encoding.
Authorization: Basic TXlVc2VybmFtZTpNeVBhc3N3b3Jk
Imagine that you have a key/value map with the following entry:
{
"entry" : [ {
"name" : "username",
"value" : "MyUsername
}, {
"name" : "password",
"value" : "MyPassword
} ],
"name" : "BasicAuthCredentials"
}
Then you would attach the following KeyValueMapOperations policies before the BasicAuthentication policy. This
way, the values for <User> and <Password> are extracted from the key/value store and populated into the
variables BasicAuth.credentials.username and BasicAuth.credentials.password.
<KeyValueMapOperations name="getUsername" mapIdentifier="BasicAuthCredentials">
<Scope>apiproxy</Scope>
<Get assignTo="credentials.username" index='1'>
<Key>
<Parameter ref="BasicAuth.credentials.username"/>
</Key>
</Get>
</KeyValueMapOperations>
and
Note
Basic authentication does not provide confidentiality. Always send credentials over a TLS-enabled
(HTTPS) connection to your backend service.
Element reference
The element reference describes the elements and attributes of the BasicAuthentication policy.
<BasicAuthentication> attributes
name The unique name of the policy. Use this name N/A Yes
to reference the policy within a Step definition
element. Characters you can use in the name
are restricted to: A-Z0-9._\-$ %. However,
the SAP API Management UI enforces
additional restrictions, such as automatically
removing characters that are not
alphanumeric.
async Note: This attribute does not make the policy false Optional
execute asynchronously.
When set to true, policy execution is
offloaded to a different thread, leaving the
main thread free to handle additional
requests. When the offline processing is
complete, the main thread comes back and
<DisplayName> element
Use in addition to the name attribute to label the policy in the management UI proxy editor with a different,
natural-language name.
<DisplayName>Policy Display Name</DisplayName>
Default: N/A
If you omit this element, the the value of the policy's name attribute is
used.
Presence: Optional
Type: String
<Operation> element
<Operation>Encode</Operation>
Default: N/A
Presence: Required
Type: String.
Valid values include:
• Encode
• Decode
When set to true, the policy will not throw an error if a variable cannot be resolved. When used in the context of a
BasicAuthentication policy, this setting is usually set to false because it is generally beneficial to throw an error if
a username or password cannot be found in the variables specified.
<IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
Default: N/A
Presence: Required
Type: Boolean
<User> element
• For encoding, use the <User> element to specify the variable containing the username. Username and
password values are concatenated with a colon prior to Base64 encoding.
• For decoding, specify the variable where the decoded username is written.
<User ref="request.queryparam.username" />
Default: N/A
Presence: Required
Type: N/A
Attributes
ref The variable from which the policy dynamically reads the username N/A Required
(encode) or writes the username (decode).
<Password> element
For encoding, use the <Password> element to specify the variable containing the password.
For decoding, specify the variable where the decoded password is written.
<Password ref="request.queryparam.password" />
Presence: Required
Type: N/A
Attributes
ref The variable from which the policy dynamically reads the password N/A Required
(encode) or writes the password (decode).
<AssignTo> element
For encoding, this is the variable where the encoded value, in the form Basic Base64EncodedString is written.
For example, request.header.Authorization, corresponding to the Authorization header.
<AssignTo createNew="false">request.header.Authorization</AssignTo>
Default: N/A
Presence: Required
Type: N/A
Attributes
createNew For the BasicAuthentication policy, you will usually set this attribute to False Optional
false.
In the context of BasicAuthentication, you do not want to require that
the policy generate a new message. Instead, you want the destination
variable to be added to the existing request message.
For decoding, the variable containing the Base64 encoded string, in the form Basic Base64EncodedString. For
example, specify request.header.Authorization, corresponding to the Authorization header.
<Source>request.header.Authorization</Source>
Default: N/A
Presence: Required
Type: N/A
Flow variables
Note
If you see variables called BasicAuthentication.{policy_name}.fault.cause and
BasicAuthentication.{policy_name}.fault.name, they are not currently being used by SAP API
Management.
Error codes
Sometimes you will find it necessary to limit access to your APIs from a specific network or computer. You might
also need to identify specific IP addresses that cannot access your API, such as a network address that has been
identified as a malicious actor.
Configuring access control based on IP addresses is a useful way to provide coarse-grained control. For example,
if you only want computers under the control of your enterprise to access the APIs exposed in your test
environment, you can allow (or whitelist) the IP address range for your internal network. Developers working from
home can access these APIs using VPN.
Note
If you block a specific address, the computer using that IP address can still directs requests to your API
through a proxy. It is also possible to spoof (falsify) the IP address of a request, so the request appears to
come from a reputable source.
SAP API Management enables you to attach an Access Control policy to your APIs (request path), where you can
define a range of IPs and allow IPs within the specified range to access an operation or service.
The configuration and execution of an Access Control policy involves the following tasks:
• Define a set of match rules with one of two actions (ALLOW or DENY) associated with each.
• For each match rule, specify the IP address (SourceAddress element).
o Configure a mask for each IP address. You allow or deny access based on a mask value on the IP address.
For more information about IP addresses, see IP addresses and dotted notation.
o If the X-FORWARDED-FOR header is present in the request address, then the header value is considered
the source address.
• Specify the order in which the rules are tested.
• The system triggers the first matching rule in the ordered list, and then subsequent matching rules are
skipped.
o If the same rule is configured with both ALLOW and DENY actions, the rule that is defined first in the order
is triggered and the subsequent rule (with the other action) is skipped.
An IPv4 address consists of four bytes (32 bits). These bytes are also known as octets. To aid with readability,
humans typically work with IP addresses in dotted decimal notation. In this notation, there are periods between
each of the four numbers (octets) that make up an IP address. For example, an IP address the computers see as:
00001010 00001010 00001010 00001010
is written in dotted decimal notation as 10.10.10.10
The mask value as shown in the examples above identifies which of the four bytes (8, 16, 24, 32 bits) the match
rule considers when allowing or denying access.
vSamples
The mask values in the following IPv4 samples identify which of the four octets (8, 16, 24, 32 bits) the match rule
considers when allowing or denying access. The default value is 32. See the mask attribute in the Element
reference for more information.
Deny 10.10.10.10
<AccessControl name="ACL">
<IPRules noRuleMatchAction="ALLOW">
<MatchRule action="DENY">
<SourceAddress mask="32">10.10.10.10</SourceAddress>
</MatchRule>
</IPRules>
</AccessControl>
Deny 10.10.10.*
<AccessControl name="ACL">
<IPRules noRuleMatchAction="ALLOW">
<MatchRule action="DENY">
<SourceAddress mask="24">10.10.10.10</SourceAddress>
</MatchRule>
Deny 10.10.*.*
<AccessControl name="ACL">
<IPRules noRuleMatchAction="ALLOW">
<MatchRule action="DENY">
<SourceAddress mask="16">10.10.10.10</SourceAddress>
</MatchRule>
</IPRules>
</AccessControl>
<AccessControl name="ACL">
<IPRules noRuleMatchAction="ALLOW">
<MatchRule action="ALLOW">
<SourceAddress mask="32">10.10.10.20</SourceAddress>
</MatchRule>
<MatchRule action="DENY">
<SourceAddress mask="24">10.10.10.20</SourceAddress>
</MatchRule>
</IPRules>
</AccessControl>
Deny all requests from client address: 10.10.10.*, but allow 10.10.10.20.
Allow requests from any other client address.
<AccessControl name="ACL">
<IPRules noRuleMatchAction="DENY">
<MatchRule action="ALLOW">
<SourceAddress mask="16">10.10.10.10</SourceAddress>
</MatchRule>
</IPRules>
</AccessControl>
<AccessControl name="ACL">
<IPRules noRuleMatchAction="DENY">
<MatchRule action="ALLOW">
<SourceAddress mask="24">10.10.20.0</SourceAddress>
<SourceAddress mask="24">10.10.30.0</SourceAddress>
<SourceAddress mask="24">10.10.40.0</SourceAddress>
</MatchRule>
</IPRules>
</AccessControl>
<AccessControl name="ACL">
<IPRules noRuleMatchAction="ALLOW">
<MatchRule action="DENY">
<SourceAddress mask="24">10.10.20.0</SourceAddress>
<SourceAddress mask="24">10.10.30.0</SourceAddress>
<SourceAddress mask="24">10.10.40.0</SourceAddress>
</MatchRule>
<AccessControl name="ACL">
<IPRules noRuleMatchAction="DENY">
<MatchRule action="DENY">
<SourceAddress mask="24">10.10.0.0</SourceAddress>
<SourceAddress mask="24">10.20.0.0</SourceAddress>
<SourceAddress mask="24">10.30.0.0</SourceAddress>
</MatchRule>
<MatchRule action="ALLOW">
<SourceAddress mask="16">10.10.0.0</SourceAddress>
<SourceAddress mask="16">10.20.0.0</SourceAddress>
<SourceAddress mask="16">10.30.0.0</SourceAddress>
</MatchRule>
</IPRules>
</AccessControl>
Usage notes
In addition to protecting your APIs against malicious IPs, the Access Control policy also gives you control over
legitimate IP access. For example, if you only want computers under the control of your enterprise to access the
APIs exposed in your test environment, you can allow (or whitelist) the IP address range for your internal network.
Developers working from home can access these APIs using VPN.
The configuration and execution of an Access Control policy includes the following tasks and behaviors:
• Define a set of match rules with one of two actions (ALLOW or DENY) associated with each.
• For each match rule, specify the IP address (SourceAddress element).
o Configure a mask for each IP address. You allow or deny access based on a mask value on the IP address.
o If the X-FORWARDED-FOR header is present in the request address, then the header value is considered
the source address. If there are multiple addresses in the header, use the <ValidateBasedOn> element to
control which are evaluated.
• Specify the order in which the rules are tested.
• All the match rules are executed in the given order. When a rules matches, the corresponding action is
executed and following match rules are skipped.
o If the same rule is configured with both ALLOW and DENY actions, the rule that is defined first in the order
is triggered and the subsequent rule (with the other action) is skipped.
CIDR notation (Classless Inter-Domain Routing) is a way of indicating a range of IP addresses through masking. It
applies to both IPv4 and IPv6. Here's how it works. We'll use IPv4 in our examples for simplicity.
IP addresses are groups of numbers separated by periods. Each number is a specific number of bits (8 for IPv4
and 16 for IPv6). The IPv4 address 10.20.30.40 looks like this in binary:
00001010 . 00010100 . 00011110 . 00101000
That's 4 groups of 8 bits, or 32 total bits. With CIDR, you can indicate a range by adding a /number (1-32) to the IP
address, like this:
10.20.30.40/16
In this case, the 16 is the number you would use for the mask attribute value in this policy.
This notation means, "Keep the first 16 bits exactly as is, the remaining bits can be anything." For example:
Notice that the mask happens at the end of group two. This makes things nice and tidy, in essence creating a
mask like this: 10.20.*.*. In most cases, using multiples of 8 (IPv4) and 16 (IPv6) will give you the masking level
you want:
IPv4: 8, 16, 24, 32
IPv6: 16, 32, 48, 64, 80, 96, 112, 128
Here it gets a litle tricky: keep the first 22 bits and allow anything in the rest—per group. In group 3, keep the first 6
bits, the last two can vary. That's four possible combinations (00, 01, 10, 11), leaving the following possible
numbers in group 3: 28, 29, 30, and 31. Since none of group 4 is affected by the mask, values can be anything
from 0 to 255.
Element reference
The element reference describes the elements and attributes of the Access Control policy.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<AccessControl async="false" continueOnError="false" enabled="true" name="Access-
Control-1">
<DisplayName>Access Control 1</DisplayName>
<IPRules noRuleMatchAction="ALLOW">
<MatchRule action="ALLOW">
<SourceAddress mask="32">10.10.10.20</SourceAddress>
</MatchRule>
<MatchRule action="DENY">
<SourceAddress mask="24">10.10.10.20</SourceAddress>
</MatchRule>
</IPRules>
<ValidateBasedOn>X_FORWARDED_FOR_ALL_IP</ValidateBasedOn>
</AccessControl>
<AccessControl> attributes
name The internal name of the policy. Characters you can use in the NA Required
name are restricted to: A-Z0-9._\-$ %. However, the management
UI enforces additional restrictions, such as automatically
removing characters that are not alphanumeric.
Optionally, use the <DisplayName> element to label the policy in
the management UI proxy editor with a different, natural-language
name.
continueOnError Set to false to return an error when a policy fails. This is expected False Optional
behavior for most policies.
Set to true to have flow execution continue even after a policy fails.
async Note: This attribute does not make the policy execute False Optional
asynchronously.
When set to true, policy execution is offloaded to a different
thread, leaving the main thread free to handle additional requests.
When the offline processing is complete, the main thread comes
back and finishes handling the message flow. In some cases,
setting async to true improves API proxy performance. However,
overusing async can hurt performance with too much thread
switching.
<DisplayName> element
Use in addition to the name attribute to label the policy in the management UI proxy editor with a different,
natural-language name.
<DisplayName>Policy Display Name</DisplayName>
Default: N/A
If you omit this element, the the value of the policy'sname attribute is
used.
Presence: Optional
Type: String
The parent element containing the rules that allow or deny IP addresses. The noRuleMatchAction attribute lets
you define how to handle any IP addresses that aren't covered by your matching rules.
<IPRules noRuleMatchAction="ALLOW">
Default N/A
Presence Optional
Type N/A
Attributes
noRuleMatchAction The action to take (allow or deny access) if the String ALLOW Required
match rule specified is not resolved (unmatched).
Valid value: ALLOW or DENY
<IPRules>/<MatchRule> element
The action to take (allow or deny access) if the IP address matches the SourceAddress(es) you define.
<IPRules noRuleMatchAction="ALLOW">
<MatchRule action="ALLOW">
<SourceAddress mask="32">10.10.10.20</SourceAddress>
</MatchRule>
<MatchRule action="DENY">
<SourceAddress mask="24">10.10.10.20</SourceAddress>
</MatchRule>
</IPRules>
Default N/A
Presence Optional
Type N/A
action The action to take (allow or deny access) if the match rule String ALLOW Required
specified is not resolved (unmatched).
Valid value: ALLOW or DENY
<IPRules>/<MatchRule>/<SourceAddress> element
Default N/A
Presence Optional
Type String
Attributes
mask The mask attribute is a way to indicate the range of IP Intege N/A Required
addresses to allow or deny. Mask is the equivalent of using r
CIDR notation (Classless Inter-Domain Routing). For example:
<SourceAddressmask="24">192.168.100.0</SourceAddress
>
is equivalent to the following CIDR notation:
192.168.100.0/24
Valid values:
IPv4: 1-32
IPv6: 1-128
A value of zero (0) is valid only for IP 0.0.0.0, hence
impractical.
<ValidateBasedOn> element
If the X-FORWARDED-FOR HTTP header is present in the request address, then the header value is considered
the source address.
If there are multiple IP addresses you want to check in the X-FORWARDED-FOR header—for example, if the
header contains the client IP address along with the IP addresses of proxies through which the request was sent
(client, proxy1, proxy2)—use this ValidateBasedOn element to control which of the IP addresses are checked.
You must enable this feature, which involves setting the feature.enableMultipleXForwardCheckForACL property in
your organization. To enable it, see the API call below.
The value you enter in this element lets you determine whether to check all IP addresses in the header (default),
only the first IP address, or only the last IP address.
<ValidateBasedOn>X_FORWARDED_FOR_ALL_IP</ValidateBasedOn>
Default X_FORWARDED_FOR_ALL_IP
Presence Required
Type String
You can set the feature.enableMultipleXForwardCheckForACL property with the following API call:
curl -u email:password -X POST -H "Content-type:application/xml"
http://host:8080/v1/o/myorg -d \
"<Organization type="trial" name="MyOrganization">
<DisplayName>MyOrganization</DisplayName>
<Environments/>
<Properties>
<Property name="feature.enableMultipleXForwardCheckForACL">true</Property>
Like XML-based services, APIs that support JavaScript object notation (JSON) is vulnerable to content-level
attacks. Simple JSON attacks attempt to use structures that overwhelm JSON parsers to crash a service and
induce application-level denial-of-service attacks.
The JSONThreatProtection policy minimizes the risk posed by such attacks by enabling you to specify limits on
various JSON structures, such as arrays and strings. All settings are optional and should be tuned to optimize
your service requirements against potential vulnerabilities.
Note
If a limit is not specified, the system applies a default value of -1 (the system equates a negative value to
no limit).
Configure the JSON Threat Protection policy using the following elements.
Note
The name attribute for this policy is restricted to these characters: A-Z0-9._\-$ %. However, the
Management UI enforces additional restrictions, such as automatically removing characters that are not
alphanumeric.
Object entry name length Specifies the maximum string length allowed for an
object's entry name.
String value length Specifies the maximum length allowed for a string
value.
Any server that receives online data is subject to attack, whether malicious or unintentional. Some attacks take
advantage of the flexibility of XML by constructing invalid documents that have the potential to compromise back-
end systems. Corrupt or extremely complex XML documents can cause servers to allocate more memory than is
available, tying up CPU and memory resources, crashing parsers, and generally disabling message processing
and creating application-level denial-of-service attacks.
SAP API Management enables you to enforce XMLThreatProtection policies that address XML vulnerabilities and
minimize attacks on your API.
You can screen against XML threats using the following approaches:
• Validate messages against an XML schema (.xsd)
• Evaluate message content for specific black-listed keywords or patterns
• Detect corrupt or malformed messages before those messages are parsed
The XMLThreatProtection policy can detect XML payload attacks based on configured limits.
Note
All limits are optional. If a limit is not specified, the system applies a default value of -1 (the system
equates a negative value to no limit).
Note
The name attribute for this policy is restricted to these characters: A-Z0-9._\-$ %. However, the
Management UI enforces additional restrictions, such as automatically removing characters that are not
alphanumeric.
Example-XMLThreatProtection policy
<XMLThreatProtection name="mypolicy">
<Source>request</Source>
<StructureLimits>
<NodeDepth>5</NodeDepth>
<AttributeCountPerElement>3</AttributeCountPerElement>
<NamespaceCountPerElement>2</NamespaceCountPerElement>
<ChildCount includeText="true"
includeComment="true"
includeProcessingInstruction="true"
includeElement="true">3</ChildCount>
</StructureLimits>
<ValueLimits>
<Text>15</Text>
<Attribute>10</Attribute>
<Namespace>10</Namespace>
<Comment>10</Comment>
<ProcessingInstructionData>10</ProcessingInstructionData>
</ValueLimits>
<NameLimits>
<Element>10</Element>
<Attribute>10</Attribute>
<Prefix>10</Prefix>
<ProcessingInstructionTarget>10</ProcessingInstructionTarget>
</NameLimits>
A regular expression, or regex for short, is a set of strings that specify a pattern in a string. Regular expressions
enable content to be programmatically evaluated for patterns. Regular expressions can be used, for example, to
evaluate entered a properly structured email address.
SAP API Management enables you to configure regular expressions that can be evaluated at runtime against API
traffic to identify common content-level threats that follow certain patterns. The policy extracts information from
a message (for example, URI Path, Query Param, Header, Form Param, Variable, XML Payload, or JSON Payload)
and evaluates that content against pre-defined regular expressions. If any specified regular expressions evaluate
to true, the message is considered a threat and is rejected.
The most common usage of RegularExpressionProtection is the evaluation of JSON and XML payloads for
malicious content.
For example, to evaluate JSON payloads for SQL injection attacks, evaluate the JSON payload using the following
JSONPath expression combined with a regular expression. The regular expression pattern is evaluated against
the content extracted by the JSONPath expression.
Example
You need to URL encode regular expressions in the XML configuration file. In the example below, the
following regular expression:
[\s]*((delete)|(exec)|(drop\s*table)|(insert)|(shutdown)|(update)|(\bor\b))
is encoded as:
%5B%5Cs%5D%2A%28%28delete%29%7C%28exec%29%7C%28drop%5Cs%2Atable%29%7C%28insert%29%7C%2
8shutdown%29%7C%28update%29%7C%28%5Cbor%5Cb%29%29
Example
<Put your example here>
<RegularExpressionProtection name="JsonSQLInjectionEvaluation">
<Source>request</Source>
<JSONPayload>
<JSONPath>
<Expression>$.</Expression>
<--The regular expression below is URL encoded -->
Blacklist Patterns
Regular expressions must be URL encoded in the policy's XML configuration file.
Note
The name attribute for this policy is restricted to these characters: A-Z0-9._\-$ %. However, the
Management UI enforces additional restrictions, such as automatically removing characters that are not
alphanumeric.
Patterns URIPath Extracts information from the request URI path and matches it
(Optional) with the specified regular expressions.
Header Extracts information from the request and response header and
matches it with the specified regular expressions.
Variable Extracts information from the given variable and matches it with
the specified regular expressions.
JSONPayload JSONPath Expression Specifies the JSONPath expression defined for the variable.
(Optional)
Pattern Defines the regular expression pattern.
RESTful services are often exposed over the open Internet for consumption by developers building apps. API
providers need a mechanism to prevent unauthorized access to the API. One approach is to provision developers
with API keys and secrets. Those keys can be used as authentication tokens, or they can be used to obtain OAUth
access tokens.
SAP API Management automatically generates API keys on behalf of apps. It enables API providers to view,
approve, and revoke API keys. By applying a policy of the type VerifyApiKey, you can enforce verification of API
keys at runtime. This ensures that no app can access a protected API without a valid key.
API keys are verified at runtime to ensure that:
• The API key presented is valid and has not been revoked
• The API key presented is approved to consume an API product that includes the URI in the request
The only setting required for the VerifyAPIKey defines the expected location of the API key. Only one key location
is supported per policy instance.
For instructions on configuring API key validation locally, refer to API keys.
Note
"API keys" are also referred to as "consumer keys" and "app keys". In OAuth, API keys are referred to as
'client id'. The names can be used interchangeably.
Samples
The policy extracts the API key from the request message by referencing the flow variable specified by
the ref attribute. In this example, the policy extracts the API key from a flow variable
named request.queryparam.apikey, which is populated by a query param named apikey.
Key in header
<VerifyAPIKey name="APIKeyVerifier">
<APIKey ref="request.header.AppKey" />
</VerifyAPIKey>
In this example, you configure the policy to look for the API key in a header named AppKey. The client app must
then pass the API key as the value of an HTTP header named AppKey.
Key in Variable
<VerifyAPIKey name="APIKeyVerifier">
<APIKey ref="requestAPIKey.key"/>
</VerifyAPIKey>
The policy can reference any variable that contains the key. The policy in this example extracts the API key from a
variable namedrequestAPIKey.key.
How that variable is populated is up to you. For example, you could use the Extract Variables policy to
populate requestAPIKey.key from a query parameter named myKey, as shown below:
<ExtractVariables async="false" continueOnError="false" enabled="true"
name="SetAPIKeyVar">
<Source>request</Source>
<QueryParam name="myKey">
<Pattern ignoreCase="true">{key}</Pattern>
</QueryParam>
<VariablePrefix>requestAPIKey</VariablePrefix>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</ExtractVariables>
SAP API Mangement automatically populates a set of flow variables when executing the Verify API Key policy for a
valid API key. You can use these variables to access information such as the app name, app ID, and information
about the developer or company who registered the app. In the example above, you use the Assign Message
policy to access the developer's first name, last name, and email address after the Verify API Key executes.
These variables are all prefixed by:
verifyapikey.{policy_name}
In this example, the Verify API key policy name is "verify-api-key". Therefore, you reference the first name of the
developer making the request by accessing the variable verifyapikey.verify-api-key.developer.firstName.
Element Reference
Following are elements and attributes you can configure on this policy.
<VerifyAPIKey async="false" continueOnError="false" enabled="true" name="Verify-API-
Key-1">
<DisplayName>Custom label used in UI</DisplayName>
<APIKey ref="variable_containing_api_key"/>
</VerifyAPIKey>
<VerifyAPIKey> attributes
<VerifyAPIKey async="false" continueOnError="false" enabled="true" name="Verify-API-
Key-1">
name The internal name of the policy. Characters you can use in the N/A Required
name are restricted to: A-Z0-9._\-$ %. However, the SAP API
Management UI enforces additional restrictions, such as
automatically removing characters that are not alphanumeric.
Optionally, use the <DisplayName> element to label the policy in
the management UI proxy editor with a different, natural-
language name.
continueOnError Set to false to return an error when a policy fails. This is expected false Optional
behavior for most policies.
Set to true to have flow execution continue even after a policy
fails.
async Note: This attribute does not make the policy execute false Optional
asynchronously.
When set to true, policy execution is offloaded to a different
thread, leaving the main thread free to handle additional
requests. When the offline processing is complete, the main
thread comes back and finishes handling the message flow. In
some cases, setting async to true improves API proxy
performance. However, overusing async can hurt performance
with too much thread switching.
To use asynchronous behavior in API proxies, see JavaScript
callouts.
Note
This topic pertains to SAP API Management SAP API Management on-premises only.
SAP API Management on-premise lets you leverage an LDAP provider in API calls. With the LDAP Policy,
applications can authenticate credentials against users stored in LDAP, and you can retrieve distinguished names
(DNs) from LDAP—the metadata, or attributes, associated with each user, such as email, address, and phone
number. The returned DN is stored in a variable for further use by the API proxy.
The LDAP Policy provides:
• Authentication: User credentials supplied in the request are validated against credentials in the LDAP
provider. The LDAP policy gives you a lot of flexibility with authentication, letting you use any DN value along
with the password, even if that DN value you want isn't in the request. For example, say you need to use email
password for authentication. The following options are possible:
o If the email is in the request, you can simply use that with the password for LDAP authentication.
o If the email isn't in the request, but another DN attribute is (such as phone number), you can use the
phone number to get the corresponding email from LDAP, then use email / password to authenticate.
• Distinguished name (DN) search: In addition to authentication, you can also use the LDAP Policy to identify a
user attribute in the request, such as email, and perform a query that retrieves other DN attributes from LDAP
for that user. The retrieved DN is stored in a variable.
Use case
Use the LDAP Policy when access to protected resources should be limited to users in your LDAP provider—such
as your admin users, organization users, and developers—especially when OAuth token access is either
unnecessary or too heavyweight. The policy is also designed for retrieving DN metadata for use in API proxy flows.
Example
You can have an API call execute only when a user is successfully authenticated against LDAP; and then
optionally retrieve DN attributes for the user after authentication succeeds.
Samples
Following are examples of using the LDAP Policy for authentication and DN search. See the “Policy settings
reference” and “Policy-specific variables” sections below for more information on these examples.
Note
Notice that in the Authentication block there is no UserName, which is not allowed when using
SearchQuery to retrieve another DN attribute for authentication.
To search LDAP and retrieve DN attributes, the request must include administrator credentials.
<Ldap name="4GLdapPolicy">
<!-- using a custom LDAP provider -->
<LdapConnectorClass>com.mycompany.MyLdapProvider</LdapConnectorClass>
<LdapResource>MyLdap</LdapResource>
<Search>
<BaseDN></BaseDN>
<SearchQuery>mail={request.header.mail}</SearchQuery>
<Attributes>
Response Codes
Following are the HTML response codes the policy returns for success or failure:
• Success: 200
• Failure: 401
Note
The name attribute for this policy is restricted to these characters: A-Z0-9._\-$ %. However, the
Management UI enforces additional restrictions, such as automatically removing characters that are not
alphanumeric.
Element Description
Ldap Parent element with a name attribute for you to enter the policy
name.
LdapConnectorClass When using the LDAP Policy with a custom LDAP server (not
provided by SAP API Management), specify the fully qualified LDAP
connector class. That’s the class in which you implemented
SAP API Management ExternalLdapConProvider interface.
LdapResource Enter the environment name of the LDAP resource (you must create
this resource in your environment).
BaseDN The base level of LDAP under which all of your data exists.
Authentication
Search
SearchQuery By identifying the user with metadata in the request or response, you
can use this element to retrieve additional DN attributes for the user
from LDAP. For example, if the request contains the user email, and
your LDAP defines a “mail” attribute for storing user email addresses,
you’d use the following setting:
<SearchQuery>mail={request.header.mail}</SearchQuery>
This query searches LDAP for an email matching the email in the
request, and the policy can now retrieve additional DN attributes for
that user with the Attributes element.
Policy-Specific Variables
Variable Description
APIs are at their best when they are combined to create composite services that bundle resources from multiple
services and API providers. One way of bundling API calls is to configure a ServiceCallout policy within a request
or response flow.
A typical use case involves a service callout from a response flow to a third-party API (external service). The
response from the third-party API is parsed and inserted in the response message to the requesting app. The data
returned from the backend service is enriched with the data obtained from the third-party API, providing the end
users of the app with data 'mashed up' from multiple services. Using a ServiceCallout policy, you can configure an
API proxy to make multiple API calls to deliver relevant customer reviews, items from a partner’s retail catalog,
and so on.
(An alternative approach to ServiceCallout is an HTTP Client written in JavaScript using the JavaScript object
model.
Policy Composition
Policy composition is an important concept to understand when configuring ServiceCallouts. Policy composition
is the definition of a sequence of policies that work together to perform a task. The ServiceCallout is usually used
with two other policy types, AssignMessage and ExtractVariables. The AssignMessage policy is used to populate
the request message sent to the remote service. The ExtractVariables policy is used to parse the response and to
extract specific content.
The typical ServiceCallout policy composition involves:
1. AssignMessage Policy: Creates a request message, populates HTTP headers, query parameters, sets the
HTTP verb, etc.
2. ServiceCallout Policy: References a message created by the Assign Message policy, defines a target URL for
the external call, and defines a name for the response object that the target service returns.
3. ExtractVariables Policy: Typically defines a JSONPath or XPath expression that parses the message
generated by the preceding ServiceCallout policy. The policy then sets variables containing the values parsed
from the ServiceCallout response.
For more information, see Generate or modify messages using AssignMessage and Extract message content
using ExtractVariables.
Sample
The following ServiceCallout policy submits a request to the Google Geocoding API. The content of the request
message is extracted from a variable called GeocodingRequest (which could be populated, for example, by an
AssignMessage policy). The response message is assigned to the variable called GeocodingResponse, where it is
available to be parsed, for example, by an ExtractVariables policy or by custom code written in JavaScript.
Note
The name attribute for this policy is restricted to these characters: A-Z0-9._\-$ %. However, the
Management UI enforces additional restrictions, such as automatically removing characters that are not
alphanumeric.
Request (Optional) The variable that contains the request message to be sent by the ServiceCallout.
• By default, clearPayload is false.
• If clearPayload is set to true, the request payload is cleared after the request is
sent to the HTTP target.
• Use the clearPayload option only if the request message is not required after
the ServiceCallout is executed, because clearPayload allocates memory during
message processing.
• The policy returns an error if the request message cannot be resolved by the
element or is of an invalid request message type.
Response (Optional) Output of the ServiceCallout (usually the response message received from the
target) that will be assigned to the response variable.
The output generated by the policy is assigned to the variable only when the entire
response is read successfully by the policy. If the response message fails for any
reason, the policy returns an error.
If this element is not specified, the policy execution does not wait for response to
be completely read and executes the message flow steps.
Timeout (Optional) The time in milliseconds that the ServiceCallout policy will wait for a response from
the target before exiting. The default timeout for ServiceCallout is determined by
the default HTTP timeout setting for SAP API Management, which is 120000
milliseconds (120 seconds).
HTTPTargetConnection Provides transport details such as URL, SSL, HTTP properties. See
theTargetEndpoint configuration reference.
Note
You can use flow variables to construct the URL in an
HttpTargetConnection element. See the example below.
Example
ServiceCallout policy
<ServiceCallout name="myPolicy">
<Request clearPayload="false" variable="myRequest"/>
<Response>myResponse</Response>
<HTTPTargetConnection>
<Properties/>
<URL>http://example.com</URL>
</HTTPTargetConnection>
</ServiceCallout>
Example
The StatisticsCollector policy type enables you to collect statistical data for messages processed in a flow, such
as product ID, price, REST action, client and target URL, and message length (predefined flow variables as well as
custom variables). The data is then provided to the analytics server, which analyzes the statistics and generates
reports. You can view the reports through Analytics Services.
You attach the StatisticsCollector Policy to the response path in your API proxy, where you can capture and
publish a range of statistics to the analytics server.
For more information on how to analyze your data using analytics services, see Analyze API message content
using custom analytics.
name Custom name provided in the referenced variable. The name cannot contain
spaces or dashes. In the example below, the referenced variable
is product.id.
Note
The following restrictions apply:
• Names cannot be multiple-word (no spaces).
• No quotation marks, underscores, hyphens, or periods.
• No special characters.
• In addition to the above, follow the column naming restrictions here:
http://www.postgresql.org/docs/8.0/static/sql-syntax.html#SQL-
SYNTAX-IDENTIFIERS
Ref Flow variable that can be a predefined variable or a variable defined in the XML
payload of the Extract Variables policy. See Extract message content using
ExtractVariables.
If provided, overrides the existing datatype of ref. Note that the type can be
left empty only if ref is a predefined variable or the type is declared in the XML
payload of the Extract Variables policy.
You can set the defaultval as shown in the following example to initialize a variable with a static, default value. If
you provide a default value, then the default value you provide will be assigned to the variable the variable only
when the variable does not get initialized during the message flow. If you do not provide a defaultval, then the
variable is assigned normally during the message flow and calls fail if the variable is not resolved.
Example
<StatisticsCollector name="publishPurchaseDetails">
<Statistics>
<Statistic name="productID" ref="product.id" type="string">{defaultval}</Statistic>
<Statistic name="price" ref="product.price" type="string">{defaultval}</Statistic>
</Statistics>
</StatisticsCollector>
SAP API Management provides a range of out-of-the-box policy capabilities that address common API
management requirements. However, there are some cases where your API requires custom behavior that is not
covered by SAP API Management standard policy palette. To support these requirements, SAP API Management
exposes scripting interfaces to ease the task of implementing custom behaviors in the proxied API message flow.
One approach is to attach your own JavaScript to an API flow, which SAP API Management then executes at
runtime.
There are many use cases for the JavaScript policy. For example, you can get and set flow variables, execute
custom logic and perform fault handling, extract data from requests or responses, dynamically edit the backend
target URL, and much more. This policy allows you to implement custom behavior that is not covered by any other
standard SAP API Management policies. In fact, you can use a JavaScript policy to achieve many of the same
behaviors implemented by other policies, like AssignMessage and ExtractVariable.
Basically, the JavaScript policy specifies the name of the JavaScript source file to execute when the step to which
the policy is attached executes. The source file is always stored in a standard location within the proxy
bundle: apiproxy/resources/jsc. Or, you can also store the source code in a resource file at the environment or
organization level. You can also upload your JavaScript through the management UI proxy editor.
JavaScript source files must always have a .js extension.
Samples
Here's a common use case: extracting data from a request body, storing it in a flow variable, and using that flow
variable elsewhere in the proxy flow. Let's say you have a weather app where the user enters their zip code in an
HTML form and submits it. You want the API proxy to extract the form data and dynamically add it to the URL
used to call the backend service. How would you do this in a JavsScript policy?
Note
If you want to try out this example, we assume you've created a new proxy in the proxy editor. When you
create it, just give it a backend service URL of: http://www.example.com. For this example, we're going to
rewrite the backend URL dynamically. If you don't know how to create a new proxy, refer to the getting
started tutorial.
if (context.flow=="PROXY_REQ_FLOW") {
var woeid = context.getVariable("request.formparam.woeid");
context.setVariable("location.woeid", woeid);
}
One final thing, let's take a look at the XML definition for the JavaScript policy used in this example. The important
thing to note is that the<ResourceURL> element is used to speicfy the JavaScript source file to execute. This
same pattern is used for any JavaScript source file:jsc://filename.js. If you're JavaScript code requires includes,
you can use one or more <IncludeURL> elements to do that, as described later in this reference.
You can add a <Property> element in configuration, then retrieve the element's value with JavaScript at runtime.
Use the element's name attribute to specify the name with which to access the property from JavaScript code.
The <Property> element's value (the value between the opening and closing tags) is the literal value that will be
received by the JavaScript.
In JavaScript, you retrieve the policy property value by accessing it as a property of the Properties object, as in the
following:
• Configure the property. Here, the property value is the variable name response.status.code.
<Javascript async="false" continueOnError="false" enabled="true" timeLimit="200"
name="JavascriptURLRewrite">
<DisplayName>JavascriptURLRewrite</DisplayName>
<Properties>
<Property name="source">response.status.code</Property>
</Properties>
<ResourceURL>jsc://JavascriptURLRewrite.js</ResourceURL>
</Javascript>
• Retrieve the property with JavaScript. Here, the retrieved value -- a variable name -- is then used by
the getVariable function to retrieve the variable's value.
var responseCode = properties.source; // Returns "response.status.code"
var value = context.getVariable(responseCode); // Get the value of
response.status.code
context.setVariable("response.header.x-target-response-code", value);
Element reference
The element reference describes the elements and attributes of the JavaScript policy.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Javascript async="false"
continueOnError="false" enabled="true" timeLimit="200"
name="JavaScript-1">
<DisplayName>JavaScript 1</DisplayName>
<Properties>
<Property name="propName">propertyValue<Property>
</Properties>
<ResourceURL>jsc://my-javascript-source-file</ResourceURL>
<IncludeURL>jsc://a-javascript-library-file</IncludeURL>
<Javascript> Attributes
name The internal name of the policy. Characters you can use in the N/A Required
name are restricted to: A-Z0-9._\-$ %. However, the SAP API
Management UI enforces additional restrictions, such as
automatically removing characters that are not alphanumeric.
Optionally, use the <DisplayName> element to label the policy in
the management UI proxy editor with a different, natural-
language name.
continueOnError Set to false to return an error when a policy fails. This is expected false Optional
behavior for most policies.
Set to true to have flow execution continue even after a policy
fails.
async Note: This attribute does not make the policy execute false Optional
asynchronously.
When set to true, policy execution is offloaded to a different
thread, leaving the main thread free to handle additional
requests. When the offline processing is complete, the main
thread comes back and finishes handling the message flow. In
some cases, setting async to true improves API proxy
performance. However, overusing async can hurt performance
with too much thread switching.
To use asynchronous behavior in API proxies, see JavaScript
callouts.
Use in addition to the name attribute to label the policy in the management UI proxy editor with a different,
natural-language name.
<DisplayName>Policy Display Name</DisplayName>
Default: N/A
If you omit this element, the the value of the policy'sname attribute is
used.
Presence: Optional
Type: String
<IncludeURL> element
Specifies a JavaScript library file to be loaded as dependency to the main JavaScript file specified with
the <ResourceURL> element. The scripts will be evaluated in the order in which they are listed in the policy. Your
code can use the objects, methods, and properties of the JavaScript object model.
Include more than one JavaScript dependency resource with additional <IncludeURL> elements.
Note
If your JavaScript files are stored at the organization or environment level, be sure they were uploaded
correctly with cURL using the -Foption or as a file attachment through a REST client. Content-Type
is multipart/form-data.
<IncludeURL>jsc://my-javascript-dependency.js</IncludeURL>
Default: None
Presence: Optional
Type: String
<Property> element
Default: None
Presence: Optional
Type: String
Attributes
<ResourceURL> element
Specifies the main JavaScript file that will execute in the API flow. You can store this file at the API proxy scope
(under /apiproxy/resources/jsc in the API proxy bundle or in the Scripts section of the API proxy editor's
Navigator pane), or at the organization or environment scopes for reuse across multiple API proxies, as described
in Resource files. Your code can use the objects, methods, and properties of the JavaScript object model.
<ResourceURL>jsc://my-javascript.js</ResourceURL>
Default: None
Presence: Required
Type: String
Flow Variables
This policy does not populate any variables by default; however, you can set (and get) flow variables in your
JavaScript code by calling methods on the context object. A typical pattern looks like this:
context.setVariable("response.header.X-SAP-Target", context.getVariable("target.name"))
The context object is part of the SAP API Management JavaScript Object Model.
This policy defines the following error codes. For guidance on handling errors, see Fault handling.
The default format for error codes returned by policies is:
{
"code" : " {ErrorCode} ",
"message" : " {Error message} ",
"contexts" : [ ]
}
WrongResourceType Resource {0} is the wrong type. It is {1}: but Javascript steps use type
jsc:
SAP API Management provides a range of out-of-the-box policy capabilities that address common API
management requirements. However, there are some cases where your API requires custom behavior that is not
covered by SAP API Management's standard policy palette. In these cases, SAP API Management's exposes
scripting interfaces to ease the task of implementing custom behaviors in the proxied API message flow. One
approach is to attach your own Python script to an API flow, which the API Platform then executes at runtime.
A Python policy contains no actual code. Instead, a Python policy references a Python 'resource' and defines the
Step in the API flow where the Python script executes. You can upload your script through the Management UI
proxy editor, or you can include it in the /resources/py directory in API proxies that you develop locally.
Note
System calls, for example network I/O, filesystem read/writes, current user info, process list, and
CPU/memory utilization are not permitted by the security model. Although some such calls may be
Note
The name attribute for this policy is restricted to these characters: A-Z0-9._\-$ %. However, the
Management UI enforces additional restrictions, such as automatically removing characters that are not
alphanumeric.
IncludeURL (Optional) You can include zero or more of these elements. Each
elemnt should specify a single Python script in the
same form as the ResourceURL element. Scripts are
evaluated in the order in which they appear in the
policy.
Example
Example
Python Script
This shows what you might include in the python script itself.
import base64
username = flow.getVariable("request.formparam.client_id")
flow.setVariable("authorizationParam",authorization)
One of the best ways to track down problems in the API runtime environment is to log messages.
SAP API Management enables you to attach and configure a Message Logging policy on your API to log custom
messages to a local disk or to syslog.
The policy can be attached in the locations mentioned in this image:
Samples
Syslog
A common usage of the MessageLogging policy type is to log to a syslog account. When configured for syslog, an
API proxy will forward log messages from SAP API Management to a remote syslog server. You may already have
a sylog server available. If not, public log management services, such a loggly, are available.
For example, imagine that you need to log information about each request message that your API receives from
consumer apps. The value 3f509b58 represents a key value specific to the loggly service. If you have a loggly
account, substitute your loggly key. The log message that is generated will be populated with four values: the
organization, API proxy, and environment name associated with the transaction, along with the value for a query
parameter on the request message.
<MessageLogging name="LogToSyslog">
<Syslog>
<Message>[3f509b58 tag="{organization.name}.{apiproxy.name}.{environment.name}"]
Weather request for WOEID {request.queryparam.w}.</Message>
<Host>logs-01.loggly.com</Host>
Note:
Host and Port elements cannot refer to variables. They must contain static values.
Log Destination
A number of configurations are supported for logging messages to a file on the SAP API Management
management server.
You can send messages to third-party message logging providers over TLS/SSL by adding the <SSLInfo> block.
If HTTP streaming is enabled in an API proxy, neither request nor response messages will be buffered by
processing pipeline. When you need to log parsed message content, set BufferMessage to true.
Element reference
Use the following elements to configure the Message Logging policy type.
Note
The name attribute for this policy is restricted to these characters: A-Z0-9._\-$ %. However, the
Management UI enforces additional restrictions, such as automatically removing characters that are not
alphanumeric.
Caution:
TLS/SSL on the syslog server must be
configured with a valid CA certificate. Self-
signed certificates are not currently
supported.
logLevel Optional.
Valid values: INFO (default), ALERT, WARN, ERROR
Set a specific level of information to be included in the message log.
If you're using the FormatMessage element (setting it to true), your
logLevel setting affects the calculated priority score (the number
inside the angle brackets) in the SAP API Management-generated
information prepended to the message.
Usage Notes
When attaching a Message Logging policy to an API proxy flow, consider placing it in the ProxyEndpoint response,
in a special flow called PostClientFlow. The PostClientFlow executes after the response is sent to the requesting
client, which ensures that all metrics are available for logging.
Note: It's important to note that the response flow variable is not available in the PostClientFlow once processing
enters the error state. Instead, you can use the message variable to set values in the MessageLogging policy in the
PostClientFlow, ensuring that they will be set whether or not the error state was the previous context.
<ProxyEndpoint name="default">
...
<PostClientFlow>
<Response>
<Step>
<Name>Message-Logging-1</Name>
</Step>
</Response>
</PostClientFlow>
...
</ProxyEndpoint>
SAP API Management Edge logs messages as simple text, and you can configure logging to include variables,
such as the date and time when the request or response was received, the user identity on the request, the source
IP address from which the request was sent, and so on. SAP API Management Edge logs message
asynchronously, meaning that no latency that might be caused by blocking callouts is introduced to your API.
The MessageLogging policy writes logged messages in memory to a buffer. The message logger reads messages
from the buffer and then writes to the destination that you configure. Each destination has its own buffer.
If the write rate to the buffer increases beyond the read rate, the buffer overflows and logging will fail. If you
encounter this issue in an on-premises deployment of SAP API Management Edge, locate the message-
logging.properties and use this solution:
Increase the max.log.message.size.in.kb property (default value = 128 KB) in the message-
logging.properties file.
Note:
The response message variables in SAP API Management Edge are not available from the Error Flow. These
variables are also not available in PostClientFlow if the preceding flow was the Error Flow. If you want to log
response information from the PostClientFlow, use the message object. You can use this object to get at headers
and other information from the response whether or not there was an error.
By default, message logs are located in the following location on message processors:
/opt/apigee/var/log/edge-message-processor/messagelog/
{org}/{environment}/{api_proxy_name}/{revision}/{logging_policy_name}/
You can change the default log location by modifying the following properties in the message-logging.properties
file on the message processors:
For example, the combination of the two properties would set the logging directory
at/opt/apigee/var/log/custom/folder/messagelog/ (note that /messagelog is added
automatically).
If you want to store log files in a flat file structure so that all log files are put in the same directory, set
the enable.flat.directory.structure property to true in the message-logging.properties file on
message processors. Messages are stored in the directory specified by the properties above, and the file names
take the form
of {org}_{environment}_{api_proxy_name}_{revision}_{logging_policy_name}_{filename}.
Default values can be specified for each variable in message template separately. For example, if the
variablerequest.header.id cannot be resolved, then its value is replaced with the value unknown.
<Message>This is a test message. id = {request.header.id:unknown}</Message>
A common default value can be specified for all the unresolved variables by setting the
defaultVariableValue attribute on the the Message element:
<Message defaultVariableValue="unknown">This is a test message. id =
{request.header.id}</Message>
Note:
The default variable value cannot contain spaces.
The Message Logging policy lets you send syslog messages to third-party log management services, such as
Splunk, Sumo Logic, and Loggly. If you want to send syslog to one of those services, see that service's
documentation to configure the service's host, port, and protocol, then set the Syslog element on this policy
accordingly.
Note:
Proxy calls succeed when logging fails
There's a difference between policy errors and message logging errors. The flow variables here are populated only
when the policy itself fails, not when message logging fails. Because message logging is first written to buffer, the
API proxy will continue successful execution even if message logging ultimately fails (for example, if there's a
connection failure to the external syslog provider). Be sure to check your logs on a regular basis to make sure
logging is happening as expected
ExtractVariables Policy
Use the ExtractVariables policy to assign variables to URI paths, query parameters, HTTP headers, form
parameters, and business-specific information in request or response message content in XML or JSON format.
Other policies and code can then reference these variables to enable dynamic behavior.
Note
SAP API Management sets numerous variables automatically during request processing. See Variables
reference. Use the ExtractVariables policy to set additional variables, with values derived from message
content.
ExtractVariables can also be used to build content-driven Analytics reports. See Analyze API message content
using custom analytics.)
Need a more detailed overview of this policy? See Extract message content using ExtractVariables
Need policy error codes? See Error Codes for the ExtractVariables policy.
Extract content from the request or response messages, including headers, URI paths, JSON/XML payloads, form
parameters, and query parameters. The policy works by applying a text pattern to the message content and, upon
finding a match, sets a variable with the specified message content.
Samples
These policy code samples illustrate how to extract variables from the following types of artifacts:
URIs
<ExtractVariables name="ExtractVariables-1">
<DisplayName>Extract a portion of the url path</DisplayName>
<Source>request</Source>
<URIPath>
<Pattern ignoreCase="true">/accounts/{id}</Pattern>
</URIPath>
<VariablePrefix>urirequest</VariablePrefix>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</ExtractVariables>
Consider the sample policy code above. The <URIPath> element tells the Extract Variables policy to extract
information from the URI path. The<Pattern> element specifies the pattern to apply to the URI path. The pattern
is treated as a simple template, with the curly braces denoting the varying portion of the URI path.
The name of the variable to be set is determined by the value specified in the <VariablePrefix> element, as well as
the value enclosed in curly braces {} in the <Pattern> element. The two values are joined by an intervening dot,
resulting in a variable name of urirequest.id for example. If there is no <VariablePrefix> element, then the variable
name is just the value enclosed in curly braces.
Consider the sample policy code above working with the following incoming request:
GET http://org1-{env}.<host:port>/accounts/12797282
You can now access the variable urirequest.id in your proxy. For example, the following AssignMessage policy
copies it to the payload of the request:
<AssignMessage async="false" continueOnError="false" enabled="true" name="GetURIPath">
<DisplayName>GetURIPath</DisplayName>
<Set>
<Payload contentType="text/xml">
<ExtractURI>{urirequest.id}</ExtractURI>
</Payload>
</Set>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
<AssignTo createNew="false" transport="http" type="request"/>
</AssignMessage>
Query Params
<ExtractVariables name="ExtractVariables-2">
<DisplayName>Extract a value from a query parameter</DisplayName>
<Source>request</Source>
<QueryParam name="code">
<Pattern ignoreCase="true">DBN{dbncode}</Pattern>
</QueryParam>
<VariablePrefix>queryinfo</VariablePrefix>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</ExtractVariables>
Consider the sample policy code above. Suppose that your API design stipulates that incoming requests must
carry a query parameter named code.code holds a term that looks like DBNXXXXX, where DBN is fixed and
the XXXXX denotes a varying string. You can use this policy to extract the varying string.
Consider the sample policy code above working with the following incoming request:
GET http://org1-{env}.<host:port>/accounts/12797282?code=DBN88271
When SAP API Management applies the Extract Variables policy code above to this incoming request, it sets the
variable queryinfo.dbncode to 88271. After SAP API Management executes the policy, subsequent policies or
code in the processing flow can refer to the variable named queryinfo.dbncode to get the string value 88271.
Multiple Params
<ExtractVariables name="ExtractVariables-2">
<DisplayName>Extract a value from a query parameter</DisplayName>
<Source>request</Source>
<QueryParam name="w">
<Pattern ignoreCase="true">{firstWeather}</Pattern>
</QueryParam>
<QueryParam name="w.2">
<Pattern ignoreCase="true">{secondWeather}</Pattern>
</QueryParam>
<VariablePrefix>queryinfo</VariablePrefix>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</ExtractVariables>
Suppose your API design allows you to specify multiple query paramaters with the same name. You can use this
policy to extract the value of multiple instances of the query parameter "w". To reference these query parameters
in the Extract Variables policy, you use indexes, where the first instance of the query parameter has no index, the
second is at index 2, the third at index 3, etc.
Consider the sample policy code above working with the following incoming request:
GET http://org1-{env}.<host:port>/weather?w=Boston&w=Chicago
When SAP API Management applies the Extract Variables policy code above to this incoming request, it sets the
variable queryinfo.firstWeather toBoston and the variable queryInfo.secondWeather to Chicago.
Headers
<ExtractVariables name='ExtractVariable-OauthToken'>
<Source>request</Source>
<Header name="Authorization">
<Pattern ignoreCase="false">Bearer {oauthtoken}</Pattern>
</Header>
<VariablePrefix>clientrequest</VariablePrefix>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</ExtractVariables>
Suppose that your API uses OAuth v2.0 bearer tokens. Consider the sample policy code above working with a
request carrying an OAuth v2.0 token that includes a header like
this: Authorization: Bearer TU08xptfFfeM7aS0xHqlxTgEAdAM.
As the API designer, suppose that you want to use the token value (but not the entire header) as a key in a cache
lookup. You could use the Extract Variables policy code above to extract the token.
When SAP API Management applies the Extract Variables policy code above to this header, it will set the
variable clientrequest.oauthtoken toTU08xptfFfeM7aS0xHqlxTgEAdAM.
You can now access the variable clientrequest.oauthtoken in your proxy. For example, the following
AssignMessage policy copies it to the payload of the request:
<AssignMessage async="false" continueOnError="false" enabled="true" name="GetURIPath">
<DisplayName>GetHeader</DisplayName>
JSON
<ExtractVariables name="ExtractVariables-3">
<Source>response</Source>
<JSONPayload>
<Variable name="latitude" type="float">
<JSONPath>$.results[0].geometry.location.lat</JSONPath>
</Variable>
<Variable name="longitude" type="float">
<JSONPath>$.results[0].geometry.location.lng</JSONPath>
</Variable>
</JSONPayload>
<VariablePrefix>geocoderesponse</VariablePrefix>
</ExtractVariables>
The Extract Variables policy can extract values from complex structures, such as JSON messages. The sample
policy code above shows how to extract a variable from a portion of a JSON message payload.
The <JSONPayload> element tells the policy to extract a variable from a JSON payload. You specify the portion to
extract using a JSON path expression in which the $ character refers to the root node of the JSON message.
When SAP API Management applies the Extract Variables policy code above to this JSON message, it sets two
variables: geocoderesponse.latitude andgeocoderesponse.longitude. Both variables use the same variable prefix
of geocoderesponse. The suffix for these variables is specified explicitly by
the <Variable> element's name attribute.
The variable geocoderesponse.latitude gets the value 37.42291810. The variable geocoderesponse.longitude gets
the value-122.08542120.
You can now access the variable geocoderesponse.latitude in your proxy. For example, the following
AssignMessage policy copies it to a header named "latitude" in the response:
<AssignMessage async="false" continueOnError="false" enabled="true" name="GetURIPath">
<DisplayName>GetJSONVar</DisplayName>
<Add>
<Headers>
<Header name="latitude">{geocoderesponse.latitude}</Header>
</Headers>
</Add>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
<AssignTo createNew="false" transport="http" type="response"/>
</AssignMessage>
XML
<ExtractVariables name="ExtractVariables-4">
<Source>response</Source>
<XMLPayload>
<Namespaces>
<XPath>/dir:Directions/dir:route/dir:leg/dir:step/dir:duration/dir:value</XPath>
</Variable>
<Variable name="timeunit" type="string">
<XPath>/dir:Directions/dir:route/dir:leg/dir:step/dir:duration/dir:text</XPath>
</Variable>
</XMLPayload>
<VariablePrefix>directionsresponse</VariablePrefix>
</ExtractVariables>
The Extract Variables policy can extract values from complex structures, such as XML messages. The sample
policy code above shows how to extract a variable from a portion of a XML message payload.
The <XMLPayload> element tells the policy to extract a variable from an XMLpayload. You specify the portion to
extract using XPath and explicitly named variables.
When SAP API Management applies the Extract Variables policy code above to this XML message, it sets three
variables:directionsresponse.travelmode, directionsresponse.duration, and directionsresponse.timeunit. All
variables use the same variable prefix of directionsresponse. The suffix for these variables is specified explicitly by
the <Variable> element's name attribute.
You can now access the variable directionresponse.travelmode in your proxy. For example, the following
AssignMessage policy copies it to a header named "tmode" in the response:
API Developers build policies that behave differently based on the content of messages, including headers, URI
paths, payloads, and query parameters.
Often, API Developers will want to extract some portion of a message, or of a header, so that they can use that
extracted portion in a condition statement. The ExtractVariables policy does this. It applies a text pattern to some
part of the message - the body or header or URL path or a query parameter - and on finding a match, sets a
designated variable with the appropriate content.
Other policies and code can then consume those variables to enable dynamic behavior or to send business data to
Analytics Services.
To see how ExtractVariables can be used to build content-driven Analytics reports, see Analyze API message
content using custom analytics.
Note
SAP API Management sets numerous variables automatically during request processing. See Variables
reference. Use the ExtractVariables policy to set additional variables, with values derived from message
content.
The Extract Variables policy extracts information from a request or response and writes that information to a
variable. For each type of information that you can extract, such as URI path or XML data, you specify the pattern
to match and the name of the variable used to hold the extracted information.
However, the way pattern matching works depends on the source of the extraction. The following sections
describe the two basic categories of information that you can extract.
When extracting information from a URI path, query parameters, headers, form parameters, and variables you
use the <Pattern> tag to specify one or more patterns to match. For example, the following policy example shows
a single matching pattern for the URI path:
<ExtractVariables name="ExtractVariables-1">
<Source>request</Source>
<URIPath>
<Pattern ignoreCase="true">/a/{pathSeg}</Pattern>
</URIPath>
<VariablePrefix>urirequest</VariablePrefix>
In this example, the urirequest.pathSeg variable is set to whatever appears in the URI path after "/a/". For
example, for the following request URL, the variable is set to "b":
http://myCo.com/a/b
In the next example, you create a policy that contains three matching patterns for the URI path:
<ExtractVariables name="ExtractVariables-1">
<Source>request</Source>
<URIPath>
<Pattern ignoreCase="true">/a/{pathSeg}</Pattern>
<Pattern ignoreCase="true">/a/b/{pathSeg}</Pattern>
<Pattern ignoreCase="true">/a/b/c/{pathSeg}</Pattern>
</URIPath>
<VariablePrefix>urirequest</VariablePrefix>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</ExtractVariables>
In this example, the first pattern matches the URI and the urirequest.pathSeg variable is set to "b". If the request
URL is:
http://myCo.com/a/b/c/d
Then the third pattern matches and the urirequest.pathSeg variable is set to "d".
The urirequest.pathSeg1 variable is set to "b" and the urirequest.pathSeg2 variable is set to "d".
To reference these query parameters in the Extract Variables policy, you use indexes, where the first instance of
the query parameter has no index, the second is at index 2, the third at index 3, etc. For example, the following
policy extracts the value of the second query parameter named "w" in the request:
<ExtractVariables name="ExtractVariables-1">
<Source>request</Source>
<QueryParam name="w.2">
<Pattern ignoreCase="true">{secondW}</Pattern>
</QueryParam>
<VariablePrefix>urirequest</VariablePrefix>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</ExtractVariables>
The urirequest.secondW variable is set to "2". If the second query parameter is omitted from the request, then
the urirequest.secondW variable is empty. Use indexing any time there are multiple items with the same name in
the request.
For example, you specify patterns to the <URIPath> element as shown below:
<URIPath>
<Pattern ignoreCase="true">/a/*/{id}</Pattern>
<Pattern ignoreCase="true">/a/**/{id}</Pattern>
</URIPath>
The first pattern matches URIs such as "/a/b/c", "/a/foo/bar", etc. The second pattern matches any number of
path segments after "/a/", such as "/a/foo/bar/baz/c", as well as "/a/b/c" and "/a/foo/bar".
When specifying patterns to query parameters, headers, and form parameters, the "*"character specifies to
match any number of characters. For example, when matching a header, specify the pattern as:
*;charset={encoding}
This pattern matches the values "text/xml;charset=UTF-16" and "application/xml;charset=ASCII".
If the value passed to the Extract Variables policy contains a special character, such as "{", use the "%" character
to escape it. The following example escapes the "{" and "}" characters in the pattern because they are used as
literal characters in the value of the query parameter:
<QueryParam>
<Pattern ignoreCase="true">%{user%} {name}</Pattern>
</QueryParam>
In this example, the pattern matches the value "{user} Steve" but not the value "user Steve".
Extensible stylesheet language transformations (XSLT) is a language for converting documents from one XML
format to another XML format. It is often used to integrate applications that support XML, but that require
different XML-formats for the same data.
The XSL policy type enables XSLT to execute as a processing step in an API proxy flow. The XSLT is implemented
in a stand-alone .xslt file, which is stored in the API proxy under /resources/xsl. The XSL policy merely references
the XSL file. See Resource Files for more.
The XSL policy requires two inputs:
• The name of an XSLT stylesheet, which contains a set of transformation rules) stored in the API proxy
under/resources/xsl
• The source of the XML to be transformed (typically a request or response message)
Sample
XSLT File
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="text"/>
<xsl:variable name="newline">
<xsl:text>
</xsl:text>
</xsl:variable>
<xsl:template match="/">
<xsl:text><Life></xsl:text>
<xsl:value-of select="$newline"/>
<xsl:text>Here are the odd-numbered items from the list:</xsl:text>
<xsl:value-of select="$newline"/>
<xsl:for-each select="list/listitem">
<xsl:if test="(position() mod 2) = 1">
<xsl:number format="1. "/>
<xsl:value-of select="."/>
<xsl:value-of select="$newline"/>
Request Message
<?xml version="1.0"?>
<list>
<title>A few of my favorite albums</title>
<listitem>A Love Supreme</listitem>
<listitem>Beat Crazy</listitem>
<listitem>Here Come the Warm Jets</listitem>
<listitem>Kind of Blue</listitem>
<listitem>London Calling</listitem>
<listitem>Remain in Light</listitem>
<listitem>The Joshua Tree</listitem>
<listitem>The Indestructible Beat of Soweto</listitem>
</list>
Transformed Message
<Life>
Here are the odd-numbered items from the list:
1. A Love Supreme
3. Here Come the Warm Jets
5. London Calling
7. The Joshua Tree
</Life>
SAP API Management relies on the Saxon XSLT processor, and supports XSLT 1.0 and 2.0.
Note
<xsl:include> and <xsl:import> are not supported.
Name (Mandatory) Name of the policy. Characters you can use in the name are
restricted to: A-Z0-9._\-$ %. However, the Management UI
OutputVariable (Optional) A variable that stores the output of the transformation. The
OutputVariable cannot be of Message type, that is, it cannot be
'message', 'request', or 'response'. You should set this element
to be a custom variable, and then consume that variable.
To replace the message content with the output of the
transformation, delete this element.
ResourceURL (Mandatory) The XSLT file to be used for transforming the message.
Parameters ignoreUnresolvedVariables Ignores any unresolved variable errors in the XSLT script
(Optional) (Optional) instructions.
Valid values: true/false
Default value: false
Parameter name Name of a custom parameter. Note that with name you can only
(Optional) (Mandatory) use one of the optional parameters listed below.
ref Specifies the reference that sources the value from a variable.
(Optional)
The API Platform enables you to configure custom exception handling using a policy of type RaiseFault.
The RaiseFault policy is a variation on the AssignMessage policy type. Like an AssignMessage policy, a RaiseFault
policy generates a custom message in response to an error condition. You use RaiseFault to define a
FaultResponse that is returned to the requesting app when a specific condition arises.
A FaultResponse can consist of HTTP headers, query parameters, and a message payload. These elements can be
dynamically populated using variables, enabling you to craft FaultResponses that are tailored to specific failure
conditions. Such tailored FaultResponses can be more useful to app developers and app end users than generic
error messages or HTTP response codes.
When executed, the RaiseFault policy transfers the message Flow execution to the default ErrorFlow, which in turn
returns the designated FaultResponse to the requesting client app. When the message Flow switches to the
default ErrorFlow, no further policy processing occurs. All remaining processing Steps are bypassed, and the
FaultResponse is returned directly to the requesting app.
In the most common usage, RaiseFault is used to return a custom FaultResponse to the requesting app. For
example to return a 404:
<RaiseFault name="404">
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
<FaultResponse>
<Set>
<StatusCode>404</StatusCode>
<ReasonPhrase>The resource requested was not found</ReasonPhrase>
</Set>
</FaultResponse>
</RaiseFault>
For a list of all variables that are available for dynamically populating FaultResponse messages, see Variables
reference
Note
The name attribute for this policy is restricted to these characters: A-Z0-9._\-$ %. However, the
Management UI enforces additional restrictions, such as automatically removing characters that are not
alphanumeric.
FaultResponse: Optional Defines the response message returned to the requesting client.
FaultResponse uses the same settings as the AssignMessage policy
type. See Generate or modify messages using AssignMessage.
Example
RaiseFault policy
<RaiseFault name="abc">
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
Policy-specific variables
Flow variables enable the dynamic behavior of policies and Flows at runtime, based on HTTP headers, message
content, or Flow context. The following predefined Flow variables are available after a RaiseFault policy executes.
For more information about Flow variables, see Variables reference.
The AssignMessage policy type is used to generate or modify a request or response messages during an API
proxy Flow. With this policy, you can assign the verb, the payload, the status code, and more - everything
pertaining to an HTTP request or response message.
There are many situations in which a request or a response message must be modified during processing by SAP
API Management. For example, you might need to strip HTTP headers from a request message before the
message is forwarded to the backend service. You might also need to add HTTP headers or insert JSON or XML
message content before a response is sent to the consumer app. You can do both operations using the
AssignMessage policy type.
In other situations, you need to generate complete request or response messages. For example, you might use a
ServiceCallout policy to invoke a remote API from an API proxy. You can use the AssignMessage policy to
generate a request message. Then, employ a ServiceCallout policy that references the variable to send that
message to a remote service or API.
AssignMessage is so named because the policy requires a message to be 'assigned' to a variable. (See Variables
reference for more on variables.) Often, variables hold string or integer values. In the case of AssignMessage, the
variable holds a message - which is a complex data type with multiple fields.
To use AssignMessage, you must select a variable name and specify the message content to assign to it. If you
use the one of the built-in names - request or response - the message will be assigned to the ambient request or
response, respectively. If you use any other name, it will refer to a custom variable to hold the message.
Samples
Custom Request
This sample shows how to build up a custom request object with Assign Message.
<AssignMessage name="AssignMessage-3">
<AssignTo createNew="true" type="request">request1</AssignTo>
<Copy>
<Headers>
<Header name="user-agent"/>
</Headers>
</Copy>
<Set>
<QueryParams>
<QueryParam name="address">{request.queryparam.address}</QueryParam>
</QueryParams>
<Verb>GET</Verb>
</Set>
It's a common use case to build up a custom request object using Assign Message, and then send it to a backend
target using the Service Callout policy. This sample:
• Creates a new request message object called request1.
• Copies the value of the user-agent HTTP header from the incoming request message object. Because
the <Copy> element uses an absolute reference to the user-agent flow variable, there is no need to specify
the source attribute to <Copy>.
• Sets a query parameter on the request1 message object.
• Sets the HTTP verb for the request1 message object to GET.
• Sets the IgnoreUnresolvedVariables element to false. So, if one of the variables we are trying to copy or
set does not exist, processing in the API flow will stop.
You can then access the request1 object in another Assign Message policy as shown below:
<AssignMessage name="CopyExample1ToRequest">
<DisplayName>AccessRequest1</DisplayName>
<AssignTo createNew="false" type="request"></AssignTo>
<Set>
<Headers>
<Header name="user-agentCopyRequest1">{request1.header.user-agent}</Header>
</Headers>
</Set>
</AssignMessage>
Create Request
Here's another example demonstrating how to create a custom request object with Assign Message.
<AssignMessage name="AssignMessage-2">
<AssignTo createNew="true" type="request">partner.request</AssignTo>
<Set>
<Verb>POST</Verb>
<Payload contentType="text/xml">
<request><operation>105</operation></request>
</Payload>
</Set>
</AssignMessage>
Modify Response
This sample shows how to modify an existing response object by adding a Header to it.
<AssignMessage name="assignMessage-4">
<AssignTo createNew="false" type="response"></AssignTo>
<Set>
<Headers>
<Header name="Cache-Hit">{lookupcache.LookupCache-1.cachehit}</Header>
</Headers>
</Set>
<IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
</AssignMessage>
This sample Assign Message policy does not create a new message. Instead, it modifies an existing response
message by adding an HTTP header. THis policy would be attached to a response flow in the API proxy. Because
you omitted a variable name in the <AssignTo> tag, and specified a typeas response, this policy modifies the
response object returned by the target server.
The HTTP header added to the response message by this policy is derived from a variable populated by the
LookupCache policy. Therefore the response message modified by this AssignMessage policy contains an HTTP
header that indicates whether the results have been pulled from the Cache or not. Setting headers in the response
can be handy for debugging and troubleshooting.
This pattern of setting headers for debugging and troubleshooting is a common practice. You can see what
header value was sent back by inspecting the response with the Trace tool or other means.
You can use Assign Message to embed dynamic content in the payload of XML or JSON response and request
messages.
To embed SAP API Management flow variables in an XML payload, wrap the designated variable in curly braces,
like this: {prefix.name}. This sample policy embeds the value of the HTTP user-agent header flow variable in an
XML element called User-agent:
Note: With a JSON payload, you cannot use curly braces to identify variables. Instead, you must declare and
embed the delimiter characters, as follows:
Remove apikey
This policy removes the apikey query parameter from the request.
<AssignMessage name="AssignMessage-1">
<AssignTo createNew="false" type=request></AssignTo>
<Remove>
<QueryParams>
<QueryParam name='apikey'/>
</QueryParams>
</Remove>
</AssignMessage>
It's a best practice to strip the apikey query parameter from the request message when you use the APIKey policy
for user authentication. You do this to prevent sensitive key information from being passed to the backend target.
This sample pattern is a common use case for AssignMessage.
Use the Assign Message policy to generate or modify request or response messages during an API proxy Flow.
With this policy, you can assign the verb, the payload, the status code, and more - everything pertaining to an
HTTP request or response message.
Assign Message is so named because the policy requires a message to be 'assigned' to a variable. In the case of
Assign Message, the variable holds a message - which is a complex data type with multiple fields.
To use Assign Message, you must select a variable name and specify the message content to assign to it. If you
use the one of the built-in names -request or response - the message will be assigned to the request or response,
respectively. If you use any other name, it refers to a custom variable that holds the message.
There are many situations in which a request or a response message must be modified during processing by SAP
API Management. For example, you might need to strip HTTP headers from a request message before the
message is forwarded to the backend service. You might also need to add HTTP headers or insert JSON or XML
message content before a response is sent to the consumer app. You can do both operations using the Assign
Message policy type.
In other situations, you need to generate complete request or response messages. For example, you might use
a ServiceCallout policy to invoke a remote API from an API proxy. You can use the AssignMessage policy to
generate the request message and assign it to a variable. Then, use a ServiceCallout policy that references the
variable to send that message to the remote API.
Element reference
The element reference describes the elements and attributes of the Assign Message policy.
Note
This policy handles a number of use cases. Typically, you select which operation(s) you wish to perform
with this policy and delete the rest of the elements. For example, if you know you want to do a Copy, then
you can delete the Remove, Add, and other elements if you wish.
<AssignMessage> attributes
name The internal name of the policy. Characters you can use in the N/A Required
name are restricted to: A-Z0-9._\-$ %. However, the SAP API
Management UI enforces additional restrictions, such as
automatically removing characters that are not alphanumeric.
Optionally, use the <DisplayName> element to label the policy in
the management UI proxy editor with a different, natural-
language name.
continueOnError Set to false to return an error when a policy fails. This is expected false Optional
behavior for most policies.
Set to true to have flow execution continue even after a policy
fails.
async Note: This attribute does not make the policy execute false Optional
asynchronously.
When set to true, policy execution is offloaded to a different
thread, leaving the main thread free to handle additional
requests. When the offline processing is complete, the main
thread comes back and finishes handling the message flow. In
some cases, setting async to true improves API proxy
performance. However, overusing async can hurt performance
with too much thread switching.
Use in addition to the name attribute to label the policy in the management UI proxy editor with a different,
natural-language name.
<DisplayName>Policy Display Name</DisplayName>
Default: N/A
If you omit this element, the the value of the policy'sname attribute is
used.
Presence: Optional
Type: String
<AssignTo> element
The <AssignTo> element determines the variable that the Assign Message policy operates on. The options are:
The request object received by the API proxy
The response object returned from the target server
A custom request or response object
For example, if you use the Assign Message policy to add a query parameter, the query parameter is added to the
variable specified by the <AssignTo> element.
If the <AssignTo> element is missing, or if the element does not explicitly specify the name of the destination
variable, then the policy assigns values to either the request or response object, depending on the Flow to which
the policy is attached. For example, if you attach the policy to a request Flow, the default object is
the request object.
Attributes
No destination variable:
<AssignTo createNew="false" transport="http" type="request"/>
createNew If createNew is set to true, then a new variable If createNew is not Optional Boolean
of the type specified by type is created. If you specified, the
do not specify the name of the new variable, poplicy responds
then the policy creates a in one of two ways:
transport Specifies the transport type for the request or http (the only Optional String
response message type. supported value)
<Copy> element
Copies information from the message specified by the source attribute to the message object specified by this
policy's <AssignTo> element.
<Copy source="request">
<Headers/>
<QueryParams/>
<FormParams/>
<Payload> </Payload>
<Verb/>
<Version/>
<StatusCode/>
<ReasonPhrase/>
Default: N/A
Presence: Optional
Type: String
Attributes
<Copy source="request">
<Copy>/<Headers> element
Copies the specified HTTP header from the source to the message variable specified with
the <AssignTo> element. To copy all headers, specify<Copy><Headers/></Copy>.
<Copy source='request'>
<Headers>
<Header name="headerName"/>
</Headers>
</Copy>
If there are multiple headers with the same name, use the following syntax:
<Copy source='request'>
<Headers>
<Header name="h1"/>
<Header name="h2"/>
<Header name="h3.2"/>
</Headers>
</Copy>
This example copies "h1", "h2", and the second value of "h3". If "h3" has only one value, then it is not copied.
Default: N/A
Type: String
<Copy>/<QueryParams> element
Copies query parameters. Note that the QueryParams is copied only when both the source and AssignTo type
are request. To copy all query parameters, specify <Copy><QueryParams/></Copy>. This example copies
the user-agent header to the message variable specified with the<AssignTo> element:
<Copy source='request'>
<QueryParams>
<QueryParam name="paramName"/>
</QueryParams>
</Copy>
If there are multiple query params with the same name, use the following syntax:
<Copy source='request'>
<QueryParams>
<QueryParam name="qp1"/>
<QueryParam name="qp2"/>
<QueryParam name="qp3.2"/>
</QueryParams>
</Copy>
This example copies "qp1", "qp2", and the second value of "qp3". If "qp3" has only one value, then it is not copied.
Default: N/A
Presence: Optional
Type: String
<Copy>/<FormParams> element
Copies the form parameters. Note that the FormParams is copied only when the contentType is source and
AssignTo is application/x-www-form-urlencoded. To copy all form parameters,
specify <Copy><FormParams/></Copy>. This example copies specified form parameter from the object
specified in the source attribute to the variable specified in the <AssignTo> element:
<Copy source='request'>
<FormParams>
<FormParam name="paramName"/>
</FormParams>
</Copy>
If there are multiple form params with the same name, use the following syntax:
<Copy source='request'>
<FormParams>
This example copies "f1", "f2", and the second value of "f3". If "f3" has only one value, then it is not copied.
Default: N/A
Presence: Optional
Type: String
<Copy>/<Payload> element
If true, the Content-Type header is copied from the object specified in the source attribute to the variable
specified in the <AssignTo> element.
<Copy source='request'>
<Payload>true</Payload>
</Copy>
Default: false
Presence: Optional
Type: Boolean
<Copy>/<Version> element
If true, the HTTP version is copied from the object specified in the source attribute to the variable specified in
the <AssignTo> element.
<Copy source='request'>
<Version>true</Version>
</Copy>
Default: false
Presence: Optional
Type: Boolean
Default: false
Presence: Optional
Type: Boolean
<Copy>/<Path> element
Copies the path found in the source attribute object to the variable specified in the <AssignTo> variable. The path
is assigned only when both the source and AssignTo type are request.
<Copy source='request'>
<Path>true</Path>
</Copy>
Default: false
Presence: Optional
Type: Boolean
<Copy>/<StatusCode> element
If true, copies the StatusCode from the object specified by the source attribute to the variable specified in the
AssignType element. The StatusCodeis copied only when both the source and AssignTo type are response.
<Copy source='request'>
<StatusCode>true</StatusCode>
</Copy>
Default: false
Presence: Optional
Type: Boolean
<Copy>/<ReasonPhrase> element
If true, copies the ReasonPhrase from the object specified by the source attribute to the variable specified in the
AssignType element. The ReasonPhrase is copied only when both the source and AssignTo type are response.
<Copy source='request'>
Default: false
Presence: Optional
Type: Boolean
<Remove> element
Removes specified elements from the message variable specified in the <AssignTo> element of this policy. For
example, a common use case is to remove a query parameter that contains sensitive information from the
incoming request object, to avoid passing it to the backend server.
<Remove>
<Headers>
<Header name="h1"/>
</Headers>
<QueryParams>
<QueryParam name="q1"/>
</QueryParams>
<FormParams>
<FormParam name="f1"/>
</FormParams>
</Payload>
</Remove>
Default: N/A
Presence: Optional
Type: N/A
<Remove>/<Headers> element
Removes specified HTTP headers from the message variable specified in the <AssignTo> element of this policy.
To remove all the headers, specify<Remove><Headers/></Remove>. This example removes the user-
agent header from the message variable specified with the <AssignTo>element.
<Remove>
<Headers>
<Header name="user-agent"/>
If there are multiple headers with the same name, use the following syntax:
<Remove>
<Headers>
<Header name="h1"/>
<Header name="h2"/>
<Header name="h3.2"/>
</Headers>
</Remove>
This example removes "h1", "h2", and the second value of "h3". If "h3" has only one value, then it is not removed.
Default: N/A
Presence: Optional
Type: String
<Remove>/<QueryParams> element
Removes specified query parameters from the message variable specified in the <AssignTo> element of this
policy. To remove all query paremeters, specify <Remove><QueryParams/></Remove>.
Note: This option only works when the <AssignTo> type is request.
<Remove>
<QueryParams>
<QueryParam name="param_name"/>
</QueryParams>
</Remove>
If there are multiple query params with the same name, use the following syntax:
<Remove>
<QueryParams>
<QueryParam name="qp1"/>
<QueryParam name="qp2"/>
<QueryParam name="qp3.2"/>
</QueryParams>
</Remove>
This example removes "qp1", "qp2", and the second value of "qp3". If "qp3" has only one value, then it is not
removed.
Default: N/A
Type: String
<Remove>/<FormParams> element
Removes specified query parameters from the message variable specified in the <AssignTo> element of this
policy. To remove all form parameters, specify <Remove><FormParams/></Remove>.
Note: This option only works when the contentType of <AssignTo> element is application/x-www-form-
urlencoded.
<Remove>
<FormParams>
<FormParam name="form_param_name"/>
</FormParams>
</Remove>
If there are multiple form params with the same name, use the following syntax:
<Remove>
<FormParams>
<FormParam name="f1"/>
<FormParam name="f2"/>
<FormParam name="f3.2"/>
</FormParams>
</Remove>
This example removes "f1", "f2", and the second value of "f3". If "f3" has only one value, then it is not removed.
Default: N/A
Presence: Optional
Type: String
<Remove>/<Payload> element
If true, the payload is cleared from the message variable specified in the <AssignTo> element.
<Remove>
<Payload>true</Payload>
</Remove>
Default: false
Presence: Optional
Type: Boolean
Adds information to the message object specified with this policy's <AssignTo> element.
<Add>
<Headers>
<Header name="h1">value</Header>
</Headers>
<QueryParams>
<QueryParam name="q1">value</QueryParam>
</QueryParams>
<FormParams>
<FormParam name="f1">value</FormParam>
</FormParams>
</Add>
Default: N/A
Presence: Optional
Type: String
<Add>/<Headers> element
Adds the headers in the variable specified in the <AssignTo> element. Note that the empty
header <Add><Headers/></Add> does not add any header. The same holds true for QueryParams and
FormParams. This example adds the user-agent header to the message variable specified with
the <AssignTo> element, and copies the value of the request.user.agent flow variable into the header.
<Add>
<Headers>
<Header name="user-agent">{request.user.agent}</Header>
</Headers>
</Add>
Default: N/A
Presence: Optional
Type: String
<Add>/<QueryParams> element
Adds specified query parameters to the message variable specified in the <AssignTo> element of this policy. Note
that the empty query params, <Add><QueryParams/></Add>, does not add any query params.
Default: N/A
Presence: Optional
Type: String
<Add>/<FormParams> element
Adds specified form parameters to the message variable specified in the <AssignTo> element of this policy. Note
that the empty form params, <Add><FormParams/></Add> does not add any form params.
Note: This option only works when the contentType of <AssignTo> element is application/x-www-form-
urlencoded.
This example adds the specified form parameter to the message variable specified with the <AssignTo> element,
and assigns it the value of the "name" query param:
<Add>
<FormParams>
<FormParam name="{my_username}">{request.queryparam.name}</FormParam>
</FormParams>
</Add>
Default: N/A
Presence: Optional
Type: String
<Set> element
Sets information in the message object specified in with this policy's <AssignTo> element.
<Set>
<Headers/>
<QueryParams/>
<FormParams/>
Default: N/A
Presence: Optional
Type: N/A
<Set>/<Headers> element
Sets or overwrites HTTP headers in the message variable specified with the <AssignTo> element. Note that the
empty header <Set><Headers/></Set> does not set any header. This example sets the user-agent header to the
message variable specified with the <AssignTo> element.
<Set>
<Headers>
<Header name="user-agent">{request.header.user-agent}</Header>
</Headers>
</Set>
Default: N/A
Presence: Optional
Type: String
<Set>/<QueryParams> element
Sets query parameters. Note that the empty query parameter <Set><QueryParams/></Set> does not set any
query parameters. This example assigns a flow variable to a query parameter called "address" to the HTTP
message specified with the <AssignTo> element.
<Set>
<QueryParams>
<QueryParam name="address">{request.queryparam.address}</QueryParam>
</QueryParams>
</Set>
Default: N/A
Presence: Optional
Type: String
Default: N/A
Presence: Optional
Type: String
<Set>/<Payload> element
Set a plain text payload:
<Set>
<Payload contentType="text/plain">test1234</Payload>
</Set>
Set a JSON payload. Notice how this example escapes the leading "{" in the payload. Otherwise, system would
interpret the leading "{" as the beginning of a variable reference:
<Set>
<Payload contentType="application/json">
\{"name":"foo", "type":"bar"}
</Payload>
</Set>
Reference a variable in a JSON payload. You cannot use curly braces to reference variables in a JSON payload.
Instead, you must declare and embed the variable delimiter characters, as follows:
<Set>
<Payload contentType="application/json" variablePrefix="@" variableSuffix="#">
{"name":"foo", "type":"@variable_name#"}
</Payload>
</Set>
Default:
Presence: Optional
Type: String
Attributes
<Payload contentType="content_type" variablePrefix="char" variableSuffix="char">
contentType If contentType is specified, its value is assigned to the contentType Optional String
header.
variablePrefix Optionally specifies the leading delimiter on a flow variable Optional Char
because JSON payloads cannot use the default "{" character.
<Set>/<Version> element
Sets the version. Note that the content of <Version> is treated as message template. The same holds true for
Verb, Path, StatusCode, and ReasonPhrase.
<Set>
<Version>2.1</Version>
</Set>
Default: false
Presence: Optional
Type: Boolean
<Set>/<Verb> element
Sets the HTTP verb only when AssignTo type is request.
Default: false
Presence: Optional
<Set>/<Path> element
Sets the HTTP path of the request only when AssignTo type is request. Specify the path relative to the domain,
which is defined by the target endpoint. For example, to set the request path as http://myCo.com/a/b/c,
where http://myCo.com is defined by the API proxy's target endpoint, specify the path as:
<Set>
<Path>/a/b/c</Path>
</Set>
Default:
Presence: Optional
Type: String
<Set>/<StatusCode> element
Sets the status code and reason phrase only when AssignTo type is response.
<Set>
<StatusCode>400 Bad Request</StatusCode>
</Set>
Default: NA
Presence: Optional
Type: String
<Set>/<ReasonPhrase> element
Sets the status code and reason phrase only when AssignTo type is response.
<Set>
Default: false
Presence: Optional
Type: Boolean
<AssignVariable> element
Lets you assign a value to a flow variable. This example assigns the value of the flow variable request.header.user-
agent to the flow variablemyvar and the value of the query parameter country to the Country variable:
<AssignVariable>
<Name>myvar</Name>
<Ref>request.header.user-agent</Ref>
<Value>ErrorOnCopy</Value>
</AssignVariable>
<AssignVariable>
<Name>Country</Name>
<Ref>request.queryparam.country</Ref>
<Value>ErrorOnCopy</Value>
</AssignVariable>
If the variable referenced by the <Ref> tag is not accessible, use the value specified by the <Value> tag.
One way to use <AssignVariable> is to set the default value of a query parameter, header, or other value that can
be passed in with the request. For example, you create a weather API proxy where the request takes a single
query parameter named "w". This parameter contains the ID of the city for which you want the weather. The
request URL has the form:
http://myCO.com/v1/weather/forecastrss?w=12797282
To define a default value for the "w" query parameter, create an Assign Message policy as shown below:
<AssignMessage async="false" continueOnError="false" enabled="true" name="DefaultWQP">
<AssignTo createNew="false" transport="http" type="request"/>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
<AssignVariable>
<Name>request.queryparam.w</Name>
<Ref>request.queryparam.w</Ref>
<Value>12797282</Value>
</AssignVariable>
</AssignMessage>
<AssignVariable>/<Name> element
Specifies the name of the destination flow variable. If the variable does not exist, a new one is created.
<AssignVariable>/<Ref> element
Specifies the source of the assignment as a flow variable or other value. If you specify a flow variable, omit the
enclosing brackets "{}" normally used to reference a flow variable.
<AssignVariable>/<Value> element
If <Ref> is not specified or is unresolvable or null, this value is assigned to the <Name> variable. The value is
always interpreted as a literal string; you cannot use a flow variable or other variable as the value.
Flow variables
This policy does not automatically create or populate any flow variables. However, you can create and populate
flow variables manually using this policy's <AssignTo>, <Copy>, <Set>, <Add>, and <AssignVariable> elements.
Error codes
InvalidVariableName AssignMessage schema validation failed: invalid variable name - {0} - in assign
variable
The KeyValueMapOperations policy provides policy-based access to a key/value store available in SAP API
Management. The store provides a lightweight persistence mechanism for data formatted as key/value pairs,
which can be accessed at runtime by policies or code running on SAP API Management. KeyValueMapOperations
are typically used to store or retrieve long-lived information that needs to be reused over multiple
request/response transactions.
KeyValue refers to any arbitrary data in the format key=value, for
example localhost=127.0.0.1,zip_code=94110, or first_name=felix.
In the first example, localhost is a key, and 127.0.0.1 is a value.
Each key/value pair is stored in a map as an entry. A key/value map can store many entries.
For example, say you need to store a list of IP addresses associated with various backend environments. You
could create a map called ipAddresses that contains a list of key/value pairs as entries. For example, this JSON
might represent such a map:
{
"entry" : [ {
"name" : "Development",
"value" : "65.87.18.18"
}, {
"name" : "Staging",
"value" : "65.87.18.22"
} ],
Note
Key/Value maps can be manipulated via the KeyValueMapOperations policy, or directly via the SAP API
Management management API.
Samples
A simple example of a useful KeyValueMap is a URL 'shortening' service. The KeyValueMap could be configured to
store shortened URLs along with corresponding full URLs.
The key in this example, urlencoding.requesturl.hashed, is an example of a custom variable. The hashed request
URL would would be generated by code (JavaScript for example) and then stored in this variable, where the
KeyValueMapOperations policy can access it.
name The unique name of the policy. Use this name N/A Yes
to reference the policy within a Step definition
element. Characters you can use in the name
are restricted to: A-Z0-9._\-$ %. However,
the SAP API Management UI enforces
additional restrictions, such as automatically
removing characters that are not
alphanumeric.
async Note: This attribute does not make the policy false Optional
execute asynchronously.
When set to true, policy execution is
offloaded to a different thread, leaving the
<DisplayName> element
Use in addition to the name attribute to label the policy in the management UI proxy editor with a different,
natural-language name.
Default: N/A
If you omit this element, the the value of the policy'sname attribute is
used.
Presence: Optional
Type: String
<Delete> element
Deletes the specified key/value pair. (At least one of <Get>, <Put>, or <Delete> must be used.)
<Delete>
<Key>
<Parameter>key_name_literal</Parameter>
</Key>
</Delete>
Default: N/A
<DisplayName> element
A natural-language name that labels the policy in the management UI proxy editor. If omitted, the
policy name attribute is used.
<DisplayName>Key Value Map Operations 1</DisplayName>
Presence: Optional
Type: String
<Entry> element
Seed values for KeyValueMaps, which are populated in the KeyValueMap when it is initialized.
<InitialEntries>
<Entry>
<Key>
<Parameter>key_name_literal</Parameter>
</Key>
<Value>v1</Value>
</Entry>
<Entry>
<Key>
<Parameter>key_name_variable</Parameter>
</Key>
<Value>v3</Value>
<Value>v4</Value>
</Entry>
</InitialEntries>
Default: N/A
Presence: Optional
Type: N/A
<ExpiryTimeInSecs> element
For a GET from the KeyValueMap, specifies the duration in seconds after which SAP API Management refreshes
its cached value from the KeyValueMap.
They Key Value Map Operations policy lets you determine how long values are persisted before being refreshed.
The refresh interval is set with the <ExpiryTimeInSecs> element. If a GET operation is executed and the expiry
interval has been exceeded, the value is refreshed and the policy gets the updated value. When you add this policy
to an API proxy, the default expiry time is now 300 seconds.
<Get> element
Retrieves the value for the key specified. (At least one of <Get>, <Put>, or <Delete> must be used.)
<Get assignTo="myvar" index="1">
<Key>
<Parameter>key_name_literal</Parameter>
</Key>
</Get>
Default: N/A
Type: N/A
assignTo The variable to which the retrieved value should be assigned. N/A Required
index The index number (in a 1-based index) of the item to fetch from a multi- N/A Optional
valued key. For example, specifying index=1 will return the first value
and assign it to the assignTovariable. If no index value is specified, all
the values of that entry are assigned to the variable as a java.util.List.
For an example, see the KeyValueMapOperations GET tab.
<InitialEntries> element
Seed values for KeyValueMaps, which are populated in the KeyValueMap when it is initialized.
<InitialEntries>
<Entry>
<Key>
<Parameter>key_name_literal</Parameter>
</Key>
<Value>v1</Value>
</Entry>
<Entry>
<Key>
<Parameter>key_name_variable</Parameter>
</Key>
<Value>v3</Value>
<Value>v4</Value>
</Entry>
</InitialEntries>
Default: N/A
Presence: Optional
Type: N/A
Specifies the key in a key/value map entry. A key can be composite, which means that more than one parameter
can be appended to create the key. For example, userID and role might be combined to create a key.
The name ratelimit is reserved.
<Key>
<Parameter>key_name_literal</Parameter>
</Key>
Default: N/A
Presence: Optional
Type: N/A
<Parameter> element
Specifies the key name in a key/value pair. This element specifies the name when creating, putting, retrieving, or
deleting the key/value pair.
A key can be composite, which means that more than one parameter can be appended to make the key. For
example, userIDand role might be combined constitute a key.
You can specify the name as either a literal string or, using the ref attribute, as a variable to be retrieved at run
time.
<!-- Specify a literal value -->
<Parameter>literal<Parameter>
OR
<!-- Specify the name of variable value to be populated at run time. -->
<Parameter ref="variable_name"><Parameter>
Whether you're getting, updating, or deleting a key/value entry, remember that you need to specify the key name
in the same way you did when you created the entry. For example, if you created the key name from a variable,
you must use the same variable to get it.
Default: N/A
Presence: Required
Type: String
ref Specifies the name of a variable whose value should be used N/A Required if no literal
for the key name. value is given
between the opening
and closing tags.
Prohibited if a literal
value is given.
<Put> element
Writes a key/value pair to an existing key value map. (At least one of <Get>, <Put>, or <Delete> must be used.)
<Put override="false">
<Key>
<Parameter ref="mykeyvar"></Parameter>
</Key>
<Value ref="myvalvar1"/>
</Put>
Default: N/A
Type: N/A
Attributes
override If set to true, it overrides the value for a key. false Optional
Defines the boundary of accessibility for KeyValueMaps. The default scope is environment, meaning that, by
default, maps entries are shared by all API proxies running in an environment (for example, test or prod). If you set
the scope to apiproxy, then entries in the KeyValueMap are accessible only by the API proxy that writes the values
to the map.
Note that when accessing a map or map entry, you must specify the same scope value you used when the map
was created. For example, if the map was created with a scope of apiproxy, you must use the apiproxy scope
when retrieving its values, putting changes, or deleting entries.
<Scope>environment</Scope>
Default: environment
Presence: Optional
Type: String
<Value> element
Default: N/A
Presence: Required
Type: String
SAP API Management stores profile data for a range for "entities", such as developers, apps, and API products.
The AccessEntity policy enables developers to retrieve those profiles during API proxy message processing. As
such, the AccessEntity policy functions as a policy-based runtime database lookup. The profile information
returned by this policy can be used to enable dynamic behavior, such as conditional endpoint routing, flow
execution, policy enforcement, and so on.
For example, you could use the AccessEntity policy to get the profile for an app, and then extract a custom field
(such as a department name) from the app profile. Using the department name as a variable, you could route the
request to a specific backend service, or you could forward the department name to Analytics to enable data
accounting.
When a policy of type AccessEntity is enforced:
1. The policy sets an entity as an XML-formatted flow variable. The variable that is set is usually consumed by an
ExtractVariable or AssignMessage policy, as illustrated in Extract message content using ExtractVariables
and Generate or modify messages using AssignMessage.
2. XPath is used to parse the desired properties from the profile. For examples see Retrieving entity profiles
using the Platform API.
3. If the specified entity is not found, the policy returns ResourceNotFoundException.
AccessEntity can be used to access profiles for the following entities:
• App
• API product
• Company
• Company developer
• Consumer key
• Developer
AccessEntity Variables
When the entity profile specified in the AccessEntity policy is retrieved, the XML-formatted profile object is added
to the message context as a variable. It can be accessed like any other variable, with reference to the variable
name. The user-provided name of the AccessEntity policy is set as the variable prefix of the variable name.
For example, if an AccessEntity policy with name of GetDeveloper is executed, then the XML-formatted profile is
stored in the variable named AccessEntity.GetDeveloper. The XML-formatted profile can then be parsed using an
XPath defined in an ExtractVariables policy that specifies AccessEntity.GetDeveloper as its source.
EntityType Specification
AccessEntity A policy used to retrieve entity profiles from SAP API Management data store.
When an AccessEntity policy executes, the result is a Flow variable populated with an XML-formatted profile
object. The XML-formatted profile object can be used as a source of data for a Flow by configuring an
ExtractVariables policy to parse the profile.
In the following example, an ExtractVariables policy is used to parse a developer profile retrieved by AccessEntity
to obtain the value of a custom attribute. The source is set to point to the variable where the developer profile is
stored by the AccessEntity policy: AccessEntity.{policy_name}. The profile can be parsed using XPath, just as any
other XML document. Sample profiles for entities managed by SAP API Management are provided below.
Before the profile can be parsed by SAP API Management, it must be converted into a request message using an
AssignMessage policy.
<AssignMessage name="ConvertXmlToMessageRequest">
<DisplayName>ConvertXmlToMessageRequest</DisplayName>
<Set>
Once the profile has been converted to an XML message, you can populate the necessary variables using an
ExtractVariables, policy. For example:
<ExtractVariables name="GetDeveloperAttribute">
<Source>AccessEntity.GetDeveloper</Source>
<VariablePrefix>developer_attribute</VariablePrefix>
<XMLPayload>
<Variable name="developer_attribute" type="string">
<XPath>/Developer/Attributes/Name</XPath>
</Variable>
</XMLPayload>
</ExtractVariables>
When configuring an AccessEntity policy, it can be useful to retrieve sample entity profiles to assist in selection of
appropriate identifiers.
For example:
Apps
$ curl -H "Accept:text/xml" -X GET \
<host>:<port>/v1/o/{org_name}/apps/{app_id} \
-u myname:mypass
Or:
$ curl -H "Accept:text/xml" -X GET \
<host>:<port>/v1/o/{org_name}/developers/{developer_email}/apps/{app_name} \
-u myname:mypass
Sample profile:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<App name="thomas-app">
<AccessType>read</AccessType>
<ApiProducts/>
<Credentials>
<Credential>
API Product
$ curl -H "Accept:text/xml" -X GET \
<host>:<port>/v1/o/{org_name}/apiproducts/{apiproduct_name} \
-u myname:mypass
Sample XPath, retrieves the second API resource (URI) from the API product named weather_free:
/ApiProduct['@name=weather_free']/ApiResources/ApiResource[1]/text()
Sample profile:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
Company
$ curl -H "Accept:text/xml" -X GET \
<host>:<port>/v1/o/{org_name}/companies/{company_name} \
Sample profile:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Company name="theramin">
<Apps/>
<DisplayName>Theramin Corporation</DisplayName>
<Organization>theramin-pm</Organization>
<Status>active</Status>
<Attributes>
<Attribute>
<Name>billing_code</Name>
<Value>13648765</Value>
</Attribute>
</Attributes>
<CreatedAt>1349208631291</CreatedAt>
<CreatedBy>[email protected]</CreatedBy>
<LastModifiedAt>1349208631291</LastModifiedAt>
<LastModifiedBy>[email protected]</LastModifiedBy>
</Company>
Company Developer
$ curl -H "Accept:text/xml" -X GET \
<host>:<port>/v1/o/{org_name}/companies/{company_name}/developers/{developer_name} \
-u myname:mypass
Sample profile:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Developers>
<Developer>
<Email>[email protected]</Email>
<Role>developer</Role>
</Developer>
</Developers>
Consumer key
$ curl -H "Accept:text/xml" -X GET \
<host>:<port>/v1/o/{org_name}/developers/{developer_email}/apps/{app_name}/keys/{consu
mer_key} \
-u myname:mypass
Sample profile:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Credential>
<Attributes/>
<ConsumerKey>XLotL3PRxNkUGXhGAFDPOr6fqtvAhuZe</ConsumerKey>
<ConsumerSecret>iNUyEaOOh96KR3YL</ConsumerSecret>
<ApiProducts>
<ApiProduct>
<Name>weather_free</Name>
<Status>approved</Status>
</ApiProduct>
</ApiProducts>
<Scopes/>
<Status>approved</Status>
</Credential>
Developer
$ curl -H "Accept:text/xml" -X GET \
http:// <host:port>/v1/o/{org_name}/developers/{developer_email} \
-u myname:mypass
Sample XPath:
/Developer/Attributes/Attribute[Name='my_custom_attribute']/Value/text()
/Developer/Email/text()
Sample profile:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Developer>
<Apps>
<App>weatherappx</App>
<App>weatherapp</App>
</Apps>
<Email>[email protected]</Email>
<DeveloperId>4Y4xd0KRZ1wmHJqu</DeveloperId>
<FirstName>Nikola</FirstName>
<LastName>Tesla</LastName>
<UserName>theramin</UserName>
<OrganizationName>theramin-pm</OrganizationName>
The MessageValidation Policy type enables you to configure API proxies to reject messages that do not conform
to schema (.xsd) or WSDL definition(s). That means developers building apps to consume your API are
immediately notified if they are submitting non-conformant requests. Message validation helps developers by
indicating where XML tags may not be properly closed, for example. Validation also protects backend services by
blocking XML or SOAP messages who structure might cause unpredictable behavior.
Validation can save you a call to tech support, and can help developers avoid time in the forums trying to find
troubleshooting help. If developers are notified that they are submitting invalid requests, they can refer to the XML
schema for the API to understand how to fix the error. This makes well-understood XML schemas a key
component of your API documentation.
SAP API Management enables you to configure your API with a Message Validation policy that validates messages
with the XML payload.
Samples
<MessageValidation name="myPolicy">
<Source>mymessage</Source>
<ResourceURL>xsd://sample</ResourceURL>
<SOAPMessage version="1.1/1.2"/>
<Element namespace="http://finance.com/1999">PurchaseOrder</Element>
<Element namespace="http://finance.com/2000">PurchaseOrder</Element>
</MessageValidation>
Element Reference
The element reference describes the elements and attributes of the MessageValidation policy.
<MessageValidation async="false" continueOnError="false" enabled="true" name="SOAP-
Message-Validation-1">
<DisplayName>SOAP Message Validation 1</DisplayName>
<Element namespace="http://sample.com">SampleObject</Element>
<SOAPMessage/>
<Source>request</Source>
<ResourceURL>wsdl://SOAP-Message-Validation-1</ResourceURL>
</MessageValidation>
<MessageValidation> attributes
DisplayName> element
Use in addition to the name attribute to label the policy in the management UI proxy editor with a different,
natural-language name.
<DisplayName>Policy Display Name</DisplayName>
Default: N/A
If you omit this element, the the value of the policy'sname attribute is
used.
Presence: Optional
Type: String
Default: request
Presence: Optional
Type: String
<ResourceURL> element
Identifies the XSD schema or WSDL definition to be used to validate the source message.
If a <ResourceURL> value is not specified, the message is checked for well-formed JSON if the content-type is
application/json.
If the WSDL does not have schemas or if the maximum import depth exceeds 10, message validation will fail.
<ResourceURL>xsd://sample</ResourceURL>
Default: wsdl://<name>
Presence: Optional
Type: String
<SOAPMessage> element
Default: N/A
Presence: Optional
Type: N/A
<Element> element
Default: sampleObject
Presence: Optional
Type: String
Attributes
ResourceURL (Optional) XSD or WSDL file used in the schema validation against the source
message. The message validation fails if the WSDL file does not have
schemas or if the maximum import depth exceeds 10.
If ResourceURL is not specified, the message is checked for:
• Well-formed XML if the content-type is application/xml
• Well-formed JSON if the content-type is application/json
SOAPMessage (Optional) Verifies that the message corresponds to the SOAP format of the
specified version(s).
If the version attribute is not specified, the message could correspond
to either SOAP 1.1 or 1.2 format (example below).
Example
This section describes the error messages and flow variables that are set when this policy triggers an error. This
information is important to know if you are developing fault rules for a proxy.
HTTP
Error name Fault string status Occurs when
Deployment errors
None.
{
"fault": {
"faultstring": "JSONThreatProtection[JPT-SecureRequest]: Execution failed. reason:
JSONThreatProtection[JTP-SecureRequest]: Exceeded object entry name length at line 2",
"detail": {
"errorcode": "steps.jsonthreatprotection.ExecutionFailed"
}
}
}
This section describes the error messages and flow variables that are set when this policy triggers an error. This
information is important to know if you are developing fault rules for a proxy.
steps.xmlthreatprotection
Runtime Errors
None.
Fault variables
{
"fault": {
"faultstring": "XMLThreatProtection[XPT-SecureRequest]: Execution failed. reason:
XMLThreatProtection[XTP-SecureRequest]: Exceeded object entry name length at line 2",
"detail": {
"errorcode": "steps.xmlthreatprotection.ExecutionFailed"
}
}
}
SAP API Management enables developers to convert messages from the extensible markup language (XML)
format to JavaScript object notation (JSON) format using the XMLToJSON policy type. This policy is useful for
enabling backend XML services to support RESTful apps that require JSON (for example, due to a lack of an XML
parsing capabilities on the client).
In a typical mediation scenario, a JSONToXML policy on the inbound request flow is often paired with an
XMLToJSON policy on the outbound response flow. By combining policies this way, a JSON API can be exposed
for backend services that natively support only XML.
For scenarios where APIs are consumed by diverse clients apps which may require either JSON and XML, the
format of the response can be dynamically set by configuring JSONToXML and XMLToJSON policies to execute
conditionally. See Flow variables and conditions for an implementation of this scenario.
The HTTP Content-type header of the source message must be set to text/xml. If the HTTP Content-type header
of the source message is not text/xml, the policy is not enforced.
The payload of the XML message is parsed and converted into JSON, and the HTTP Content-type header of the
XML-formatted message is set to application/json.
Sample
This policy type defines a set of reasonable defaults. The minimal policy configuration required to convert XML to
JSON is the following:
<XMLToJSON name="ConvertToJSON">
<Options>
</Options>
<OutputVariable>response</OutputVariable>
<Source>response</Source>
</XMLToJSON>
Assuming that the intent is to convert an XML-formatted response into a JSON-formatted response, the policy
would be attached to a response Flow (for example, the ProxyEndpoint response PostFlow). This configuration
takes a JSON-formatted response message as the source, and then creates an XML-formatted message that is
populated in the response OutputVariable. SAP API Management automatically uses the content of this variable
as the message for next processing step.
For more advanced control over mapping XML to JSON structures, use the following configuration elements. All
fields are optional. However, if you specify NamespaceBlockName, you must also
specifyDefaultNamespaceNodeName and NamespaceSeparator.
<XMLtoJSON> attributes
name The unique name of the policy. Use this name N/A Yes
to reference the policy within a Step definition
element. Characters you can use in the name
are restricted to: A-Z0-9._\-$ %. However,
the SAP API Management UI enforces
additional restrictions, such as automatically
removing characters that are not
alphanumeric.
async Note: This attribute does not make the policy false Optional
execute asynchronously.
When set to true, policy execution is
offloaded to a different thread, leaving the
main thread free to handle additional
requests. When the offline processing is
complete, the main thread comes back and
finishes handling the message flow. In some
cases, setting async to true improves API
<DisplayName> element
Use in addition to the name attribute to label the policy in the management UI proxy editor with a different,
natural-language name.
<DisplayName>Policy Display Name</DisplayName>
Default: N/A
If you omit this element, the the value of the policy'sname attribute is
used.
Presence: Optional
Type: String
<Source> element
The variable, request or response, that contains the XML message that you want to convert to JSON.
The HTTP Content-type header of the source message must be set to application/xml, otherwise the policy is not
enforced. If <Source> is not defined, then it is treated as message (which resolves to request when the policy is
attached to a request flow, or response when the policy is attached to a response flow).
If the source variable cannot be resolved, or resolves to a non-message type, the policy throws an error.
<Source>response</Source>
Presence Optional
Type message
Stores the output of the XML to JSON format conversion. This is usually the same value as the source, that is,
usually XML response is converted to a JSON response.
The payload of the XML message is parsed and converted into JSON, and the HTTP Content-type header of the
XML-formatted message is set to application/json.
If OutputVariable is not specified, the source is treated as OutputVariable. For example, if the source isresponse,
then OutputVariable defaults to response.
<OutputVariable>response</Response>
Presence Optional
Type message
<Options>/<RecognizeNumber> element
If true, then number fields in the XML payload retain their original format.
<RecognizeNumber>true</RecognizeNumber>
Default false
Presence Optional
Type Boolean
<Options>/<RecognizeBoolean> element
Lets the conversion maintain boolean true/false values rather than turning the values into strings.
<RecognizeBoolean>true</RecognizeBoolean>
Default false
Presence Optional
Type Boolean
<Options>/<RecognizeNull> element
Default false
Presence Optional
Type Boolean
<Options>/<NullValue> element
Indicates what constitutes a null value in the message to be converted. By default the value is NULL.
<NullValue>NULL</NullValue>
Default NULL
Presence Optional
Type String
<Options>/<NamespaceBlockName>
<Options>/<DefaultNamespaceNodeName>
<Options>/<NamespaceSeparator> elements
Presence Optional
However, if you specify <NamespaceBlockName>, you must also
specify the other two elements.
Type Strings
<Options>/<TextAlwaysAsProperty>
<Options>/<TextNodeName> elements
<TextAlwaysAsProperty>true</TextAlwaysAsProperty>
<TextNodeName>TEXT</TextNodeName>
If TextAlwaysAsProperty is set to true and TextNodeName specified as TEXT, the following JSON structure is
generated:
{
"a": {
"b": {
"TEXT": "value1"
},
"c": {
"TEXT": [
"value2",
"value4"
],
"d": {
"TEXT": "value3"
}
}
}
}
If TextAlwaysAsProperty is set to false and TextNodeName specified as TEXT, the following JSON structure is
generated:
{
"a": {
"b": "value1",
"c": {
"TEXT": [
"value2",
"value4"
],
{
"d": "value3",
}
}
}
Presence Optional
<Options>/<AttributeBlockName>
<Options>/<AttributePrefix> elements
Presence Optional
Type String
<Options>/<OutputPrefix>
<Options>/<OutputSuffix> elements
If both the attributes (OutputPrefix and OutputSuffix) are specified as defined in the XML to JSON example, the
following JSON structure is generated:
PREFIX_{
"a": "value"
}_SUFFIX
If neither OutputPrefix nor OutputSuffix is specified, the following JSON structure is generated:
{
"a": "value"
}
Presence Optional
Type String
This section describes the error messages and flow variables that are set when this policy triggers an error. This
information is important to know if you are developing fault rules for a proxy.
ExecutionFailed 500 See the fault string. Be sure the incoming message
contains valid XML.
Fault variables
These variables are set when a runtime error occurs.
Note:
For error handling, the best practice is to trap the errorcode part of the error response. Do not rely on the text in
the faultstring, because it could change.
{
"fault": {
"faultstring": "XMLToJSON[XMLtoJSON-1]: Source xyz is not available",
"detail": {
"errorcode": "steps.xml2json.SourceUnavailable"
}
}
}
When setting a JSON payload using an Assign Message or Raise Fault policy, users were sometimes required to
use workarounds to ensure a JSON message was properly formatted at runtime, such as beginning the payload
with a backslash "\" or specifying a variablePrefix and variableSuffix on the Payload element, even if no variables
were used in the message.
With this enhancement, no workarounds are needed to ensure proper JSON message formatting, and variables
can be specified using curly braces without creating invalid JSON. For example, the following inserts the value of
message.content in the JSON message:
<Payload contentType="application/json">{"Message: " : "{message.content}"}</Payload>
If you used a workaround, your code will continue to work as is. You can also use variablePrefix and variableSuffix
instead of curly braces to indicate variables.
SAP API Management enables developers to convert messages from the JavaScript object notation (JSON)
format to the extensible markup language (XML) format by using the JSONtoXML policy type. This policy is useful
for enabling backend XML services to support RESTful apps that require JSON (for example, due to a lack of an
XML parsing capabilities on the client).
In a typical mediation scenario, a JSONtoXML policy on the inbound request flow is often paired with an
XMLtoJSON policy on the outbound response flow. By combining policies this way, a JSON API can be exposed
for services that natively support only XML.
For scenarios where APIs are consumed by diverse clients apps which may require either JSON or XML, the
format of the response can be dynamically set by configuring JSONtoXML and XMLtoJSON policies to execute
conditionally.
See Flow variables and conditions for an implementation of this scenario.
Sample
A set of configuration options are provided to customize the XML output by the JSONtoXML policy. The
JSONtoXML policy defines a set of reasonable defaults. It is often useful to apply the default (empty) JSONtoXML
policy and iteratively add configuration elements as required.
The minimum required configuration is the following:
<JSONToXML name="jsontoxml">
<Options>
</Options>
</JSONToXML>
All elements in this policy type are optional unless you need to define XML namespaces.
IfNamespaceBlockName is set, DefaultNamespaceNodeName and NamespaceSeparator must also be specified.
The HTTP Content-type header of the source message must be set to application/json. If the HTTP Content-type
header of the source message is not application/json, then the policy is not enforced.
The payload of the JSON message is parsed and converted into XML. The HTTP Content-type header of the XML-
formatted message is set to application/xml.
Note
The name attribute for this policy is restricted to these characters: A-Z0-9._\-$ %. However, the
Management UI enforces additional restrictions, such as automatically removing characters that are not
alphanumeric.
OutputVariable The variable name of the resultant XML-formatted message. Usually, you set
this to request or response, depending on whether the message to be
transformed is inbound or outbound. In most cases, an JSON request is
transformed into an XML request. Similarly, a JSON response is usually
transformed into an XML response.
If OutputVariable is not specified, then the source variable is treated
asOutputVariable. That is, the policy assumes that a JSON request, for example,
is being converted into an XML request.
InvalidCharsReplacement To assist with handling invalid XML that may cause issues with a parser, this
setting replaces any JSON elements that produce invalid XML with the string.
For example, the following setting:
<InvalidCharsReplacement>_</InvalidCharsReplacement>
Converts this JSON object
{
"First%%%Name": "John"
}
to this XML structure:
<First_Name>John<First_Name>
TextNodeName Converts a JSON property into an XML text node with the specified name. For
example, the following setting:
<TextNodeName>age</TextNodeName>
AttributeBlockName Enables you to specify when JSON elements are converted into XML attributes
(rather than XML elements).
For example, the following setting converts properties inside an object
named#attrs into XML attributes:
<AttributeBlockName>#attrs</AttributeBlockName>
The following JSON object:
{
"person" : {
AttributePrefix Converts the property starting with the specified prefix into XML attributes.
Where the attribute prefix is set to @, for example:
<AttributePrefix>@</AttributePrefix>
Converts the following JSON object:
{
"person" : {
"@firstName" : "John",
"@lastName" : "Smith"
"occupation" : "explorer",
}
}
to the following XML structure:
<person firstName="John" lastName="Smith">
<occupation>explorer</occupation>
</person>
NamespaceBlockName JSON has no support for namespaces, while XML documents often require
them. The NamespaceBlockName enables you to define a JSON property that
serves as the source of a namespace definition in the XML that is produced by
the policy. (This means that the source JSON must provide a property that can
be mapped into a namespace that is expected by application that consumes the
resulting XML.)
For example, the following settings:
<NamespaceBlockName>#namespaces</NamespaceBlockName>
<DefaultNamespaceNodeName>$default</DefaultNamespaceNodeName>
<NamespaceSeparator>:</NamespaceSeparator>
Indicates that a property called #namespaces exists in the source JSON that
contains at least one namespace designated as the default. For example:
{
ArrayRootElementName Converts a JSON array into a list of XML elements with specified parent and
child element names.
For example, the following settings:
<ArrayRootElementName>Array</ArrayRootElementName>
<ArrayItemElementName>Item</ArrayItemElementName>
Converts the following JSON array:
[
"John Cabot",
{
"explorer": "Pedro Cabral"
},
"John Smith"
]
into the following XML structure:
<Array>
<Item>John Cabot</Item>
<Item>
<explorer>Pedro Cabral</explorer>
</Item>
<Item>John Smith</Item>
</Array>
Create a TargetServer
Create a TargetServer in the specified environment. TargetServers are used to decouple TargetEndpoint
HTTPTargetConnections from concrete URLs for backend services.
environments/{env_name}/targetservers
To do so, an HTTPConnection can be configured to use a LoadBalancer that lists one or more 'named'
TargetSevers. Using TargetServers, you can create an HTTPTargetConnection that calls a different backend
server based on the environment where the API proxy is deployed. See also Load Balancing Across Backend
Servers.
Category TargetServers,
Note:
Characters you can use in the name are restricted to: A-Z0-9._\-$%
You can configure a TargetServer to use SSL.TargetServers expose the same SSL configuration settings as
TargetEndpoints:
<TargetServer name="TargetServer 1">
<IsEnabled>true</IsEnabled>
<Host>www.example.com</Host>
<Port>443</Port>
<SSLInfo>
<Ciphers/>
<ClientAuthEnabled>true</ClientAuthEnabled>
<Enabled>true</Enabled>
<IgnoreValidationErrors>false</IgnoreValidationErrors>
Resource URL
https://<managment_server_ip:8080>/v1/organizations/{org_name}/environments/{env_name}
/targetservers
Header Parameters
Request Body
Delete a TargetServer configuration from an environment. Returns information about the deleted TargetServer.
{environments}/env/targetservers/{targetserver_name}
Resource Summary
Category TargetServers,
Resource URL
https://<managment_server_ip:8080>/v1/organizations/{org_name}/environments/{env_name}/t
argetservers/{targetserver_name}
Resource Summary
Category TargetServers,
Resource URL
https://<managment_server_ip:8080>/v1/organizations/{org_name}/environments/{env_name}
/targetservers
Resource Summary
Category TargetServers,
Resource URL
https://managment_server_ip:8080>/v1/organizations/{org_name}/environments/{env_name}/
targetservers/{targetserver_name}
Update a TargetServer
For example, use this method to toggles a TargetServer configuration from enabled to disabled. This is useful
when TargetServers are used in load balancing configurations, and one or more TargetServers need to be taken
out of rotation periodically. You could also use this API to modify the hostname of an enabled target server.
/environments/{env_name}/targetservers/{targetserver_name}
Resource Summary
Category TargetServers,
https://managment_server_ip:8080>/v1/organizations/{org_name}/environments/{env_name}/ta
rgetservers/{targetserver_name}
Header Parameters
Request Body
The Java Callout Policy enables you to use Java to implement custom behavior that is not delivered out-of-the-box
by SAP API Management policies.
The Java Callout Policy can be attached in the following locations:
Samples
<JavaCallout name="cityLookUp">
<ClassName>com.sap.CityLookup</ClassName>
<ResourceURL>java://CityLookup.jar</ResourceURL>
</JavaCallout>
Element reference
The element reference describes the elements and attributes of the JavaCallout policy.
<JavaCallout name="MyJavaCalloutPolicy">
<ClassName>com.example.mypolicy.MyJavaCallout</ClassName>
<ResourceURL>java://MyJavaCallout.jar</ResourceURL>
</JavaCallout>
<JavaCallout> attributes
<JavaCallout name="MyJavaCalloutPolicy">
name The internal name of the policy. Characters you can use in the N/A Required
name are restricted to: A-Z0-9._\-$ %. However, the SAP API
Management Edge UI enforces additional restrictions, such
as automatically removing characters that are not
alphanumeric.
Optionally, use the <DisplayName> element to label the
policy in the management UI proxy editor with a different,
natural-language name.
continueOnError Set to false to return an error when a policy fails. This is false Optional
expected behavior for most policies.
Set to true to have flow execution continue even after a policy
fails.
<DisplayName> element
Use in addition to the name attribute to label the policy in the management UI proxy editor with a different,
natural-language name.
<DisplayName>Policy Display Name</DisplayName>
Default: N/A
If you omit this element, the value of the policy's nameattribute is used.
Presence: Optional
Type: String
<ResourceURL> element
Specifies the name and location of the main JAR file used to execute the callout. This JAR file contains compiled
Java code written to the Java API exposed by the API Platform processing pipeline.
<JavaCallout name="MyJavaCalloutPolicy">
<ResourceURL>java://MyJavaCallout.jar</ResourceURL>
<ClassName>com.example.mypolicy.MyJavaCallout</ClassName>
</JavaCallout>
<ClassName> element
Specifies the name of the Java class that executes the callout.
<JavaCallout name="MyJavaCalloutPolicy">
<ResourceURL>java://MyJavaCallout.jar</ResourceURL>
<ClassName>com.example.mypolicy.MyJavaCallout</ClassName>
</JavaCallout>
• Default: N/A
• Presence: Required
• Type: String
Error reference
This section describes the error messages and flow variables that are set when this policy triggers an error. This
information is important to know if you are developing fault rules to handle errors.
steps.messagelogging
Runtime errors
Fault variables
{
"fault":{
"faultstring":"Failed to execute JavaCallout. [policy_name]",
"detail":{
"errorcode":"javacallout.ExecutionError"
}
}
}
<FaultRule name="JavaCalloutFailed">
<Step>
<Name>AM-JavaCalloutError</Name>
</Step>
Before we take a look at the Java implementation, let's see how to reference a Java class (or classes) in a policy. In
this cookbook sample, there is a policy called cityLookup.xml. You can find it in the standard policies directory
inside the apiproxy folder. If you downloaded the code, you can find the policy XML here: doc-samples/java-
cookbook/apiproxy/policies/cityLookup.xml.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<JavaCallout name="cityLookUp">
<ClassName>com.sap.CityLookup</ClassName>
<ResourceURL>java://CityLookup.jar</ResourceURL>
</JavaCallout>
This is a very simple, straightforward policy! Besides a name (cityLookup), this policy references the main Java
class file and a JAR file. As you might expect, the class file and all supporting classes are stored in the JAR. If you
refer back to the flow, you will note that the cityLookup policy is called in the <Request> stage of the
ProxyEndpoint. This means that the Java class is executed at that stage in the flow.
Let's look at the Java class next, and then at how it is compiled, packaged, and deployed.
This example Java class is deliberately simple and trivial. However, it illustrates some fundamental concepts
common to any Java code that is executed through a JavaCallout policy.
package com.sap;
import com.sap.flow.execution.ExecutionContext;
import com.sap.flow.execution.ExecutionResult;
import com.sap.flow.execution.spi.Execution;
import com.sap.flow.message.MessageContext;
if (cityName.equals("MILAN")) w=718345;
else if (cityName.equals("ROME")) w=721943;
else if (cityName.equals("VENICE")) w=725746;
if(w>0) {
messageContext.getRequestMessage().setQueryParam("w", w);
} else {
//default to palo alto
messageContext.getRequestMessage().setQueryParam("w", 2467861);
}
return ExecutionResult.SUCCESS;
} catch (Exception e) {
return ExecutionResult.ABORT;
}
}
}
The most important things to remember about this Java implementation are:
• Imports classes from the com.sap.flow.execution and com.sap.flow.message packages. These packages
must be included in the JAR file that is packaged and deployed. We'll cover packaging and deployment later in
this topic. In the cookbook sample download, you can find these packages in doc-samples/java-cookbook/lib.
• Implements Execution. Any Java code that is executed within an API proxy must implement Execution.
<<note about javadoc>>
Error handling
The execute() method in our Java class throws an exception if it can't recognize the city query parameter (only
three Italian city names are valid: Milan, Venice, and Rome). On error, the method returns an
ExectionResult.ABORT status. To handle this error situation, we added a RaiseFault policy to the flow. If you refer
back to the proxy flow shown previously, you will see that this policy, called Fault.MissingCityName, is added to
the policy's <FaultRules> element.
Here is the policy XML. If you downloaded the sample code from Github, you can find this policy XML here: doc-
samples/java-cookbook/apiproxy/policies/Fault.MissingCityName.xml.
<RaiseFault name="Fault.MissingCityName">
<IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
<FaultResponse>
Our final task is to specify the Yahoo Weather API URL on the proxy's TargetEndPoint. If you downloaded the
code, you can find the policy XML here: doc-samples/java-cookbook/apiproxy/targets/default.xml. Here is the
source code:
<TargetEndpoint name="default">
<HTTPTargetConnection>
<Properties/>
<URL>http://weather.yahooapis.com/</URL>
</HTTPTargetConnection>
</TargetEndpoint>
Before you can deploy and test this sample, you must first compile the CityLookup.java class and generate a JAR
file that contains that class plus the required packages that the custom class requires. The required libraries are
expressions-1.0.0.jar and message-flow-1.0.0.jar, and they are located in the doc-samples/java-cookbook/lib
folder.
To summarize, you can call the API as follows. Substitute {myorg} with your organization name. This example
assumes you are using the test environment.
curl http://{hostname}:{port}/java-cookbook/forecastrss?city=venice
The response includes weather information for Venice in XML format. Here are the first few lines of the response:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<rss version="2.0" xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0"
xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#">
<channel>
<error>
<httpResponseCode>409</httpResponseCode>
<errorCode>error_409</errorCode>
<errorMessage>Missing City Name</errorMessage>
<errorMoreInfo>Provide a city parameter in the querystring e.g.
city=venice</errorMoreInfo>
</error>
• For lightweight operations, such as API calls to remote services, we recommend using the ServiceCallout
policy. See Service Callout policy.
• For relatively simple interactions with message content, such as modifying or extracting HTTP headers,
parameters, or message content, you can use JavaScript or Python languages.
• Place the JAR in an API proxy under /resources/java. If your JavaCallout relies on additional third-party
libraries packaged as independent JAR files, then place those JAR files in the /resources/java directory as
well to ensure that they are loaded correctly at runtime. If you are using the management UI to create or
modify the proxy, add a new resource and specify an additional dependent JAR file. If there are multiple JARs,
simply add them as additional resources. You do not need to modify the policy configuration to refer to
additional JAR files. Putting them in /resources/java is sufficient.
• System calls, for example network I/O, filesystem read/writes, current user info, process list, and
CPU/memory utilization are not permitted by the security model. Although some such calls may be
functional, they are unsupported and liable to be actively disabled at any time. For forward compatibility, you
should avoid making such calls in your JavaCallout.
Use the Flow Callout policy to call out to a shared flow from either an API proxy or another shared flow.
Note: The ability to create shared flows is available only on request. The feature will not appear in the user
interface unless activated for your org.
In a shared flow, you create a sequence of steps that you can reuse at run time from multiple places. These steps
are implemented as policies, as with an API proxy. The Flow Callout policy gives you a way to call to the shared
flow from API proxies and other shared flows.
• For example, imagine that you've implemented a shared flow with security features such as API key
verification and OAuth token validation. Using the Flow Callout policies, you can route requests through that
flow from multiple API proxies. In this way, you can enforce standard security in one place, then use it from
multiple others.
• You can call one shared flow from another by implementing a Flow Callout policy in a shared flow. For
example, the security shared flow could use a Flow Callout policy to call to another shared flow that performs
a transformation on the incoming request message
For more on shared flows, see Reusable shared flows. You can also call a shared flow from outside API proxy code
to do request pre-processing or response post-processing.
This policy can be attached in the following locations.
There are many scenarios where you can use a Service Callout policy in your API proxy. For example, you can
configure an API proxy to make calls to an external service to deliver geolocation data, customer reviews, items
from a partner’s retail catalog, and so on.
Element reference
Following are elements and attributes you can configure on this policy:
<FlowCallout async="false" continueOnError="false" enabled="true" name="Flow-Callout-
1">
<DisplayName>Custom label used in UI</DisplayName>
<SharedFlowBundle>thereferencedsharedflowbundle</SharedFlowBundle>
</FlowCallout>
<FlowCallout> attributes
Name The internal name of the policy. Characters you can use in N/A Required
the name are restricted to: A-Z0-9._\-$ %. However, the
Edge management UI enforces additional restrictions,
such as automatically removing characters that are not
alphanumeric.
continueOnError Set to false to return an error when a policy fails. This is False Optional
expected behavior for most policies.
Set to true to have flow execution continue even after a
policy fails.
<DisplayName> element
Use in addition to the name attribute to label the policy in the management UI proxy editor with a different,
natural-language name.
<DisplayName>Policy Display Name</DisplayName>
Default: N/A
If you omit this element, the value of the policy's name attribute is used.
Presence: Optional
Type: String
<SharedFlowBundle> element
Specifies the name of the shared flow to call. This element's value should be the same as the value of the target
SharedFlowBundle element's name attribute.
<SharedFlowBundle/>
In the simplest example, you give the name of the shared flow being called as a value for this element. That is, this
element's value must be the same as the shared flow's name attribute value.
<SharedFlowBundle>Shared-Flow-Name</SharedFlowBundle>
Default: N/A
Presence: Required
Type: String
Attributes: None
Flow variables enable dynamic behavior of policies and flows at runtime, based on HTTP headers, message
content, or flow context.
Attribute Description
apigee.edge.flowhook.name Scope: During execution of the shared flow attached to the flow hook.
Type: String
Permission: Read
The name of the flow hook.
Error Codes
None.
Definition
Term
API Proxy A type of application that runs on SAP API Management and exposes a facade
for one or more APIs, generic HTTP services.
An API proxy is implemented as a set of configuration files, policies, and code
that rely on a set of resources provided by SAP API Management Services.
API proxies can be generated and configured using the SAP API Management
UI, or they can be implemented locally in a text editor or IDE.
API base path and resources APIs defined by network addresses and URIs. An API is made up of a "base
path" and a set of "API resources". Every API proxy defines a base path and,
optionally, multiple API resource paths. You can think of an API simply as a
set of URIs, all of which share a common base path.
API Product A collection of API resources (URIs) combined with a quota, or 'service plan',
which is published to app developers at design time. API products can in turn
be bundled into API packages.
An API key is bound to one or more API products, enforcing a binding between
an app and the bundle of URIs that the app is permitted to consume.
API package A collection of API products that are presented to developers as a bundle, and
typically associated with a rate plan.
Apps • Your developers use apps to access the resources in your API products.
When you create an app, you select the API product to include, and SAP
API Management generates a key. Each app has a single key that provides
access to multiple API products. Apps allow you to control who can
access your resources. You can control who has access to your API
products by revoking and refreshing an app's key. And you can control
access to bundles of resources by revoking or deleting access to the
products in an app.
Environment A runtime execution context for API proxies. An API proxy must be deployed
to an environment before the API it exposes is accessible over the network.
By default, organizations are provisioned with two environments: 'test' and
'prod'.
• The 'test' environment is typically used for deploying API proxies during
development.
The 'prod' environment is typically used for promoting API proxies from the
test environment after they have been fully developed and tested.
Organization A container for all the objects in the SAP API Management account, including
API proxies, API products, API packages, apps, and developers.
A user account is required for each organization for which you are a member.
(Most users will have an account in only one organization.) You need to supply
your credentials (username and password) and the name of your organization
with each API request you submit.
Policy A processing step that executes as an atomic, reusable unit of logic within an
API proxy processing flow.
Typical policy-based functionality includes transforming message formats,
enforcing access control, calling remote services for additional information,
masking sensitive data from external users, examining message content for
potential threats, caching common responses to improve performance, and
so on.
Policies may be conditionally executed based on the content or context of a
request or response message. For example, a transformation policy may be
executed to customize a response format if the request message was sent
from a smartphone.
resource A RESTful concept, a resource path is a uniform resource identified (URI) that
path identifies the network path to a given resource.