Credit Builder Card API-First Documentation

Please note: If your company is integrating our Card product using only our APIs, you’re in the right spot!

Overview

Upwardli provides a seamless and secure way for businesses to enable a credit building card to their end users. End users can incorporate credit building into their daily activities by loading money to their FDIC insured DDA account and then swiping their card at any location where Mastercard is accepted. Upwardli’s platform customers are able to monetize the card through interchange, deposit interest, and expedited external payments.


Introduction

Welcome to the Credit Builder Card! Our documentation will walk you through the basics (authentication, request structure) to using and creating the financial products associated with the Credit Builder Card (accounts, cards, payments, etc.).

The introduction covers basic concepts you should be familiar with in order to make the most out of the Upwardli card issuance and management platform.


How the Credit Builder Card Works

Credit Builder Card Diagram

  • The card’s available credit is equal to:
    • the available funds that the user maintains in a linked deposit account, plus
    • any verified incoming payments to the user, such as payments due for wages or gig work
  • The user may obtain a physical, digital card or both. The user makes purchases anywhere Mastercard is accepted.
  • As the user makes purchases on the card, an equal amount of funds in the linked deposit account are put on hold, and the card’s available credit decreases in an equal amount.
  • The cardholder may opt in to automatic payments to pay off balances as they incur charges, but must pay the card’s balance in full on the payment due date.
  • If the balance is not paid on time and the DDA balance is at zero the card will freeze until the user has made a payment.
  • By default, there are no fees to use the card and the user is charged 0% APR.

Implementation Options

Upwardli offers three ways to integrate the credit builder card into your website or mobile app for your credit program.

  • Use Credit Builder Card APIs. When integrating credit builder cards into your own website or app, this option offers flexibility in designing a unique user experience including the credit services and financial products you wish to offer. This option provides a secure, PCI-compliant, customizable experience for purchasing and providing basic banking services (i.g statements, transaction, history, card management, etc).
  • Use our Embedded Integration. The embedded flow is a drop-in module that enables you to seamlessly offer a credit builder card within your app or web page. It allows individuals to easily access their credit and credit builder card details securely without redirecting away from your app or website.
  • Leverage an Upwardli Hosted App. If you do not want to build and host a credit account and banking experience, Upwardli can handle the product build and push to your app store instance. This approach offers less flexibility and, while easier to implement, it requires higher platform fees.

Environments

There are two types of environments for the Upwardli Credit Suite:

  1. Sandbox
    You can test out your integration and explore common usage patterns in our sandbox environment. This environment is fully isolated and will not perform any “live” financial transactions.

You can request sandbox access once you have a signed contract.

Important: The Sandbox environment is fully secure, but you should not store any real consumer data here.

  1. Production
    Once you have completed sandbox testing and submitted your test plans, you will be provisioned production access keys. These details will be shared with you via a secure sharing mechanism. All transactions in our production environment are live financial activity.

Getting Started

Regardless of which method you choose for integration you will always need to follow our authentication methods.

Authentication

Upwardli’s API uses OAuth 2.0 to authenticate requests. All API calls must include a token. These authentication tokens are used for machine to machine communication.

Note: An invalid, missing or expired token will result in an {invalid_token} response

URLs

Environment URL Sandbox Authentication https://auth-sandbox.upwardli.com/auth/token

Production Authentication https://auth.upwardli.com/auth/token

Tokens

Upwardli has the concept of three different tokens:

  • Customer Onboarding Tokens: are system level and assigned to a specific organization that allows you to onboard new users. Once a user is onboarded you would use the customer token to access their specific information.
  • Customer Access Tokens: are specific to an end user also known as consumers in our product and only provide data specific to that consumer. These tokens are used to secure our embedded components.
  • Partner API Tokens: are highly secure tokens that are used to integrate your backend platform with Upwardli’s APIs. These tokens SHOULD NOT BE USED OUTSIDE OF DIRECT API CALLS BETWEEN YOUR SYSTEM AND UPWARDLI.

When a token is created, it is assigned a set of Scopes. The scopes define the resources that can be accessed using the token, and the access level (read/write) that will be allowed using that token.

NOTE ON TOKEN EXPIRATION: Partner API Tokens expire after 10 hours have elapsed since creation, and Customer Access Tokens expire after 1 hour

If a new token is not requested then it will result in a 403 screen.

Scopes

Scopes define the access level of a token.

A list of all scopes within Upwardli:

ScopeToken TypeUse
api:readPartner API TokenUsed to perform read actions on the platform
api:writePartner API TokenUsed to perform full CRUD operations on the platform
ui:client-onboardingPartner API TokenUsed for the client onboarding component
api:card-management:readCustomer Access TokenUsed to populate all card-management pages, card image
api:card-management:writeCustomer Access TokenPerform card management actions (pin change, freeze/unfreeze, lost/stolen)
api:consumer-profile:readCustomer Access TokenUsed to populate all profile pages (dispute, statements)
api:consumer-profile:writeCustomer Access TokenUsed for account closing
api:credit-goals:readCustomer Access TokenUsed to populate credit goals page
api:purchase:writeCustomer Access TokenCreate an ACH transfer in and out of an individual’s account
api:purchase:readCustomer Access TokenRetrieve an ACH transaction history for an individual
api:statements:readCustomer Access TokenRetrieve statements directly
api:accounts:readCustomer Access TokenGet bank accounts
api:accounts:writeCustomer Access TokenCreate bank accounts
api:simulated-card:writeCustomer Access TokenSimulate funding/auth/settlement

Requesting Tokens Using The API

The Upwardli API uses OAuth 2.0 for authentication and authorization. Before you can use the API, you must obtain an access token using the client_id and client_secret provided to you. Once a token has been obtained, it must be passed in the Authorization header of each request to the API.

Customer Onboarding Token Request

To request a token send a POST to our auth server containing your client ID and client secret values.

POST https://auth-sandbox.upwardli.com/auth/token/

1{
2 "header": "content-type: application/json",
3 "grant_type": "client_credentials",
4 "client_id": "[your id here]",
5 "client_secret": "[your secret here]",
6 "scope": "ui:client-onboarding"
7}

Here’s a cURL example for the token request:

1POST https://auth-sandbox.upwardli.com/auth/token/ \
2
3 --header 'Content-Type: application/json' \
4 --data \
5'{
6 "grant_type":"client_credentials",
7 "client_id":"[api client key]",
8 "client_secret":"[api client secret]",
9 "scope":"api:read api:write ui:client-onboarding"
10}'
11
12curl --location 'https://auth-sandbox.upwardli.com/auth/token/' \
13--header 'Content-Type: application/json' \
14--data '{
15 "grant_type": "client_credentials",
16 "client_id": "XXXXXX",
17 "client_secret": "XXXXXX",
18 "scope":"api:read api:write ui:client-onboarding"
19}'

Here’s what a successful response looks like:

1{
2 "access_token": "xxxxx",
3 "expires_in": 86400,
4 "token_type": "Bearer",
5 "scope": "api:read api:write ui:client-onboarding"
6}

Exchanging Partner API Token for a Customer Token

Once a valid token has been obtained using the Authentication API, a limited scope token can be obtained using the token exchange API. This token can be used to make requests for a specific consumer, and is safe to send to the client application/web browser as needed.

To request a token exchange send a POST to our auth server containing the access_token and requested scope.

This token expires after 1 hour and will need to be exchanged for a new token for the customer to continue to have access.

Notes:

  • The audience must be for the correct Environment.
    • Sandbox: https://auth-sandbox.upwardli.com
    • Production: https://auth.upwardli.com
  • The upwardli_consumer_id is the Upwardli id that you get from the Consumer API or the consumer.created webhook.
  • The new access token is a significantly longer string than the original access token.

POST https://auth-sandbox.upwardli.com/auth/token/exchange/

1Header
2{
3 "Authorization":"Bearer [access_token]"
4}
5Body
6{
7 "grant_type":"urn:ietf:params:oauth:grant-type:token-exchange",
8 "subject_token_type":"urn:ietf:params:oauth:token-type:access_token",
9 "subject_token":"[access_token]",
10 "audience":"https://auth-sandbox.upwardli.com",
11 "scope":"<See scopes table> consumer:[upwardli_consumer_id]"
12}

Here’s what a successful response looks like:

1{
2 "token_type": "Bearer",
3 "expires_in": 3600,
4 "access_token": "[scoped access token]",
5 "scope": "<Scope(s)>",
6 "issued_token_type": "urn:ietf:params:oauth:token-type:access_token"
7}

Onboarding a New User

A consumer is the individual end user that you are creating a credit product. Consumers are limited to individuals using a valid SSN or ITIN, or single-member LLCs (coming soon).

A Consumer record is automatically created once an application is started and Upwardli will manage the ongoing regulatory requirements tied to application notice, approval and denial notifications to the end user.

Consumer onboarding is a fully asynchronous process due to the KYC and Banking integrations, which are themselves asynchronous. Our design goal for customers interacting with the Onboarding component is to capture data in realtime, and then process asynchronously. This will reduce elapsed consumer interaction time and improve the customer experience.

NOTE: we recommend listening to webhooks. to be notified of the status of each consumer as they make their way through the application and approval process. You will have access to the consumers financial products once they have been fully onboarded and approved.

All consumers are created as part of our onboarding. Regardless of the integration method you’ll need to use our embedded iframe to offer our application flow. We do allow you to customize the UI of the application but to ensure consistent and fair lending practices we own the specific language and disclosures surrounding the application process.


Authentication & Loading the Onboarding Embedded Flow

Authentication

Tip: Your API Key and Secret will be shared with you by your Upwardli client team.

The first step in integrating your product is to configure authentication. All Upwardli components and APIs require Oauth tokens for access.

Creating the Consumer Record

POST https://api-sandbox.upwardli.com/v2/consumers/

1Header
2{
3 "Authorization":"Bearer [access_token]"
4}

Body

1{
2 "id": "{consumer_id}",
3 "pcid": "{pcid}",
4 "first_name": "John",
5 "last_name": "Doe",
6 "email": "john.doe@email.com",
7 "phone_number": "425-555-1212",
8 "date_of_birth": "1999-10-06",
9 "tax_identifier": "123-45-6789",
10 "address_line1": "121 Big Creek",
11 "address_city": "Tuscaloosa",
12 "address_state": "AL",
13 "address_zip": "35405"
14}

Response

1{
2 "id": "bce4e19c-69fe-4af0-8ff7-6652f7265018",
3 "pcid": "8d397680-deb1-44fe-a6fa-7454e8843fb7",
4 "first_name": "John",
5 "last_name": "Doe",
6 "email": "john.doe@email.com",
7 "is_active": true,
8 "kyc_status": "Complete",
9 "phone_number": "425-555-1212",
10 "date_of_birth": "1999-10-06",
11 "tax_id_type": "SSN",
12 "tax_identifier": "***-**-6789",
13 "address_line1": "121 Big Creek",
14 "address_line2": null,
15 "address_city": "Tuscaloosa",
16 "address_state": "AL",
17 "address_zip": "354050000"
18}

Upwardli sends out a consumer.created webhook message to your server. The Upwardli Servers will send a webhook message to you with the following general schema, indicating that the consumer record was created on our side.

1{
2 "id": "ea04f0a8-b005-47cd-ba33-b02a00c0c426",
3 "created_at": "2023-06-23T07:41:50.45-04:00",
4 "event_name": "consumer.created",
5 "partner_id": "2f221c90-b82d-4e12-9bfd-ae8301097de3",
6 "resources": ["https://api-sandbox.upwardli.com/v2/consumers/{consumer_id}"],
7 "last_attempted_at": "2023-06-23T07:41:50.45-04:00"
8}

You Link the Upwardli ID to your Local Object. Upon receiving the webhook message, you will parse it for the eventName property and determine that this message means that a new consumer was created. You can then call the url in the resources property to get information about that consumer.

Example of output via API - assuming the consumer stopped before complete KYC and that you did not pre-fill any data for that user.

NOTE: At the time of creation, the user has not completed KYC, so their personal data has not been captured and will be null in the response body.

Onboarding Flow UI Specifics

Our onboarding endpoints expose hooks into the custom onboarding workflows created for your consumers. Each step/section can be completed individually and in any order. API-based Consumer onboarding can begin once the consumer object has been created.

The details below outline the standard flow of onboarding a consumer:

  1. Get Started
  2. Verify the Consumer’s Identity (KYC)
  3. [optional] Provide Underwriting decisioning
  4. [optional] Provide product decision details
  5. Accept Terms

Additionally, we support adding per-consumer metadata to each onboarding object.

Step 1: Get Started

To start the onboarding workflow for a user, you post a message containing the pcid of the consumer and an onboarding_template_id value of card_onboarding. The API will return a partially hydrated onboarding object containing the consumer’s current onboarding state.

POST https://api-sandbox.upwardli.com/v2/onboarding/

1Header
2{
3 "Authorization":"Bearer [access_token]"
4}

Body

1{
2 "pcid": "{consumer pcid}",
3 "onboarding_template_id": "card_onboarding"
4}

Response

1{
2 "id": "6a822b8a-0423-4ae7-bad6-02e09adab632",
3 "consumer": {
4 "id": "bce4e19c-69fe-4af0-8ff7-6652f7265018",
5 "pcid": "8d397680-deb1-44fe-a6fa-7454e8843fb7",
6 "first_name": "John",
7 "last_name": "Doe",
8 "email": "john.doe@email.com",
9 "is_active": true,
10 "kyc_status": "Complete",
11 "phone_number": "425-555-1212",
12 "date_of_birth": "1999-10-06",
13 "tax_id_type": "SSN",
14 "tax_identifier": "***-**-6789",
15 "address_line1": "121 Big Creek",
16 "address_line2": null,
17 "address_city": "Tuscaloosa",
18 "address_state": "AL",
19 "address_zip": "354050000"
20 },
21 "kyc": {
22 "inquiry_template_id": null
23 "inquiry_ids": null
24 },
25 "e_sign": {
26 "agreement_accepted": null,
27 "agreement_accepted_date": null
28 },
29 "product": {
30 "product_id": null
31 },
32 "underwriting": {
33 "result": null,
34 "data": null
35 },
36 "previous_step": {
37 "slug": "get_started",
38 },
39 "current_step": {
40 "slug": "verify_identity",
41 }
42}

Step 2: Verify the Consumer’s Identity (KYC)

Each consumer will see an entry screen that will highlight the value props and also include the appropriate disclaimers for the product.

POST https://api-sandbox.upwardli.com/v2/onboarding/{onboarding_id}/verify_identity

1Header
2{
3 "Authorization":"Bearer [access_token]"
4}

Body

1{
2 "inquiry_id": "inq_be55e136-2ca9-4f20-b262-4a1004f27e2e"
3}

Response

1{
2 "id": "6a822b8a-0423-4ae7-bad6-02e09adab632",
3 "consumer": {
4 "id": "bce4e19c-69fe-4af0-8ff7-6652f7265018",
5 "pcid": "8d397680-deb1-44fe-a6fa-7454e8843fb7",
6 "first_name": "John",
7 "last_name": "Doe",
8 "email": "john.doe@email.com",
9 "is_active": true,
10 "kyc_status": "Complete",
11 "phone_number": "425-555-1212",
12 "date_of_birth": "1999-10-06",
13 "tax_id_type": "SSN",
14 "tax_identifier": "***-**-6789",
15 "address_line1": "121 Big Creek",
16 "address_line2": null,
17 "address_city": "Tuscaloosa",
18 "address_state": "AL",
19 "address_zip": "354050000"
20 },
21 "kyc": {
22 "inquiry_template_id": null
23 "inquiry_ids": [
24 "inq_be55e136-2ca9-4f20-b262-4a1004f27e2e",
25 "inq_bd77c402-b95b-4d58-8104-9652a25bc1e9"
26 ]
27 },
28 "e_sign": {
29 "agreement_accepted": null,
30 "agreement_accepted_date": null
31 },
32 "product": {
33 "product_id": null
34 },
35 "underwriting": {
36 "result": null,
37 "data": null
38 },
39 "previous_step": {
40 "slug": "get_started",
41 },
42 "current_step": {
43 "slug": "accept_terms",
44 }
45}

Step 3: Provide product decision details

The is optional step allows you to provide external data for decisioning for consumer underwriting.

POST https://api-sandbox.upwardli.com/v2/onboarding/{onboarding_id}/select-product

1Header
2{
3 "Authorization":"Bearer [access_token]"
4}

Body

1{
2 "product_id": "{product_id}"
3}

Response

1{
2 "id": "6a822b8a-0423-4ae7-bad6-02e09adab632",
3 "consumer": {
4 "id": "bce4e19c-69fe-4af0-8ff7-6652f7265018",
5 "pcid": "8d397680-deb1-44fe-a6fa-7454e8843fb7",
6 "first_name": "John",
7 "last_name": "Doe",
8 "email": "john.doe@email.com",
9 "is_active": true,
10 "kyc_status": "Complete",
11 "phone_number": "425-555-1212",
12 "date_of_birth": "1999-10-06",
13 "tax_id_type": "SSN",
14 "tax_identifier": "***-**-6789",
15 "address_line1": "121 Big Creek",
16 "address_line2": null,
17 "address_city": "Tuscaloosa",
18 "address_state": "AL",
19 "address_zip": "354050000"
20 },
21 "kyc": {
22 "inquiry_template_id": null
23 "inquiry_ids": [
24 "inq_be55e136-2ca9-4f20-b262-4a1004f27e2e",
25 "inq_bd77c402-b95b-4d58-8104-9652a25bc1e9"
26 ]
27 },
28 "e_sign": {
29 "agreement_accepted": null,
30 "agreement_accepted_date": null
31 },
32 "product": {
33 "product_id": "95630f7a-dc51-4c61-914b-14c26b99968c"
34 },
35 "underwriting": {
36 "result": "pass",
37 "data": "{\"key_1\":\"value_1\",\"key_2\":\"value_2\}"
38 },
39 "previous_step": {
40 "slug": "get_started",
41 },
42 "current_step": {
43 "slug": "accept_terms",
44 }
45}

Step 4: [optional] Provide Underwriting decisioning

The is optional step allows you to provide external data for decisioning for consumer underwriting.

POST https://api-sandbox.upwardli.com/v2/onboarding/{onboarding_id}/perform-underwriting

1Header
2{
3 "Authorization":"Bearer [access_token]"
4}

Body

1{
2 "result": "pass|fail",
3 "data": "{\"key_1\":\"value_1\",\"key_2\":\"value_2}"
4}

Response

1{
2 "id": "6a822b8a-0423-4ae7-bad6-02e09adab632",
3 "consumer": {
4 "id": "bce4e19c-69fe-4af0-8ff7-6652f7265018",
5 "pcid": "8d397680-deb1-44fe-a6fa-7454e8843fb7",
6 "first_name": "John",
7 "last_name": "Doe",
8 "email": "john.doe@email.com",
9 "is_active": true,
10 "kyc_status": "Complete",
11 "phone_number": "425-555-1212",
12 "date_of_birth": "1999-10-06",
13 "tax_id_type": "SSN",
14 "tax_identifier": "***-**-6789",
15 "address_line1": "121 Big Creek",
16 "address_line2": null,
17 "address_city": "Tuscaloosa",
18 "address_state": "AL",
19 "address_zip": "354050000"
20 },
21 "kyc": {
22 "inquiry_template_id": null
23 "inquiry_ids": [
24 "inq_be55e136-2ca9-4f20-b262-4a1004f27e2e",
25 "inq_bd77c402-b95b-4d58-8104-9652a25bc1e9"
26 ]
27 },
28 "e_sign": {
29 "agreement_accepted": null,
30 "agreement_accepted_date": null
31 },
32 "product": {
33 "product_id": null
34 },
35 "underwriting": {
36 "result": "pass",
37 "data": "{\"key_1\":\"value_1\",\"key_2\":\"value_2\}"
38 },
39 "previous_step": {
40 "slug": "get_started",
41 },
42 "current_step": {
43 "slug": "accept_terms",
44 }
45}

Step 5: Accept Terms

Once a user has accepted the terms of their loan + card agreements, you can update their onboarding workflow to reflect the date/time that the agreements were accepted.

POST https://api-sandbox.upwardli.com/v2/onboarding/{onboarding_id}/accept-terms/

1Header
2{
3 "Authorization":"Bearer [access_token]"
4}

Body

1{
2 "agreement_accepted": true,
3 "agreement_accepted_date": "2025-05-11T14:47:56.152870Z"
4}

Response

