NAV Navbar
python javascript

Introduction

Welcome to the i2 Trading developer documentation. These documents outline our trading interface functionality and APIs.

Availability

The i2 Trading REST and Websocket feed services are continuously available with the exception of a maintenance window that runs from 17:30 to 18:00 EST/EDT daily.

Sandbox Environment

For testing and development please access our sandbox environment at the URLs below. The sandbox environment requires different credentials than the production APIs. For access, please email [email protected]

User Authentication API (documented separately)

https://sbx.auth.api.i2trading.com/beta/auth/

REST API

https://sbx.api.i2trading.com/

Websocket Feed

ws://sbx.ws.api.i2trading.com:9000

Production Environment

For access, please email [email protected]

User Authentication API (documented separately)

https://auth.api.i2trading.com/beta/auth/

REST API

https://api.i2trading.com/

Websocket Feed

ws://ws.api.i2trading.com:9000

Onboarding API

The Authentication API has endpoints for user management and signup flow.

Authentication API Beta Production URL

https://auth.api.i2trading.com/beta/auth/

Requests

All requests and responses are application/json content type and use appropriate HTTP response status codes for success and failure. All requests made to the Authentication API must send the X-Api-Key header.

Sign Up flow

Personal

Request

{
    "email": "[email protected]",
    "password": "xxxxxxxx",
    "clientId": "xxxxxxxxxxxxxxxxxxxxxxx"
}

Response

{
    "signupResponse": {
        "UserConfirmed": false,
        "CodeDeliveryDetails": {
            "Destination": "j***@d***.com",
            "DeliveryMedium": "EMAIL",
            "AttributeName": "email"
        },
        "UserSub": "xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx",
        "account_type": "personal"
    },
    "registerResponse": {
        "username": "j***@d***.com",
        "party_type": "user",
        "user_currency": "USD",
        "party_id": "xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx",
        "balance_limit": 10000
    }
}

POST /sign-up/personal

Register a new user with the personal account type.

PARAMETERS

Param Description
email User email
password User password
clientId ClientId to connect with correct user pool

Notes:

Institutional

Request

{
    "email": "[email protected]",
    "password": "xxxxxxxx",
    "clientId": "xxxxxxxxxxxxxxxxxxxxxxx"
}

Response

{
    "signupResponse": {
        "UserConfirmed": false,
        "CodeDeliveryDetails": {
            "Destination": "j***@d***.com",
            "DeliveryMedium": "EMAIL",
            "AttributeName": "email"
        },
        "UserSub": "xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx",
        "account_type": "institution"
    },
    "registerResponse": {
        "username": "j***@d***.com",
        "party_type": "user",
        "user_currency": "USD",
        "party_id": "xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx",
        "balance_limit": 10000
    }
}

POST /sign-up/institution

Register a new user with the institutional account type.

PARAMETERS

Param Description
email User email
password User password
clientId ClientId to connect with correct user pool

Notes:

Confirm User

Request

{
    "email": "[email protected]",
    "confirmCode": "xxxxxx",
    "clientId": "xxxxxxxxxxxxxxxxxxxxxxx"
}

Response

{}

POST /confirm-user

Register a new user with the personal account type.

PARAMETERS

Param Description
email User email
confirmCode User code sent by email
clientId ClientId to connect with correct user pool

Notes:

Resend Verification Code

Request

{
    "email": "[email protected]",
    "clientId": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}

Response

{}

POST /resend-verification

Resend the email verification code to an user.

PARAMETERS

Param Description
email User email
clientId ClientId to connect with correct user pool

Sign In flow

Here will be described all the endpoints needed to sign in a user and return him the access token required to perform the actions on Trading API.

The sign in flow can occur in two different ways:

Sign in

Request

{
    "email": "[email protected]",
    "password": "xxxxxxxx",
    "clientId": "xxxxxxxxxxxxxxxxxxxxxxx"
}

Response (without 2FA)

{
    "ChallengeParameters": {},
    "AuthenticationResult": {
        "AccessToken": "eyJraWQiOiJua2ly...",
        "ExpiresIn": 3600,
        "TokenType": "Bearer",
        "RefreshToken": "eyJjdHkiOiJKV1Qi...",
        "IdToken": "eyJraWQiOiJLYlBoYzlYdzFa..."
    },
    "user_info": {
        "Username": "xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx",
        "sub": "xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx",
        "account_type": "personal",
        "email_verified": "true",
        "account_status": "PENDING",
        "email": "[email protected]"
    }
}

Response (with 2FA)

{
    "ChallengeName": "SMS_MFA",
    "Session": "v94oMsRrnoMGUy96aCnDcqlBeaMUStdD...",
    "ChallengeParameters": {
        "CODE_DELIVERY_DELIVERY_MEDIUM": "SMS",
        "CODE_DELIVERY_DESTINATION": "+*******1234",
        "USER_ID_FOR_SRP": "xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx"
    }
}

POST /sign-in

Request a user sign in to get the access token (without 2FA) or the session token (with 2FA).

PARAMETERS

Param Description
email User email
password User password
clientId ClientId to connect with correct user pool

Confirm Sign In

Request

{
  "email": "[email protected]",
  "clientId": "xxxxxxxxxxxxxxxxxxxxx",
  "confirmCode": "xxxxxx",
  "session": "FbE-GfNxx1PK8VRnfV6nMz8ZP6..."
}

Response

{
    "ChallengeParameters": {},
    "AuthenticationResult": {
        "AccessToken": "eyJraWQiOiJua2lyYzdaMWhtREhTVVZXczhnOCtNY0Y2bWJLdEx5Qm84Z1J...",
        "ExpiresIn": 3600,
        "TokenType": "Bearer",
        "RefreshToken": "eyJjdHkiOiJKV1QiLCJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiUlN...",
        "IdToken": "eyJraWQiOiJLYlBoYzlYdzFaeDl2aUhkNTdjWURWRDJ6c1Bi..."
    },
    "user_info": {
        "Username": "xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx",
        "sub": "xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx",
        "account_type": "personal",
        "email_verified": "true",
        "account_status": "PENDING",
        "phone_number_verified": "true",
        "phone_number": "+11111111111",
        "email": "[email protected]"
    }
}

POST /confirm-signin

Confirm a user signIn verifying the code sent by phone number.

Only used if the user has 2FA enabled

PARAMETERS

Param Description
email User email
clientId ClientId to connect with correct user pool
confirmCode code sent to the user phone
session session token provided by signin endpoint

Sign out

Request

{
  "clientId": "xxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "accessToken": "eyJraWQiOiJua2lyYzdaMWhtREhTVVZXczhnOCtNY0..."
}

Response

{}

Sign out a user previously signed in.

POST /sign-out

PARAMETERS

Param Description
clientId ClientId to connect with correct user pool
accessToken User access token

Update User Profile

Request

{
  "clientId": "7spv3mv4mnhvsbn3l01ogm4poh",
  "accessToken": "eyJraWQiOiJua2lyYzdaMWhtREhTVVZXczhnOC....",
  "first_name": "John",
  "phone_number": "+11111111111"
}

Response

{}

Endpoint to update the user profile with custom data.

POST /update-profile

PARAMETERS

Param Description
accessToken User access token
clientId ClientId to connect with correct user pool
params_to_update Any of the possible properties to be changed

User Info

Request

.../users/info?accessToken=H0m198oxHQMErXGX....

Response

{
    "Username": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "sub": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "email_verified": "true",
    "phone_number_verified": "true",
    "nationality": "BR",
    "last_name": "Doe",
    "account_type": "personal",
    "first_name": "John",
    "phone_number": "+xxxxxxxxxxx",
    "website": "www.example.com",
    "email": "[email protected]",
    "account_status": "ACTIVE"
}

Endpoint to all info stored about a specific user.

GET /users/info

PARAMETERS

Param Description
accessToken User access token

Notes:

2FA Enabling Flow

Here will be described all the endpoints needed to enable the 2FA sign if for a user.

Notes:

Send Phone Code

Request

{
    "accessToken": "eyJraWQiOiJua2lyYzdaMWhtREhTVVZXczhnOCtNY0Y2bWJLdEx5Qm8...",
    "clientId": "xxxxxxxxxxxxxxxxxxxxxxxxxx"
}

Response

{
    "CodeDeliveryDetails": {
        "Destination": "+*******1111",
        "DeliveryMedium": "SMS",
        "AttributeName": "phone_number"
    }
}

POST /send-phone-code

Send a phone code to the phone number registered to the current user.

PARAMETERS

Param Description
accessToken User access token
clientId ClientId to connect with correct user pool

Confirm Phone

Request

{
  "accessToken": "eyJraWQiOiJua2lyYzdaMWhtREhTVVZXczhnOCtNY0Y2bWJLdEx5Qm84Z....",
  "confirmCode": "xxxxxx"
}

Response

{}

POST /confirm-phone

Confirm the code received by the previous endpoint.

PARAMETERS

Param Description
accessToken User access token
confirmCode Code received by phone

Password Management

Endpoints used to manage the users accounts passwords.

Reset Password

Request

{
    "clientId": "xxxxxxxxxxxxxxxxxxxxxxxxxx",
    "email": "[email protected]"
}

Response

{
    "CodeDeliveryDetails": {
        "Destination": "j***@d***.com",
        "DeliveryMedium": "EMAIL",
        "AttributeName": "email"
    }
}

POST /reset-password

Ask the API for a password change. This action will send a confirmation code by e-mail, and this code must be used to confirm the change password action.

PARAMETERS

Param Description
cliendtId ClientId to connect with correct user pool
email User email of the account

Confirm Reset Password

Request

{
    "clientId": "xxxxxxxxxxxxxxxxxxxxxxxxxx",
    "email": "[email protected]",
    "confirmCode": "xxxxxx",
    "password": "xxxxxxxx"
}

Response

{}

POST /confirm-reset-password

Endpoint to confirm password change. In order to perform this action the user must have the confirm code.

PARAMETERS

Param Description
cliendtId ClientId to connect with correct user pool
email User email of the account
confirmCode Code confirmation received previously
password New password to be set

Notes:

Bitcoin Liquidity API

The REST API has endpoints for order management and trading.

REST API Production URL

https://api.i2trading.com

There is also a websocket feed for streaming market data and order execution reports.

Requests

All requests and responses are application/json content type and use appropriate HTTP response status codes for success and failure.

Errors

{
  "message": "Invalid Symbol"
}

Unless otherwise stated, bad requests will recieve a response with HTTP 4xx status codes. The body will also contain a message parameter indicating the cause. Your language's HTTP library should be configured to provide message bodies for non-2xx requests so that you can read the message field from the body.

Common error codes

Status Code Description Possible Cause
400 Bad Request Invalid request format
401 Unauthorized Invalid access token or bad header
403 Forbidden You do not have access to the requested resource
404 Not Found Invalid URL
500 Internal Server Error i2 Trading had a problem handling your request

Success

A successful response is indicated by HTTP status code 200 and may contain an optional body. If the response has a body it will be documented under each resource below.

Types

Timestamps

Unless otherwise specified, timestamps from the API are returned in ISO 8601 with microseconds. Make sure you can parse the following ISO 8601 format. Your language should have a library that can handle this without issues.

2019-06-04T16:53:40.357515+00:00

Numbers

Decimal numbers are returned as strings to preserve full precision across platforms. When making a request, it is recommended that you also convert your numbers to strings to avoid truncation and precision errors.

Integer numbers are unquoted.

Strings

All strings should be encoded in utf-8 unless otherwise specified.

IDs

Most identifiers are UUID unless otherwise specified. When making a request which requires a UUID, both forms (with and without dashes) are accepted.

11ffe56f-fce2-4fba-80ec-ab50a54f5eef or 11ffe56ffce24fba80ecab50a54f5eef

Authentication

User Account Creation

The i2 Trading APIs use AWS Cognito for user account management and authorization. AWS Cognito implements OAuth2 and OpenID Connect. The trading REST API and Websocket feed require valid Cognito (OAuth2) access tokens to authorize user requests.

Getting an Access Token

Registered users can retrieve an access token which is used to access the REST and Websocket APIs. Access tokens are valid for one hour from the time they are retrieved. A new access token can be retrieved either by signing-in again or by using the RefreshToken in the sign-in response.

Request

{
  "email": "[email protected]",
  "password": "xxxxxxxx",
  "clientId": "xxxxxxxxxxxxxxxxxxxxxxxxxx"
}

Response

{
  "AuthenticationResult": {
    "AccessToken": "eyJraWQiOiJMS3FrYUl..........",
    "ExpiresIn": 3600,
    "TokenType": "Bearer",
    "RefreshToken": "ayJasdsadJKV1QiLCJlb........",
    "IdToken": "ayJasdsadJKV1QiLCJlb..........."
  },
  "user_info": {
    "Username": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "sub": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "email_verified": "true",
    "phone_number_verified": "true",
    "nationality": "US",
    "last_name": "Doe",
    "account_type": "personal",
    "first_name": "John",
    "phone_number": "+xxxxxxxxxxx",
    "website": "www.example.com",
    "email": "[email protected]"
  }
}

HTTP Request

POST /sign-in

The headers referenced in creating a request are not required to access this endpoint.

Attributes

The AccessToken attribute returned in the response is a JSON web token granting access to the REST and Websocket APIs (see creating a request). Access tokens are valid for one hour from the time they are retrieved.

Creating a Request

All REST requests aside from must contain the following headers:

Header Content
i2-ACCESS-KEY Cognito AccessToken acquired from the /sign-in endpoint
i2-ACCESS-SIGN The base64-encoded signature (see Signing a Message)
i2-ACCESS-TIMESTAMP The UTC timestamp for your request

All request bodies should have the content type application/json and be valid JSON.

Timestamp Request Header

The i2-ACCESS-TIMESTAMP request header must be the number of seconds since Unix Epoch in UTC. Decimal values are allowed.

Your timestamp must be within 10 seconds of the API service or your request will be considered stale and rejected. We recommend using the time endpoint to query for the API server time if you think there may be a skew between your server and the API servers.

Signing a Message

# Requires python-requests. Install with pip: pip install requests

import json, hashlib, time, requests, base64
from requests.auth import AuthBase

# Create authentication class for i2 API
class I2Auth(AuthBase):
    def __init__(self, access_token):
        self.access_token = access_token

    def __call__(self, request):
        timestamp = str(time.time())
        try:
            body = request.body.decode("utf8")
        except AttributeError:
            body = ""
        message = self.access_token + timestamp + request.path_url + body
        signature = hashlib.sha256(message.encode("utf-8"))
        signature_b64 = base64.b64encode(signature.digest())

        request.headers.update(
            {
                "i2-ACCESS-KEY": self.access_token,
                "i2-ACCESS-SIGN": signature_b64,
                "i2-ACCESS-TIMESTAMP": timestamp,
            }
        )
        return request

# Get time from server
r = requests.get(api_url + "time", auth=auth)
print(r.json)
arrayBufferToBase64 = ( buffer ) => {
    var binary = '';
    var bytes = new Uint8Array( buffer );
    var len = bytes.byteLength;
    for (var i = 0; i < len; i++) {
        binary += String.fromCharCode( bytes[ i ] );
    }
    return btoa(binary);
  }

fetchTestFromApi = (authObj) => {
  const path = '/time';
  // The body is the request body string or is omitted if there is no request body (typically GET requests).
  let headerObj = {
    'i2-ACCESS-KEY': authObj.accessToken.jwtToken,
    'i2-ACCESS-TIMESTAMP': new Date().getTime() / 1000,
    'Content-Type': 'application/json'

  }
  let message = headerObj['i2-ACCESS-KEY'] + headerObj['i2-ACCESS-TIMESTAMP'] + path;
  message = utf8.encode(message);
  let sha256Encrypted = sha256.array(message);
  headerObj['i2-ACCESS-SIGN'] = this.arrayBufferToBase64(sha256Encrypted);
  const options = {
    method: 'GET',
    headers: {
      ...headerObj
    }
  }
  fetch('/time', options).then((resp) => {console.log(resp)})
}

Output:

{
  "iso": "2019-06-06T13:46:53.146390+00:00",
  "epoch": "1559828813.14639",
  "maintenance_start": "21:30:00+00:00",
  "maintenance_end": "22:00:00+00:00"
}

The i2-ACCESS-SIGN request header is generated by creating a sha256 hash of the concatenation of the prehash string i2-ACCESS-KEY + i2-ACCESS-TIMESTAMP + requestPath + body (where + indicates string concatenation) and base64 encoding the binary output of the hash function. Make sure you base64 encode the binary / byte string digest of the sha264 hash function. Any other digest, such as a hexadecimal string digest, will not work.

To check your hash function you can hash the string "123". The b64 encoded sha256 hash should be

pmWkWSBCL51Bfkhn79xPuKBKHz//H6B+mY6G9/eieuM=

The body is the request body string or is omitted if there is no request body (typically GET requests).

Orders

The API only supports limit orders with the time-in-force set to fill-or-kill. Orders accepted by the API will either be filled in full at or below the limit price immediately or cancelled.

No other order types are currently supported.

Orders can only be placed for amounts less than or equal to your current unsettled trade limit. Trades that would cause you to exceed this limit are automatically rejected.

Place a New Order

Request

{
  "client_oid": "410e532e-6d87-4f3e-a83d-739da5a8d61b",
  "product_id": "BTC-USD",
  "price": "8600.25",
  "size": "10.0",
  "ord_type": "limit",
  "side": "buy",
  "time_in_force": "FOK"
}

Response

{
  "id": "210d35ca-bfd8-419c-be37-87a556a904e1",
  "client_oid": "410e532e-6d87-4f3e-a83d-739da5a8d61b",
  "product_id": "BTC-USD",
  "price": "8600.25",
  "size": "10.00000000",
  "ord_type": "limit",
  "side": "buy",
  "time_in_force": "FOK",
  "created_at": "2019-06-04T18:34:02.327857+00:00",
  "status": "pending"
}

HTTP Request

POST /orders

Parameters

Param Description
client_oid [optional] Client specified order id up to 36 characters
product_id Acceptable values: "BTC-USD"
ord_type Acceptable values: "limit"
side Acceptable values: "buy" or "sell"
time_in_force Acceptable values: "FOK"
price Order price as a decimal number
size Quantity of symbol to transact.

Note: Values exceeding the max decimal precision for the symbol or price will be truncated (8 decimals for BTC and 2 decimals for USD).

You can see the symbols available and their precision using the products endpoint.

Client Order ID

The optional client_oid field should be a UUID generated by your application. Uniqueness of client_oid is strongly recommended but is not enforced. The client_oid is different than the server-assigned order_id. You should record the server-assigned order_id since the client_oid will NOT be used after the received message is sent.

Product ID

The product_id must match a valid product. The products list is available via the /products endpoint. Currently only "BTC-USD" is available.

Type

Orders can only be placed using the limit order type.

A limit order will be filled at the price specified or better. If market conditions cannot fill the order immediately, the server will cancel it according to the time_in_force specified.

Time in Force

Time in force policies provide gaurantees about the lifetime of an order. Currently, the only valid policy is fill-or-kill (FOK).

FOK Fill or kill orders are rejected if the entire size cannot be executed immediately at or below the limit price.

Order Lifecycle

An HTTP request will receive a response when an order is either rejected (invalid parameters, etc) or received by the system. A 200 response indicates that the order was received and is active.

Subsequent updates to the status of an order (including rejections such as unsettled trade limit exceeded) will be published to the user over the streaming data feed. Users should subscribe to this data feed to track the status of their order.

Request for Quote (RFQ)

Get a firm quote with a set expiration time.

Request

{
  "product_id": "BTC-USD",
  "base_currency_size": "10.0",
  "side": "buy"
}

Response

{
  "quote_id": "6377c3da-d3e4-48d9-a503-b047e141606c",
  "product_id": "BTC-USD",
  "base_currency": "BTC",
  "quote_currency": "USD",
  "price": "8650.00",
  "base_currency_size": "10.0",
  "quote_currency_size": "86500.00",
  "side": "buy",
  "created_at": "2019-10-29T15:32:02.327857+00:00",
  "expiry": "2019-10-29T15:35:02.327857+00:00"
}

HTTP Request

POST /quotes

In addition to trading directly against i2's live streaming quotes, clients can request a firm quote for a specific product and market side (buy/sell). Quotes requested through the RFQ endpoint remain valid and tradeable for a specific amount of time.

Requesting a new quote invalidates any previous unexpired quote for the same product and side. Only the latest quote received for a given product and market side may be accepted and traded.

Param Description
product_id Product to trade (see GET /products)
base_currency_size Size to trade in base currency (i.e. BTC if product is BTC-USD). Only one of base_currency_size or quote_currency_size can be specified.
quote_currency_size Size to trade in quote currency
side buy or sell

Trading a Quote

HTTP Request

POST /quotes/accept

Request

{
  "quote_id": "6377c3da-d3e4-48d9-a503-b047e141606c",
  "settlement_address": "1XPTgDRhN8RFnzniWCddobD9iKZatrvH4"
}

Response

{
  "success": true,
  "quote_id": "6c1b33f4-84fe-40a1-a017-a7991d46fe84",
  "order": {
    "id": "0f0665a9-4274-418e-ba93-3b8bd4d5b1bf",
    "created_at": "2020-01-29T19:39:03.513046+00:00",
    "product_id": "BTC-USD",
    "ord_type": "limit",
    "time_in_force": "FOK",
    "price": "8650.00",
    "size": "10.0",
    "side": "buy",
    "settle_from": "ADDRESS_Z",
    "settle_to": "ADDRESS",
    "status": "done",
    "executed_value": "86500.00"
  }
}
Param Description
quote_id Quote id
settlement_address [optional] Cryptocurrency address requested to be used for settlement
settlement_zelle [optional] Zelle id requested to be used for USD settlement

Note: Any settlement_address or settlement_zelle specified in the request must first be whitelisted through the API. See whitelist settlement details.

Order History

Get the status of the previous 25 orders.

[
  {
      "id": "4fd6e2c3-abc0-4084-b772-d7a9d4f8484e",
      "client_oid": "11f61551-f6ac-49f6-ac89-a2e66b65cf8d",
      "product_id": "BTC-USD",
      "price": "9400.00",
      "size": "10.00000000",
      "ord_type": "limit",
      "side": "buy",
      "time_in_force": "FOK",
      "created_at": "2019-10-02T14:51:56.145546+00:00",
      "status": "done",
      "done_at": "2019-10-02T14:51:56.154162+00:00",
      "done_reason": "filled",
      "filled_size": "10.00000000",
      "executed_value": "83295.40"
  },
  {
      "id": "675ee2bb-4cf2-43ec-9a72-3c4082acb3e9",
      "client_oid": "26d5d210-1bfb-44a7-82ef-ab92d64b32b6",
      "product_id": "BTC-USD",
      "price": "9400.00",
      "size": "10.00000000",
      "ord_type": "limit",
      "side": "buy",
      "time_in_force": "FOK",
      "created_at": "2019-10-02T14:46:49.924266+00:00",
      "status": "done",
      "done_at": "2019-10-02T14:46:49.930250+00:00",
      "done_reason": "filled",
      "filled_size": "10.00000000",
      "executed_value": "83236.80"
  }
]

HTTP Request

GET /orders

Polling

It is strongly recommended that you maintain your own list of open orders and use the streaming market data feeds to keep it updated.

executed_value is the filled size multiplied by the fill price, which may be equal to or less than the order's limit price.

Optional Fields

The fields done_at, done_reason, and executed_value are optional and may not be returned for each order. The fields done_at and done_reason are only returned for completed ("done") orders. The field executed_value is only returned for orders that have been partially or completely filled.

Get a Specific Order

Get a single order by order id.

HTTP Request

GET /orders/<order-id>

Whitelist Settlement Details

These endpoints allow clients to "whitelist" specific cryptocurrency addresses and Zelle ids to be used for settling trades.

Add to the whitelist

Request

{
  "currency": "BTC",
  "type": "crypto_address",
  "value": "1XPTgDRhN8RFnzniWCddobD9iKZatrvH4",
  "alias": "My favorite wallet"
}

Response

{
  "success": true
}

HTTP Request

POST /whitelist

Param Description
currency Currency the address corresponds to. Must be USD for Zelle ids.
type Resource type. Acceptable values: crypto_address and zelle_id
value The address or Zelle id to whitelist
alias [optional] Human readable name for the resource

Remove from the whitelist

Response

{
  "success": true
}

HTTP Request

DELETE /whitelist/<value>

Get whitelisted records

Returns all whitelisted addresses and Zelle ids for the user.

[
  {
    "currency": "BTC",
    "type": "crypto_address",
    "value": "1XPTgDRhN8RFnzniWCddobD9iKZatrvH4",
    "alias": "My favorite wallet"
  },
  {
    "currency": "BTC",
    "type": "crypto_address",
    "value": "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa",
    "alias": "My other favorite wallet"
  }
]

HTTP Request

GET /whitelist

Unsettled Balances

Get your current unsettled trade balances.

{
  "balances": {
    "BTC": {
      "net_quantity": "10.00000000",
      "net_notional_value": "80000.00",
      "notional_currency": "USD",
      "reference_price": "8000.00"
    },
    "USD": {
      "net_quantity": "-80000.00",
      "net_notional_value": "-80000.00",
      "notional_currency": "USD",
      "reference_price": "1.00"
    }
  },
  "limit": {
    "unsettled_trade_limit": "100000.00",
    "limit_currency": "USD"
  }
}

HTTP Request

GET /balances

Details

The unsettled_trade_limit field indicates the total unsettled net notional value that the account is permitted to have before settling its trades. Trades that would cause the unsettled net notional balance to exceed this limit are rejected by the system. The limit is typically denoted in USD as indicated by the limit_currency field.

You can calculate the remaining notional value you can trade before settling by subtracting net amount owed to i2 from the unsettled_trade_limit. The net amount due is calculated by taking the sum of net_notional_value for any currencies where net_notional_value is negative.

Products

Get a list of available pairs for trading.

[
  {
    "id": "BTC-USD",
    "base_currency": "BTC",
    "quote_currency": "USD",
    "base_min_size": "0.001",
    "base_max_size": "1000.00",
    "quote_increment": "0.01",
    "base_precision": 8,
    "quote_precision": 2
  }
]

HTTP Request

GET /products

Details

The base_min_size and base_max_size fields define the min and max order size. The base_max_size is unrelated to trade limits on an account and serves as a sanity check for abnormally large orders.

The quote_increment field specifies the min order price as well as the price increment.

The order price must be a multiple of this increment (i.e. if the increment is 0.01, order prices of 0.001 or 0.021 would be rejected).

The base_precision and quote_precision fields define the number of decimal points of divisibility available for the respective currency. For example, BTC is divisible to 8 decimal points (eg. 0.00000001 BTC) and USD is divisible to 2 (eg. $0.01).

Time

Get the API server time.

{
  "iso": "2019-06-06T13:46:53.146390+00:00",
  "epoch": "1559828813.14639",
  "maintenance_start": "21:30:00+00:00",
  "maintenance_end": "22:00:00+00:00"
}

HTTP Request

GET /time

Epoch

The epoch field represents decimal seconds since Unix Epoch

Live Order Updates (WS Feed)

The websocket feed provides real-time market data and updates for orders and trades.

Websocket Production URL

wss://ws.i2trading.com

Protocol Overview

All messages (in both directions) are encoded as JSON objects and include a type attribute that can be used to handle the message appropriately.

New messages can be added at any time. Client should ignore messages they do not support.

Authentication

To authenticate and connect to the websocket feed you must pass the same headers used to send an authenticated call to the REST API in the initial HTTP handshake. If authentication succeeds the connection will be automatically upgraded to websockets.

Message Types

Once authenticated the server will automatically send level two market data snapshots for BTC-USD as well as order acknowledgements and execution reports for completed trades.

Level 2 Snapshots

{
   "type":"l2_snapshot",
   "sending_time":"2019-06-28 20:54:23.059460",
   "fix_seq_no":"35085",
   "product":"BTC-USD",
   "bids":{
      "3660.13":{
         "pos":1,
         "size":"1000.0",
         "id":"25"
      },
      "3659.31":{
         "pos":2,
         "size":"2000.0",
         "id":"29"
      },
      "3659.22":{
         "pos":3,
         "size":"3000.0",
         "id":"26"
      }
   },
   "asks":{
      "3660.95":{
         "pos":1,
         "size":"1000.0",
         "id":"30"
      },
      "3661.04":{
         "pos":2,
         "size":"2000.0",
         "id":"27"
      },
      "3661.13":{
         "pos":3,
         "size":"3000.0",
         "id":"28"
      }
   }
}

TYPE

l2_snapshot

Level two market data snapshot for the specified symbol.

Field Type Description
seq number Non-decreasing sequence number of snapshot
pos number Position of price level in side of book starting from 1
size number Aggregate size available at this price level
id string Uniquely identifies the price level within the snapshot. Will reuse ids across snapshots

Note: If you receive a message with a seq lower than one you have seen previously the message has arrived out of order and safely ignored.

Order Acknowledgement

Received

{
  "type": "received",
  "sending_time": "2019-06-04T18:34:02.347857+00:00",
  "product_id": "BTC-USD",
  "order_id": "210d35ca-bfd8-419c-be37-87a556a904e1",
  "side": "buy",
  "price": "8600.25",
  "size": "10.00000000",
  "ord_type": "limit",
  "time_in_force": "FOK"
}

Open

{
  "type": "open",
  "sending_time": "2019-06-04T18:34:02.357857+00:00",
  "product_id": "BTC-USD",
  "order_id": "210d35ca-bfd8-419c-be37-87a556a904e1",
  "side": "buy",
  "price": "8600.25",
  "size": "10.00000000",
  "ord_type": "limit",
  "time_in_force": "FOK"
}

Received

Indicates a valid order has been received and is now active.

Open

Indicates an order is open and working. This message type is only sent for orders which are not immediately filled (or cancelled). This means that an open message is not sent for orders with a time_in_force of FOK.

Execution Reports

Fill

{
  "type": "fill",
  "sending_time": "2019-06-04T18:34:02.642108+00:00",
  "product_id": "BTC-USD",
  "order_id": "210d35ca-bfd8-419c-be37-87a556a904e1",
  "side": "buy",
  "fill_price": "8600.25",
  "fill_quantity": "10.00000000",
  "remaining_size": "0.00000000"
}

Done

{
  "type": "done",
  "sending_time" : "2019-06-04T18:34:02.712102+00:00",
  "product_id": "BTC-USD",
  "order_id": "210d35ca-bfd8-419c-be37-87a556a904e1",
  "side": "buy",
  "reason": "filled"
}

{
  "type": "done",
  "sending_time": "2019-09-28T18:36:25.326192+00:00",
  "product_id": "BTC-USD",
  "order_id": "0aabf91e-f65b-4277-9f66-8cb2e4985072",
  "side": "buy",
  "reason": "cancelled",
  "reason_text": "No ask liquidity at limit price 7400.00"
}

Fill

A fill message is broadcast any time an order is partially or completely filled by i2 Trading. Fill messages indicate the fill_price, which may be different from the original order's limit price, and the fill_quantity at that price. The remaining_size field indicates how much of the order is still open and working, which is 0 for completed orders.

Done

A done message is sent when an order is either filled on its full size, or cancelled. There will be no additional messages sent for the order_id after a done message.

Done messages may have an optional field, reason_text, that provides a more detailed information on the order.

USD Money Movement Rail

Welcome to the AppBrilliance, Inc. SDK Documentation and Developer Guide. The following documents will take you through the various integration points needed to allow for the AppBrilliance SDK to function across iOS and Android devices.

New iOS Project Integration

About the dev API

The dev API comes bundled as a fat iOS framework, this means that the same framework can be used on iOS simulators or in real devices while testing.

Getting Started

Create a new project to begin the integration process. The following example shows how to integrate the library into a single view iOS application.

In Xcode, select File -> New -> Project to create a new project.

New project

Select Single View App for the application type.

Project type

Pick a name, add information about your organization and choose Swift as the language.

Project details

Select a destination to save the project. This should present a window where with a project explorer found on the left-hand side.

Open a finder window and navigate to the location the framework was downloaded and drag the BoundlessAPI.framework file into the project explorer to include it in the new project as seen below:

Add framework to project

Add the framework to the Embedded Binaries list in the project settings. Do not add the same framework in the Linked Frameworks and Libraries option.

Embed binary

While still in the project settings, navigate to the Build Settings tab and search for the Enable Bitcode option and set it to "No". If the option isn't visible, click on the All filter.

Bitcode setting

Edit the info.plist file to include exceptions needed to access to a particlular bank's web servers if they are flagged as insecure by Apple. In this case, Bank of America does not support Forward Secrecy which requires an exception. The list of exceptions may be manually managed or may be copied directly from the provided library. To copy the list, locate the framework in the project explorer, right-click on it and choose Show in Finder as shown below:

Show in Finder

Once you have the finder window opened, expand the framework files to show the package contents and locate the info.plist file inside the framework:

Framework contents

Double-click on the info.plist file to open it in Xcode and highlight App Transport Security Settings, copy the contents of the highlighted key (⌘ + C).

info.plist contents

Locate your info.plist file in the project explorer and open it. Highlight the top level property Information Property List and paste the properties from your clipboard (⌘ + V).

User's info.plist

This completes the steps required to include the framework into a new project. It can now be imported and used in the source code. For example, the following line may be added to ViewController.swift file:

import BoundlessAPI

Add a property to contain the shared instance of the Manager class. The Manager class is only meant to be used this way and provides a single instance of itself through this class property.

let manager = Manager.shared

An MFA handler method is required when the FI presents a challenge. In this example, a simple one is used to watch the challenge in the console:

    func handleMFA(json:JSON){
        print("MFA received: \(json)")
        //TODO: present this information to the user and prompt for the response
    }

In the viewDidLoad method, initialize the library instance to register the global MFA Handler and to set the API keys:

    override func viewDidLoad() {
        super.viewDidLoad()

        // Your API key goes here
        manager.setAPIKey(apiKey: "0dfguQSCdbRWs12gb5p0L-WpSpyD2es3I2cDaR33xfw")

        // Your global MFA handler goes here
        manager.registerMFAhandler(handler: handleMFA)   
    }

Add UI components to receive a username and password. Implement a simple app to launch the Citibank login process, add some labels and at least two textEdit and a textView to display some output and a Login button like shown below:

Minimal login UI

Connect the UI elements with the ViewController and add an action for the Login button. The final code should look like the following:

import UIKit
import BoundlessAPI

class ViewController: UIViewController {
    let manager = Manager.shared

    @IBOutlet weak var status:UITextView!
    @IBOutlet weak var username:UITextField!
    @IBOutlet weak var password:UITextField!

    func handleMFA(json:JSON){
        print("MFA received: \(json)")
        //TODO: present this information to the user and prompt for the response
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        // Your API key goes here
        self.manager.setAPIKey(apiKey: "0dfguQSCdbRWs12gb5p0L-WpSpyD2es3I2cDaR33xfw")

        // Your global MFA handler goes here
        self.manager.registerMFAhandler(handler: handleMFA)   
    }

    @IBAction func doLogin(sender: UIButton){
        self.manager.registerSSOUser(userId: "globalSSOuserID") { response in
            print("----registerSSOUser: \(response)")
            if (response["status"].stringValue == "OK") {
                self.manager.addCredentials(fiID: "citibank", username: self.username.text! , password: self.password.text!){ res in
                    print("----addCredentials: \(res)")
                    self.status.text="Please wait..."
                    self.manager.login(fiID: "citibank") { response in
                        print("----login: \(response)")
                        self.status.text="There are \(response["accounts"].count) accounts!"
                    }
                }
            }
        }
    }
}

If completed correctly, the app should successfully access Citibank.

Existing iOS Project Integration

To integrate into an existing project follow these steps:

Drag and drop the BoundlessAPI.framework provided from within a Finder window to the project explorer to include the framework in your existing project.

Add framework to project

Next, add the framework to the Embedded Binaries list on your project settings. Don't add the same framework in the Linked Frameworks and Libraries option.

Embed binary

Now, while still in the project settings navigate to the Build Settings tab and search for the Enable Bitcode option and set it to No. If you can't find the option hit the All filter.

Bitcode setting

The final step is to edit your info.plist file to include the exceptions needed to have access to the bank web servers when those servers are flagged as insecure by Apple. In this case Bank of America does not support Forward Secrecy and we need to add an exception for that. You could keep track of this exceptions yourself or you can just copy the list of exceptions directly from the library provided. In order to do so, locate the framework in the project explorer right click on it and choose Show in Finder as shown below:

Show in Finder

Once you have the finder window opened, expand the framework files to show the package contents and locate the info.plist file inside the framework:

Framework contents

Then double click on the info.plist file to open it in Xcode and highlight App Transport Security Settings, copy the contents of the highlighted key (⌘ + C).

info.plist contents

Finally, locate your info.plist file in the project explorer and open it, then highlight the top level property Information Property List and paste the properties in your clipboard (⌘ + V).

User's info.plist

This completes the steps required to include the framework into your existing project and you can start using it in your code by importing it:

import BoundlessAPI

You can check the sample code from the integration into a new project section to start using the library.

New Android Project Integration

The Android version of the library comes packaged into an AAR file. The current build is not a fat AAR so you will need to add the extra dependencies needed an included in the Android directory, but first create a new project.

In Android Studio select File -> New -> New Project

New project

Then select a basic activity app

New project

Next configure your project, select java as the language and the minimum API level. Keep in mind that if you plan on publishing your app in Google Play you will need to select API level 26 as a minimum. New project

Once your project is created locate the libs directory inside the new directory created for your project, in this example the final directory is: /Users/sergio/AndroidStudioProjects/MyTestApplication/app/libs

Now drag and drop the .AAR files provided into this /libs directory New project

As a final step, edit the graddle.build file for your new app (the module "app" one) and change the first line in the dependencies section highlighted in blue below:

New project

into this:

implementation fileTree(dir: 'libs', include: ['*.jar','*.aar'])

Additionally in the same file you need to add the compile options for java 8, like shown below:

New project

Compile options java compileOptions { sourceCompatibility = '1.8' targetCompatibility = '1.8' }

And finally you need to add internet access permissions to your new app. Edit your manifest file to include: java <uses-permission android:name="android.permission.INTERNET"></uses-permission>

Now you can import the library in the main activity of your app like this:

import com.appbrilliance.boundlessapi.Manager;
import com.appbrilliance.boundlessapi.internal.ManagerFactory;

And initialize it in your onCreate method like this:

    Manager manager = ManagerFactory.shared(this.getApplicationContext(), "LHXuvpbOsjm1qXGwHzvC43QLksd9yWdRKTJrS5ivSkU");

    manager.registerMFAhandler(new ValueCallback<JSONObject>() {
        @Override
        public void onReceiveValue(JSONObject value) {
            Log.d("MFAHandler", value.toString());
        }
    });

Manager factory here is the way provided to create an instance of the Manager class analogous to iOS, but in this case it receives a context and the API key. You should supply this method with your key in order to activate the library. Immediately after that we are configuring a default MFA handler.

Now we can start using the library in a similar fashion as the iOS version, for example to add user credentials we can change the default onClick listener defined for the view in this test app and change the default behaviour to make it register an SSO user, add credentials and login into Bank of America like this:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        manager = ManagerFactory.shared(this.getApplicationContext(), "LHXuvpbOsjm1qXGwHzvC43QLksd9yWdRKTJrS5ivSkU");
        manager.registerMFAhandler(new ValueCallback<JSONObject>() {
            @Override
            public void onReceiveValue(JSONObject value) {
                Log.d("MFAHandler", value.toString());
            }
        });

        FloatingActionButton fab = findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                manager.registerSSOUser("testUser", new ValueCallback<JSONObject>() {
                    @Override
                    public void onReceiveValue(JSONObject value) {
                        if (value.optString("status").equals("OK")) {
                            manager.addCredentials("boa", "someuser", "somepssword", new ValueCallback<JSONObject>() {
                                @Override
                                public void onReceiveValue(JSONObject value) {
                                    manager.login("boa", new ValueCallback<JSONObject>() {
                                        @Override
                                        public void onReceiveValue(JSONObject value) {
                                            Log.d("MyTestApp", "login response:\n"+value.toString());
                                        }
                                    });
                                }
                            });
                        }
                    }
                });
            }
        });
    }

Execute your new app and in the Logcat output you will find something like this:

New project

This concludes the integration tutorial into a new Android application.

Existing Android Project Integration

To integrate into an existing project follow these steps:

Drag and drop the .AAR files provided into this /libs directory of your project New project

Edit the graddle.build file for your app and change the first line in the dependencies section highlighted in blue below:

New project

into this:

implementation fileTree(dir: 'libs', include: ['*.jar','*.aar'])

Additionally in the same file you need to add the compile options for java 8, like shown below:

New project

Compile options java compileOptions { sourceCompatibility = '1.8' targetCompatibility = '1.8' }

And finally you need to add internet access permissions to your app if it isn't there yet. Edit your manifest file to include: java <uses-permission android:name="android.permission.INTERNET"></uses-permission>

Now you can import the library in the main activity of your app like this:

import com.appbrilliance.boundlessapi.Manager;
import com.appbrilliance.boundlessapi.internal.ManagerFactory;

After this you finished integrating the library to your project, you can check the sample code from the integration into a new project section to start using the library.

Features discovery

After following one of the previous tutorials you were able to integrate the library with your new or existing project, now you will learn how to discover what institutions and features are enabled for your license of the library. But first let's see again the steps done in the example to understand what's going on.

    manager = Manager.shared

    override func viewDidLoad() {
        super.viewDidLoad()

        // Your API key goes here
        self.manager.setAPIKey(apiKey: "0dfguQSCdbRWs12gb5p0L-WpSpyD2es3I2cDaR33xfw")

        // Your global MFA handler goes here
        self.manager.registerMFAhandler(handler: handleMFA)   
    }

    @IBAction func doLogin(sender: UIButton){
        self.manager.registerSSOUser(userId: "globalSSOuserID") { response in

            if (response["status"].stringValue == "OK") {
                self.manager.addCredentials(fiID: "citibank", username: self.username.text! , password: self.password.text!){ res in

                    self.status.text="Please wait..."
                    self.manager.login(fiID: "citibank") { response in
                        // At this point we are logged in
                    }
                }
            }
        }
    }

The manager class can only be accessed trough its shared class property. In the example we first access this instance to set the API key provided and the MFA handler function, this two steps are mandatory and both methods setAPIKey and registerMFAHandler in its two variants are the only methods that don't have any return values. All the other methods return a JSON response either directly or trough the callback you provide when calling the methods. Said JSON response will contain a status that can either be OK or ERROR and if there is an error message to explain the error an errorMessage key with the present in the JSON response with an error description. Any return value expected due to the method call will be inside this JSON response as well when the status is OK.

Returning to the example we see that after registering the MFA handler the use of the library begins by registering a Single Sign On User, the reason for this is that since you are able to login to multiple financial institutions at the same time it is practical to have a single sign on in order to access all your different online bankings. This also explain the reason to add credentials for a given institution before doing the login.

But how can we tell what institutions are enabled? In order to know the available FIs you can use the listAvailableFIs method, sample output as follows:

{
  "fis" : [
    {
      "name" : "Bank of America",
      "fiid" : "boa"
    },
    {
      "name" : "Citibank",
      "fiid" : "citibank"
    }
  ]
}

The fiid from this list is what we use to identify a given FI in all the method calls. This list contains all the available FIs you can currently use with your license of the library. After this first step you can start adding credentials for this FIs using the addCredentials method, and login using the login method. After you add credentials the library stores the credentials inside the keychain in encrypted form in this way the next time you register the same SSO user it will load automatically all the available credentials from the keychain. In order to list the FIs that the current SSO user has credentials for you need to use the listUserFIs method, sample output:

{
  "fis" : [
    {
      "name" : "Bank of America",
      "fiid" : "boa"
    }
  ]
}

With this you can use the login method to effectively login into Bank of America.

Once you know the available FIs to login you can list what actions are enabled for each FI by using the listAvailableActions method, sample output as follows for Bank of America.

[
  "transactions",
  "refreshBalances",
  "answerMFA",
  "setupTransfer",
  "transactionDetails",
  "scheduleTransfer"
]

Now that we have a list of potential actions to execute, we need to know the parameters needed for each one, in order to get that information you can use the method listParametersForAction, sample output for Bank of America and the action transactions:

[
  "accountId"
]

At this point we know that Bank of America is enabled in this example, that there is an action defined called transactions and that said action receives an accountId as a parameter. The way of passing parameters to an action is using a json payload with all the required parameters, to continue this example to execute the action transactions you would use a JSON payload as follows:

{
  "accountId" : "f9d071ce-ea75-67ce-6a5d-6250a6e874ff"
}

Where accountId is the ID of an account returned by either the login method or the refreshBalances action.

By using this method you can identify what actions are available for each available FI in your license.

Interface introduction

While using the library every call to the API returns a JSON object with a status and a corresponding result. If the status is OK the JSON response will contain a nested key with the result of the call. When the status is ERROR an optional key errorMessage could exist in the object with a brief description of the error.

Generic examples of outputs:

Example output when status is OK

{
  "status" : "OK",
  "transactions" : [
    {
      "id" : "286cd69e-dcda-c328-c39f-83d90d143c07",
      "description" : "Online Banking transfer to SAV 3827 Confirmation# 1107098185",
      "amount" : "-3.00",
      "date" : "03\/08\/2019",
      "status" : "Cleared",
      "balance" : "89.25"
    },
    {
      "id" : "25f0de28-d961-8295-aa05-5b28053f518a",
      "description" : "BKOFAMERICA ATM 02\/20 #000003307 DEPOSIT LOUETTA SPRING TX",
      "amount" : "100.00",
      "date" : "02\/20\/2019",
      "status" : "Cleared",
      "balance" : "100.00"
    }
  ]
}

Example output when status is ERROR

{
  "status" : "ERROR",
  "errorMessage" : "No credentials found for specified FI",
  "errorCode" : "E00704" 
}

Error Responses

During the normal execution of the library whenever an error occurs you will receive an error reponse in the form:

{
  "status": "ERROR",
  "errorMessage": "Unable to access payments",
  "errorCode": "E01201"
}

The errorMessage is a small description of what happened and the errorCode is a categorization of the error that is provided when available, this means if the library is able to determine what failed and the reason it is categorized in this way. Instead if the error is a variable error provided by the FI (i.e. "amount must be less than $100.000") the error code will default to E00006 "Uncategorized error".

The following is the list of error codes you can receive and need to handle in your host app:

Error Code Error Description
E00000 Unknown error
E00001 Network error
E00002 Timeout
E00003 Reload needed
E00004 [FI] System is temporarily unavailable. Please try again later
E00005 [FI] Information for this account is temporarily unavailable. Please try again later.
E00006 Uncategorized error
E00010 Wrong credentials
E00011 Account locked
E00012 Wrong answer
E00100 Failed to load transaction details
E00101 A transaction details request is still being processed
E00102 Transaction not found
E00103 Account not found
E00104 Transfer not found
E00105 Payee not found
E00106 Pending link not found
E00107 Payment not found
E00300 Transfer setup is not complete
E00301 Payment setup is not complete
E00302 External transfer setup is not complete
E00303 Failed to setup transfer
E00350 Billpay is already enabled for this account
E00351 Billpay enroll setup is not complete
E00400 Invalid frequency
E00401 Invalid cancel option
E00402 Invalid "from" account
E00403 Invalid "to" account
E00404 Invalid service id
E00405 Amount error
E00406 Date error
E00407 Invalid send time
E00408 Invalid transfer type
E00409 Illegal testDeposits: Must be in the form: "0.50"
E00411 No eligible billpay account for the given payee
E00412 No available accounts to transfer to
E00413 No available accounts to transfer from
E00500 Could not select from account
E00510 Failed to schedule payment, please reset payment and try again.
E00511 Unable to cancel payment
E00512 Could not verify pending link
E00513 Unable to cancel transfer
E00540 Failed to launch verification process
E00550 Could not retrieve transfer confirmation data
E00599 Manual steps required trough online banking
E00700 No MFA challenge in progress for the given FI
E00701 No MFA Handler set for institution
E00702 No SSO user registered
E00703 No MFA Handler set
E00704 No credentials found for specified FI
E00705 Action not found
E00706 FI not found
E00709 Invalid JSON input
E00710 Invalid JSON output
E00711 Already executing an action
E00712 Action not allowed during MFA challenge
E00750 Error adding credentials
E00751 Error registering SSO user
E00752 Error executing action
E00753 Error removing credentials

The following is the list of errors you can receive and you need to inform AppBrilliance about it to handle the errors, opening a support ticket based on it is encouraged:

Error Code Error Description
E01000 Fingerprint error
E01200 Unable to access billpay
E01201 Unable to access payments
E01202 Error fetching payment list
E01203 Error fetching transfer list
E01204 Error fetching transaction list
E01205 Could not fetch pending account links
E01206 Unable to access overview
E01223 Could not access transfers
E01224 Could not access external accounts
E01226 Could not identify service options
E01227 Could not identify send time options
E01507 Error merging FIs
E01508 Error merging actions
E01510 Error deleting old MFA data
E09000 Section not configured

Accessing Static Data

Different financial institutions have different requirements for write operations. This creates a problem when building an application to access multiple banks since it is not always trivial to create an adaptive UI to present to the user for a transfer/payment for instance. In order to provide support in the creation of such a UI, the parameters required in the write operations that have variations are provided in two separate groups: static data and dynamic data.

Dynamic data can be extracted using two web services provided by AppBrilliance to retrieve in JSON format: * The list of enabled FIs for your company * The list of static data needed to create the UI for all the write operations for a given FI

To access the list of FIs associated with your API KEY you need to perform a GET operation in the following endpoint, replace YOUR_API_KEY with the actual key:

https://dev.appbrilliance.com/api/listFIs/YOUR_API_KEY

A sample output of calling the service is:

{
  "fis": [
    {
      "fiid": "ABI111907979",
      "name": "Texas Bank Financial",
      "url": "https://www.texas-bank.com",
      "routingNumber": "111907979",
      "last_updated": "2019-12-07T08:27:05.514336"
    }
  ]
}

With the information from this service, you can call a second service to retrieve the static data associated with this FI:

The second service is accessible performing a GET operation too, replace YOUR_API_KEY with the actual key provided and FIID with one of the fiid returned by the previous service:

https://dev.appbrilliance.com/api/getData/YOUR_API_KEY/FIID

A sample output would look like this:

{
  "data": {
    "setupTransfer": {
      "parameters": {
        "frequency": {
          "type": "select",
          "name": "frequency",
          "displayName": "Frequency",
          "required": true,
          "options": [
            {
              "displayName": "Just Once",
              "id": "0"
            },
            {
              "displayName": "Weekly",
              "id": "1",
              "triggers": [
                "repeatUntil",
                "afterHoliday"
              ]
            },
            {
              "displayName": "Every Other Week",
              "id": "2",
              "triggers": [
                "repeatUntil",
                "afterHoliday"
              ]
            },
            {
              "displayName": "Monthly",
              "id": "3",
              "triggers": [
                "repeatUntil",
                "afterHoliday"
              ]
            },
            {
              "displayName": "Every Other Month",
              "id": "4",
              "triggers": [
                "repeatUntil",
                "afterHoliday"
              ]
            },
            {
              "displayName": "Every 3 Months",
              "id": "5",
              "triggers": [
                "repeatUntil",
                "afterHoliday"
              ]
            },
            {
              "displayName": "Every 6 Months",
              "id": "6",
              "triggers": [
                "repeatUntil",
                "afterHoliday"
              ]
            },
            {
              "displayName": "Yearly",
              "id": "7",
              "triggers": [
                "repeatUntil",
                "afterHoliday"
              ]
            }
          ]
        },
        "repeatUntil": {
          "type": "select",
          "name": "repeatUntil",
          "displayName": "Repeat Until",
          "options": [
            {
              "id": "canceled",
              "displayName": "Until I cancel these transfers"
            },
            {
              "id": "endDate",
              "displayName": "Until a given date",
              "triggers": [
                "endDate"
              ]
            }
          ]
        },
        "endDate": {
          "type": "date",
          "name": "endDate",
          "displayName": "End Date"
        },
        "afterHoliday": {
          "type": "checkbox",
          "name": "afterHoliday",
          "displayName": "After Holiday",
          "option": "Payments that fall on a holiday or weekend will be paid the next available business day"
        },
        "date": {
          "type": "date",
          "name": "date",
          "displayName": "Date",
          "required": true
        },
        "amount": {
          "type": "amount",
          "name": "amount",
          "displayName": "Amount",
          "required": true
        },
        "memo": {
          "type": "text",
          "name": "memo",
          "required": false,
          "displayName": "Memo",
          "maxLength": 110
        }
      },
      "suggestedOrder": [
        "frequency",
        "date",
        "amount",
        "memo"
      ],
      "notes": []
    },
    "billpaySetupPayment": {
      "parameters": {
        "date": {
          "type": "date",
          "name": "date",
          "displayName": "Date",
          "required": true
        },
        "amount": {
          "type": "amount",
          "name": "amount",
          "displayName": "Amount",
          "required": true
        },
        "memo": {
          "type": "text",
          "name": "memo",
          "required": false,
          "displayName": "Memo",
          "maxLength": 25
        }
      },
      "suggestedOrder": [
        "date",
        "amount",
        "memo"
      ],
      "notes": []
    },
    ...
 }
}

The adobe example is truncated a limited to two actions for practical reasons.

The data returned contains an object (map) of actions with 3 main keys in it parameters, suggestedOrder and notes.

Parameters is also an object (map) of parameters where the key matches the parameter name expected by the action. There could be more defined parameters than the ones needed for a specific call. For instance different recurring cases can trigger different extra parameters.

To define which parameters to use when building the UI you need to start with the suggestedOrder array. This array contains the names of the parameters that will always be required by the action, so you can start with it.

For example, using the adobe output for setupTransfer, the suggested order in this case is:

{
      ...,
      "suggestedOrder": [
        "frequency",
        "date",
        "amount",
        "memo"
      ]
}

The first parameter is frequency, we use this label to access the parameters object and extract the frequency associated data:

{
  "frequency": {
    "type": "select",
    "name": "frequency",
    "displayName": "Frequency",
    "required": true,
    "options": [
      {
        "displayName": "Just Once",
        "id": "0"
      },
      {
        "displayName": "Weekly",
        "id": "1",
        "triggers": [
          "repeatUntil",
          "afterHoliday"
        ]
      },
      {
        "displayName": "Every Other Week",
        "id": "2",
        "triggers": [
          "repeatUntil",
          "afterHoliday"
        ]
      },
      {
        "displayName": "Monthly",
        "id": "3",
        "triggers": [
          "repeatUntil",
          "afterHoliday"
        ]
      },
      {
        "displayName": "Every Other Month",
        "id": "4",
        "triggers": [
          "repeatUntil",
          "afterHoliday"
        ]
      },
      {
        "displayName": "Every 3 Months",
        "id": "5",
        "triggers": [
          "repeatUntil",
          "afterHoliday"
        ]
      },
      {
        "displayName": "Every 6 Months",
        "id": "6",
        "triggers": [
          "repeatUntil",
          "afterHoliday"
        ]
      },
      {
        "displayName": "Yearly",
        "id": "7",
        "triggers": [
          "repeatUntil",
          "afterHoliday"
        ]
      }
    ]
  }
}

Each parameter definition will contain several pieces of information: * name: the formal parameter name to be used when calling the action, it matches the outer key in the parameters object. * displayName: label to use when building the UI element if applicable, it can also be used to define a placeholder or similar depending on your specific UI design. * type: the parameter type. This defines the final UI element to use, for instance in this example it is a select which means you can use a dropdown style of element or a floating list of elements to present to the use to choose from. * required: a flag indicating if the presence of the parameters needs to be enforced. For triggered parameters it is ignored since triggered parameters are always required. * options: in this example, since the parameters is of type select it contains an array of options to populate the select. Each option contains its own id and displayName to generate the UI. It is this id present in the options that needs to be used as the value of the parameter when calling the action. This rule applies only to parameters that contain an options array.

It is very important the key triggers present in some of the options for the frequency parameter. It means that if the user selects that option, let's say option with id = 4 and displayName = "Every Other Month" then in the adaptive UI you need to request the user to input some extra parameters, for this case those parameters are:

    "triggers": [
      "repeatUntil",
      "afterHoliday"
    ]

Using this array of triggered parameters you use those keys in the parameters object for the action to generate new UI elements for repeatUntil and afterHoliday:

"repeatUntil": {
  "type": "select",
  "name": "repeatUntil",
  "displayName": "Repeat Until",
  "options": [
    {
      "id": "canceled",
      "displayName": "Until I cancel these transfers"
    },
    {
      "id": "endDate",
      "displayName": "Until a given date",
      "triggers": [
        "endDate"
      ]
    }
  ]
},
"afterHoliday": {
  "type": "checkbox",
  "name": "afterHoliday",
  "displayName": "After Holiday",
  "option": "Payments that fall on a holiday or weekend will be paid the next available business day"
}

From this configuration we receive that after the user selects the option with id = 4 for the frequency, two new parameters are required to finish the setup: * repeatUntil: is also of type select, the option with id = "endDate" triggers yet another extra parameter called endDate * afterHoliday: is checkbox (true/false). Checkboxes have a single option parameters that is a self explanatory message to present to the user next to the checkbox. In this case the displayName is provided in case the design contains group labels or similar.

Similar to the triggers key optionally present in some options, there could be a triggersInline key that instead of containing an array of parameters names will contain an array of full parameters definitions to be added inline when that option is selected. Both keys could coexist in some scenarios.

Finally, the array called notes contains any information relevant to the action including but not limited to: disclosures, fees, processing times or rules, etc.

This covers the static data retrieval and handling when building an application. Both services provided here are to be used for development purposes and not to be used directly from within your application. You can cache/mirror the information provided by the services in your own servers and use those mirrors in your production application.

IMPORTANT NOTE: remember that the disclosures and legal notes as well are no replacement for your own company's legal notes and disclosures. It is provided as a guide or complement but you shouldn't rely solely on this notes. The same happens with the fee key as it is no replacement for the bank's own information.

Dynamic Data

Similar to the static data case, the dynamic data is used to obtain the remaining information needed to build the UI for a given action. Only present and correlated to a variadic action like billpaySetupPayment, which will be used as an example here.

When trying to build the UI to make a payment you will need the static data explained in the previous section and the data returned by getBillpayDynamicData, a sample output from the latter is:

{
  "status": "OK",
  "billpayDynamicData": {
    "parameters": {
      "fundingAccount": {
        "name": "fundingAccount",
        "displayName": "Funding Account",
        "type": "select",
        "required": true,
        "options": [
          {
            "id": "77827",
            "balance": "99",
            "displayName": "Checking",
            "maskedNumber": "*6437",
            "accountNumber": "2086437",
            "triggersInline": [
              {
                "name": "payee",
                "displayName": "Payee",
                "type": "select",
                "required": true,
                "options": [
                  {
                    "id": "1",
                    "displayName": "Eric",
                    "maskedNumber": "*3296",
                    "accountNumber": "280213296",
                    "nextDate": "12/18/2019"
                  },
                  {
                    "id": "2",
                    "displayName": "Eric",
                    "maskedNumber": "*3296",
                    "accountNumber": "280213296",
                    "nextDate": "12/18/2019"
                  }
                ]
              }
            ]
          }
        ]
      }
    },
    "notes": [],
    "suggestedOrder": [
      "fundingAccount",
      "payee"
    ]
  }
}

The output from the action has the same format as the data returned by the web service used to access the static data, the difference is that this data can only be generated once the application is running and a user session has been established to a given FI (i.e. the user has successfully logged into the bank).

The final UI to be generated needs to use the combined information from this dynamic action plus all the information contained in the static data for the given action, in this case billpaySetupPayment. The order of the parameter sets presented to the user (dynamic-static or static-dynamic) is irrelevant, but in most scenarios using dynamic-static is best.

Parameters Definitions

All the parameters definitions, either static or dynamic, have the following properties always: * name: Formal name for the parameters to be sent in all subsequent calls to the action. * displayName: An example display name to use as a label for the widget presented to the user when requesting the data. * type: The type of input (i.e. widget) to use when displaying this information to the user. The type can also trigger extra validation in the UI and this is encouraged.

The required key has an implied value of true when it is not present and it is defined in a suggestedOrder array or in a triggers array.

There is also additional information always present depending on the type of parameter, for instance a select type of parameter always contains an options key to fill some sort of dropdown or similar to present to the user. Said options are always an array of options and the format of each option in the array will always contain an id and displayName to fill the UI element. The displayName is the label you need to use for the element or the placeholder. The id is the value you need to use for the parameter when calling the associated action.

Sample dynamic data to be used for setupTransfer, this is the result of calling getTransfersDynamicData json { "status": "OK", "transfersDynamicData": { "parameters": { "accountFrom": { "name": "accountFrom", "displayName": "Account From", "type": "select", "required": true, "options": [ { "id": "77827", "balance": "99", "displayName": "Checking", "maskedNumber": "*6437", "accountNumber": "2086437", "triggersInline": [ { "name": "accountTo", "displayName": "Account To", "type": "select", "required": true, "options": [ { "id": "77845", "displayName": "Savings", "maskedNumber": "*9908", "accountNumber": "3019908", "nextDate": "12/16/2019" } ] } ] }, { "id": "77845", "balance": "50.03", "displayName": "Savings", "maskedNumber": "*9908", "accountNumber": "3019908", "triggersInline": [ { "name": "accountTo", "displayName": "Account To", "type": "select", "required": true, "options": [ { "id": "77827", "displayName": "Checking", "maskedNumber": "*6437", "accountNumber": "2086437", "nextDate": "12/16/2019" } ] } ] } ] } }, "notes": [], "suggestedOrder": [ "accountFrom", "accountTo" ] } }

This means we need to populate a dropdown that displays the displayName (or displayName and balance) for the user to select the accounts from that list and once the selection is done you fill each parameter with the id of the selected option for each select object.

Different parameters of type select can have different data in each option, but displayName and id will always exist.

The full list of parameters types are:

Type Description
select As in the previous example will resume later with more option types.
checkbox A true (checked) or false (unchecked) value.
text Simple edit input. Can include a maxLength key to denote the maximum allowed input (for validation purposes).
numeric Numeric only input positive integers expected.
date A full date in the format MM/DD/YYYY. Sometimes this type of parameter also contains a nextValue key with a date in it, this date represent the closest possible date you can select. For instance when setting up a regular billpay payment you can't select a date prior to the value in nextValue.
day The day part of a full date in DD format.
month The month part of a full date in MM format.
year The year part of a full date in YYYY format.
cardNumber A credit/debit card number.
testDeposit An amount ranging from 0.00 to 0.99 in 0.XX format.
csc A card security code.
amount An amount in the format XXXXXXXXXXXX.YY
id An id representing in-context information. For example if the parameter name is payeeId of type id you need to provide a previously gathered payeeId as a result of calling the action billpayGetPayeeList.
email An email address.
address An address, could be an address line 1 or 2.
ssn Social security number.
state State, full name.
state2 State abbreviation (max length 2).
password A password.

Types of options for select type of parameters: * For billpay accounts selections (i.e. when there is more than one checking account) the list of accounts to select from can include an nextDate denoting that by using that account the earliest possible date you can use to schedule a payment is that date - use this additional field for validation purposes. It can also include a balance. * For external transfers the list can include a balance, if some accounts have an empty balance value in the accountFrom parameters this means the FI supports pulling money from that account into this FI. It also means that said account is from a different FI, hence the balance can not be retrieved.

Login

For most banks the login is a special case of method because it will not return a result until the login process is complete. This means that any MFA/2FA challenge will happen in between. While one of said challenges is fired in the library what happens in practice is a pause of the login process until the challenge is completed.

The input to the action is also special in the sense that it can only be controlled indirectly since the only argument in the call to login is the FI id, this means that in order to login to a given FI you first need to add the credentials for said FI using the addCredentials method.

Once the login is complete the response from the action is an account overview (refreshBalances action) which contains a key indicating the account is loggged in, information about the billpay enabled status and a list of accounts with account IDs, names and balances:

Example login response

{
  "loggedIn" : true,
  "userSegment" : " Blue",
  "status" : "OK",
  "accounts" : [
    {
      "currentBalance" : "$26.27",
      "accountNumber" : "",
      "accountName" : "Checking ...7321",
      "id" : "721df899-11f4-9818-cd89-c662b0441941",
      "availableBalance" : "$26.27",
      "routingNumber" : ""
    },
    {
      "currentBalance" : "$9.49",
      "accountNumber" : "",
      "accountName" : "Citi Savings Account ...7334",
      "id" : "99c88944-bac5-c504-58c0-63e003119aa4",
      "availableBalance" : "$9.49",
      "routingNumber" : ""
    }
  ]
}

Example error response

{
  "status": "ERROR",
  "errorMessage": "Wrong credentials",
  "errorCode": "E00010"
}

For more information about the output of login regarding the list of accounts read the refreshBalances action documentation.

Refresh Balances

This action is called with no parameters after the login is successful and can be called again when needed.

The response is a JSON object and includes always a list of accounts where each account is a JSON object with accountID, accountName (that can be seen as a display name) and availableBalance. In certain cases it also contains a currentBalance.

Example parameters payload to refreshBalances json {}

Example of refreshBalances output for Citibank json { "accounts" : [ { "currentBalance" : "$26.27", "accountNumber" : "", "accountName" : "Checking ...7321", "id" : "721df899-11f4-9818-cd89-c662b0441941", "availableBalance" : "$26.27", "routingNumber" : "" }, { "currentBalance" : "$9.49", "accountNumber" : "979797979721", "accountName" : "Citi Savings Account ...7334", "id" : "99c88944-bac5-c504-58c0-63e003119aa4", "availableBalance" : "$9.49", "routingNumber" : "113193532" } ], "status" : "OK", "userSegment" : " Blue" }

In some cases the output will contain additional information if available, in the adobe example userSegment contains the user segment assigned for Citibank to this user. This additional information is not going to be present always and varies from bank to bank.

The IDs returned for each account are assigned the first time an account is seen based on its display name and stored in peristent storage for subsequent use. This ID changes between installations meaning that from different devices using the same account you can receive information about the same account with two different IDs, this is because there is no reliable information and absolute information at this point to determine a more persistent ID. However, after you use the getAccountNumber action and a definitive account number/routing information can be associated with the account it is also stored and from that point on you will receive the accountNumber and routingNumber along with the ID.

As an example after using the getAccountNumber action for the account IDs from the previous sample the next call to the action refreshBalances gives the following results:

{
  "accounts" : [
    {
      "currentBalance" : "$26.27",
      "accountNumber" : "979797979721",
      "accountName" : "Checking ...7321",
      "id" : "721df899-11f4-9818-cd89-c662b0441941",
      "availableBalance" : "$26.27",
      "routingNumber" : "113193532"
    },
    {
      "currentBalance" : "$9.49",
      "accountNumber" : "979797979722",
      "accountName" : "Citi Savings Account ...7334",
      "id" : "99c88944-bac5-c504-58c0-63e003119aa4",
      "availableBalance" : "$9.49",
      "routingNumber" : "113193532"
    }
  ],
  "status" : "OK",
  "userSegment" : " Blue"
}

In this way you can use the extra information as a more persistent ID during the lifespan of this app installation and avoid making multiple calls to getAccountNumber.

Get Account Number

Use the action getAccountNumber to retrieve the account number and routing information for a given account ID. The information provided by this action is persisted and associated with the account ID for that account. This means that it only needs to be called once per application install for any new account discovered. Further analysis needs to be done in order to determine if a given account is new or is an old account renamed, said analysis can be done by using the result of this action.

Sample input parameters:

{
  "accountId" : "721df899-11f4-9818-cd89-c662b0441941"
}

Which yields the following sample output on success: json { "accountNumber" : "979797979721", "routingNumber" : "113193532", "status" : "OK" }

If the accountId provided is not found the action will return an error like:

{
  "status": "ERROR",
  "errorMessage": "Account not found",
  "errorCode": "E00103"
}

Sometimes it is possible that the source system has problems accessing the information, in such instances an error like in the following example is returned:

{
  "status": "ERROR",
  "errorMessage": "[FI] Information for this account is temporarily unavailable. Please try again later.",
  "errorCode": "E00005"
}

When the action is able to fetch the acount number this information is stored in persistent storage and appended to the already existing information about the accountId, which makes subsequent calls to login/refreshBalances contain this new information in the future.

Transactions

Use the transactions action to list the history of transactions for a given account, this action must be called with an accountId as parameter and returns a list of transactions for that account. The accountId to be used is the id returned for accounts from a login or refreshBalances action.

The action also checks the description of each transaction looking for test deposits from known sources to detect an active account linking process from another bank to this specific account. This information is provided in a separate key called accountLinkInfo and contains a list of transactions in the same format as the transactions output but with an added fiid key indicating the originating financial institution for the test deposits.

Sample input: json { "accountId" : "39da51ac-6bcb-1b9b-8c31-4b76edea4d84" }

Sample output with no account linking information: json { "accountLinkInfo" : [], "transactions" : [ { "id" : "e3278c69-858c-48ec-4893-433f8b84fde2", "balance" : "$16.27", "date" : "04\/01\/2019", "description" : "Monthly Service Fee", "amount" : "-$25.00" }, { "id" : "c53c18e0-b064-8a1d-425d-6418d21a350e", "balance" : "$41.27", "date" : "03\/25\/2019", "description" : "Debit Card Purchase 03\/20 09:57a #1824 STARBUCKS STORE 27233 DRIPPING SPRI TX 19081", "amount" : "-$2.65" }, { "id" : "168014cf-ded3-8df1-2a55-bcc7241169f1", "balance" : "$43.92", "date" : "03\/15\/2019", "description" : "Debit Card Purchase 03\/13 07:50p #1824 H-E-B #611 DRIPPING SPRI TX 19073", "amount" : "-$18.45" }, { "id" : "9e76e936-5d37-9d3e-1234-717ef5ab3dfc", "balance" : "$62.37", "date" : "03\/14\/2019", "description" : "Debit Card Purchase 03\/12 07:32p #1824 REIDS LAUNDRY DRY CLE AUSTIN TX 19072", "amount" : "-$42.22" }, { "id" : "286cd69e-dcda-c328-c39f-83d90d143c07", "balance" : "$104.59", "date" : "03\/12\/2019", "description" : "Debit Card Purchase 03\/08 08:03a #1824 STARBUCKS STORE 06203 AUSTIN TX 19070", "amount" : "-$11.64" }, { "id" : "151bca56-b8e9-4817-a2ac-52c46a597c49", "balance" : "$116.23", "date" : "03\/11\/2019", "description" : "Debit Card Purchase 03\/07 07:54p #1824 REIDS LAUNDRY DRY CLE AUSTIN TX 19067", "amount" : "-$16.89" }, { "id" : "25f0de28-d961-8295-aa05-5b28053f518a", "balance" : "", "date" : "03\/11\/2019", "description" : "Debit Card Purchase 03\/06 08:06a #1824 STARBUCKS STORE 06203 AUSTIN TX 19067", "amount" : "-$15.00" }, { "id" : "272e1122-9929-92e4-09e1-c7ceb0149988", "balance" : "$148.12", "date" : "03\/08\/2019", "description" : "Debit Card Purchase 03\/06 01:29p #1824 EINSTEIN BROS BAGELS19 AUSTIN TX 19066", "amount" : "-$20.74" }, { "id" : "9862632d-4f46-c784-dc49-2a19012535f3", "balance" : "", "date" : "03\/08\/2019", "description" : "Debit Card Purchase 03\/05 07:40a #1824 CHICK-FIL-A #0923 AUSTIN TX 19066", "amount" : "-$18.67" }, { "id" : "a37a4d31-598a-30d7-8df6-bfd5b0c5d107", "balance" : "", "date" : "03\/08\/2019", "description" : "Debit Card Purchase 03\/06 06:03p #1824 VISIONWORKS #258 AUSTIN TX 19066", "amount" : "-$8.65" }, { "id" : "ecd99c89-3eb1-d6cf-0e96-00bebb6d3109", "balance" : "$196.18", "date" : "03\/07\/2019", "description" : "Transfer to Citi Savings 06:03a #1824 ONLINE Reference # 010025", "amount" : "-$1.00" }, { "id" : "6e125fb3-ed53-85b8-2e58-8e433c150a8d", "balance" : "$197.18", "date" : "03\/05\/2019", "description" : "Mobile Deposit", "amount" : "$165.90" }, { "id" : "2ef02799-4d95-82e1-3b3b-d525ba36aa13", "balance" : "$31.28", "date" : "03\/01\/2019", "description" : "Mobile Deposit", "amount" : "$50.00" }, { "id" : "6b9a9ee1-be84-5140-f507-311fb3823dde", "balance" : "", "date" : "03\/01\/2019", "description" : "Monthly Service Fee", "amount" : "-$25.00" }, { "id" : "19932faf-8836-fa51-ff26-d3c74a6b38a5", "balance" : "$6.28", "date" : "02\/28\/2019", "description" : "Transfer to Citi Savings 11:48a #1824 ONLINE Reference # 001082", "amount" : "-$0.50" }, { "id" : "ea677399-be8d-26d4-6976-740d975331df", "balance" : "$6.78", "date" : "02\/06\/2019", "description" : "Transfer to Citi Savings 08:45a #1824 ONLINE Reference # 001204", "amount" : "-$0.01" }, { "id" : "e5debca5-3cf0-5d92-2aed-445a03dd75b0", "balance" : "$6.79", "date" : "01\/31\/2019", "description" : "Monthly Service Fee", "amount" : "-$25.00" }, { "id" : "846621bf-1d1c-294f-8340-e7d39f93a94d", "balance" : "$31.79", "date" : "01\/15\/2019", "description" : "Transfer to Citi Savings 03:32p #1824 ONLINE Reference # 000937", "amount" : "-$1.07" }, { "id" : "f0ac0ad2-b7c6-c70f-e442-e2f617452f0a", "balance" : "", "date" : "01\/15\/2019", "description" : "Transfer to Citi Savings 09:37a #1824 ONLINE Reference # 000084", "amount" : "-$0.01" }, { "id" : "b2d74a1c-1caa-c08b-4264-8acffbe563f2", "balance" : "$32.87", "date" : "01\/10\/2019", "description" : "Transfer to Citi Savings 05:02p #1824 ONLINE Reference # 000473", "amount" : "-$0.01" }, { "id" : "335f1f34-0452-64eb-967d-c1e9f5e1aa9e", "balance" : "$32.88", "date" : "01\/04\/2019", "description" : "Mobile Deposit", "amount" : "$75.00" }, { "id" : "c347d0fe-08c7-e359-fa0d-870fcd9a4381", "balance" : "$42.12", "date" : "01\/02\/2019", "description" : "Overdraft Fee", "amount" : "-$34.00" }, { "id" : "20362022-dc91-c09e-b5ea-fd86c7aaefd6", "balance" : "$8.12", "date" : "12\/31\/2018", "description" : "Monthly Service Fee", "amount" : "-$25.00" }, { "id" : "56f988aa-8da7-f461-89fb-8654f7395343", "balance" : "$16.88", "date" : "12\/12\/2018", "description" : "Transfer to Citi Savings 12\/11 11:17p #1824 ONLINE Reference # 002153", "amount" : "-$0.01" }, { "id" : "5686dad6-d0c4-5c84-f6df-6bf345e2f763", "balance" : "", "date" : "12\/12\/2018", "description" : "Transfer to Citi Savings 02:45p #1824 ONLINE Reference # 000329", "amount" : "-$0.01" }, { "id" : "08b2f34b-b52d-b9a1-cfd8-ad9ccc14cf86", "balance" : "", "date" : "12\/12\/2018", "description" : "Transfer to Citi Savings 12:51p #1824 ONLINE Reference # 002384", "amount" : "-$0.01" }, { "id" : "b4afba70-4567-f92f-f761-4e3a369ceabc", "balance" : "$16.91", "date" : "12\/11\/2018", "description" : "Mobile Deposit", "amount" : "$20.00" }, { "id" : "9c77d049-9892-704e-856a-dddd99e51b78", "balance" : "", "date" : "12\/11\/2018", "description" : "Transfer to Citi Savings 10:13a #1824 ONLINE Reference # 001934", "amount" : "-$5.00" }, { "id" : "3465581d-76ac-b4e9-bcb4-094a917131eb", "balance" : "$1.91", "date" : "12\/03\/2018", "description" : "Monthly Service Fee", "amount" : "-$25.00" }, { "id" : "2f5e2881-eccd-1645-6a07-f34f95b03108", "balance" : "", "date" : "12\/03\/2018", "description" : "Transfer From Citi Savings 02:55p #1824 ONLINE Reference # 000501", "amount" : "$14.00" }, { "id" : "822d2913-3721-67d5-046d-bad2b9b599df", "balance" : "", "date" : "12\/03\/2018", "description" : "Transfer From Citi Savings 02:56p #1824 ONLINE Reference # 000503", "amount" : "$1.00" }, { "id" : "15835b49-9259-762a-3029-7da0a207c3c4", "balance" : "", "date" : "12\/03\/2018", "description" : "Transfer to Citi Savings 02:55p #1824 ONLINE Reference # 000535", "amount" : "-$0.01" }, { "id" : "721777bc-a771-7ced-2650-d2f9947f52ac", "balance" : "$11.92", "date" : "11\/26\/2018", "description" : "Transfer From Citi Savings 05:58p #1824 ONLINE Reference # 002096", "amount" : "$1.00" }, { "id" : "a2e3fb43-0228-7339-6e77-17f47bc42933", "balance" : "$10.92", "date" : "11\/07\/2018", "description" : "Transfer to Citi Savings 02:17p #1824 ONLINE Reference # 001026", "amount" : "-$0.01" } ], "status" : "OK" }

The ID for each transaction is transient, and in every call for the same account you will receive new IDs, you should never store the IDs for later use, instead you should guide the flow of your application as you normally use this information: having a view with a list of accounts you can tap an account and view the list of transactions, and after that you can tap on each transaction and view the transactionDetails. When refreshing the list of transactions you need to use the new ids to retrieve the transaction details using the transactionDetails action.

