Hello Developers.

Introduction

Welcome to our RESTful API. Here you'll find reference documentation, guides and tutorials to help you start integrating our domestic shipping platform into your app or website as quickly as possible. We can't wait to see what you build!

Changes

This is a versionless API. Advance notification of breaking changes will be available in this document and will be sent by email to our developer mailing list.

Feedback & Issues


If you believe you have found a bug, or you'd like to request additional functionality (no guarantees), or you release something using this API, we'd love to hear from you: support@universalpackagesys.com

Sorry, but we are unable to answer basic HTTP programming questions with this API.

Please make sure you are properly encoding the parameters. If you are having issues with credentials failing that you know are valid, this is very likely to be the issue. If you are crafting your GET query-string or POST request-body manually, you need to URL-encode the values.

Going live


Once you’re ready to go live, please contact us so that we can set up billing and give you your live API key.

Root Endpoint


You can issue a GET request to the root endpoint to get all the endpoint categories of the API that your account has permission to access:

GET http://domestic.universalpackagesys.com/Test.DSS/v2 

Response formats


The Envelope

All responses to requests to the API endpoints, whether successful or not, will be returned in the same type of envelope structure. That is, each response has a predictable set of keys with which you can expect to interact. The following describes how that envelope works and what it may contain.

Sample Response Envelope
{
    "meta": {
        "code": 200,
        "message": null,
        "type": null
    },
    "data": {
        ...
    }
}
META

The meta key is used to communicate extra information about the response to the developer. This object will always contain code, a copy of the HTTP status code that has been returned. If all goes well, you'll only ever see the code key with value 200. However, sometimes things go wrong, and in that case you might see a response like:

{
    "meta": {
        "code": 400,
        "type": "BadRequest",
        "message": "..."
    }
}
DATA

The data key is the meat of the response. It may be either be an object itself or a list of objects, but either way this is where you'll find the data you requested. The particular data returned is described in each endpoint’s documentation.

Unset fields will be represented as a null instead of being omitted.

Pretty-printed JSON


We return a minified form of JSON by default, but support pretty-printing of JSON for debugging and enhanced readability.

To request pretty-printing, provide the following query parameter with your request:

?pretty=true

Set it to false or omit the parameter entirely if you wish to receive minified JSON.

Rate Limiting


Rate limiting is by default, 100 requests per minute. All responses will include X-RateLimit-* headers containing your current rate limit status.

...
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 99
X-RateLimit-Reset: 1372700873
...
Header Description
X-RateLimit-Limit Total number of allowed requests in the current period.
X-RateLimit-Remaining The number of remaining requests in the current period.
X-RateLimit-Reset UNIX timestamp of when the current period will reset.

HTTP responses will return a 429 Too Many Requests status code for any request until the rate limit has dropped below the required threshold. In this situation, your application should not send any further requests until X-Rate-Limit-Reset timestamp have elapsed.

If you need the reset timestamp in a different format, any modern programming language can get the job done. For example, if you open up the console on your web browser, you can easily get the reset time as a JavaScript Date object.

new Date(1372700873 * 1000)
// => Mon Jul 01 2013 13:47:53 GMT-0400 (EDT)

If you have need for a higher rate limit, please get in touch so that we can try and help out.

Authentication


All endpoints of this API require authentication. Unauthorized requests will return 404 Not Found, instead of 403 Forbidden or 401 Unauthorized. This is to prevent the accidental leakage of private information to unauthorized users.

Creating an access token

Authenticated requests require an access_token. These tokens are unique to a verified account and should be stored securely. Access tokens may expire at any time in the future.

A typical request to the tokens endpoint looks like this:

POST http://domestic.universalpackagesys.com/Test.DSS/v2/tokens
Content-Type: application/json

{
    "grant_type": "client_id",
    "client_id": "{client_id}"
}

where {client_id} should be replaced with the client identifier associated with your profile.

Response

On success, the response from the service has the status code 200 OK in the response header, and JSON data in the response body:

200 OK
Content-Type: application/json;charset=UTF-8

{
    "meta": {
        "code": 200
    },
    "data": {
        "access_token": "NgCXRK...MzYjw",
        "token_type": "Bearer",
        "expires_at": 1372700873,
        "refresh_token": "NgAagA...Um_SHo"
    }
}

Using the access token to make authenticated requests

Now that you have a bearer token, you can make authenticated requests to the API. This is done by either setting the HTTP Authorization header or query string in the request.

in a header
Authorization: Bearer NgCXRK...MzYjw
as a parameter
GET http://domestic.universalpackagesys.com/Test.DSS/v2/endpoint?access_token=NgCXRK...MzYjw

Requesting a new access token from refresh token

Access tokens are deliberately set to expire after a short time, after which new tokens may be granted by supplying the refresh token originally obtained during the authentication process.

The request is sent to the tokens endpoint like this:

POST http://domestic.universalpackagesys.com/Test.DSS/v2/tokens
Content-Type: application/json

{
    "grant_type": "refresh_token",
    "refresh_token": "{refresh_token}"
}

where {refresh_token} should be replaced with the refresh token attained from a previous authentication.

Response
200 OK
Content-Type: application/json;charset=UTF-8

{
    "meta": {
        "code": 200
    },
    "data": {
        "access_token": "NgCXRK...MzYjw",
        "token_type": "Bearer",
        "expires_at": 1372700873,
        "refresh_token": "NgAagA...Um_SHo"
    }
}

Note: refresh tokens cannot be reused once redeemed for a new access token