1{
2 "id": "6a822b8a-0423-4ae7-bad6-02e09adab632",
3 "consumer": {
4 "id": "bce4e19c-69fe-4af0-8ff7-6652f7265018",
5 "pcid": "8d397680-deb1-44fe-a6fa-7454e8843fb7",
6 "first_name": "John",
7 "last_name": "Doe",
8 "email": "john.doe@email.com",
9 "is_active": true,
10 "kyc_status": "Complete",
11 "phone_number": "425-555-1212",
12 "date_of_birth": "1999-10-06",
13 "tax_id_type": "SSN",
14 "tax_identifier": "***-**-6789",
15 "address_line1": "121 Big Creek",
16 "address_line2": null,
17 "address_city": "Tuscaloosa",
18 "address_state": "AL",
19 "address_zip": "354050000"
20 },
21 "kyc": {
22 "inquiry_template_id": null
23 "inquiry_ids": [
24 "inq_be55e136-2ca9-4f20-b262-4a1004f27e2e",
25 "inq_bd77c402-b95b-4d58-8104-9652a25bc1e9"
26 ]
27 },
28 "e_sign": {
29 "agreement_accepted": true,
30 "agreement_accepted_date": "2025-05-11T14:47:56.152870Z"
31 },
32 "product": {
33 "product_id": "95630f7a-dc51-4c61-914b-14c26b99968c"
34 },
35 "underwriting": {
36 "result": "pass",
37 "data": "{\"key_1\":\"value_1\",\"key_2\":\"value_2\}"
38 },
39 "previous_step": {
40 "slug": "get_started",
41 },
42 "current_step": {
43 "slug": "accept_terms",
44 }
45}

Step 6: Submit Loan

Once a user has accepted the terms of their loan + card agreements, you are ready to submit their loan data. This step will also begin to provision their cards and any associated loans and bank accounts

After onboarding completion

  • The consumer bank account and card may not be open at this point while we are completing the onboarding with the bank. Once the accounts and card are provisioned you will receive a webhook message called PaymentCard.Created
  • If a user doesn’t order a physical to start they can order under card management. A partner can order on behalf of a user by calling the card.order API

POST https://api-sandbox.upwardli.com/v2/onboarding/{onboarding_id}/submit-loan/

1Header
2{
3 "Authorization":"Bearer [access_token]"
4}

Body

1{}

Response

1{
2 "id": "6a822b8a-0423-4ae7-bad6-02e09adab632",
3 "consumer": {
4 "id": "bce4e19c-69fe-4af0-8ff7-6652f7265018",
5 "pcid": "8d397680-deb1-44fe-a6fa-7454e8843fb7",
6 "first_name": "John",
7 "last_name": "Doe",
8 "email": "john.doe@email.com",
9 "is_active": true,
10 "kyc_status": "Complete",
11 "phone_number": "425-555-1212",
12 "date_of_birth": "1999-10-06",
13 "tax_id_type": "SSN",
14 "tax_identifier": "***-**-6789",
15 "address_line1": "121 Big Creek",
16 "address_line2": null,
17 "address_city": "Tuscaloosa",
18 "address_state": "AL",
19 "address_zip": "354050000"
20 },
21 "kyc": {
22 "inquiry_template_id": null
23 "inquiry_ids": [
24 "inq_be55e136-2ca9-4f20-b262-4a1004f27e2e",
25 "inq_bd77c402-b95b-4d58-8104-9652a25bc1e9"
26 ]
27 },
28 "e_sign": {
29 "agreement_accepted": true,
30 "agreement_accepted_date": "2025-05-11T14:47:56.152870Z"
31 },
32 "product": {
33 "product_id": "95630f7a-dc51-4c61-914b-14c26b99968c"
34 },
35 "underwriting": {
36 "result": "pass",
37 "data": "{\"key_1\":\"value_1\",\"key_2\":\"value_2\}"
38 },
39 "previous_steps": [
40 {
41 "slug": "perform_underwriting"
42 },
43 {
44 "slug": "select_product"
45 },
46 {
47 "slug": "accept_terms"
48 },
49 {
50 "slug": "verify_identity"
51 },
52 {
53 "slug": "get_started"
54 }
55 ],
56 "current_steps": null
57}

Managing Metadata on the Onboarding Object

You can add/update metadata on the onboarding object as a set of key/value pairs.

Example: Adding Metadata

POST https://api-sandbox.upwardli.com/v2/onboarding/{onboarding_id}/metadata/

1Header
2{
3 "Authorization":"Bearer [access_token]"
4}

Body

1{
2 "metadata": {
3 "key_1": "value_1",
4 "key_2": "value_2",
5 "key_3": "value_3"
6 }
7}

Response

1{
2 "id": "6a822b8a-0423-4ae7-bad6-02e09adab632",
3 "consumer": {
4 "id": "bce4e19c-69fe-4af0-8ff7-6652f7265018",
5 "pcid": "8d397680-deb1-44fe-a6fa-7454e8843fb7",
6 "first_name": "John",
7 "last_name": "Doe",
8 "email": "john.doe@email.com",
9 "is_active": true,
10 "kyc_status": "Complete",
11 "phone_number": "425-555-1212",
12 "date_of_birth": "1999-10-06",
13 "tax_id_type": "SSN",
14 "tax_identifier": "***-**-6789",
15 "address_line1": "121 Big Creek",
16 "address_line2": null,
17 "address_city": "Tuscaloosa",
18 "address_state": "AL",
19 "address_zip": "354050000"
20 },
21 "kyc": {
22 "inquiry_template_id": null
23 "inquiry_ids": [
24 "inq_be55e136-2ca9-4f20-b262-4a1004f27e2e",
25 "inq_bd77c402-b95b-4d58-8104-9652a25bc1e9"
26 ]
27 },
28 "e_sign": {
29 "agreement_accepted": true,
30 "agreement_accepted_date": "2025-05-11T14:47:56.152870Z"
31 },
32 "product": {
33 "product_id": "95630f7a-dc51-4c61-914b-14c26b99968c"
34 },
35 "underwriting": {
36 "result": "pass",
37 "data": "{\"key_1\":\"value_1\",\"key_2\":\"value_2\}"
38 },
39 "metadata": {
40 "key_1": "value_1",
41 "key_2": "value_2",
42 "key_3": "value_3",
43 },
44 "previous_step": {
45 "slug": "get_started",
46 },
47 "current_step": {
48 "slug": "accept_terms",
49 }
50}

Example: Updating Metadata

PUT https://api-sandbox.upwardli.com/v2/onboarding/{onboarding_id}/metadata/

1Header
2{
3 "Authorization":"Bearer [access_token]"
4}

Body

1{
2 "key_1": "new_value",
3 "key_4": "value_4"
4}

Response

1{
2 "id": "6a822b8a-0423-4ae7-bad6-02e09adab632",
3 "consumer": {
4 "id": "bce4e19c-69fe-4af0-8ff7-6652f7265018",
5 "pcid": "8d397680-deb1-44fe-a6fa-7454e8843fb7",
6 "first_name": "John",
7 "last_name": "Doe",
8 "email": "john.doe@email.com",
9 "is_active": true,
10 "kyc_status": "Complete",
11 "phone_number": "425-555-1212",
12 "date_of_birth": "1999-10-06",
13 "tax_id_type": "SSN",
14 "tax_identifier": "***-**-6789",
15 "address_line1": "121 Big Creek",
16 "address_line2": null,
17 "address_city": "Tuscaloosa",
18 "address_state": "AL",
19 "address_zip": "354050000"
20 },
21 "kyc": {
22 "inquiry_template_id": null
23 "inquiry_ids": [
24 "inq_be55e136-2ca9-4f20-b262-4a1004f27e2e",
25 "inq_bd77c402-b95b-4d58-8104-9652a25bc1e9"
26 ]
27 },
28 "e_sign": {
29 "agreement_accepted": true,
30 "agreement_accepted_date": "2025-05-11T14:47:56.152870Z"
31 },
32 "product": {
33 "product_id": "95630f7a-dc51-4c61-914b-14c26b99968c"
34 },
35 "underwriting": {
36 "result": "pass",
37 "data": "{\"key_1\":\"value_1\",\"key_2\":\"value_2\}"
38 },
39 "metadata": {
40 "key_1": "new_value",
41 "key_2": "value_2",
42 "key_3": "value_3",
43 "key_4": "value_4",
44 },
45 "previous_step": {
46 "slug": "get_started",
47 },
48 "current_step": {
49 "slug": "accept_terms",
50 }
51}