Sample output with account linking information: json { "status" : "OK", "accountLinkInfo" : [ { "fiid" : "citibank", "amount" : "0.45", "balance" : "78.24", "status" : "Processing", "id" : "16e281ba-d1c4-3569-2f09-573d52805e26", "description" : "ACH CREDIT CITIBANK XFER IIT_CREDIT ON 05\/01", "date" : "Processing" }, { "fiid" : "citibank", "amount" : "0.51", "balance" : "77.79", "status" : "Processing", "id" : "8ebd4980-f856-1118-f17a-b72d277fe1ed", "description" : "ACH CREDIT CITIBANK XFER IIT_CREDIT ON 05\/01", "date" : "Processing" } ], "transactions" : [ { "status" : "Processing", "balance" : "77.28", "id" : "1e52faab-fb62-e773-85fd-d055fe713118", "date" : "Processing", "description" : "ACH HOLD CITIBANK XFER IIT_DEBIT ON 05\/01", "amount" : "-0.96" }, { "amount" : "0.45", "status" : "Processing", "description" : "ACH CREDIT CITIBANK XFER IIT_CREDIT ON 05\/01", "fiid" : "citibank", "id" : "16e281ba-d1c4-3569-2f09-573d52805e26", "date" : "Processing", "balance" : "78.24" }, { "date" : "Processing", "status" : "Processing", "description" : "ACH CREDIT CITIBANK XFER IIT_CREDIT ON 05\/01", "amount" : "0.51", "balance" : "77.79", "fiid" : "citibank", "id" : "8ebd4980-f856-1118-f17a-b72d277fe1ed" }, { "description" : "Monthly Maintenance Fee", "balance" : "77.28", "date" : "04\/23\/2019", "id" : "80afb518-2079-7cc7-3590-21fe50fd995b", "status" : "Cleared", "amount" : "-4.95" }, { "description" : "EXXONMOBIL 479 04\/01 PURCHASE HOUSTON TX", "balance" : "82.23", "date" : "04\/02\/2019", "id" : "3bf2582a-d478-feef-a511-05856fdbafc6", "status" : "Cleared", "amount" : "-1.07" }, { "description" : "Monthly Maintenance Fee", "balance" : "83.30", "date" : "03\/22\/2019", "id" : "776c85bb-8169-6ca0-94ca-a6969e387af4", "status" : "Cleared", "amount" : "-4.95" }, { "description" : "Online Banking transfer to SAV 3827 Confirmation# 5312284008", "balance" : "88.25", "date" : "03\/20\/2019", "id" : "674ce8f4-c360-d489-f1b6-23c71d662224", "status" : "Cleared", "amount" : "-1.00" }, { "description" : "Online Banking transfer to SAV 3827 Confirmation# 1107098185", "balance" : "89.25", "date" : "03\/08\/2019", "id" : "83de5a70-d52f-ba3c-28d6-e9293ee50ec6", "status" : "Cleared", "amount" : "-3.00" }, { "description" : "Online Banking transfer to SAV 3827 Confirmation# 2306121751", "balance" : "92.25", "date" : "03\/08\/2019", "id" : "780822a7-8171-0236-93b0-b61b2b76f1bf", "status" : "Cleared", "amount" : "-2.00" }, { "description" : "Online scheduled transfer to SAV 3827 Confirmation# 1339205934", "balance" : "94.25", "date" : "03\/06\/2019", "id" : "fe999221-80a2-57e9-8bee-9c3e95e21e72", "status" : "Cleared", "amount" : "-0.25" }, { "description" : "Online Banking transfer to SAV 3827 Confirmation# 7367584397", "balance" : "94.50", "date" : "03\/04\/2019", "id" : "bbfb8bf7-c5d8-c39c-b2d3-093f7c05f926", "status" : "Cleared", "amount" : "-1.00" }, { "description" : "Online Banking transfer to SAV 3827 Confirmation# 7167583157", "balance" : "95.50", "date" : "03\/04\/2019", "id" : "cc6668cd-9adc-e5f2-bd75-7222f42cab81", "status" : "Cleared", "amount" : "-1.00" }, { "description" : "Online Banking transfer to SAV 3827 Confirmation# 6567582543", "balance" : "96.50", "date" : "03\/04\/2019", "id" : "0e568530-d672-1d9b-d31d-5a4959403b73", "status" : "Cleared", "amount" : "-1.00" }, { "description" : "Online Banking transfer to SAV 3827 Confirmation# 6367408687", "balance" : "97.50", "date" : "03\/04\/2019", "id" : "6217aa97-fb1d-cb4a-3c31-215b9caab083", "status" : "Cleared", "amount" : "-1.25" }, { "description" : "Online Banking transfer to SAV 3827 Confirmation# 6367377877", "date" : "03\/04\/2019", "amount" : "-1.25", "balance" : "98.75", "status" : "Cleared", "id" : "df89ea1f-8f5b-04c5-a8f7-531dd79327a3" }, { "description" : "BKOFAMERICA ATM 02\/20 #000003307 DEPOSIT LOUETTA SPRING TX", "balance" : "100.00", "date" : "02\/20\/2019", "id" : "d84f5720-a484-e409-0c81-3d639d20df66", "status" : "Cleared", "amount" : "100.00" } ] }

Transaction Details

The action transactionDetails provides at the very least the same level of detail as the transactions action. This means that if available there will be more information compared to the transactions action, but never less.

If no additional information exists for a given FI this action is still implemented providing you with the information that was available in the transactions action.

As input it receives a transactionId that must be from the immediate previous call to transactions.

Example payload:

{"transactionId" : "19932faf-8836-fa51-ff26-d3c74a6b38a5"}

example output, Citibank:

{
  "transactionDetails" : {
    "id" : "19932faf-8836-fa51-ff26-d3c74a6b38a5",
    "balance" : "$6.28",
    "date" : "02\/28\/2019",
    "description" : "Transfer to Citi Savings 11:48a #1824 ONLINE Reference # 001082",
    "amount" : "-$0.50"
  },
  "status" : "OK"
}

In the adobe example for Citibank no new information is provided, but the action is still implemented. For other FIs there could be more additional information, for instance for Bank of America a sample payload would look like:

{"transactionId" : "b3d53080-7eea-762e-d5a1-b66c10290b9b"}

And the corresponding sample output is: json { "transactionDetails" : { "id" : "b3d53080-7eea-762e-d5a1-b66c10290b9b", "balance" : "82.23", "extraData" : { "imageErrorCode" : null, "description" : "EXXONMOBIL 479 04\/01 PURCHASE HOUSTON TX", "postIndicator" : true, "referenceNumber" : "905704011139742", "displayOffer" : true, "helpAbout" : null, "transactionAmount" : "-1.07", "sicCodeDescription" : "Service Stations (with or without Ancillary Services)", "claimsPostedDate" : "04022019", "debitBrand" : "MC", "checkUserDesc" : null, "showOCCLink" : true, "purchaser" : "DAVID J FURLANG III", "imageError" : false, "deviceNickName" : null, "fixCatTransIndicator" : "Y", "images" : null, "dcsError" : false, "debitTransactionDisputeEligible" : true, "helpAvoid" : null, "devicePhoneNumber" : null, "transactionType" : "13", "sicCodeId" : "5541", "postedDate" : "04\/02\/2019", "cutoffPeriod" : "18", "claimsTransDate" : "04022019", "expenseCategoryCode" : "Automobiles and Vehicles", "imageType" : "Unknown", "detailCode" : "03024", "transactionCategoryCode" : "142", "transactionId" : "8b14249e2d89ed4a432add5a66932d5e472405873c46318ef7f015d4af56e2b3", "spendingEligible" : true, "helpWhat" : null, "walletProviderName" : null, "virtualCardNumber" : null, "userDescription" : null, "longDescription" : "CHECKCARD 0401 EXXONMOBIL 479 HOUSTON TX 15486809092837004639596", "claimsTransAmt" : "1.07", "merchantName" : "EXXON MOBIL", "checkNumber" : null }, "description" : "EXXONMOBIL 479 04\/01 PURCHASE HOUSTON TX", "date" : "04\/02\/2019", "status" : "Cleared", "amount" : "-1.07" }, "status" : "OK" }

In this case there is a whole package of information available related to the transaction that is provided in the extraData key of the JSON response. Depending of the type of transfer some extra information can be present, for example when there are images a sample output would look like:

