Skip to main content

Sync jobs API reference

This page is the endpoint-by-endpoint reference for the sync jobs API. For a conceptual introduction, the lifecycle, and how to choose between modes, start with the overview. For mode-specific guidance, see DIFF, PATCH, CROSS_SCOPE, and OVERRIDE.

All sync job endpoints are mounted under /persister/synchronization/jobs.

Authentication

Every request needs:

  • Authorization: Bearer <api-key>
  • jupiterone-account: <account-id>

See Authentication for setup.

Request body properties

The start endpoint accepts these top-level properties:

source

  • api for ad-hoc data uploaded by you.
  • integration-external for custom integrations.

scope

  • Any string. Used to group everything in this sync job for the purposes of comparison on finalize.
  • Required when syncMode is DIFF.
  • Can only be used when source is api.

syncMode

  • DIFF (default): replaces the full dataset in scope. See DIFF.
  • PATCH: adds or updates entities only; never deletes. See PATCH.
  • CROSS_SCOPE: relationships between entities in different scopes. See CROSS_SCOPE.
  • OVERRIDE: pins property values on managed-integration entities. See OVERRIDE.

integrationInstanceId

  • Required when referencing a custom integration (when source is integration-external).

Request flags

ignoreDuplicates

  • Instructs the system not to throw an error if there are graph objects with duplicate keys. The latest object wins.
info

The CREATE_OR_UPDATE mode is deprecated and no longer functions.

Validation

The synchronization API performs comprehensive validation on all uploaded data. The required fields depend on the sync mode; see each mode's page for the full list.

Property constraints

Custom properties:

  • Cannot start with underscore (_) — these are reserved for system properties.
  • Must be one of: string, boolean, number, null, or a homogenous array of one of those types.

Invalid values:

  • Mixed-type arrays (e.g., ["string", 123, true]).
  • Nested objects (except _rawData).
  • undefined.

Mapped relationships

Mapped relationships (used when one of the related entities isn't directly known) require:

  • _key, _type, _class.
  • _mapping object with:
    • sourceEntityKey — required, the key of the source entity.
    • targetFilterKeys — required, array of arrays for filtering target entities.
    • targetEntity — required, object describing the target entity.
    • skipTargetCreation — optional boolean.
    • relationshipDirection — optional, "FORWARD" or "REVERSE".

Upload size constraints

Each upload request must contain at least one entity or one relationship. Both arrays can be present in the same request (mode permitting).

Common validation errors

ErrorCauseFix
Missing JupiterOne-Account headerRequired header not provided.Include jupiterone-account.
/entities/0/_key is requiredMissing required field.Add _key (required by DIFF).
/entities/0 (entity key: "key-1") has invalid property name '_internal'Property name starts with _.Rename without the leading underscore.
/entities/0/_class (entity key: "key-1") has invalid type. Valid types are string or array of strings.Invalid _class type.Use a string or array of strings.
/entities/0/_key: maximum length exceededField exceeds character limit.Shorten _key to ≤ 7000 characters.
Relationships are not allowed in PATCH jobsRelationships uploaded in PATCH mode.Use DIFF or CROSS_SCOPE.
Relationship uploads are not allowed for OVERRIDE sync jobsRelationships uploaded in OVERRIDE mode.OVERRIDE only accepts entities.
OVERRIDE sync jobs are limited to 10000 entities per jobPer-job entity cap exceeded.Split across multiple sync jobs.
OVERRIDE sync mode is not enabled for this accountAccount not on the OVERRIDE allowlist.Contact JupiterOne support.
entities must have minimum 1 itemEmpty entities array.Include at least one entity, or omit the array.

Endpoints

Start a synchronization job

POST /persister/synchronization/jobs

Request:

{
"source": "api",
"syncMode": "DIFF",
"scope": "my-sync-job"
}

Or with a custom integration source:

{
"source": "integration-managed",
"integrationInstanceId": "5465397d-8491-4a12-806a-04792839abe3"
}

Response:

{
"job": {
"source": "api",
"scope": "my-sync-job",
"id": "f445397d-8491-4a12-806a-04792839abe3",
"status": "AWAITING_UPLOADS",
"startTimestamp": 1586915139427,
"numEntitiesUploaded": 0,
"numRelationshipsUploaded": 0,
"numMappedRelationshipsUploaded": 0
}
}

Get status of a synchronization job

GET /persister/synchronization/jobs/{jobId}

Response:

{
"job": {
"source": "api",
"scope": "my-sync-job",
"id": "f445397d-8491-4a12-806a-04792839abe3",
"status": "AWAITING_UPLOADS",
"startTimestamp": 1586915139427,
"numEntitiesUploaded": 0,
"numRelationshipsUploaded": 0,
"numMappedRelationshipsUploaded": 0
}
}

The response carries running counters of the data uploaded so far in this job: total entities, total relationships, and total mapped relationships. After finalize completes, these are the final totals applied to the graph.

Upload a batch of entities and/or relationships

The upload endpoints accept application/json only. Send the body with Content-Type: application/json. Requests may be gzip- or brotli-compressed.

POST /persister/synchronization/jobs/{jobId}/upload
{
"entities": [
{
"_key": "1",
"_class": "DataStore",
"_type": "fake_entity",
"displayName": "my_datastore"
},
{
"_key": "2",
"_class": "Database",
"_type": "fake_entity",
"displayName": "my_database"
}
],
"relationships": [
{
"_key": "a",
"_type": "fake_relationship",
"_class": "IS",
"_fromEntityKey": "1",
"_toEntityKey": "2"
}
]
}

Upload entities only

POST /persister/synchronization/jobs/{jobId}/entities
{
"entities": [
{ "_key": "1", "_type": "fake_entity" }
]
}

Upload relationships only

POST /persister/synchronization/jobs/{jobId}/relationships
{
"relationships": [
{
"_key": "a",
"_type": "fake_relationship",
"_class": "HAS",
"_fromEntityKey": "1",
"_toEntityKey": "2"
}
]
}

Finalize a synchronization job

POST /persister/synchronization/jobs/{jobId}/finalize

Finalize is asynchronous. The response confirms the job has entered finalization; it does not wait for the graph to be updated.

{
"job": {
"id": "f445397d-8491-4a12-806a-04792839abe3",
"status": "FINALIZE_PENDING"
}
}

Poll get status until status is FINISHED (or terminal: ABORTED, FAILED, ERROR).

See also