Getting Information on an In-Progress Onboarding

Once a user has accepted the terms of their loan + card agreements, you are ready to submit their loan data. This step will also begin to provision their cards and any associated loans and bank accounts

After onboarding completion

  • The consumer bank account and card may not be open at this point while we are completing the onboarding with the bank. Once the accounts and card are provisioned you will receive a webhook message called PaymentCard.Created
  • If a user doesn’t order a physical to start they can order under card management. A partner can order on behalf of a user by calling the card.order API

POST https://api-sandbox.upwardli.com/v2/onboarding/{onboarding_id}

1Header
2{
3 "Authorization":"Bearer [access_token]"
4}

Body

1{}

Response

1{
2 "id": "6a822b8a-0423-4ae7-bad6-02e09adab632",
3 "consumer": {
4 "id": "bce4e19c-69fe-4af0-8ff7-6652f7265018",
5 "pcid": "8d397680-deb1-44fe-a6fa-7454e8843fb7",
6 "first_name": "John",
7 "last_name": "Doe",
8 "email": "john.doe@email.com",
9 "is_active": true,
10 "kyc_status": "Complete",
11 "phone_number": "425-555-1212",
12 "date_of_birth": "1999-10-06",
13 "tax_id_type": "SSN",
14 "tax_identifier": "***-**-6789",
15 "address_line1": "121 Big Creek",
16 "address_line2": null,
17 "address_city": "Tuscaloosa",
18 "address_state": "AL",
19 "address_zip": "354050000"
20 },
21 "kyc": {
22 "inquiry_template_id": null
23 "inquiry_ids": [
24 "inq_be55e136-2ca9-4f20-b262-4a1004f27e2e",
25 "inq_bd77c402-b95b-4d58-8104-9652a25bc1e9"
26 ]
27 },
28 "e_sign": {
29 "agreement_accepted": true,
30 "agreement_accepted_date": "2025-05-11T14:47:56.152870Z"
31 },
32 "product": {
33 "product_id": "95630f7a-dc51-4c61-914b-14c26b99968c"
34 },
35 "underwriting": {
36 "result": "pass",
37 "data": "{\"key_1\":\"value_1\",\"key_2\":\"value_2\}"
38 },
39 "previous_steps": [
40 {
41 "slug": "perform_underwriting"
42 },
43 {
44 "slug": "select_product"
45 },
46 {
47 "slug": "accept_terms"
48 },
49 {
50 "slug": "verify_identity"
51 },
52 {
53 "slug": "get_started"
54 }
55 ],
56 "current_steps": null
57}

Managing Metadata on the Onboarding Object

Working with the Persona Control

The next section describes best practices for integrating the Persona embedded controls within your existing onboarding flow.

You can pre-fill data for your consumer to reduce onboarding friction. If you want to pre-fill data for your consumer see the section entitled: “KYC Data Pre-Fill” below.

KYC Details

Consumer Completes the KYC step(s)

Once the user has successfully completed KYC, then we will send a further webhook with an event_name of consumer.updated

1{
2 "id": "ea04f0a8-b005-47cd-ba33-b02a00c0c426",
3 "created_at": "2023-06-23T07:41:50.45-04:00",
4 "event_name": "consumer.updated",
5 "partner_id": "2f221c90-b82d-4e12-9bfd-ae8301097de3",
6 "resources": ["https://api-sandbox.upwardli.com/v2/consumers/{consumer_id}"],
7 "last_attempted_at": "2023-06-23T07:41:50.45-04:00"
8}

When you retrieve the updated consumer record related to this webhook, you will see that the kyc_status value has changed to "kyc_status": "Complete", indicating that this consumer has successfully completed the KYC step. In some cases, we will need to complete a manual review of the information provided by the consumer.

This webhook will also allow you to see the KYC information that was provided by the consumer when completing this step. We do not provided the full tax_identifier.

NOTE: KYC completed does not mean the consumer has completed onboarding or that a card product has been provisioned.

1{
2 "id": "{consumer_id}",
3 "pcid": "{pcid}",
4 "first_name": "John",
5 "last_name": "Doe",
6 "email": "john.doe@gmail.com",
7 "is_active": true,
8 "kyc_status": "Complete",
9 "phone_number": "+12065559034",
10 "date_of_birth": "2000-01-01",
11 "tax_id_type": "SSN",
12 "tax_identifier": "***-**-1234",
13 "address_line1": "100 Main Street",
14 "address_line2": null,
15 "address_city": "Tuscaloosa",
16 "address_state": "AL",
17 "address_zip": "354050000"
18}

TIP: If you do not receive the webhook you can call the Consumer endpoint to retrieve the consumer details.

GET https://api-sandbox.upwardli.com/v2/consumer/{id}

Optional: KYC Data Pre-Fill

Before loading the embedded component, you can pre populate data for a consumer by calling the api: POST: https://api-sandbox.upwardli.com/v2/consumer/ and providing the following fields:

Pre-filled KYC

Edge Cases / Unhappy path:

  1. If a user does not complete KYC, then you will only receive the consumer.created message
  2. If a user fails KYC, then we will send a consumer.updated webhook, with a kyc_status value of Failed. We will not open a credit line for any users who do not pass KYC.

Example of a Complete Onboarding Object

1{
2 "id": "6a822b8a-0423-4ae7-bad6-02e09adab632",
3 "consumer": {
4 "id": "bce4e19c-69fe-4af0-8ff7-6652f7265018",
5 "pcid": "8d397680-deb1-44fe-a6fa-7454e8843fb7",
6 "first_name": "John",
7 "last_name": "Doe",
8 "email": "john.doe@mailinator.com",
9 "is_active": true,
10 "kyc_status": "Complete",
11 "phone_number": "425-555-1212",
12 "date_of_birth": "1999-10-06",
13 "tax_id_type": "SSN",
14 "tax_identifier": "***-**-8455",
15 "address_line1": "121 Big Creek",
16 "address_line2": null,
17 "address_city": "Tuscaloosa",
18 "address_state": "AL",
19 "address_zip": "354050000"
20 },
21 "kyc": {
22 "inquiry_template_id": null
23 "inquiry_ids": [
24 "inq_be55e136-2ca9-4f20-b262-4a1004f27e2e",
25 "inq_bd77c402-b95b-4d58-8104-9652a25bc1e9"
26 ]
27 },
28 "e_sign": {
29 "agreement_accepted": null,
30 "agreement_accepted_date": null
31 },
32 "product": {
33 "product_id": "95630f7a-dc51-4c61-914b-14c26b99968c"
34 },
35 "underwriting": {
36 "result": "pass",
37 "data": "{\"key_1\":\"value_1\",\"key_2\":\"value_2\}"
38 },
39 "previous_step": {
40 "slug": "get_started",
41 },
42 "current_step": {
43 "slug": "accept_terms",
44 }
45}