{
  "status" : "OK",
  "transactionDetails" : {
    "date" : "02\/20\/2019",
    "balance" : "100.00",
    "id" : "0b9739ba-917c-f669-b00f-cf0b649a1691",
    "description" : "BKOFAMERICA ATM 02\/20 #000003307 DEPOSIT LOUETTA SPRING TX",
    "extraData" : {
      "userDescription" : null,
      "devicePhoneNumber" : null,
      "showOCCLink" : true,
      "dcsError" : false,
      "transactionCategoryCode" : "148",
      "checkUserDesc" : null,
      "transactionId" : "ffd4d1e1ff3ec653cbde124e9d528c8312c1bd376773dfcc522e452c240a46bd",
      "claimsTransAmt" : "100.00",
      "debitBrand" : "UNKNOWN",
      "helpWhat" : null,
      "longDescription" : "BKOFAMERICA ATM 02\/20 #000003307 DEPOSIT                    LOUETTA            SPRING        TX",
      "purchaser" : null,
      "imageErrorCode" : null,
      "sicCodeId" : null,
      "postedDate" : "02\/20\/2019",
      "expenseCategoryCode" : null,
      "detailCode" : "02008",
      "spendingEligible" : true,
      "sicCodeDescription" : null,
      "images" : [
        {
          "imageData" : "data:image\/jpeg;base64,\/9j\/4AAQSkZXRgABAQAAAQABAAD\/2wBDAKBueIx4ZKCMgoy0qqC+8P\/\/8Nzc8P\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/2wBDAaq0tPDS8P\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/wAARCAH0BLADASIAAhEBAxEB\/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL\/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6\/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL\/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6\/9oADAMBAAIRAxEAPwCaiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAo6UUj\/cb6H+VABvX+8PzFG9f7w\/MVUp\/lP\/AHf1H+NAFgMpOAwP40tVTG69VNCuy9D+HagC1RTI5A49+4p9ABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUEgdSB9aKqyEmQ59f07UAWutFRW5OCO3b+tS0AFFRvMFOAMkVJQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFI\/3G+h\/lS0j\/cb6H+VAFSrlU6uUAFQzR8Fh+P8Aj\/jU1HWgCorFWBHUVbByMjvVMjBI9KswHMY9v\/10APoJA6kD60yV9i8dT0qABpG9TQBP5qf3v508EHoQag8g4+8M\/wCf89Kj+ZG9CKALdBIHUgfWmo29c\/n9ajuP4fx\/pQBKGB6EH8aC6r1I\/wA+1VVJB+XqeKcIXPoPrQBOJUJ+9TutVXjZOvT1p0L4baeh\/SgCxRRUM0hB2rx60ASl1XqR\/n2pvmp\/e\/nVdULnAFPMDgdjQBYBBGQc0VUVmQ8ce3+NWkYMoIoAWkZ1XqRUU7kfKPx\/wqJULnAFAFjzU\/vfof8ACngg9CD9Kr+Q3qP1\/wAKEjYOMgj3H\/1umaALFNcRk4bGfrg06q03+tP4fyFAFhcY+XGPalJA6kCo7f7h+v8AQUx4myzZGOTQBETkk+tW96\/3h+YqpUnkN6j9f8KALAIPQg\/Sio4oymc45x0qSgAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigApH+430P8AKlpH+430P8qAKlXKp1coAKKKCcDJ7UAVH++31P8AOp7f7h+v9BVcnJye9WYhiMf5\/wA8UAQzHMh9v8\/zqWBcJn1\/z\/jUD\/fb6n+dKI3YZA4\/CgC1UNwOVP1pnlP\/AHf1H+NHlP8A3f1H+NADrc8sP8\/55pbj+H8f6UQoyuSwxxRcfw\/j\/SgBtv8AfP0\/qKsVXt\/vn6f1FWKAEYblI9RVSrlU6ALe4bd3bGaqE5OT3qz\/AMsP+A\/0qtQBajXagH5\/WnUUUAV51w+QOv8AOnW56r+P+P8ASi4\/h\/H+lNt\/vn6f1FABOCJM+tLDIFGD09amZA4wRUDQMOmD\/n\/PegCcMG6EGlqmQVPIINSxzEcNyPXvQBPVab\/Wn8P5CrPWq03+tP4fyFAEtv8AcP1\/oKe\/3G+h\/lTLf7h+v9BT3+430P8AKgCpVyqdXKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigApH+430P8qWkf7jfQ\/yoAqVcqnS72\/vH8zQBb6VBNJn5V6dzUfzP6t+tPWFj14FADUXe2Pz+lWulIqhRgCloArTDEh9+f8\/jUkDZXb3FOlj3jjqP84quQyHuDQBboqt5r\/3v5UhZ3OMk57f\/AFqALVQ3H8P4\/wBKfCGVMMMelMuP4fx\/pQA23++fp\/UVYqmASflBz7U4SuB96gCxK21D6np\/n2qqBkgetKSXPPJqaGMg7mGD2oAlwMYxxVMjBwe1XKimjz8y9e4oAfG25Afz+tOqoCyHjIP+e1KZXI+9QA6dsvgdv5063HBP4VGkbP0HHr\/nrVpQFAA7UAFFV5DIHLcgfpjtQJnHofr\/APWxQBYIDDBGaqMMMR6GnGZz6D6UiRs\/Qcev+etAFiI5jXNQTf60\/h\/IVZAwAPSq03+tP4fyFAEtv9w\/X+gp7\/cb6H+VMt\/uH6\/0FSEZGD3oAp1c61UdShwf\/wBdKJHUYDUAWqKgidmk5yR+g\/p2qegAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKCARgjNFFACbF\/uj8hS9KKKACobj+H8f6VNUNx\/D+P9KAG2\/wB8\/T+oqwQD1AP1qvb\/AHz9P6irFAAAB0AH0ooooAKKKKAAgHqAaQKoOQoH4UtFABRRRQAUEA9QD9aKKAAADoAPpRRRQAUUUUAFFFFAB1pNi\/3R+QpaKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAoIB6gH60UUAIFA6AD8KWiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAopGUMMMM1EUUTKuOCP8AGgCYkAZJxR1qORFWJtoxnH86FkVUXOegGccf5+lAElFMmI2DJOCR0pWYIoyf8TQA6imhwTjBBPTI606gAoyM4yM+lNaQKcck+gpm4NOuM9O\/0NAEtFNMig4GSR2AzShwVLA5AoAWimCVSMgNjvx0+tO3Dbuzx60ALRTPNX3x644pzOqjJPXp70ALRTQ4JxggnpkdaaMGc8nIH4f55\/OgCSiovNPmEYbAHTHP1qUHIzQAUU3eA4TByaC4Dhe5oAdRSM4DBeST6UhkHYMfoKAHUUiurDIPTr7U3zV7BiPXHFAD6KAcjI70juEGTmgBaKYZVBGc4PfHFBlUY4OD3xxQA+ikLgY756Y5zSCQE4IKn3GKAHUEgdSOaazhevU9h1qN2DPHwQc9CMdxQBNRTWdVOOSfQdaVWDdO3UelAC0UMcAn0pocFN\/agB1FIrhl3DpTGcNETyB\/n9KAJKOlRM+yMBc89Ce39PwpxbcjfKRweox2oAeCCMg5oqKOQLEOCceg9\/yqTcNu7PHrQAtFM81ffHrjildwqgnkH0oAdRSO4QZOaY0hEgABx346\/SgCSigHIzgj60jMF60ALRTPNGcEFfqKfQAUU13CYznmgSDOCCPTIxmgB1FIzhTjkn0ApFkDHHIPoaAHUUzzRkjBJHYCnKwbp26j0oAWimmRQcDJI7AZpQ4KlgcgUALRTBKrYxkk9vT60+gAoyM4yM+lNMgBwAWPsM0xCDOxHp\/hQBLRTPNXtk+pA6U4uAm7qPagBaKZ5q4BwceuOKeSAMk8UAFFM81ffHrjinM6qMk9envQAtFNDgnGCCemR1powZzycgfh\/nn86AJKKi80+YRhsAdMc\/WpQcjNABRTWkCnHJPoKVWDZ6gjqDQAoIPQg0VFDxE3Xv0+lOjwsWRkjk80APopglUjIDY78dPrTwQRkdKACiion+WZG9eP6f1oAloqGfLMAOwJ\/wA\/lTmbMBb1H\/1jQBJRTEKxxruPX+vNKrgnHIPoeKAHUZGcZGfSiogQLhs+n19KAJaKajh8gZBHY0GQdgx+goAdRTPNXbuGSB19qduG3d2xmgBaKaJF2bjwPegSKTjkZ6ZHX6UAOoopGcLjOcnoBQAtFMEoLbdrZ+lKzqpxyT6DrQA6ikVg3Tt1HpTBMpHAP0x+v0oAkopA6ld2eKb5q++PXHFAD6KazhCAe9AcEEjOB3x\/KgB1FMMoHZseuOKSSTCAr379v\/1+1AElFIrZzwRj14pvmr749ccUAPoJAGScUhYKMk8VHI4aM8EZxjI60AS9aKRPuL9B\/KmyuUXjOT3oAf0oBBGQc0wtuRvlI4PUY7U2OQLEOCceg9\/yoAloqOUqYwSTgnt\/n\/JpzMEUZP8AiaAHUU0OCcYIJ6ZHWnUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABUbf8fC\/T\/GpKQoC4bnIoAbN\/qj+H8xSP8A8e\/4D+lPZQykHvQUBTbzjj9KAIpf9Qn4fyqR03YwcEHrQ0YZQpzgUrKGx1BHQigBgdkYK+DnuP8AP+fepKaIwDkksfc5p1AEcf8ArXz1z+n+HT9KG\/4+F+n+NOaMMc8g+ooEah9wzmgCOLfg425zznOf8\/8A16cFZVkLEcgnj8acYwTkEqfY4pCoWNsZ6H+VABFjyRnpz\/M1Fz5HfG79P8M\/rT44w0YJJ9xng81JtG3bjj0oAR8eUemMcf0\/+tTFQtGnOCOh\/wA\/hTvKX3x6Z4pzIGx1GOmOMUAMDsjBXwc9x\/n\/AD70L\/x8N9P8KcIwDkksfc5pQgDlucmgBi\/8fDfT\/CpKa0YZt2SD6inAADAoAjm+Uo\/oefX\/AD1phywdwejDp7f\/AK81Myh1waAgCbecc\/rQAxTvmLDkAcH6\/wCTQru+SgAHv\/8AWpyIEzjPNJ5S5JGQD1APFADYhlpA3c8\/rRh4xwQyjt0+v+f0p6xquQM4NJ5Q6bmx6Z4oAcjblB9aZcfcH1\/oakAAGB0pHQOMHNADLj7g+v8AQ0s3+qP4fzFOdA4wc0MoZSD3oAZvICKoySB16U1929N2OvbPqKkMakDrx0I60nlLkHnI9+v1oAQf8fBz6cfp0\/X9aJfvx\/X+opzIG69R3HWk8pcg85Hv1+tADF3ea+MZz3z09vb\/AOtT0Vg5ZiOR2zStGGOeQfUUqoF55J9SaAF61XB+Qx553Y\/\/AFfiP1qxTfLG\/fzn9KAI2OzzFz15H49f8+1OcbbfHsP5jNOeNXYE5pWUMpB70ARS\/wCoT8P5VK\/3G+h\/lQUBTaelIIwARknjHJ7e3agBqf8AHv8Agf60w5+zrj1\/qamCAJt5xz+tAQBNvUe9ACPjyj0xjj+n\/wBaonz9nXPr\/jUnlL749M8U5lDLtI4oAZcfcH1\/oaG\/4+F+n+NBhUjkn65\/T6U50D4JyCO4oAdTZH24AGSelKqhRxn8aHQOMGgCKbftG7bjPbNTUwxKRyST655p9AEcv34\/r\/UUT\/dXHXPHr\/npSTDLoD3P+FPEYBySWPuc0AIXYvsQDI6k0z5vPXdjOO341I0YZt2SD6igRqH3DOaAGxffk+v9TQn+vfHTH68fr1\/Wmou535I57H3NSqgQYAoAii34ONuc85zn\/P8A9enBWVZCxHIJ4\/GnGME5BKn2OKAgCkc89ef1+tACQ\/6ofj\/On0iqFUAdqWgCOD7rZ6559f8APWmnPnSY67f6CpDGpbcMg98HGaFjVWyM0ARxb9g27ce+c\/j\/AJ6UFSkDAnv\/AFFP8oZyCV+hpJFCwkDp\/wDXFACnHkc\/3f6VG2fs69ev6c4\/DpT1jUquScYHGeOlSEAjBHFADXx5R6Yxx\/T\/AOtTFQtGnOCOh\/z+FO8pffHpninMgbHUY6Y4xQAwOyMFfBz3H+f8+9C\/8fDfT\/CnCMA5JLH3OaUIA5bnJoAYv\/Hw30\/wqSmtGGbdkg+opwAAwKAGMh3FkbBx\/n\/OKEclirDBHp0pSgJzkgnrg9aFQL06nuetAEcX+of8f5U5P+Pf8D\/WnLGFUqM4NBULEQOwNACRY8kZ6c\/zNJBny+fWkjjDRgkn3GeDzUhQFNuOKAFqOcZTPoakAwMDtQwDAg96AIkIkkZucYxj6\/8A6qj6qIyed3+f1JqwiBBgZpPLG\/fzn9KAGSZ85cY6cZ6Z5\/Xp+lKVkZlJK8HtmnsgcYIpBGAcksSOmTQA6o1\/4+G+n+FSUgQBy3OTQAxf+Phvp\/hQru+SgAHv\/wDWp4QBy3OTTfKXJIyAeoB4oAZGNxkBxk\/\/AF6TcfI245zj39f\/AK1SogTOM80nlLv3c5zmgBko2iMDGB69O3X9f1pzrIwAJUYOeM09lDDBGRTREO5Y46ZPT8qAH1E+fOBXkgcj\/P1qWoWx53JK8dc9f6f\/AKqAHBWaTewxgYAz\/n1NNXd5r4xnPfPT29v\/AK1KDiQBGLeuTkYp7RhjnkH1FACIrByzEcjtmkt\/uH6\/0FPVAvPJPqTQiBBgZoAr8+Qcf3v6VKVkZMfJg+macsaqpXqD60nlL0y2PTPFADZBzEDz6\/pUjttUn0pGQMVJz8vSnEAjB6UAREyNGThQCD65xTG\/491+v+NS+UuMEkj69KXy12bO1ABLny2xTFDmMAbMEe\/+c\/1p6oF9T259PT0pPKXsWA9M8UAMYFRGG6A8+nX\/AAp83+qP4fzFOKKV2kcU3ylIwST6c9P6fpQA5PuL9B\/KmXH3B9f6GpAMAD0pGUMMGgAf7jfQ\/wAqYn\/Hv+B\/rThGACMk8Y5Pb27UoQBNvOOf1oAgb\/j3X6\/41M6bsYOCD1pDGCgXJwKcyhsdQR0IoAYHZGCvg57j\/P8An3qSmiMA5JLH3OadQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFNkOEPOPegELGCzZHr\/KgB1FN81OPmHNNnbC4B5P8qAJKKZGI+qde\/Wl8xM43D\/Pv0oAdRSFgFyTxRvUkDPJ\/wD10ALRTfNTGdw\/z7daPMTGdw\/z7daAHUdaRWDDIORSGVB\/EP5\/yoAcAAMAYopryBVzkH0oSQPgZ5xzQA6imRcgnfu5\/wA\/57UpkUHBYf5\/lQA6ijIxnPFN81MfeoAdRR1psjhFz37UAOopqSB8DPOOaDIoOCw\/z\/KgB1FAIIyDmigAopvmJnG4f59+lMg4jP1\/oKAJaKb5iZxuH+ffpTiQBknFABRTRIhOAwzS7gWK55FAC0Um4FiueRSeamM7h\/n260AOopvmJjO4f59utKrBhkHIoAWimmRQcFh\/n+VKWAXJPFAC0U3zU4+Yc0jyBSB78+w\/xoAfRSKwYZU5oZgv3jigBaKCQoyelIWUDJIwaAFopFZW6EGjcAwXPJoAWik3AMFzyaTevPPTrQA6igHIyO9IzBR8xxQAtFQuwZ49pzz\/AFFSlgvUgUALRSKwYfKc0nmIM\/N0oAcQD1A4ooBDDIOaaZFBwWH+f5UAOooyMZyMetN81M43D\/Pv0oAcAB0A5opknVQH25P50PIFIHvz7D\/GgB9FIrBhlTmloAKKaybjncw+hqNFLMwLtwfX60ATUVFMMRAZJ57\/AI0\/zFyBuGTQA6ggEYIzSMyr1IFCurfdOaAF6UU0uoJBOCKVWVvunNAC0VFBxGfr\/QVIrBhkdKAFopGYL944pSQoyelABRSFlAySMGhWVuhBoAWik3AsVzyKNwLFc8igBaOtFQMytKdx+UdP8igCcAAYAxRTQURRyAO3+etKrK3Qg0ALRSb1yRnkUoIYZHSgAoqO4+4Pr\/Q04SKTgMM0AOopCwXqQKRXVjgGgB1FNLqCQTgilVlb7pzQAtFRxffk+v8AU07cCrEHp3x\/nNADqKZGcR5LZHr\/AJ5pfNTH3qAHUUZGM5GPWmean979D\/hQA+ggHqAaAcjI70m4btueaAFAA6ACik3AMFzyaCwUgE9elAC0UxD87nfkDt6f55\/nSCZdxycDtwaAJKKicgTqSccf41IrqxIBzigBaKKiUF3fLMMHsfrQBLRUakpKELFgRnn\/AD7U9mVepAoAWikV1b7pzSeYgz83SgB1FIrBhkHIqODiM\/X+goAlopFYMMjpS9KACim+Ymcbh\/n36UkrbUODgnpQA+ioohHxj7wHv\/8AqqWgAoqGQszttJAUdj\/n\/IqVG3KD60ALRTfMTn5hx\/n8fwo8xMZ3D\/Pt1oAdRSKyt905pDIoOCw\/z\/KgB1FIWAXJPFG9SQM8n\/8AXQAtFMTl2+fPt6f556fWlMiL1YUAOopNwxnIx65pBIjHAagB1FFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAyb\/VH8P5ikf8A49\/wH9Ke67lK5xmkKZj2Z7Dn6UAMYD7P0HQH+VJL\/qE\/D+VSFMx7M9hz9KRo9yBc9MfoKAFlOI2xQijygMcEc04jIwe9M8rA2hzt9P8A69AEYObdvY\/1FSxgBBgdQKCg8vYOB\/8AXzTlGFA9BQBFABsPHf8ApRb\/AHD9afGmxcZzzRGmxcZzzQAyLAaTsAf8aUOSPljyv1A\/SnLHgtk53f8A1\/8AGkWMgY3nb7f40ARL\/wAe7fX\/AAqdPuL9B\/KmrGAhUnIP4UqIVxlyQOgoAjiOIWI7Z\/lToQPL6detOjTYuM55pBHj7rEA9R\/h6UAMThZVHQZ\/r\/hSoB9nPA6H+tPCAIVHfP60BMR7M9jz9aAEh\/1Q\/H+Zom\/1R\/D+YpyLtULnOKGUMpB6GgBAcQ5HZf6U2EDy+nXrTkQrjLkgdBSCPH3WIB6j\/D0oASHhnUdAf8f8KdKcRtilRQgwKUjIwe9ADYwBGBjqOfxqDOID7t\/SphGQMBzt9O\/50LGAhUnIP4UAK6jyiMcAcVETuSIHoT\/I4\/lUnlZG0udvp\/8AXpWQMu09BQA7A44HHSo1\/wCPhvp\/hTlRgRlycfh+frSNHl9yttP50AIv\/Hw30\/wpIANh47\/0pyx7XLbicjv\/AI0sabFxnPNADLf7h+tInHm44x\/9epI02LjOeaETazHOcmgCOLcE4jznvkc0EMtuQ3r\/AFFPEZX7jkD0xmlKZQruP1PNADGA+z9B0B\/lSN\/yx\/D+lSFMx7M9hz9KRo9yqM4K9DQA+myruQjv1FKoI6sSaWgCEnesa+vX144P9aUfNcHPOBx+n+NJCo8xiOg4H\/6\/p\/OpGQMQ2SCO9ADJOJUI6k8\/pSt\/x8L9P8acI8NuYkt\/ntQ6biGBwR3oAa3\/AB8L9P8AGkjAMjkjof6mnCPDhixOPX\/PA9qVE2sxznJoAdUQ+a4OecDj9P8AGpaa6biGBIYd6AGS\/wCsj+v9RSHJnPy7sDgdPT\/GnmMlgSxJH+ePSldNxDAkMO9ADQHMoYrtGMHkH\/Paki\/1kn1\/qaeqkHJcn9B+VRoCXfa2Ofr3NABnbJJj0z+P+TToQPL6detORAmeSSeppBHj7rEA9R\/h6UAMRdwkQdM8f5\/AUuWRcOgKjuP8Pr9KeIwE2gke\/ekMbNwzkj6AUANkOXjI7n\/Cll+\/H9f6inNHkrg42\/8A1v8ACh03gc4I6GgB1FN2naQXOT36f596cBgYoAKji+\/J9f6mpKaibWY5zk0ANuPuD6\/0NJOBsHHf+lPkTeuM45okTeuM45oARnw+FXc35cfWmcmdcrtOPr2NPaPL7lbafzoEeJA24n60ANABuGyO3+FC\/wDHw30\/wp4TEhfPUdPy\/wAKAmJC+eo6fl\/hQBAudnIOzPOKsjGOOlMWMKhUnOaWNSi4zkfSgAlXchHfqKjJ3rGvr19eOD\/WpqhhUeYxHQcD\/wDX9P50AKPmuDnnA4\/T\/GiTiVCOpPP6U9kDENkgjvQI8NuYkt\/ntQA1f+Phvp\/hQv8Ax8N9P8KVo8vuVtp\/OhY9rltxOR3\/AMaAH1Gv\/Hw30\/wqSmhMSF89R0\/L\/CgBg+a4OecDj9P8aJOJUI6k8\/pT2QMQ2SCO9Ajw25iS3+e1ADAAbhsjPH+FS00JiQvnqOn5f4U6gCO4+4Pr\/Q0swHlH2xj+VOdA4wc0zyycb3JA7dKADfgJxucjj8f5U1yTIm5dvPrnuKkdNxDA4I70hjJYEsSR\/nj0oAaADcNkdv8AChf+Phvp\/hTwmJC+eo6fl\/hQExIXz1HT8v8ACgCE7syY6Z5x6ZNSnHknb0wf5UqptLHOd3\/16RY9qsu7g57dKAET\/j3\/AAP9aRAPs54HQ\/1p4TEezPY8\/WgJiPZnsefrQBEQTbrj1\/Pk8U5sybQEK479MfT\/AD2pHXYqDPIPB7de\/WlcugyZAfbA5oAlqOX5XR\/fBP8An8akByAcYprpvXFAETZyzjHDD9OP8KePmnz2Udfr\/wDrpypiPbn15+tJHHszznNACRffk+v9TRF9+T6\/1NORNrMc5yaTyyHLKxGeooAa3\/Hwv0\/xob\/j4X6f40\/Z86tnoMfz70FMyB89B0\/P\/GgB1Qou53+YjnscdzU1R+WwYlXxk+lADcGOUHOd3HPXtT2fD4Vdzflx9aBH825juP8AntQ0eX3K20\/nQAzkzrldpx9expYgPMc46H\/GnCPEgbcT9aVE2sxznJoAZDw8n1\/xqNc7OQdmecVOibWY5zk0ixhUKk5zQA8Yxx0qOc4j+pp0alFxnI+lKyhlIPQ0AI6jyiMcAcVGTm25\/wA80\/ysjaXO30\/+vSsm5No4\/wDrUAKn3F+g\/lSk4BPpQowoHoKR13rjOKAIY2+Vsqx3dSB\/n3p0BOCp7GpVGFA9BTdmJC4PUdKAGRf6yT6\/1NEIG+Tjv\/U09E2sxznJoRNrMc5yaAI+kshH93\/CiLcE4jznvkc1IExIXz1HT8v8KQRlfuOQPTGaAGEMtuQ3r\/UVJGAEGB1AoKZQruP1PNOUYUD0FAEKHBlI7Z\/rToQPL6detORNrMc5yaQRkfdYgHt\/ge1ACuyoAMZ9BUUxYqNyY565BqRo9ygZOR0NI0RYcuc\/p+VAElFIy5IOSMeneloAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigApGVW+8M0tFAAAFGAMUUUUAFFFFABRRRQAUUUUAFFFFABSBQpJA69aWigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigBGVW+8M0oAUYAxRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUABAYYIzTRGinIWnUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRSb1\/vD8xQGUnAYH8aAFooooAKKKKACiigkAZJxQAUUAg9CD9KKACiiigAoopCwXqQKAFopFYMMg5pSQBknFABRSb1\/vD8xS0AFFFFABRRRQAUUUUAFFFHSgAopAwPQg\/jS0AFFFFABRRRQAUUEgDJOKiacD7oz\/KgCWo3lKfwHH+fTNMzLJyMge3A\/+v8ArQrLH\/EWPoOn+fcUAKZQ4+8U\/X\/69H71eQd6\/n\/9em7kc4KkH\/Z\/wpfLKHcHAHryD+X9KAHLOD94Y9\/8\/wD16kDBuhBqF5EIHG4jueP8j2phkbGBhR7cUAWqKrp5ucjP49P1\/pUokUYDMM+3I\/OgB9FHWigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKAKajLAepp8kWwA5zTFzuGOueKc5ckb8\/lQBPCxZOexpxZQcFgPxpqAGPCHHv3\/\/AF\/56VEY1XducZ7f\/XHWgCwCCMg5pCyg4LAfjUEBIkx602X\/AFjfX\/Pr\/n06UAWSyg4LAfjTZv8AVH8P5ioZU2Ec5zTyc23P+eaAC3\/i\/D+tS71P8Q\/OqyuVBA796lgQbd3U\/wAqAJaTen94fnUc7EKAO9MWMGIt3\/w\/z\/nmgCxkYzniqspzIec0+ElgydiPy\/zmo3G1iB2oAsxqFXCnNNnOEx6mnIgQYB71FcHLAeg\/nQBFjGPerinKg+oqvKu1U47c\/wA\/8akiP7n6Z\/x9R\/MUAPDKTgMD+NAZScBgfxqqi7nAzjP+FDDa5A7GgC0WUHBYD8aWqsibGxnPFSM5WBcHk8f5\/wA\/kaAJd6g43D86XrVVQhQknDdh+FSW7HJXt1oAlDKTgMD+NI+GRgCP8PrVZQWYAdTUvllInyRzj19f8\/8A6qAFiQKxIYHjt9alJA6kCq9v98\/T+opuTJIM9z+n+f8A69AFkMG6EGlJAGScVAYmV8oOO3P6f57U+ZCwzuAA9en1oAfvU\/xD86Wqrqq4Ctk96sRHMa5oASSLec5I\/UUwosS7iu4\/p\/n\/ADxU1FAFVneQ4\/QU4RYGZDgfr\/n86lfKDKIM\/wCfxNViSxyTmgCQyAcRqB79\/wDP51GSWPJJNSJEWwTwKUukfEYBPr\/n\/wDVQAixHq5Cj\/P+f6Ub0T7gyfU\/5\/w\/GmMxY\/Mc0qRs\/Tp60AIzs33jmnJEzew9TUyRKvufU0+gBqIEHBJp1FFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAVFOHBPYipJZA4AGfWn+QnvS+SnofzoAiQssTEZAOMf1\/z+uaSPZht2M44\/wA8VY2jbtwMelNEKA55PtQBDD\/rR+P8jSS\/6xv8\/wCf89OlTrEqtkZoaJWOTnn\/AD\/9egCO4+8Pp\/n\/ADj8+y\/8u3+f71SPGHIznijYNm3t\/k0AV0TcrHuKfbthivr\/AJ\/z9KlRAnTPNIIlByM\/n\/n6fSgBlwOFP1oVwICD15H5\/wD66mIBGD0qMwIT3FADLcfOT6D\/AD\/WmS\/6xvr\/AJ9f8+nSrKqFGAMCmtErHJzn6\/5\/z7UAPqs\/zSke+P6VZpixKrZGc\/8A1sUAQtEyqSSOKdAeGHtn\/J4\/mKnIDDB6UxYlU5GemKAIYf8AWj8f5Gkl\/wBY31\/z6\/59OlTrEqtkZz\/9bFBiVmJOeff\/AD\/npQBFcffH0\/qaVxmFT6f59\/8APYdpXjVzk5pQoC7e3vQBBGIyp39fx6f5\/GpIihJ2qQaDAhPcU9VCjAGBQBXh\/wBaPx\/kanl\/1bf5\/wA\/5zxSLEqtkZp7DcCD3oArwDLkex\/pTUOyQZ7Hn+VWEjVDkZoeNXOT19RQAxpcOAuG6fnTJ2JcjsKmSNUOR19TQ8avyc5oAgkCAKE\/H9P84qaH\/VD8f5mjyUwBzTlUKoA7UALRRRQAUmxd27AzS0UAQTF\/4uF9un+f8ioutXCARgjNNWNVOQKAI0h7v+X\/ANepulIo2jA\/z\/n\/ADxS0AFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFAH\/9k=",
          "imageFace" : "front",
          "checkAmount" : "100.00"
        },
        {
          "imageData" : "data:image\/jpeg;base64,\/9j\/4AAQSkZXRgABAQAAAQABAAD\/2wBDAKBueIx4ZKCMgoy0qqC+8P\/\/8Nzc8P\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/2wBDAaq0tPDS8P\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/wAARCAH0BLADASIAAhEBAxEB\/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL\/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6\/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL\/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6\/9oADAMBAAIRAxEAPwCaiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACgkDqQPrUUsuPlXr3NQgM57k0AWPNT+9\/OlEiH+Ify\/nUIgcjsKRonHbP0\/zmgCzRUEAbd1O2p6ACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKAGPIEOCDSpIHzjPHrUNx98fT+pp1v\/ABfh\/WgCaiiigAoJA6kD60VDcfw\/j\/SgCUMD0IP40tV7f75+n9RVigAooooAKKKKACiiigAooooAKKKKACmPIEOCDT6r3H3x9P6mgCZJA+cZ49adUNv\/ABfh\/WpqACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACmyNsQnv2p1Q3B+6P8AP+etAEIGTgd6tRoEXHfvUEIzIPbmrNABRRRQAUUUUAFNMiD+Ifhz\/KoJZCxIB+WlSEsMk4H50ATCRW6MKdVZ4igz1FOhkIO0ng9P8+lAE9JvX+8PzFLVOgC51pplQfxD+f8AKq4DyDAyQPy\/\/X+tO8h\/Uf5\/CgCdXVuhFLVPpVqJt6Anr3oAdQSB1IFNdti5\/L61W+aRvU0AWPNT+9\/Ongg9CD9Kg8g4+8M\/5\/z0qNlaNueD7UAW6CQOpApkT7156jrSXH3B9f6GgB4YHoQfxpSQBknFVYm2Pk9P8\/1ody5yfwFAFgSKWwDk06q8KnzAcHHrj2p0yMzjAJGP8\/SgCQyIP4h\/P+VJ5qf3v0P+FRCFz6D\/AD7UGFwM8H6UAWAQehBoqorFTkVbByAfWgCvcffH0\/qadb\/xfh\/Wm3H3x9P6mnW\/8X4f1oAmooooAKhuP4fx\/pU1Q3H8P4\/0oAbb\/fP0\/qKsVXt\/vn6f1FWKACiiigAooqCaQklVPHegCUyKvVhQJEP8Q\/Hj+dQJEXGegpXhKjIOR+VAFiiq0UhU4J+WrNABTTIinBaoppOdoPTr70xI2fp09aALAkQ\/xD8eP51DcffH0\/qaDA4HY0xgQcNmgCW3\/i\/D+tTVDb\/xfh\/WpWbapJ7UAKSAMk4pnmp\/e\/nVdmLHJNPELkZ4H1oAmEiH+Ify\/nQZEH8Q\/n\/KqzKVOCKWNN5Izj8KALKsGGVOaWmxpsXGc81FNISSqnjvQBKZFXqwoEiH+Ifjx\/OoEiLjPQUrwlRkHI\/KgCxRVaKQqcE\/LVmgBCyg4LAfjSggjIOarTf60\/h\/IUqy7Y8Drnj2FAE7Mq9SBQrBhlTmqnJPcmrEAIQ5BHP+FAElFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAVXuPvj6f1NWKguByp\/z\/nmgBLf75+n9RViq0JxIPfirNAEU4J24BPXp+FQlWAyVI\/CrdMm\/wBUfw\/mKAIYf9aPx\/kamlOIz\/n\/ADxUMP8ArR+P8jUtx9wfX+hoAgRdzgVbqmAWOB1p\/lP\/AHf1H+NAFkjIwe9U6f5T\/wB39R\/jR5T\/AN39R\/jQBZByAfWqdW1GFAPYCqlAFtPuL9B\/KlpE+4v0H8qWgCtN\/rT\/AJ7VLb\/cP1\/oKim\/1p\/D+QqW3+4fr\/QUAMuD84HoP8\/0pbderfh\/n9KZN\/rT+H8hSKjMMqM0AWqiuB8oPvUflP8A3f1H+NHlP\/d\/Uf40ALAcSfUf\/XqS4+4Pr\/Q0yON1kBI4\/D0p9x9wfX+hoAgVSzADqaspGEHHX1qCH\/Wj8f5GrNABRRUMk3OE\/P8AwoAmoqsPNfkFvzxS7JTwc49z\/wDXoAYww5A7E1Yh\/wBUPx\/marEYJHpVmH\/VD8f5mgCK4++Pp\/U063\/i\/D+tNuPvj6f1NOt\/4vw\/rQBNRRRQAVDcfw\/j\/SpqhuP4fx\/pQA23++fp\/UVYqvb\/AHz9P6irFABRRRQAjnCE+1VAMkD1qzN\/qj+H8xVYDJwO9AFwDAwO1FVvKf8Au\/qP8aPKf+7+o\/xoAaww5A7E1ZRh5QPYD+VQeU\/939R\/jUoBWAg9cH+tAFcnJye9Wo12oB+f1qrVygAqvcffH0\/qasVXuPvj6f1NADrf+L8P6064\/wBWPr\/jTbf+L8P61K4BQgnA9aAK0WPMXNWqpkYOKkEzgY4P1oAfcY2j1zUcOfMGPemks7Z6mp4o9gyep\/SgB7nCE+1VAMkD1qzN\/qj+H8xVYDJwO9AFwDAwO1FVvKf+7+o\/xo8p\/wC7+o\/xoAaww5A7E1ZjOY1+n8uKg8p\/7v6j\/Gp4wVjAPX\/69AEE3+tP4fyFLFHvOT0H60k3+tP4fyFS2\/3D9f6CgCQAAYHSiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACmSruQ46jmn0UAUwcHI7VaRw4yPxFRyQ85T8v8Ki5U9wfyoAt0yb\/AFR\/D+YqHzX\/AL36D\/Cmlmc8kn2\/+tQA6H\/Wj8f5GpphmM+3P+fwqOGNgwYjA96n60AVEba4PpVvrVaSIqSQMr\/Kmq7L0JoAt0VVMrkfepUDlwwBPuf8aALNU6uVToAtp9xfoP5UtIn3F+g\/lS0AVpv9afw\/kKlt\/uH6\/wBBUU3+tP4fyFS2\/wBw\/X+goAjnGHB9R\/n+lOt26r+IqSRN6479qrFWQ8gg0AW6KqiVwPvUF3buf8\/SgC1Udx9wfX+hpIFZQcjAP+elLcfcH1\/oaAIof9aPx\/kas1Wh\/wBaPx\/kas0AIxwpI7A1Uq51qq6FDg\/gaALQGBgdqKrLKyjHBHvS5kl+n6UAMfl2+pqxD\/qh+P8AM1XZSrEHqKsQ\/wCqH4\/zNAEVx98fT+pp1v8Axfh\/Wm3H3x9P6mnW\/wDF+H9aAJqKKKACobj+H8f6VNUNx\/D+P9KAG2\/3z9P6irFUwSOhIpd7f3j+ZoAt0VU3t\/eP5mje394\/maALTjchHt\/+qqgOCD6VYgJKHJJ5\/wAKZLEQcqOPQdqAJ1IYAjvRVRWZehIp3mv\/AHv5UAWaCMjB71VAdzkZJ9f\/AK9WqAKfSrUbbkB\/P61FNGc7gOO9RqxU\/KcUAW6rzkF+D2\/qaaXd+Mk+w\/8ArUOhQDPegCS3\/i\/D+tNnYl9vYU63\/i\/D+tLOg+9kD+v\/ANf\/AD2oAIUUpkgE1JsX+6PyFVACTgDNLsb+6fyNAFsAAYAxRVQhl5IIpyysvfI96ALDjchHt\/8AqqoDgg+lXAcjI71BLEQcqOPQdqAJ1IYAjvRVRWZehIp3mv8A3v5UAWaKqgO5yMk+v\/16tUAVpv8AWn8P5Cpbf7h+v9BUU3+tP4fyFS2\/3D9f6CgCSiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAoIBGCM0UUAJsX+6PyFKAAMAYoooAKKKKACkKqTkqD+FLRQAgUDoAPwpaKKACiiigAooooAKKKKACjrRRQAmxf7o\/IUoAAwBiiigAooooAKKKKACjrRRQAmxR\/CPypaKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigBCoPUA\/hQFUHIUD8KWigAooooAKQqpOSoP4UtFAAAAMAYooooAKrTNmQjsKs1BNGdxYcjvQA63A2k981LVRWZfunFP8APb0H6\/40AWOtU2xuOOmeKc0rN1OB6ClSIseeB\/npQBPEMRrmnUdKKAEKg9QD+FAVQchQPwpaKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAQordQP8+9N8pP7v6n\/Gn0UAIEUdFFLRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRSMu4YyR9KiKkShd7YI9frQBNRUci7Ym+Ynp1Oe9KsihVBYdB\/n2oAfRQSAMk4pA6scAjP+fzoAWiimN\/rVG\/Ht6\/5\/SgB9FIXUHBODSCRD\/EKAHUU0OrHAPNKzqvUigBaKRWDD5TmkZ1U4JoAdRTVdWOFOaDIoOCw\/wA\/yoAdRR1oJAGScUAFFNEik4DD\/P8AOklbahwcE9KAH0VFEI+MfeA9\/wD9VSMwUZNAC0UyOUMACfmPbmmxsFeTJA5\/xoAlopFYMMg5FIZFBwWH+f5UAOoo602Q4Q8496AHUUwvsjBLZOOPf\/Pf\/GlSQPgZ5xzQA6immRQcFh\/n+VKWAXJPFAC0U3zE4+Yc\/wCfw\/GgyIP4h+HP8qAHUUdaZJJsHHWgB9FMLqyNtOcA\/wAqbG6rEMkf5JoAlooJAGSRimiRGOA1ADqKY8gUge\/PsP8AGnKwYZU5oAWikZgv3jilJCjJ6UAFFIWUDJIwaFZW6EGgBaKTcCxXPIo3AsVzyKAFooppkRerCgB1FIGBXcDxSb14569KAHUUjOq9SKUEEZBzQAUUdKb5qZxuH+ffpQA6imu4Vc569P8APpSLKpHJ5xk0APoqNJQ3B4OeP6U9mVepAoAWigEMMg5pvmpjO4f59utADqKb5iYzuH+fbrShlK7geKAFopvmpx8w5\/z+H40rMFXcTxQAtFMjlDAAn5j25oTl2+fPt6f556fWgB9FN81MZ3U4EEZHSgAopplQH71KrBhlTmgBaKbI4Rc9+1CSB8DPOOaAHUU0yKDgsP8AP8qcCCMg5oAKKRmCjJ6UuRjPagAoqN2BTIbAz1wf8\/5xT87QNxH16UALRSK6t905oDAsVB5FAC0Um4FiueRRuAYLnk0ALRQSAMnpSBgV3A8UALRQCGGR0pA6kZyMfl\/OgBaKaJEY4DUrMFHzHFAC0UiurfdOaWgAopvmIM\/N0pwIYZBzQAUU3zExndxSsyr1IFAC0UgYN0INDOq9SKAFopAwIyCMUgkUnAYZoAdRSMwUfMcUK6t905oAWimmRFOC1OyMZyMetABRTRIpOAwzTiQoyTigAoqGZ1ZBtOef6VNQAUUjMq9SBQrq33TmgBaKazqpwTTgQwyDmgAooJAGScU3zUzjcP8APv0oAdRRSMwUZY4oAWimiRScBhmlLBepAoAWimq6scA0pdQcE4NAC0UiurfdOaGZV6kCgBaKAQwyDmm+YmM7uKAHUVGv\/Hw30\/wp7Oq9SKAFooyMZyMetN81M43D\/Pv0oAdRSMwUfMcUK6t905oAWiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAqNv+Phfp\/jUlNKZkD56Dp+f+NACTf6o\/h\/MU1wPs447D+lSOu5SucZpCmY9mew5+lAEb\/diHXOOPXpSuHYDCYweORTygKBT2x+lIEbvIePQY\/xzQA+o2\/4+F+n+NSU0pmQPnoOn5\/40AMb\/j4X6f40MB9oXjt\/jTymZA+eg6fn\/jQUzIHz0HT8\/wDGgBkv+sj+v9RTt\/zEImT3PSldNzKc4waTyyHLKxGeooAbHnz2yMHHT8qRSVkc7S3PUc\/h\/n0p6x7XLbicjv8A40yIEg7G2jPTAJoAVAyo7dM5IHp\/n+lJFuCcR5z3yOadGxLlSdwHelEZX7jkD0xmgAiDKmG9aSblkU9Cf8P8aeowMZJ+tDqHGDQAyYDy+nTpRIcwZPcD+lKY8\/eYkDoP8fWnOu5SucZoAE+4v0H8qH+430P8qVRhQPQUEZGD3oAZD\/qh+P8AM02L\/WSfX+ppyxleN52+n\/1\/\/wBVKibWY5zk0ARpx5uOMf8A16ItwTiPOe+RzUiJtZjnOTSCMr9xyB6YzQARBlTDetE3+qP4fzFOUYGMk\/Wh13KVzjNADH\/49\/wH9KcDiHI7L\/Sl2AptPTGKREK4y5IHQUARxbgnEec98jmghltyG9f6iniMr9xyB6YzSlMoV3H6nmgBjgfZxx2H9KdgeR0\/h\/pSlMx7M9hz9KXb8m3PbH6UANh\/1Q\/H+ZpLj7g+v9DT0XaoXOcUOgdcGgAf7jfQ\/wAqjQD7OeOx\/rTwh2kFyeCP8+p\/GgJiPZnsefrQAxWCxLkZPOB75psxYqNyY565Bp\/lfIBnkdDQ0RYcuc\/p+VABL9+P6\/1FSU103gc4I6GlUEdWJNACSruQjv1FRk71jX16+vHB\/rU1QwqPMYjoOB\/+v6fzoAUfNcHPOBx+n+NEnEqEdSef0p7IGIbJBHegR4bcxJb\/AD2oAav\/AB8N9P8AChf+Phvp\/hStHl9yttP50LHtctuJyO\/+NAD6jD5zsTI9enNSUwRlSdrEKe3\/ANegCNOkvGPb86fCAIwccnPP40qx7Qw3Z3f\/AF\/z605F2qFznFAEMRblgm4k9cgVJEGG7IwCcgcf59KDGQxKsVz1705VI6sT9f6UADEKpJ6VGzM0ZxH8uPUdPXFSMoZSD0NM8s7dpc47f57j2oAb\/wAu3+f71Sp9xfoP5UgQeXsPI\/8Ar5oRCuMuSB0FADbf7h+v9BTVJ81yF3EH1xiniMqTtYhT2\/8Ar0NHltysVP50AIgbzGJXAP06\/wCc0kAGw8d\/6VIqkcliT+n5UkabFxnPNADLf7h+tIvHnfj\/AFqSNNi4znmmlNqyHOcg\/wBaAFiAMQHrnNMjOYG9s\/yojQtGPnIB6j8fWpQoC7e1ADYf9UPx\/maSL78n1\/qaVYyvG87fT\/6\/\/wCqlRNrMc5yaAGQAFDwOuP5UQ\/6pucdefwp8abFxnPNMKBIWBJI9uPT60ANUnytuw5Ptxz3qZAVQA9f8\/yqNQ2wHzABj0H86fExZMn\/APXQAk3+qP4fzFKDiHI7L\/SlZQykHoaREK4y5IHQUANhA8vp160Q8M6joD\/j\/hSiPH3WIB6j\/D0pyKEGBQAOu5SPWod\/+j989P8AP4VPUflfPu3HGc4oAbKu2FR6H+hpZcmVRjdx0\/P\/AAp8ib1xnHNDoHxyQR0NADCHZ1OzGPcHilb5Z1PQMMf5\/SnBWzkuTj2A\/P1okj3gc4xQBEONsnAyx\/X\/AA5p8fMrt+H+fypxTMezOOlEabFxnNADiMjB71ACfKKd92Pp\/kg1PTPKHmb8\/h\/n35oAZnYJV49vx\/w4p2RHGoIJPYe\/\/wCs\/WleLewOcUrpvA5wR0NAEUxYqNyY565BqSRCWDLgkdj+lI0RYcuc\/p+VOZSTlWI\/Ufl60AIr5fDLhsf55p9MWPDbmYsfyp9AEUX+sk+v9TSpxO4HTGf5f4mmoCXfa2Ofr3NSIgTPJJPU0AMtwNpOOc\/0oj5lcnqDx+tPjTYuM55oMeW3KSG\/z2oAYfluBjjI5\/X\/AAog5BY9SetPVApLZJJ70hjIYlWK5696AEn4jwOBn\/69IwYptEePxFP2AoVJJHv1pBGwGN52\/r+dACMjEqwwWA5B9aVXy+GXDY\/zzSspPIcg\/n+nrSLHhtzMWP5UANCvHnaoYfr\/AJ\/A0kjAw\/LwM4x+tP2N0Ehx7jJ\/OlEahCvODQAxgxTaI8fiKDlpUDc8c\/Xn\/CnCNgMbzt\/X86V0DAcnI6GgBlx9wfWpajaIsOXOf0\/KpKAGM+Hwq7m\/Lj60zkzrldpx9exp7R5fcrbT+dAjxIG3E\/WgBNrI5ZQDk\/j7\/wCfpTo2DZwMHuPegq2flcj6jP8AkUIgTPJJPU0ADsqrlhkelRyMxjOUwOOc\/wBKldA64NMMZZcFyf8APf1\/OgB6fcX6D+VMuPuD6\/0NSKMKB6Co7j7g+v8AQ0ALMB5R9sY\/lSb8BONzkcfj\/KlMZP3mJA7f4nvSum4hgcEd6AI3JMibl28+ue4pW\/4+F+n+NOMZLAliSP8APHpTXGZ1AOOOv50ALJxKhHXOP8\/maapPmuQu4g+uMU9Y8NuZix\/Kho8tuVip\/OgBEDeYxK4B+nX\/ADmktwNpOOc\/0qRVI5LEn9PypI02LjOeaAGr\/wAfDfT\/AApkRblgm4k9cgVKExIXz1HT8v8ACkMZDEqxXPXvQA1UYq6kYB5A4\/z6UZZFw6AqO4\/w+v0p4Q7SCzc9\/wDD0pDGzcM5I+gFACOpZldMHjv+lKr5fDLhsf55pSh42sVwMeo\/L196RY8NuZix\/KgB9FFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRSOSEJBAPvSbtseWIJ9u\/pQA6ikVgwGCM46ZpSQOpHNABRQSAMk4oyOORz096ACigkDqQPrRQAUUU1gxPytj8M0AOoqJC7Mw34wfQUOWVoxuJ557Z5FAEtNMaMcladkZxkZ9KaxbzFAIx3Hf8Az6frQA4AKMAYooJA6kD60daACiikLKDgsB+NAC0UAg9CDRkZxkZ9KACigkDqRzQCCcAjNABRR0oBBGQc0AFFGRzyOOvtRkYzkY9aACigEHoQaYJFLEZAA7560APoo6UAgjIOaACigkDqQKjJPnqAeCPw70ASUUU1SxdskEe3X\/P170AOooyOeRx19qMjGcjHrQAUUAg9CDSFgOpA\/GgBaKKQsoOCwH40ALRQCD0INAIPQjigBGVW+8M0oAUYAxRQCCcAjNABRRkZxkZ9KMjOMjPpQAUU1SxdskEe3X\/P170xSf3vJ4zj260AS0U2Ikxgk56\/zp1ABRSBgehB\/Gl6UAFFAIIyDmjI55HHX2oAKKTcCcZGfrSkgdSBQAUUEgdSBRQAUUUm4ZxkZ9M0ALRRSBgehB\/GgBaCMjB70U1pAHC8e\/tQA4AKMDpRUczfuwVPfqD9akyM4yM+lABRR0oBBGQc0AFHWimqWLtkgj26\/wCfr3oAPKTOdtO6UZHPI46+1GRjORj1oAKKAQehBpCwHUgfjQAtFFIWUHBYD8aAFooBB6EGjIzjIz6UAFFFFABRQCD0INGRnGRn0oAKKAQehB+lFABRRkc8jjr7UZGM54oAKKAQRkHNBIHUgUAFFHWjIzjIz6UAFFBIHUgUZGcZ5oAQKFJIHXrS0EgHBIzUcRJd8k8H\/GgCSiikYMcbWx+GaAFoqIFzIU39B1wPb\/GlfcsRy2T69O4oAkopqkbVyeSB1707pQAUUAg9CD9KMjOMjPpQAUUAg9CD9KjiJLvkng\/40ASUUAg9COKCQOpAoAKKMjGc8UAgjIOaACigEHoQaMjOMjPpQAUUZGcZGfSigAoqKRsyBd20dzUiAAcMW9yc0ALSMoYYYZpQQehBoJA6kc0AFFGRnGelNlJEZIOOn86AHUm0Fg2ORSIRtUE8kD69KdQAUUgYHoQfxpcjOMjPpQAUUAg9CD9KjUnz2GTjHT8qAJKKMjOMjPpTYyxBLEHnt\/n\/AOv60AOopNy4zuGPrS9aACik3qP4h+dKCCMg5oAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKAGTf6o\/h\/MU1wPIBx0A\/pT5FLIQO9BTMe0nsP0oARQFi3ADO3+lRpt28ozE9TjP5VIiuAAxGB+tIEdOFII988flQA3n7OQwIx6\/UUMqiAHAzgc09lYxlSQT69O9DITFt4zgfpQAmxfJzgZ25\/TNLD\/qh\/nvS7T5e3vjH6UgRhGFDAEfj3oAfRRRQBHF9+T6\/1NJMMugPc\/wCFORCrMTjk\/wCNDoWZSMcH\/CgBsgCyIVGMnt+FK3\/Hwv0\/xpXQsykY4P8AhQUJlDcYA\/xoAYVKuxKbwT9f0qSMoQdn4j\/P\/wCqgiQHgqR7\/wAuKI025JOSetADmztOOuOKrqU8rGPm+nOe1TS\/6s5OP8\/1pqeZsGNuMd80ANbKQAdCev8An17GkYDZhY2BHQ4\/rTwRNHzx\/jSgSYxuGPXv\/hQAyT5jHuHXr+lK6hZI9oxz\/hTnQsyHI4PP6UOhZlIxwf8ACgBjnM2GBIA6D+v+fSlX\/W\/KhVSOcjH\/ANanMh3blOD+h+tKofOWI+gH9aAI0UNI+ecHp+JpzlAwBXLYxgDPH06f1pUQqzE45P8AjQyMJN6Ec9c0AMGPOGFKgjkEYz17elLEoLvkDg+n1pdjeaGLA4\/D1oCMrkqRg9c0ANc5mwwJAHQf1\/z6Uq\/635UKqRzkY\/8ArU5kOQyt82OfQ\/WlUPnLEfQD+tADFAeVy3OOB6d6CALhcDHH+NOKMHLIRz1B6UmxvNDFgcfh60ASVHF9+T6\/1NSUxEKsxOOT\/jQA2NQZHyAef6mkiVd75AODx+tPRCrMTjk\/40IhVmJxyf8AGgBqYWZgOBj\/AAoBjxhYyR6gf1607yyZGJ6EY9+1IqOo27gB2OOf8P50AJDnyjjrzj8qYpTysY+b6c57U\/ZshYMce4\/D6UqeZsGNuMd80AMbKxopHXrjr\/8Ar\/rSt2KRsCD6U4fvkB6EHrSgSdyo+gzmgB9Rn5Zwf7w\/z\/IVJTJUL4wcEUARqTuD84ZiOvY9Py5\/L6U9PmmY+nH+fyP50pjzFsGM\/wBe\/wDWljUouCcknNADYvvyfX+ppq\/8tvx\/rT0QqzE45P8AjSCMjzOnzdP1\/wAaAFh\/1Q\/H+ZolUsmB1\/nSxqVQA9qVgSPlOD\/nigCMFAQGTaQePw9\/8ikc5mwwJAHQf1\/z6U5kd8ByAPb\/AOvSsh3blOD+h+tADV\/1vyoVUjnIx\/8AWpEUNI+ecHp+JqRQ+csR9AP60iIVZiccn\/GgBso2ujDgDj8P\/wBWaVvmmUf3ef8AP6U6Rd6EUkaFSSxBJ\/pQBGhBJZkLEn0yP8\/0p8ORuGCBnjNGxlJKEYPY9vyp6hh94g\/h0oAGxtO7p3qJihQ4jPTg4\/XNSuu5SPWmbJNm0sBxj\/P\/AOqgBu0vbgDr\/wDX\/wA\/lSgoCAybSDx+Hv8A5FOVWWMAEAj8j7UjI74DkAe3\/wBegCSomA89Rgcj\/GpaY6EsGUjI9aAGzgCMADHP+NJMoVQVGCD2pzozpgkZzn26fjSyoXXAx1oAY5zNhgSAOg\/r\/n0pV\/1vyoVUjnIx\/wDWpzId25Tg\/ofrSqHzliPoB\/WgB1Rxffk+v9TUlMRCrMTjk\/40ANjUGR8gHn+ppIlXe+QDg8frT0QqzE45P+NCIVZiccn\/ABoAamFmYDgY\/wAKAY8YWMkeoH9etO8smRiehGPftSKjqNu4Adjjn\/D+dACQ58o4684\/KmKU8rGPm+nOe1P2bIWDHHuPw+lKnmbBjbjHfNADWykAHQnr\/n17GkYDZhY2BHQ4\/rTwRNHzx\/jSgSYxuGPXv\/hQA9SSoJ64qKT5pVQ9Ov8AP\/Cpaa6biCDgjvQAyUBMOowQaHAadQemP8adsZiC5GB2HT9aChMobjAH+NADcBbhccZH+NS0woTKG4wB\/jT6AIUUNI+ecHp+JoYgzYKkhRwB\/h\/ntT0QqzE45P8AjQyHduU4P6H60ANX\/W\/KhVSOcjH\/ANaiIB8uwySaeofOWI+gH9absZSShGD2Pb8qAElwkWFGATSvGojPHQde9OKFk2scn1xTSjkbSwx645P1oAY5LQKT6\/41LtCKSBzg8nvSPHmMKuOPWn9aAI4kUpuIyT680kIw7gdj\/jSqjrwrDb79R9P8\/hSojLuyRk9\/z7UAPopFyFG45NLQBGv\/AB8N9P8AClm\/1R\/D+YoCESluMEf4UsilkIHegCNlUQA4GcDmnEptTfycDA69f896VkJi28ZwP0pDG3ylSNyjHPSgBjEeYhVSvPpinOA06g9Mf40pR2ZSWHB6fl09fxpShMobjAH+NADcBbhccZH+NM3FWfGeTyfTk1KUJlDcYA\/xoVMF84w3\/wBf\/GgByABRt6UOu5CPWmxqyAgkEdqfQBDuzbgc56f5\/Chl+dIz0A\/Pr\/h+poC5uCOw5\/l\/WpHTcQQcEd6AGSgJh1GCDSt\/x8L9P8aXYzEFyMDsOn60OhLBlIyPWgBG\/wCPhfp\/jUlRhG8wMxB\/yakoAiYDz1GByP8AGhwDIqdF64H4\/wCfzpxQmUNxgD\/GldNxBBwR3oAZKAmHUYINEwy6D3\/wp2xmILkYHYdP1odCzKRjg\/4UAOVQo+UYps3+qP4fzFPpHXcpXOM0AR7F8noM4znv60BlMSmTn+uP8\/Sl2SFdu4bfXvilePKrtOCvSgCOUjAIQqc9cYpzgNOoPTH+NK6O4GWH07fn1pShMobjAH+NADcBbhccZH+NNdisrlRzj8unNSFCZQ3GAP8AGgIRKW4wR\/hQAsQGzI5z1J6mm2\/3D9f6ClRCjHGNp+vFESFFwcdaAGQorKSRnnH8qRM\/Z2x\/kcZ\/rUkSFFwcdajZNkJDHv278dO1ACEoYwFHzfTn3qdRhQOPwphMoXJ28DPeno25QfWgBaKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooprPhwu0nPf\/P60AOooJAIHc9KZK5RcjHWgB9FFFABRTXfYQAM596aZGX7yED1BzQBJRR1ooAKKKKACimByZSvGAP8ACn0ABAIwelM8odMtj0zxT6KAAAAYHSiio1d3yVCge+f6UASUUUjtsXNAC0U2N9+eMEdqdQAUUUUAFFFFABRRTWfDhdpOe\/8An9aAHUUUUAFFFFABRRRQAUUUUABAIwelM8odMtj0zxT6KAAAAYHSiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooACARg9KZ5Q6ZbHpnin0UAAAAwOlFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUjDcMZI+lLRQAioFzjOT1JpaKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACkZQwwRkUtFADPKHGSxA7E8U\/pRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAMmzsyCRj3psrEhdpxkE+\/AzUjDcpHqKjhDZywIwMDP1z+lAA7kxrtPLY\/wDr4\/HilJImVcnGP8aaqt5gBB2qTg\/59\/8AOKcwPnqcHGOv50ANdczgZPI\/Lr0pZhiIDJPPf8aWQESK4BIHHH40kuWjGFPX8elABJuQBtxJ6e35D\/PvUtRzglBgE8\/41JQBFN99Mc8\/4UkrOUIKYHrnNOlB3IQCcHt+FDOWUqqNk+oxQA7+AbWwB39hUbnZgrIW9ic0PGQij7wHUCkkG5RtjI\/Dn8hzQA+UncgBIyf8KQ7kkX5id3XNLKCXTAPB\/wAKJQS6YB4P+FADS4SZifT\/AAqRAfvMck\/kPp\/n\/wCuzZmZty8Y\/wAKWLcpKEHA6HFAEhOAT6VGgZ13FyPTH9fWpCMgj1qNCyLtKE+mP6+lAAjFgyseQcZH+f6U2BcrncRg9AeO1PiUjJbqTSQAhDkEc\/4UASVHL8zqn4n\/AD+dSVEqb3YuD7dRQAfdn9mH+fxyP1pXJ85QGI4\/xpHjCgMi8g\/WlIJnU4OMf40AIdwlChzg8\/zobKSLhiQx6GlYHz1ODjHX86JQS6YB4P8AhQAO5Mm3dtAHJ\/woVsSbd24Ecd\/1\/wA9qR1Ik37dwPUdfy\/z605cFuI8D1wBQA1dzO43EDP+PT0\/\/VSkkTKuTjH+NEQId8g8n\/GhgfPU4OMdfzoAGLNJsBwAOf8A61OCkZ+cn0zzimsCsm8DII59fwpWLOjAKR6Z\/X6UANbABPmncPcdR7U+NiyAnrUYH7vAiOcdSP1GeT9KemVhHykkdvxoAfRQOnPFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRTPNT+9+h\/wAKPNT+9\/OgB9FFFABRRRQAUUUEhRk9KACikV1bO05xS0AFFFFABRRTWdU6mgB1FIjBxkUpIUZPSgAopnmp\/e\/Q\/wCFPoAKKKKACiiigAooooAKKKCQBk9KACimq6scKc06gAooooAKKKKACikZgo+Y4qJp\/wC6PxNAE3So2aTqqjHtz\/n8qj2O4y5wPf8Aw\/8A1UBkj+7kn1PA\/wA+xoAXzQwwwI\/3T\/TpQFb\/AJZvn26foaA\/mH5k3e44x\/n8KGjRDksR7d6AFEzKcOv9D\/n8qlVw4yKhaYEYC5x\/e5\/yaYWd+Mk+3\/1hQBaoqusbrySE+p\/z+RqQTKMAkn3xQBJRQCGGQc0UAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQBUUZYD1NPljCAEH86jUEsAOuac6sCC+T+P6UATQHMf0NOMqA\/epE2vHgcDp\/n\/P61FiNQQW3Htjt+uDQBOrBh8pzSGRAcE8\/jUEJxIPfNJL\/rG\/z\/AJ\/znmgCwZEBwTz+NJNzEfw\/mKhlQIRj0p\/\/AC7f59aAC3\/i\/D+tSCRCcA5P41WDEAgd+tTwAbMjr3oAk6UzzUzjNNuCQAPX+lNWMGEt35OfpQBNuG3dniq0hDOSOlOhOSyE8Ef5xTHADkDpmgCzHt2\/J0\/rTZzhAPU\/5\/pT0UIMCoJzlwPQf5\/pQBGRgD3\/AP1VbVsoGOOlQS42pgg4GDg1JEf3J9s\/4+3r6\/jQA4SITgH+dAkQnAPP41XjUM4B70jja5HvQBZMqA\/ep2RjOeKrSqEYAelPdiIFHr\/L9P8APf1AHmVAetPBBGR0qquzYdw+bnFPtydxHbGaAJRIhOAf50jMrow3Yx1P+ev9arou5gPWpjH5cb85yB\/nr\/n3oAIggY7WJOP6\/wD6qkZ1X7xxUEHDn6f4U1f3kgz3NAFhZFboefSlZgoyTgVE0J3ZQgD\/AD9adKgblmxigBfNT+9\/On1VfZwEz7n1qeH\/AFQ\/z3oAV41c5PX1FN2eWPkXcfX\/AOt\/h+tSUUAVfnkbByT\/AJ\/Kn+WqDLnJ9B\/n\/CpX34+TGe\/r\/h+dVeSe+aAHtKSML8o9qaAWPGSakSHjc5wPT\/H0\/wA9KGlAGIxgev8An+tAAIgozI2Pb\/P9PzpDLjiNQvv3\/wA\/nUZJJyTmnpEz89BQAwkseSSakSEnluB+v+f84qdUVOg\/GloAREVOgpaKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAqKcMD6GnyS7wBjFTeUn90f5\/wA\/j3oEaD+EUAQqGWJj0zj8v8OfekjZVDbuvGOP8\/zFWetNEaKchaAIIf8AWj8f5Gkl\/wBY3+f8\/wCc81YCKDkDn\/IoKKTkjn\/IoAiuPvD6f5\/zn8u6\/wDLt\/n+9UrIrdRmjaNuMcen45oArxoGV\/UdP1p1u2GI9f6VMqqv3Rik8tAc7Rn\/AOvn\/P5dKAGXCkqD2H9aasgEJXvzx9fwqfrTPKT+7\/OgCO3B3E9sYpkv+sb6\/wCfX\/Pp0q0AAMAYppRSckc\/5FADqrN88p9zjj+f5VZpoRQcgc\/5FAELw7VLbs49v\/r0sJ4Ye2f88j\/PepyARg9KQIqnIGKAK8P+tH4\/yNJL\/rG+v+fT\/Pr1qwEUHIHP+RQY0JyVH+f8\/wBaAIbj74+n9TTmXMCkDp\/L8v8APqe8rIrHJGaUAAYHSgCvEyBTuAz9M1JEwbJCAe4\/l\/n9KcYkJ+7TgABgDFAFaH\/Wj8f5Gp5f9W30\/wA+n+fXpQEUHIHP+RTiARg9KAK8H3z9P8KaP3cnPY1ZCKpyBihkVvvDNAERlJkAQ5HuP8mmT58w5\/D\/AD9asKir90YoZFb7wzQBXlZSFCDoKmh\/1Q\/H+ZpTGhGNox\/n\/CnABRgDFABRRRQAUYGc4GfWiigCCZXzk8j27fhUQBJwOtXKRVC5wMZoAjjiUckhj+lS0AY6UUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFAH\/\/Z",
          "imageFace" : "front",
          "checkAmount" : "100.00"
        }
      ],
      "helpAvoid" : null,
      "cutoffPeriod" : "18",
      "helpAbout" : null,
      "walletProviderName" : null,
      "fixCatTransIndicator" : "Y",
      "referenceNumber" : "950602200003307",
      "imageError" : false,
      "displayOffer" : true,
      "deviceNickName" : null,
      "merchantName" : "BKOFAMERICA ATM DEPOSIT LOUETTA TX",
      "checkNumber" : null,
      "transactionType" : "07",
      "postIndicator" : true,
      "virtualCardNumber" : null,
      "claimsTransDate" : "02202019",
      "debitTransactionDisputeEligible" : true,
      "claimsPostedDate" : "02202019",
      "transactionAmount" : "100.00",
      "description" : "BKOFAMERICA ATM 02\/20 #000003307 DEPOSIT                    LOUETTA            SPRING        TX",
      "imageType" : "ATMDepositSlipIndex"
    },
    "status" : "Cleared",
    "amount" : "100.00"
  }
}

