Getting Started

About

This guide provides instructions to create a user in Bloom Enablement Services, and the steps necessary to import that user's tradelines for furnishing. Also included are instructions covering closing a user's tradeline, and deleting a user.

🐝

TIP

A postman collection can be provided upon request with the Bloom Enablement Services endpoints (HTTP and GraphQL), as well as the Plaid Sandbox endpoints references in this guide.

Reference

  • Plaid - An aggregator. An aggregator handles creating connections to financial institutions and retrieving information about those connections like bank accounts and transactions. Currently, plaid is the only natively supported aggregator - contact Bloom support if you would like to use a different aggregator.
  • User - a user in enablement services represents a consumer. A user can have connections and tradelines.
  • Connection - a connection is used to pull tradeline data from an aggregator into Bloom Enablement Services.
  • Tradeline - a tradeline represents a user's account with recurring transactions.

Prerequisites

  • Completed Bloom onboarding process.
  • Create a Plaid account.To use a different aggregator, contact Bloom support.

Getting Started

  1. Obtain a Client ID and Client Secret for Authorization from the Bloom onboarding process. Your organization's slug is also needed, obtained during this process as well.
  2. Create a user using the RegisterOrganizationUser GraphQL Mutation, with the user's information and the organization slug obtained above. Optionally, check if a user exists with the email by using the UserExistsWithEmail GraphQL Query. In Bloom's sandbox environment, there is a limit of 100 users per organization. There is no limit in the production environment.
    1. Grab the correct GraphQL URL from What URL Should I be Using . Use this URL for all following GraphQL operations.
    2. Authorization is provided via the Client ID and Client Secret obtained in step 1 as a bearer token header. This step requires organization scoped authentication (see Enablement Services Authorization).
      Authorization: Bearer client_id:client_secret
      
    3. The user id in the response will be used in the next step, so hold on to it.
      mutation RegisterOrganizationUser {
          registerOrganizationUser(
              input: {
                  organizationSlug: "bloom"
                  email: "[email protected]"
                  phoneNumber: "+12345678901"
                  name: { first: "Buzz", last: "Inga" }
                  address: {
                      line1: "123 Main "
                      city: "Athens"
                      state: "FL"
                      country: "USA"
                      zipcode: "37745"
                      type: PRIMARY
                  }
                  dateOfBirth: { day: 14, month: 6, year: 1986 }
                  nationalId: "1234"
              }
          ) {
              user {
                  id
                  name {
                      first
                      middle
                      last
                  }
              }
          }
      }
      
  3. Authenticate the user via the /v1/users/authenticate/{{user_id}} HTTP endpoint. Use the API URL, not the GraphQL URL, from What URL Should I Be Using?. Replace {{user_id}} with the user id from the previous step's response. The response's body will be the session token, to be used for authorizing the user.
    1. This token is valid for 2 hours. When it expires, simply grab another one with this endpoint.
    2. There may be a slight delay of no more than 10 seconds between user creation, and when authentication can be performed.
    3. Use organization scoped authorization, just as in the previous step.
curl --location --request POST 'https://api.bloomplus.dev/v1/users/authenticate/{{user_id}}' \
--header 'Authorization: Bearer {{client_id}}:{{client_secret}}'
  1. From here on out, use the session token obtained in step 3 for authorization unless otherwise stated. Provide the token as a bearer token in the headers. This is referred to as user scoped authorization (see Enablement Services Authorization). Replace session_token with the user's session token (no quotes).

    Authorization: Bearer session_token
    
  2. Check that the newly created user exists with the Me GraphQL query. Make sure you are using the user scoped session token from the previous step for authorization.

    query Me {
        me {
            id
            email
            phoneNumber
            status
            notificationPreferences
            createdAt
            updatedAt
            syncedAt
            closedAt
            name {
                first
                middle
                last
            }
        }
    }
    
    
  3. Obtain a connection token from Plaid.

    1. For sandbox, see Getting Plaid Sandbox Token
  4. Use the ImportConnection Mutation to import a connection. Replace the token with the Plaid connection token. This will start a workflow in the background to ingest the user's transactions into Bloom Enablement Services.

    mutation ImportConnection {
        importConnection(token: "access-sandbox-faa83ce0-7bb4-4baa-a824-b746d5c99f28") {
            provider
            connectionId
        }
    }
    
  5. Check that the user's transactions have been imported. These will be listed under the tradelines for the user in the Me query, once the ingestion process is completed. The transaction ingestion is complete when the query shows the user's tradelines. A sample query is listed below, showing the first 5 tradelines for the user.

    1. In sandbox, this takes about 5 minutes.
    2. Tradelines will be listed as eligible or ineligible via the isEligible property. Eligible tradelines can be imported in the next step.
    3. In the response, the tradeline ID's will be under tradelines > edges > node > id for each tradeline.
query Me {
    me {
        tradelines(input: { first: 5 }) {
            edges {
                cursor
                node {
                    id
                    merchant
                    category
                    isOpen
                    isEligible
                    paymentFrequency
                    serviceAddress
                    servicePhone
                    leaseStartDate
                    utilityTypes
                    serviceAddressType
                    createdAt
                    updatedAt
                    transactions(input: { first: 5 }) {
                        edges {
                            cursor
                            node {
                                id
                                date
                                value {
                                    amount
                                    currency
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
  1. Open a tradeline to be reported with the OpenTradeline Mutation. The tradeline ID is obtained in the previous step. Only use an eligible tradeline. For example, to import a Rent tradeline:
mutation OpenTradeline {
    openTradeline(
        input: {
            servicePhone: "1234567890"
            serviceAddressType: PRIMARY
            leaseStartDate: "2025-01-01"
            agreements: {
                rent: { isPrimaryAddress: true, hasOtherMortgageOrRent: false }
            }
            tradelineId: "0195d95a-314e-7d42-9baf-862f83354110"
        }
    ) {
        attestation {
            agreements {
                rent {
                    isPrimaryAddress
                    hasOtherMortgageOrRent
                }
            }
        }
    }
}

  1. Upon importing a tradeline with the above mutation, Bloom Enablement Services will ingest the transactions from the aggregator. To verify that the tradeline has been successfully opened, use the Me query again. The imported tradeline should be listed with the isOpen property set to true. The tradeline is now ready to be furnished!

Closing a Tradeline

  1. To close a tradeline, use the CloseTradeline Mutation. All that is required is the tradeline ID, which can be found with the Me query. This mutation requires a session token, as per User Scoped Authentication. Following the example in Getting Started , the mutation may look like:
mutation CloseTradeline {
    closeTradeline(id: "0195d95a-314e-7d42-9baf-862f83354110") {
        tradeline {
            id
            merchant
            category
            isOpen
            isEligible
            paymentFrequency
            serviceAddress
            servicePhone
            leaseStartDate
            utilityTypes
            serviceAddressType
            createdAt
            updatedAt
        }
    }
}
  1. This will start a background workflow in the Bloom Enablement Services to ensure the tradeline will not be furnished.
  2. The status of a closed tradeline can be checked with the Me query. The tradeline will be shown in the query result with the property "isOpen": false, and isEligible: false.

Delete a User

To delete a user, use the DeleteMe mutation. Use the user's session token, mentioned in User Scoped Authentication.


What URL Should I Be Using

  • For sandbox environments:
    • API: https://api.blomplus.dev
    • GraphQL: https://api.bloomplus.dev/gql
  • For production environments:
    • API: https://api.bloomplus.com
    • GraphQL: https://api.bloomplus.com/gql

Sandbox vs Production

Currently, there is one main difference between the Sandbox and Production environments in Bloom's Enablement Services:

  • Sandbox: can import Plaid sandbox access tokens
  • Production: can not import Plaid sandbox access tokens (instead use production tokens)

Data is not shared between sandbox and production environments.


Getting Plaid Sandbox Token

Plaid provides a custom user sandbox that can be used to create test users with test data for accounts and transactions. For detailed information, see the Plaid Documentation . These endpoints are also available in the Bloom Enablement Services Postman collection.

  1. Create a sandbox user in the Plaid UI. The video provided in the first link gives a good overview. Once you create a plaid account, create a test user in the Plaid UI under Developers > Sandbox page . Hold on to the username for the next step. When creating a sandbox user in plaid, we have had success with this config json.
    1. You may need to adjust the dates. A set of recurring payments must have one payment within the last 90 days to be considered eligible. One easy way adjust this payload is to prompt you favorite AI code editor with give me this JSON data but shift all dates forward X months , where X is a more recent set of months.
{
  "override_accounts": [
    {
      "type": "depository",
      "subtype": "checking",
      "transactions": [
        {
          "date_transacted": "2025-04-08",
          "date_posted": "2025-04-08",
          "amount": 1350,
          "description": "Rent payment",
          "currency": "USD"
        },
        {
          "date_transacted": "2025-03-08",
          "date_posted": "2025-03-08",
          "amount": 1350,
          "description": "Rent payment",
          "currency": "USD"
        },
        {
          "date_transacted": "2025-02-08",
          "date_posted": "2025-02-08",
          "amount": 1350,
          "description": "Rent payment",
          "currency": "USD"
        },
        {
          "date_transacted": "2025-04-03",
          "date_posted": "2025-04-03",
          "amount": 248,
          "description": "EVERGY MO WEST",
          "currency": "USD"
        },
        {
          "date_transacted": "2025-03-03",
          "date_posted": "2025-03-03",
          "amount": 221,
          "description": "EVERGY MO WEST",
          "currency": "USD"
        },
        {
          "date_transacted": "2025-02-03",
          "date_posted": "2025-02-03",
          "amount": 212,
          "description": "EVERGY MO WEST",
          "currency": "USD"
        },
        {
          "date_transacted": "2025-04-06",
          "date_posted": "2025-04-06",
          "amount": 115,
          "description": "Verizon Wireless Bill Pay",
          "currency": "USD"
        },
        {
          "date_transacted": "2025-03-06",
          "date_posted": "2025-03-06",
          "amount": 115,
          "description": "Verizon Wireless Bill Pay",
          "currency": "USD"
        },
        {
          "date_transacted": "2025-02-06",
          "date_posted": "2025-02-06",
          "amount": 115,
          "description": "Verizon Wireless Bill Pay",
          "currency": "USD"
        },
        {
          "date_transacted": "2025-04-02",
          "date_posted": "2025-04-02",
          "amount": 17.99,
          "description": "Netflix Subscription",
          "currency": "USD"
        },
        {
          "date_transacted": "2025-03-02",
          "date_posted": "2025-03-02",
          "amount": 17.99,
          "description": "Netflix Subscription",
          "currency": "USD"
        },
        {
          "date_transacted": "2025-02-02",
          "date_posted": "2025-02-02",
          "amount": 17.99,
          "description": "Netflix Subscription",
          "currency": "USD"
        },
        {
          "date_transacted": "2025-04-10",
          "date_posted": "2025-04-10",
          "amount": 120,
          "description": "HelloFresh Subscription",
          "currency": "USD"
        },
        {
          "date_transacted": "2025-03-10",
          "date_posted": "2025-03-10",
          "amount": 120,
          "description": "HelloFresh Subscription",
          "currency": "USD"
        },
        {
          "date_transacted": "2025-02-10",
          "date_posted": "2025-02-10",
          "amount": 120,
          "description": "HelloFresh Subscription",
          "currency": "USD"
        },
        {
          "date_transacted": "2025-04-01",
          "date_posted": "2025-04-01",
          "amount": 25,
          "description": "Water Company Water Bill",
          "currency": "USD"
        },
        {
          "date_transacted": "2025-03-01",
          "date_posted": "2025-03-01",
          "amount": 21,
          "description": "Water Company Water Bill",
          "currency": "USD"
        },
        {
          "date_transacted": "2025-02-01",
          "date_posted": "2025-02-01",
          "amount": 23,
          "description": "Water Company Water Bill",
          "currency": "USD"
        }
      ],
      "identity": {
        "names": [
          "John Doe"
        ],
        "phone_numbers": [
          {
            "primary": true,
            "type": "home",
            "data": "4673956022"
          }
        ],
        "emails": [
          {
            "primary": true,
            "type": "primary",
            "data": "[email protected]"
          }
        ],
        "addresses": [
          {
            "primary": true,
            "data": {
              "country": "US",
              "city": "Malakoff",
              "street": "2992 Cameron Road",
              "postal_code": "14236",
              "region": "NY"
            }
          }
        ]
      }
    }
  ]
}
  1. Obtain the Plaid client ID and secret from the Developers > Keys page.
  2. Get a Plaid Sandbox Token via the plaid API. Replace plaid_client_id and plaid_client_secret with your Plaid keys, and custom_username with your test user's username. Hang on the to public_token returned in the response. Make sure to include the identity and transactions products as shown below.
  3. The institution_id corresponds to a plaid sandbox institution. In this case, we wish to use a non-OAuth institution. See the Plaid documentation for more details.
  4. Since this is sandbox only, we bypass the Plaid Link process .
curl --location 'https://sandbox.plaid.com/sandbox/public_token/create' \
--header 'Content-Type: application/json' \
--data '{
    "client_id": "plaid_client_id",
    "secret": "plaid_client_secret",
    "institution_id": "ins_109508",
    "initial_products": ["identity", "transactions"],
    "options": {
        "override_username": "custom_username"
    }
}'
  1. Exchange the Plaid sandbox token for an access token. Replace plaid_client_id and plaid_client_secret with your Plaid keys, and plaid_sandbox_token with your Plaid public_token (the token returned in the previous step). Hold on to the access_token in the response.
  2. According to the Plaid documentation , this token does not expire.
curl --location 'https://sandbox.plaid.com/item/public_token/exchange' \
--header 'Content-Type: application/json' \
--data '{
    "client_id": "plaid_client_id",
    "secret": "plaid_client_secret",
    "public_token": "plaid_sandbox_token"
}'
  1. To test that your access token works, query the get accounts endpoint. This should correspond to the test data you provided when creating your test user in step 1. Replace plaid_client_id and plaid_client_secret with your Plaid keys, and plaid_access_token with your Plaid access_token.
curl --location 'https://sandbox.plaid.com/accounts/get' \
--header 'Content-Type: application/json' \
--data '{
    "client_id": "plaid_client_id",
    "secret": "plaid_client_secret",
    "access_token": "plaid_access_token"
}'

What’s Next

Head to the API Reference