Getting Started

The API is available at https://api.parkwhiz.com/v4. A sandbox API is available at http://api.sandbox.parkwhiz.com/v4.

Full documentation is available at http://developer.arrive.com/v4/

Please contact dev@arrive.com with any questions or concerns.

Introduction


ParkWhiz offers a free API that allows anyone to add parking locations, pricing, and availability data to their website or application.

The purpose of this guide is to help you gain access to the API. The requesting of client credentials, passwords, authorization codes, and refresh tokens will be discussed. We will talk about how ParkWhiz uses scopes to establish a level of access control. Finally, we will talk about how you can use Zooms to return multiple resources from a single request.

Authentication


To authenticate with the API, you must use an OAuth2 access token as an authorization header: Authorization Bearer ACCESS_TOKEN.

The request is made using the POST method to the oauth/token endpoint using the grant_type parameter.

The type of token that you request (Grant Type) and the Scope requested will determine what resources you have access to with that specific token. Some tokens are not suitable for public use, as the data they return contains sensitive client information. Please take care to choose the correct grant_type for your use case to protect your credentials.

When making the request, there are several ways to specify the requested data. Query parameters are used in the below examples. Please refer to the full documentation for all options when making authentication requests.

Grant Types


When requesting an access token one of four grant types can be requested: client_credentials, password, authorization_code, refresh_token

Grant Flow Types

The type of token grant flow you use should depend on the type of data you require from the API. The table below provides you with use cases about which grant flow to use.

Grant Flow Name grant_type parameter value Use Case
[The client credential flow] grant_type=client_credentials Used by an app or trusted partner when user specific information doesn't need to be retrieved. This is most appropriate for requests not associated with user data like GET /quotes. To access or modify user data (e.g. GET /bookings, GET /accounts/me) you must use a password grant or authorization code grant.
[The password grant type] grant_type=password Used when user information is known and the client credentials need to be concealed, such as in a client-side web application, and specific user information needs to be accessed or modified.
[The authorization code] grant_type=authorization_code Used by an app or a trusted partner when they need to access or modify user specific information on behalf of a user but do not have access to the user's information to use a password grant.
[The refresh token] grant_type=refresh_token Used to refresh a token to prevent expiry. Cannot be used to regenerate a token generated from the client credentials flow.


Client Credentials

grant_type=client_credentials is meant to be used by an app or trusted partner when access to user data is not required. An access token granted via client_credentials cannot view or modify user specific data. For example, requests using this token will not be able to view a users bookings (e.g. GET /bookings/) or modify user data (e.g. POST /accounts/me/).

Obtaining a token is done by using grant_type=client_credentials in POST /oauth/token

Request:
POST /oauth/token?grant_type=client_credentials&client_id=ASSIGNED_CLIENT_ID_1234&client_secret=ASSIGNED_CLIENT_SECRET_1234&scope=public

Response:
{
    "access_token": "184abde730160226258fdf3d11ead7e1e3df3181c4517037a4084c4f7ffc829d",
    "token_type": "bearer",
    "expires_in": 31557600,
    "refresh_token": "faa5ec32eee8e6egaaa18ddab050925360cc264dc2cd19dcdb281e948038cdb1",
    "scope": "public",
    "created_at": 1499798701
}

In cases where you do not wish to provide the client secret (e.g. in a mobile app), you can obtain a public client credentials token by posting to the /oauth/public_token endpoint. This token will behave in much the same way a regular client credentials token does except it is limited to the mobile and public scopes. If the scope parameter is not explicitly set, public will be assumed. NOTE: your partner credentials will need permission in order to use this endpoint.


Password

grant_type=password is meant to be used when the client credentials need to be concealed (such as in a client-side web application), but specific user information needs to be accessed or modified. This should be used for things like listing a user's bookings GET /bookings/ or retrieving / modifying a users account information GET/POST /accounts/me).

Obtaining a token is done by using grant_type=password inPOST /oauth/token

Request:
POST oauth/token?grant_type=password&customer_email=user@domain.com&customer_password=my_super_secure_password123&scope=public