In this case there are two images related to the transaction, the images are delivered as a base64 representation ready to be displayed inside a < img > HTML element.

For the case of Bank of America the transactionCategoryCode description for each code is as follows:

100: "Business Expenses: Business Miscellaneous"

101: "Business Expenses: Dues & Subscriptions"

102: "Business Expenses: Office Maintenance"

103: "Business Expenses: Office Supplies"

104: "Business Expenses: Postage & Shipping"

105: "Business Expenses: Printing"

106: "Education: Education"

107: "Finance: Credit Card Payments"

108: "Finance: Loans"

109: "Finance: Service Charges/Fees"

110: "Finance: Taxes"

111: "Giving: Giving"

112: "Groceries: Groceries"

113: "Health: Healthcare/Medical"

114: "Health: Insurance"

115: "Home & Utilities: Cable/Satellite Services"

116: "Home & Utilities: Home Improvement"

117: "Home & Utilities: Home Maintenance"

118: "Home & Utilities: Mortgages"

119: "Home & Utilities: Rent"

120: "Home & Utilities: Telephone Services"

121: "Home & Utilities: Utilities"

122: "Cash, Checks & Misc: ATM/Cash Withdrawals"

123: "Cash, Checks & Misc: Checks"

124: "Cash, Checks & Misc: Other Bills"

