curl --request POST \
--url https://api.dittowords.com/v2/textItems/linkFigmaNodes \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"projectId": "project-id-1",
"links": [
{
"textItemId": "greeting",
"figmaNodeIds": [
"1:23",
"1:24"
]
},
{
"textItemId": "submit-button",
"figmaNodeIds": [
"1:30"
]
}
],
"branchId": null
}
'import requests
url = "https://api.dittowords.com/v2/textItems/linkFigmaNodes"
payload = {
"projectId": "project-id-1",
"links": [
{
"textItemId": "greeting",
"figmaNodeIds": ["1:23", "1:24"]
},
{
"textItemId": "submit-button",
"figmaNodeIds": ["1:30"]
}
],
"branchId": None
}
headers = {
"Authorization": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
projectId: 'project-id-1',
links: [
{textItemId: 'greeting', figmaNodeIds: ['1:23', '1:24']},
{textItemId: 'submit-button', figmaNodeIds: ['1:30']}
],
branchId: null
})
};
fetch('https://api.dittowords.com/v2/textItems/linkFigmaNodes', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.dittowords.com/v2/textItems/linkFigmaNodes",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'projectId' => 'project-id-1',
'links' => [
[
'textItemId' => 'greeting',
'figmaNodeIds' => [
'1:23',
'1:24'
]
],
[
'textItemId' => 'submit-button',
'figmaNodeIds' => [
'1:30'
]
]
],
'branchId' => null
]),
CURLOPT_HTTPHEADER => [
"Authorization: <api-key>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.dittowords.com/v2/textItems/linkFigmaNodes"
payload := strings.NewReader("{\n \"projectId\": \"project-id-1\",\n \"links\": [\n {\n \"textItemId\": \"greeting\",\n \"figmaNodeIds\": [\n \"1:23\",\n \"1:24\"\n ]\n },\n {\n \"textItemId\": \"submit-button\",\n \"figmaNodeIds\": [\n \"1:30\"\n ]\n }\n ],\n \"branchId\": null\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.dittowords.com/v2/textItems/linkFigmaNodes")
.header("Authorization", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"projectId\": \"project-id-1\",\n \"links\": [\n {\n \"textItemId\": \"greeting\",\n \"figmaNodeIds\": [\n \"1:23\",\n \"1:24\"\n ]\n },\n {\n \"textItemId\": \"submit-button\",\n \"figmaNodeIds\": [\n \"1:30\"\n ]\n }\n ],\n \"branchId\": null\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.dittowords.com/v2/textItems/linkFigmaNodes")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"projectId\": \"project-id-1\",\n \"links\": [\n {\n \"textItemId\": \"greeting\",\n \"figmaNodeIds\": [\n \"1:23\",\n \"1:24\"\n ]\n },\n {\n \"textItemId\": \"submit-button\",\n \"figmaNodeIds\": [\n \"1:30\"\n ]\n }\n ],\n \"branchId\": null\n}"
response = http.request(request)
puts response.read_body{
"projectId": "project-id-1",
"branchId": null,
"results": [
{
"figmaNodeId": "1:23",
"textItemId": "greeting",
"outcome": "linked"
},
{
"figmaNodeId": "1:30",
"textItemId": "submit-button",
"outcome": "linked_to_other_text_item",
"linkedTextItemId": "header-title",
"message": "This Figma text node is already linked to text item \"header-title\"."
},
{
"figmaNodeId": "1:24",
"textItemId": "greeting",
"outcome": "not_found",
"message": "This Figma text node is not in the cache for the target project context. Sync first, then retry."
}
]
}{
"message": "Project \"project-id-1\" is not linked to Figma."
}{
"message": "Text item \"greeting\" was not found in project \"project-id-1\"."
}Link Figma nodes to text items
Links Figma text nodes to existing text items in a Figma-linked project, so those nodes become Figma instances of their text items. Takes a mapping of text item developer IDs to Figma node IDs.
The nodes must already have been synced to Ditto through the Ditto Figma plugin. Get node IDs from Figma (its REST API or MCP server). Pass branchId to link nodes inside a branch file; if not provided, nodes are looked up in the project’s main Figma file. A max of 500 distinct node IDs are allowed per request across all link mappings.
The link is recorded in Ditto right away, but Ditto writes to a Figma file only from the plugin. So the Figma layer doesn’t reflect the link — and later edits to the text item don’t reach that layer — until someone next opens the Ditto Figma plugin on the file.
Unknown text item IDs, or a node ID mapped to more than one text item, reject the whole request. Otherwise nodes are handled independently: the response reports an outcome per node ID. linked indicates a successful outcome. already_linked indicates the node is already linked to the requested text item, and linked_to_other_text_item indicates the node’s already linked to a different text item. Outcomes not_found (sync the file from the plugin, then retry), not_text_node, wrong_file_or_branch, or main_component_text_node (link instance text nodes directly, or link the main component’s text from the Figma plugin) all indicate the node was not linked.
curl --request POST \
--url https://api.dittowords.com/v2/textItems/linkFigmaNodes \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"projectId": "project-id-1",
"links": [
{
"textItemId": "greeting",
"figmaNodeIds": [
"1:23",
"1:24"
]
},
{
"textItemId": "submit-button",
"figmaNodeIds": [
"1:30"
]
}
],
"branchId": null
}
'import requests
url = "https://api.dittowords.com/v2/textItems/linkFigmaNodes"
payload = {
"projectId": "project-id-1",
"links": [
{
"textItemId": "greeting",
"figmaNodeIds": ["1:23", "1:24"]
},
{
"textItemId": "submit-button",
"figmaNodeIds": ["1:30"]
}
],
"branchId": None
}
headers = {
"Authorization": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
projectId: 'project-id-1',
links: [
{textItemId: 'greeting', figmaNodeIds: ['1:23', '1:24']},
{textItemId: 'submit-button', figmaNodeIds: ['1:30']}
],
branchId: null
})
};
fetch('https://api.dittowords.com/v2/textItems/linkFigmaNodes', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.dittowords.com/v2/textItems/linkFigmaNodes",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'projectId' => 'project-id-1',
'links' => [
[
'textItemId' => 'greeting',
'figmaNodeIds' => [
'1:23',
'1:24'
]
],
[
'textItemId' => 'submit-button',
'figmaNodeIds' => [
'1:30'
]
]
],
'branchId' => null
]),
CURLOPT_HTTPHEADER => [
"Authorization: <api-key>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.dittowords.com/v2/textItems/linkFigmaNodes"
payload := strings.NewReader("{\n \"projectId\": \"project-id-1\",\n \"links\": [\n {\n \"textItemId\": \"greeting\",\n \"figmaNodeIds\": [\n \"1:23\",\n \"1:24\"\n ]\n },\n {\n \"textItemId\": \"submit-button\",\n \"figmaNodeIds\": [\n \"1:30\"\n ]\n }\n ],\n \"branchId\": null\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.dittowords.com/v2/textItems/linkFigmaNodes")
.header("Authorization", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"projectId\": \"project-id-1\",\n \"links\": [\n {\n \"textItemId\": \"greeting\",\n \"figmaNodeIds\": [\n \"1:23\",\n \"1:24\"\n ]\n },\n {\n \"textItemId\": \"submit-button\",\n \"figmaNodeIds\": [\n \"1:30\"\n ]\n }\n ],\n \"branchId\": null\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.dittowords.com/v2/textItems/linkFigmaNodes")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"projectId\": \"project-id-1\",\n \"links\": [\n {\n \"textItemId\": \"greeting\",\n \"figmaNodeIds\": [\n \"1:23\",\n \"1:24\"\n ]\n },\n {\n \"textItemId\": \"submit-button\",\n \"figmaNodeIds\": [\n \"1:30\"\n ]\n }\n ],\n \"branchId\": null\n}"
response = http.request(request)
puts response.read_body{
"projectId": "project-id-1",
"branchId": null,
"results": [
{
"figmaNodeId": "1:23",
"textItemId": "greeting",
"outcome": "linked"
},
{
"figmaNodeId": "1:30",
"textItemId": "submit-button",
"outcome": "linked_to_other_text_item",
"linkedTextItemId": "header-title",
"message": "This Figma text node is already linked to text item \"header-title\"."
},
{
"figmaNodeId": "1:24",
"textItemId": "greeting",
"outcome": "not_found",
"message": "This Figma text node is not in the cache for the target project context. Sync first, then retry."
}
]
}{
"message": "Project \"project-id-1\" is not linked to Figma."
}{
"message": "Text item \"greeting\" was not found in project \"project-id-1\"."
}Authorizations
Body
Developer ID of the Ditto project linked to the Figma file containing these nodes.
Text items and the Figma node IDs to link to each. Max 500 distinct node IDs in total per request, across all links.
1Show child attributes
Show child attributes
Figma branch ID (from the branch file's Figma URL) that every node in this request belongs to; one branch per request. If omitted, nodes are looked up in the project's main Figma file.
Response
Returns the resolved project and branch context, plus 1 result per distinct Figma node ID