The Connector SDK APIs are available through Forge's Early Access Program (EAP).
EAPs are offered to selected users for testing and feedback purposes. We are currently working with a select group of EAP participants to get their apps production-ready and available for publishing on Marketplace.
To use the Connector SDK, you must be part of the Forge connector EAP. If you are interested in joining this EAP, you can express interest through this form.
The setRelationships method allows you to create or update relationships in bulk. Relationships connect different types of objects (e.g., documents, teams, Jira issues) to represent how they relate to each other.
1 2setRelationships(request: BulkRelationshipsRequest): Promise<BulkRelationshipsResponse>
BulkRelationshipsRequest1 2{ relationships: RelationshipPayload[]; connectionId: string; }
BulkRelationshipsRequest1 2{ relationships: RelationshipPayload[]; connectionId: string; }
BulkRelationshipsResponse1 2{ success: boolean; results?: { [relationshipType: string]: RelationshipResponse[]; }; error?: string; originalError?: unknown; }
1 2{ from: RelationshipEntity; // Source entity to: RelationshipEntity; // Target entity updateSequenceNumber: number; // Update sequence number createdAt?: string; // ISO 8601 timestamp updatedAt?: string; // ISO 8601 timestamp // Note: 'type' is not included in the response - it's the key in the results object }
1 2{ from: RelationshipEntity; // Required - Source entity to: RelationshipEntity; // Required - Target entity type: string; // Required - Relationship type identifier updateSequenceNumber?: number; // Optional - Used for conflict resolution updatedAt?: string; // Optional - ISO 8601 timestamp createdAt?: string; // Optional - ISO 8601 timestamp }
1 2{ type: string; // Required - Entity type (e.g., "atlassian:document", "issueId") value: RelationshipEntityValue; // Required - Entity identifier }
1 2{ entityId?: string; // For entities identified by entityId issueId?: string; // For Jira issues worklogId?: string; // For worklogs [key: string]: string | undefined; // Additional identifier fields }
MAX_BULK_RELATIONSHIPS)from, to, typeupdateSequenceNumber, updatedAt, createdAt1 2import { graph, types } from '@forge/teamwork-graph'; const relationships: types.RelationshipPayload[] = [ { from: { type: 'atlassian:team', value: { entityId: 'team-id-1' } }, to: { type: 'issueWorklogId', value: { issueId: 'PT-1', worklogId: '10000' } }, type: 'external-team-works-on-jira-work-item-worklog', updateSequenceNumber: 1, updatedAt: '2024-02-01T12:00:00.000Z', createdAt: '2024-01-10T10:00:00.000Z' } ]; const response = await graph.setRelationships({ relationships: relationships, connectionId: 'your-connection-id' }); if (response.success) { console.log('Relationships created:', response.results); // Results are grouped by relationship type if (response.results) { Object.entries(response.results).forEach(([relationshipType, relationships]) => { console.log(`${relationshipType}: ${relationships.length} relationships created`); }); } } else { console.error('Error:', response.error); }
1 2import { graph, types } from '@forge/teamwork-graph'; const relationships: types.RelationshipPayload[] = [ { from: { type: 'atlassian:team', value: { entityId: 'team-id-1' } }, to: { type: 'issueWorklogId', value: { issueId: 'PT-1', worklogId: '10000' } }, type: 'external-team-works-on-jira-work-item-worklog', updateSequenceNumber: 1, updatedAt: '2024-02-01T12:00:00.000Z', createdAt: '2024-01-10T10:00:00.000Z' }, { from: { type: 'atlassian:document', value: { entityId: 'doc-001' } }, to: { type: 'issueId', value: { issueId: 'PT-2' } }, type: 'external-document-works-on-jira-work-item', updateSequenceNumber: 1, updatedAt: '2024-02-01T12:00:00.000Z', createdAt: '2024-01-10T10:00:00.000Z' } ]; const response = await graph.setRelationships({ relationships: relationships, connectionId: 'your-connection-id' });
The method validates the following:
relationships field must be a valid array.relationships array cannot be empty.from, to, and type fields.| Error message | Description |
|---|---|
relationships array cannot be empty | The relationships array is empty. |
Bulk relationship ingestion supports maximum 100 relationships. Received {count} | The number of relationships per request has exceeded the maximum limit. |
{field} is required | A required field is missing from the relationship payload. |
'type' is not valid. | The relationship type is not valid or not registered. |
The method returns a promise that resolves to a BulkRelationshipsResponse object containing the ingestion results.
On success, results is an object where:
"external-team-works-on-jira-work-item-worklog")Example response:
1 2{ "success": true, "results": { "external-team-works-on-jira-work-item-worklog": [ { "from": { "type": "atlassian:team", "value": { "entityId": "team-id-1" } }, "to": { "type": "issueWorklogId", "value": { "issueId": "10001", "worklogId": "20002" } }, "updateSequenceNumber": 1, "createdAt": "2011-08-01T21:32:44.882Z", "updatedAt": "2011-08-01T21:32:44.882Z" } ] } }
1 2if (response.success && response.results) { // Iterate over relationship types Object.entries(response.results).forEach(([relationshipType, relationships]) => { console.log(`Relationship type: ${relationshipType}`); console.log(`Created ${relationships.length} relationships`); relationships.forEach(relationship => { console.log(`From: ${relationship.from.type} (${relationship.from.value.entityId})`); console.log(`To: ${relationship.to.type} (${relationship.to.value.issueId})`); }); }); // Access specific relationship type const teamWorklogRelationships = response.results['external-team-works-on-jira-work-item-worklog']; if (teamWorklogRelationships) { console.log(`Created ${teamWorklogRelationships.length} team-worklog relationships`); } }
Relationship types are string identifiers that describe the nature of the relationship. They typically follow a naming convention:
Format: external-{source-type}-{action}-{target-type}
external-team-works-on-jira-work-item-worklog - Team works on a Jira work item worklogexternal-team-works-on-worklog - Team works on a worklogexternal-document-works-on-jira-work-item - Document relates to a Jira work itemNote: Relationship types must be valid and may need to be registered or follow specific conventions defined by your connector configuration.
atlassian:document - Document entitiesatlassian:team - Team entitiesatlassian:work-item - Work item entitiesissueId - Jira issue identifierissueWorklogId - Jira issue worklog identifierFor atlassian:document:
1 2{ type: 'atlassian:document', value: { entityId: 'doc-001' } }
For issueId:
1 2{ type: 'issueId', value: { issueId: 'PT-1' } }
For issueWorklogId:
1 2{ type: 'issueWorklogId', value: { issueId: '10001', worklogId: '20002' } }
All types are exported from @forge/teamwork-graph:
1 2import { types, graph } from '@forge/teamwork-graph'; // Available types: // - types.RelationshipPayload // - types.RelationshipEntity // - types.RelationshipEntityValue // - types.BulkRelationshipsRequest // - types.BulkRelationshipsResponse
MAX_BULK_RELATIONSHIPS = 100 - Maximum number of relationships per bulk requestupdateSequenceNumber for conflict resolution and tracking updatescreatedAt and updatedAt timestamps in ISO 8601 formatsuccess field and handle errors appropriatelyconnectionId for your connectorRate this page: