vendure-data-hub-plugin

GraphQL API

The examples in this guide are validated against the generated plugin schema by npm run verify:docs. Runtime GraphQL introspection remains the definitive contract for the exact plugin version installed by an application.

The Data Hub plugin extends the Vendure Admin API with queries and mutations for pipeline management.

Queries

dataHubPipelines

List all pipelines:

query {
    dataHubPipelines(options: { take: 20, skip: 0 }) {
        items {
            id
            code
            name
            enabled
            configurationSource
            createdAt
            updatedAt
        }
        totalItems
    }
}

dataHubPipeline

Get a single pipeline:

query GetPipeline($id: ID!) {
    dataHubPipeline(id: $id) {
        id
        code
        name
        enabled
        configurationSource
        definition
        createdAt
        updatedAt
    }
}

dataHubConnections

List connections:

query {
    dataHubConnections {
        items {
            id
            code
            type
            configurationSource
            createdAt
        }
        totalItems
    }
}

configurationSource is DATABASE for Dashboard-managed resources and CODE_FIRST for active deployed definitions. Update, delete, lifecycle, draft, and restore mutations reject active code-first resources. Pipeline review, publication, execution, export, history, and comparison remain available.

dataHubSecrets

List secrets (values hidden):

query {
    dataHubSecrets {
        items {
            id
            code
            provider
            hasValue
            createdAt
        }
        totalItems
    }
}

dataHubSecretReferences

List secret codes that can be referenced by pipelines, connections, triggers, and destinations. This read-only query includes both code-first and database-managed secrets but never returns secret values. Results are filtered on the server; take must be between 1 and 100.

query SecretReferences($search: String, $skip: Int = 0, $take: Int = 25) {
    dataHubSecretReferences(search: $search, skip: $skip, take: $take) {
        items {
            code
            provider
            source
        }
        totalItems
    }
}

Code-first results are returned first in code order, followed by distinct database results in code order. The query requires ReadDataHubSecret.

dataHubAdapters

List available adapters:

Requires ManageDataHubAdapters.

query {
    dataHubAdapters {
        code
        name
        type
        category
        description
        version
        deprecated
        deprecatedMessage
        schema {
            fields {
                key
                type
                required
                label
                defaultValue
                options { value label }
            }
        }
    }
}

dataHubPipelineRuns

Query pipeline runs:

query GetRuns($pipelineId: ID!) {
    dataHubPipelineRuns(pipelineId: $pipelineId, options: { take: 10 }) {
        items {
            id
            status
            startedAt
            finishedAt
            triggeredBy
        }
        totalItems
    }
}

dataHubPipelineRun

Get a single run:

query GetRun($id: ID!) {
    dataHubPipelineRun(id: $id) {
        id
        status
        startedAt
        completedAt
        metrics
        triggeredBy
    }
}

dataHubLogs

Query execution logs:

query GetLogs {
    dataHubLogs(options: { take: 100 }) {
        items {
            id
            level
            message
            stepKey
            createdAt
            metadata
        }
        totalItems
    }
}

dataHubRunErrors

Query failed records for a specific run. Use the returned cursor to request the next page; cursors are opaque and must not be constructed by clients.

query RunErrors($runId: ID!, $first: Int!, $after: String) {
    dataHubRunErrors(runId: $runId, first: $first, after: $after) {
        items {
            id
            stepKey
            message
            payload
            stackTrace
            createdAt
        }
        totalItems
        hasNextPage
        endCursor
    }
}

dataHubDeadLetters(first:, after:) uses the same page shape. Page size is bounded by the server query limit.

dataHubSettings

Get plugin settings:

query {
    dataHubSettings {
        retentionDaysRuns
        retentionDaysErrors
        retentionDaysLogs
        logPersistenceLevel
    }
}

dataHubExportDestinations

List channel-scoped delivery destinations. The API returns configuration and Secret Codes, never resolved secret values:

query {
    dataHubExportDestinations {
        id
        name
        type
        enabled
        url
        auth {
            type
            secretCode
            usernameSecretCode
        }
    }
}

Destination definitions are stored in the database and scoped to the active Vendure channel. API and worker processes read the same durable definition, so registrations survive restarts and do not rely on process-local cache invalidation. Only validated configuration and Secret Codes are persisted; resolved credential values are never written to the destination table. Pipeline destination schemas and saved pipeline definitions remain separate.

Each channel can store up to 100 managed destinations. Creation and deletion are serialized per channel with the configured Data Hub lock backend, and the capacity check runs in a transaction opened after the lock is acquired. Managed creation rejects an ID that already exists in the active channel instead of silently replacing its configuration.

Mutations