125: "Cash, Checks & Misc: Other Expenses"

126: "Personal & Family Care: Child/Dependent Expenses"

127: "Personal & Family Care: Personal Care"

128: "Personal & Family Care: Pets/Pet Care"

129: "Restaurants & Dining: Restaurants/Dining"

130: "Savings & Transfers: Savings"

131: "Savings & Transfers: Securities Trades"

132: "Savings & Transfers: Transfers"

133: "Shopping & Entertainment: Clothing/Shoes"

134: "Shopping & Entertainment: Electronics"

135: "Shopping & Entertainment: Entertainment"

136: "Shopping & Entertainment: General Merchandise"

137: "Shopping & Entertainment: Gifts"

138: "Shopping & Entertainment: Hobbies"

139: "Shopping & Entertainment: Online Services"

140: "Transportation: Automotive Expenses"

141: "Transportation: Car Payments"

142: "Transportation: Gasoline/Fuel"

143: "Transportation: Public Transportation"

144: "Travel: Travel"

147: "Income: Consulting"

148: "Income: Deposits"

149: "Income: Expense Reimbursement"

150: "Income: Interest"

151: "Income: Investment Income"

152: "Income: Other Income"

153: "Income: Paychecks/Salary"

154: "Income: Retirement Income"

155: "Income: Sales"

156: "Income: Services"

157: "Income: Wages Paid"

158: "Finance: Bank of America Credit Card Payment"

159: "Health: Fitness or Health club membership"

160: "Insurance: Insurance"

161: "Finance: Investment Account Fees/Charges"

998: "Uncategorized: Pending"

999: "Uncategorized: Uncategorized"

Zelle Dynamic Data

The action getZelleDynamicData is used before attempting to setup a Zelle transfer for the first time, and it provides an output in a similar format as the webservice in charge of supplying the static data.

Sample input: json {}

Sample output: json { "zelleDynamicData": { "parameters": { "accountFrom": { "name": "accountFrom", "displayName": "Account From", "type": "select", "required": true, "options": [ { "id": "0", "displayName": "Regular Checking - 7715 - AvailBal $2,291.76" }, { "id": "1", "displayName": "Regular Savings - 9026 - AvailBal $0.34" } ] }, "contact": { "name": "contact", "displayName": "Contact", "type": "select", "required": true, "options": [ { "id": "4", "displayName": "APPBRILLIANCE", "token": "[email protected]", "status": "active", "nicknameId": "128429466", "uid": "CFR000327676" }, { "id": "6", "displayName": "Binance", "token": "[email protected]", "status": "inactive", "nicknameId": "173818398", "uid": "" }, { "id": "7", "displayName": "Eric Citi", "token": "5126297786", "status": "active", "nicknameId": "176325352", "uid": "CTIcm0xgcbdIgfHtq" }, { "id": "5", "displayName": "eric mobilenumber", "token": "5127779809", "status": "active", "nicknameId": "177839990", "uid": "570964860" } ] } }, "suggestedOrder": [ "accountFrom", "contact" ], "notes": [] } }

Zelle Setup Transfer

Use the zelleSetupTransfer action to setup a new zelle transfer.

LThe parameters needed to effectively setup a zelle transfer can vary from FI to FI. To get the list of parameters along with types, available choices and so on please refer o the Parameters Discovery for write operations section. A brief description of the steps needed are: * Have the data from the call the getData web service cached somewhere, this needs to be accessible in your host application. * Once the application is running and logged in, make a call to getZelleDynamicData to fetch the dynamic data needed to make a transfer. * Use the suggestedOrder defined in the static and dynamic data to build the initial UI and accept input from the user. * As the user selects options with triggers or triggersInline present the user with the corresponding options to input the additional parameters. * Once all the parameters have been filled and there are no more triggers call zelleSetupTransfer with all the parameters.

An example on how to setup a Zelle transfer is as follows:

Sample input: json { "accountFrom": "0", "contact": "5", "amount": "1.02", "memo": "test memo" }

Sample output: json { "status": "OK", "reviewItems": [ { "key": "From:", "value": "Regular Checking - 7715" }, { "key": "To:", "value": "eric mobilenumber - (512) 777-9809" }, { "key": "Amount:", "value": "$1.02" }, { "key": "Date:", "value": "12/20/2019" }, { "key": "Message:", "value": "test memo" }, { "key": "Verified User", "value": "Enrolled in Zelle as CHARLES" } ] }

Zelle Schedule Transfer

The action zelleScheduleTransfer is used to confirm a transfer, it receives no parameters and the sample output after the transfer setup is complete looks like:

{
  "status": "OK",
  "referenceNumber": "f5b743a65"
}

In case of an error or if the transfer setup is not complete you will receive an error along with an error message explaining the situation:

{
  "status": "ERROR",
  "errorMessage": "Transfer setup is not complete",
  "errorCode": "E00300"
}

It is important to note that depending on the FI, the actual field validation can take place in the zelleSetupTranfer action or in this action (or both). If the error is received in this action it will require you to use the zelleSetupTransfer action to attempt a new setup.

Zelle Add Contact

The action zelleAddContact is used to add a new Zelle contact before sending money.

Sample input: json { "contactType": "1", "firstName": "Sergio Test", "lastName": "Eric DontUse", "token": "[email protected]", "nickname": "dont use me" }

Sample output: json { "status": "OK" }

Sample error outputs:

{
  "status": "ERROR",
  "errorMessage": "Your request can't be completed. The recipient you are attempting to add is a duplicate Please enter information for a new recipient or select the Manage Accounts menu to edit an existing recipient",
  "errorCode": "E00006"
}
{
  "status": "ERROR",
  "errorMessage": "Your request can't be completed. Please enter a first name using only valid characters: letters (a-z), space, -, '",
  "errorCode": "E00006"
}