Response:
{
    "access_token": "a84823535f04030bdcbfcc713c2c4d84871d0f70d5214bc942f0d6eca7cdd09bb",
    "token_type": "bearer",
    "expires_in": 31557600,
    "scope": "public",
    "created_at": 1499797873
}

### Authorization Code **grant_type=authorization_code** is used by an app or a trusted partner when they need to access specific information on behalf of a user but do not have the appropriate user information to authenticate as that user using a password grant.

Obtaining a token is done by first making a request to retrieve an authorization code via POST /oauth/authorize using a response_type of code (response_type=code). You will need your client_id, client_secret, and redirect_uri. All three are used to verify your identity. All three can be supplied by ParkWhiz when setting up your access.

Request:
POST /oauth/authorize?response_type=code&customer_email=dev@arrive.com&redirect_uri=http://yoursite.com/oauth/auth_code&client_id=ASSIGNED_CLIENT_ID&client_secret=ASSIGNED_CLIENT_SECRET&scope=partner`

Response:
{
    "code": "0f80aec8b8b74b4880e680db9b0c6e5323418749000fb991989b9094e191332d"
}


Note that under normal circumstances the response will be redirected to the supplied redirect_uri containg the above authorization code as a query parameter. This authorization code is valid for 30 minutes.

You will then use this authorization code to retrieve an access token. Note that you will again supply the client_id, client_secret, and redirect_uri with a grant type of authorization_code (grant_type=authorization_code)

Request:
POST /oauth/token?grant_type=authorization_code&client_id=ASSIGNED_CLIENT_ID&client_secret=ASSIGNED_CLIENT_SECRET&redirect_uri=https://api.parkwhiz.com/v3/oauth/auth_code&code=0f80aec8b8b74b4880e680db9b0c6e5323418749000fb991989b9094e191332d&scope=partner

Response:
{
    "access_token": "0d3d2ffd611fa8dfc44f0c5173de5460693a044a79ca60cda0eb99c5bb407c23",
    "token_type": "bearer",
    "expires_in": 31557600,
    "refresh_token": "9a923ebf877ffa1e134b7eb23dbc758a56a44d1c3ea27d839a05d86e3e57ca86",
    "scope": "partner",
    "created_at": 1499800062
}

### Refresh Token **grant_type=refresh_token** is meant to be used to renew tokens before they expire to avoid having to re-use one of the above authentication flows. Tokens are regenerated with the same permissions they were originally requested with using the refresh token that was returned with the original access token request.

Obtaining a token is done by using grant_type=password inPOST /oauth/token.

Request:
POST /oauth/token?grant_type=refresh_token&client_id=ASSIGNED_CLIENT_ID&client_secret=ASSIGNED_CLIENT_SECRET&refresh_token=YOUR_REFRESH_TOKEN

Response:
{
    "access_token": "0d3d2ffd611fa8dfc44f0c2373de5460693a044a79ca60cda0eb99c5bb407c23",
    "token_type": "bearer",
    "expires_in": 31557600,
    "refresh_token": "9a923ebf877ffa1e134b7eb23dbc908a56a44d1c3ea27d839a05d86e3e57ca86",
    "scope": "public",
    "created_at": 1499800062
}

Scopes


Scopes provide an additional level of control to restrict access to specific resources for access tokens. Using scopes lets you request a token allowing you full access to your user data: scope=partner for use on your servers and restrict access granted to public tokens by using scope=public.

Scopes are also used to verify a request has sufficient permission to access a requested resource. Requests attempting to access data restricted by the data license must have the data scope attached to them.

The scope parameter defines what resources the returned authorization token will have access to. Currently the following scopes are supported: internal, mobile, partner and public where public is the default scope if no value is provided. Scopes will have different api resources they can or cannot access. To determine whether a scope has access to a particular endpoint check the endpoints section.

Some partners may only have the partner and public scopes available to them. If they request a scope that is not granted to them, they will receive an error message.

To declare a scope, add as a parameter to the POST /oauth/authorize or the POST /oauth/token request. Example:

POST /oauth/token?grant_type=client_credentials&client_id=1234abcde&client_secret=abcd1234&scope=internal