dataHubRegisterExportDestination

Create every referenced secret first, then register the destination using only Secret Codes. Plaintext credential fields, credential-bearing static headers, embedded URL credentials, and prototype keys are rejected.

mutation RegisterPartnerDestination {
    dataHubRegisterExportDestination(input: {
        id: "partner-http"
        name: "Partner HTTP"
        type: HTTP
        url: "https://partner.example.com/import"
        method: "POST"
        auth: {
            type: BEARER
            secretCode: "partner-api-token"
        }
    }) {
        success
        id
    }
}

S3 uses accessKeyIdSecretCode and secretAccessKeySecretCode. FTP uses passwordSecretCode; SFTP supports passwordSecretCode, privateKeySecretCode, passphraseSecretCode, and hostKeyFingerprintSecretCode. The fingerprint reference must resolve to the trusted OpenSSH SHA256:<base64> server host-key fingerprint and is required in production. SMTP authentication uses smtp.usernameSecretCode (or a non-secret smtp.username) together with smtp.passwordSecretCode. Secret values are resolved only while testing or delivering to a destination.

dataHubDeleteExportDestination

Delete a managed destination from the active Vendure channel. A destination with the same ID in another channel is not affected. The mutation requires ManageDataHubDestinations and returns Vendure’s standard deletion result.

mutation DeletePartnerDestination {
    dataHubDeleteExportDestination(id: "partner-http") {
        result
        message
    }
}

createDataHubPipeline

Create a pipeline:

mutation CreatePipeline($input: CreateDataHubPipelineInput!) {
    createDataHubPipeline(input: $input) {
        id
        code
        name
    }
}

Variables:

{
    "input": {
        "code": "my-pipeline",
        "name": "My Pipeline",
        "definition": {
            "version": 1,
            "steps": [],
            "edges": []
        }
    }
}

updateDataHubPipeline

Update a pipeline:

mutation UpdatePipeline($input: UpdateDataHubPipelineInput!) {
    updateDataHubPipeline(input: $input) {
        id
        name
        enabled
    }
}

Variables:

{
    "input": {
        "id": "1",
        "name": "Updated Name",
        "enabled": true
    }
}

deleteDataHubPipeline

Delete a pipeline:

mutation DeletePipeline($id: ID!) {
    deleteDataHubPipeline(id: $id) {
        result
        message
    }
}

Pipeline lifecycle mutations

Pipeline lifecycle transitions are enforced by the service and revision layers:

Publication uses the saved REVIEW definition and fails closed. It performs full structural, semantic, adapter, dependency, resource, and hook validation; inability to verify a dependency, connection, secret, hook script, or target pipeline blocks publication. It also rejects reachable cycles across dependsOn and TRIGGER_PIPELINE references and verifies the effective adapter and operator permissions. The standalone validation query is advisory: isValid excludes warnings and does not include every publication-only cycle, permission, or concurrent-change check.

mutation ReactivatePipeline($id: ID!) {
    reactivateDataHubPipeline(id: $id) {
        id
        status
        enabled
        version
    }
}

startDataHubPipelineRun

Execute a pipeline:

mutation RunPipeline($pipelineId: ID!) {
    startDataHubPipelineRun(pipelineId: $pipelineId) {
        id
        status
    }
}

cancelDataHubPipelineRun

Cancel a running pipeline:

mutation CancelRun($id: ID!) {
    cancelDataHubPipelineRun(id: $id) {
        id
        status
    }
}

runDataHubHookTest

Execute the configured observation actions for one hook stage. Interceptor and script actions are reported as skipped because they require the pipeline’s record-processing lifecycle.

mutation TestHook($pipelineId: ID!, $stage: String!, $payload: JSON) {
    runDataHubHookTest(pipelineId: $pipelineId, stage: $stage, payload: $payload) {
        status
        configured
        executed
        skipped
        failed
        errors {
            action
            type
            error
        }
    }
}

The mutation requires the Run Data Hub Pipeline permission. A resolved mutation is not necessarily successful: inspect status and failed.

validateDataHubPipelineDefinition

Validate a pipeline definition:

query Validate($definition: JSON!) {
    validateDataHubPipelineDefinition(definition: $definition) {
        isValid
        level
        issues {
            stepKey
            field
            message
            reason
        }
        warnings {
            stepKey
            field
            message
            reason
        }
    }
}

Requires ReadDataHubPipeline. reason is a nullable technical code supplied when the validator can classify an issue; unexpected failures can be message-only.

createDataHubConnection

Create a connection:

Requires ManageDataHubConnections.

mutation CreateConnection($input: CreateDataHubConnectionInput!) {
    createDataHubConnection(input: $input) {
        id
        code
        type
    }
}

