> For the complete documentation index, see [llms.txt](https://developers.bloomcredit.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developers.bloomcredit.io/enablement-services/enablement-services-getting-started.md).

# 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 for closing a user's tradeline, and deleting a user.

{% hint style="info" %}
**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.
{% endhint %}

### Terminology

* [**Plaid**](https://plaid.com/docs/) - 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 Bloom 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.

### Pre-requisites

* 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. An `organizationSlug` is also needed, and obtained during onboarding.
2. Create a user via the [RegisterOrganizationUser](/enablement-services/enablement_gql_ref.md#mutation-registerorganizationuser) GraphQL Mutation, with the user's personal information and the `organizationSlug` obtained above. *Optionally, check if a user exists with the email by using the* [*UserExistsWithEmail*](/enablement-services/enablement_gql_ref.md#query-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](#what-url-should-i-be-using) . Use this URL for all following GraphQL operations.
   2. This step requires Organization Scoped Authentication (see [Enablement Services Authentication](/enablement-services/enablement-services-getting-started/enablement-services-authentication.md)).

      ```
      Authorization: Bearer <organization_scoped_access_token>
      ```
   3. The `user_id` in the response needs to be stored against the consumer, and is required to interact with certain Enablement Services endpoints.

      > NOTE: If you've already registered [a webhook endpoint](/enablement-services/enablement-webhooks.md) you will receive a `user.created` event upon completion of this step

      <pre class="language-graphql" data-title="GraphQL"><code class="lang-graphql">mutation RegisterOrganizationUser {
          registerOrganizationUser(
              input: {
                  organizationSlug: "bloom"
                  email: "buzz.inga@bloomcredit.io"
                  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
                  }
              }
          }
      }
      </code></pre>
3. Authenticate the user via the `/v2/users/<user_id>/authenticate` HTTP endpoint. Use the API URL, *not* the GraphQL URL, from [What URL Should I Be Using?](#what-url-should-i-be-using). Replace `<user_id>` with the `user_id`from the previous step's response. The access token will be in the response body, to be used for authorizing the user.
   1. <pre class="language-json" data-title="Sample Response"><code class="lang-json">{
        "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.KMUFsIDTnFmyG3nMiGM6H9FNFUROf3wh7SmqJp-QV30",
        "expires_in": 7200,
        "token_type": "Bearer"
      }
      </code></pre>
   2. This token is valid for 2 hours. Upon expiration, regenerate one following the same process.
   3. There may be a slight delay of no more than 10 seconds between user creation, and when authentication can be performed.
   4. Use Organization Scoped Authentication, just as in the previous step.

      ```
      curl --location --request POST 'https://api.bloomplus.dev/v2/users/<user_id>/authenticate' \
      --header 'Authorization: Bearer <organization_scoped_access_token>'
      ```
4. For the remaining steps, use the user scoped access token obtained in Step 3 for authentication unless otherwise stated. Provide the token as a bearer token in the headers. This is referred to as User Scoped Authentication (see [Enablement Services Authentication](/enablement-services/enablement-services-getting-started/enablement-services-authentication.md)). Replace `user_scoped_access_token` with the user's access token.

   ```
   Authorization: Bearer <user_scoped_access_token>
   ```
5. Check that the newly created user exists with the [Me](/enablement-services/enablement_gql_ref.md#query-me) GraphQL query. Make sure you are using the User Scoped access token from the previous step for authentication.

   <pre class="language-graphql" data-title="GraphQL"><code class="lang-graphql">query Me {
       me {
           id
           email
           phoneNumber
           status
           notificationPreferences
           createdAt
           updatedAt
           syncedAt
           closedAt
           name {
               first
               middle
               last
           }
       }
   }

   </code></pre>
6. Obtain a connection token from Plaid. See [Plaid Processor Tokens](/enablement-services/enablement-services-getting-started/plaid-processor-tokens.md).
   1. The best sync times in the Bloom Aggregator occur when the Plaid [SYNC\_UPDATES\_AVAILABLE](https://plaid.com/docs/transactions/webhooks/#integrating-the-update-notification-webhook) webhook has been received with the field `historical_update_complete` set to `true`. Waiting for this update allows Bloom to import the full transaction history, instead of having to poll for the status periodically (potentially wasting import time).
7. All processor tokens created in Step 6 will be passed into the [ImportPlaidProcessorTokens](/enablement-services/enablement_gql_ref.md) mutation in a single request to import the processor tokens.
   1. This will return two lists. One list contains a list of the created connection object and corresponding token, one for each successfully imported token. The other list contains contains a list of each failed token and a corresponding error code. This will start a workflow in the background to ingest the user's transactions into Bloom Enablement Services. If an error is encountered importing the processor token, the connection's status will be updated. Updates can be viewed using the [Me](/enablement-services/enablement_gql_ref.md#query-me) query.

      > NOTE: If you've already registered [a webhook endpoint](/enablement-services/enablement-webhooks.md) you will receive one `connection.created` and one `user.synced` event for each token imported upon completion of this step. You will also receive `tradeline.created` webhooks if the imported tokens have recurring sets of transactions.

      <pre class="language-graphql" data-title="GraphQL"><code class="lang-graphql">mutation ImportPlaidProcessorTokens {
          importPlaidProcessorTokens(
              input: {
                  tokens: [
                      "processor-sandbox-448c2232-72d1-4592-92a3-dc1af242fead"
                  ]
              }
          ) {
              successes {
                  token
                  connection {
                      id
                      status
                      externalConnectionId
                  }
              }
              failures {
                  token
                  error
              }
          }
      }

      </code></pre>
8. Check that the user's transactions have been imported. These will be listed under the tradelines for the user in the [Me](/enablement-services/enablement_gql_ref.md#query-me) query, once the ingestion process is completed. The transaction ingestion is complete when the query shows the user's tradelines or once a `user.synced` webhook is received. A sample query is listed below, showing the first 5 tradelines for the user. *In sandbox, this takes about 5 minutes.*
   1. Tradelines will be listed as eligible or ineligible via the `isEligible` property. Tradelines with `isEligible == true` and `status == UNOPENED` are able to be opened in the next step.
      1. **Opening a tradeline begins the process of reporting it to credit bureaus.**
   2. The user's tradelines have been successfully imported when the user's `syncedAt` property has been set to a non-null date. This property will be updated whenever the user's tradelines are updated.
   3. In the response, the tradeline ID's will be under tradelines > edges > node > id for each tradeline.

{% code title="GraphQL" %}

```graphql
query Me {
    me {
        tradelines(input: { first: 5 }) {
            edges {
                cursor
                node {
                    id
                    merchant
                    category
                    status
                    isEligible
                    paymentFrequency
                    createdAt
                    updatedAt
                    transactions(input: { first: 5 }) {
                        edges {
                            cursor
                            node {
                                id
                                date
                                value {
                                    amount
                                    currency
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```

{% endcode %}

9. Open a tradeline to be reported with one of the corresponding open tradeline methods. Each bill type has a corresponding mutation to open the tradeline (ie. rent, utility, telco).
   1. You will need the `tradeline_id` obtained in the previous step as well as some extra details about the tradeline. Only tradelines with `status == UNOPENED` and `isEligible == true` can be opened.
   2. After opening a tradeline the status will change to `OPEN`. Retrieve the status from the response to verify. This tradeline will now be furnished to the bureaus.

      > NOTE: If you've already registered [a webhook endpoint](/enablement-services/enablement-webhooks.md) you will receive a `tradeline.opened` event upon completion of this step

      For example, to open a Utility tradeline:

{% code title="GraphQL" %}

```graphql
mutation OpenUtilityTradeline {
  openUtilityTradeline(
    id: "808b1fe0-8015-4df5-8bed-89d4acf68213"
    details: { isPrimaryAddress: true, utilityTypes: [WATER] }
  ) {
    tradeline {
      id
      status
      details {
        ... on UtilityTradelineDetails {
          isPrimaryAddress
          utilityTypes
        }
      }
    }
  }
}
```

{% endcode %}

<br>

### Closing a Tradeline

1. To close a tradeline, use the [CloseTradeline](/enablement-services/enablement_gql_ref.md#mutation-closetradeline) Mutation. All that is required is the `tradeline_id`, which can be found with the [Me](/enablement-services/enablement_gql_ref.md#query-me) query. This mutation requires an access token, as per [Enablement Services Authentication](/enablement-services/enablement-services-getting-started/enablement-services-authentication.md). Following the example in [Getting Started](#getting-started) , the mutation may look like:

{% code title="GraphQL" %}

```graphql
mutation CloseTradeline {
    closeTradeline(id: "808b1fe0-8015-4df5-8bed-89d4acf68213") {
        tradeline {
          id
          status
          details {
            ... on UtilityTradelineDetails {
              utilityTypes
              isPrimaryAddress
            }
          }
        }
    }
}
```

{% endcode %}

2. This will start a background workflow in the Bloom Enablement Services to ensure the tradeline will not be furnished.
3. After closing a tradeline the status will change to `CLOSED`. Retrieve the status from the response to verify.

   > NOTE: If you've already registered [a webhook endpoint](/enablement-services/enablement-webhooks.md) you will receive a `tradeline.closed_by_user` event upon completion of this step

### Delete a User

To delete a user, use the [DeleteMe](/enablement-services/enablement_gql_ref.md#mutation-deleteme) mutation. Use the user's access token, mentioned in [Enablement Services Authentication](/enablement-services/enablement-services-getting-started/enablement-services-authentication.md).

> NOTE: If you've already registered [a webhook endpoint](/enablement-services/enablement-webhooks.md) you will receive a `user.closed` event upon completion of this step

{% code title="GraphQL" %}

```graphql
mutation DeleteMe {
  deleteMe {
    user {
      id
      name {
        first
        middle
        last
      }
    }
  }
}
```

{% endcode %}

<br>

### Disconnecting a Connection

1. Call the [deleteConnection](/enablement-services/enablement_gql_ref.md#mutation-deleteconnection) GraphQL mutation to soft delete (disconnect) the connection.
2. Using the access token associated with your plaid processor token, you may wish to call the [Plaid item remove](https://plaid.com/docs/api/items/#itemremove) endpoint. This will invalidate the processor token

{% code title="GraphQL" %}

```graphql
mutation DeleteConnection {
    deleteConnection(id: "813bbced-d62a-4144-9f60-231f41ff5c16") {
        connection {
            id
            status
            externalConnectionId
        }
    }
}
```

{% endcode %}

<br>

### What URL Should I Be Using

* For sandbox environments:
  * API: `https://api.blomplus.dev`
  * GraphQL: `https://api.bloomplus.dev/v2/gql`
* For production environments:
  * API: `https://api.bloomplus.com`
  * GraphQL: `https://api.bloomplus.com/v2/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 processor tokens
* Production: can **not** import Plaid sandbox processor tokens (instead use production tokens)

Data is not shared between sandbox and production environments.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://developers.bloomcredit.io/enablement-services/enablement-services-getting-started.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