will return:

{
  "access_token": "new_token_12345",
  "token_type": "bearer",
  "expires_in": 31557600,
  "scope": "internal",
  "created_at": 1486143527
}```

...
More than one scope can be requested when requesting an access token by separating the requested scopes with spaces.

Request: POST /oauth/token?grant_type=client_credentials&client_id=ASSIGNED_CLIENT_ID_1234&client_secret=ASSIGNED_CLIENT_SECRET_1234&scope=partner public

Response: { "access_token": "88e2c51afc22e71c0da6d5bf29c77d7138fb40c46460c8fa94013cdfff24b974", "token_type": "bearer", "expires_in": 31557600, "refresh_token": "c03c4d7c860dbfc980f43b5bbc0f38bbe27a4d3bf4732bfe919efcbf2bc0ca65", "scope": "partner public", "created_at": 1499801066 }


If an invalid scope, or a scope that you do not have access to, has been requested you will receive an error.

Request: POST /oauth/token?grant_type=client_credentials&client_id=ASSIGNED_CLIENT_ID_1234&client_secret=ASSIGNED_CLIENT_SECRET_1234&scope=everything public

Response: { "error": "invalid_scope", "error_description": "The requested scope is invalid, unknown, or malformed." }


<br/>

## Zooms
---
Zooms provide an easy way for a single request to return multiple related resources.  Normally when requesting a resource additional API calls would be needed to fetch related resources as they are exposed in the `_links` field.  For example when searching for parking for an event API calls would be needed to retrieve both the venue information **and** the associated venue information.  By using zooms all of this data can be retrieved in a single request and will immediately be available to the API consumer.

For Example a request to view an event will show a `_links` entry for a venue record

Request: GET /events/31727?zoom=pw:venue

Response: { "id": 31727, "name": "Anything Goes", "venue_id": 382, "start_time": "2011-04-29T19:00:00.000-04:00", "end_time": "2011-04-29T22:00:00.000-04:00", "_links": { "self": { "href": "/events/31727" }, "pw:venue": { "href": "/venues/382" }, "pw:quotes": { "href": "/quotes?q=event_id:31727" }, "curies": [ { "name": "pw", "href": "https://api.parkwhiz.com/v4/{rel}", "templated": true } ] } }


By adding  a zoom for pw:venue the venue will be returned with the original request

Request: GET /events/31727?zoom=pw:venue

Response: { "id": 31727, "name": "Anything Goes", "venue_id": 382, "start_time": "2011-04-29T19:00:00.000-04:00", "end_time": "2011-04-29T22:00:00.000-04:00", "_embedded": { "pw:venue": { "id": 382, "name": "Stephen Sondheim Theatre", "address1": "124 West 43rd St", "city": "New York", "state": "NY", "postal_code": "10036", "_links": { "self": { "href": "/venues/382" }, "pw:events": { "href": "/venues/382/events" }, "pw:quotes": { "href": "/quotes?q=venue_id:382" }, "curies": [ { "name": "pw", "href": "https://api.parkwhiz.com/v4/{rel}", "templated": true } ] } } }, "_links": { "self": { "href": "/events/31727" }, "pw:venue": { "href": "/venues/382" }, "pw:quotes": { "href": "/quotes?q=event_id:31727" }, "curies": [ { "name": "pw", "href": "https://api.parkwhiz.com/v4/{rel}", "templated": true } ] } }```

Zooms can be applied to any endpoint and will load related data into the _embedded field of the response.

Add-Ons


Add-ons are additional options that can be purchased alongside a parking quote retrieved from a call to GET /quotes.

Add-ons, if present, will be a part of the purchase option. Add-ons can either be required or optional.

If an add-on is required ("required" : true) then one of the options present must be sent along with the request to purchase in order to complete a transaction.

Required add-ons

Currently the only required add-ons are related to vehicle size. This allows parking to be purchased for Standard, Oversize, or Supersize vehicles. Each option in the add_ons collection represents one of these selections as denoted in the name field.

