Introduction
Welcome to the Token Transit Payments API.
The Token Transit Payments API is a RESTful service that can be used as a drop-in Stripe replacement allowing roll-ups, custom receipts, and other useful payment functionality.
The payments API allows purchase of payments for authenticated users in third-party applications.
In addition to the live API, you may also access our test API by using a test API key.
Headers
The Token Transit API uses a number of common headers across the API. Some requests also require specific headers that will be mentioned separately. These should be included in each request.
Cookies used are described in the Cookies section.
List
This is a list of all headers and the endpoints for which they are useful.
Request Headers
These are all of the headers that you may need to include with requests
Header | Endpoints | Default | Description |
---|---|---|---|
Token-Transit-Api-Key |
all | N/A (Required) | Authentication that also identifies your service and access |
Token-Transit-Api-Version |
all | N/A (Required) | Describes which version of the API you wish to use. This document describes version |
Authentication |
Purchase, Pass Retrieveal, Login | N/A (Ignored/optional if user_session_id cookie is provided) |
A JWT signed by your service authenticating the user |
Idempotency-Key |
Purchase | N/A (Highly Recommended!) | A key to indicate a request is a duplicate (retry) of a previous request to prevent duplicate transactions |
Response headers
This is a list of important headers that might be sent back across multiple API requests.
Header | Endpoints | Description |
---|---|---|
Content-Type |
all | The encoding of the response (usually application/json ) |
Retry-After |
stateful endpoints upon a 503 failure | How many seconds to wait until retrying a request. A value of 0 means that the request may be retried immediately. |
Access-Control-Allow-Origin |
all | This is set to "*" to allow CORS requests. |
`
Cookies
These are all of the cookies that are used in the API.
Cookie Name | Endpoints | Description |
---|---|---|
user_session_id |
Purchase, Pass Retrieval, Login, Logout | A session id that can be used instead of a JWT to authenticate a user. |
API Authentication
Token Transit API uses API keys for authentication of your service. If you are integrating with us, your secret and publishable test and live API keys will be sent to you during the integration process.
To authenticate with Token Transit, you must send your API key as the Token-Transit-API-Key
HTTP header like the following example:
Token-Transit-API-Key: sk_fake_1234567890abcdef
API keys have two components: key type and environment.
Key Types
There are two types of keys: publishable (publishable
) and secret (secret
). Publishable keys may be freely used in your app. Publishable API keys are indicated with a pk
prefix to all keys. An API key has
Key Type | Key Prefix | Access Level | Allowed Usage |
---|---|---|---|
Publishable (publishable ) |
pk |
Agency information | App or web clients |
Secret (secret ) |
sk |
All | Backend servers only |
If an endpoint restricts only certain information or is only available for use with a secret key, it will be marked as "(Requires Secret Key)".
Environments
There are three environments available as part of the Token Transit API: fake, test, and live.
Environment | Key Infix | Description |
---|---|---|
fake |
_fake_ |
Fast, deterministic, stateless, fake API useful for exploring the API or automating integration tests. |
test |
_test_ |
Test servers that use fake credit cards, user accounts, and test payment provider environment. Useful for testing before launch. |
live |
_live_ |
Live service that should only use real accounts. |
Code examples in this doc exclusively use the fake environment.
Distribution
During your integration, we will ask you to provide us with a public RSA key. We we sign your API keys and distribute them to you over e-mail or your preferred method of contact.
Retrieval and Invalidation
Once we send you a copy of your API key, it is impossible for us to re-send you your key. If you suspect a key has been compromised or you lose your API key, we will have to send you new key(s) and invalidate the old one(s).
Protocol
All calls must be made over HTTPS and include API key authentication or they will fail.
User Credentials
In addition to API keys, some endpoints also require you also to provide us with a JWT that we can use to verify account credentials. You must have a user id (unique per user) for each of your users that you are willing to share with us and that you guarantee you can map back to a user for the duration of our integration with you.
The JWT should be specified according to IETF RFC 7519 and specify a number of claims and be signed using a key that is specified according to IETF RFC 7517 using an algorithm specified in IETF RFC 7518.
Here is a list of useful Links if you are not experienced with JWTs:
Authorization Header
User credentials should be sent using the Authorization
header specifying the Bearer
type. Example:
Authorization: Bearer JWTHeader.JWTClaims.JWTSignature
JWT Specification
We use the following standard claims:
Claim | Required | Description |
---|---|---|
iat |
Required | Creation time of the JWT. Must be in the past. |
exp |
Required | Expiration time of the JWT (Recommended no longer than 10 minutes past creation time) |
sub |
Required | User ID of your user that must be unique and that you can use to look up the user if we provide to you. |
aud |
Optional | If specified, please set to "tokentransit.com". We will reject any requests that include this claim but specify something else. This may be helpful to specify if you are generating JWTs for another API and don't want to mix up the JWTs. |
iss |
Optional | If specified, it must be a prefix of the HTTPS address of the JWKS server you have on file. This may be helpful to specify if you have a test and live server and you want an appropriate error message indicating that the issuer is incorrect. |
jti |
Optional | Can be used to force generation of a new session. We will never duplicate a session across JTIs even if the device ID is the same. |
We also use the following custom claims:
Claim | Required | Description |
---|---|---|
email |
Required | Specifies a contact method for the user. We require a contact method to be required for customer service purposes and to send users receipts. |
device_id |
Conditionally Required | If you will be generating and showing our visual tickets in your app, then you must provide a unique ID that represents a user's device. Some contracts with agencies require us to prevent users from sharing tickets across devices. |
phone |
Optional | Specifies a sms contact method for the user. We may use phone number to communicate notifications to a user. |
Sessions
In order to speed up calls and shrink the size of requests, we create a session id after every successful use of a JWT. The session id is returned in the user_session_id
cookie and can be used in place of the normal JWT authentication. If both a session id and a JWT are included in a request, the JWT is ignored.
You may wish to use the endpoint /user/login
to obtain a session id, as this endpoint has no further side effects. Any changes in a JWT will always result in a new session being created regardless of whether the JWT is for the same user on the same device.
Any successful request sent with a JWT (except those sent to the /user/logout
endpoint) will result in the user_session_id
cookie being set. This cookie may be used in place of a JWT authentication until the session expires. The session may expire at any time, so you should always first try a call with the user_session_id
and fall back to using a JWT if the request failes with a 401
Authorization Error status code.
If you would like to forcibly destroy a session, please call /user/logout
. This will block all further calls to the Token Transit API using that session id to fail with an authorization error.
Versioning
The Token Transit API uses a versioning system to separate breaking API changes. The Token-Transit-Api-Version
header should always be set to ensure that the correct version of the API is used.
All version ids look like date strings in the format YYYY-MM-DD
.
This version of the API is 2020-05-21
.
Idempotency
All requests that have the ability to modify state will be PUT
, POST
, DELETE
, or PATCH
requests. Any of these requests can include an Idempotency-Key
header. The idempotency key allows for requests to be retried without duplication of side-effects. All results whether successful or not will be saved server-side allowing a later request including an Idempotency-Key to be retried. These requests will always return the same result.
If an idempotency key is included in a request then the parameters of the request must match all previous requests with that key.
You may use any UUID suitable to yourself, but we strongly recommend generating UUIDs using UUID version 4 as specified in by IETF RFC 4122. Your UUID must be no longer than 128 bytes long and must be encoded in UTF8 format. We recommend either encoding the bytes using URL-safe base 64 encoding or the standard hexadecimal format specified in IETF RFC 4122.
Because GET
requests are inherently idempotent (they do not modify state), the Idempotency-Key
will be ignored on all GET
requests.
Errors
Token Transit uses standard HTTP codes to indicate success or failure as well as a JSON-encoded response for each error as well as a JSON response with more details.
Status Codes
Token Transit API uses a set of standard error codes.
Status Code | Name | Meaning |
---|---|---|
200 | Success | Request was successful. |
400 | Bad Request | Requested parameters or format were invalid. |
401 | Unauthorized | API key, user JWT, or session ID was missing or invalid. |
403 | Forbidden | Requested resource cannot be accesssed by API key and/or user JWT or session ID. |
404 | Not Found | Requested resource (e.g. Path, pass ID, etc) does not exist. |
409 | Conflict | Idempotency key was already used in a previous request with different parameters. |
429 | Too Many Requests | Your request has been rate-limited and must be retried. |
500 | Server Error | An internal error in the Token Transit service occurred. |
503 | Service Unavailable | An interanl error occurred that is retriable. Use the Retry-After header for guidance for when to retry. |
JSON Error Response
In addition to the status code, we also return a response with the following fields:
Field Name | Type | Description |
---|---|---|
type |
string | The type of error returned. |
code |
string | A code identifying a specific error. |
message |
string | A message to help debug the error. |
retryable |
boolean | A boolean indicating whether the request should be retried. |
param |
string | The name of the param that is missing or invalid. |
Developers
A developer is an entity that uses the Token Transit API. Generally your integration will have two developers: test and live. We provide a few endpoints to allow you to verify that your API keys work properly.
Retrieving Developer Info
Retrieves key type and developer id to verify that your key is working. Your API key uniquely identifies what partner is making the request, the environment, and what permissions may be accessed.
HTTP Request
curl "https://api.tokentransit.com/developer" \
-H "Token-Transit-Api-Key: sk_fake_1234567890abcXYZ" \
-H "Token-Transit-Api-Version: 2020-05-21"
The above command returns JSON structured like this
{
"platform_id": "plat_1234567890abcXYZ",
"platform_name": "Fake Platform",
"owner_entity_kind": "Platform",
"developer_id": "dev_1234567890abcXYZ",
"api_key_type": "secret",
"env": "fake"
}
GET /developer
HTTP Response
Field Name | Type | Description |
---|---|---|
platform_id |
string | ID of your platform. A platform is the entity associated with a developer. |
platform_name |
string | The name of your platform. |
developer_id |
string | A unique id for your developer. This developer is what your API keys are associated with |
api_key_type |
enum (as string) | Either publishable or secret indicating the key type |
env |
enum (as string) | Either fake , test or live indicating the environment that is being accessed |
Testing a Secret Key (Requires Secret Key)
This endpoint will return success if you are using a secret key and fail if you are using a publishable key.
HTTP Requst
curl "https://api.tokentransit.com/developer/private" \
-H "Token-Transit-Api-Key: sk_fake_1234567890abcXYZ" \
-H "Token-Transit-Api-Version: 2020-05-21"
The above command returns JSON structured like this
{
"platform_id": "plat_1234567890abcXYZ",
"platform_name": "Fake Platform",
"owner_entity_kind": "Platform",
"developer_id": "dev_1234567890abcXYZ",
"api_key_type": "secret",
"env": "fake"
}
GET /developer/private
HTTP Response
Field Name | Type | Description |
---|---|---|
platform_id |
string | ID of your platform. A platform is the entity associated with a developer. |
platform_name |
string | The name of your platform. |
developer_id |
string | A unique id for your developer. This developer is what your API keys are associated with |
api_key_type |
enum (as string) | Either publishable or secret indicating the key type |
env |
enum (as string) | Either fake , test or live indicating the environment that is being accessed |
Users
A user is the Token Transit representation of an account on your system. Users must be authenticated using JWTs that are signed by your service and returned to our service. We provide endpoints to fetch information about a user, generate a user session, and destroy a user session.
Generating a New User Session (Logging in) (User Authentication Required)
To obtain a user session, make a request to the login endpoint for the user
and specify a signed JWT. The session ID returned in the cookie can be used in place of a JWT in any requests requiring User Authentication.
HTTP Request
curl -H "Authorization: Bearer yJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6InVzZXItY29udGFjdC1lbWFpbEB0aGlyZC1wYXJ0eS1zaXRlLmNvbSIsImF1ZCI6IlRva2VuVHJhbnNpdCIsImlzcyI6Imh0dHBzOi8vdGhpcmQtcGFydHktc2l0ZS5jb20vcHVibGljLWtleS1zaWduYXR1cmUiLCJzdWIiOiJ1bmlxdWVVc2VySUQxMjM0NTY3ODkwIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE1NTk0MzAyMjR9.WRYRX2PYdUmouiQgG3r_KOTB7FRaW51YotR_YYuvnTCbymmlCP_I4-Di0QzvH096H7Mjh332JUp_Zx6P-TQt-iriEjCqKkZ8_WS9lc0TYClT5jL1cviS7yaZJgJfzakZL8nDtfseRMuXRNVy5nym87u_wZrZR20KpqlCSkhb-MI" \
-H "Token-Transit-Api-Key: sk_fake_1234567890abcXYZ" \
-H "Token-Transit-Api-Version: 2020-05-21" \
-d include_stripe_customer_id=true \
-b /tmp/tt_fake_api_cookies \
-c /tmp/tt_fake_api_cookies \
-X POST \
"https://api.tokentransit.com/user/login"
The above command returns JSON structured like this
{
"stripe_customer_id": "cus_1234567890abdXYZ"
}
POST https://api.tokentransit.com/user/login
Query Parameters
Parameter | Required/Default | Description |
---|---|---|
include_stripe_customer_id (Secret Key Only) |
false |
If true , return the Stripe customer id, but only if using a secret API key. |
HTTP Response
Field Name | Type | Description |
---|---|---|
stripe_customer_id |
string | The Stripe customer id of the user (for use with attaching a source to a customer. This will only be returned if include_stripe_customer_id is set to true |
Destroying an Existing User Session (Logging out) (User Authentication Required)
To destroy an existing user session, make a request to the logout endpoint and specify the session id.
HTTP Request
The following command assumes you have already sent a login request and saved cookies in
/tmp/tt_fake_api_cookies
curl -H "Token-Transit-Api-Key: sk_fake_1234567890abcXYZ" \
-H "Token-Transit-Api-Version: 2020-05-21" \
-b /tmp/tt_fake_api_cookies \
-c /tmp/tt_fake_api_cookies \
-X POST \
"https://api.tokentransit.com/user/logout"
The above command returns JSON structured like this
{}
POST https://api.tokentransit.com/user/login
Cookies
Name | Required | Description |
---|---|---|
user_session_id |
Required | The session id to destroy. This will prevent any future requests from using this session id. |
HTTP Response
The response will always be an empty JSON response upon success with a cookie set to delete the user_session_id
cookie.
Payments
A payment object is an updateable object that encompasses the entire flow for a single payment. Each payment has an id that is associated with the payment that can be used for retrieval and update.
Headers
The following headers are either required, strongly recommended, or specific to this set of endpoints.
Name | Required | Description |
---|---|---|
Idempotency-Key |
Strongly Recommended for POST endpoints |
A key to unique to the given request. Specifying an idempotency key will guarantee a single purchase per key no matter how many times the endpoint is called. |
Authentication |
Required if no user_session_id |
A customer token must be provided for the user unless the user_session_id cookie is set. |
Response Object
All responses in this section will return a response object with the following fields
Field Name | Type | Description |
---|---|---|
id |
string | A unique id for the payment. |
amount |
integer | An integer amount of the lowest denomination of the provided currency for the amount of the payment. |
currency |
string | A three-letter ISO currency code |
application_fee_amount |
integer | The amount charged by Token Transit for use of the service (in lowest denonimation of specified currency). |
canceled_at |
integer | Time in seconds of cancellation. |
cancellation_reason | string | A reason for the cancellation. |
created |
integer | Creation timestamp in seconds. |
last_payment_error |
string | A string indicating the error that occurred while requesting the payment. |
metadata |
dictionary | A dictionary containing all metadata associated with this payment. |
next_action |
dictionary | Next action that is required (for 3D-secure) cards. |
next_action.redirect_to_url |
dictionary | Redirect after payment instructions. |
next_action.redirect_to_url.return_url |
dictionary | If the customer does not exit their browser while authenticating, they will be redirected to this specified URL after completion. |
next_action.redirect_to_url.url |
string | URL you must direct customer to for payment authentication |
payment_method |
string | ID of payment method used for payment |
status |
string (enum) | One of requires_payment_info , requires_confirmation , requires_action , processing , cancellation_processing , canceled , or succeeded . |
Creating a Payment (User Authentication Required)
Creating a payment will always be the first thing that you do. If you supply enough information, this payment may be confirmed.
HTTP Request
POST /agency/{agency_id}/payment
Path components
Path component | description |
---|---|
agency_id |
Unique identifier for the agency. |
Query Parameters
Parameter | Required/Default | Description |
---|---|---|
amount |
Required for confirmation | An integer amount (may be 0) of the lowest denomination of the specified currency |
currency |
Required for confirmation | Three-letter ISO currency code (case insenstive) |
metadata |
Optional | A dictionary of metadata for your service (e.g. start stop, end stop, trip id) |
payment_method |
Required in final payment | A stripe payment source or token |
save_payment_method |
false |
If set to true , payment method will be saved to user account and a reusable payment method will be sent back in response. |
HTTP Response
A payment object.
Retrieving a Payment (User Authentication Required)
Retrieve an existing payment
HTTP Request
GET /agency/{agency_id}/payment/{payment_id}
Path components
Path component | description |
---|---|
agency_id |
Unique identifier for the agency. |
payment_id |
Unique identifier for the payment. |
Updating a Payment (User Authentication Required)
Update existing fields of a payment (e.g. payment_method
, amount
, currency
, metadata
, etc.)
This is optional if the original create request contained all of the necessary fields.
Path components
Path component | description |
---|---|
agency_id |
Unique identifier for the agency. |
payment_id |
Unique identifier for the payment. |
Query Parameters
Parameter | Required/Default | Description |
---|---|---|
amount |
Required for confirmation | An integer amount (may be 0) of the lowest denomination of the specified currency |
currency |
Required for confirmation | Three-letter ISO currency code (case insenstive) |
metadata |
Optional | A dictionary of metadata for your service (e.g. start stop, end stop, trip id). If a key is specified with an empty value, that value will be deleted. |
payment_method |
Required in final payment | A stripe payment source or token |
save_payment_method |
Optional (no default) | If set to true , payment method will be saved to user account and a reusable payment method will be sent back in response. If set to false payment method will not be saved. Omitting this field will not modify the existing value. |
HTTP Response
A payment object
Confirming a Purchase (User Authentication Required)
This endpoint is used to confirm a purchase. After submission, the payment will be executed.
HTTP Request
POST /agency/{agency_id}/payment/{payment_id}/confirm
Path components
Path component | description |
---|---|
agency_id |
Unique identifier for the agency. |
payment_id |
Unique identifier for the payment. |
Query Parameters
Parameter | Required/Default | Description |
---|---|---|
metadata |
Optional | A dictionary of metadata for your service (e.g. start stop, end stop, trip id). If a key is specified with an empty value, that value will be deleted. |
Cancelling a Purchase (User Authentication Required)
This endpoint is used to cancel a purchase. A purchase may be cancelled at any time, even after the purchase has already gone through.
HTTP Request
POST /agency/{agency_id}/payment/{payment_id}/cancel
Path components
Path component | description |
---|---|
agency_id |
Unique identifier for the agency. |
payment_id |
Unique identifier for the payment. |
Query Parameters
Parameter | Required/Default | Description |
---|---|---|
metadata |
Optional | A dictionary of metadata for your service (e.g. start stop, end stop, trip id). If a key is specified with an empty value, that value will be deleted. |
HTTP Response
A payment object (generally with the status set to cancelled. If a non-retryable error is received, it means the payment was not cancelled.