Post Onboarding API Interactions

Once a consumer is onboarded you have two option to display consumer account and card details.

  1. Embedded widget - we display the UI for you in our hosted components, you have control over the look and feel but not the layout.
  2. API - you query our platform for the raw data and have full control of how you display it in your own UI (beyond what is listed in the box below)

For PCI reasons you will also need to use our embedded widget for Card Display and Card Management such as PIN reset, Freeze / Unfreeze, and Lost / Stolen options.

Card Management

The card management widget is intended to give consumers the ability to view their card, update actions tied to their card (transaction history, PIN set, ATM locator, freeze a card). A consumer will also be able to view their credit score, see statements, make payments and initiate transfers.

Card Management via API

When using our API method post onboarding you will be able to pull specific information regarding card details, transfers, credit insights and other actions directly into your app or website. The only two areas where you will need to use our standalone embedded widgets are (1) card image and (2) card details (i.e PIN set, freeze card, etc).

Authentication

You will need to authenticate to get access to the APIs you will use the URL below and the a Partner API Token with the applicable API url.

Important Parameters

ParameterValueNotes
access*tokenPartner API token
redirect_urlURL*(optional)_ The URL to redirect the web component to once the consumer has completed onboarding.
api_urlURLSee API table below

Card Image

This entry spot will provide a PCI compliant way to display the card image and transaction details for the user. A user will be able to add their card details to their Apple or Google mobile wallet manually. In-app push provisioning will be available in 2H 2025.

Card Image

Below is a list of the API calls used to populate the Card Management embedded component.

Example: Payment Card

GET https://api-sandbox.upwardli.com/v2/consumers/{consumer_id}/payment-cards/

1Header
2{
3 "Authorization":"Bearer [access_token]"
4}

Response

1{
2 "count": 1,
3 "next": null,
4 "previous": null,
5 "results": [
6 {
7 "id": "4a2472ea-75d9-4448-a4f4-e081a324e176",
8 "consumer_id": "00000000-0000-0000-0000-000000000003",
9 "status": "active",
10 "emboss_hold": true,
11 "available_balance": 197.02,
12 "account_number": "1234567890",
13 "routing_number": "021214891",
14 "created_at": "2025-02-05T22:57:31.749142Z"
15 }
16 ]
17}

Partner + Product Endpoint

Get Partner Details

GET https://api-sandbox.upwardli.com/v2/partners/

1Header
2{
3 "Authorization":"Bearer [access_token]"
4}

Response

1{
2 "partner_id": "98ecf2e2-3cb8-4101-8532-9dbcdd87d0f9",
3 "name": "Grow",
4 "customer_service_number": null,
5 "customer_service_email": null,
6 "default_consumer_locale": "en_US"
7}

Get Partner Product Details

GET https://api-sandbox.upwardli.com/v2/partners/{partner_id}/products

1Header
2{
3 "Authorization":"Bearer [access_token]"
4}

Response

1{
2 "count": 2,
3 "next": null,
4 "previous": null,
5 "results": [
6 {
7 "id": "faaf9d7f-2fb3-4559-8741-f3700f52a76c",
8 "key": "SecuredCardGrow1",
9 "product_type": "subscription",
10 "description": "Grow Option 1"
11 },
12 {
13 "id": "e7c3dcdc-5e99-45b6-9437-26a31154aa0e",
14 "key": "SecuredCardGrow2",
15 "product_type": "subscription",
16 "description": "Grow Option 2"
17 }
18 ]
19}

Example: Accounts

GET https://api-sandbox.upwardli.com/v2/consumers/{consumer_id}/accounts/

1Header
2{
3 "Authorization":"Bearer [access_token]"
4}

Response

1{
2 "count": 2,
3 "next": null,
4 "previous": null,
5 "results": [
6 {
7 "id": "083959d1-8282-4512-a52e-5630a5af042f",
8 "consumer_id": "00000000-0000-0000-0000-000000000003",
9 "bank_name": "Upward Financial Inc",
10 "balance": 0,
11 "account_name": "Upwardli Credit Builder",
12 "account_number": "******7890",
13 "account_type": "Secured Card",
14 "account_routing_number": "*****4891",
15 "is_primary": false
16 },
17 {
18 "id": "bbd3005f-b6b0-40fe-975e-34bae4b20a5c",
19 "consumer_id": "00000000-0000-0000-0000-000000000003",
20 "bank_name": ".",
21 "balance": 0,
22 "account_name": "Account Name",
23 "account_number": "******6789",
24 "account_type": "checking",
25 "account_routing_number": "*****6789",
26 "is_primary": true
27 }
28 ]
29}

Example: Credit Insights

GET https://api-sandbox.upwardli.com/v2/credit-insights/{consumer_id}/summary/

1Header
2{
3 "Authorization":"Bearer [access_token]"
4}

Response

1{
2 "credit_score_card": {
3 "score": 655,
4 "change": 28,
5 "credit_usage": 14,
6 "total_tradelines": 3,
7 "payment_history": 2,
8 "credit_inquiries": 1,
9 "credit_age": 35,
10 "debt_collection_count": 1,
11 "report_date": "2025-01-06",
12 "late_payment_percentage": 0,
13 "total_public_records": 0,
14 "total_open_revolving_accounts": 0,
15 "total_open_collection_accounts": 0,
16 "total_bankruptcies": 0,
17 "credit_report_status": "NotOrdered"
18 },
19 "credit_score_history": [
20 {
21 "month": "2025-01",
22 "score": 655
23 },
24 {
25 "month": "2024-12",
26 "score": 627
27 },
28 {
29 "month": "2024-11",
30 "score": 601
31 },
32 {
33 "month": "2024-10",
34 "score": 587
35 },
36 {
37 "month": "2024-09",
38 "score": 688
39 }
40 ]
41}

POST https://api-sandbox.upwardli.com/v2/accounts/

1Header
2{
3 "Authorization":"Bearer [access_token]"
4}
5Body
6{
7 "account_name": "Account Name"
8 "account_number": "0123456789"
9 "bank_name": " . "
10 "consumer_id": "00000000-0000-0000-0000-000000000003"
11 "routing_number": "123456789"
12}

Response

1{
2 "message": "Bank account created successfully",
3 "data": {
4 "id": "0f845102-f717-4bb9-a96a-c167a36148d6",
5 "consumer_id": "00000000-0000-0000-0000-000000000003",
6 "bank_name": ".",
7 "balance": 0,
8 "account_name": "Account Name",
9 "account_number": "******6789",
10 "account_type": "checking",
11 "account_routing_number": "*****6789",
12 "is_primary": true
13 "is_active": true
14 }
15}

