3scale/apisonator

View on GitHub
docs/api.html

Summary

Maintainability
Test Coverage
API version 2.0 (the documentation for the previous version is <a href="/support/api-service-management-v1-1/">here</a>).

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.

<h3>Documentation</h3>

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.

<h3>Definitions</h3>

<dl>
  <dt>service</dt>
  <dd>any web service implementing an API</dd>

  <dt>provider</dt>
  <dd>an organization, company or individual providing a service</dd>

  <dt>application</dt>
  <dd>a consumer endpoint of a web service (website, embeddable widget, desktop program, mobile application, HTTP enabled microwave oven, ...)</dd>

  <dt>transaction</dt>
  <dd>Single unit of interaction between an application and a service. In case of HTTP-base web services, this is usually one request-response exchange.</dd>

  <dt>resource</dt>
  <dd>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.</dd>

  <dt>metric</dt>
  <dd>A way to measure a resource. For example: number of API hits, amount of disk space in megabytes, CPU time in milliseconds, ...</dd>

  <dt>provider key</dt>
  <dd>Unique textual identifier of a provider.</dd>

  <dt>application id</dt>
  <dd>Public unique textual identifier of an application.</dd>

  <dt>application key</dt>
  <dd>Secret key for authenticating transactions.</dd>
</dl>

<h3>Operations</h3>

The API exposes a simple REST-based interface that provides these operations: <strong>authorize</strong>, and <strong>report</strong>.

<h4>Authorize</h4>

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.

<code class="http"><pre>GET /transactions/authorize.xml?app_id={app_id}&amp;provider_key={provider_key}[&amp;app_key={app_key}]</pre></code>

<h5>Parameters</h5>

<dl>
  <dt><var>provider_key</var></dt> <dd>Provider key. Required.</dd>
  <dt><var>service_id</var></dt> <dd>Service id. Required only if as a provider you have multiple services allowed and enabled.</dd>
  <dt><var>app_id</var></dt> <dd>Application id. Required.</dd>
  <dt><var>app_key</var></dt> <dd>Application key. Required only if it is defined for the application.</dd>
  <dt><var>referrer</var></dt> <dd>Referrer IP Address or Domain. Required if referrer filtering is enabled. If special value "*" (start) is passed, the referrer check is bypassed.</dd>
  <dt><var>usage</var></dt> <dd>Predicted usage. Optional</dd>
</dl>

<h5>Predicted usage</h5>

It's possible to pass a "predicted usage" to the authorize call. This can serve two purposes:

<ol>
  <li>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 <var>usage</var> parameter, authorize only checks the usage that has already been reported. If the <var>usage</var> parameter is passes in, it will check whether the already reported usage + the passed in predicted usage is still within limit.</li>

  <li>To limit the authorization only to a subset of metrics. If <var>usage</var> is passed in, only the metrics listed in it will be checked against the limits. For example: There are two metrics defined: <var>searches</var> and <var>updates</var>. <var>updates</var> are already over limit, but <var>searches</var> 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 <code>usage[searches]=1</code> to the authorize call.</li>
</ol>

<p>NOTE: Even if the predicted usage is passed in, authorize is still a read-only operation. You have to make the <strong>report</strong> call to report the usage.

<p>NOTE: <var>usage</var> is an associative array of the form <code>{metric : value}</code>. Please reefer to the "Encoding complex data structures in URLs" appendix for more info.

<p>NOTE: <var>usage</var> 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, <code>usage[hits]=1</code> will increment the hits counter by <code>+1</code>, whereas <code>usage[hits]=#1</code> will set the hits counters to <code>1</code>.

<p>Setting the value of a counter with the prefix '#' to wherever the <var>usage</var> 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: <code>usage[hits]=#1</code>, <code>usage[hits]=#10</code> it is not possible to determine the final value of <var>hits</var>, 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 <code>usage[hits]=1</code> and <code>usage[hits]=10</code>, the final value of <var>hits</var> would have been incremented by <var>11</var>.