updateDataHubConnection

Update a connection:

Requires ManageDataHubConnections.

mutation UpdateConnection($input: UpdateDataHubConnectionInput!) {
    updateDataHubConnection(input: $input) {
        id
        code
    }
}

deleteDataHubConnection

Delete a connection:

Requires ManageDataHubConnections.

mutation DeleteConnection($id: ID!) {
    deleteDataHubConnection(id: $id) {
        result
        message
    }
}

Inspect both fields. NOT_DELETED includes a missing-resource, dependency, or persistence failure reason in message.

createDataHubSecret

Create a secret:

Requires CreateDataHubSecret.

mutation CreateSecret($input: CreateDataHubSecretInput!) {
    createDataHubSecret(input: $input) {
        id
        code
        provider
        hasValue
    }
}

Variables:

{
    "input": {
        "code": "api-key",
        "provider": "ENV",
        "value": "MY_API_KEY"
    }
}

updateDataHubSecret

Update a secret:

Requires UpdateDataHubSecret.

mutation UpdateSecret($input: UpdateDataHubSecretInput!) {
    updateDataHubSecret(input: $input) {
        id
        code
    }
}

The value fields have explicit three-state semantics:

Sending value: null, an empty/whitespace value, or both value and clearValue is rejected instead of silently deleting data. Changing provider requires a valid non-blank replacement in the same update. ENV values must be environment-variable names such as SUPPLIER_API_KEY and cannot contain fallbacks. INLINE writes require DATAHUB_MASTER_KEY with at least 32 characters. Secret queries and mutation responses expose hasValue; the stored value is never returned.

deleteDataHubSecret

Delete a secret:

Requires DeleteDataHubSecret.

mutation DeleteSecret($id: ID!) {
    deleteDataHubSecret(id: $id) {
        result
        message
    }
}

Tracked references from published pipelines, saved connections, or managed destinations prevent deletion and return NOT_DELETED with a reason. Missing secrets also return NOT_DELETED with Secret not found.

retryDataHubRecord

Retry a single failed record with an optional field patch:

mutation RetryRecord($errorId: ID!, $patch: JSON) {
    retryDataHubRecord(errorId: $errorId, patch: $patch) {
        success
        outcome
        message
        errorId
        runId
        stepKey
        adapterCode
        definitionVersion
        appliedPatch
        rejectedPatchKeys
        processed
        succeeded
        failed
        auditId
        auditRecorded
    }
}

The retry uses the failed run’s immutable definition snapshot. Adapter identity is resolved from canonical step.config.adapterCode, with the typed root step.adapterCode supported for code-first definitions. A patch is rejected atomically if any requested field is not patchable; inspect success, outcome, and rejectedPatchKeys before reporting success. APPLIED means replay produced at least one successful side effect. Audit persistence is reported separately through auditRecorded and auditId.

ReplayDataHubRecord is required for every retry. A non-empty patch also requires EditDataHubQuarantine; callers with replay-only access can retry the recorded payload unchanged by omitting patch or passing {}.

updateDataHubSettings

Update plugin settings:

mutation UpdateSettings($input: DataHubSettingsInput!) {
    updateDataHubSettings(input: $input) {
        retentionDaysRuns
        retentionDaysErrors
    }
}

TypeScript Client

Inside a Vendure Dashboard extension, use its authenticated api client with a typed document generated from the host application’s Admin API schema:

import { api } from '@vendure/dashboard';
import { graphql } from '@/gql';

const runPipelineDocument = graphql(`
    mutation RunDataHubPipeline($pipelineId: ID!, $expectedRevisionId: ID) {
        startDataHubPipelineRun(
            pipelineId: $pipelineId
            expectedRevisionId: $expectedRevisionId
        ) {
            id
            status
            revisionId
        }
    }
`);

const result = await api.mutate(runPipelineDocument, {
    pipelineId: '1',
    expectedRevisionId: null,
});

const run = result.startDataHubPipelineRun;

The Dashboard client supplies the active session and channel tokens. External clients should send the same operation to Vendure’s configured Admin API path with an authenticated administrator session and, when applicable, the target channel token header.

Error Handling

Authorization, lookup, duplicate-code, and create/update validation failures are returned through the GraphQL errors array. Vendure Dashboard’s api client rejects the request with an Error that can also expose extensions and fieldErrors; narrow an unknown caught value before reading those properties. Do not assume Apollo-specific properties such as graphQLErrors. The exact extensions.code depends on the originating Vendure or resolver error and is not guaranteed for every validation path.

Delete mutations use Vendure’s DeletionResponse; inspect result and message even when the GraphQL request itself succeeds.