@growthub/cli 0.3.53 → 0.3.55
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/worker-kits/growthub-ai-website-cloner-v1/.env.example +7 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/QUICKSTART.md +116 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/brands/NEW-CLIENT.md +22 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/brands/_template/brand-kit.md +27 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/brands/growthub/brand-kit.md +26 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/bundles/growthub-ai-website-cloner-v1.json +53 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/docs/ai-website-cloner-fork-integration.md +118 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/docs/design-token-system.md +135 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/docs/multi-phase-pipeline.md +129 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/docs/parallel-builder-dispatch.md +103 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/examples/clone-brief-sample.md +54 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/examples/component-spec-sample.md +123 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/examples/platform-handoff-sample.md +102 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/examples/visual-qa-sample.md +119 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/growthub-meta/README.md +71 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/growthub-meta/kit-standard.md +47 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/kit.json +105 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/output/README.md +26 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/output-standards.md +75 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/runtime-assumptions.md +70 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/setup/check-deps.sh +50 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/setup/clone-fork.sh +66 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/setup/verify-env.mjs +78 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/skills.md +186 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/templates/asset-manifest.md +57 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/templates/builder-dispatch-plan.md +92 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/templates/clone-brief.md +59 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/templates/component-spec.md +124 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/templates/design-token-extraction.md +89 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/templates/platform-handoff.md +114 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/templates/reconnaissance-report.md +77 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/templates/visual-qa-checklist.md +107 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/validation-checklist.md +76 -0
- package/assets/worker-kits/growthub-ai-website-cloner-v1/workers/ai-website-cloner-operator/CLAUDE.md +256 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/.env.example +40 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/QUICKSTART.md +114 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/brands/NEW-CLIENT.md +42 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/brands/_template/brand-kit.md +49 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/brands/growthub/brand-kit.md +50 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/bundles/growthub-open-montage-studio-v1.json +55 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/docs/cms-node-bridge.md +152 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/docs/open-montage-fork-integration.md +120 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/docs/pipeline-reference.md +147 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/docs/provider-adapter-layer.md +105 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/examples/cms-node-video-gen-sample.md +109 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/examples/pipeline-selection-sample.md +67 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/examples/platform-ready-handoff-sample.md +101 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/examples/video-production-brief-sample.md +68 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/growthub-meta/README.md +7 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/growthub-meta/kit-standard.md +45 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/kit.json +107 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/output/README.md +34 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/output-standards.md +79 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/runtime-assumptions.md +86 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/setup/check-deps.sh +43 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/setup/clone-fork.sh +53 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/setup/verify-env.mjs +102 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/skills.md +254 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/templates/asset-tracking.md +46 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/templates/cms-node-pipeline-mapping.md +64 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/templates/generation-batch-plan.md +70 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/templates/pipeline-selection-brief.md +67 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/templates/platform-ready-execution-handoff.md +103 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/templates/prompt-matrix.md +48 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/templates/provider-selection-brief.md +86 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/templates/review-qa-checklist.md +59 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/templates/scene-plan.md +65 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/templates/video-production-brief.md +58 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/validation-checklist.md +46 -0
- package/assets/worker-kits/growthub-open-montage-studio-v1/workers/open-montage-studio-operator/CLAUDE.md +304 -0
- package/assets/worker-kits/growthub-postiz-social-v1/.env.example +18 -0
- package/assets/worker-kits/growthub-postiz-social-v1/QUICKSTART.md +136 -0
- package/assets/worker-kits/growthub-postiz-social-v1/brands/NEW-CLIENT.md +67 -0
- package/assets/worker-kits/growthub-postiz-social-v1/brands/_template/brand-kit.md +120 -0
- package/assets/worker-kits/growthub-postiz-social-v1/brands/growthub/brand-kit.md +117 -0
- package/assets/worker-kits/growthub-postiz-social-v1/bundles/growthub-postiz-social-v1.json +52 -0
- package/assets/worker-kits/growthub-postiz-social-v1/docs/ai-caption-layer.md +118 -0
- package/assets/worker-kits/growthub-postiz-social-v1/docs/bullmq-queue-layer.md +157 -0
- package/assets/worker-kits/growthub-postiz-social-v1/docs/platform-coverage.md +97 -0
- package/assets/worker-kits/growthub-postiz-social-v1/docs/postiz-fork-integration.md +143 -0
- package/assets/worker-kits/growthub-postiz-social-v1/examples/analytics-brief-sample.md +125 -0
- package/assets/worker-kits/growthub-postiz-social-v1/examples/client-proposal-sample.md +127 -0
- package/assets/worker-kits/growthub-postiz-social-v1/examples/content-calendar-sample.md +75 -0
- package/assets/worker-kits/growthub-postiz-social-v1/examples/social-campaign-sample.md +104 -0
- package/assets/worker-kits/growthub-postiz-social-v1/growthub-meta/README.md +128 -0
- package/assets/worker-kits/growthub-postiz-social-v1/growthub-meta/kit-standard.md +113 -0
- package/assets/worker-kits/growthub-postiz-social-v1/kit.json +104 -0
- package/assets/worker-kits/growthub-postiz-social-v1/output/README.md +56 -0
- package/assets/worker-kits/growthub-postiz-social-v1/output-standards.md +127 -0
- package/assets/worker-kits/growthub-postiz-social-v1/runtime-assumptions.md +159 -0
- package/assets/worker-kits/growthub-postiz-social-v1/setup/check-deps.sh +117 -0
- package/assets/worker-kits/growthub-postiz-social-v1/setup/clone-fork.sh +83 -0
- package/assets/worker-kits/growthub-postiz-social-v1/setup/verify-env.mjs +99 -0
- package/assets/worker-kits/growthub-postiz-social-v1/skills.md +277 -0
- package/assets/worker-kits/growthub-postiz-social-v1/templates/analytics-brief.md +123 -0
- package/assets/worker-kits/growthub-postiz-social-v1/templates/caption-copy-deck.md +127 -0
- package/assets/worker-kits/growthub-postiz-social-v1/templates/client-proposal.md +139 -0
- package/assets/worker-kits/growthub-postiz-social-v1/templates/content-calendar.md +65 -0
- package/assets/worker-kits/growthub-postiz-social-v1/templates/platform-publishing-plan.md +112 -0
- package/assets/worker-kits/growthub-postiz-social-v1/templates/scheduling-manifest.md +83 -0
- package/assets/worker-kits/growthub-postiz-social-v1/templates/social-campaign-brief.md +111 -0
- package/assets/worker-kits/growthub-postiz-social-v1/validation-checklist.md +79 -0
- package/assets/worker-kits/growthub-postiz-social-v1/workers/postiz-social-operator/CLAUDE.md +287 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/.env.example +15 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/QUICKSTART.md +90 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/brands/NEW-CLIENT.md +57 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/brands/_template/brand-kit.md +88 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/brands/growthub/brand-kit.md +92 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/bundles/growthub-twenty-crm-v1.json +56 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/docs/api-and-webhooks.md +296 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/docs/data-model-layer.md +172 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/docs/twenty-fork-integration.md +213 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/examples/crm-playbook-sample.md +172 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/examples/crm-setup-sample.md +100 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/examples/lead-enrichment-sample.md +117 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/examples/pipeline-automation-sample.md +132 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/growthub-meta/README.md +114 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/growthub-meta/kit-standard.md +61 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/kit.json +108 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/output/README.md +46 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/output-standards.md +175 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/runtime-assumptions.md +150 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/setup/check-deps.sh +56 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/setup/clone-fork.sh +77 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/setup/verify-env.mjs +105 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/skills.md +401 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/templates/api-query-plan.md +179 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/templates/crm-playbook.md +155 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/templates/crm-setup-brief.md +94 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/templates/custom-object-design.md +115 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/templates/data-model-design.md +112 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/templates/enrichment-field-map.md +100 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/templates/import-mapping.md +139 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/templates/integration-handoff.md +190 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/templates/lead-enrichment-pipeline.md +128 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/templates/pipeline-automation-brief.md +88 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/templates/webhook-integration-spec.md +129 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/templates/workspace-config-checklist.md +129 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/validation-checklist.md +115 -0
- package/assets/worker-kits/growthub-twenty-crm-v1/workers/twenty-crm-operator/CLAUDE.md +310 -0
- package/package.json +1 -1
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// verify-env.mjs — Validate Twenty CRM credentials and API connectivity.
|
|
3
|
+
// Usage: node setup/verify-env.mjs
|
|
4
|
+
// Exit 0 = credentials are valid and API is reachable. Exit 1 = missing, invalid, or unreachable.
|
|
5
|
+
|
|
6
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
7
|
+
import { resolve } from "node:path";
|
|
8
|
+
|
|
9
|
+
const envPath = resolve(process.cwd(), ".env");
|
|
10
|
+
|
|
11
|
+
function parseEnvFile(filePath) {
|
|
12
|
+
const vars = {};
|
|
13
|
+
const lines = readFileSync(filePath, "utf8").split("\n");
|
|
14
|
+
for (const line of lines) {
|
|
15
|
+
const trimmed = line.trim();
|
|
16
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
17
|
+
const eqIndex = trimmed.indexOf("=");
|
|
18
|
+
if (eqIndex === -1) continue;
|
|
19
|
+
const key = trimmed.slice(0, eqIndex).trim();
|
|
20
|
+
const value = trimmed.slice(eqIndex + 1).trim();
|
|
21
|
+
vars[key] = value;
|
|
22
|
+
}
|
|
23
|
+
return vars;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async function main() {
|
|
27
|
+
if (!existsSync(envPath)) {
|
|
28
|
+
console.error("ERROR: .env file not found.");
|
|
29
|
+
console.error("Run: cp .env.example .env then set your TWENTY_API_TOKEN and TWENTY_API_URL.");
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const env = parseEnvFile(envPath);
|
|
34
|
+
const apiToken = env["TWENTY_API_TOKEN"];
|
|
35
|
+
const apiUrl = env["TWENTY_API_URL"] ?? "https://api.twenty.com";
|
|
36
|
+
|
|
37
|
+
if (!apiToken || apiToken === "your_twenty_api_token_here" || apiToken.trim() === "") {
|
|
38
|
+
console.error("ERROR: TWENTY_API_TOKEN is not set in .env.");
|
|
39
|
+
console.error("Generate a token in your Twenty workspace: Settings > API > Tokens");
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
console.log(`Verifying token against ${apiUrl} ...`);
|
|
44
|
+
|
|
45
|
+
const graphqlQuery = JSON.stringify({
|
|
46
|
+
query: "{ currentWorkspace { id displayName } }",
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
let res;
|
|
50
|
+
try {
|
|
51
|
+
res = await fetch(`${apiUrl}/graphql`, {
|
|
52
|
+
method: "POST",
|
|
53
|
+
headers: {
|
|
54
|
+
Authorization: `Bearer ${apiToken}`,
|
|
55
|
+
"Content-Type": "application/json",
|
|
56
|
+
},
|
|
57
|
+
body: graphqlQuery,
|
|
58
|
+
});
|
|
59
|
+
} catch (err) {
|
|
60
|
+
console.error(`ERROR: Could not reach ${apiUrl}.`);
|
|
61
|
+
console.error(err.message);
|
|
62
|
+
console.error("");
|
|
63
|
+
console.error("If using local-fork mode, ensure Twenty is running via Docker Compose.");
|
|
64
|
+
console.error("Run: bash setup/clone-fork.sh");
|
|
65
|
+
process.exit(1);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (res.status === 401 || res.status === 403) {
|
|
69
|
+
console.error(`ERROR: API token rejected (HTTP ${res.status}).`);
|
|
70
|
+
console.error("Check your TWENTY_API_TOKEN in .env — generate a new one at Settings > API > Tokens.");
|
|
71
|
+
process.exit(1);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (!res.ok) {
|
|
75
|
+
console.error(`ERROR: Unexpected response from Twenty API (HTTP ${res.status}).`);
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
let body;
|
|
80
|
+
try {
|
|
81
|
+
body = await res.json();
|
|
82
|
+
} catch {
|
|
83
|
+
console.error("ERROR: Could not parse API response as JSON.");
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (body.errors && body.errors.length > 0) {
|
|
88
|
+
console.error("ERROR: GraphQL error from Twenty API:");
|
|
89
|
+
for (const err of body.errors) {
|
|
90
|
+
console.error(` - ${err.message}`);
|
|
91
|
+
}
|
|
92
|
+
process.exit(1);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const workspace = body?.data?.currentWorkspace;
|
|
96
|
+
if (workspace) {
|
|
97
|
+
console.log(`OK: Connected to workspace "${workspace.displayName}" (id: ${workspace.id})`);
|
|
98
|
+
} else {
|
|
99
|
+
console.log("OK: TWENTY_API_TOKEN is valid and the API is reachable.");
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
process.exit(0);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
main();
|
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
# Twenty CRM Operator — Master Skill Doc
|
|
2
|
+
|
|
3
|
+
**Source of truth for methodology. Read this file completely before beginning any task.**
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## QUICK REFERENCE TABLE
|
|
8
|
+
|
|
9
|
+
| Resource | Path |
|
|
10
|
+
|---|---|
|
|
11
|
+
| Agent operating law | `workers/twenty-crm-operator/CLAUDE.md` |
|
|
12
|
+
| Brand kit template | `brands/_template/brand-kit.md` |
|
|
13
|
+
| Growthub example brand kit | `brands/growthub/brand-kit.md` |
|
|
14
|
+
| Output contract | `output-standards.md` |
|
|
15
|
+
| Runtime assumptions | `runtime-assumptions.md` |
|
|
16
|
+
| Fork integration notes | `docs/twenty-fork-integration.md` |
|
|
17
|
+
| API and webhooks doc | `docs/api-and-webhooks.md` |
|
|
18
|
+
| Data model layer doc | `docs/data-model-layer.md` |
|
|
19
|
+
| CRM setup brief | `templates/crm-setup-brief.md` |
|
|
20
|
+
| Data model design | `templates/data-model-design.md` |
|
|
21
|
+
| Lead enrichment pipeline | `templates/lead-enrichment-pipeline.md` |
|
|
22
|
+
| Pipeline automation brief | `templates/pipeline-automation-brief.md` |
|
|
23
|
+
| Webhook integration spec | `templates/webhook-integration-spec.md` |
|
|
24
|
+
| API query plan | `templates/api-query-plan.md` |
|
|
25
|
+
| CRM playbook | `templates/crm-playbook.md` |
|
|
26
|
+
| Custom object design | `templates/custom-object-design.md` |
|
|
27
|
+
| Import mapping | `templates/import-mapping.md` |
|
|
28
|
+
| Workspace config checklist | `templates/workspace-config-checklist.md` |
|
|
29
|
+
| Integration handoff | `templates/integration-handoff.md` |
|
|
30
|
+
| Enrichment field map | `templates/enrichment-field-map.md` |
|
|
31
|
+
| Sample CRM setup | `examples/crm-setup-sample.md` |
|
|
32
|
+
| Sample enrichment pipeline | `examples/lead-enrichment-sample.md` |
|
|
33
|
+
| Sample pipeline automation | `examples/pipeline-automation-sample.md` |
|
|
34
|
+
| Sample CRM playbook | `examples/crm-playbook-sample.md` |
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## STEP 0 — BEFORE ANY TASK, ANSWER THESE QUESTIONS
|
|
39
|
+
|
|
40
|
+
Before producing anything, confirm:
|
|
41
|
+
|
|
42
|
+
1. Which client or brand is this for?
|
|
43
|
+
2. What is the primary CRM use case?
|
|
44
|
+
3. What data sources exist today?
|
|
45
|
+
4. What deployment mode is the client using?
|
|
46
|
+
5. Does the client have a local fork available for inspection?
|
|
47
|
+
6. What is the expected go-live scope: data model only / pipeline only / full implementation?
|
|
48
|
+
|
|
49
|
+
If any of these are unknown after the 3-question gate in CLAUDE.md, stop and ask.
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## STEP 1 — LOAD THE BRAND KIT
|
|
54
|
+
|
|
55
|
+
Read `brands/<client-slug>/brand-kit.md` if it exists. Otherwise start from `brands/_template/brand-kit.md`.
|
|
56
|
+
|
|
57
|
+
Extract:
|
|
58
|
+
- client identity (name, slug, industry, company size)
|
|
59
|
+
- primary CRM objective
|
|
60
|
+
- current tech stack and data sources
|
|
61
|
+
- pipeline stages and deal flow
|
|
62
|
+
- team size and CRM admin capacity
|
|
63
|
+
- target enrichment providers
|
|
64
|
+
- existing deliverables log
|
|
65
|
+
|
|
66
|
+
The brand kit drives all output naming, object naming conventions, and proposal context.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## STEP 2 — CHECK THE WORKING SUBSTRATE
|
|
71
|
+
|
|
72
|
+
If the user has a local Twenty fork, inspect it before planning anything.
|
|
73
|
+
|
|
74
|
+
### Source-of-truth file order in the fork
|
|
75
|
+
|
|
76
|
+
1. `README.md`
|
|
77
|
+
2. `packages/twenty-server/src/modules/` — standard CRM object modules
|
|
78
|
+
3. `packages/twenty-server/src/metadata/` — custom object and field metadata API
|
|
79
|
+
4. `packages/twenty-server/src/api/` — REST and GraphQL endpoint definitions
|
|
80
|
+
5. `packages/twenty-server/src/workflow/` — workflow trigger and action engine
|
|
81
|
+
6. `packages/twenty-front/src/modules/` — UI module definitions
|
|
82
|
+
7. `packages/twenty-cli/src/` — CLI command surface
|
|
83
|
+
8. `docker-compose.yml` — self-hosted stack definition
|
|
84
|
+
|
|
85
|
+
### What to verify in the fork
|
|
86
|
+
|
|
87
|
+
- Which standard CRM objects are present (`Person`, `Company`, `Opportunity`, etc.)
|
|
88
|
+
- Whether the metadata API is enabled and accessible
|
|
89
|
+
- What workflow trigger types are implemented
|
|
90
|
+
- Whether webhook outbound actions are supported
|
|
91
|
+
- What the GraphQL schema looks like for the target objects
|
|
92
|
+
- Which CLI commands are available
|
|
93
|
+
- Whether any custom modules are already registered
|
|
94
|
+
|
|
95
|
+
If the fork cannot be inspected, use the frozen assumptions in `runtime-assumptions.md` and label outputs `assumption-based`.
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## STEP 3 — WORKFLOW SELECTION LOGIC
|
|
100
|
+
|
|
101
|
+
Select the narrowest workflow scope that satisfies the real job.
|
|
102
|
+
|
|
103
|
+
| Workflow | Primary Use | Data Model Required? | Automation Required? |
|
|
104
|
+
|---|---|---|---|
|
|
105
|
+
| `crm-setup` | Net-new workspace from scratch | Yes | Optional |
|
|
106
|
+
| `data-model` | Object schema design only | Yes | No |
|
|
107
|
+
| `lead-enrichment` | Import + enrichment pipeline | Yes | Optional |
|
|
108
|
+
| `pipeline-automation` | Trigger-action automation | Existing model assumed | Yes |
|
|
109
|
+
| `webhook-integration` | External event or outbound hook | Existing model assumed | Yes |
|
|
110
|
+
| `api-reporting` | Query plans for data access | Existing model assumed | No |
|
|
111
|
+
| `full-playbook` | All-in CRM operator documentation | Yes | Yes |
|
|
112
|
+
|
|
113
|
+
Default selection rules:
|
|
114
|
+
- "Set up Twenty from scratch" → `crm-setup` → escalate to `full-playbook`
|
|
115
|
+
- "Design objects for X use case" → `data-model`
|
|
116
|
+
- "Connect Apollo / Clearbit / Clay" → `lead-enrichment`
|
|
117
|
+
- "Automate follow-up / stage transitions" → `pipeline-automation`
|
|
118
|
+
- "Connect Segment / Stripe / Intercom" → `webhook-integration`
|
|
119
|
+
- "Build a dashboard or export data" → `api-reporting`
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## STEP 4 — DATA MODEL DESIGN LOGIC
|
|
124
|
+
|
|
125
|
+
Twenty supports both standard objects and fully custom metadata-defined objects.
|
|
126
|
+
|
|
127
|
+
### Standard objects (always available)
|
|
128
|
+
|
|
129
|
+
| Object | Purpose | Key fields |
|
|
130
|
+
|---|---|---|
|
|
131
|
+
| `Person` | Individual contacts | name, email, phone, company, city, linkedInLink, position |
|
|
132
|
+
| `Company` | Organizations | name, domain, employees, annualRecurringRevenue, address |
|
|
133
|
+
| `Opportunity` | Deals and pipeline | name, stage, amount, closeDate, pointOfContact |
|
|
134
|
+
| `Note` | Freeform notes | body, author, target (relation) |
|
|
135
|
+
| `Task` | Action items | title, dueAt, assignee, status, target (relation) |
|
|
136
|
+
| `Workspace Member` | Team users | name, email, role |
|
|
137
|
+
|
|
138
|
+
### Custom objects
|
|
139
|
+
|
|
140
|
+
When standard objects do not fit the use case:
|
|
141
|
+
|
|
142
|
+
1. Define the object in `templates/custom-object-design.md`
|
|
143
|
+
2. Specify all fields (name, type, required, select options if enum)
|
|
144
|
+
3. Define relationships to standard or other custom objects
|
|
145
|
+
4. Document whether creation is via UI (`Settings > Objects`) or metadata API
|
|
146
|
+
5. Define the default view configuration
|
|
147
|
+
|
|
148
|
+
### Field types available in Twenty
|
|
149
|
+
|
|
150
|
+
- `TEXT` — single-line text
|
|
151
|
+
- `RICH_TEXT` — multi-line rich text
|
|
152
|
+
- `NUMBER` — numeric (integer or decimal)
|
|
153
|
+
- `BOOLEAN` — true/false toggle
|
|
154
|
+
- `DATE` — date only
|
|
155
|
+
- `DATE_TIME` — date and time
|
|
156
|
+
- `SELECT` — single-choice from predefined options
|
|
157
|
+
- `MULTI_SELECT` — multi-choice from predefined options
|
|
158
|
+
- `RELATION` — link to another object (one-to-one, one-to-many, many-to-many)
|
|
159
|
+
- `LINK` — URL field (label + href)
|
|
160
|
+
- `EMAILS` — multi-email field with primary designation
|
|
161
|
+
- `PHONES` — multi-phone field with primary designation
|
|
162
|
+
- `CURRENCY` — amount + currency code pair
|
|
163
|
+
- `ADDRESS` — structured address (street, city, state, country, postalCode)
|
|
164
|
+
- `RATING` — 1–5 star rating
|
|
165
|
+
|
|
166
|
+
### Naming conventions
|
|
167
|
+
|
|
168
|
+
- Object names: PascalCase (`LeadScore`, `PartnerAccount`)
|
|
169
|
+
- Field names: camelCase (`enrichmentSource`, `closeDate`)
|
|
170
|
+
- Select option values: SCREAMING_SNAKE_CASE (`QUALIFIED`, `NOT_INTERESTED`)
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
## STEP 5 — LEAD ENRICHMENT PIPELINE LOGIC
|
|
175
|
+
|
|
176
|
+
Enrichment pipelines connect external data providers to Twenty CRM contact and company records.
|
|
177
|
+
|
|
178
|
+
### Supported enrichment patterns
|
|
179
|
+
|
|
180
|
+
| Pattern | Description |
|
|
181
|
+
|---|---|
|
|
182
|
+
| CSV import + field map | Bulk import from Apollo/Clay export with field-to-Twenty mapping |
|
|
183
|
+
| Webhook ingest | Inbound webhook from enrichment provider populates records |
|
|
184
|
+
| GraphQL mutation | Direct API call to create/update Person or Company records |
|
|
185
|
+
| REST API batch | POST to Twenty REST API with enriched data |
|
|
186
|
+
|
|
187
|
+
### Deduplication strategy (required)
|
|
188
|
+
|
|
189
|
+
Every enrichment pipeline must define a match key before import:
|
|
190
|
+
|
|
191
|
+
| Match key | When to use |
|
|
192
|
+
|---|---|
|
|
193
|
+
| `email` | Primary match for Person objects — highest reliability |
|
|
194
|
+
| `domain` | Primary match for Company objects |
|
|
195
|
+
| `linkedInLink` | Secondary match for Person when email is unavailable |
|
|
196
|
+
| `phone` | Tertiary match — use only when domain and email are both absent |
|
|
197
|
+
| Composite | Email + domain for contacts with company context |
|
|
198
|
+
|
|
199
|
+
Deduplication behavior in Twenty:
|
|
200
|
+
- On import, Twenty checks for existing records matching the key field
|
|
201
|
+
- If a match is found: update existing record (merge mode)
|
|
202
|
+
- If no match: create new record (insert mode)
|
|
203
|
+
- Always document whether the pipeline runs in merge or insert-only mode
|
|
204
|
+
|
|
205
|
+
### Enrichment field map requirements
|
|
206
|
+
|
|
207
|
+
For every provider integration, produce an `EnrichmentFieldMap` that lists:
|
|
208
|
+
- provider field name
|
|
209
|
+
- provider data type
|
|
210
|
+
- target Twenty object
|
|
211
|
+
- target Twenty field name
|
|
212
|
+
- target Twenty field type
|
|
213
|
+
- transformation required (none / normalize / truncate / format)
|
|
214
|
+
- required / optional
|
|
215
|
+
|
|
216
|
+
Use `templates/enrichment-field-map.md`.
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## STEP 6 — PIPELINE AUTOMATION LOGIC
|
|
221
|
+
|
|
222
|
+
Twenty's workflow engine supports trigger-action automation for any object.
|
|
223
|
+
|
|
224
|
+
### Trigger types
|
|
225
|
+
|
|
226
|
+
| Trigger | Event |
|
|
227
|
+
|---|---|
|
|
228
|
+
| `on_create` | A record of the specified object type is created |
|
|
229
|
+
| `on_update` | A record is updated (optionally scoped to specific fields) |
|
|
230
|
+
| `on_field_change` | A specific field value changes (supports before/after conditions) |
|
|
231
|
+
| `on_delete` | A record is deleted |
|
|
232
|
+
| `on_schedule` | Time-based trigger (cron expression) |
|
|
233
|
+
| `on_webhook` | Inbound webhook event triggers a workflow |
|
|
234
|
+
|
|
235
|
+
### Action types
|
|
236
|
+
|
|
237
|
+
| Action | What it does |
|
|
238
|
+
|---|---|
|
|
239
|
+
| `update_field` | Set one or more fields on the trigger record or a related record |
|
|
240
|
+
| `create_record` | Create a new record of any object type |
|
|
241
|
+
| `send_webhook` | Fire an outbound HTTP POST to an external endpoint |
|
|
242
|
+
| `assign_owner` | Assign the record to a specific workspace member or rotation |
|
|
243
|
+
| `create_task` | Create a Task linked to the trigger record |
|
|
244
|
+
| `send_notification` | In-app notification to a workspace member |
|
|
245
|
+
|
|
246
|
+
### Automation design rules
|
|
247
|
+
|
|
248
|
+
- One trigger per workflow — do not chain triggers into a single workflow definition
|
|
249
|
+
- Conditions on `on_update` must specify which field changed and what values are relevant
|
|
250
|
+
- `send_webhook` actions must include the full endpoint, payload schema, and retry policy
|
|
251
|
+
- Every automation must have an explicit "when this fails" path documented
|
|
252
|
+
- Do not design polling loops when `on_update` or `on_webhook` triggers are available
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
## STEP 7 — API AND WEBHOOK INTEGRATION LOGIC
|
|
257
|
+
|
|
258
|
+
### GraphQL API
|
|
259
|
+
|
|
260
|
+
Twenty's GraphQL API is the primary data access surface.
|
|
261
|
+
|
|
262
|
+
Common query patterns:
|
|
263
|
+
|
|
264
|
+
```graphql
|
|
265
|
+
# Fetch all persons with company relation
|
|
266
|
+
query {
|
|
267
|
+
people {
|
|
268
|
+
edges {
|
|
269
|
+
node {
|
|
270
|
+
id
|
|
271
|
+
name { firstName lastName }
|
|
272
|
+
emails { primaryEmail }
|
|
273
|
+
company { name domain }
|
|
274
|
+
createdAt
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
# Create a person record
|
|
281
|
+
mutation {
|
|
282
|
+
createPerson(data: {
|
|
283
|
+
name: { firstName: "Jane", lastName: "Doe" }
|
|
284
|
+
emails: { primaryEmail: "jane@example.com" }
|
|
285
|
+
companyId: "<company-id>"
|
|
286
|
+
}) {
|
|
287
|
+
id
|
|
288
|
+
createdAt
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
# Update an opportunity stage
|
|
293
|
+
mutation {
|
|
294
|
+
updateOpportunity(
|
|
295
|
+
id: "<opportunity-id>"
|
|
296
|
+
data: { stage: "CLOSING" }
|
|
297
|
+
) {
|
|
298
|
+
id
|
|
299
|
+
stage
|
|
300
|
+
updatedAt
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### REST API
|
|
306
|
+
|
|
307
|
+
Twenty provides a REST API at `/api/objects/<object-name>` for simple CRUD operations.
|
|
308
|
+
|
|
309
|
+
```bash
|
|
310
|
+
# GET all companies
|
|
311
|
+
GET /api/objects/companies
|
|
312
|
+
|
|
313
|
+
# POST a new person
|
|
314
|
+
POST /api/objects/people
|
|
315
|
+
Content-Type: application/json
|
|
316
|
+
Authorization: Bearer <app-token>
|
|
317
|
+
|
|
318
|
+
# PATCH update a field
|
|
319
|
+
PATCH /api/objects/opportunities/<id>
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### Webhooks
|
|
323
|
+
|
|
324
|
+
Twenty emits webhook events for object lifecycle events.
|
|
325
|
+
|
|
326
|
+
Event naming pattern: `<object>.<event>` (e.g., `opportunity.created`, `person.updated`)
|
|
327
|
+
|
|
328
|
+
Every webhook spec must define:
|
|
329
|
+
- event name
|
|
330
|
+
- trigger object and conditions
|
|
331
|
+
- payload schema (what Twenty sends)
|
|
332
|
+
- target endpoint URL pattern
|
|
333
|
+
- auth mechanism on the receiving end
|
|
334
|
+
- retry policy (Twenty default: 3 attempts with exponential backoff)
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
338
|
+
## STEP 8 — IMPORT AND MIGRATION LOGIC
|
|
339
|
+
|
|
340
|
+
When migrating from another CRM (Salesforce, HubSpot, Pipedrive, Airtable):
|
|
341
|
+
|
|
342
|
+
### Import workflow
|
|
343
|
+
|
|
344
|
+
1. Export data from source CRM as CSV
|
|
345
|
+
2. Clean and deduplicate the CSV (remove test records, normalize email format)
|
|
346
|
+
3. Produce an `ImportMapping` document that maps every source column to a Twenty field
|
|
347
|
+
4. Run a sample import (first 50 rows) and verify field alignment
|
|
348
|
+
5. Run the full import
|
|
349
|
+
6. Run a post-import audit: record count, duplicate check, relation integrity
|
|
350
|
+
|
|
351
|
+
### Common source-to-Twenty field mappings
|
|
352
|
+
|
|
353
|
+
| Source (generic) | Twenty Field | Object | Notes |
|
|
354
|
+
|---|---|---|---|
|
|
355
|
+
| First Name | `name.firstName` | Person | |
|
|
356
|
+
| Last Name | `name.lastName` | Person | |
|
|
357
|
+
| Email | `emails.primaryEmail` | Person | Use as dedup key |
|
|
358
|
+
| Phone | `phones.primaryPhoneNumber` | Person | |
|
|
359
|
+
| Company Name | `company.name` | Company | Create or link |
|
|
360
|
+
| Company Domain | `company.domain` | Company | Use as dedup key |
|
|
361
|
+
| Job Title | `position` | Person | |
|
|
362
|
+
| LinkedIn URL | `linkedInLink.url` | Person | |
|
|
363
|
+
| Deal Name | `name` | Opportunity | |
|
|
364
|
+
| Deal Stage | `stage` | Opportunity | Map to Twenty select values |
|
|
365
|
+
| Deal Value | `amount.amountMicros` | Opportunity | Multiply by 1,000,000 for micros |
|
|
366
|
+
| Close Date | `closeDate` | Opportunity | ISO 8601 format |
|
|
367
|
+
|
|
368
|
+
---
|
|
369
|
+
|
|
370
|
+
## STEP 9 — OUTPUT ORDER
|
|
371
|
+
|
|
372
|
+
Produce artifacts in this strict order:
|
|
373
|
+
|
|
374
|
+
1. CRM Setup Brief (`templates/crm-setup-brief.md`)
|
|
375
|
+
2. Data Model Design (`templates/data-model-design.md`)
|
|
376
|
+
3. Lead Enrichment Pipeline (`templates/lead-enrichment-pipeline.md`)
|
|
377
|
+
4. Pipeline Automation Brief (`templates/pipeline-automation-brief.md`)
|
|
378
|
+
5. Webhook Integration Spec (`templates/webhook-integration-spec.md`)
|
|
379
|
+
6. API Query Plan (`templates/api-query-plan.md`)
|
|
380
|
+
7. Custom Object Design (`templates/custom-object-design.md`) — if custom objects required
|
|
381
|
+
8. Import Mapping (`templates/import-mapping.md`) — if data migration required
|
|
382
|
+
9. Workspace Config Checklist (`templates/workspace-config-checklist.md`)
|
|
383
|
+
10. Integration Handoff (`templates/integration-handoff.md`)
|
|
384
|
+
11. Enrichment Field Map (`templates/enrichment-field-map.md`)
|
|
385
|
+
12. CRM Playbook (`templates/crm-playbook.md`)
|
|
386
|
+
|
|
387
|
+
---
|
|
388
|
+
|
|
389
|
+
## STEP 10 — QUALITY BAR
|
|
390
|
+
|
|
391
|
+
Good output looks like this:
|
|
392
|
+
|
|
393
|
+
- all object schemas are grounded in Twenty's actual field types and naming conventions
|
|
394
|
+
- data model is complete before any automation or pipeline spec is written
|
|
395
|
+
- deduplication key is explicitly named in every import or enrichment pipeline
|
|
396
|
+
- every automation trigger-action pair has a named failure path
|
|
397
|
+
- webhook specs include the full payload schema, not just the event name
|
|
398
|
+
- GraphQL queries are syntactically correct and reference real Twenty field paths
|
|
399
|
+
- CRM playbook is written at a level a non-technical team member can execute
|
|
400
|
+
- every output file can be handed to a developer or CRM admin and acted on immediately
|
|
401
|
+
- no filler paragraphs — every sentence either presents a decision, explains a constraint, or specifies an action
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# API Query Plan — [CLIENT NAME]
|
|
2
|
+
|
|
3
|
+
**Date:** YYYY-MM-DD
|
|
4
|
+
**Kit:** `growthub-twenty-crm-v1`
|
|
5
|
+
**Mode:** `[cloud / self-hosted / local-fork / agent-only]`
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## QUERY INVENTORY
|
|
10
|
+
|
|
11
|
+
| # | Name | Type | Object | Use case |
|
|
12
|
+
|---|---|---|---|---|
|
|
13
|
+
| 1 | [Name] | [GraphQL / REST] | [object] | [use case] |
|
|
14
|
+
| 2 | [Name] | [GraphQL / REST] | [object] | [use case] |
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## QUERY 1 — [NAME]
|
|
19
|
+
|
|
20
|
+
**Use case:** [What this query supports — e.g. "Weekly pipeline report: all open Opportunities by stage"]
|
|
21
|
+
**Consumer:** [dashboard / export script / integration / reporting tool]
|
|
22
|
+
**Type:** `GraphQL`
|
|
23
|
+
|
|
24
|
+
### Query
|
|
25
|
+
|
|
26
|
+
```graphql
|
|
27
|
+
query GetOpenOpportunitiesByStage($filter: OpportunityFilterInput) {
|
|
28
|
+
opportunities(filter: $filter, orderBy: { createdAt: DescNullsLast }) {
|
|
29
|
+
edges {
|
|
30
|
+
node {
|
|
31
|
+
id
|
|
32
|
+
name
|
|
33
|
+
stage
|
|
34
|
+
amount { amountMicros currencyCode }
|
|
35
|
+
closeDate
|
|
36
|
+
pointOfContact {
|
|
37
|
+
name { firstName lastName }
|
|
38
|
+
emails { primaryEmail }
|
|
39
|
+
}
|
|
40
|
+
company { name domain }
|
|
41
|
+
createdAt
|
|
42
|
+
updatedAt
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
totalCount
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**Variables:**
|
|
51
|
+
|
|
52
|
+
```json
|
|
53
|
+
{
|
|
54
|
+
"filter": {
|
|
55
|
+
"stage": { "in": ["LEAD", "QUALIFIED", "DEMO", "PROPOSAL"] }
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**Expected response structure:**
|
|
61
|
+
|
|
62
|
+
```json
|
|
63
|
+
{
|
|
64
|
+
"data": {
|
|
65
|
+
"opportunities": {
|
|
66
|
+
"edges": [
|
|
67
|
+
{
|
|
68
|
+
"node": {
|
|
69
|
+
"id": "...",
|
|
70
|
+
"name": "...",
|
|
71
|
+
"stage": "QUALIFIED",
|
|
72
|
+
"amount": { "amountMicros": 10000000, "currencyCode": "USD" }
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
],
|
|
76
|
+
"totalCount": 42
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**Authentication:**
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
Authorization: Bearer <TWENTY_API_TOKEN>
|
|
86
|
+
Content-Type: application/json
|
|
87
|
+
POST <TWENTY_API_URL>/graphql
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## QUERY 2 — [NAME]
|
|
93
|
+
|
|
94
|
+
**Use case:** [description]
|
|
95
|
+
**Consumer:** [consumer]
|
|
96
|
+
**Type:** `[GraphQL / REST]`
|
|
97
|
+
|
|
98
|
+
### REST Query (if applicable)
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
GET <TWENTY_API_URL>/api/objects/people?filter=emails.primaryEmail[eq]=jane@example.com
|
|
102
|
+
Authorization: Bearer <TWENTY_API_TOKEN>
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### GraphQL Query (if applicable)
|
|
106
|
+
|
|
107
|
+
```graphql
|
|
108
|
+
query {
|
|
109
|
+
# [query here]
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## QUERY 3 — MUTATION: CREATE PERSON
|
|
116
|
+
|
|
117
|
+
**Use case:** [e.g. "Create a new Person record from enrichment pipeline"]
|
|
118
|
+
**Type:** `GraphQL mutation`
|
|
119
|
+
|
|
120
|
+
```graphql
|
|
121
|
+
mutation CreatePerson($data: PersonCreateInput!) {
|
|
122
|
+
createPerson(data: $data) {
|
|
123
|
+
id
|
|
124
|
+
name { firstName lastName }
|
|
125
|
+
emails { primaryEmail }
|
|
126
|
+
createdAt
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
**Variables:**
|
|
132
|
+
|
|
133
|
+
```json
|
|
134
|
+
{
|
|
135
|
+
"data": {
|
|
136
|
+
"name": { "firstName": "Jane", "lastName": "Doe" },
|
|
137
|
+
"emails": { "primaryEmail": "jane@example.com" },
|
|
138
|
+
"position": "Head of Growth",
|
|
139
|
+
"linkedInLink": { "url": "https://linkedin.com/in/janedoe", "label": "LinkedIn" }
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## QUERY 4 — MUTATION: UPDATE OPPORTUNITY STAGE
|
|
147
|
+
|
|
148
|
+
**Use case:** [e.g. "Automation updates stage when deal is marked as won"]
|
|
149
|
+
**Type:** `GraphQL mutation`
|
|
150
|
+
|
|
151
|
+
```graphql
|
|
152
|
+
mutation UpdateOpportunityStage($id: ID!, $stage: String!) {
|
|
153
|
+
updateOpportunity(id: $id, data: { stage: $stage }) {
|
|
154
|
+
id
|
|
155
|
+
stage
|
|
156
|
+
updatedAt
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
**Variables:**
|
|
162
|
+
|
|
163
|
+
```json
|
|
164
|
+
{
|
|
165
|
+
"id": "<opportunity-id>",
|
|
166
|
+
"stage": "CLOSED_WON"
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## RATE LIMITS AND CONSTRAINTS
|
|
173
|
+
|
|
174
|
+
| Constraint | Value | Notes |
|
|
175
|
+
|---|---|---|
|
|
176
|
+
| GraphQL endpoint | `<TWENTY_API_URL>/graphql` | All mutations and queries |
|
|
177
|
+
| REST endpoint | `<TWENTY_API_URL>/api/objects/<object>` | CRUD only |
|
|
178
|
+
| Auth | Bearer token | Workspace-scoped |
|
|
179
|
+
| [Rate limit if known] | [value] | [notes] |
|