API Reference

Delivery Hub exposes REST APIs for cross-org synchronization and a portal API for client-facing dashboards. The sync endpoints are used internally by the sync engine, while the portal endpoints power the client portal experience.

Salesforce API Base URL

https://your-org.my.salesforce.com/services/apexrest/delivery/deliveryhub/v1/api/

Replace your-org with your Salesforce org's My Domain. The delivery namespace prefix is the managed package namespace.

Authentication

All Public API calls require an X-Api-Key header with a valid API key from a Connected NetworkEntity record:

X-Api-Key: <api_key>

API keys are 64-character hex strings generated via DeliveryPublicApiService.generateApiKey(). All data is scoped to the authenticated NetworkEntity — you can only access WorkItems where ClientNetworkEntityId__c matches the entity. The Sync API uses opt-in API key validation for backward compatibility.

Portal API Base URL

https://cloudnimbusllc.com/api

Portal endpoints are served from the Cloud Nimbus web application. All portal endpoints require an X-Api-Key header for authentication. Endpoints that return entity-scoped data also require the X-Portal-User header to identify the requesting user and their entity context.

Portal Authentication

Portal API endpoints use API key authentication rather than OAuth:

X-Api-Key: <api_key> X-Portal-User: <portal_user_id>
HeaderRequiredDescription
X-Api-KeyYesAPI key for authenticating the request.
X-Portal-UserYesPortal user ID. Used to resolve the user's entity for data scoping.

Portal Endpoints

GET/api/dashboard

Returns the portal dashboard scoped to the authenticated NetworkEntity. Includes active/completed/attention counts, phase distribution, recent completions, and recent activity.

GET/api/work-items

Returns work items for the authenticated entity. Optionally filter by status.

Parameters

ParamTypeDescription
statusStringactive | completed | attention (optional)

GET/api/work-items/{id}

Returns full detail for a single work item including comments (up to 200), file count, and ordered stages for a progress bar. Returns 403 if the work item belongs to a different entity.

POST/api/work-items

Creates a new work item request. Title is automatically prefixed with [Portal]. Created with stage Backlog, status New, and IsActive true.

Request Body

{ "title": "Add revenue report", "description": "Create a summary revenue report...", "priority": "High", "type": "Enhancement" }

POST/api/work-items/{id}/comments

Adds a comment to a work item. Auto-tagged with Author "Portal User" and Source "Client". Returns 403 if the work item belongs to a different entity.

Request Body

{ "body": "Looks good — approved for deployment." }

GET/api/activity-feed

Returns a unified activity feed combining comments, hours logged, and field changes across work items for an entity.

Parameters

ParamTypeDescription
filterTypeStringall | comments | hours | changes
pageOffsetNumberPagination offset for results.
entityIdStringNetwork Entity ID to scope results.

GET/api/conversations

Returns comments grouped by work item, providing a conversation-style view of discussions across the entity's work items.

Parameters

ParamTypeDescription
pageOffsetNumberPagination offset for results.
entityIdStringNetwork Entity ID to scope results.

GET/api/pending-approvals

Returns draft WorkLogs that are awaiting approval for the given entity.

Parameters

ParamTypeDescription
pageOffsetNumberPagination offset for results.
entityIdStringNetwork Entity ID to scope results.

GET/api/work-logs

Returns recent work logs (time entries) for the given entity.

Parameters

ParamTypeDescription
entityIdStringNetwork Entity ID to scope results.

GET/api/files

Returns files attached to work items for an entity. Optionally filter to a specific work item.

Parameters

ParamTypeDescription
entityIdStringNetwork Entity ID to scope results.
workItemIdStringOptional. Filter files to a specific work item.

GET/api/board-summary

Returns an AI-generated summary of the current board state for an entity, highlighting key activity and attention items.

Parameters

ParamTypeDescription
entityIdStringNetwork Entity ID to scope the summary.

GET/api/documents

Returns documents and invoices associated with an entity.

Parameters

ParamTypeDescription
entityIdStringNetwork Entity ID to scope results.

POST/api/approve-worklogs

Batch approves one or more draft work logs.

Request Body

{ "workLogIds": ["a0B000000000001", "a0B000000000002"] }
FieldTypeDescription
workLogIdsString[]Array of WorkLog record IDs to approve.

POST/api/reject-worklogs

Batch rejects one or more draft work logs.

Request Body

{ "workLogIds": ["a0B000000000001", "a0B000000000002"] }
FieldTypeDescription
workLogIdsString[]Array of WorkLog record IDs to reject.

POST/api/log-hours

Logs hours worked against a specific work item.

Request Body

