API version 2.0 (the documentation for the previous version is here).
The other way to integrate your API with our API Management solution is to use the 3scale REST API for authenticating calls and reporting usage.
Documentation
This document describes the protocol used for your API to communicate with 3scale backend server for authorizing and reporting transactions between your infrastructure and your API users.
Definitions
- service
- any web service implementing an API
- provider
- an organization, company or individual providing a service
- application
- a consumer endpoint of a web service (website, embeddable widget, desktop program, mobile application, HTTP enabled microwave oven, ...)
- transaction
- Single unit of interaction between an application and a service. In case of HTTP-base web services, this is usually one request-response exchange.
- resource
- Anything that is spent during a transaction and can be measured. This can be for example CPU time spent during the processing, or storage space used for storing some data, and so on.
- metric
- A way to measure a resource. For example: number of API hits, amount of disk space in megabytes, CPU time in milliseconds, ...
- provider key
- Unique textual identifier of a provider.
- application id
- Public unique textual identifier of an application.
- application key
- Secret key for authenticating transactions.
Operations
The API exposes a simple REST-based interface that provides these operations: authorize, and report.
Authorize
Read-only operation to authorize an application. It is used to check if a particular application exists, is active and is within usage limits of the service. It can be optionally used to authenticate a call using an application key.
GET /transactions/authorize.xml?app_id={app_id}&provider_key={provider_key}[&app_key={app_key}]
Parameters
- provider_key
- Provider key. Required.
- service_id
- Service id. Required only if as a provider you have multiple services allowed and enabled.
- app_id
- Application id. Required.
- app_key
- Application key. Required only if it is defined for the application.
- referrer
- Referrer IP Address or Domain. Required if referrer filtering is enabled. If special value "*" (start) is passed, the referrer check is bypassed.
- usage
- Predicted usage. Optional
Predicted usage
It's possible to pass a "predicted usage" to the authorize call. This can serve two purposes:
- To make sure an API call won't go over the limits before the call is made, if the usage of the call is known in advance. In this case, the estimated usage can be passed to the authorize call, and it will respond whether the actual API call is still within limit. In other words, without the usage parameter, authorize only checks the usage that has already been reported. If the usage parameter is passes in, it will check whether the already reported usage + the passed in predicted usage is still within limit.
- To limit the authorization only to a subset of metrics. If usage is passed in, only the metrics listed in it will be checked against the limits. For example: There are two metrics defined: searches and updates. updates are already over limit, but searches are not. In this case, the user should still be allowed to do a search call, but not an update one. To authorize this, pass
usage[searches]=1
to the authorize call.
NOTE: Even if the predicted usage is passed in, authorize is still a read-only operation. You have to make the report call to report the usage.
NOTE: usage is an associative array of the form {metric : value}
. Please reefer to the "Encoding complex data structures in URLs" appendix for more info.
NOTE: usage can be either a positive integer (e.g. 1, 50) or a positive integer prefixed with the character '#' (e.g. #1, #50). In the first case, the value of the usage will be incremented, whereas in the second case will be set to the numerical value. Thus, usage[hits]=1
will increment the hits counter by +1
, whereas usage[hits]=#1
will set the hits counters to 1
.
Setting the value of a counter with the prefix '#' to wherever the usage is present. However, this is something that needs to be handled with care because it can raise concurrency issues. For instance, in the case of two (or more) concurrent requests: usage[hits]=#1
, usage[hits]=#10
it is not possible to determine the final value of hits, it can be either 1 or 10 depending on which was the last request processed by 3scale's backend. We cannot ensure order preserving or reconciliation. In the case of usage[hits]=1
and usage[hits]=10
, the final value of hits would have been incremented by 11.
Another potential issue with setting the value of a counter with the prefix '#' is that in the case applying to methods (metrics that are children of metrics) the parent will also be take the value of the child. For instance, let's assume that views and save are methods of the metric hits, thus views and save are children of hits. In this case, if we do usage[save]=1
and usage[views]=3
, the value of views will be increased by 3, the value of save will be increased by 1 and the value of hits will be implicitly increased by 4 (3+1). On the other hand, doing a usage[save]=#1
and usage[views]=#3
will set the value of views to 3, the value of save will be set to 1, but the value of hits will be set to either 3 or 1 depending which method was processed last.
Successful Response
Has status code 200 OK
(if authorization is granted), 409
(if it's not granted) and a body containing authorization result, failure reason (if authorization failed), the plan type and list of usage report entries for every current metric limit.
Example of successful authorize response
<status>
<authorized>true</authorized>
<plan>Pro</plan>
<usage_reports>
<usage_report metric="hits" period="month">
<period_start>2010-08-01 00:00:00 +00:00</period_start>
<period_end>2010-09-01 00:00:00 +00:00</period_end>
<current_value>17344</current_value>
<max_value>20000</max_value>
</usage_report>
<usage_report metric="hits" period="day">
<period_start>2010-08-04 00:00:00 +00:00</period_start>
<period_end>2010-08-05 00:00:00 +00:00</period_end>
<current_value>732</current_value>
<max_value>1000</max_value>
</usage_report>
</usage_reports/>
</status>
Example of failed authorize response (exceeded limits)
<status>
<authorized>false</authorized>
<reason>Usage limits are exceeded</reason>
<plan>Pro</plan>
<usage_reports>
<usage_report metric="hits" period="month">
<period_start>2010-08-01 00:00:00 +00:00</period_start>
<period_end>2010-09-01 00:00:00 +00:00</period_end>
<current_value>17344</current_value>
<max_value>20000</max_value>
</usage_report>
<usage_report metric="hits" period="day" exceeded="true">
<period_start>2010-08-04 00:00:00 +00:00</period_start>
<period_end>2010-08-05 00:00:00 +00:00</period_end>
<current_value>1042</current_value>
<max_value>1000</max_value>
</usage_report>
</usage_reports/>
</status>
Explanation of the elements
- status
- Root element of the response.
- authorized
- Contains text "true" if the authorization was successful, or "false" if it failed.
- reason
- Human readable textual description of failure reason. This element appears only if authorize is false.
- plan
- Name of the plan the user is signed up to.
- usage_reports
- Contains list of usage_report elements - one per each usage limit defined for the plan the user is signed up to.
- usage_report
- Contains information about usage status. Contains these elements: period_start, period_end, current_value and max_value. Has attributes metric with the name of the metric the limit applies to, period, which is the period of the limit (year, month, week, day, hour, minute) and optionally exceeded which is set to "true" if the limit is exceeded in the current period.
- period_start
- Start of the limit period. It's in the form YYYY-MM-DD HH:MM:SS +ZZ:ZZ. +ZZ:ZZ (or -ZZ:ZZ) is a time offset (in hours and minutes) from UTC.
- period_end
- End of the limit period. Same format as period_start
- current_value
- Value of the corresponding metric accumulated so far in the current period.
- max_value
- Maximum value allowed by the usage limit.
Errors
In case of error, the response body contains an XML-formatted object with a single element error. This element has one attribute code containing a unique string identifier of the error. The content of this element is a human-readable English description of the error.
These are all possible error identifiers and their meanings:
- provider_key_invalid
- Provider key is not valid
- application_not_found
- Application with the given id does not exist.
This is an example of an error response:
<?xml version="1.0" encoding="utf-8" ?>
<error code="application_not_found">Application with id="12345678" was not found</error>
Example Request
GET /transactions/authorize.xml?app_id=709deaac&provider_key=pkey&app_key=app_key HTTP/1.1
Host: su1.3scale.net
Example Request with referrer
GET /transactions/authorize.xml?app_id=709deaac&provider_key=pkey&app_key=app_key&referrer=example.org HTTP/1.1
Host: su1.3scale.net
Example Request with usage
GET /transactions/authorize.xml?app_id=709deaac&provider_key=pkey&app_key=app_key&usage[hits]=1&usage[transfer]=1024 HTTP/1.1
Host: su1.3scale.net
Example Request with usage and service_id
GET /transactions/authorize.xml?service_id=7812315&app_id=709deaac&provider_key=pkey&app_key=app_key&usage[hits]=1&usage[transfer]=1024 HTTP/1.1
Host: su1.3scale.net
OAuth Authorize
It's a modified version of the authorize call that returns some extra data that is needed to power OAuth APIs. It's only available for users with OAuth enabled APIs.
GET /transactions/oauth_authorize.xml?app_id={app_id}&provider_key={provider_key}[&app_key={app_key}]
Parameters
- provider_key
- Provider key. Required.
- service_id
- Service id. Required only if as a provider you have multiple services allowed and enabled.
- app_id
- Application id. Required.
- app_key
- Application key. Optionl. Will be validated if sent.
- referrer
- Referrer IP Address or Domain. Required if referrer filtering is enabled. If special value "*" (start) is passed, the referrer check is bypassed.
- usage
- Predicted usage. Optional
- redirect_url
- Redirect URL for OAuth. Optional. Will be validated if sent.
Successful Response
Has status code 200 OK
(if authorization is granted), 409
(if it's not granted) and a body containing authorization result, failure reason (if authorization failed), the plan type and list of usage report entries for every current metric limit.
Example of successful authorize response
<status>
<authorized>true</authorized>
<plan>Pro</plan>
<application>
<id>57c53c8a</id>
<key>433dbee8b34524326a2b4a3c126ec5c3</key>
<redirect_url>http://www.example.com/redirect_url</redirect_url>
</application>
<usage_reports>
<usage_report metric="hits" period="month">
<period_start>2010-08-01 00:00:00 +00:00</period_start>
<period_end>2010-09-01 00:00:00 +00:00</period_end>
<current_value>17344</current_value>
<max_value>20000</max_value>
</usage_report>
<usage_report metric="hits" period="day">
<period_start>2010-08-04 00:00:00 +00:00</period_start>
<period_end>2010-08-05 00:00:00 +00:00</period_end>
<current_value>732</current_value>
<max_value>1000</max_value>
</usage_report>
</usage_reports/>
</status>
Example of failed authorize response (exceeded limits)
<status>
<authorized>false</authorized>
<reason>Usage limits are exceeded</reason>
<plan>Pro</plan>
<application>
<id>57c53c8a</id>
<key>433dbee8b34524326a2b4a3c126ec5c3</key>
<redirect_url>http://www.example.com/redirect_url</redirect_url>
</application>
<usage_reports>
<usage_report metric="hits" period="month">
<period_start>2010-08-01 00:00:00 +00:00</period_start>
<period_end>2010-09-01 00:00:00 +00:00</period_end>
<current_value>17344</current_value>
<max_value>20000</max_value>
</usage_report>
<usage_report metric="hits" period="day" exceeded="true">
<period_start>2010-08-04 00:00:00 +00:00</period_start>
<period_end>2010-08-05 00:00:00 +00:00</period_end>
<current_value>1042</current_value>
<max_value>1000</max_value>
</usage_report>
</usage_reports/>
</status>
Explanation of the elements
- status
- Root element of the response.
- authorized
- Contains text "true" if the authorization was successful, or "false" if it failed.
- reason
- Human readable textual description of failure reason. This element appears only if authorize is false.
- plan
- Name of the plan the user is signed up to.
- application
- Parent element that holds the application details.
- id
- ID of the application. Matches the sent app_id.
- key
- Key of the application. You should use this as your OAuth v1.0a secret or OAuth v2.0 key.
- redirect_url
- Rdirect URL configured by the author of the application. If it's a web application you might be interested in making sure you'll only redirect users to this URL.
- usage_reports
- Contains list of usage_report elements - one per each usage limit defined for the plan the user is signed up to.
- usage_report
- Contains information about usage status. Contains these elements: period_start, period_end, current_value and max_value. Has attributes metric with the name of the metric the limit applies to, period, which is the period of the limit (year, month, week, day, hour, minute) and optionally exceeded which is set to "true" if the limit is exceeded in the current period.
- period_start
- Start of the limit period. It's in the form YYYY-MM-DD HH:MM:SS +ZZ:ZZ. +ZZ:ZZ (or -ZZ:ZZ) is a time offset (in hours and minutes) from UTC.
- period_end
- End of the limit period. Same format as period_start
- current_value
- Value of the corresponding metric accumulated so far in the current period.
- max_value
- Maximum value allowed by the usage limit.
Errors
In case of error, the response body contains an XML-formatted object with a single element error. This element has one attribute code containing a unique string identifier of the error. The content of this element is a human-readable English description of the error.
These are all possible error identifiers and their meanings:
- provider_key_invalid
- Provider key is not valid
- application_not_found
- Application with the given id does not exist.
This is an example of an error response:
<?xml version="1.0" encoding="utf-8" ?>
<error code="application_not_found">Application with id="12345678" was not found</error>
Example Request
GET /transactions/oauth_authorize.xml?app_id=709deaac&provider_key=pkey&app_key=app_key HTTP/1.1
Host: su1.3scale.net
Authrep
"One-shot" operation to authorize an application and report traffic. The only difference between this call and the regular authorize call is that metric usage will be reported if the authorization is successful. For additional examples of authrep calls you can see the examples or authorize calls, all parameters in authorized are also valid in the authrep case.
GET /transactions/authrep.xml?app_id={app_id}&provider_key={provider_key}[&app_key={app_key}]&usage[hits]=1
Parameters
- provider_key
- Provider key. Required.
- service_id
- Service id. Required only if as a provider you have multiple services allowed and enabled.
- app_id
- Application id. Required.
- app_key
- Application key. Required only if it is defined for the application.
- referrer
- Referrer IP Address or Domain. Required if referrer filtering is enabled. If special value "*" (start) is passed, the referrer check is bypassed.
- usage
- Metric usage. If the authorization succeeds and the application is still within the limits with this usage, it's aggregated to the application statistics and usage limits.
- log
- Log requests. Optional, available only to certain 3scale's plans. If allowed and enabled it let's you log requests/responses/response_codes of your API, such logs will be accessible on your admin portal as a providers as well as on the buyer portal for the users of your API.
Usage
The usage parameters should be passed along in order to report traffic.
- This will make sure an API call won't go over the limits. It will check whether the already reported usage + the passed in usage is still within limit.
- If the authorization is successful the usage will then be "reported" and aggregated for statistics and usage limits purposes. There is no need to make a second call to report the traffic since this is already taken care of.
NOTE: usage is an associative array of the form {metric : value}
. Please refer to the "Encoding complex data structures in URLs" appendix for more info.
Log
The log parameters should be passed along in order to keep a log of your API requests.
- This parameter is optional and it is only allowed to certain 3scale's plans. If as providers you have log requests allowed and enabled you can send the body of the API requests, responses and status code to 3scale so that you can keep a log of the latest activity of your API. Please refer to the "Log Request" appendix for more info.
- In addition, log is an associative array of the form
{request : value, response : value, code : value}
. Please refer to the "Encoding complex data structures in URLs" appendix for more info.
- The request in log is required whereas the rest are optional and can be left blank. Additionally, the values for log they have to be url-encoded.
Example Request with usage
GET /transactions/authrep.xml?app_id=709deaac&provider_key=pkey&app_key=app_key&usage[hits]=1&usage[storage]=500 HTTP/1.1
Host: su1.3scale.net
Example Request with logs
GET /transactions/authrep.xml?app_id=709deaac&provider_key=pkey&app_key=app_key&usage[hits]=1&usage[storage]=500&log[request]=%2Fmethod1.xml%3Fkey%3DXXX%26id%3DYYYY%26usage%5Bbla%5D%3D1&log[response]=%3C%3Fxml+version%3D%221.0%22+encoding%3D%22UTF-8%22%3F%3E%3Cerror+code%3D%22key_invalid%22%3Ekey+%22XXX%22+is+invalid%3C%2F& log[code]=200& HTTP/1.1
Host: su1.3scale.net
Successful Response
Has status code 200 OK
(if authorization is granted - and therefore reported), 409
(if it's not granted) and a body containing authorization result, failure reason (if authorization failed), the plan type and list of usage report entries for every current metric limit.
Report
This operation is used to report 3scale system about transactions. Any number of transactions can be reported in one request.
POST /transactions.xml
Parameters
- transactions
- List of parameters for each transaction in the batch. More details are explained below. Required.
- provider_key
- Provider key. Required.
- service_id
- Service id. Required only if as a provider you have multiple services allowed and enabled.
The structure of the transactions parameter
The transactions should contain numerically indexed list of records, one for each transaction. Each record can contain these parameters:
- app_id
- Application ID. Required.
- usage
- Usage data of the transaction. This should be associative array (a hash) of the form:
{metric => value, ...}
, where metric is name of the metric that measures the particular resource (for example "storage" or "hits") and value is any amount of the corresponding resource spend in the transaction. Required.
- timestamp
- If given, should be date and time when the transaction occurred. It can be
specified in two ways: First, in UTC (Greenwich time), second, in any other time zone.
In the first case, the timestamp has to be in this format:
YYYY-MM-DD HH:MM:SS
for example 2009-01-01 17:45:02
. In the second case, the format has to be YYYY-MM-DD HH:MM:SS +HH:MM
or YYYY-MM-DD HH:MM:SS -HH:MM
, where the +HH:MM
(or -HH:MM
) part specifies the time offset from UTC in hours and minutes. For example, for timestamp in PST (Pacific Standard Time), it should look like this: 2009-01-01 22:15:31 -08:00
. Optional. If not specified, the time when the transaction was received is used.
- log
- This parameter is optional and it is only allowed to certain 3scale's plans. If as providers you have log requests allowed and enabled you can send the body of the API requests, responses and status code to 3scale so that you can keep a log of the latest activity of your API. Please refer to the "Log Request" appendix for more info. In addition, log is an associative array of the form
{request : value, response : value, code : value}
. Please refer to the "Encoding complex data structures in URLs" appendix for more info. The request in log is required whereas the rest are optional and can be left blank. Additionally, the values for log they have to be url-encoded.
These parameters have to be encoded in HTTP POST request using the application/x-www-form-urlencoded
media type. Please reefer to the "Encoding complex data structures in URLs" appendix for more info.
Successful Response
Has status code 202 Accepted
and no response body
Errors
Processing transactions, especially if there is lot of them, can be time consuming task. To achieve low response times, most of the processing is actually done offline. Fot this reason, there are two ways the errors are reported:
Errors detected during request processing
Only one type of error can occur during request processing - invalid provider key. In case the provider key is not valid, the response has status code 403 Forbidden
and the body contains XML document with description of the error. Example:
<?xml version="1.0" encoding="utf-8" ?>
<error code="provider_key_invalid">Provider key "abcd1234" is invalid</error>
Errors detected during offline processing
If an error occurs during offline processing, it's description is stored and can be examined by visiting the provider admin area on www.3scale.net.
Errors that can occur in the offline processing are:
- invalid application id
- invalid metric
- invalid usage value
- general parsing failure
Note that transactions from a single batch are reported only if all of them are valid. If there is an error in processing of at least one of them, none is reported.
Note that a batch can only report transactions to the same service, service_id is at the same level that provider_key. Multiple report calls will have to be issued to report transactions to different services.
Example Request
POST /transactions.xml HTTP/1.1
Host: su1.3scale.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 428
transactions[0][app_id]=app_id&
transactions[0][usage][hits]=1&
transactions[0][usage][transfer]=4500&
transactions[0][timestamp]=2009-01-01%2014%3A23%3A08&
transactions[1][app_id]=app_id&
transactions[1][usage][hits]=1&
transactions[1][usage][transfer]=2840&
transactions[1][timestamp]=2009-01-01%2018%3A11%3A59&
provider_key=pkey
Example Request with Service id
A batch can only report transactions to the same service, service_id has to be
POST /transactions.xml HTTP/1.1
Host: su1.3scale.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 428
transactions[0][app_id]=app_id&
transactions[0][usage][hits]=1&
transactions[0][usage][transfer]=4500&
transactions[0][timestamp]=2009-01-01%2014%3A23%3A08&
transactions[1][app_id]=app_id&
transactions[1][usage][hits]=1&
transactions[1][usage][transfer]=2840&
transactions[1][timestamp]=2009-01-01%2018%3A11%3A59&
provider_key=pkey&
service_id=78910
Example Request with log
The transactions contain the requests/response/code of the API in log. These will be logged and can be retrieved on the admin and buyer portal.
POST /transactions.xml HTTP/1.1
Host: su1.3scale.net
Content-Type: application/x-www-form-urlencoded
transactions[0][app_id]=app_id&
transactions[0][usage][hits]=1&
transactions[0][usage][transfer]=4500&
transactions[0][timestamp]=2009-01-01%2014%3A23%3A08&
transactions[0][log][request]=%2Fmethod1.xml%3Fkey%3DXXX%26id%3DYYYY%26usage%5Bbla%5D%3D1 &
transactions[0][log][response]=%3C%3Fxml+version%3D%221.0%22+encoding%3D%22UTF-8%22%3F%3E%3Cerror+code%3D%22key_invalid%22%3Ekey+%22XXX%22+is+invalid%3C%2F&
transactions[0][log][code]=200&
09-01-01%2018%3A11%3A59&
provider_key=pkey&
service_id=78910
Appendix: Log requests detail
To enable the API log requests the provider has to send the information on what needs to be reported
on their calls to the Service Management API.
Every log entry contains
- request
- Required. The API request to the provider sent by the user
- response
- Optional. the API response generated by the provider to be sent to the user
- code
- Optional. Additional string to denote supplementary information, could be the http_status_code or other semantically relevant string like success or failure
All the strings need to be url encoded, for instance, blank spaces need to be replaced by "+" or by "%20", etc.
Additionally there is a cap to the length of the log data:
MAX_LEN_REQUEST = 1024 bytes
MAX_LEN_RESPONSE = 4096 bytes
MAX_LEN_CODE = 32 bytes
Appendix (II): Encoding complex data structures in URLs
The usual way to encode a complex data structure (array, associative array, nested structures) is to "flatten" it.
For example, having this structure:
{
"0": {
"app_id": "app_id",
"usage": {"hits": 1, "transfer": 4500},
"timestamp": "2009-01-01 14:23:08"},
"1": {
"app_id": "app_id",
"usage": {"hits": 1, "transfer": 2840},
"timestamp": "2009-01-01 18:11:59"}}
It has to be encoded like this:
transactions[0][app_id]=app_id&
transactions[0][usage][hits]=1&
transactions[0][usage][transfer]=4500&
transactions[0][timestamp]=2009-01-01%2014%3A23%3A08&
transactions[1][app_id]=app_id&
transactions[1][usage][hits]=1&
transactions[1][usage][transfer]=2840&
transactions[1][timestamp]=2009-01-01%2018%3A11%3A59
(note that spaces are encoded as %20
and colons as %3A
according to URL encoding rules)