Transactions

1{
2 "mcc": "{mcc_code}",
3 "merchant_id": "{merchant_id}",
4 "amount": "{trans_amount}",
5 "consumer_id": "{consumer.external_id}",
6 "auth_remarks": [
7 {
8 "code": "{response_code}",
9 "code_objects": "{response_code_objects}",
10 "description": "{response_code_description}"
11 }
12 ]
13}

Real-Time Transaction Handling

If you sign up to participate in the real-time authorization, we will sent purchase request data to a pre-defined endpoint on your system via HTTP POST. You will have 600ms to respond to this request, otherwise we will automatically decline the transaction.

Sample HTTP Headers:

1{
2 "content-type": "application/json",
3 "upwardli-signature": "{HMAC Signature}"
4}

Sample Message Body:

1{
2 "amount": "50.00",
3 "consumer_id": "{guid}",
4 "mcc": 1811,
5 "merchant_id": "HBLr4RErBXkzrYU",
6 "merchant_name": "COMPANY NAME",
7 "payment_card_id": "{Guid}",
8 "payment_reference_number": "9876543210",
9 "auth_remarks": [
10 {
11 "code": "51",
12 "code_objects": {
13 "51": ["Non-sufficient funds and not a force post"]
14 },
15 "description": "Insufficient funds (NSF). The authorization amount is larger than the cardholder's available balance. Mastercard only."
16 }
17 ]
18}

In order to approve the purchase, you must reply with the following response:

1{
2 "response_code": "00"
3}

Here are the most common Response codes

  • 00 — Success
  • 10 — Approved for partial amount
  • 51 — Insufficient funds
  • 59 — Suspected fraud
  • 63 — Suspected fraud (Mastercard only)

For a list of all possible response codes, you can view this page.

Example: Get Transaction History

GET https://api-sandbox.upwardli.com/v2/payment-cards/{payment_card_id}/transactions/

1Header
2{
3 "Authorization":"Bearer [access_token]"
4}

Response

1{
2 "count": 1,
3 "next": null,
4 "previous": null,
5 "results": [
6 {
7 "id": "3a8ee16d-a561-4265-886b-186c10e409f2",
8 "status": "posted",
9 "amount": "57.57",
10 "posted_at": "2025-02-03 23:13:38",
11 "effective_at": "2025-02-03 23:13:38",
12 "description": "Test Client Transaction: 0",
13 "direction": "credit"
14 }
15 ]
16}

Example: Create ACH

POSThttps://api-sandbox.upwardli.com/v2/payments/ach/

1Header
2{
3 "Authorization":"Bearer [access_token]"
4}
5Body
6{
7 "amount": 6
8 "consumer_id": "Consumer_id"
9 "originating_account_id": "Account_id"
10 "receiving_account_id": "Account_id"
11 "description": "ACH originating_account_id to receiving_account_id"
12}

Example: Fund Card

Note: payment_card_id is not bank account id

POST https://api-sandbox.upwardli.com/v2/simulations/payment-cards/{{payment_card_id}}/create-simulated-fund-card

1Header
2{
3 "Authorization":"Bearer [access_token]"
4}

Sandbox Activity Simulation Endpoints

Example: Simulate Card Auth

POST https://api-sandbox.upwardli.com/v2/simulations/payment-cards/{{payment_card_id}}/create-simulated-card-auth

1Header
2{
3 "Authorization":"Bearer [access_token]"
4}
5Body
6{
7 "amount": 10.00,
8 "association": "visa",
9 "merchant_name": "UPW"
10}

Example: Simulate Card Settlement

POST https://api-sandbox.upwardli.com/v2/simulations/payment-cards/{{payment_card_id}}/create-simulated-card-settlement

1Header
2{
3 "Authorization":"Bearer [access_token]"
4}
5Body
6{
7 "auth_id": "<auth_id_from_above>",
8 "settle_amount": 10.00
9}

Card Actions

Freeze

Note: payment_card_id is not bank account id

POST https://api-sandbox.upwardli.com/v2/payment-cards/{payment_card_id}/freeze

1Header
2{
3 "Authorization":"Bearer [access_token]"
4}
5Body
6{
7 "end_date": "input_formats=["%Y-%m-%d %H:%M:%S", "%Y-%m-%dT%H:%M:%S.%fZ"]",
8}

Unfreeze

Note: payment_card_id is not bank account id

POST https://api-sandbox.upwardli.com/v2/payment-cards/{payment_card_id}/unfreeze

1Header
2{
3 "Authorization":"Bearer [access_token]"
4}

Lost or Stolen

Note: payment_card_id is not bank account id

POST https://api-sandbox.upwardli.com/v2/payment-cards/{payment_card_id}/replace-lost-stolen/

1Header
2{
3 "Authorization":"Bearer [access_token]"
4}
5Body
6{
7 "card_status": "L|S"
8}

Replace Card

POST https://api-sandbox.upwardli.com/v2/payment-cards/{payment_card_id}/reissue/

1Header
2{
3 "Authorization":"Bearer [access_token]"
4}

Credit Goals

Credit Goals via API

Example: Credit Insights

GET https://api-sandbox.upwardli.com/v2/credit-insights/{consumer_id}/summary/

1Header
2{
3 "Authorization":"Bearer [access_token]"
4}

Response

1{
2 "credit_score_card": {
3 "score": 655,
4 "change": 28,
5 "credit_usage": 14,
6 "total_tradelines": 3,
7 "payment_history": 2,
8 "credit_inquiries": 1,
9 "credit_age": 35,
10 "debt_collection_count": 1,
11 "report_date": "2025-01-06",
12 "late_payment_percentage": 0,
13 "total_public_records": 0,
14 "total_open_revolving_accounts": 0,
15 "total_open_collection_accounts": 0,
16 "total_bankruptcies": 0,
17 "credit_report_status": "NotOrdered"
18 },
19 "credit_score_history": [
20 {
21 "month": "2025-01",
22 "score": 655
23 },
24 {
25 "month": "2024-12",
26 "score": 627
27 },
28 {
29 "month": "2024-11",
30 "score": 601
31 },
32 {
33 "month": "2024-10",
34 "score": 587
35 },
36 {
37 "month": "2024-09",
38 "score": 688
39 }
40 ]
41}

Profile

Important Parameters

ParameterValueNotes
access_tokenCustomer Access TokenA token that when used with the scope api:card-management:read
urlURLhttps://component-embedded-sandbox.upwardli.com/consumer-profile/?access_token={access_token}

Profile via API

Example: Statements

GET https://api-sandbox.upwardli.com/v2/consumers/{consumer_id}/statements

1Header
2{
3 "Authorization":"Bearer [access_token]"
4}

https://api-sandbox.upwardli.com/v2/consumers/{consumer_id}/statements/{pdf_filename}/download

General API information

If you are utilizing the API approach you will also want to access other APIs for requesting specific information about Upwardli resources

ResourceURLNotes
Consumer - Profile/v2/consumers/
Consumer - Statement/v2/consumers/{consumer_id}/statements
Consumer - Close/v2/payment-cards/{payment_card_id}/close/
Payments - Book Transfer/v2/payments/transfer