{ "workItemId": "a0A000000000001", "hours": 2.5, "workNotes": "Implemented validation logic", "workDate": "2026-03-14" }
FieldTypeDescription
workItemIdStringThe WorkItem record ID to log hours against.
hoursNumberNumber of hours worked (supports decimals).
workNotesStringDescription of work performed.
workDateDateThe date the work was performed (YYYY-MM-DD).

Sync Endpoints

POST/sync/{ObjectType}

Pushes changes from one org to another. The URL includes the object type (e.g., WorkItem__c, WorkItemComment__c, ContentVersion).

Headers

HeaderRequiredDescription
X-Api-KeyOptionalAPI key for opt-in validation. Must match a Connected NetworkEntity if sent.
X-Global-Source-IdOptionalOriginal record ID for gateway-level echo suppression and multi-hop loop prevention.

Request Payload

{ "BriefDescriptionTxt__c": "Add revenue report", "DetailsTxt__c": "Create a summary revenue report...", "StageNamePk__c": "In_Development", "PriorityPk__c": "High", "EstimatedHoursNumber__c": 8, "IsActiveBool__c": true, "SourceId": "a00xx0000000001AAA", "TargetId": "a00xx0000000099AAA", "GlobalSourceId": "a00xx0000000001AAA", "SenderOrgId": "00Dxx0000000001" }

Response

// Success { "status": "Success", "processedId": "a00xx0000000099AAA", "orgId": "00Dxx0000000002" } // Echo suppressed { "status": "Echo suppressed", "globalSourceId": "a00xx0000000001AAA" }

Payload Fields

FieldTypeDescription
SourceIdStringRecord ID in the sending org. Used for record resolution and bridge mapping.
TargetIdStringKnown record ID in the receiving org (if previously synced). Used as direct fallback for resolution.
GlobalSourceIdStringOriginal record ID that initiated the sync chain. Carried forward across multi-hop topologies for loop prevention.
SenderOrgIdStringSalesforce Organization ID of the sending org. Used for auto-parenting to the correct NetworkEntity.
VendorPushBooleanIndicates this is a real-time vendor push (upstream), not a standard downstream sync.

GET/sync/changes

Pull flow endpoint. Returns staged outbound SyncItems for a specific client entity. Items are marked as Synced after being returned. Used by the DeliveryHubPoller scheduled job for 15-minute polling.

Parameters

ParamTypeDescription
clientIdStringRequired. NetworkEntity ID for data segregation.
sinceISO DateTimeOptional. Filter to items created after this datetime. Defaults to 1900-01-01.

Response

[ { "objectType": "WorkItem__c", "payload": "{...}", "syncItemId": "a03xx0000000001AAA", "createdDate": "2026-03-09T10:00:00.000Z" } ]

Returns up to 200 items per request, ordered by CreatedDate ascending. Only returns items with StatusPk__c = "Staged" and DirectionPk__c = "Outbound".

Retry Logic

Failed sync items are retried up to 3 times. On each failure, RetryCountNumber__c is incremented and ErrorLogTxt__c is populated with error details.

  • Attempt 1: Immediate (via DeliverySyncItemProcessor queueable)
  • Attempt 2: Picked up on next scheduled poller run (15-minute intervals)
  • Attempt 3: Final automatic retry on next poller cycle

After 3 failed attempts, the sync item remains in Failed status for manual investigation via the Sync Retry Panel LWC on the admin home page. The DeliveryHubScheduler acts as a safety net, picking up any items that were missed.

Echo Suppression

When Org A pushes a change to Org B, the update in Org B triggers its own outbound sync trigger. Without echo suppression, this would create an infinite loop. Delivery Hub prevents this with 3 layers:

  1. Gateway-level (X-Global-Source-Id): HTTP header carries the original record ID. The receiving org checks for an existing outbound SyncItem with that GlobalSourceId and suppresses if matched.
  2. In-memory origin blocking: DeliverySyncItemIngestor registers the origin route in DeliverySyncEngine.blockedOrigins (static Set), preventing re-queuing within the same transaction.
  3. GlobalSourceId inheritance: When creating outbound SyncItems, the engine checks the ledger for an existing GlobalSourceId and carries it forward rather than replacing with the local ID. This enables multi-hop loop prevention across complex topologies (Org A → Org B → Org C).

Error Codes

CodeStatusDescription
200OKSync processed successfully or echo suppressed.
201CreatedResource created (POST work-items, comments, log-hours, submissions).
400Bad RequestMissing body, blank required field, invalid parameters, or empty payload.
401UnauthorizedMissing or invalid X-Api-Key header, or entity not in Connected status.
403ForbiddenWork item belongs to a different NetworkEntity than the authenticated one.
404Not FoundUnknown endpoint path or work item ID not found.
500Server ErrorUnexpected Apex exception. Check Sync Retry Panel for details.

Related

  • Architecture — data model and sync engine design
  • CI/CD — automated testing for sync endpoints