> For the complete documentation index, see [llms.txt](https://docs.harmony.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.harmony.io/integrations/saas-applications/bring-your-own-app.md).

# Bring Your Own App

### About Bring Your Own App

Harmony provides built-in integrations for a wide range of SaaS applications. Bring Your Own App covers everything else — an internal tool, a niche vendor, a regional product, or an application whose API Harmony does not yet support. You run a small script that sends the application's user list and usage activity to Harmony over HTTPS.

Once the data arrives, the application behaves exactly like a built-in integration: it appears in your software inventory, its users are matched to employees, seats and license tiers are tracked, and activity feeds the same dashboards, access reviews, and license optimization workflows as every other connected app.

### What Bring Your Own App enables

| Capability        | Description                                                                    |
| ----------------- | ------------------------------------------------------------------------------ |
| User Discovery    | Surface the application's users in Harmony's software inventory                |
| License Tracking  | Report each user's tier and plan to understand billable use                    |
| Role Visibility   | Record the role each user holds, in the application's own terms                |
| Activity Tracking | Report per-user activity to identify active and inactive users                 |
| Cost Attribution  | Attribute spend or consumption to individual users                             |
| Any Application   | Works for any application you can query — no Harmony-side development required |

### The two kinds of data

Bring Your Own App accepts two data types. **Users is mandatory** — every application must push its user list. Usage is optional and adds activity on top.

|           | **Users**                                                             | **Usage**                                                    |
| --------- | --------------------------------------------------------------------- | ------------------------------------------------------------ |
| Answers   | *Who has access to this app?*                                         | *Who actually used it, and how much?*                        |
| Endpoint  | `POST /custom-push/v1/users`                                          | `POST /custom-push/v1/usage`                                 |
| Shape     | A complete list of every current user                                 | A list of dated activity records                             |
| Semantics | **Full replacement** — a snapshot                                     | **Additive** — deduplicated by your own event ID             |
| Send it   | Whenever your roster changes, or on a schedule                        | Daily, or as activity happens                                |
| Powers    | Seat counts, license tiers, roles, access reviews, offboarding checks | Active/inactive users, activity charts, license optimization |

Full field-by-field reference: [**Users data**](/integrations/saas-applications/bring-your-own-app/bring-your-own-app-users.md) and [**Usage data**](/integrations/saas-applications/bring-your-own-app/bring-your-own-app-usage.md).

{% hint style="warning" %}
**A users push replaces the entire user list.** Any user missing from your most recent push is removed from Harmony. Always send every current user in every push — never send only the users who changed. See [Users data](/integrations/saas-applications/bring-your-own-app/bring-your-own-app-users.md) for the full rules.
{% endhint %}

### Prerequisites

* **Harmony Account**: Active Harmony workspace with administrator access
* **Access Key**: A Bring Your Own App access key — [contact Harmony support](mailto:support@harmony.io) to request one
* **App ID**: A stable identifier for the application you are sending data about (see Step 2)
* **A way to run a script**: Anything that can make an HTTPS request on a schedule — a cron job, a CI pipeline, a serverless function, or an automation platform

### Set up Bring Your Own App

#### Step 1: Request an access key

Contact Harmony support and ask for a Bring Your Own App access key for your workspace. Support will provision a key with the permissions this API requires.

Treat the key like a password. Store it in a secrets manager or an environment variable — never commit it to source control.

#### Step 2: Choose your App ID

The **App ID** is how Harmony recognizes which application a push belongs to. Take it from the application's own API — most applications expose their account, organization, or workspace identifier through an endpoint like `GET /me` or `/organizations/me`. It is often a UUID.

Rules for the App ID:

* Use letters, digits, dots, dashes, and underscores only — no spaces, no colons
* Maximum 200 characters
* Use the **same value in every push** for that application

{% hint style="warning" %}
**Do not invent an App ID, and do not change it later.** The App ID is the permanent link between your pushes and the application record in Harmony. Changing it after you have sent data orphans everything sent under the old value — the previous users and activity stay behind in a separate record that no longer receives updates.
{% endhint %}

#### Step 3: Register the application in Harmony

1. Log in to your Harmony dashboard
2. Go to **Settings** > **Integrations**
3. Find **Bring Your Own App** under **SaaS Applications** and click **Connect**
4. Enter the **App ID** from Step 2
5. Enter an **App display name** — the friendly name shown throughout Harmony, for example `Acme CRM`
6. Click **Connect**

{% hint style="info" %}
Register one integration per application. To send data for a second application, create a second Bring Your Own App integration with its own App ID. A single integration cannot serve multiple applications — see [Limits and rules](#limits-and-rules).
{% endhint %}

#### Step 4: Send your first push

```bash
curl -X POST https://external.harmony.io/custom-push/v1/users \
  -H "Authorization: Bearer $HARMONY_ACCESS_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "external_app_id": "acme-crm",
    "users": [
      { "external_id": "u-1001", "email": "alice@example.com", "name": "Alice Chen", "license_tier": "paid" },
      { "external_id": "u-1002", "email": "bob@example.com",   "name": "Bob Ortiz",  "license_tier": "free" }
    ]
  }'
```

A successful push returns `202 Accepted`:

```json
{
  "batch_id": "8f14e45f-ce34-4f2b-9b3d-1a2c5e7d9f01",
  "snapshot_id": "01937f2a-9c4d-7e10-b8a3-5f6d7e8c9a0b",
  "accepted_rows": 2
}
```

### When your data appears

Bring Your Own App is asynchronous. A `202 Accepted` response means Harmony has **received and validated** your data — not that it has finished processing it.

Your data flows through Harmony's standard processing cycle, the same one every built-in integration uses. Expect the application and its users to appear in the dashboard within the next sync cycle rather than immediately. Activity charts update on their own cycle after that.

{% hint style="info" %}
If you push data and do not see it right away, this is normal. Wait for the next sync cycle before investigating. A `202` response means the data was accepted.
{% endhint %}

### Limits and rules

| Rule                    | Detail                                                                                                                                                                     |
| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Rows per request        | Maximum 100. Larger user lists are sent as [multiple batches](/integrations/saas-applications/bring-your-own-app/bring-your-own-app-users.md#sending-more-than-100-users). |
| Metadata per row        | Maximum 1 KB when serialized to JSON                                                                                                                                       |
| Text field length       | 255 characters (254 for email addresses)                                                                                                                                   |
| App ID                  | 1–200 characters, `A–Z a–z 0–9 . _ -`                                                                                                                                      |
| One app per integration | Each Bring Your Own App integration serves exactly one application. Sending several applications through one integration causes them to overwrite each other's data.       |
| Users before usage      | Send a users push before the first usage push. Activity for users Harmony has not yet seen is not counted.                                                                 |
| Rate limiting           | Requests are rate limited per workspace. A throttled request returns `429` — wait, then retry.                                                                             |

### What Harmony Syncs

**From your users pushes:**

* Users, with their email address and display name
* Account status in the application — active, inactive, pending, suspended, or expired
* The role each user holds, in the application's own terms
* License tier and plan name per user

**From your usage pushes:**

* Per-user, per-day activity for each action you report
* Active and inactive user determination
* Consumption or cost figures, when you report them

Users are matched to Harmony employee records by email address, so the same person is recognized across every connected application.

### Troubleshooting

| Symptom                           | Cause                                                              | Fix                                                                                                                                                       |
| --------------------------------- | ------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400 unknown_app`                 | The App ID is not registered, or does not match                    | Check the App ID in **Settings** > **Integrations** matches the `external_app_id` you are sending, character for character                                |
| `400 app_disabled`                | The integration exists but is disabled                             | Re-enable it in **Settings** > **Integrations**                                                                                                           |
| `400 ambiguous_app`               | Two enabled integrations use the same App ID                       | Disable the duplicate                                                                                                                                     |
| `400 validation`                  | One or more rows failed validation                                 | The response lists the offending row and field — see [API reference](/integrations/saas-applications/bring-your-own-app/bring-your-own-app-api.md#errors) |
| `403 integration_access_denied`   | The access key lacks the required permissions                      | Contact Harmony support — this is a key provisioning issue, not a problem with your request                                                               |
| `503 integrations_unavailable`    | Temporary service issue                                            | Retry with backoff. Your data was not accepted, so no partial data has landed                                                                             |
| Push succeeds but nothing appears | Processing has not completed yet                                   | Wait for the next sync cycle                                                                                                                              |
| Users disappeared after a push    | The push did not include them                                      | A users push replaces the whole list. Re-send every current user                                                                                          |
| Usage not showing in charts       | Activity is older than 90 days, or the users were not pushed first | See [Usage data](/integrations/saas-applications/bring-your-own-app/bring-your-own-app-usage.md#the-90-day-activity-window)                               |

### Use Cases

<details>

<summary>Bring an internal tool into your software inventory</summary>

Report the users of a homegrown or internal application so it appears alongside your commercial SaaS in inventory, access reviews, and offboarding checks

</details>

<details>

<summary>License Optimization</summary>

Report each user's license tier along with their activity, then find paid seats that go unused month after month and reclaim them

</details>

<details>

<summary>Access Review</summary>

Include applications with no built-in integration in periodic access certification, with each user's role shown in the application's own terms

</details>

<details>

<summary>Offboarding Verification</summary>

Confirm that departed employees no longer hold accounts in applications Harmony cannot reach directly

</details>

<details>

<summary>Cost Attribution</summary>

Report per-user consumption or spend so usage-based application costs can be attributed to individuals and teams

</details>

<details>

<summary>Shadow Access Detection</summary>

Compare an application's user list against your identity provider to find accounts created outside standard provisioning

</details>

### Reference

* [**Users data**](/integrations/saas-applications/bring-your-own-app/bring-your-own-app-users.md) — every field, snapshot rules, and multi-batch pushes
* [**Usage data**](/integrations/saas-applications/bring-your-own-app/bring-your-own-app-usage.md) — every field, the event ID contract, and the activity window
* [**API reference**](/integrations/saas-applications/bring-your-own-app/bring-your-own-app-api.md) — endpoints, responses, errors, and retry guidance


---

# 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 dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.harmony.io/integrations/saas-applications/bring-your-own-app.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
