Skip to main content

Create and update with the API

API writes change the knowledge base as soon as they succeed. Your key needs an effective Editor type or higher, plus the relevant business permissions and available plan capacity.

Prepare and verify a write​

  1. Check the key's organization, effective permissions and intended real-data or scenario context.
  2. Read the metamodel to identify property keys, value formats and allowed relationship directions.
  3. Read the target object and prepare only the fields you intend to change.
  4. Send the request with Bearer authentication and Content-Type: application/json.
  5. Check the HTTP status and returned result, then read back the asset and affected relationships.

The paths below follow /api/v1. Example keys such as application, reference, depends_on and weight must exist in your organization's metamodel. Calculated properties are read-only. Owners supplied in a request must be active members.

Create or update an asset​

Send this example to POST /assets:

{
"asset_type_key": "application",
"name": "Demo application",
"properties": { "reference": "APP-DEMO-001" },
"on_conflict": "update"
}

A unique-key property matches an existing asset; the name alone does not. on_conflict controls what happens when that unique key already exists:

ValueEffect
error (default)Reject the conflict.
updateMerge the supplied fields into the existing asset; restore an archived match before updating.
ignoreLeave the existing asset's content unchanged; attest: true still attests it.

Check data.id and data.action: created, updated, restored or unchanged. A creation returns 201; other successful outcomes return 200. Conflicting unique properties that identify different assets cause conflicting_unique_keys.

Use PATCH /assets/{id} for a targeted modification. Omitted fields stay unchanged and properties is partial. For example:

{
"properties": { "description": null },
"owned_by_ids": []
}

This clears the description and removes all owners. Omitting owned_by_ids preserves them. access_domain_keys also replaces the supplied list. Property null is accepted for clearing with PATCH, but not as a property value in the creation schema. Metamodel validation still applies.

Add or synchronize relationships​

To add a relationship independently, use POST /relationships:

{
"source_asset_id": "application:reference:APP-DEMO-001",
"target_asset_id": "application:reference:APP-DEMO-002",
"relationship_type_key": "depends_on",
"properties": { "weight": 25 }
}

The type must support relationship properties and your permissions must allow the operation. GET /metamodel/relationship-types/{key} gives the property keys in properties, empty when the type has no properties. Self-links are refused by this endpoint. To update only properties, use PATCH /relationships/{id}; it does not change the endpoints.

allow_duplicate: true permits a parallel relationship only when its type allows it. At least one non-calculated property must differ, including defaults; otherwise identical_relationship_already_exists returns 409. In a bulk request, its indexes name the items concerned. Do not combine allow_duplicate: true with on_conflict: "update" or "ignore". Check each instance's ID instead of treating the endpoint pair as unique.

An asset PATCH can instead synchronize a whole relationship group:

{
"relationships": [{
"direction": "outgoing",
"relationship_type_key": "depends_on",
"related_assets": [{
"related_asset_id": "application:reference:APP-DEMO-002"
}]
}]
}
This replaces a group

The submitted direction/type group is synchronized with the listed targets. Existing targets omitted from that group can be archived, subject to permissions. related_assets: [] requests an empty group. Omitted groups stay unchanged; relationships: [] does not clear every relationship. Use independent relationship creation when you only intend to add a link.

Archive, restore and attest​

ActionRequest
Archive an assetDELETE /assets/{id}
Restore an assetPOST /assets/{id}/restore
Attest an assetPOST /assets/{id}/attest
Archive a relationshipDELETE /relationships/{id}
Restore a relationshipPOST /relationships/{id}/restore

DELETE archives the object; it is not permanent deletion. Archiving an asset deactivates its attached relationships. Restoration returns restored_relationship_ids; only eligible relationships are restored. A missing restored link requires checking its other endpoint and archive state.

Restoring an already active asset through POST /assets/{id}/restore returns HTTP 409 with asset_already_active. In a restore batch, it appears in data.skipped with reason already_active.

Attestation requires active quality tracking and the key's owner to own the asset. It is available only in real data. attest: true during asset creation or bulk creation requests attestation after writing. Preconditions are checked, but content and attestation are not guaranteed as one indivisible operation. Read back both after a failure.

Process a batch​

Create or update batches with POST or PATCH on /bulk/assets and /bulk/relationships, up to 10,000 entries per request. Consult the reference for the schema of each method. Asset creation uses an assets array and optional top-level on_conflict. client_ref matches a response to an input row; it is not a business unique key.

Unlike unit creation, POST /bulk/assets does not accept relationships inside its asset entries. Create those links separately or use a compatible subsequent PATCH.

Bulk relationship creation uses source, target and direction, unlike the unit endpoint:

{
"relationships": [{
"source": "application:reference:APP-DEMO-001",
"target": "application:reference:APP-DEMO-002",
"direction": "outgoing",
"relationship_type_key": "depends_on",
"properties": { "weight": 25 }
}]
}

Lifecycle batches have lower limits. POST /bulk/assets/archive, /bulk/assets/restore and /bulk/assets/attest accept an ids array of at most 500. POST /bulk/relationships/archive and /bulk/relationships/restore accept at most 200.

These lifecycle requests return data.applied and data.skipped, including a reason for each skipped ID. Reasons include not_found, forbidden, already_archived, already_active or not_owner, depending on the action. HTTP 200 does not mean every entry was applied. A global error or an ambiguous identifier can still fail the request. Do not assume this partial-result format applies to every bulk operation.

Work in a scenario​

Read GET /scenarios and choose an accessible, active, ready scenario. Add ?scenario=<ID> to every compatible request; omission targets real data. Check the resulting context before writing. The x-boldo-scenario header is rejected.

In the interactive reference, fill the scenario query parameter on a compatible operation before executing it. The current scenario selected in Boldo does not automatically fill this parameter. Leaving it empty writes to real data.

Assets, relationships and their compatible reads or writes support scenario context. Attestation, including attest: true, does not. Organization administration and typed OpenAPI are not scenario operations. The public v1 API does not offer scenario creation, application or abandonment; use the scenario interface.

If a request fails or times out, retain its response and x-request-id, then inspect current data before repeating it. Follow the error and rate-limit guidance.