Embedded Component Endpoints

The Credit Builder Card API provides access to several different types of detail.

You decide which of the experiences you want to include:

ExperiencesURL / Endpoint(s)Description
Onboardinghttps://component-embedded-sandbox.upwardli.com/en/onboarding/card-product/?pcid={$partner_consumer_id}&access_token={$access_token}End to End Onboarding
Onboarding initial transferhttps://component-embedded-sandbox.upwardli.com/en/onboarding/transfer/?access_token={userscopetoken}Initial ACH to fund the account
Card Managementhttps://component-embedded-sandbox.upwardli.com/card-management?access_token={userscopetoken}Home
Card Details
Transactions
Card Management
Add External Accounts
PaymentsComing soon - available through card management or via API only. No stand alone option for external transfers is available todayTransfer Funds
Credit Goalshttps://component-embedded-sandbox.upwardli.com/en/credit-goals/?access_token={userscopetoken}Credit Insights
Credit Guides
Profilehttps://component-embedded-sandbox.upwardli.com/consumer-profile/?access_token={userscopetoken}Full Profile (excludes Statements and Payment Settings)
Card imagehttps://component-embedded-sandbox.upwardli.com/card-image?access_token={userscopetoken}Virtual card image
Card actionshttps://component-embedded-sandbox.upwardli.com/card-actions?access_token={userscopetoken}

Using the Upwardli Webhooks

By design we do not include extensive information about the webhook data sources. To learn more about the object referenced by the webhook, you can use the url[s] in the webhook body to make api requests.

Available Webhooks

ResourceEvents
ConsumersConsumer.Created
Consumer.Updated
Consumer.Closed
Consumer.KYC.Started
Consumer.KYC.Pending
Consumer.KYC.Completed
Consumer.KYC.Needs_Review
Consumer.KYC.Approved
Consumer.KYC.Failed
Payment CardsPaymentCard.Created
PaymentCard.Updated
PaymentCard.Closed
Payment Card TransactionsPaymentCard.Transaction.Auth
PaymentCard.Transaction.Auth_Expired
PaymentCard.Transaction.Archived
PaymentCard.Transaction.Settlement
ACH PaymentsACH.Sent
ACH.Received
ACH.Failed
Transfer PaymentsPayment.Transfer.Created
Payment.Transfer.Completed
Payment.Transfer.Failed

Webhook Message Description

All Upwardli webhook messages use the same format. To learn more about the resource(s) that are referenced by a specific webhook message, you can make an API request to the url(s) inside of the resources property.

1{
2 "id": "{Unique Webhook Id}",
3 "created_at": "Datetime: YYYY-MM-DDTHH:MM:SS.SS-TZ",
4 "event_name": "Webhook Message",
5 "partner_id": "{Your unique Partner Id}",
6 "resources": [
7 "https://{environment}.upwardli.com/v2/{resource}/{resource_id}"
8 ],
9 "last_attempted_at": "Datetime: YYYY-MM-DDTHH:MM:SS.SS-TZ"
10}

Webhook Authentication

Upwardli’s webhooks are secured using a Hashed Message Authentication Code (HMAC) in the webhook message header. The name of this header value is Upwardli-Signature. The Upwardli-Signature header contains two comma-separated key-value pairs encoding information about the request.

The first key-value pair will be in the form t=<unix_timestamp> and represents the unix time that the request was sent. The second key-value pair will be in the form v1=WeNeedSomethingHere, where the signature is a sha256 hash computed from the consumers webhook secret and a dot-separated string composed of the unix timestamp joined with the request body.

Note: computing the signature is sensitive to the exact characters input into the algortihm. The request data should be a json string with no whitespace formatting.

Sample Data

1`client_id => 'public'`
2
3`signature => 't=2023-10-12T20:44:58.082694+00:00,v1=263a5f79d899f7d5e04eb9a902b173d5901a9088966b932edca7174aec3d9e12'`
4
5`message => '{"id":"954935cb-be33-47a4-99af-ec8bbc662ec7","createdAt":"2023-10-05T17:39:21.097794+00:00","eventName":"consumer_created","partnerId":"cb739356-5f69-429c-8157-756876d08d27","resources":["api/v2/consumers/00000000-0000-0000-0000-000000000000"],"lastAttemptedAt":"2023-10-05T17:39:21.097794+00:00"}'`

Example decode in Python

11t, v1 = [value.split('=')[1] for value in request.headers['Upwardli-Signature'].split(',')]2computed_digest = hmac.new(<YOUR_CLIENT_ID>.encode(), (t + '.' + request.data.decode('utf-8')).encode(), 'sha256').hexdigest()34if hmac.compare_digest(v1, computed_digest):5 # Process webhook

Registering for Webhook Messages

POST https://api-sandbox.upwardli.com/v2/webhooks/registrations/

Header

1Header
2{
3 "Authorization":"Bearer [access_token]"
4}

Example Request Body

1{
2 "webhook_name": "{webhook_name}",
3 "endpoint": "{endpoint to receive messages at}"
4}

Get All Webhook Registrations

GET https://api-sandbox.upwardli.com/v2/webhooks/registrations/

Header

1Header
2{
3 "Authorization":"Bearer [access_token]"
4}

Example Response

1{
2 "count": 2,
3 "next": null,
4 "previous": null,
5 "results": [
6 {
7 "id": "{webhook_registration_id}",
8 "partner_id": "{partner_id}",
9 "webhook_name": "consumer.created",
10 "endpoint": "{webhook_endpoint}",
11 "status": "active",
12 "failures": 0,
13 "last_failure": null
14 },
15 {
16 "id": "{webhook_registration_id}",
17 "partner_id": "{partner_id}",
18 "webhook_name": "consumer.updated",
19 "endpoint": "{webhook_endpoint}",
20 "status": "active",
21 "failures": 0,
22 "last_failure": null
23 }
24}

Sandbox Testing and Activity Simulation

Example: Fund Card

Note: payment_card_id is not back account id

POST https://api-sandbox.upwardli.com/v2/simulations/payment-cards/{{payment_card_id}}/create-simulated-fund-card

1Header
2{
3 "Authorization":"Bearer [access_token]"
4}

Example: Simulate Card Auth

Note: payment_card_id is not back account id

POST https://api-sandbox.upwardli.com/v2/simulations/payment-cards/{{payment_card_id}}/create-simulated-card-auth

1Header
2{
3 "Authorization":"Bearer [access_token]"
4}
5Body
6{
7 "amount": 10.00,
8 "association": "visa",
9 "merchant_name": "Testing Transactions" length needs to greater than 5
10}

Example: Simulate Card Settlement

Note: payment_card_id is not bank account id

POST https://api-sandbox.upwardli.com/v2/simulations/payment-cards/{{payment_card_id}}/create-simulated-card-settlement

1Header
2{
3 "Authorization":"Bearer [access_token]"
4}
5Body
6{
7 "auth_id": "<auth_id_from_above_response>",
8 "settle_amount": 10.00
9}

Change Log

VersionDescription of Changes and Updates
v5.12.25Initial Document Creation