Skip to main content

Ingest data

Last updated on

Once your integration is enabled, you send it data. How you do that depends on the ingestion mode you chose: an API integration receives HTTP calls that you make, and a webhook integration receives calls that the source tool makes.

info

Push data with the API

Copy the Upsert Endpoint from the integration's Overview tab. It has this shape:

POST https://app.harness.io/gateway/integration/api/v1/accounts/{accountId}/integrations/{integrationId}/data/{dataKind}
tip
  • Copy the endpoint from the Overview tab rather than assembling it by hand. It already contains your account ID, the integration Id, and the correct data kind.
  • Always include entity_ref in every record you push. Without it, records ingest successfully but are not linked to any entity and will not appear on any entity page. Find the correct value on the entity's detail page under Identity → entityRef, for example component:account/api_cards_docs.

Headers

HeaderRequiredValue
x-api-keyYesHarness Service Account Token (SAT) or Personal Access Token (PAT)
Harness-AccountYesYour Harness account ID.
Content-TypeYesapplication/json

Request body

Records are sent in a records array. Each object is one record matching the integration's data schema:

{
"records": [
{
"identifier": "run-98765",
"name": "backend-api-build",
"entity_ref": "component:default/my-backend-service",
"service": "my-backend-service",
"timestamp": "2026-05-26T09:50:00Z",
"status": "SUCCESS",
"branch": "main",
"sha": "a1b2c3d4e5f6",
"repositoryUrl": "https://github.com/example/backend-api"
}
]
}

cURL example

curl \
--location 'https://app.harness.io/gateway/integration/api/v1/accounts/<ACCOUNT_ID>/integrations/<INTEGRATION_ID>/data/build' \
--header 'Content-Type: application/json' \
--header 'x-api-key: <HARNESS_TOKEN>' \
--header 'Harness-Account: <ACCOUNT_ID>' \
--data '{
"records": [
{
"identifier": "run-98765",
"name": "backend-api-build",
"entity_ref": "component:default/my-backend-service",
"service": "my-backend-service",
"timestamp": "2026-05-26T09:50:00Z",
"status": "SUCCESS",
"branch": "main",
"sha": "a1b2c3d4e5f6",
"repositoryUrl": "https://github.com/example/backend-api"
}
]
}'

How updates work

The identifier field is the record's key. Pushing a record whose identifier already exists updates that record in place rather than creating a second one.

This is what lets you report progress on a long-running operation. A Jenkins pipeline can push a build with "status": "RUNNING" when it starts and push the same identifier again with "status": "SUCCESS" when it finishes, and the entity page shows one build that changed state.

info

For the Custom schema, identifier is optional. If your schema omits it, Harness assigns each record an internal ID and those records cannot be updated by a later push.


Receive data with a webhook

For a webhook integration, copy the Webhook URL from the integration's Overview tab and register it in the source tool. It has this shape:

https://app.harness.io/gateway/integration/api/v1/accounts/{accountId}/webhooks/{webhookId}

The source tool posts its own payload to this URL. Harness authenticates the request using the Auth Type you configured, then converts the payload into a record using the payload mapping on the schema fields.

You do not control the request body here, so the mapping does the work of translating it. Verify the mapping against a real payload from your tool rather than its documentation, since payload shapes often differ between event types.

info

Because the same identifier updates the same record, a tool that fires repeatedly for one entity behaves correctly. PagerDuty sending triggered and then resolved for one incident produces a single incident record that changes status, provided identifier is mapped to the incident's own ID.


Instead of relying on Correlation Mapping, a record can name its target entity directly with entity_ref:

{
"records": [
{
"identifier": "deploy-456",
"name": "prod-release-v2.1",
"entity_ref": "component:default/payment-service",
"timestamp": "2026-05-26T13:55:00Z",
"status": "SUCCESS",
"environment": "production"
}
]
}
tip

If your Correlation Mapping is not showing data on the entity page, add entity_ref directly to the payload as a fallback. Unlike correlation mapping, which requires an exact match against metadata.name (not the display title), entity_ref links the record to the entity unconditionally. You can find the entity_ref of any entity on its detail page under Identity → entityRef.