Note: To prevent accidental purchases of Standard parking we do not pre-select any required add-ons and require the add-on id to be explicitly sent alongside the request to book parking if vehicle_size add-ons are present in the purchase option. Not all purchase options will have add-ons.

Each vehicle_size add-on option will have the following:

  • name to indicate the name of the add-on
  • price to indicate the price of the add-on
  • availability to indicate whether this type of parking is available or not
  • items that represent what each option represents at that facility. As different facilities have different definitions of Oversize, and Supersize it's important to verify that the vehicle type you are selecting parking for is in the set of items for the option that you purchase.

The list of items is as follows: coupe, sedan, hatchback, wagon, crossover, minivan, suv, truck/van

In the example below you can see the Standard, Oversize, and Supersize add-ons.

"add_ons": {
    "vehicle_size": {
        "required": true,
        "options": [
            {
                "id": "1fd867a5-eaf5-4b2a-95cb-b38bf44c3dc5",
                "name": "Standard",
                "start_time": "2017-10-26T21:30:00.000-05:00",
                "end_time": "2017-10-27T03:30:00.000-05:00",
                "price": {
                    "USD": "0.00"
                },
                "availability": {
                    "status": "available"
                },
                "items": [
                    "Coupe",
                    "Sedan",
                    "Hatchback"
                ],
                "icon": {
                "position": 0,
                    "sizes": {
                        "original": {
                            "URL": "https://d2uqqhmijd5j2z.cloudfront.net/files/102823/original/sedan.png?1465878137",
                            "width": 500,
                            "height": 500
                        }
                    }
                }
            },
            {
                "id": "301a2acc-aa94-4bf2-8aea-e8b3b80b33a6",
                "name": "Oversize",
                "start_time": "2017-10-26T21:30:00.000-05:00",
                "end_time": "2017-10-27T03:30:00.000-05:00",
                "price": {
                    "USD": "10.00"
                },
                "availability": {
                    "status": "available"
                },
                "icon": {
                    "position": 0,
                    "sizes": {
                        "original": {
                            "URL": "https://d2uqqhmijd5j2z.cloudfront.net/files/102824/original/van.png?1465878137",
                            "width": 500,
                            "height": 500
                        }
                    }
                }
            },
            {
                "id": "608ee199-1652-4902-a7ba-0e432db09872",
                "name": "Supersize",
                "start_time": "2017-10-26T21:30:00.000-05:00",
                "end_time": "2017-10-27T03:30:00.000-05:00",
                "price": {
                    "USD": "20.00"
                },
                "availability": {
                    "status": "available"
                },
                "icon": {
                    "position": 0,
                    "sizes": {
                        "original": {
                            "URL": "https://d2uqqhmijd5j2z.cloudfront.net/files/102825/original/truck.png?1465878137",
                            "width": 500,
                            "height": 500
                        }
                    }
                }
            }
        ]
    },
    ...

General Add-Ons

General add-ons are not required for purchase but are value-add services that can be selected with parking.

Below is an example of an optional add-on for a car wash. Note that it contains the same name, price, and availability fields as required add-ons.

"general": {
    "required": false,
    "options": [
        {
            "id": "0ce16a57-f83f-415f-837a-d7277dd5bee2",
            "name": "Car Wash",
            "description": "Get your car washed while you are parked.  Car washes are done professionally inside of our immaculate garage.",
            "start_time": "2017-10-26T21:30:00.000-05:00",
            "end_time": "2017-10-27T03:30:00.000-05:00",
            "price": {
                "USD": "10.00"
            },
            "availability": {
                "status": "available"
            },
            "icon": {
                "position": 0,
                "sizes": {
                    "original": {
                        "URL": "https://d2uqqhmijd5j2z.cloudfront.net/files/102826/original/addon.png?1465878138",
                        "width": 500,
                        "height": 500
                    }
                }
            }
        }
    ]
}

Purchasing Add-Ons

To purchase any add-on include its id in both the call to preview and purchase in the add_on_ids field. This is a comma-separated list that can hold all add-ons that you would like to purchase. Note that only add-ons attached to a quote can be purchased.

Last updated March 11, 2024