---
updatedAt: 2026-08-04T16:50:32.000Z
agentTools:
  projectIndex: https://developer.validic.com/llms.txt
---

# Custom Marketplace

## What is the Custom Marketplace?

The Inform Marketplace is where users browse and connect health apps and devices so their data will be available to your system. The Custom Marketplace is one of three "flavors" of the Marketplace and it supports Cloud and Cellular sources only.

The Standard Marketplace is a Inform API JSON endpoint that returns all of the details you will need to build your own marketplace or connection list. Using the results you get from the Custom Marketplace, you can build your own user experience that is styled the way you want. The JSON is the same data we use to build our Standard Marketplace so there won't be a discrepancy in how the connection process works.

You have full control to build the behavior that your users will need -- just keep in mind that users will still need to be routed to the appropriate source for Cloud connections and that user experience is controlled by the source.

<Callout icon="📌" theme="default">
  ### Are you looking for an experience that supports mobile?

  If you're looking for a customizable solution that supports Cloud, Cellular, and Mobile, then Unified Sources is for you.
</Callout>

***

## What is the User Experience like?

The user experience is whatever you'd like it to be. Since Inform is simply providing you with details in a JSON format, you can use those details -- plus any that you want to add -- to create a connection workflow that works best for your users. All the styling and behavior is built by you.

If you'd like to get an idea of what a typical workflow might look like, then have a look at how our Standard Marketplace works.

The Standard Marketplace is designed to support Cloud and Cellular sources, just like the Custom Marketplace, and it provides a full, but basic, experience that you can use right away as either your own connection workflow or as inspiration for a custom workflow that you build using the Custom Marketplace.

<Callout icon="📘" theme="info">
  ### The Custom Marketplace is great for Cellular sources

  The Custom Marketplace is a great option if you want to use Cellular sources. With the Custom Marketplace, you can show or hide any sources that it returns.

  _Want to display Cellular Sources and let your users enter in their device identifier?_ You can do that with the Custom Marketplace.

  **_Want to get fancy and hide the Cellular Sources so your users don't have to worry about entering complicated device identifiers?_** You can do that with the Custom Marketplace too (along with the appropriate Direct Connection endpoint for the Cellular source).
</Callout>

Guide the user through the connection of their Cellular and Cloud Sources using the Custom Marketplace details to power your user experience, then be sure to display feedback to them based on whether you receive a message parameter in your redirect. If no parameter is present, the connection succeeded. If `?message=access_denied` is present, the user cancelled or denied permissions. Note: In rare edge cases, a connection failure may redirect without a message parameter—always verify the connection status via the Marketplace JSON. If a disconnect URL displays for the user, then the connection was successful. You will receive a connection event in the Streaming API for all successful Custom Marketplace connections, if your stream is set up to receive them.

If your user ever needs to disconnect from a source, they will need to navigate back to the Custom Marketplace where you should display a Disconnect button for any connected sources. You'll be able to tell whether a source is connected or not from the JSON returned by the Custom Marketplace.

<Callout icon="❗️" theme="error">
  ### Please plan your user documentation and user experience so that users can get back to the Custom Marketplace to disconnect, when appropriate.
</Callout>

***

## How do I use the Custom Marketplace?

The Custom Marketplace JSON can be requested simply by adding `&format=json` to the end of the user's marketplace URL, which you can get from the user's [profile](https://helpdocs.validic.com/reference/get-user-profile).

For example, if the user's marketplace url is:

```
https://syncmydevice.com/?token=4deee4c7c81e9b652d22c8999beaf7c972daa513c6cf6aaa6af636f8117bf929
```

then that user's Custom Marketplace can be accessed at:

```
https://syncmydevice.com/?token=4deee4c7c81e9b652d22c8999beaf7c972daa513c6cf6aaa6af636f8117bf929&format=json
```

BUT you're not done yet...because....

<Callout icon="🚧" theme="warn">
  ### Redirect URI is Required

  When using the Custom Marketplace, clients must append a `redirect_uri` query parameter to the `connect_url` and `disconnect_url` provided in the Custom Marketplace JSON response.
</Callout>

The `redirect_uri` ensures that users are properly redirected following the connection process, otherwise, the user will be redirected to the Standard Marketplace and not your super awesome custom connection experience.

Any `redirect_uri` that you specify must begin with `https://` or the resulting URL will fail. You should also url-encode your uri.

Here's an example of how to indicate the `redirect_uri` for a connection. In this example the user will be redirected to <https://www.google.com> (don't do this, of course -- this is just an example):