Use this when the sending system genuinely knows the IDP entity reference. In most pipelines it does not, so Correlation Mapping on a value like the service name or repository URL is more practical.


Schema reference

Fields marked required cause the record to be rejected if missing. Timestamps use ISO 8601 format, for example 2026-05-26T13:55:00Z.

All schemas accept these common fields:

FieldTypeDescription
identifierstringUnique record identifier from the source system. Acts as the record key for updates.
namestringHuman-readable name shown in the catalog table.
timestampstringUsed to order records. Defaults to ingestion time if omitted.
typestringA value you define. Records become filterable by it on the entity page.
entity_refstringLinks the record to a catalog entity directly.
urlstringLink back to the record in the source tool. Makes the record name clickable in the catalog.
tagsobjectKey-value strings for extra context.
customDataobjectFree-form additional data, shown in the record details panel.
info

The six out-of-the-box schemas have additionalProperties: false. This means a record with any field not listed in the schema table is rejected. If you need extra fields, use the Custom schema, which allows any fields you define.

FieldTypeRequiredDescription
identifierstringYesUnique build identifier.
namestringYesBuild name, such as the job or pipeline name.
timestampstringYesBuild start time.
branchstringYesSource branch that was built.
shastringYesGit commit SHA that triggered the build.
repositoryUrlstringYesRepository URL.
statusstringNoSUCCESS, FAILED, RUNNING, ABORTED, or QUEUED.
durationInSecintegerNoBuild duration in seconds.
buildNumberintegerNoSequential build number.
artifactarray of stringsNoArtifacts produced by the build.
triggeredBystringNoPerson or system that triggered the build.
servicestringNoService identifier, commonly used for correlation.
{
"records": [{
"identifier": "run-98765",
"name": "backend-api-build",
"entity_ref": "component:default/my-backend-service",
"service": "my-backend-service",
"timestamp": "2026-05-26T09:50:00Z",
"status": "SUCCESS",
"branch": "main",
"sha": "a1b2c3d4e5f6",
"repositoryUrl": "https://github.com/example/backend-api",
"durationInSec": 30,
"buildNumber": 142,
"artifact": ["docker.example.com/backend-api:1.2.3"],
"triggeredBy": "github-webhook",
"url": "https://ci.example.com/builds/98765"
}]
}

Delete ingested records

API-based integrations expose a Delete Endpoint, available on the Overview tab:

DELETE https://app.harness.io/gateway/integration/api/v1/accounts/{accountId}/integrations/{integrationId}/data/{dataKind}

Use exactly one filter per request. Combining filters in a single call is not supported.

{
"identifiers": ["run-98765", "run-98766"]
}
info

Webhook-based integrations do not expose a delete endpoint. To remove data ingested through a webhook, delete the integration.


Monitor ingestion with the Events tab

Every Custom Integration has an Events tab that records configuration changes and ingestion activity. Use it to confirm data is arriving and to diagnose rejected records.

Filter the list with the Event Type and Status dropdowns, and select Refresh events to reload it.

ColumnDescription
Event NameThe action and its outcome, such as Integration created or Entity rejected.
StatusSUCCESS or FAILED.
DescriptionA summary of what happened, including the reason for failures.
StartedWhen the event began.
Last UpdatedThe most recent timestamp for the event.
Triggered ByThe actor responsible, either System or the user or service account that made the call.

Events you will see include:

Event NameMeaning
Integration createdThe integration was created successfully.
Integration enabledThe integration is active and accepting data.
Integration updatedThe configuration was changed.
Entity rejectedAn incoming record was not ingested. The description gives the reason, most often a schema validation failure.
tip

Entity rejected is the first place to look when a push returns success but nothing appears in the catalog. It distinguishes a payload that failed validation from a payload that was accepted but did not correlate to any entity.


Next steps

Data that has been ingested does not appear on entity pages until you add the corresponding tab to your entity layout. Go to View data in the catalog.