<p>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 <var>views</var> and <var>save</var> are methods of the metric <var>hits</var>, thus <var>views</var> and <var>save</var> are children of <var>hits</var>. In this case, if we do <code>usage[save]=1</code> and <code>usage[views]=3</code>, the value of <var>views</var> will be increased by 3, the value of <var>save</var> will be increased by 1 and the value of <var>hits</var> will be implicitly increased by 4 (3+1). On the other hand, doing a <code>usage[save]=#1</code> and <code>usage[views]=#3</code> will set the value of <var>views</var> to 3, the value of <var>save</var> will be set to 1, but the value of <var>hits</var> will be set to either 3 or 1 depending which method was processed last.






<h5>Successful Response</h5>

Has status code <code class="http">200 OK</code> (if authorization is granted), <code class="http">409</code> (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

<code class="xml">
<pre>&lt;status&gt;
  &lt;authorized&gt;true&lt;/authorized&gt;
  &lt;plan&gt;Pro&lt;/plan&gt;

  &lt;usage_reports&gt;
    &lt;usage_report metric="hits" period="month"&gt;
      &lt;period_start&gt;2010-08-01 00:00:00 +00:00&lt;/period_start&gt;
      &lt;period_end&gt;2010-09-01 00:00:00 +00:00&lt;/period_end&gt;
      &lt;current_value&gt;17344&lt;/current_value&gt;
      &lt;max_value&gt;20000&lt;/max_value&gt;
    &lt;/usage_report&gt;

    &lt;usage_report metric="hits" period="day"&gt;
      &lt;period_start&gt;2010-08-04 00:00:00 +00:00&lt;/period_start&gt;
      &lt;period_end&gt;2010-08-05 00:00:00 +00:00&lt;/period_end&gt;
      &lt;current_value&gt;732&lt;/current_value&gt;
      &lt;max_value&gt;1000&lt;/max_value&gt;
    &lt;/usage_report&gt;
  &lt;/usage_reports/&gt;
&lt;/status&gt;</pre></code>

Example of failed authorize response (exceeded limits)

<code class="xml">
<pre>&lt;status&gt;
  &lt;authorized&gt;false&lt;/authorized&gt;
  &lt;reason&gt;Usage limits are exceeded&lt;/reason&gt;
  &lt;plan&gt;Pro&lt;/plan&gt;

  &lt;usage_reports&gt;
    &lt;usage_report metric="hits" period="month"&gt;
      &lt;period_start&gt;2010-08-01 00:00:00 +00:00&lt;/period_start&gt;
      &lt;period_end&gt;2010-09-01 00:00:00 +00:00&lt;/period_end&gt;
      &lt;current_value&gt;17344&lt;/current_value&gt;
      &lt;max_value&gt;20000&lt;/max_value&gt;
    &lt;/usage_report&gt;

    &lt;usage_report metric="hits" period="day" exceeded="true"&gt;
      &lt;period_start&gt;2010-08-04 00:00:00 +00:00&lt;/period_start&gt;
      &lt;period_end&gt;2010-08-05 00:00:00 +00:00&lt;/period_end&gt;
      &lt;current_value&gt;1042&lt;/current_value&gt;
      &lt;max_value&gt;1000&lt;/max_value&gt;
    &lt;/usage_report&gt;
  &lt;/usage_reports/&gt;
&lt;/status&gt;</pre>
</code>

Explanation of the elements

<dl>
  <dt><var>status</var></dt>
  <dd>Root element of the response.</dd>

  <dt><var>authorized</var></dt>
  <dd>Contains text "true" if the authorization was successful, or "false" if it failed.</dd>

  <dt><var>reason</var></dt>
  <dd>Human readable textual description of failure reason. This element appears only if <var>authorize</var> is false.</dd>

  <dt><var>plan</var></dt>
  <dd>Name of the plan the user is signed up to.</dd>

  <dt><var>usage_reports</var></dt>
  <dd>Contains list of <var>usage_report</var> elements - one per each usage limit defined for the plan the user is signed up to.</dd>

  <dt><var>usage_report</var></dt>
  <dd>Contains information about usage status. Contains these elements: <var>period_start</var>, <var>period_end</var>, <var>current_value</var> and <var>max_value</var>. Has attributes <var>metric</var> with the name of the metric the limit applies to, <var>period</var>, which is the period of the limit (year, month, week, day, hour, minute) and optionally <var>exceeded</var> which is set to "true" if the limit is exceeded in the current period.</dd>

  <dt><var>period_start</var></dt>
  <dd>Start of the limit period. It's in the form <samp>YYYY-MM-DD HH:MM:SS +ZZ:ZZ</samp>. <samp>+ZZ:ZZ</samp> (or <samp>-ZZ:ZZ</samp>) is a time offset (in hours and minutes) from UTC.</dd>

  <dt><var>period_end</var></dt>
  <dd>End of the limit period. Same format as <var>period_start</var></dd>

  <dt><var>current_value</var></dt>
  <dd>Value of the corresponding metric accumulated so far in the current period.</dd>

  <dt><var>max_value</var></dt>
  <dd>Maximum value allowed by the usage limit.</dd>
</dl>

<h5>Errors</h5>

In case of error, the response body contains an XML-formatted object with a single element <var>error</var>. This element has one attribute <var>code</var> 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:

<dl>
  <dt><var>provider_key_invalid</var></dt>
  <dd>Provider key is not valid</dd>

  <dt><var>application_not_found</var></dt>
  <dd>Application with the given id does not exist.</dd>
</dl>

This is an example of an error response:

<code class="xml">
<pre>&lt;?xml version="1.0" encoding="utf-8" ?&gt;
&lt;error code="application_not_found"&gt;Application with id="12345678" was not found&lt;/error&gt;</pre>
</code>

<h5>Example Request</h5>

<code class="http"><pre>
GET /transactions/authorize.xml?app_id=709deaac&amp;provider_key=pkey&amp;app_key=app_key HTTP/1.1

Host: su1.3scale.net</pre></code>

<h5>Example Request with referrer</h5>

<code class="http"><pre>
GET /transactions/authorize.xml?app_id=709deaac&amp;provider_key=pkey&amp;app_key=app_key&amp;referrer=example.org HTTP/1.1

Host: su1.3scale.net</pre></code>

<h5>Example Request with usage</h5>

<code class="http"><pre>
GET /transactions/authorize.xml?app_id=709deaac&amp;provider_key=pkey&amp;app_key=app_key&amp;usage[hits]=1&amp;usage[transfer]=1024 HTTP/1.1

Host: su1.3scale.net</pre></code>

<h5>Example Request with usage and service_id</h5>

<code class="http"><pre>
GET /transactions/authorize.xml?service_id=7812315&amp;app_id=709deaac&amp;provider_key=pkey&amp;app_key=app_key&amp;usage[hits]=1&amp;usage[transfer]=1024 HTTP/1.1

Host: su1.3scale.net</pre></code>

<h4>OAuth Authorize</h4>

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.

<code class="http"><pre>GET /transactions/oauth_authorize.xml?app_id={app_id}&amp;provider_key={provider_key}[&amp;app_key={app_key}]</pre></code>

<h5>Parameters</h5>

<dl>
  <dt><var>provider_key</var></dt> <dd>Provider key. Required.</dd>
  <dt><var>service_id</var></dt> <dd>Service id. Required only if as a provider you have multiple services allowed and enabled.</dd>
  <dt><var>app_id</var></dt> <dd>Application id. Required.</dd>
  <dt><var>app_key</var></dt> <dd>Application key. Optionl. Will be validated if sent.</dd>
  <dt><var>referrer</var></dt> <dd>Referrer IP Address or Domain. Required if referrer filtering is enabled. If special value "*" (start) is passed, the referrer check is bypassed.</dd>
  <dt><var>usage</var></dt> <dd>Predicted usage. Optional</dd>
  <dt><var>redirect_url</var></dt> <dd>Redirect URL for OAuth. Optional. Will be validated if sent.</dd>
</dl>

<h5>Successful Response</h5>

Has status code <code class="http">200 OK</code> (if authorization is granted), <code class="http">409</code> (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

<code class="xml">
<pre>&lt;status&gt;
  &lt;authorized&gt;true&lt;/authorized&gt;
  &lt;plan&gt;Pro&lt;/plan&gt;

  &lt;application&gt;
    &lt;id&gt;57c53c8a&lt;/id&gt;
    &lt;key&gt;433dbee8b34524326a2b4a3c126ec5c3&lt;/key&gt;
    &lt;redirect_url&gt;http://www.example.com/redirect_url&lt;/redirect_url&gt;
  &lt;/application&gt;

  &lt;usage_reports&gt;
    &lt;usage_report metric="hits" period="month"&gt;
      &lt;period_start&gt;2010-08-01 00:00:00 +00:00&lt;/period_start&gt;
      &lt;period_end&gt;2010-09-01 00:00:00 +00:00&lt;/period_end&gt;
      &lt;current_value&gt;17344&lt;/current_value&gt;
      &lt;max_value&gt;20000&lt;/max_value&gt;
    &lt;/usage_report&gt;

    &lt;usage_report metric="hits" period="day"&gt;
      &lt;period_start&gt;2010-08-04 00:00:00 +00:00&lt;/period_start&gt;
      &lt;period_end&gt;2010-08-05 00:00:00 +00:00&lt;/period_end&gt;
      &lt;current_value&gt;732&lt;/current_value&gt;
      &lt;max_value&gt;1000&lt;/max_value&gt;
    &lt;/usage_report&gt;
  &lt;/usage_reports/&gt;
&lt;/status&gt;</pre></code>

Example of failed authorize response (exceeded limits)

<code class="xml">
<pre>&lt;status&gt;
  &lt;authorized&gt;false&lt;/authorized&gt;
  &lt;reason&gt;Usage limits are exceeded&lt;/reason&gt;
  &lt;plan&gt;Pro&lt;/plan&gt;

  &lt;application&gt;
    &lt;id&gt;57c53c8a&lt;/id&gt;
    &lt;key&gt;433dbee8b34524326a2b4a3c126ec5c3&lt;/key&gt;
    &lt;redirect_url&gt;http://www.example.com/redirect_url&lt;/redirect_url&gt;
  &lt;/application&gt;

  &lt;usage_reports&gt;
    &lt;usage_report metric="hits" period="month"&gt;
      &lt;period_start&gt;2010-08-01 00:00:00 +00:00&lt;/period_start&gt;
      &lt;period_end&gt;2010-09-01 00:00:00 +00:00&lt;/period_end&gt;
      &lt;current_value&gt;17344&lt;/current_value&gt;
      &lt;max_value&gt;20000&lt;/max_value&gt;
    &lt;/usage_report&gt;

    &lt;usage_report metric="hits" period="day" exceeded="true"&gt;
      &lt;period_start&gt;2010-08-04 00:00:00 +00:00&lt;/period_start&gt;
      &lt;period_end&gt;2010-08-05 00:00:00 +00:00&lt;/period_end&gt;
      &lt;current_value&gt;1042&lt;/current_value&gt;
      &lt;max_value&gt;1000&lt;/max_value&gt;
    &lt;/usage_report&gt;
  &lt;/usage_reports/&gt;
&lt;/status&gt;</pre>
</code>

Explanation of the elements

<dl>
  <dt><var>status</var></dt>
  <dd>Root element of the response.</dd>

  <dt><var>authorized</var></dt>
  <dd>Contains text "true" if the authorization was successful, or "false" if it failed.</dd>

  <dt><var>reason</var></dt>
  <dd>Human readable textual description of failure reason. This element appears only if <var>authorize</var> is false.</dd>

  <dt><var>plan</var></dt>
  <dd>Name of the plan the user is signed up to.</dd>

  <dt><var>application</var></dt>
  <dd>Parent element that holds the application details.</dd>

  <dt><var>id</var></dt>
  <dd>ID of the application. Matches the sent app_id.</dd>

  <dt><var>key</var></dt>
  <dd>Key of the application. You should use this as your OAuth v1.0a secret or OAuth v2.0 key.</dd>

  <dt><var>redirect_url</var></dt>
  <dd>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.</dd>

  <dt><var>usage_reports</var></dt>
  <dd>Contains list of <var>usage_report</var> elements - one per each usage limit defined for the plan the user is signed up to.</dd>

  <dt><var>usage_report</var></dt>
  <dd>Contains information about usage status. Contains these elements: <var>period_start</var>, <var>period_end</var>, <var>current_value</var> and <var>max_value</var>. Has attributes <var>metric</var> with the name of the metric the limit applies to, <var>period</var>, which is the period of the limit (year, month, week, day, hour, minute) and optionally <var>exceeded</var> which is set to "true" if the limit is exceeded in the current period.</dd>

  <dt><var>period_start</var></dt>
  <dd>Start of the limit period. It's in the form <samp>YYYY-MM-DD HH:MM:SS +ZZ:ZZ</samp>. <samp>+ZZ:ZZ</samp> (or <samp>-ZZ:ZZ</samp>) is a time offset (in hours and minutes) from UTC.</dd>

  <dt><var>period_end</var></dt>
  <dd>End of the limit period. Same format as <var>period_start</var></dd>

  <dt><var>current_value</var></dt>
  <dd>Value of the corresponding metric accumulated so far in the current period.</dd>

  <dt><var>max_value</var></dt>
  <dd>Maximum value allowed by the usage limit.</dd>
</dl>

<h5>Errors</h5>

In case of error, the response body contains an XML-formatted object with a single element <var>error</var>. This element has one attribute <var>code</var> 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:

<dl>
  <dt><var>provider_key_invalid</var></dt>
  <dd>Provider key is not valid</dd>

  <dt><var>application_not_found</var></dt>
  <dd>Application with the given id does not exist.</dd>
</dl>

This is an example of an error response:

<code class="xml">
<pre>&lt;?xml version="1.0" encoding="utf-8" ?&gt;
&lt;error code="application_not_found"&gt;Application with id="12345678" was not found&lt;/error&gt;</pre>
</code>

<h5>Example Request</h5>

<code class="http"><pre>
GET /transactions/oauth_authorize.xml?app_id=709deaac&amp;provider_key=pkey&amp;app_key=app_key HTTP/1.1

Host: su1.3scale.net</pre></code>

<h4>Authrep</h4>

"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.

<code class="http"><pre>GET /transactions/authrep.xml?app_id={app_id}&amp;provider_key={provider_key}[&amp;app_key={app_key}]&amp;usage[hits]=1</pre></code>

<h5>Parameters</h5>

<dl>
  <dt><var>provider_key</var></dt> <dd>Provider key. Required.</dd>
  <dt><var>service_id</var></dt> <dd>Service id. Required only if as a provider you have multiple services allowed and enabled.</dd>
  <dt><var>app_id</var></dt> <dd>Application id. Required.</dd>
  <dt><var>app_key</var></dt> <dd>Application key. Required only if it is defined for the application.</dd>
  <dt><var>referrer</var></dt> <dd>Referrer IP Address or Domain. Required if referrer filtering is enabled. If special value "*" (start) is passed, the referrer check is bypassed.</dd>
  <dt><var>usage</var></dt> <dd>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.</dd>
  <dt><var>log</var></dt> <dd>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.</dd>
</dl>

<h5>Usage</h5>

The usage parameters should be passed along in order to report traffic.

<ol>
  <li>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.</li>

  <li>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.</li>
</ol>

NOTE: <var>usage</var> is an associative array of the form <code>{metric : value}</code>. Please refer to the "Encoding complex data structures in URLs" appendix for more info.

<h5>Log</h5>

The log parameters should be passed along in order to keep a log of your API requests.

<ol>
  <li>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. </li>

  <li>In addition, <var>log</var> is an associative array of the form <code>{request : value, response : value, code : value}</code>. Please refer to the "Encoding complex data structures in URLs" appendix for more info. </li>

  <li>The <var>request</var> in <var>log</var> is required whereas the rest are optional and can be left blank. Additionally, the <var>values</var> for <var>log</var> they have to be url-encoded.</li>
</ol>

<h5>Example Request with usage</h5>

<code class="http"><pre>
GET /transactions/authrep.xml?app_id=709deaac&amp;provider_key=pkey&amp;app_key=app_key&amp;usage[hits]=1&amp;usage[storage]=500 HTTP/1.1

Host: su1.3scale.net</pre></code>


<h5>Example Request with logs</h5>

<code class="http"><pre>
GET /transactions/authrep.xml?app_id=709deaac&amp;provider_key=pkey&amp;app_key=app_key&amp;usage[hits]=1&amp;usage[storage]=500&amp;log[request]=%2Fmethod1.xml%3Fkey%3DXXX%26id%3DYYYY%26usage%5Bbla%5D%3D1&amp;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&amp; log[code]=200&amp; HTTP/1.1

Host: su1.3scale.net</pre></code>


<h5>Successful Response</h5>

Has status code <code class="http">200 OK</code> (if authorization is granted - and therefore reported), <code class="http">409</code> (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.

<h4>Report</h4>

This operation is used to report 3scale system about transactions. Any number of transactions can be reported in one request.

<code class="http">POST /transactions.xml</code>

<h5>Parameters</h5>

<dl>
  <dt><var>transactions</var></dt>
  <dd>List of parameters for each transaction in the batch. More details are explained below. Required.</dd>

  <dt><var>provider_key</var></dt>
  <dd>Provider key. Required.</dd>
  <dt><var>service_id</var></dt>
  <dd>Service id. Required only if as a provider you have multiple services allowed and enabled.</dd>
</dl>

<h6>The structure of the transactions parameter</h6>

The <em>transactions</em> should contain numerically indexed list of records, one for each transaction. Each record can contain these parameters:

<dl>
  <dt><var>app_id</var></dt>
  <dd>Application ID. Required.</dd>

  <dt><var>usage</var></dt>
  <dd>Usage data of the transaction. This should be associative array (a hash) of the form: <code>{metric =&gt; value, ...}</code>, 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.</dd>

  <dt><var>timestamp</var></dt>
  <dd>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: <code>YYYY-MM-DD HH:MM:SS</code>
for example <code>2009-01-01 17:45:02</code>. In the second case, the format has to be <code>YYYY-MM-DD HH:MM:SS +HH:MM</code> or <code>YYYY-MM-DD HH:MM:SS -HH:MM</code>, where the <code>+HH:MM</code>
(or <code>-HH:MM</code>) 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: <code>2009-01-01 22:15:31 -08:00</code>. Optional. If not specified, the time when the transaction was received is used.</dd>

  <dt><var>log</var></dt>
  <dd>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, <var>log</var> is an associative array of the form <code>{request : value, response : value, code : value}</code>. Please refer to the "Encoding complex data structures in URLs" appendix for more info. The <var>request</var> in <var>log</var> is required whereas the rest are optional and can be left blank. Additionally, the <var>values</var> for <var>log</var> they have to be url-encoded.</dd>


</dl>

These parameters have to be encoded in <span class="caps">HTTP</span> <span class="caps">POST</span> request using the <code>application/x-www-form-urlencoded</code> media type. Please reefer to the "Encoding complex data structures in URLs" appendix for more info.

<h5>Successful Response</h5>

Has status code <code class="http">202 Accepted</code> and no response body

<h5>Errors</h5>

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:

<h6>Errors detected during request processing</h6>

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 <code class="http">403 Forbidden</code> and the body contains XML document with description of the error. Example:

<code class="xml">
<pre>&lt;?xml version="1.0" encoding="utf-8" ?&gt;
&lt;error code="provider_key_invalid"&gt;Provider key "abcd1234" is invalid&lt;/error&gt;</pre>
</code>

<h6>Errors detected during offline processing</h6>

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:

<ul>
    <li>invalid application id</li>
    <li>invalid metric</li>
    <li>invalid usage value</li>
    <li>general parsing failure</li>
</ul>

Note that transactions from a single batch are reported only if <strong>all of them are valid</strong>. If there is an error in processing of at least one of them, <strong>none is reported</strong>.

Note that a batch can only report transactions to the same service, <var>service_id</var> is at the same level that <var>provider_key</var>. Multiple <em>report</em> calls will have to be issued to report transactions to different services.


<h5>Example Request</h5>

<code class="http">
<pre>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&amp;
transactions[0][usage][hits]=1&amp;
transactions[0][usage][transfer]=4500&amp;
transactions[0][timestamp]=2009-01-01%2014%3A23%3A08&amp;
transactions[1][app_id]=app_id&amp;
transactions[1][usage][hits]=1&amp;
transactions[1][usage][transfer]=2840&amp;
transactions[1][timestamp]=2009-01-01%2018%3A11%3A59&amp;
provider_key=pkey</pre>
</code>

<h5>Example Request with Service id</h5>

A batch can only report transactions to the same service, <var>service_id</var> has to be

<code class="http">
<pre>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&amp;
transactions[0][usage][hits]=1&amp;
transactions[0][usage][transfer]=4500&amp;
transactions[0][timestamp]=2009-01-01%2014%3A23%3A08&amp;
transactions[1][app_id]=app_id&amp;
transactions[1][usage][hits]=1&amp;
transactions[1][usage][transfer]=2840&amp;
transactions[1][timestamp]=2009-01-01%2018%3A11%3A59&amp;
provider_key=pkey&amp;
service_id=78910
</pre>
</code>

<h5>Example Request with log</h5>

The transactions contain the requests/response/code of the API in <var>log</var>. These will be logged and can be retrieved on the admin and buyer portal.

<code class="http">
<pre>POST /transactions.xml HTTP/1.1
Host: su1.3scale.net
Content-Type: application/x-www-form-urlencoded

transactions[0][app_id]=app_id&amp;
transactions[0][usage][hits]=1&amp;
transactions[0][usage][transfer]=4500&amp;
transactions[0][timestamp]=2009-01-01%2014%3A23%3A08&amp;
transactions[0][log][request]=%2Fmethod1.xml%3Fkey%3DXXX%26id%3DYYYY%26usage%5Bbla%5D%3D1 &amp;
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&amp;
transactions[0][log][code]=200&amp;
09-01-01%2018%3A11%3A59&amp;
provider_key=pkey&amp;
service_id=78910
</pre>
</code>

<h3>Appendix: Log requests detail</h3>

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

<dl>
  <dt><var>request</var></dt> <dd>Required. The API request to the provider sent by the user</dd>
  <dt><var>response</var></dt> <dd>Optional. the API response generated by the provider to be sent to the user</dd>
  <dt><var>code</var></dt> <dd>Optional. Additional string to denote supplementary information, could be the http_status_code or other semantically relevant string like <em>success</em> or <em>failure</em></dd>
</dl>

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:

<code>
<li>MAX_LEN_REQUEST = 1024 bytes</li>
<li>MAX_LEN_RESPONSE = 4096 bytes</li>
<li>MAX_LEN_CODE = 32 bytes</li>
</code>

<h3>Appendix (II): Encoding complex data structures in URLs</h3>

The usual way to encode a complex data structure (array, associative array, nested structures) is to "flatten" it.

For example, having this structure:

<code class="javascript">
<pre>{
  "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"}}</pre>
</code>

It has to be encoded like this:

<code class="http">
<pre>transactions[0][app_id]=app_id&amp;
transactions[0][usage][hits]=1&amp;
transactions[0][usage][transfer]=4500&amp;
transactions[0][timestamp]=2009-01-01%2014%3A23%3A08&amp;
transactions[1][app_id]=app_id&amp;
transactions[1][usage][hits]=1&amp;
transactions[1][usage][transfer]=2840&amp;
transactions[1][timestamp]=2009-01-01%2018%3A11%3A59</pre>
</code>

(note that spaces are encoded as <code>%20</code> and colons as <code>%3A</code> according to URL encoding rules)