```
https://syncmydevice.com/?token=4deee4c7c81e9b652d22c8999beaf7c972daa513c6cf6aaa6af636f8117bf929&format=json&redirect_uri=https%3A%2F%2Fwww.google.com
```

Last, be sure that you can handle the message parameter that may be appended to your redirect\_uri. On success, no parameter is added—verify the connection via the marketplace JSON as you would expect a disconnect link on that vendor connection for the user. On failure or cancellation, `?message=access_denied` is typically appended. Best practice: Always verify the actual connection state via the Marketplace JSON rather than relying solely on the presence or absence of the message parameter.

### Setting Scope Overrides

<Callout icon="📘" theme="info">
  ### This feature is currently supported for Google Health only

  We plan to expand `scopes_override` support to other sources in the future. For now, adding this parameter to a `connect_url` for any source other than Google Health has no effect.
</Callout>

By default, the scopes requested from a user during a custom marketplace connection are whatever your organization has configured with us. If you're not sure what's set for your organization you can always ask our Customer Support team.

If you need more control on a per-connection basis, per user, you can override those default scopes at connection time by adding a `scopes_override` query parameter to the `connect_url`.&#x20;

**This feature is available in the custom marketplace only. It is not yet supported in the unified marketplace.**

A few things to know about how `scopes_override` works:

* Scope names must exactly match the source's own scope names. See the "Valid Scopes by Source" section below.
* To request more than one scope, separate them with commas.
* You should also url-encode the scopes.
* A small set of required scopes (like Settings) is always requested no matter what, since Inform needs those to function. That means you may still see an extra scope or two being requested depending on the source, if we need them for data processing.
* If a scope you pass is invalid, or isn't enabled for your org, it's silently dropped and the connection continues with whatever valid scopes remain (we log the drop on our end, but the user won't see an error for it).
* If `scopes_override` is empty, it's ignored, and your org's configured scopes are used instead. Same thing if you exclude `scopes_override` ; your org's configured scopes are used in that case.

<br />

#### Valid Scopes by Source

The scope names you pass in `scopes_override` must exactly match one of the values the source supports below. Any scope not listed here is treated as invalid and will be silently dropped from the request.&#x20;

Today, Google Health is the only source that supports `scopes_override`, but we'll add rows to this table as we extend support to other sources.

| Source          | Scope                                                                                                                                                                                                       | Description                             | Resource Type                       |
| --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------- | ----------------------------------- |
| `google_health` | `https://www.googleapis.com/auth/googlehealth.activity_and_fitness.readonly`<br />url-encoded: `https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fgooglehealth.activity_and_fitness.readonly`                       | Activity data                           | `summaries`, `workouts`, `intraday` |
| `google_health` | `https://www.googleapis.com/auth/googlehealth.health_metrics_and_measurements.readonly`<br />url-encoded: `https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fgooglehealth.health_metrics_and_measurements.readonly` | Vitals and body measures                | `measurements`                      |
| `google_health` | `https://www.googleapis.com/auth/googlehealth.sleep.readonly`<br />url-encoded: `https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fgooglehealth.sleep.readonly`                                                     | Sleep details                           | `sleep`                             |
| `google_health` | `https://www.googleapis.com/auth/googlehealth.nutrition.readonly`<br />url-encoded: `https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fgooglehealth.nutrition.readonly`                                             | Daily nutrient summaries and food items | `nutrition`                         |

<br />

#### Examples

Here's what the override looks like in practice. Assume this is your base connect URL:

```text
https://syncmydevice.com/connect/google_health?token=ae4fdfd364e42137af14b207eSAMPLEbcdefaae7b99e3e49361SAMPLE1eb0d
```

**Passing a single scope:**

```text
https://syncmydevice.com/connect/google_health?token=ae4fdfd364e42137af14b207eSAMPLEbcdefaae7b99e3e49361SAMPLE1eb0d&scopes_override=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fgooglehealth.sleep.readonly
```

Result: only the Sleep scope, plus the required Settings scope, is requested.

**Passing two scopes (comma-separated):**

```text
https://syncmydevice.com/connect/google_health?token=ae4fdfd364e42137af14b207eSAMPLEbcdefaae7b99e3e49361SAMPLE1eb0d&scopes_override=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fgooglehealth.activity_and_fitness.readonly%2Chttps%3A%2F%2Fwww.googleapis.com%2Fauth%2Fgooglehealth.sleep.readonly
```

Result: Activity, Sleep, and Settings scopes are requested.

**Passing two scopes where one is invalid or not configured for your org:**

```text
https://syncmydevice.com/connect/google_health?token=ae4fdfd364e42137af14b207eSAMPLEbcdefaae7b99e3e49361SAMPLE1eb0d&scopes_override=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fgooglehealth.activity_and_fitness.readonly%2CNOT_A_SCOPE
```

Result: `NOT_A_SCOPE` is dropped. Only Activity and Settings scopes are requested.

**Passing an empty scopes list:**

```text
https://syncmydevice.com/connect/google_health?token=ae4fdfd364e42137af14b207eSAMPLEbcdefaae7b99e3e49361SAMPLE1eb0d&scopes_override=
```

Result: the parameter is ignored, and your org's normally configured scope list is used.

**Passing a list with only invalid scopes:**

```text
https://syncmydevice.com/connect/google_health?token=ae4fdfd364e42137af14b207eSAMPLEbcdefaae7b99e3e49361SAMPLE1eb0d&scopes_override=INVALID%2Calso_invalid
```

Result: only the required Settings scope is requested, nothing else.

<br />

***

<br />

## What Does the Custom Marketplace look like?

Whatever you like! You're going to be building the user experience and styling it however you'd like.

Here's an example of what you get from the Custom Marketplace. These details will help you with your display so that you don't have to go hunt down a bunch of info like source name, logo images, and the like. We'll maintain all of this info for you.

You just have to build the user experience to display what you want from this info and route the user properly for connections and disconnections.

```Text Example Request
https://syncmydevice.com/?token=ae4fdfd364e42137af14b207eSAMPLEbcdefaae7b99e3e49361SAMPLE1eb0d&format=json&redirect_uri=https%3A%2F%2Fwww.google.com
```

<br />

```Text Example Response
[
    {
        "type": "omron",
        "connected": true,
        "logo_url": "//assets.prod.validic.com/cmapi/images/sources/omron.png",
        "disconnect_url": "https://syncmydevice.com/connect/omron?token=ae4fdfd364e42137af14b207eSAMPLEbcdefaae7b99e3e49361SAMPLE1eb0d"
    },
    {
        "type": "polar",
        "connected": true,
        "logo_url": "//assets.prod.validic.com/cmapi/images/sources/polar.png",
        "disconnect_url": "https://syncmydevice.com/connect/polar?token=ae4fdfd364e42137af14b207eSAMPLEbcdefaae7b99e3e49361SAMPLE1eb0d"
    },
    {
        "type": "fitbit",
        "connected": true,
        "logo_url": "//assets.prod.validic.com/cmapi/images/sources/fitbit.png",
        "disconnect_url": "https://syncmydevice.com/connect/fitbit?token=ae4fdfd364e42137af14b207eSAMPLEbcdefaae7b99e3e49361SAMPLE1eb0d"
    },
    {
        "type": "garmin",
        "connected": true,
        "logo_url": "//assets.prod.validic.com/cmapi/images/sources/garmin.png",
        "disconnect_url": "https://syncmydevice.com/connect/garmin?token=ae4fdfd364e42137af14b207eSAMPLEbcdefaae7b99e3e49361SAMPLE1eb0d"
    },
  ...
]
```