Compare commits
26
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dd265a5f0f | ||
|
|
8bbda86eb6 | ||
|
|
6f6a9a55fb | ||
|
|
882e9fd231 | ||
|
|
ae122f4bb1 | ||
|
|
c433b2b73f | ||
|
|
309fd7a526 | ||
|
|
5ab3eeb830 | ||
|
|
75bb3a904d | ||
|
|
82a1179e23 | ||
|
|
662de17644 | ||
|
|
1993614637 | ||
|
|
a3aae5c857 | ||
|
|
22a203680e | ||
|
|
36bcc71f3d | ||
|
|
06bdb5ad6a | ||
|
|
a9696705c1 | ||
|
|
0acc08c333 | ||
|
|
c2a79fc0c2 | ||
|
|
5b28e59ca7 | ||
|
|
66d93c4d28 | ||
|
|
2c69102f15 | ||
|
|
fea47aa9f8 | ||
|
|
73268535dc | ||
|
|
02bd71052b | ||
|
|
faee5ee63d |
@@ -65,7 +65,7 @@ jobs:
|
||||
key: ${{ env.STORYBOOK_BUILD_CACHE_KEY_FOR_SAVE_ACTION }}
|
||||
front-sb-test:
|
||||
timeout-minutes: 30
|
||||
runs-on: ubuntu-latest-4-cores
|
||||
runs-on: ubuntu-latest
|
||||
needs: front-sb-build
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
||||
@@ -51,7 +51,7 @@ jobs:
|
||||
tasks: ${{ matrix.task }}
|
||||
sdk-e2e-test:
|
||||
timeout-minutes: 30
|
||||
runs-on: ubuntu-latest-4-cores
|
||||
runs-on: ubuntu-latest
|
||||
needs: [changed-files-check, sdk-test]
|
||||
if: needs.changed-files-check.outputs.any_changed == 'true'
|
||||
services:
|
||||
|
||||
@@ -25,6 +25,7 @@ jobs:
|
||||
packages/twenty-server/**
|
||||
packages/twenty-front/src/generated/**
|
||||
packages/twenty-front/src/generated-metadata/**
|
||||
packages/twenty-sdk/src/clients/generated/metadata/**
|
||||
packages/twenty-emails/**
|
||||
packages/twenty-shared/**
|
||||
|
||||
@@ -32,7 +33,7 @@ jobs:
|
||||
needs: changed-files-check
|
||||
if: needs.changed-files-check.outputs.any_changed == 'true'
|
||||
timeout-minutes: 30
|
||||
runs-on: ubuntu-latest-4-cores
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Fetch custom Github Actions and base branch history
|
||||
uses: actions/checkout@v4
|
||||
@@ -60,7 +61,7 @@ jobs:
|
||||
needs: changed-files-check
|
||||
if: needs.changed-files-check.outputs.any_changed == 'true'
|
||||
timeout-minutes: 30
|
||||
runs-on: ubuntu-latest-4-cores
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Fetch custom Github Actions and base branch history
|
||||
uses: actions/checkout@v4
|
||||
@@ -79,7 +80,7 @@ jobs:
|
||||
server-validation:
|
||||
needs: server-build
|
||||
timeout-minutes: 30
|
||||
runs-on: ubuntu-latest-4-cores
|
||||
runs-on: ubuntu-latest
|
||||
services:
|
||||
postgres:
|
||||
image: twentycrm/twenty-postgres-spilo
|
||||
@@ -158,8 +159,10 @@ jobs:
|
||||
|
||||
exit 1
|
||||
fi
|
||||
- name: GraphQL / Check for Pending Generation
|
||||
- name: Check for Pending Code Generation
|
||||
run: |
|
||||
HAS_ERRORS=false
|
||||
|
||||
npx nx run twenty-front:graphql:generate
|
||||
npx nx run twenty-front:graphql:generate --configuration=metadata
|
||||
|
||||
@@ -171,15 +174,29 @@ jobs:
|
||||
git diff -- packages/twenty-front/src/generated packages/twenty-front/src/generated-metadata
|
||||
echo "==================================================="
|
||||
echo ""
|
||||
echo "Please run 'npx nx run twenty-front:graphql:generate' and 'npx nx run twenty-front:graphql:generate --configuration=metadata' and commit the changes."
|
||||
echo ""
|
||||
exit 1
|
||||
HAS_ERRORS=true
|
||||
fi
|
||||
|
||||
npx nx run twenty-sdk:generate-metadata-client
|
||||
|
||||
if ! git diff --quiet -- packages/twenty-sdk/src/clients/generated/metadata; then
|
||||
echo "::error::SDK metadata client changes detected. Please run 'npx nx run twenty-sdk:generate-metadata-client' and commit the changes."
|
||||
echo ""
|
||||
echo "The following SDK metadata client changes were detected:"
|
||||
echo "==================================================="
|
||||
git diff -- packages/twenty-sdk/src/clients/generated/metadata
|
||||
echo "==================================================="
|
||||
echo ""
|
||||
HAS_ERRORS=true
|
||||
fi
|
||||
|
||||
if [ "$HAS_ERRORS" = true ]; then
|
||||
exit 1
|
||||
fi
|
||||
server-test:
|
||||
needs: server-build
|
||||
timeout-minutes: 30
|
||||
runs-on: ubuntu-latest-4-cores
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Fetch custom Github Actions and base branch history
|
||||
uses: actions/checkout@v4
|
||||
@@ -201,7 +218,7 @@ jobs:
|
||||
|
||||
server-integration-test:
|
||||
timeout-minutes: 30
|
||||
runs-on: ubuntu-latest-4-cores
|
||||
runs-on: ubuntu-latest
|
||||
needs: server-build
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
needs: changed-files-check
|
||||
if: needs.changed-files-check.outputs.any_changed == 'true'
|
||||
timeout-minutes: 30
|
||||
runs-on: ubuntu-latest-4-cores
|
||||
runs-on: ubuntu-latest
|
||||
services:
|
||||
postgres:
|
||||
image: twentycrm/twenty-postgres-spilo
|
||||
|
||||
@@ -43,7 +43,7 @@ yarn twenty auth:login
|
||||
yarn twenty entity:add
|
||||
|
||||
# Start dev mode: watches, builds, and syncs local changes to your workspace
|
||||
# (also auto-generates typed API clients — CoreApiClient and MetadataApiClient — in node_modules/twenty-sdk/generated)
|
||||
# (also auto-generates typed CoreApiClient — MetadataApiClient ships pre-built with the SDK — both available via `twenty-sdk/clients`)
|
||||
yarn twenty app:dev
|
||||
|
||||
# Watch your application's function logs
|
||||
@@ -107,7 +107,7 @@ npx create-twenty-app@latest my-app -m
|
||||
- Use `yarn twenty auth:login` to authenticate with your Twenty workspace.
|
||||
- Explore the generated project and add your first entity with `yarn twenty entity:add` (logic functions, front components, objects, roles, views, navigation menu items, skills).
|
||||
- Use `yarn twenty app:dev` while you iterate — it watches, builds, and syncs changes to your workspace in real time.
|
||||
- Two typed API clients are auto‑generated by `yarn twenty app:dev` and stored in `node_modules/twenty-sdk/generated`: `CoreApiClient` (for workspace data via `/graphql`) and `MetadataApiClient` (for workspace configuration and file uploads via `/metadata`).
|
||||
- `CoreApiClient` (for workspace data via `/graphql`) is auto-generated by `yarn twenty app:dev`. `MetadataApiClient` (for workspace configuration and file uploads via `/metadata`) ships pre-built with the SDK. Both are available via `import { CoreApiClient, MetadataApiClient } from 'twenty-sdk/clients'`.
|
||||
|
||||
## Publish your application
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "create-twenty-app",
|
||||
"version": "0.6.4",
|
||||
"version": "0.7.0-canary.0",
|
||||
"description": "Command-line interface to create Twenty application",
|
||||
"main": "dist/cli.cjs",
|
||||
"bin": "dist/cli.cjs",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
## Base documentation
|
||||
|
||||
- Documentation: https://docs.twenty.com/developers/extend/capabilities/apps
|
||||
- Rich app example: https://github.com/twentyhq/twenty/tree/main/packages/twenty-sdk/src/cli/__tests__/apps/rich-app
|
||||
- Rich app example: https://github.com/twentyhq/twenty/tree/main/packages/twenty-sdk/src/app-seeds/rich-app
|
||||
|
||||
## UUID requirement
|
||||
|
||||
|
||||
@@ -113,6 +113,7 @@ export class CreateAppCommand {
|
||||
includeExampleView: false,
|
||||
includeExampleNavigationMenuItem: false,
|
||||
includeExampleSkill: false,
|
||||
includeExampleAgent: false,
|
||||
includeExampleIntegrationTest: false,
|
||||
};
|
||||
}
|
||||
@@ -126,6 +127,7 @@ export class CreateAppCommand {
|
||||
includeExampleNavigationMenuItem: true,
|
||||
includeExampleSkill: true,
|
||||
includeExampleIntegrationTest: true,
|
||||
includeExampleAgent: true,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -8,5 +8,6 @@ export type ExampleOptions = {
|
||||
includeExampleView: boolean;
|
||||
includeExampleNavigationMenuItem: boolean;
|
||||
includeExampleSkill: boolean;
|
||||
includeExampleAgent: boolean;
|
||||
includeExampleIntegrationTest: boolean;
|
||||
};
|
||||
|
||||
@@ -25,6 +25,7 @@ const ALL_EXAMPLES: ExampleOptions = {
|
||||
includeExampleView: true,
|
||||
includeExampleNavigationMenuItem: true,
|
||||
includeExampleSkill: true,
|
||||
includeExampleAgent: true,
|
||||
includeExampleIntegrationTest: true,
|
||||
};
|
||||
|
||||
@@ -41,6 +42,7 @@ const NO_EXAMPLES: ExampleOptions = {
|
||||
includeExampleObject: false,
|
||||
includeExampleField: false,
|
||||
includeExampleSkill: false,
|
||||
includeExampleAgent: false,
|
||||
includeExampleLogicFunction: false,
|
||||
includeExampleFrontComponent: false,
|
||||
includeExampleView: false,
|
||||
@@ -384,6 +386,12 @@ describe('copyBaseApplicationProject', () => {
|
||||
),
|
||||
).toBe(true);
|
||||
|
||||
expect(
|
||||
await fs.pathExists(
|
||||
join(testAppDirectory, '.github', 'workflows', 'ci.yml'),
|
||||
),
|
||||
).toBe(true);
|
||||
|
||||
// Install functions should always exist
|
||||
expect(
|
||||
await fs.pathExists(
|
||||
@@ -462,6 +470,12 @@ describe('copyBaseApplicationProject', () => {
|
||||
join(srcPath, '__tests__', 'app-install.integration-test.ts'),
|
||||
),
|
||||
).toBe(false);
|
||||
|
||||
expect(
|
||||
await fs.pathExists(
|
||||
join(testAppDirectory, '.github', 'workflows', 'ci.yml'),
|
||||
),
|
||||
).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -476,6 +490,7 @@ describe('copyBaseApplicationProject', () => {
|
||||
includeExampleObject: false,
|
||||
includeExampleField: false,
|
||||
includeExampleSkill: false,
|
||||
includeExampleAgent: false,
|
||||
includeExampleLogicFunction: false,
|
||||
includeExampleFrontComponent: true,
|
||||
includeExampleView: false,
|
||||
@@ -513,6 +528,7 @@ describe('copyBaseApplicationProject', () => {
|
||||
exampleOptions: {
|
||||
includeExampleObject: false,
|
||||
includeExampleSkill: false,
|
||||
includeExampleAgent: false,
|
||||
includeExampleField: false,
|
||||
includeExampleLogicFunction: true,
|
||||
includeExampleFrontComponent: false,
|
||||
|
||||
@@ -50,15 +50,14 @@ describe('scaffoldIntegrationTest', () => {
|
||||
"import { appBuild, appUninstall } from 'twenty-sdk/cli'",
|
||||
);
|
||||
expect(content).toContain(
|
||||
"import { MetadataApiClient } from 'twenty-sdk/generated'",
|
||||
"import { MetadataApiClient } from 'twenty-sdk/clients'",
|
||||
);
|
||||
expect(content).toContain(
|
||||
"import { APPLICATION_UNIVERSAL_IDENTIFIER } from 'src/application-config'",
|
||||
);
|
||||
expect(content).toContain('TWENTY_TEST_API_KEY');
|
||||
expect(content).toContain('assertServerIsReachable');
|
||||
expect(content).toContain('appBuild');
|
||||
expect(content).toContain('appUninstall');
|
||||
expect(content).toContain('new MetadataApiClient()');
|
||||
expect(content).toContain('findManyApplications');
|
||||
expect(content).toContain('APPLICATION_UNIVERSAL_IDENTIFIER');
|
||||
});
|
||||
@@ -84,7 +83,8 @@ describe('scaffoldIntegrationTest', () => {
|
||||
expect(content).toContain('.twenty-sdk-test');
|
||||
expect(content).toContain('config.json');
|
||||
expect(content).toContain('process.env.TWENTY_API_URL');
|
||||
expect(content).toContain('process.env.TWENTY_TEST_API_KEY');
|
||||
expect(content).toContain('process.env.TWENTY_API_KEY');
|
||||
expect(content).toContain('assertServerIsReachable');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -101,7 +101,8 @@ describe('scaffoldIntegrationTest', () => {
|
||||
|
||||
const content = await fs.readFile(vitestConfigPath, 'utf8');
|
||||
|
||||
expect(content).toContain('TWENTY_TEST_API_KEY');
|
||||
expect(content).toContain('TWENTY_API_KEY');
|
||||
expect(content).not.toContain('TWENTY_TEST_API_KEY');
|
||||
expect(content).toContain('TWENTY_API_URL');
|
||||
expect(content).toContain('setup-test.ts');
|
||||
expect(content).toContain('tsconfig.spec.json');
|
||||
@@ -109,6 +110,37 @@ describe('scaffoldIntegrationTest', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('github workflow', () => {
|
||||
it('should create .github/workflows/ci.yml with correct structure', async () => {
|
||||
await scaffoldIntegrationTest({
|
||||
appDirectory: testAppDirectory,
|
||||
sourceFolderPath,
|
||||
});
|
||||
|
||||
const workflowPath = join(
|
||||
testAppDirectory,
|
||||
'.github',
|
||||
'workflows',
|
||||
'ci.yml',
|
||||
);
|
||||
|
||||
expect(await fs.pathExists(workflowPath)).toBe(true);
|
||||
|
||||
const content = await fs.readFile(workflowPath, 'utf8');
|
||||
|
||||
expect(content).toContain('name: CI');
|
||||
expect(content).toContain('TWENTY_VERSION: latest');
|
||||
expect(content).toContain('twenty-version: ${{ env.TWENTY_VERSION }}');
|
||||
expect(content).toContain('actions/checkout@v4');
|
||||
expect(content).toContain('spawn-twenty-docker-image@main');
|
||||
expect(content).toContain('actions/setup-node@v4');
|
||||
expect(content).toContain('yarn install --immutable');
|
||||
expect(content).toContain('yarn test');
|
||||
expect(content).toContain('TWENTY_API_URL');
|
||||
expect(content).toContain('TWENTY_TEST_API_KEY');
|
||||
});
|
||||
});
|
||||
|
||||
describe('tsconfig.spec.json', () => {
|
||||
it('should create tsconfig.spec.json extending the base tsconfig', async () => {
|
||||
await scaffoldIntegrationTest({
|
||||
|
||||
@@ -103,6 +103,14 @@ export const copyBaseApplicationProject = async ({
|
||||
});
|
||||
}
|
||||
|
||||
if (exampleOptions.includeExampleAgent) {
|
||||
await createExampleAgent({
|
||||
appDirectory: sourceFolderPath,
|
||||
fileFolder: 'agents',
|
||||
fileName: 'example-agent.ts',
|
||||
});
|
||||
}
|
||||
|
||||
if (exampleOptions.includeExampleIntegrationTest) {
|
||||
await scaffoldIntegrationTest({
|
||||
appDirectory,
|
||||
@@ -519,6 +527,36 @@ export default defineSkill({
|
||||
await fs.writeFile(join(appDirectory, fileFolder ?? '', fileName), content);
|
||||
};
|
||||
|
||||
const createExampleAgent = async ({
|
||||
appDirectory,
|
||||
fileFolder,
|
||||
fileName,
|
||||
}: {
|
||||
appDirectory: string;
|
||||
fileFolder?: string;
|
||||
fileName: string;
|
||||
}) => {
|
||||
const universalIdentifier = v4();
|
||||
|
||||
const content = `import { defineAgent } from 'twenty-sdk';
|
||||
|
||||
export const EXAMPLE_AGENT_UNIVERSAL_IDENTIFIER =
|
||||
'${universalIdentifier}';
|
||||
|
||||
export default defineAgent({
|
||||
universalIdentifier: EXAMPLE_AGENT_UNIVERSAL_IDENTIFIER,
|
||||
name: 'example-agent',
|
||||
label: 'Example Agent',
|
||||
description: 'A sample AI agent for your application',
|
||||
icon: 'IconRobot',
|
||||
prompt: 'You are a helpful assistant. Help users with their questions and tasks.',
|
||||
});
|
||||
`;
|
||||
|
||||
await fs.ensureDir(join(appDirectory, fileFolder ?? ''));
|
||||
await fs.writeFile(join(appDirectory, fileFolder ?? '', fileName), content);
|
||||
};
|
||||
|
||||
const createApplicationConfig = async ({
|
||||
displayName,
|
||||
description,
|
||||
|
||||
@@ -25,6 +25,7 @@ export const scaffoldIntegrationTest = async ({
|
||||
|
||||
await createVitestConfig(appDirectory);
|
||||
await createTsconfigSpec(appDirectory);
|
||||
await createGithubWorkflow(appDirectory);
|
||||
};
|
||||
|
||||
const createVitestConfig = async (appDirectory: string) => {
|
||||
@@ -45,7 +46,7 @@ export default defineConfig({
|
||||
setupFiles: ['src/__tests__/setup-test.ts'],
|
||||
env: {
|
||||
TWENTY_API_URL: 'http://localhost:3000',
|
||||
TWENTY_TEST_API_KEY:
|
||||
TWENTY_API_KEY:
|
||||
'${SEED_API_KEY}',
|
||||
},
|
||||
},
|
||||
@@ -93,16 +94,36 @@ import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import { beforeAll } from 'vitest';
|
||||
|
||||
const TWENTY_API_URL = process.env.TWENTY_API_URL ?? 'http://localhost:3000';
|
||||
const TEST_CONFIG_DIR = path.join(os.tmpdir(), '.twenty-sdk-test');
|
||||
|
||||
beforeAll(() => {
|
||||
const assertServerIsReachable = async () => {
|
||||
let response: Response;
|
||||
|
||||
try {
|
||||
response = await fetch(\`\${TWENTY_API_URL}/healthz\`);
|
||||
} catch {
|
||||
throw new Error(
|
||||
\`Twenty server is not reachable at \${TWENTY_API_URL}. \` +
|
||||
'Make sure the server is running before executing integration tests.',
|
||||
);
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(\`Server at \${TWENTY_API_URL} returned \${response.status}\`);
|
||||
}
|
||||
};
|
||||
|
||||
beforeAll(async () => {
|
||||
await assertServerIsReachable();
|
||||
|
||||
fs.mkdirSync(TEST_CONFIG_DIR, { recursive: true });
|
||||
|
||||
const configFile = {
|
||||
profiles: {
|
||||
default: {
|
||||
apiUrl: process.env.TWENTY_API_URL,
|
||||
apiKey: process.env.TWENTY_TEST_API_KEY,
|
||||
apiKey: process.env.TWENTY_API_KEY,
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -129,35 +150,15 @@ const createIntegrationTest = async ({
|
||||
}) => {
|
||||
const content = `import { APPLICATION_UNIVERSAL_IDENTIFIER } from 'src/application-config';
|
||||
import { appBuild, appUninstall } from 'twenty-sdk/cli';
|
||||
import { MetadataApiClient } from 'twenty-sdk/generated';
|
||||
import { MetadataApiClient } from 'twenty-sdk/clients';
|
||||
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
|
||||
|
||||
const APP_PATH = process.cwd();
|
||||
const TWENTY_API_URL = process.env.TWENTY_API_URL ?? 'http://localhost:3000';
|
||||
|
||||
const assertServerIsReachable = async () => {
|
||||
let response: Response;
|
||||
|
||||
try {
|
||||
response = await fetch(\`\${TWENTY_API_URL}/healthz\`);
|
||||
} catch {
|
||||
throw new Error(
|
||||
\`Twenty server is not reachable at \${TWENTY_API_URL}. \` +
|
||||
'Make sure the server is running before executing integration tests.',
|
||||
);
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(\`Server at \${TWENTY_API_URL} returned \${response.status}\`);
|
||||
}
|
||||
};
|
||||
|
||||
describe('App installation', () => {
|
||||
let appInstalled = false;
|
||||
|
||||
beforeAll(async () => {
|
||||
await assertServerIsReachable();
|
||||
|
||||
const buildResult = await appBuild({
|
||||
appPath: APP_PATH,
|
||||
onProgress: (message: string) => console.log(\`[build] \${message}\`),
|
||||
@@ -165,7 +166,7 @@ describe('App installation', () => {
|
||||
|
||||
if (!buildResult.success) {
|
||||
throw new Error(
|
||||
\`App build failed: \${buildResult.error?.message ?? 'Unknown error'}\`,
|
||||
\`Build failed: \${buildResult.error?.message ?? 'Unknown error'}\`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -187,20 +188,7 @@ describe('App installation', () => {
|
||||
});
|
||||
|
||||
it('should find the installed app in the applications list', async () => {
|
||||
const apiKey = process.env.TWENTY_TEST_API_KEY;
|
||||
|
||||
if (!apiKey) {
|
||||
throw new Error(
|
||||
'No API key found. Set TWENTY_TEST_API_KEY in your vitest config env.',
|
||||
);
|
||||
}
|
||||
|
||||
const metadataClient = new MetadataApiClient({
|
||||
url: \`\${TWENTY_API_URL}/metadata\`,
|
||||
headers: {
|
||||
Authorization: \`Bearer \${apiKey}\`,
|
||||
},
|
||||
});
|
||||
const metadataClient = new MetadataApiClient();
|
||||
|
||||
const result = await metadataClient.query({
|
||||
findManyApplications: {
|
||||
@@ -224,3 +212,56 @@ describe('App installation', () => {
|
||||
await fs.ensureDir(join(appDirectory, fileFolder ?? ''));
|
||||
await fs.writeFile(join(appDirectory, fileFolder ?? '', fileName), content);
|
||||
};
|
||||
|
||||
const DEFAULT_TWENTY_VERSION = 'latest';
|
||||
|
||||
const createGithubWorkflow = async (appDirectory: string) => {
|
||||
const content = `name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request: {}
|
||||
|
||||
env:
|
||||
TWENTY_VERSION: ${DEFAULT_TWENTY_VERSION}
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Spawn Twenty instance
|
||||
id: twenty
|
||||
uses: twentyhq/twenty/.github/actions/spawn-twenty-docker-image@main
|
||||
with:
|
||||
twenty-version: \${{ env.TWENTY_VERSION }}
|
||||
github-token: \${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Enable Corepack
|
||||
run: corepack enable
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'yarn'
|
||||
|
||||
- name: Install dependencies
|
||||
run: yarn install --immutable
|
||||
|
||||
- name: Run integration tests
|
||||
run: yarn test
|
||||
env:
|
||||
TWENTY_API_URL: \${{ steps.twenty.outputs.server-url }}
|
||||
TWENTY_TEST_API_KEY: \${{ steps.twenty.outputs.access-token }}
|
||||
`;
|
||||
|
||||
const workflowDir = join(appDirectory, '.github', 'workflows');
|
||||
|
||||
await fs.ensureDir(workflowDir);
|
||||
await fs.writeFile(join(workflowDir, 'ci.yml'), content);
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
## Base documentation
|
||||
|
||||
- Documentation: https://docs.twenty.com/developers/extend/capabilities/apps
|
||||
- Rich app example: https://github.com/twentyhq/twenty/tree/main/packages/twenty-sdk/src/cli/__tests__/apps/rich-app
|
||||
- Rich app example: https://github.com/twentyhq/twenty/tree/main/packages/twenty-sdk/src/app-seeds/rich-app
|
||||
|
||||
## UUID requirement
|
||||
- All generated UUIDs must be valid UUID v4.
|
||||
|
||||
@@ -1,38 +1,19 @@
|
||||
{
|
||||
"$schema": "./node_modules/oxlint/configuration_schema.json",
|
||||
"plugins": ["typescript", "import", "unicorn"],
|
||||
"plugins": ["typescript"],
|
||||
"categories": {
|
||||
"correctness": "off"
|
||||
},
|
||||
"ignorePatterns": ["node_modules"],
|
||||
"ignorePatterns": ["node_modules", "dist"],
|
||||
"rules": {
|
||||
"func-style": ["error", "declaration", { "allowArrowFunctions": true }],
|
||||
"no-console": ["warn", { "allow": ["group", "groupCollapsed", "groupEnd"] }],
|
||||
"no-control-regex": "off",
|
||||
"no-debugger": "error",
|
||||
"no-duplicate-imports": "error",
|
||||
"no-undef": "off",
|
||||
"no-unused-vars": "off",
|
||||
"no-redeclare": "off",
|
||||
"import/no-duplicates": "error",
|
||||
"typescript/no-redeclare": "error",
|
||||
"typescript/ban-ts-comment": "error",
|
||||
"typescript/consistent-type-imports": ["error", {
|
||||
"prefer": "type-imports",
|
||||
"fixStyle": "inline-type-imports"
|
||||
}],
|
||||
"typescript/explicit-function-return-type": "off",
|
||||
"typescript/explicit-module-boundary-types": "off",
|
||||
"typescript/no-empty-object-type": ["error", {
|
||||
"allowInterfaces": "with-single-extends"
|
||||
}],
|
||||
"typescript/no-empty-function": "off",
|
||||
"typescript/no-explicit-any": "off",
|
||||
"typescript/no-unused-vars": ["warn", {
|
||||
"vars": "all",
|
||||
"varsIgnorePattern": "^_",
|
||||
"args": "after-used",
|
||||
"argsIgnorePattern": "^_"
|
||||
}]
|
||||
|
||||
"typescript/no-unused-vars": [
|
||||
"warn",
|
||||
{
|
||||
"argsIgnorePattern": "^_"
|
||||
}
|
||||
],
|
||||
"typescript/no-explicit-any": "off"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
## Base documentation
|
||||
|
||||
- Documentation: https://docs.twenty.com/developers/extend/capabilities/apps
|
||||
- Rich app example: https://github.com/twentyhq/twenty/tree/main/packages/twenty-sdk/src/cli/__tests__/apps/rich-app
|
||||
- Rich app example: https://github.com/twentyhq/twenty/tree/main/packages/twenty-sdk/src/app-seeds/rich-app
|
||||
|
||||
## UUID requirement
|
||||
- All generated UUIDs must be valid UUID v4.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@twentyhq/hello-world",
|
||||
"version": "0.2.2",
|
||||
"name": "hello-world",
|
||||
"version": "0.1.0",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^24.5.0",
|
||||
@@ -20,7 +20,7 @@
|
||||
"@types/react": "^18.2.0",
|
||||
"oxlint": "^0.16.0",
|
||||
"react": "^18.2.0",
|
||||
"twenty-sdk": "0.6.3",
|
||||
"twenty-sdk": "0.6.4",
|
||||
"typescript": "^5.9.3",
|
||||
"vite-tsconfig-paths": "^4.2.1",
|
||||
"vitest": "^3.1.1"
|
||||
|
||||
@@ -1,34 +1,14 @@
|
||||
import { APPLICATION_UNIVERSAL_IDENTIFIER } from 'src/application-config';
|
||||
import { appBuild, appUninstall } from 'twenty-sdk/cli';
|
||||
import { MetadataApiClient } from 'twenty-sdk/generated';
|
||||
import { MetadataApiClient } from 'twenty-sdk/clients';
|
||||
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
|
||||
|
||||
const APP_PATH = process.cwd();
|
||||
const TWENTY_API_URL = process.env.TWENTY_API_URL ?? 'http://localhost:3000';
|
||||
|
||||
const assertServerIsReachable = async () => {
|
||||
let response: Response;
|
||||
|
||||
try {
|
||||
response = await fetch(`${TWENTY_API_URL}/healthz`);
|
||||
} catch {
|
||||
throw new Error(
|
||||
`Twenty server is not reachable at ${TWENTY_API_URL}. ` +
|
||||
'Make sure the server is running before executing integration tests.',
|
||||
);
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Server at ${TWENTY_API_URL} returned ${response.status}`);
|
||||
}
|
||||
};
|
||||
|
||||
describe('App installation', () => {
|
||||
let appInstalled = false;
|
||||
|
||||
beforeAll(async () => {
|
||||
await assertServerIsReachable();
|
||||
|
||||
const buildResult = await appBuild({
|
||||
appPath: APP_PATH,
|
||||
onProgress: (message: string) => console.log(`[build] ${message}`),
|
||||
@@ -36,7 +16,7 @@ describe('App installation', () => {
|
||||
|
||||
if (!buildResult.success) {
|
||||
throw new Error(
|
||||
`App build failed: ${buildResult.error?.message ?? 'Unknown error'}`,
|
||||
`Build failed: ${buildResult.error?.message ?? 'Unknown error'}`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -58,20 +38,7 @@ describe('App installation', () => {
|
||||
});
|
||||
|
||||
it('should find the installed app in the applications list', async () => {
|
||||
const apiKey = process.env.TWENTY_TEST_API_KEY;
|
||||
|
||||
if (!apiKey) {
|
||||
throw new Error(
|
||||
'No API key found. Set TWENTY_TEST_API_KEY in your vitest config env.',
|
||||
);
|
||||
}
|
||||
|
||||
const metadataClient = new MetadataApiClient({
|
||||
url: `${TWENTY_API_URL}/metadata`,
|
||||
headers: {
|
||||
Authorization: `Bearer ${apiKey}`,
|
||||
},
|
||||
});
|
||||
const metadataClient = new MetadataApiClient();
|
||||
|
||||
const result = await metadataClient.query({
|
||||
findManyApplications: {
|
||||
|
||||
@@ -3,16 +3,36 @@ import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import { beforeAll } from 'vitest';
|
||||
|
||||
const TWENTY_API_URL = process.env.TWENTY_API_URL ?? 'http://localhost:3000';
|
||||
const TEST_CONFIG_DIR = path.join(os.tmpdir(), '.twenty-sdk-test');
|
||||
|
||||
beforeAll(() => {
|
||||
const assertServerIsReachable = async () => {
|
||||
let response: Response;
|
||||
|
||||
try {
|
||||
response = await fetch(`${TWENTY_API_URL}/healthz`);
|
||||
} catch {
|
||||
throw new Error(
|
||||
`Twenty server is not reachable at ${TWENTY_API_URL}. ` +
|
||||
'Make sure the server is running before executing integration tests.',
|
||||
);
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Server at ${TWENTY_API_URL} returned ${response.status}`);
|
||||
}
|
||||
};
|
||||
|
||||
beforeAll(async () => {
|
||||
await assertServerIsReachable();
|
||||
|
||||
fs.mkdirSync(TEST_CONFIG_DIR, { recursive: true });
|
||||
|
||||
const configFile = {
|
||||
profiles: {
|
||||
default: {
|
||||
apiUrl: process.env.TWENTY_API_URL,
|
||||
apiKey: process.env.TWENTY_TEST_API_KEY,
|
||||
apiKey: process.env.TWENTY_API_KEY,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -2,7 +2,7 @@ import { defineApplication } from 'twenty-sdk';
|
||||
import { DEFAULT_ROLE_UNIVERSAL_IDENTIFIER } from 'src/roles/default-role';
|
||||
|
||||
export const APPLICATION_UNIVERSAL_IDENTIFIER =
|
||||
'1badae7c-8a42-4dea-b4b8-3c56e77c2f9a';
|
||||
'6563e091-9f5b-4026-a3ea-7e3b3d09e218';
|
||||
|
||||
export default defineApplication({
|
||||
universalIdentifier: APPLICATION_UNIVERSAL_IDENTIFIER,
|
||||
|
||||
@@ -3,7 +3,7 @@ import { EXAMPLE_OBJECT_UNIVERSAL_IDENTIFIER } from 'src/objects/example-object'
|
||||
|
||||
export default defineField({
|
||||
objectUniversalIdentifier: EXAMPLE_OBJECT_UNIVERSAL_IDENTIFIER,
|
||||
universalIdentifier: '2c503a0d-36c9-49ec-b82f-4fafe0eb6f47',
|
||||
universalIdentifier: '770d32c2-cf12-4ab2-b66d-73f92dc239b5',
|
||||
type: FieldType.NUMBER,
|
||||
name: 'priority',
|
||||
label: 'Priority',
|
||||
|
||||
@@ -10,7 +10,7 @@ export const HelloWorld = () => {
|
||||
};
|
||||
|
||||
export default defineFrontComponent({
|
||||
universalIdentifier: '26c17445-fbfb-4b34-99d6-f461e734ca97',
|
||||
universalIdentifier: 'd371f098-5b2c-42f0-898d-94459f1ee337',
|
||||
name: 'hello-world-front-component',
|
||||
description: 'A sample front component',
|
||||
component: HelloWorld,
|
||||
|
||||
@@ -5,7 +5,7 @@ const handler = async (): Promise<{ message: string }> => {
|
||||
};
|
||||
|
||||
export default defineLogicFunction({
|
||||
universalIdentifier: '4f0b7137-1399-4e50-ac00-3c3bb2555c38',
|
||||
universalIdentifier: '2baa26eb-9aaf-4856-a4f4-30d6fd6480ee',
|
||||
name: 'hello-world-logic-function',
|
||||
description: 'A simple logic function',
|
||||
timeoutSeconds: 5,
|
||||
|
||||
@@ -5,7 +5,7 @@ const handler = async (payload: InstallLogicFunctionPayload): Promise<void> => {
|
||||
};
|
||||
|
||||
export default definePostInstallLogicFunction({
|
||||
universalIdentifier: 'c1410017-8536-42aa-a188-4bfc5a1c3dae',
|
||||
universalIdentifier: '7a3f4684-51db-494d-833b-a747a3b90507',
|
||||
name: 'post-install',
|
||||
description: 'Runs after installation to set up the application.',
|
||||
timeoutSeconds: 300,
|
||||
|
||||
@@ -5,7 +5,7 @@ const handler = async (payload: InstallLogicFunctionPayload): Promise<void> => {
|
||||
};
|
||||
|
||||
export default definePreInstallLogicFunction({
|
||||
universalIdentifier: '68d005d4-1110-4fa0-8227-71e06d6b9f30',
|
||||
universalIdentifier: '1272ffdb-8e2f-492c-ab37-66c2b97e9c23',
|
||||
name: 'pre-install',
|
||||
description: 'Runs before installation to prepare the application.',
|
||||
timeoutSeconds: 300,
|
||||
|
||||
+4
-7
@@ -1,14 +1,11 @@
|
||||
import { defineNavigationMenuItem } from 'twenty-sdk';
|
||||
import { EXAMPLE_VIEW_UNIVERSAL_IDENTIFIER } from 'src/views/example-view';
|
||||
|
||||
export default defineNavigationMenuItem({
|
||||
universalIdentifier: '574a895f-1511-4b38-9d28-d6b8436738ff',
|
||||
universalIdentifier: '10f90627-e9c2-44b7-9742-bed77e3d1b17',
|
||||
name: 'example-navigation-menu-item',
|
||||
icon: 'IconList',
|
||||
color: 'blue',
|
||||
position: 0,
|
||||
// Link to a view:
|
||||
// viewUniversalIdentifier: '...',
|
||||
// Or link to an object:
|
||||
// targetObjectUniversalIdentifier: '...',
|
||||
// Or link to an external URL:
|
||||
// link: 'https://example.com',
|
||||
viewUniversalIdentifier: EXAMPLE_VIEW_UNIVERSAL_IDENTIFIER,
|
||||
});
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { defineObject, FieldType } from 'twenty-sdk';
|
||||
|
||||
export const EXAMPLE_OBJECT_UNIVERSAL_IDENTIFIER =
|
||||
'b75cfe84-18ce-47da-812a-53e25ee094af';
|
||||
'dfd43356-39b3-4b55-b4a7-279bec689928';
|
||||
|
||||
export const NAME_FIELD_UNIVERSAL_IDENTIFIER =
|
||||
'6ab9c690-06ce-455e-a2c9-8067a9747f96';
|
||||
'd2d7f6cd-33f6-456f-bf00-17adeca926ba';
|
||||
|
||||
export default defineObject({
|
||||
universalIdentifier: EXAMPLE_OBJECT_UNIVERSAL_IDENTIFIER,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { defineRole } from 'twenty-sdk';
|
||||
|
||||
export const DEFAULT_ROLE_UNIVERSAL_IDENTIFIER =
|
||||
'f14afc30-f2fa-4f70-9b12-903c5f852225';
|
||||
'9238bc7b-d38f-4a1c-9d19-31ab7bc67a2f';
|
||||
|
||||
export default defineRole({
|
||||
universalIdentifier: DEFAULT_ROLE_UNIVERSAL_IDENTIFIER,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { defineSkill } from 'twenty-sdk';
|
||||
|
||||
export const EXAMPLE_SKILL_UNIVERSAL_IDENTIFIER =
|
||||
'4f00dd76-c07b-4d55-a43a-7f17e7f6440a';
|
||||
'd0940029-9d3c-40be-903a-52d65393028f';
|
||||
|
||||
export default defineSkill({
|
||||
universalIdentifier: EXAMPLE_SKILL_UNIVERSAL_IDENTIFIER,
|
||||
|
||||
@@ -1,10 +1,22 @@
|
||||
import { defineView } from 'twenty-sdk';
|
||||
import { EXAMPLE_OBJECT_UNIVERSAL_IDENTIFIER } from 'src/objects/example-object';
|
||||
import { defineView, ViewKey } from 'twenty-sdk';
|
||||
import { EXAMPLE_OBJECT_UNIVERSAL_IDENTIFIER, NAME_FIELD_UNIVERSAL_IDENTIFIER } from 'src/objects/example-object';
|
||||
|
||||
export const EXAMPLE_VIEW_UNIVERSAL_IDENTIFIER = 'e004df40-29f3-47ba-b39d-d3a5c444367a';
|
||||
|
||||
export default defineView({
|
||||
universalIdentifier: 'e574b32c-c058-492a-8a5c-780b844a8735',
|
||||
name: 'example-view',
|
||||
universalIdentifier: EXAMPLE_VIEW_UNIVERSAL_IDENTIFIER,
|
||||
name: 'All example items',
|
||||
objectUniversalIdentifier: EXAMPLE_OBJECT_UNIVERSAL_IDENTIFIER,
|
||||
icon: 'IconList',
|
||||
key: ViewKey.INDEX,
|
||||
position: 0,
|
||||
fields: [
|
||||
{
|
||||
universalIdentifier: '496c40c2-5766-419c-93bf-20fdad3f34bb',
|
||||
fieldMetadataUniversalIdentifier: NAME_FIELD_UNIVERSAL_IDENTIFIER,
|
||||
position: 0,
|
||||
isVisible: true,
|
||||
size: 200,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
@@ -15,7 +15,7 @@ export default defineConfig({
|
||||
setupFiles: ['src/__tests__/setup-test.ts'],
|
||||
env: {
|
||||
TWENTY_API_URL: 'http://localhost:3000',
|
||||
TWENTY_TEST_API_KEY:
|
||||
TWENTY_API_KEY:
|
||||
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIyMDIwMjAyMC1lNmI1LTQ2ODAtOGEzMi1iODIwOTczNzE1NmIiLCJ1c2VySWQiOiIyMDIwMjAyMC1lNmI1LTQ2ODAtOGEzMi1iODIwOTczNzE1NmIiLCJ3b3Jrc3BhY2VJZCI6IjIwMjAyMDIwLTFjMjUtNGQwMi1iZjI1LTZhZWNjZjdlYTQxOSIsIndvcmtzcGFjZU1lbWJlcklkIjoiMjAyMDIwMjAtNDYzZi00MzViLTgyOGMtMTA3ZTAwN2EyNzExIiwidXNlcldvcmtzcGFjZUlkIjoiMjAyMDIwMjAtMWU3Yy00M2Q5LWE1ZGItNjg1YjUwNjlkODE2IiwidHlwZSI6IkFDQ0VTUyIsImF1dGhQcm92aWRlciI6InBhc3N3b3JkIiwiaWF0IjoxNzUxMjgxNzA0LCJleHAiOjIwNjY4NTc3MDR9.HMGqCsVlOAPVUBhKSGlD1X86VoHKt4LIUtET3CGIdik',
|
||||
},
|
||||
},
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
## Base documentation
|
||||
|
||||
- Documentation: https://docs.twenty.com/developers/extend/capabilities/apps
|
||||
- Rich app example: https://github.com/twentyhq/twenty/tree/main/packages/twenty-sdk/src/cli/__tests__/apps/rich-app
|
||||
- Rich app example: https://github.com/twentyhq/twenty/tree/main/packages/twenty-sdk/src/app-seeds/rich-app
|
||||
|
||||
## Common Pitfalls
|
||||
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
---
|
||||
title: APIs
|
||||
description: Query and modify your CRM data programmatically using REST or GraphQL.
|
||||
---
|
||||
|
||||
import { VimeoEmbed } from '/snippets/vimeo-embed.mdx';
|
||||
|
||||
Twenty was built to be developer-friendly, offering powerful APIs that adapt to your custom data model. We provide four distinct API types to meet different integration needs.
|
||||
|
||||
## Developer-First Approach
|
||||
|
||||
Twenty generates APIs specifically for your data model:
|
||||
- **No long IDs required**: Use your object and field names directly in endpoints
|
||||
- **Standard and custom objects treated equally**: Your custom objects get the same API treatment as built-in ones
|
||||
- **Dedicated endpoints**: Each object and field gets its own API endpoint
|
||||
- **Custom documentation**: Generated specifically for your workspace's data model
|
||||
|
||||
<Note>
|
||||
Your personalized API documentation is available under **Settings → API & Webhooks** after creating an API key. Since Twenty generates APIs that match your custom data model, the documentation is unique to your workspace.
|
||||
</Note>
|
||||
|
||||
## The Two API Types
|
||||
|
||||
### Core API
|
||||
Accessed on `/rest/` or `/graphql/`
|
||||
|
||||
Work with your actual **records** (the data):
|
||||
- Create, read, update, delete People, Companies, Opportunities, etc.
|
||||
- Query and filter data
|
||||
- Manage record relationships
|
||||
|
||||
### Metadata API
|
||||
Accessed on `/rest/metadata/` or `/metadata/`
|
||||
|
||||
Manage your **workspace and data model**:
|
||||
- Create, modify, or delete objects and fields
|
||||
- Configure workspace settings
|
||||
- Define relationships between objects
|
||||
|
||||
## REST vs GraphQL
|
||||
|
||||
Both Core and Metadata APIs are available in REST and GraphQL formats:
|
||||
|
||||
| Format | Available Operations |
|
||||
|--------|---------------------|
|
||||
| **REST** | CRUD, batch operations, upserts |
|
||||
| **GraphQL** | Same + **batch upserts**, relationship queries in one call |
|
||||
|
||||
Choose based on your needs — both formats access the same data.
|
||||
|
||||
## API Endpoints
|
||||
|
||||
| Environment | Base URL |
|
||||
|-------------|----------|
|
||||
| **Cloud** | `https://api.twenty.com/` |
|
||||
| **Self-Hosted** | `https://{your-domain}/` |
|
||||
|
||||
## Authentication
|
||||
|
||||
Every API request requires an API key in the header:
|
||||
|
||||
```
|
||||
Authorization: Bearer YOUR_API_KEY
|
||||
```
|
||||
|
||||
### Create an API Key
|
||||
|
||||
1. Go to **Settings → APIs & Webhooks**
|
||||
2. Click **+ Create key**
|
||||
3. Configure:
|
||||
- **Name**: Descriptive name for the key
|
||||
- **Expiration Date**: When the key expires
|
||||
4. Click **Save**
|
||||
5. **Copy immediately** — the key is only shown once
|
||||
|
||||
<VimeoEmbed videoId="928786722" title="Creating API key" />
|
||||
|
||||
<Warning>
|
||||
Your API key grants access to sensitive data. Don't share it with untrusted services. If compromised, disable it immediately and generate a new one.
|
||||
</Warning>
|
||||
|
||||
### Assign a Role to an API Key
|
||||
|
||||
For better security, assign a specific role to limit access:
|
||||
|
||||
1. Go to **Settings → Roles**
|
||||
2. Click on the role to assign
|
||||
3. Open the **Assignment** tab
|
||||
4. Under **API Keys**, click **+ Assign to API key**
|
||||
5. Select the API key
|
||||
|
||||
The key will inherit that role's permissions. See [Permissions](/user-guide/permissions-access/capabilities/permissions) for details.
|
||||
|
||||
### Manage API Keys
|
||||
|
||||
**Regenerate**: Settings → APIs & Webhooks → Click key → **Regenerate**
|
||||
|
||||
**Delete**: Settings → APIs & Webhooks → Click key → **Delete**
|
||||
|
||||
## API Playground
|
||||
|
||||
Test your APIs directly in the browser with our built-in playground — available for both **REST** and **GraphQL**.
|
||||
|
||||
### Access the Playground
|
||||
|
||||
1. Go to **Settings → APIs & Webhooks**
|
||||
2. Create an API key (required)
|
||||
3. Click on **REST API** or **GraphQL API** to open the playground
|
||||
|
||||
### What You Get
|
||||
|
||||
- **Interactive documentation**: Generated for your specific data model
|
||||
- **Live testing**: Execute real API calls against your workspace
|
||||
- **Schema explorer**: Browse available objects, fields, and relationships
|
||||
- **Request builder**: Construct queries with autocomplete
|
||||
|
||||
The playground reflects your custom objects and fields, so documentation is always accurate for your workspace.
|
||||
|
||||
## Batch Operations
|
||||
|
||||
Both REST and GraphQL support batch operations:
|
||||
- **Batch size**: Up to 60 records per request
|
||||
- **Operations**: Create, update, delete multiple records
|
||||
|
||||
**GraphQL-only features:**
|
||||
- **Batch Upsert**: Create or update in one call
|
||||
- Use plural object names (e.g., `CreateCompanies` instead of `CreateCompany`)
|
||||
|
||||
## Rate Limits
|
||||
|
||||
API requests are throttled to ensure platform stability:
|
||||
|
||||
| Limit | Value |
|
||||
|-------|-------|
|
||||
| **Requests** | 100 calls per minute |
|
||||
| **Batch size** | 60 records per call |
|
||||
|
||||
<Tip>
|
||||
Use batch operations to maximize throughput — process up to 60 records in a single API call instead of making individual requests.
|
||||
</Tip>
|
||||
@@ -0,0 +1,677 @@
|
||||
---
|
||||
title: Building Apps
|
||||
description: Define objects, logic functions, front components, and more with the Twenty SDK.
|
||||
---
|
||||
|
||||
<Warning>
|
||||
Apps are currently in alpha testing. The feature is functional but still evolving.
|
||||
</Warning>
|
||||
|
||||
## Use the SDK resources (types & config)
|
||||
|
||||
The twenty-sdk provides typed building blocks and helper functions you use inside your app. Below are the key pieces you'll touch most often.
|
||||
|
||||
### Helper functions
|
||||
|
||||
The SDK provides helper functions for defining your app entities. As described in [Entity detection](/developers/extend/apps/getting-started#entity-detection), you must use `export default define<Entity>({...})` for your entities to be detected:
|
||||
|
||||
| Function | Purpose |
|
||||
|----------|---------|
|
||||
| `defineApplication` | Configure application metadata (required, one per app) |
|
||||
| `defineObject` | Define custom objects with fields |
|
||||
| `defineLogicFunction` | Define logic functions with handlers |
|
||||
| `definePreInstallLogicFunction` | Define a pre-install logic function (one per app) |
|
||||
| `definePostInstallLogicFunction` | Define a post-install logic function (one per app) |
|
||||
| `defineFrontComponent` | Define front components for custom UI |
|
||||
| `defineRole` | Configure role permissions and object access |
|
||||
| `defineField` | Extend existing objects with additional fields |
|
||||
| `defineView` | Define saved views for objects |
|
||||
| `defineNavigationMenuItem` | Define sidebar navigation links |
|
||||
| `defineSkill` | Define AI agent skills |
|
||||
|
||||
These functions validate your configuration at build time and provide IDE autocompletion and type safety.
|
||||
|
||||
### Defining objects
|
||||
|
||||
Custom objects describe both schema and behavior for records in your workspace. Use `defineObject()` to define objects with built-in validation:
|
||||
|
||||
```typescript
|
||||
// src/app/postCard.object.ts
|
||||
import { defineObject, FieldType } from 'twenty-sdk';
|
||||
|
||||
enum PostCardStatus {
|
||||
DRAFT = 'DRAFT',
|
||||
SENT = 'SENT',
|
||||
DELIVERED = 'DELIVERED',
|
||||
RETURNED = 'RETURNED',
|
||||
}
|
||||
|
||||
export default defineObject({
|
||||
universalIdentifier: '54b589ca-eeed-4950-a176-358418b85c05',
|
||||
nameSingular: 'postCard',
|
||||
namePlural: 'postCards',
|
||||
labelSingular: 'Post Card',
|
||||
labelPlural: 'Post Cards',
|
||||
description: 'A post card object',
|
||||
icon: 'IconMail',
|
||||
fields: [
|
||||
{
|
||||
universalIdentifier: '58a0a314-d7ea-4865-9850-7fb84e72f30b',
|
||||
name: 'content',
|
||||
type: FieldType.TEXT,
|
||||
label: 'Content',
|
||||
description: "Postcard's content",
|
||||
icon: 'IconAbc',
|
||||
},
|
||||
{
|
||||
universalIdentifier: 'c6aa31f3-da76-4ac6-889f-475e226009ac',
|
||||
name: 'recipientName',
|
||||
type: FieldType.FULL_NAME,
|
||||
label: 'Recipient name',
|
||||
icon: 'IconUser',
|
||||
},
|
||||
{
|
||||
universalIdentifier: '95045777-a0ad-49ec-98f9-22f9fc0c8266',
|
||||
name: 'recipientAddress',
|
||||
type: FieldType.ADDRESS,
|
||||
label: 'Recipient address',
|
||||
icon: 'IconHome',
|
||||
},
|
||||
{
|
||||
universalIdentifier: '87b675b8-dd8c-4448-b4ca-20e5a2234a1e',
|
||||
name: 'status',
|
||||
type: FieldType.SELECT,
|
||||
label: 'Status',
|
||||
icon: 'IconSend',
|
||||
defaultValue: `'${PostCardStatus.DRAFT}'`,
|
||||
options: [
|
||||
{ value: PostCardStatus.DRAFT, label: 'Draft', position: 0, color: 'gray' },
|
||||
{ value: PostCardStatus.SENT, label: 'Sent', position: 1, color: 'orange' },
|
||||
{ value: PostCardStatus.DELIVERED, label: 'Delivered', position: 2, color: 'green' },
|
||||
{ value: PostCardStatus.RETURNED, label: 'Returned', position: 3, color: 'orange' },
|
||||
],
|
||||
},
|
||||
{
|
||||
universalIdentifier: 'e06abe72-5b44-4e7f-93be-afc185a3c433',
|
||||
name: 'deliveredAt',
|
||||
type: FieldType.DATE_TIME,
|
||||
label: 'Delivered at',
|
||||
icon: 'IconCheck',
|
||||
isNullable: true,
|
||||
defaultValue: null,
|
||||
},
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
Key points:
|
||||
|
||||
- Use `defineObject()` for built-in validation and better IDE support.
|
||||
- The `universalIdentifier` must be unique and stable across deployments.
|
||||
- Each field requires a `name`, `type`, `label`, and its own stable `universalIdentifier`.
|
||||
- The `fields` array is optional — you can define objects without custom fields.
|
||||
- You can scaffold new objects using `yarn twenty entity:add`, which guides you through naming, fields, and relationships.
|
||||
|
||||
<Note>
|
||||
**Base fields are created automatically.** When you define a custom object, Twenty automatically adds standard fields
|
||||
such as `id`, `name`, `createdAt`, `updatedAt`, `createdBy`, `updatedBy` and `deletedAt`.
|
||||
You don't need to define these in your `fields` array — only add your custom fields.
|
||||
You can override default fields by defining a field with the same name in your `fields` array,
|
||||
but this is not recommended.
|
||||
</Note>
|
||||
|
||||
|
||||
### Application config (application-config.ts)
|
||||
|
||||
Every app has a single `application-config.ts` file that describes:
|
||||
|
||||
- **Who the app is**: identifiers, display name, and description.
|
||||
- **How its functions run**: which role they use for permissions.
|
||||
- **(Optional) variables**: key–value pairs exposed to your functions as environment variables.
|
||||
- **(Optional) pre-install function**: a logic function that runs before the app is installed.
|
||||
- **(Optional) post-install function**: a logic function that runs after the app is installed.
|
||||
|
||||
Use `defineApplication()` to define your application configuration:
|
||||
|
||||
```typescript
|
||||
// src/application-config.ts
|
||||
import { defineApplication } from 'twenty-sdk';
|
||||
import { DEFAULT_ROLE_UNIVERSAL_IDENTIFIER } from 'src/roles/default-role';
|
||||
|
||||
export default defineApplication({
|
||||
universalIdentifier: '4ec0391d-18d5-411c-b2f3-266ddc1c3ef7',
|
||||
displayName: 'My Twenty App',
|
||||
description: 'My first Twenty app',
|
||||
icon: 'IconWorld',
|
||||
applicationVariables: {
|
||||
DEFAULT_RECIPIENT_NAME: {
|
||||
universalIdentifier: '19e94e59-d4fe-4251-8981-b96d0a9f74de',
|
||||
description: 'Default recipient name for postcards',
|
||||
value: 'Jane Doe',
|
||||
isSecret: false,
|
||||
},
|
||||
},
|
||||
defaultRoleUniversalIdentifier: DEFAULT_ROLE_UNIVERSAL_IDENTIFIER,
|
||||
});
|
||||
```
|
||||
|
||||
Notes:
|
||||
- `universalIdentifier` fields are deterministic IDs you own; generate them once and keep them stable across syncs.
|
||||
- `applicationVariables` become environment variables for your functions (for example, `DEFAULT_RECIPIENT_NAME` is available as `process.env.DEFAULT_RECIPIENT_NAME`).
|
||||
- `defaultRoleUniversalIdentifier` must match the role file (see below).
|
||||
- Pre-install and post-install functions are automatically detected during the manifest build. See [Pre-install functions](#pre-install-functions) and [Post-install functions](#post-install-functions).
|
||||
|
||||
#### Roles and permissions
|
||||
|
||||
Applications can define roles that encapsulate permissions on your workspace's objects and actions. The field `defaultRoleUniversalIdentifier` in `application-config.ts` designates the default role used by your app's logic functions.
|
||||
|
||||
- The runtime API key injected as `TWENTY_API_KEY` is derived from this default function role.
|
||||
- The typed client will be restricted to the permissions granted to that role.
|
||||
- Follow least‑privilege: create a dedicated role with only the permissions your functions need, then reference its universal identifier.
|
||||
|
||||
##### Default function role (*.role.ts)
|
||||
|
||||
When you scaffold a new app, the CLI also creates a default role file. Use `defineRole()` to define roles with built-in validation:
|
||||
|
||||
```typescript
|
||||
// src/roles/default-role.ts
|
||||
import { defineRole, PermissionFlag } from 'twenty-sdk';
|
||||
|
||||
export const DEFAULT_ROLE_UNIVERSAL_IDENTIFIER =
|
||||
'b648f87b-1d26-4961-b974-0908fd991061';
|
||||
|
||||
export default defineRole({
|
||||
universalIdentifier: DEFAULT_ROLE_UNIVERSAL_IDENTIFIER,
|
||||
label: 'Default function role',
|
||||
description: 'Default role for function Twenty client',
|
||||
canReadAllObjectRecords: false,
|
||||
canUpdateAllObjectRecords: false,
|
||||
canSoftDeleteAllObjectRecords: false,
|
||||
canDestroyAllObjectRecords: false,
|
||||
canUpdateAllSettings: false,
|
||||
canBeAssignedToAgents: false,
|
||||
canBeAssignedToUsers: false,
|
||||
canBeAssignedToApiKeys: false,
|
||||
objectPermissions: [
|
||||
{
|
||||
objectUniversalIdentifier: '9f9882af-170c-4879-b013-f9628b77c050',
|
||||
canReadObjectRecords: true,
|
||||
canUpdateObjectRecords: true,
|
||||
canSoftDeleteObjectRecords: false,
|
||||
canDestroyObjectRecords: false,
|
||||
},
|
||||
],
|
||||
fieldPermissions: [
|
||||
{
|
||||
objectUniversalIdentifier: '9f9882af-170c-4879-b013-f9628b77c050',
|
||||
fieldUniversalIdentifier: 'b2c37dc0-8ae7-470e-96cd-1476b47dfaff',
|
||||
canReadFieldValue: false,
|
||||
canUpdateFieldValue: false,
|
||||
},
|
||||
],
|
||||
permissionFlags: [PermissionFlag.APPLICATIONS],
|
||||
});
|
||||
```
|
||||
|
||||
The `universalIdentifier` of this role is then referenced in `application-config.ts` as `defaultRoleUniversalIdentifier`. In other words:
|
||||
|
||||
- **\*.role.ts** defines what the default function role can do.
|
||||
- **application-config.ts** points to that role so your functions inherit its permissions.
|
||||
|
||||
Notes:
|
||||
- Start from the scaffolded role, then progressively restrict it following least‑privilege.
|
||||
- Replace the `objectPermissions` and `fieldPermissions` with the objects/fields your functions need.
|
||||
- `permissionFlags` control access to platform-level capabilities. Keep them minimal; add only what you need.
|
||||
- See a working example in the Hello World app: [`packages/twenty-apps/hello-world/src/roles/function-role.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-apps/hello-world/src/roles/function-role.ts).
|
||||
|
||||
### Logic function config and entrypoint
|
||||
|
||||
Each function file uses `defineLogicFunction()` to export a configuration with a handler and optional triggers.
|
||||
|
||||
```typescript
|
||||
// src/app/createPostCard.logic-function.ts
|
||||
import { defineLogicFunction } from 'twenty-sdk';
|
||||
import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk';
|
||||
import { CoreApiClient, type Person } from 'twenty-sdk/generated';
|
||||
|
||||
const handler = async (params: RoutePayload) => {
|
||||
const client = new CoreApiClient();
|
||||
const name = 'name' in params.queryStringParameters
|
||||
? params.queryStringParameters.name ?? process.env.DEFAULT_RECIPIENT_NAME ?? 'Hello world'
|
||||
: 'Hello world';
|
||||
|
||||
const result = await client.mutation({
|
||||
createPostCard: {
|
||||
__args: { data: { name } },
|
||||
id: true,
|
||||
name: true,
|
||||
},
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
export default defineLogicFunction({
|
||||
universalIdentifier: 'e56d363b-0bdc-4d8a-a393-6f0d1c75bdcf',
|
||||
name: 'create-new-post-card',
|
||||
timeoutSeconds: 2,
|
||||
handler,
|
||||
triggers: [
|
||||
// Public HTTP route trigger '/s/post-card/create'
|
||||
{
|
||||
universalIdentifier: 'c9f84c8d-b26d-40d1-95dd-4f834ae5a2c6',
|
||||
type: 'route',
|
||||
path: '/post-card/create',
|
||||
httpMethod: 'GET',
|
||||
isAuthRequired: false,
|
||||
},
|
||||
// Cron trigger (CRON pattern)
|
||||
// {
|
||||
// universalIdentifier: 'dd802808-0695-49e1-98c9-d5c9e2704ce2',
|
||||
// type: 'cron',
|
||||
// pattern: '0 0 1 1 *',
|
||||
// },
|
||||
// Database event trigger
|
||||
// {
|
||||
// universalIdentifier: '203f1df3-4a82-4d06-a001-b8cf22a31156',
|
||||
// type: 'databaseEvent',
|
||||
// eventName: 'person.updated',
|
||||
// updatedFields: ['name'],
|
||||
// },
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
Common trigger types:
|
||||
- **route**: Exposes your function on an HTTP path and method **under the `/s/` endpoint**:
|
||||
> e.g. `path: '/post-card/create',` -> call on `<APP_URL>/s/post-card/create`
|
||||
- **cron**: Runs your function on a schedule using a CRON expression.
|
||||
- **databaseEvent**: Runs on workspace object lifecycle events. When the event operation is `updated`, specific fields to listen to can be specified in the `updatedFields` array. If left undefined or empty, any update will trigger the function.
|
||||
> e.g. `person.updated`
|
||||
|
||||
Notes:
|
||||
- The `triggers` array is optional. Functions without triggers can be used as utility functions called by other functions.
|
||||
- You can mix multiple trigger types in a single function.
|
||||
|
||||
### Pre-install functions
|
||||
|
||||
A pre-install function is a logic function that runs automatically before your app is installed on a workspace. This is useful for validation tasks, prerequisite checks, or preparing workspace state before the main installation proceeds.
|
||||
|
||||
When you scaffold a new app with `create-twenty-app`, a pre-install function is generated for you at `src/logic-functions/pre-install.ts`:
|
||||
|
||||
```typescript
|
||||
// src/logic-functions/pre-install.ts
|
||||
import { definePreInstallLogicFunction, type InstallLogicFunctionPayload } from 'twenty-sdk';
|
||||
|
||||
const handler = async (payload: InstallLogicFunctionPayload): Promise<void> => {
|
||||
console.log('Pre install logic function executed successfully!', payload.previousVersion);
|
||||
};
|
||||
|
||||
export default definePreInstallLogicFunction({
|
||||
universalIdentifier: '<generated-uuid>',
|
||||
name: 'pre-install',
|
||||
description: 'Runs before installation to prepare the application.',
|
||||
timeoutSeconds: 300,
|
||||
handler,
|
||||
});
|
||||
```
|
||||
|
||||
You can also manually execute the pre-install function at any time using the CLI:
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty function:execute --preInstall
|
||||
```
|
||||
|
||||
Key points:
|
||||
- Pre-install functions use `definePreInstallLogicFunction()` — a specialized variant that omits trigger settings (`cronTriggerSettings`, `databaseEventTriggerSettings`, `httpRouteTriggerSettings`, `isTool`).
|
||||
- The handler receives an `InstallLogicFunctionPayload` with `{ previousVersion: string }` — the version of the app that was previously installed (or an empty string for fresh installs).
|
||||
- Only one pre-install function is allowed per application. The manifest build will error if more than one is detected.
|
||||
- The function's `universalIdentifier` is automatically set as `preInstallLogicFunctionUniversalIdentifier` on the application manifest during the build — you do not need to reference it in `defineApplication()`.
|
||||
- The default timeout is set to 300 seconds (5 minutes) to allow for longer preparation tasks.
|
||||
- Pre-install functions do not need triggers — they are invoked by the platform before installation or manually via `function:execute --preInstall`.
|
||||
|
||||
### Post-install functions
|
||||
|
||||
A post-install function is a logic function that runs automatically after your app is installed on a workspace. This is useful for one-time setup tasks such as seeding default data, creating initial records, or configuring workspace settings.
|
||||
|
||||
When you scaffold a new app with `create-twenty-app`, a post-install function is generated for you at `src/logic-functions/post-install.ts`:
|
||||
|
||||
```typescript
|
||||
// src/logic-functions/post-install.ts
|
||||
import { definePostInstallLogicFunction, type InstallLogicFunctionPayload } from 'twenty-sdk';
|
||||
|
||||
const handler = async (payload: InstallLogicFunctionPayload): Promise<void> => {
|
||||
console.log('Post install logic function executed successfully!', payload.previousVersion);
|
||||
};
|
||||
|
||||
export default definePostInstallLogicFunction({
|
||||
universalIdentifier: '<generated-uuid>',
|
||||
name: 'post-install',
|
||||
description: 'Runs after installation to set up the application.',
|
||||
timeoutSeconds: 300,
|
||||
handler,
|
||||
});
|
||||
```
|
||||
|
||||
You can also manually execute the post-install function at any time using the CLI:
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty function:execute --postInstall
|
||||
```
|
||||
|
||||
Key points:
|
||||
- Post-install functions use `definePostInstallLogicFunction()` — a specialized variant that omits trigger settings (`cronTriggerSettings`, `databaseEventTriggerSettings`, `httpRouteTriggerSettings`, `isTool`).
|
||||
- The handler receives an `InstallLogicFunctionPayload` with `{ previousVersion: string }` — the version of the app that was previously installed (or an empty string for fresh installs).
|
||||
- Only one post-install function is allowed per application. The manifest build will error if more than one is detected.
|
||||
- The function's `universalIdentifier` is automatically set as `postInstallLogicFunctionUniversalIdentifier` on the application manifest during the build — you do not need to reference it in `defineApplication()`.
|
||||
- The default timeout is set to 300 seconds (5 minutes) to allow for longer setup tasks like data seeding.
|
||||
- Post-install functions do not need triggers — they are invoked by the platform during installation or manually via `function:execute --postInstall`.
|
||||
|
||||
### Route trigger payload
|
||||
|
||||
<Warning>
|
||||
**Breaking change (v1.16, January 2026):** The route trigger payload format has changed. Prior to v1.16, query parameters, path parameters, and body were sent directly as the payload. Starting with v1.16, they are nested inside a structured `RoutePayload` object.
|
||||
|
||||
**Before v1.16:**
|
||||
```typescript
|
||||
const handler = async (params) => {
|
||||
const { param1, param2 } = params; // Direct access
|
||||
};
|
||||
```
|
||||
|
||||
**After v1.16:**
|
||||
```typescript
|
||||
const handler = async (event: RoutePayload) => {
|
||||
const { param1, param2 } = event.body; // Access via .body
|
||||
const { queryParam } = event.queryStringParameters;
|
||||
const { id } = event.pathParameters;
|
||||
};
|
||||
```
|
||||
|
||||
**To migrate existing functions:** Update your handler to destructure from `event.body`, `event.queryStringParameters`, or `event.pathParameters` instead of directly from the params object.
|
||||
</Warning>
|
||||
|
||||
When a route trigger invokes your logic function, it receives a `RoutePayload` object that follows the AWS HTTP API v2 format. Import the type from `twenty-sdk`:
|
||||
|
||||
```typescript
|
||||
import { defineLogicFunction, type RoutePayload } from 'twenty-sdk';
|
||||
|
||||
const handler = async (event: RoutePayload) => {
|
||||
// Access request data
|
||||
const { headers, queryStringParameters, pathParameters, body } = event;
|
||||
|
||||
// HTTP method and path are available in requestContext
|
||||
const { method, path } = event.requestContext.http;
|
||||
|
||||
return { message: 'Success' };
|
||||
};
|
||||
```
|
||||
|
||||
The `RoutePayload` type has the following structure:
|
||||
|
||||
| Property | Type | Description |
|
||||
|----------|------|-------------|
|
||||
| `headers` | `Record<string, string \| undefined>` | HTTP headers (only those listed in `forwardedRequestHeaders`) |
|
||||
| `queryStringParameters` | `Record<string, string \| undefined>` | Query string parameters (multiple values joined with commas) |
|
||||
| `pathParameters` | `Record<string, string \| undefined>` | Path parameters extracted from the route pattern (e.g., `/users/:id` → `{ id: '123' }`) |
|
||||
| `body` | `object \| null` | Parsed request body (JSON) |
|
||||
| `isBase64Encoded` | `boolean` | Whether the body is base64 encoded |
|
||||
| `requestContext.http.method` | `string` | HTTP method (GET, POST, PUT, PATCH, DELETE) |
|
||||
| `requestContext.http.path` | `string` | Raw request path |
|
||||
|
||||
### Forwarding HTTP headers
|
||||
|
||||
By default, HTTP headers from incoming requests are **not** passed to your logic function for security reasons. To access specific headers, explicitly list them in the `forwardedRequestHeaders` array:
|
||||
|
||||
```typescript
|
||||
export default defineLogicFunction({
|
||||
universalIdentifier: 'e56d363b-0bdc-4d8a-a393-6f0d1c75bdcf',
|
||||
name: 'webhook-handler',
|
||||
handler,
|
||||
triggers: [
|
||||
{
|
||||
universalIdentifier: 'c9f84c8d-b26d-40d1-95dd-4f834ae5a2c6',
|
||||
type: 'route',
|
||||
path: '/webhook',
|
||||
httpMethod: 'POST',
|
||||
isAuthRequired: false,
|
||||
forwardedRequestHeaders: ['x-webhook-signature', 'content-type'],
|
||||
},
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
In your handler, you can then access these headers:
|
||||
|
||||
```typescript
|
||||
const handler = async (event: RoutePayload) => {
|
||||
const signature = event.headers['x-webhook-signature'];
|
||||
const contentType = event.headers['content-type'];
|
||||
|
||||
// Validate webhook signature...
|
||||
return { received: true };
|
||||
};
|
||||
```
|
||||
|
||||
<Note>
|
||||
Header names are normalized to lowercase. Access them using lowercase keys (for example, `event.headers['content-type']`).
|
||||
</Note>
|
||||
|
||||
You can create new functions in two ways:
|
||||
|
||||
- **Scaffolded**: Run `yarn twenty entity:add` and choose the option to add a new logic function. This generates a starter file with a handler and config.
|
||||
- **Manual**: Create a new `*.logic-function.ts` file and use `defineLogicFunction()`, following the same pattern.
|
||||
|
||||
### Marking a logic function as a tool
|
||||
|
||||
Logic functions can be exposed as **tools** for AI agents and workflows. When a function is marked as a tool, it becomes discoverable by Twenty's AI features and can be selected as a step in workflow automations.
|
||||
|
||||
To mark a logic function as a tool, set `isTool: true` and provide a `toolInputSchema` describing the expected input parameters using [JSON Schema](https://json-schema.org/):
|
||||
|
||||
```typescript
|
||||
// src/logic-functions/enrich-company.logic-function.ts
|
||||
import { defineLogicFunction } from 'twenty-sdk';
|
||||
import { CoreApiClient } from 'twenty-sdk/generated';
|
||||
|
||||
const handler = async (params: { companyName: string; domain?: string }) => {
|
||||
const client = new CoreApiClient();
|
||||
|
||||
const result = await client.mutation({
|
||||
createTask: {
|
||||
__args: {
|
||||
data: {
|
||||
title: `Enrich data for ${params.companyName}`,
|
||||
body: `Domain: ${params.domain ?? 'unknown'}`,
|
||||
},
|
||||
},
|
||||
id: true,
|
||||
},
|
||||
});
|
||||
|
||||
return { taskId: result.createTask.id };
|
||||
};
|
||||
|
||||
export default defineLogicFunction({
|
||||
universalIdentifier: 'f47ac10b-58cc-4372-a567-0e02b2c3d479',
|
||||
name: 'enrich-company',
|
||||
description: 'Enrich a company record with external data',
|
||||
timeoutSeconds: 10,
|
||||
handler,
|
||||
isTool: true,
|
||||
toolInputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
companyName: {
|
||||
type: 'string',
|
||||
description: 'The name of the company to enrich',
|
||||
},
|
||||
domain: {
|
||||
type: 'string',
|
||||
description: 'The company website domain (optional)',
|
||||
},
|
||||
},
|
||||
required: ['companyName'],
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
Key points:
|
||||
|
||||
- **`isTool`** (`boolean`, default: `false`): When set to `true`, the function is registered as a tool and becomes available to AI agents and workflow automations.
|
||||
- **`toolInputSchema`** (`object`, optional): A JSON Schema object that describes the parameters your function accepts. AI agents use this schema to understand what inputs the tool expects and to validate calls. If omitted, the schema defaults to `{ type: 'object', properties: {} }` (no parameters).
|
||||
- Functions with `isTool: false` (or unset) are **not** exposed as tools. They can still be executed directly or called by other functions, but will not appear in tool discovery.
|
||||
- **Tool naming**: When exposed as a tool, the function name is automatically normalized to `logic_function_<name>` (lowercased, non-alphanumeric characters replaced with underscores). For example, `enrich-company` becomes `logic_function_enrich_company`.
|
||||
- You can combine `isTool` with triggers — a function can be both a tool (callable by AI agents) and triggered by events (cron, database events, routes) at the same time.
|
||||
|
||||
<Note>
|
||||
**Write a good `description`.** AI agents rely on the function's `description` field to decide when to use the tool. Be specific about what the tool does and when it should be called.
|
||||
</Note>
|
||||
|
||||
### Front components
|
||||
|
||||
Front components let you build custom React components that render within Twenty's UI. Use `defineFrontComponent()` to define components with built-in validation:
|
||||
|
||||
```typescript
|
||||
// src/front-components/my-widget.tsx
|
||||
import { defineFrontComponent } from 'twenty-sdk';
|
||||
|
||||
const MyWidget = () => {
|
||||
return (
|
||||
<div style={{ padding: '20px', fontFamily: 'sans-serif' }}>
|
||||
<h1>My Custom Widget</h1>
|
||||
<p>This is a custom front component for Twenty.</p>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default defineFrontComponent({
|
||||
universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
|
||||
name: 'my-widget',
|
||||
description: 'A custom widget component',
|
||||
component: MyWidget,
|
||||
});
|
||||
```
|
||||
|
||||
Key points:
|
||||
- Front components are React components that render in isolated contexts within Twenty.
|
||||
- The `component` field references your React component.
|
||||
- Components are built and synced automatically during `yarn twenty app:dev`.
|
||||
|
||||
You can create new front components in two ways:
|
||||
|
||||
- **Scaffolded**: Run `yarn twenty entity:add` and choose the option to add a new front component.
|
||||
- **Manual**: Create a new `.tsx` file and use `defineFrontComponent()`, following the same pattern.
|
||||
|
||||
### Skills
|
||||
|
||||
Skills define reusable instructions and capabilities that AI agents can use within your workspace. Use `defineSkill()` to define skills with built-in validation:
|
||||
|
||||
```typescript
|
||||
// src/skills/example-skill.ts
|
||||
import { defineSkill } from 'twenty-sdk';
|
||||
|
||||
export default defineSkill({
|
||||
universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
|
||||
name: 'sales-outreach',
|
||||
label: 'Sales Outreach',
|
||||
description: 'Guides the AI agent through a structured sales outreach process',
|
||||
icon: 'IconBrain',
|
||||
content: `You are a sales outreach assistant. When reaching out to a prospect:
|
||||
1. Research the company and recent news
|
||||
2. Identify the prospect's role and likely pain points
|
||||
3. Draft a personalized message referencing specific details
|
||||
4. Keep the tone professional but conversational`,
|
||||
});
|
||||
```
|
||||
|
||||
Key points:
|
||||
- `name` is a unique identifier string for the skill (kebab-case recommended).
|
||||
- `label` is the human-readable display name shown in the UI.
|
||||
- `content` contains the skill instructions — this is the text the AI agent uses.
|
||||
- `icon` (optional) sets the icon displayed in the UI.
|
||||
- `description` (optional) provides additional context about the skill's purpose.
|
||||
|
||||
You can create new skills in two ways:
|
||||
|
||||
- **Scaffolded**: Run `yarn twenty entity:add` and choose the option to add a new skill.
|
||||
- **Manual**: Create a new file and use `defineSkill()`, following the same pattern.
|
||||
|
||||
### Generated typed clients
|
||||
|
||||
Two typed clients are auto-generated by `yarn twenty app:dev` and stored in `node_modules/twenty-sdk/generated` based on your workspace schema:
|
||||
|
||||
- **`CoreApiClient`** — queries the `/graphql` endpoint for workspace data
|
||||
- **`MetadataApiClient`** — queries the `/metadata` endpoint for workspace configuration and file uploads
|
||||
|
||||
```typescript
|
||||
import { CoreApiClient, MetadataApiClient } from 'twenty-sdk/generated';
|
||||
|
||||
const client = new CoreApiClient();
|
||||
const { me } = await client.query({ me: { id: true, displayName: true } });
|
||||
|
||||
const metadataClient = new MetadataApiClient();
|
||||
const { currentWorkspace } = await metadataClient.query({ currentWorkspace: { id: true } });
|
||||
```
|
||||
|
||||
Both clients are re-generated automatically by `yarn twenty app:dev` whenever your objects or fields change.
|
||||
|
||||
#### Runtime credentials in logic functions
|
||||
|
||||
When your function runs on Twenty, the platform injects credentials as environment variables before your code executes:
|
||||
|
||||
- `TWENTY_API_URL`: Base URL of the Twenty API your app targets.
|
||||
- `TWENTY_API_KEY`: Short‑lived key scoped to your application's default function role.
|
||||
|
||||
Notes:
|
||||
- You do not need to pass URL or API key to the generated client. It reads `TWENTY_API_URL` and `TWENTY_API_KEY` from process.env at runtime.
|
||||
- The API key's permissions are determined by the role referenced in your `application-config.ts` via `defaultRoleUniversalIdentifier`. This is the default role used by logic functions of your application.
|
||||
- Applications can define roles to follow least‑privilege. Grant only the permissions your functions need, then point `defaultRoleUniversalIdentifier` to that role's universal identifier.
|
||||
|
||||
#### Uploading files
|
||||
|
||||
The generated `MetadataApiClient` includes an `uploadFile` method for attaching files to file-type fields on your workspace objects. Because standard GraphQL clients do not support multipart file uploads natively, the client provides this dedicated method that implements the [GraphQL multipart request specification](https://github.com/jaydenseric/graphql-multipart-request-spec) under the hood.
|
||||
|
||||
```typescript
|
||||
import { MetadataApiClient } from 'twenty-sdk/generated';
|
||||
import * as fs from 'fs';
|
||||
|
||||
const metadataClient = new MetadataApiClient();
|
||||
|
||||
const fileBuffer = fs.readFileSync('./invoice.pdf');
|
||||
|
||||
const uploadedFile = await metadataClient.uploadFile(
|
||||
fileBuffer, // file contents as a Buffer
|
||||
'invoice.pdf', // filename
|
||||
'application/pdf', // MIME type (defaults to 'application/octet-stream')
|
||||
'58a0a314-d7ea-4865-9850-7fb84e72f30b', // field universal identifier
|
||||
);
|
||||
|
||||
console.log(uploadedFile);
|
||||
// { id: '...', path: '...', size: 12345, createdAt: '...', url: 'https://...' }
|
||||
```
|
||||
|
||||
The method signature:
|
||||
|
||||
```typescript
|
||||
uploadFile(
|
||||
fileBuffer: Buffer,
|
||||
filename: string,
|
||||
contentType: string,
|
||||
fieldMetadataUniversalIdentifier: string,
|
||||
): Promise<{ id: string; path: string; size: number; createdAt: string; url: string }>
|
||||
```
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `fileBuffer` | `Buffer` | The raw file contents |
|
||||
| `filename` | `string` | The name of the file (used for storage and display) |
|
||||
| `contentType` | `string` | MIME type of the file (defaults to `application/octet-stream` if omitted) |
|
||||
| `fieldMetadataUniversalIdentifier` | `string` | The `universalIdentifier` of the file-type field on your object |
|
||||
|
||||
Key points:
|
||||
- The `uploadFile` method is available on `MetadataApiClient` because the upload mutation is resolved by the `/metadata` endpoint.
|
||||
- It uses the field's `universalIdentifier` (not its workspace-specific ID), so your upload code works across any workspace where your app is installed — consistent with how apps reference fields everywhere else.
|
||||
- The returned `url` is a signed URL you can use to access the uploaded file.
|
||||
|
||||
### Hello World example
|
||||
|
||||
Explore a minimal, end-to-end example that demonstrates objects, logic functions, front components, and multiple triggers [here](https://github.com/twentyhq/twenty/tree/main/packages/twenty-apps/hello-world).
|
||||
@@ -0,0 +1,231 @@
|
||||
---
|
||||
title: Getting Started
|
||||
description: Create your first Twenty app in minutes.
|
||||
---
|
||||
|
||||
<Warning>
|
||||
Apps are currently in alpha testing. The feature is functional but still evolving.
|
||||
</Warning>
|
||||
|
||||
Apps let you extend Twenty with custom objects, fields, logic functions, AI skills, and UI components — all managed as code.
|
||||
|
||||
**What you can do today:**
|
||||
- Define custom objects and fields as code (managed data model)
|
||||
- Build logic functions with custom triggers (HTTP routes, cron, database events)
|
||||
- Define skills for AI agents
|
||||
- Build front components that render inside Twenty's UI
|
||||
- Deploy the same app across multiple workspaces
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Node.js 24+ and Yarn 4
|
||||
- A Twenty workspace and an API key (create one at https://app.twenty.com/settings/api-webhooks)
|
||||
|
||||
## Getting Started
|
||||
|
||||
Create a new app using the official scaffolder, then authenticate and start developing:
|
||||
|
||||
```bash filename="Terminal"
|
||||
# Scaffold a new app (includes all examples by default)
|
||||
npx create-twenty-app@latest my-twenty-app
|
||||
cd my-twenty-app
|
||||
|
||||
# Start dev mode: automatically syncs local changes to your workspace
|
||||
yarn twenty app:dev
|
||||
```
|
||||
|
||||
The scaffolder supports two modes for controlling which example files are included:
|
||||
|
||||
```bash filename="Terminal"
|
||||
# Default (exhaustive): all examples (object, field, logic function, front component, view, navigation menu item, skill)
|
||||
npx create-twenty-app@latest my-app
|
||||
|
||||
# Minimal: only core files (application-config.ts and default-role.ts)
|
||||
npx create-twenty-app@latest my-app --minimal
|
||||
```
|
||||
|
||||
From here you can:
|
||||
|
||||
```bash filename="Terminal"
|
||||
# Add a new entity to your application (guided)
|
||||
yarn twenty entity:add
|
||||
|
||||
# Watch your application's function logs
|
||||
yarn twenty function:logs
|
||||
|
||||
# Execute a function by name
|
||||
yarn twenty function:execute -n my-function -p '{"name": "test"}'
|
||||
|
||||
# Execute the pre-install function
|
||||
yarn twenty function:execute --preInstall
|
||||
|
||||
# Execute the post-install function
|
||||
yarn twenty function:execute --postInstall
|
||||
|
||||
# Uninstall the application from the current workspace
|
||||
yarn twenty app:uninstall
|
||||
|
||||
# Display commands' help
|
||||
yarn twenty help
|
||||
```
|
||||
|
||||
See also: the CLI reference pages for [create-twenty-app](https://www.npmjs.com/package/create-twenty-app) and [twenty-sdk CLI](https://www.npmjs.com/package/twenty-sdk).
|
||||
|
||||
## Project structure (scaffolded)
|
||||
|
||||
When you run `npx create-twenty-app@latest my-twenty-app`, the scaffolder:
|
||||
|
||||
- Copies a minimal base application into `my-twenty-app/`
|
||||
- Adds a local `twenty-sdk` dependency and Yarn 4 configuration
|
||||
- Creates config files and scripts wired to the `twenty` CLI
|
||||
- Generates core files (application config, default function role, pre-install and post-install functions) plus example files based on the scaffolding mode
|
||||
|
||||
A freshly scaffolded app with the default `--exhaustive` mode looks like this:
|
||||
|
||||
```text filename="my-twenty-app/"
|
||||
my-twenty-app/
|
||||
package.json
|
||||
yarn.lock
|
||||
.gitignore
|
||||
.nvmrc
|
||||
.yarnrc.yml
|
||||
.yarn/
|
||||
install-state.gz
|
||||
.oxlintrc.json
|
||||
tsconfig.json
|
||||
README.md
|
||||
public/ # Public assets folder (images, fonts, etc.)
|
||||
src/
|
||||
├── application-config.ts # Required - main application configuration
|
||||
├── roles/
|
||||
│ └── default-role.ts # Default role for logic functions
|
||||
├── objects/
|
||||
│ └── example-object.ts # Example custom object definition
|
||||
├── fields/
|
||||
│ └── example-field.ts # Example standalone field definition
|
||||
├── logic-functions/
|
||||
│ ├── hello-world.ts # Example logic function
|
||||
│ ├── pre-install.ts # Pre-install logic function
|
||||
│ └── post-install.ts # Post-install logic function
|
||||
├── front-components/
|
||||
│ └── hello-world.tsx # Example front component
|
||||
├── views/
|
||||
│ └── example-view.ts # Example saved view definition
|
||||
├── navigation-menu-items/
|
||||
│ └── example-navigation-menu-item.ts # Example sidebar navigation link
|
||||
└── skills/
|
||||
└── example-skill.ts # Example AI agent skill definition
|
||||
```
|
||||
|
||||
With `--minimal`, only the core files are created (`application-config.ts`, `roles/default-role.ts`, `logic-functions/pre-install.ts`, and `logic-functions/post-install.ts`).
|
||||
|
||||
At a high level:
|
||||
|
||||
- **package.json**: Declares the app name, version, engines (Node 24+, Yarn 4), and adds `twenty-sdk` plus a `twenty` script that delegates to the local `twenty` CLI. Run `yarn twenty help` to list all available commands.
|
||||
- **.gitignore**: Ignores common artifacts such as `node_modules`, `.yarn`, `generated/` (typed client), `dist/`, `build/`, coverage folders, log files, and `.env*` files.
|
||||
- **yarn.lock**, **.yarnrc.yml**, **.yarn/**: Lock and configure the Yarn 4 toolchain used by the project.
|
||||
- **.nvmrc**: Pins the Node.js version expected by the project.
|
||||
- **.oxlintrc.json** and **tsconfig.json**: Provide linting and TypeScript configuration for your app's TypeScript sources.
|
||||
- **README.md**: A short README in the app root with basic instructions.
|
||||
- **public/**: A folder for storing public assets (images, fonts, static files) that will be served with your application. Files placed here are uploaded during sync and accessible at runtime.
|
||||
- **src/**: The main place where you define your application-as-code
|
||||
|
||||
### Entity detection
|
||||
|
||||
The SDK detects entities by parsing your TypeScript files for **`export default define<Entity>({...})`** calls. Each entity type has a corresponding helper function exported from `twenty-sdk`:
|
||||
|
||||
| Helper function | Entity type |
|
||||
|-----------------|-------------|
|
||||
| `defineObject` | Custom object definitions |
|
||||
| `defineLogicFunction` | Logic function definitions |
|
||||
| `definePreInstallLogicFunction` | Pre-install logic function (runs before installation) |
|
||||
| `definePostInstallLogicFunction` | Post-install logic function (runs after installation) |
|
||||
| `defineFrontComponent` | Front component definitions |
|
||||
| `defineRole` | Role definitions |
|
||||
| `defineField` | Field extensions for existing objects |
|
||||
| `defineView` | Saved view definitions |
|
||||
| `defineNavigationMenuItem` | Navigation menu item definitions |
|
||||
| `defineSkill` | AI agent skill definitions |
|
||||
|
||||
<Note>
|
||||
**File naming is flexible.** Entity detection is AST-based — the SDK scans your source files for the `export default define<Entity>({...})` pattern. You can organize your files and folders however you like. Grouping by entity type (e.g., `logic-functions/`, `roles/`) is just a convention for code organization, not a requirement.
|
||||
</Note>
|
||||
|
||||
Example of a detected entity:
|
||||
```typescript
|
||||
// This file can be named anything and placed anywhere in src/
|
||||
import { defineObject, FieldType } from 'twenty-sdk';
|
||||
|
||||
export default defineObject({
|
||||
universalIdentifier: '...',
|
||||
nameSingular: 'postCard',
|
||||
// ... rest of config
|
||||
});
|
||||
```
|
||||
|
||||
Later commands will add more files and folders:
|
||||
|
||||
- `yarn twenty app:dev` will auto-generate two typed API clients in `node_modules/twenty-sdk/generated`: `CoreApiClient` (for workspace data via `/graphql`) and `MetadataApiClient` (for workspace configuration and file uploads via `/metadata`).
|
||||
- `yarn twenty entity:add` will add entity definition files under `src/` for your custom objects, functions, front components, roles, skills, and more.
|
||||
|
||||
## Authentication
|
||||
|
||||
The first time you run `yarn twenty auth:login`, you'll be prompted for:
|
||||
|
||||
- API URL (defaults to http://localhost:3000 or your current workspace profile)
|
||||
- API key
|
||||
|
||||
Your credentials are stored per-user in `~/.twenty/config.json`. You can maintain multiple profiles and switch between them.
|
||||
|
||||
### Managing workspaces
|
||||
|
||||
```bash filename="Terminal"
|
||||
# Login interactively (recommended)
|
||||
yarn twenty auth:login
|
||||
|
||||
# Login to a specific workspace profile
|
||||
yarn twenty auth:login --workspace my-custom-workspace
|
||||
|
||||
# List all configured workspaces
|
||||
yarn twenty auth:list
|
||||
|
||||
# Switch the default workspace (interactive)
|
||||
yarn twenty auth:switch
|
||||
|
||||
# Switch to a specific workspace
|
||||
yarn twenty auth:switch production
|
||||
|
||||
# Check current authentication status
|
||||
yarn twenty auth:status
|
||||
```
|
||||
|
||||
Once you've switched workspaces with `yarn twenty auth:switch`, all subsequent commands will use that workspace by default. You can still override it temporarily with `--workspace <name>`.
|
||||
|
||||
## Manual setup (without the scaffolder)
|
||||
|
||||
While we recommend using `create-twenty-app` for the best getting-started experience, you can also set up a project manually. Do not install the CLI globally. Instead, add `twenty-sdk` as a local dependency and wire a single script in your package.json:
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn add -D twenty-sdk
|
||||
```
|
||||
|
||||
Then add a `twenty` script:
|
||||
|
||||
```json filename="package.json"
|
||||
{
|
||||
"scripts": {
|
||||
"twenty": "twenty"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Now you can run all commands via `yarn twenty <command>`, e.g. `yarn twenty app:dev`, `yarn twenty help`, etc.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- Authentication errors: run `yarn twenty auth:login` and ensure your API key has the required permissions.
|
||||
- Cannot connect to server: verify the API URL and that the Twenty server is reachable.
|
||||
- Types or client missing/outdated: restart `yarn twenty app:dev` — it auto-generates the typed client.
|
||||
- Dev mode not syncing: ensure `yarn twenty app:dev` is running and that changes are not ignored by your environment.
|
||||
|
||||
Discord Help Channel: https://discord.com/channels/1130383047699738754/1130386664812982322
|
||||
@@ -0,0 +1,119 @@
|
||||
---
|
||||
title: Publishing
|
||||
description: Distribute your Twenty app to the marketplace or deploy it internally.
|
||||
---
|
||||
|
||||
<Warning>
|
||||
Apps are currently in alpha testing. The feature is functional but still evolving.
|
||||
</Warning>
|
||||
|
||||
## Overview
|
||||
|
||||
Once your app is [built and tested locally](/developers/extend/apps/building), you have two paths for distributing it:
|
||||
|
||||
- **Publish to npm** — list your app in the Twenty marketplace for any workspace to discover and install.
|
||||
- **Push a tarball** — deploy your app to a specific Twenty server for internal use without making it publicly available.
|
||||
|
||||
## Publishing to npm
|
||||
|
||||
Publishing to npm makes your app discoverable in the Twenty marketplace. Any Twenty workspace can browse, install, and upgrade marketplace apps directly from the UI.
|
||||
|
||||
### Requirements
|
||||
|
||||
- An [npm](https://www.npmjs.com) account
|
||||
- Your package name **must** use the `twenty-app-` prefix (e.g., `twenty-app-postcard-sender`)
|
||||
|
||||
### Steps
|
||||
|
||||
1. **Build your app** — the CLI compiles your TypeScript sources and generates the application manifest:
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty app:build
|
||||
```
|
||||
|
||||
2. **Publish to npm** — push the built package to the npm registry:
|
||||
|
||||
```bash filename="Terminal"
|
||||
npx twenty app:publish
|
||||
```
|
||||
|
||||
### Auto-discovery
|
||||
|
||||
Packages with the `twenty-app-` prefix are automatically discovered by the Twenty marketplace catalog. Once published, your app appears in the marketplace within a few minutes — no manual registration or approval required.
|
||||
|
||||
### CI publishing
|
||||
|
||||
The scaffolded project includes a GitHub Actions workflow that publishes on every release. It runs `app:build`, then `npm publish --provenance` from the build output:
|
||||
|
||||
```yaml filename=".github/workflows/publish.yml"
|
||||
name: Publish
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "24"
|
||||
registry-url: https://registry.npmjs.org
|
||||
- run: yarn install --immutable
|
||||
- run: npx twenty app:build
|
||||
- run: npm publish --provenance --access public
|
||||
working-directory: .twenty/output
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
```
|
||||
|
||||
For other CI systems (GitLab CI, CircleCI, etc.), the same three commands apply: `yarn install`, `npx twenty app:build`, then `npm publish` from `.twenty/output`.
|
||||
|
||||
<Tip>
|
||||
**npm provenance** is optional but recommended. Publishing with `--provenance` adds a trust badge to your npm listing, letting users verify the package was built from a specific commit in a public CI pipeline. See the [npm provenance docs](https://docs.npmjs.com/generating-provenance-statements) for setup instructions.
|
||||
</Tip>
|
||||
|
||||
## Internal distribution
|
||||
|
||||
For apps you don't want publicly available — proprietary tools, enterprise-only integrations, or experimental builds — you can push a tarball directly to a Twenty server.
|
||||
|
||||
### Push a tarball
|
||||
|
||||
Build your app and deploy it to a specific server in one step:
|
||||
|
||||
```bash filename="Terminal"
|
||||
npx twenty app:publish --server <server-url>
|
||||
```
|
||||
|
||||
Any workspace on that server can then install and upgrade the app from the **Applications** settings page.
|
||||
|
||||
### Version management
|
||||
|
||||
To release an update:
|
||||
|
||||
1. Bump the `version` field in your `package.json`
|
||||
2. Push a new tarball with `npx twenty app:publish --server <server-url>`
|
||||
3. Workspaces on that server will see the upgrade available in their settings
|
||||
|
||||
<Note>
|
||||
Internal apps are scoped to the server they're pushed to. They won't appear in the public marketplace and can't be installed by workspaces on other servers.
|
||||
</Note>
|
||||
|
||||
## App categories
|
||||
|
||||
Twenty organizes apps into three categories based on how they're distributed:
|
||||
|
||||
| Category | How it works | Visible in marketplace? |
|
||||
|----------|-------------|------------------------|
|
||||
| **Development** | Local dev mode apps running via `yarn twenty app:dev`. Used for building and testing. | No |
|
||||
| **Published** | Apps published to npm with the `twenty-app-` prefix. Listed in the marketplace for any workspace to install. | Yes |
|
||||
| **Internal** | Apps deployed via tarball to a specific server. Available only to workspaces on that server. | No |
|
||||
|
||||
<Tip>
|
||||
Start in **Development** mode while building your app. When it's ready, choose **Published** (npm) for broad distribution or **Internal** (tarball) for private deployment.
|
||||
</Tip>
|
||||
@@ -14,7 +14,7 @@ Apps let you build and manage Twenty customizations **as code**. Instead of conf
|
||||
**What you can do today:**
|
||||
- Define custom objects and fields as code (managed data model)
|
||||
- Build logic functions with custom triggers
|
||||
- Define skills for AI agents
|
||||
- Define skills and agents for AI
|
||||
- Deploy the same app across multiple workspaces
|
||||
|
||||
## Prerequisites
|
||||
@@ -38,7 +38,7 @@ yarn twenty app:dev
|
||||
The scaffolder supports two modes for controlling which example files are included:
|
||||
|
||||
```bash filename="Terminal"
|
||||
# Default (exhaustive): all examples (object, field, logic function, front component, view, navigation menu item, skill)
|
||||
# Default (exhaustive): all examples (object, field, logic function, front component, view, navigation menu item, skill, agent)
|
||||
npx create-twenty-app@latest my-app
|
||||
|
||||
# Minimal: only core files (application-config.ts and default-role.ts)
|
||||
@@ -114,8 +114,10 @@ my-twenty-app/
|
||||
│ └── example-view.ts # Example saved view definition
|
||||
├── navigation-menu-items/
|
||||
│ └── example-navigation-menu-item.ts # Example sidebar navigation link
|
||||
└── skills/
|
||||
└── example-skill.ts # Example AI agent skill definition
|
||||
├── skills/
|
||||
│ └── example-skill.ts # Example AI agent skill definition
|
||||
└── agents/
|
||||
└── example-agent.ts # Example AI agent definition
|
||||
```
|
||||
|
||||
With `--minimal`, only the core files are created (`application-config.ts`, `roles/default-role.ts`, `logic-functions/pre-install.ts`, and `logic-functions/post-install.ts`).
|
||||
@@ -147,6 +149,7 @@ The SDK detects entities by parsing your TypeScript files for **`export default
|
||||
| `defineView()` | Saved view definitions |
|
||||
| `defineNavigationMenuItem()` | Navigation menu item definitions |
|
||||
| `defineSkill()` | AI agent skill definitions |
|
||||
| `defineAgent()` | AI agent definitions |
|
||||
|
||||
<Note>
|
||||
**File naming is flexible.** Entity detection is AST-based — the SDK scans your source files for the `export default define<Entity>({...})` pattern. You can organize your files and folders however you like. Grouping by entity type (e.g., `logic-functions/`, `roles/`) is just a convention for code organization, not a requirement.
|
||||
@@ -166,7 +169,7 @@ export default defineObject({
|
||||
|
||||
Later commands will add more files and folders:
|
||||
|
||||
- `yarn twenty app:dev` will auto-generate two typed API clients in `node_modules/twenty-sdk/generated`: `CoreApiClient` (for workspace data via `/graphql`) and `MetadataApiClient` (for workspace configuration and file uploads via `/metadata`).
|
||||
- `yarn twenty app:dev` will auto-generate two typed API clients in `node_modules/twenty-sdk/clients`: `CoreApiClient` (for workspace data via `/graphql`) and `MetadataApiClient` (for workspace configuration and file uploads via `/metadata`).
|
||||
- `yarn twenty entity:add` will add entity definition files under `src/` for your custom objects, functions, front components, roles, skills, and more.
|
||||
|
||||
## Authentication
|
||||
@@ -223,6 +226,7 @@ The SDK provides helper functions for defining your app entities. As described i
|
||||
| `defineView()` | Define saved views for objects |
|
||||
| `defineNavigationMenuItem()` | Define sidebar navigation links |
|
||||
| `defineSkill()` | Define AI agent skills |
|
||||
| `defineAgent()` | Define AI agents with system prompts |
|
||||
|
||||
These functions validate your configuration at build time and provide IDE autocompletion and type safety.
|
||||
|
||||
@@ -315,6 +319,71 @@ Key points:
|
||||
but this is not recommended.
|
||||
</Note>
|
||||
|
||||
### Defining fields on existing objects
|
||||
|
||||
Use `defineField()` to add custom fields to existing objects — both standard objects (like `company`, `person`, `opportunity`) and custom objects defined by other apps. Each field lives in its own file and references the target object by its `universalIdentifier`.
|
||||
|
||||
To reference standard objects, import `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS` from `twenty-sdk`. This constant provides stable identifiers for all built-in objects and their fields:
|
||||
|
||||
```typescript
|
||||
// src/fields/apollo-total-funding.field.ts
|
||||
import {
|
||||
defineField,
|
||||
FieldType,
|
||||
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS,
|
||||
} from 'twenty-sdk';
|
||||
|
||||
export default defineField({
|
||||
universalIdentifier: 'c90ae72d-4ddf-4f22-882f-eef98c91e40e',
|
||||
objectUniversalIdentifier:
|
||||
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS.company.universalIdentifier,
|
||||
type: FieldType.CURRENCY,
|
||||
name: 'apolloTotalFunding',
|
||||
label: 'Total Funding',
|
||||
description: 'Total funding raised by the company',
|
||||
icon: 'IconCash',
|
||||
});
|
||||
```
|
||||
|
||||
Key points:
|
||||
|
||||
- `objectUniversalIdentifier` tells Twenty which object to attach the field to. Use `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS.<objectName>.universalIdentifier` for standard objects.
|
||||
- Each field requires its own stable `universalIdentifier`, a `name`, `type`, `label`, and the target `objectUniversalIdentifier`.
|
||||
- You can scaffold new fields using `yarn twenty entity:add` and choosing the field option.
|
||||
- `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS` is also exported as `STANDARD_OBJECT` for convenience — both refer to the same constant.
|
||||
|
||||
Available standard objects include: `attachment`, `blocklist`, `calendarChannel`, `calendarEvent`, `calendarEventParticipant`, `company`, `connectedAccount`, `dashboard`, `favorite`, `favoriteFolder`, `message`, `messageChannel`, `messageParticipant`, `messageThread`, `note`, `noteTarget`, `opportunity`, `person`, `task`, `taskTarget`, `timelineActivity`, `workflow`, `workflowAutomatedTrigger`, `workflowRun`, `workflowVersion`, and `workspaceMember`.
|
||||
|
||||
Each standard object also exposes its field identifiers. For example, to reference a specific field on a standard object in role permissions:
|
||||
|
||||
```typescript
|
||||
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS.company.fields.name.universalIdentifier
|
||||
```
|
||||
|
||||
#### Relation fields on existing objects
|
||||
|
||||
You can also define relation fields that link existing objects to your custom objects:
|
||||
|
||||
```typescript
|
||||
// src/fields/people-on-call-recording.field.ts
|
||||
import { defineField, FieldType, RelationType, STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS } from 'twenty-sdk';
|
||||
import { CALL_RECORDING_OBJECT_UNIVERSAL_IDENTIFIER } from 'src/objects/call-recording';
|
||||
import { CALL_RECORDING_ON_PERSON_ID } from 'src/fields/call-recording-on-person.field';
|
||||
|
||||
export default defineField({
|
||||
universalIdentifier: '4a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d',
|
||||
objectUniversalIdentifier:
|
||||
CALL_RECORDING_OBJECT_UNIVERSAL_IDENTIFIER,
|
||||
type: FieldType.RELATION,
|
||||
name: 'person',
|
||||
label: 'Person',
|
||||
relationTargetObjectMetadataUniversalIdentifier:
|
||||
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS.person.universalIdentifier,
|
||||
relationTargetFieldMetadataUniversalIdentifier:
|
||||
CALL_RECORDING_ON_PERSON_ID,
|
||||
relationType: RelationType.MANY_TO_ONE,
|
||||
});
|
||||
```
|
||||
|
||||
### Application config (application-config.ts)
|
||||
|
||||
@@ -427,7 +496,7 @@ Each function file uses `defineLogicFunction()` to export a configuration with a
|
||||
// src/app/createPostCard.logic-function.ts
|
||||
import { defineLogicFunction } from 'twenty-sdk';
|
||||
import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk';
|
||||
import { CoreApiClient, type Person } from 'twenty-sdk/generated';
|
||||
import { CoreApiClient, type Person } from 'twenty-sdk/clients';
|
||||
|
||||
const handler = async (params: RoutePayload) => {
|
||||
const client = new CoreApiClient();
|
||||
@@ -665,7 +734,7 @@ To mark a logic function as a tool, set `isTool: true` and provide a `toolInputS
|
||||
```typescript
|
||||
// src/logic-functions/enrich-company.logic-function.ts
|
||||
import { defineLogicFunction } from 'twenty-sdk';
|
||||
import { CoreApiClient } from 'twenty-sdk/generated';
|
||||
import { CoreApiClient } from 'twenty-sdk/clients';
|
||||
|
||||
const handler = async (params: { companyName: string; domain?: string }) => {
|
||||
const client = new CoreApiClient();
|
||||
@@ -790,15 +859,50 @@ You can create new skills in two ways:
|
||||
- **Scaffolded**: Run `yarn twenty entity:add` and choose the option to add a new skill.
|
||||
- **Manual**: Create a new file and use `defineSkill()`, following the same pattern.
|
||||
|
||||
### Agents
|
||||
|
||||
Agents define AI agents with system prompts that can operate within your workspace. Use `defineAgent()` to define agents with built-in validation:
|
||||
|
||||
```typescript
|
||||
// src/agents/example-agent.ts
|
||||
import { defineAgent } from 'twenty-sdk';
|
||||
|
||||
export default defineAgent({
|
||||
universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
|
||||
name: 'sales-assistant',
|
||||
label: 'Sales Assistant',
|
||||
description: 'An AI agent that helps with sales tasks',
|
||||
icon: 'IconRobot',
|
||||
prompt: `You are a sales assistant. Help users with:
|
||||
1. Researching prospects and companies
|
||||
2. Drafting personalized outreach messages
|
||||
3. Tracking follow-ups and next steps
|
||||
4. Analyzing deal pipeline and suggesting actions`,
|
||||
});
|
||||
```
|
||||
|
||||
Key points:
|
||||
- `name` is a unique identifier string for the agent (kebab-case recommended).
|
||||
- `label` is the human-readable display name shown in the UI.
|
||||
- `prompt` contains the system prompt — this is the instruction text that defines the agent's behavior.
|
||||
- `icon` (optional) sets the icon displayed in the UI.
|
||||
- `description` (optional) provides additional context about the agent's purpose.
|
||||
|
||||
You can create new agents in two ways:
|
||||
|
||||
- **Scaffolded**: Run `yarn twenty entity:add` and choose the option to add a new agent.
|
||||
- **Manual**: Create a new file and use `defineAgent()`, following the same pattern.
|
||||
|
||||
### Generated typed clients
|
||||
|
||||
Two typed clients are auto-generated by `yarn twenty app:dev` and stored in `node_modules/twenty-sdk/generated` based on your workspace schema:
|
||||
Two typed clients are auto-generated by `yarn twenty app:dev` and stored in `node_modules/twenty-sdk/clients` based on your workspace schema:
|
||||
|
||||
- **`CoreApiClient`** — queries the `/graphql` endpoint for workspace data
|
||||
- **`MetadataApiClient`** — queries the `/metadata` endpoint for workspace configuration and file uploads
|
||||
|
||||
```typescript
|
||||
import { CoreApiClient, MetadataApiClient } from 'twenty-sdk/generated';
|
||||
import { CoreApiClient } from 'twenty-sdk/clients';
|
||||
import { MetadataApiClient } from 'twenty-sdk/clients';
|
||||
|
||||
const client = new CoreApiClient();
|
||||
const { me } = await client.query({ me: { id: true, displayName: true } });
|
||||
@@ -807,7 +911,7 @@ const metadataClient = new MetadataApiClient();
|
||||
const { currentWorkspace } = await metadataClient.query({ currentWorkspace: { id: true } });
|
||||
```
|
||||
|
||||
Both clients are re-generated automatically by `yarn twenty app:dev` whenever your objects or fields change.
|
||||
`CoreApiClient` is re-generated automatically by `yarn twenty app:dev` whenever your objects or fields change. `MetadataApiClient` ships pre-built with the SDK.
|
||||
|
||||
#### Runtime credentials in logic functions
|
||||
|
||||
@@ -823,10 +927,10 @@ Notes:
|
||||
|
||||
#### Uploading files
|
||||
|
||||
The generated `MetadataApiClient` includes an `uploadFile` method for attaching files to file-type fields on your workspace objects. Because standard GraphQL clients do not support multipart file uploads natively, the client provides this dedicated method that implements the [GraphQL multipart request specification](https://github.com/jaydenseric/graphql-multipart-request-spec) under the hood.
|
||||
The `MetadataApiClient` includes an `uploadFile` method for attaching files to file-type fields on your workspace objects. Because standard GraphQL clients do not support multipart file uploads natively, the client provides this dedicated method that implements the [GraphQL multipart request specification](https://github.com/jaydenseric/graphql-multipart-request-spec) under the hood.
|
||||
|
||||
```typescript
|
||||
import { MetadataApiClient } from 'twenty-sdk/generated';
|
||||
import { MetadataApiClient } from 'twenty-sdk/clients';
|
||||
import * as fs from 'fs';
|
||||
|
||||
const metadataClient = new MetadataApiClient();
|
||||
|
||||
@@ -14,20 +14,18 @@ Twenty is designed to be extensible. Use our APIs, webhooks, and app framework t
|
||||
|
||||
- **APIs**: Query and modify your CRM data programmatically using REST or GraphQL
|
||||
- **Webhooks**: Receive real-time notifications when events occur in Twenty
|
||||
- **Apps**: Build custom applications that extend Twenty's capabilities - Coming soon!
|
||||
- **Apps**: Build custom applications that extend Twenty's capabilities
|
||||
|
||||
## Getting Started
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="APIs" icon="code" href="/developers/extend/capabilities/apis">
|
||||
<Card title="APIs" icon="code" href="/developers/extend/api">
|
||||
Connect to Twenty programmatically
|
||||
</Card>
|
||||
<Card title="Webhooks" icon="bell" href="/developers/extend/capabilities/webhooks">
|
||||
<Card title="Webhooks" icon="bell" href="/developers/extend/webhooks">
|
||||
Get notified of events in real-time
|
||||
</Card>
|
||||
<Card title="Apps" icon="puzzle-piece" href="/developers/extend/capabilities/apps">
|
||||
Build customizations as code (Alpha)
|
||||
<Card title="Apps" icon="puzzle-piece" href="/developers/extend/apps/getting-started">
|
||||
Build customizations as code
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
---
|
||||
title: Webhooks
|
||||
description: Receive real-time notifications when events occur in your CRM.
|
||||
---
|
||||
|
||||
import { VimeoEmbed } from '/snippets/vimeo-embed.mdx';
|
||||
|
||||
|
||||
Webhooks push data to your systems in real-time when events occur in Twenty — no polling required. Use them to keep external systems in sync, trigger automations, or send alerts.
|
||||
|
||||
## Create a Webhook
|
||||
|
||||
1. Go to **Settings → APIs & Webhooks → Webhooks**
|
||||
2. Click **+ Create webhook**
|
||||
3. Enter your webhook URL (must be publicly accessible)
|
||||
4. Click **Save**
|
||||
|
||||
The webhook activates immediately and starts sending notifications.
|
||||
|
||||
<VimeoEmbed videoId="928786708" title="Creating a webhook" />
|
||||
|
||||
### Manage Webhooks
|
||||
|
||||
**Edit**: Click the webhook → Update URL → **Save**
|
||||
|
||||
**Delete**: Click the webhook → **Delete** → Confirm
|
||||
|
||||
## Events
|
||||
|
||||
Twenty sends webhooks for these event types:
|
||||
|
||||
| Event | Example |
|
||||
|-------|---------|
|
||||
| **Record Created** | `person.created`, `company.created`, `note.created` |
|
||||
| **Record Updated** | `person.updated`, `company.updated`, `opportunity.updated` |
|
||||
| **Record Deleted** | `person.deleted`, `company.deleted` |
|
||||
|
||||
All event types are sent to your webhook URL. Event filtering may be added in future releases.
|
||||
|
||||
## Payload Format
|
||||
|
||||
Each webhook sends an HTTP POST with a JSON body:
|
||||
|
||||
```json
|
||||
{
|
||||
"event": "person.created",
|
||||
"data": {
|
||||
"id": "abc12345",
|
||||
"firstName": "Alice",
|
||||
"lastName": "Doe",
|
||||
"email": "[email protected]",
|
||||
"createdAt": "2025-02-10T15:30:45Z",
|
||||
"createdBy": "user_123"
|
||||
},
|
||||
"timestamp": "2025-02-10T15:30:50Z"
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `event` | What happened (e.g., `person.created`) |
|
||||
| `data` | The full record that was created/updated/deleted |
|
||||
| `timestamp` | When the event occurred (UTC) |
|
||||
|
||||
<Note>
|
||||
Respond with a **2xx HTTP status** (200-299) to acknowledge receipt. Non-2xx responses are logged as delivery failures.
|
||||
</Note>
|
||||
|
||||
## Webhook Validation
|
||||
|
||||
Twenty signs each webhook request for security. Validate signatures to ensure requests are authentic.
|
||||
|
||||
### Headers
|
||||
|
||||
| Header | Description |
|
||||
|--------|-------------|
|
||||
| `X-Twenty-Webhook-Signature` | HMAC SHA256 signature |
|
||||
| `X-Twenty-Webhook-Timestamp` | Request timestamp |
|
||||
|
||||
### Validation Steps
|
||||
|
||||
1. Get the timestamp from `X-Twenty-Webhook-Timestamp`
|
||||
2. Create the string: `{timestamp}:{JSON payload}`
|
||||
3. Compute HMAC SHA256 using your webhook secret
|
||||
4. Compare with `X-Twenty-Webhook-Signature`
|
||||
|
||||
### Example (Node.js)
|
||||
|
||||
```javascript
|
||||
const crypto = require("crypto");
|
||||
|
||||
const timestamp = req.headers["x-twenty-webhook-timestamp"];
|
||||
const payload = JSON.stringify(req.body);
|
||||
const secret = "your-webhook-secret";
|
||||
|
||||
const stringToSign = `${timestamp}:${payload}`;
|
||||
const expectedSignature = crypto
|
||||
.createHmac("sha256", secret)
|
||||
.update(stringToSign)
|
||||
.digest("hex");
|
||||
|
||||
const receivedSignature = req.headers["x-twenty-webhook-signature"];
|
||||
const isValid = crypto.timingSafeEqual(
|
||||
Buffer.from(expectedSignature, "hex"),
|
||||
Buffer.from(receivedSignature, "hex")
|
||||
);
|
||||
```
|
||||
|
||||
## Webhooks vs Workflows
|
||||
|
||||
| Method | Direction | Use Case |
|
||||
|--------|-----------|----------|
|
||||
| **Webhooks** | OUT | Automatically notify external systems of any record change |
|
||||
| **Workflow + HTTP Request** | OUT | Send data out with custom logic (filters, transformations) |
|
||||
| **Workflow Webhook Trigger** | IN | Receive data into Twenty from external systems |
|
||||
|
||||
For receiving external data, see [Set Up a Webhook Trigger](/user-guide/workflows/how-tos/connect-to-other-tools/set-up-a-webhook-trigger).
|
||||
+106
-76
@@ -358,13 +358,14 @@
|
||||
"group": "Extend",
|
||||
"icon": "plug",
|
||||
"pages": [
|
||||
"developers/extend/extend",
|
||||
"developers/extend/api",
|
||||
"developers/extend/webhooks",
|
||||
{
|
||||
"group": "Capabilities",
|
||||
"group": "Apps",
|
||||
"pages": [
|
||||
"developers/extend/capabilities/apis",
|
||||
"developers/extend/capabilities/webhooks",
|
||||
"developers/extend/capabilities/apps"
|
||||
"developers/extend/apps/getting-started",
|
||||
"developers/extend/apps/building",
|
||||
"developers/extend/apps/publishing"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -803,13 +804,14 @@
|
||||
"group": "Étendre",
|
||||
"icon": "plug",
|
||||
"pages": [
|
||||
"l/fr/developers/extend/extend",
|
||||
"l/fr/developers/extend/api",
|
||||
"l/fr/developers/extend/webhooks",
|
||||
{
|
||||
"group": "Capacités",
|
||||
"group": "Apps",
|
||||
"pages": [
|
||||
"l/fr/developers/extend/capabilities/apis",
|
||||
"l/fr/developers/extend/capabilities/webhooks",
|
||||
"l/fr/developers/extend/capabilities/apps"
|
||||
"l/fr/developers/extend/apps/getting-started",
|
||||
"l/fr/developers/extend/apps/building",
|
||||
"l/fr/developers/extend/apps/publishing"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -1248,13 +1250,14 @@
|
||||
"group": "التوسيع",
|
||||
"icon": "plug",
|
||||
"pages": [
|
||||
"l/ar/developers/extend/extend",
|
||||
"l/ar/developers/extend/api",
|
||||
"l/ar/developers/extend/webhooks",
|
||||
{
|
||||
"group": "القدرات",
|
||||
"group": "Apps",
|
||||
"pages": [
|
||||
"l/ar/developers/extend/capabilities/apis",
|
||||
"l/ar/developers/extend/capabilities/webhooks",
|
||||
"l/ar/developers/extend/capabilities/apps"
|
||||
"l/ar/developers/extend/apps/getting-started",
|
||||
"l/ar/developers/extend/apps/building",
|
||||
"l/ar/developers/extend/apps/publishing"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -1693,13 +1696,14 @@
|
||||
"group": "Rozšíření",
|
||||
"icon": "plug",
|
||||
"pages": [
|
||||
"l/cs/developers/extend/extend",
|
||||
"l/cs/developers/extend/api",
|
||||
"l/cs/developers/extend/webhooks",
|
||||
{
|
||||
"group": "Možnosti",
|
||||
"group": "Apps",
|
||||
"pages": [
|
||||
"l/cs/developers/extend/capabilities/apis",
|
||||
"l/cs/developers/extend/capabilities/webhooks",
|
||||
"l/cs/developers/extend/capabilities/apps"
|
||||
"l/cs/developers/extend/apps/getting-started",
|
||||
"l/cs/developers/extend/apps/building",
|
||||
"l/cs/developers/extend/apps/publishing"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -2138,13 +2142,14 @@
|
||||
"group": "Erweitern",
|
||||
"icon": "plug",
|
||||
"pages": [
|
||||
"l/de/developers/extend/extend",
|
||||
"l/de/developers/extend/api",
|
||||
"l/de/developers/extend/webhooks",
|
||||
{
|
||||
"group": "Funktionen",
|
||||
"group": "Apps",
|
||||
"pages": [
|
||||
"l/de/developers/extend/capabilities/apis",
|
||||
"l/de/developers/extend/capabilities/webhooks",
|
||||
"l/de/developers/extend/capabilities/apps"
|
||||
"l/de/developers/extend/apps/getting-started",
|
||||
"l/de/developers/extend/apps/building",
|
||||
"l/de/developers/extend/apps/publishing"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -2583,13 +2588,14 @@
|
||||
"group": "Ampliar",
|
||||
"icon": "plug",
|
||||
"pages": [
|
||||
"l/es/developers/extend/extend",
|
||||
"l/es/developers/extend/api",
|
||||
"l/es/developers/extend/webhooks",
|
||||
{
|
||||
"group": "Capacidades",
|
||||
"group": "Apps",
|
||||
"pages": [
|
||||
"l/es/developers/extend/capabilities/apis",
|
||||
"l/es/developers/extend/capabilities/webhooks",
|
||||
"l/es/developers/extend/capabilities/apps"
|
||||
"l/es/developers/extend/apps/getting-started",
|
||||
"l/es/developers/extend/apps/building",
|
||||
"l/es/developers/extend/apps/publishing"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -3028,13 +3034,14 @@
|
||||
"group": "Estendi",
|
||||
"icon": "plug",
|
||||
"pages": [
|
||||
"l/it/developers/extend/extend",
|
||||
"l/it/developers/extend/api",
|
||||
"l/it/developers/extend/webhooks",
|
||||
{
|
||||
"group": "Funzionalità",
|
||||
"group": "Apps",
|
||||
"pages": [
|
||||
"l/it/developers/extend/capabilities/apis",
|
||||
"l/it/developers/extend/capabilities/webhooks",
|
||||
"l/it/developers/extend/capabilities/apps"
|
||||
"l/it/developers/extend/apps/getting-started",
|
||||
"l/it/developers/extend/apps/building",
|
||||
"l/it/developers/extend/apps/publishing"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -3473,13 +3480,14 @@
|
||||
"group": "拡張",
|
||||
"icon": "plug",
|
||||
"pages": [
|
||||
"l/ja/developers/extend/extend",
|
||||
"l/ja/developers/extend/api",
|
||||
"l/ja/developers/extend/webhooks",
|
||||
{
|
||||
"group": "機能",
|
||||
"group": "Apps",
|
||||
"pages": [
|
||||
"l/ja/developers/extend/capabilities/apis",
|
||||
"l/ja/developers/extend/capabilities/webhooks",
|
||||
"l/ja/developers/extend/capabilities/apps"
|
||||
"l/ja/developers/extend/apps/getting-started",
|
||||
"l/ja/developers/extend/apps/building",
|
||||
"l/ja/developers/extend/apps/publishing"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -3918,13 +3926,14 @@
|
||||
"group": "확장",
|
||||
"icon": "plug",
|
||||
"pages": [
|
||||
"l/ko/developers/extend/extend",
|
||||
"l/ko/developers/extend/api",
|
||||
"l/ko/developers/extend/webhooks",
|
||||
{
|
||||
"group": "기능",
|
||||
"group": "Apps",
|
||||
"pages": [
|
||||
"l/ko/developers/extend/capabilities/apis",
|
||||
"l/ko/developers/extend/capabilities/webhooks",
|
||||
"l/ko/developers/extend/capabilities/apps"
|
||||
"l/ko/developers/extend/apps/getting-started",
|
||||
"l/ko/developers/extend/apps/building",
|
||||
"l/ko/developers/extend/apps/publishing"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -4363,13 +4372,14 @@
|
||||
"group": "Extend",
|
||||
"icon": "plug",
|
||||
"pages": [
|
||||
"l/pt/developers/extend/extend",
|
||||
"l/pt/developers/extend/api",
|
||||
"l/pt/developers/extend/webhooks",
|
||||
{
|
||||
"group": "Capabilities",
|
||||
"group": "Apps",
|
||||
"pages": [
|
||||
"l/pt/developers/extend/capabilities/apis",
|
||||
"l/pt/developers/extend/capabilities/webhooks",
|
||||
"l/pt/developers/extend/capabilities/apps"
|
||||
"l/pt/developers/extend/apps/getting-started",
|
||||
"l/pt/developers/extend/apps/building",
|
||||
"l/pt/developers/extend/apps/publishing"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -4808,13 +4818,14 @@
|
||||
"group": "Extend",
|
||||
"icon": "plug",
|
||||
"pages": [
|
||||
"l/ro/developers/extend/extend",
|
||||
"l/ro/developers/extend/api",
|
||||
"l/ro/developers/extend/webhooks",
|
||||
{
|
||||
"group": "Capabilities",
|
||||
"group": "Apps",
|
||||
"pages": [
|
||||
"l/ro/developers/extend/capabilities/apis",
|
||||
"l/ro/developers/extend/capabilities/webhooks",
|
||||
"l/ro/developers/extend/capabilities/apps"
|
||||
"l/ro/developers/extend/apps/getting-started",
|
||||
"l/ro/developers/extend/apps/building",
|
||||
"l/ro/developers/extend/apps/publishing"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -5253,13 +5264,14 @@
|
||||
"group": "Расширяйте",
|
||||
"icon": "plug",
|
||||
"pages": [
|
||||
"l/ru/developers/extend/extend",
|
||||
"l/ru/developers/extend/api",
|
||||
"l/ru/developers/extend/webhooks",
|
||||
{
|
||||
"group": "Возможности",
|
||||
"group": "Apps",
|
||||
"pages": [
|
||||
"l/ru/developers/extend/capabilities/apis",
|
||||
"l/ru/developers/extend/capabilities/webhooks",
|
||||
"l/ru/developers/extend/capabilities/apps"
|
||||
"l/ru/developers/extend/apps/getting-started",
|
||||
"l/ru/developers/extend/apps/building",
|
||||
"l/ru/developers/extend/apps/publishing"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -5698,13 +5710,14 @@
|
||||
"group": "Genişlet",
|
||||
"icon": "plug",
|
||||
"pages": [
|
||||
"l/tr/developers/extend/extend",
|
||||
"l/tr/developers/extend/api",
|
||||
"l/tr/developers/extend/webhooks",
|
||||
{
|
||||
"group": "Yetkinlikler",
|
||||
"group": "Apps",
|
||||
"pages": [
|
||||
"l/tr/developers/extend/capabilities/apis",
|
||||
"l/tr/developers/extend/capabilities/webhooks",
|
||||
"l/tr/developers/extend/capabilities/apps"
|
||||
"l/tr/developers/extend/apps/getting-started",
|
||||
"l/tr/developers/extend/apps/building",
|
||||
"l/tr/developers/extend/apps/publishing"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -6143,13 +6156,14 @@
|
||||
"group": "扩展",
|
||||
"icon": "plug",
|
||||
"pages": [
|
||||
"l/zh/developers/extend/extend",
|
||||
"l/zh/developers/extend/api",
|
||||
"l/zh/developers/extend/webhooks",
|
||||
{
|
||||
"group": "功能",
|
||||
"group": "Apps",
|
||||
"pages": [
|
||||
"l/zh/developers/extend/capabilities/apis",
|
||||
"l/zh/developers/extend/capabilities/webhooks",
|
||||
"l/zh/developers/extend/capabilities/apps"
|
||||
"l/zh/developers/extend/apps/getting-started",
|
||||
"l/zh/developers/extend/apps/building",
|
||||
"l/zh/developers/extend/apps/publishing"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -6272,6 +6286,22 @@
|
||||
}
|
||||
},
|
||||
"redirects": [
|
||||
{
|
||||
"source": "/developers/extend/capabilities/api",
|
||||
"destination": "/developers/extend/api"
|
||||
},
|
||||
{
|
||||
"source": "/developers/extend/capabilities/apis",
|
||||
"destination": "/developers/extend/api"
|
||||
},
|
||||
{
|
||||
"source": "/developers/extend/capabilities/webhooks",
|
||||
"destination": "/developers/extend/webhooks"
|
||||
},
|
||||
{
|
||||
"source": "/developers/extend/capabilities/apps",
|
||||
"destination": "/developers/extend/apps/getting-started"
|
||||
},
|
||||
{
|
||||
"source": "/developers/local-setup",
|
||||
"destination": "/developers/contribute/capabilities/local-setup"
|
||||
@@ -6302,27 +6332,27 @@
|
||||
},
|
||||
{
|
||||
"source": "/developers/api-and-webhooks",
|
||||
"destination": "/developers/extend/extend"
|
||||
"destination": "/developers/extend/api"
|
||||
},
|
||||
{
|
||||
"source": "/developers/api-and-webhooks/apis-overview",
|
||||
"destination": "/developers/extend/capabilities/apis"
|
||||
"destination": "/developers/extend/api"
|
||||
},
|
||||
{
|
||||
"source": "/developers/api-and-webhooks/api",
|
||||
"destination": "/developers/extend/capabilities/apis"
|
||||
"destination": "/developers/extend/api"
|
||||
},
|
||||
{
|
||||
"source": "/developers/api-and-webhooks/api-keys",
|
||||
"destination": "/developers/extend/capabilities/apis"
|
||||
"destination": "/developers/extend/api"
|
||||
},
|
||||
{
|
||||
"source": "/developers/api-and-webhooks/webhooks",
|
||||
"destination": "/developers/extend/capabilities/webhooks"
|
||||
"destination": "/developers/extend/webhooks"
|
||||
},
|
||||
{
|
||||
"source": "/developers/api-and-webhooks/integrations",
|
||||
"destination": "/developers/extend/capabilities/apis"
|
||||
"destination": "/developers/extend/api"
|
||||
},
|
||||
{
|
||||
"source": "/developers/bugs-and-requests",
|
||||
|
||||
@@ -15,7 +15,7 @@ description: أنشئ وأدِر تخصيصات Twenty على هيئة كود.
|
||||
|
||||
* عرِّف كائنات وحقولًا مخصصة على شكل كود (نموذج بيانات مُدار)
|
||||
* أنشئ وظائف منطقية مع مشغلات مخصصة
|
||||
* حدد المهارات لوكلاء الذكاء الاصطناعي
|
||||
* تعريف المهارات والوكلاء للذكاء الاصطناعي
|
||||
* انشر التطبيق نفسه عبر مساحات عمل متعددة
|
||||
|
||||
## المتطلبات الأساسية
|
||||
@@ -39,7 +39,7 @@ yarn twenty app:dev
|
||||
يدعم المُنشئ وضعين للتحكم في ملفات الأمثلة التي سيتم تضمينها:
|
||||
|
||||
```bash filename="Terminal"
|
||||
# الافتراضي (شامل): جميع الأمثلة (كائن، حقل، دالة منطقية، مكوّن الواجهة الأمامية، عرض، عنصر قائمة التنقل، مهارة)
|
||||
# الافتراضي (شامل): جميع الأمثلة (كائن، حقل، دالة منطقية، مكوّن الواجهة الأمامية، عرض، عنصر قائمة التنقل، مهارة، وكيل)
|
||||
npx create-twenty-app@latest my-app
|
||||
|
||||
# الأدنى: الملفات الأساسية فقط (application-config.ts و default-role.ts)
|
||||
@@ -115,8 +115,10 @@ my-twenty-app/
|
||||
│ └── example-view.ts # تعريف عرض محفوظ — مثال
|
||||
├── navigation-menu-items/
|
||||
│ └── example-navigation-menu-item.ts # رابط تنقّل في الشريط الجانبي — مثال
|
||||
└── skills/
|
||||
└── example-skill.ts # تعريف مهارة لوكيل الذكاء الاصطناعي — مثال},{
|
||||
├── skills/
|
||||
│ └── example-skill.ts # تعريف مهارة لوكيل الذكاء الاصطناعي — مثال
|
||||
└── agents/
|
||||
└── example-agent.ts # تعريف وكيل الذكاء الاصطناعي — مثال
|
||||
```
|
||||
|
||||
مع `--minimal`، سيتم إنشاء الملفات الأساسية فقط (`application-config.ts`، `roles/default-role.ts`، `logic-functions/pre-install.ts`، و`logic-functions/post-install.ts`).
|
||||
@@ -148,6 +150,7 @@ my-twenty-app/
|
||||
| `defineView()` | تعريفات العروض المحفوظة |
|
||||
| `defineNavigationMenuItem()` | تعريفات عناصر قائمة التنقل |
|
||||
| `defineSkill()` | تعريفات مهارات وكيل الذكاء الاصطناعي |
|
||||
| `defineAgent()` | تعريفات وكلاء الذكاء الاصطناعي |
|
||||
|
||||
<Note>
|
||||
**تسمية الملفات مرنة.** يعتمد اكتشاف الكيانات على بنية الشجرة المجردة (AST) — إذ يقوم SDK بفحص ملفات المصدر لديك بحثًا عن النمط `export default define<Entity>({...})`. يمكنك تنظيم ملفاتك ومجلداتك كيفما تشاء. التجميع حسب نوع الكيان (مثلًا، `logic-functions/` و`roles/`) هو مجرد عرف لتنظيم الشيفرة، وليس مطلبًا إلزاميًا.
|
||||
@@ -225,6 +228,7 @@ yarn twenty auth:status
|
||||
| `defineView()` | تعريف العروض المحفوظة للكائنات |
|
||||
| `defineNavigationMenuItem()` | تعريف روابط التنقل في الشريط الجانبي |
|
||||
| `defineSkill()` | عرّف مهارات وكيل الذكاء الاصطناعي |
|
||||
| `defineAgent()` | Define AI agents with system prompts |
|
||||
|
||||
تتحقق هذه الدوال من تكوينك وقت البناء وتوفّر إكمالًا تلقائيًا في بيئة التطوير وأمان الأنواع.
|
||||
|
||||
@@ -802,6 +806,41 @@ export default defineSkill({
|
||||
* **مُنشأ بالقالب**: شغِّل `yarn twenty entity:add` واختر خيار إضافة مهارة جديدة.
|
||||
* **يدوي**: أنشئ ملفًا جديدًا واستخدم `defineSkill()` مع اتباع النمط نفسه.
|
||||
|
||||
### Agents
|
||||
|
||||
Agents define AI agents with system prompts that can operate within your workspace. Use `defineAgent()` to define agents with built-in validation:
|
||||
|
||||
```typescript
|
||||
// src/agents/example-agent.ts
|
||||
import { defineAgent } from 'twenty-sdk';
|
||||
|
||||
export default defineAgent({
|
||||
universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
|
||||
name: 'sales-assistant',
|
||||
label: 'Sales Assistant',
|
||||
description: 'An AI agent that helps with sales tasks',
|
||||
icon: 'IconRobot',
|
||||
prompt: `You are a sales assistant. Help users with:
|
||||
1. Researching prospects and companies
|
||||
2. Drafting personalized outreach messages
|
||||
3. Tracking follow-ups and next steps
|
||||
4. Analyzing deal pipeline and suggesting actions`,
|
||||
});
|
||||
```
|
||||
|
||||
النقاط الرئيسية:
|
||||
|
||||
* `name` is a unique identifier string for the agent (kebab-case recommended).
|
||||
* `label` هو اسم العرض المقروء للبشر الظاهر في واجهة المستخدم.
|
||||
* `prompt` contains the system prompt — this is the instruction text that defines the agent's behavior.
|
||||
* `icon` (اختياري) يحدّد الأيقونة المعروضة في واجهة المستخدم.
|
||||
* `description` (optional) provides additional context about the agent's purpose.
|
||||
|
||||
You can create new agents in two ways:
|
||||
|
||||
* **Scaffolded**: Run `yarn twenty entity:add` and choose the option to add a new agent.
|
||||
* **Manual**: Create a new file and use `defineAgent()`, following the same pattern.
|
||||
|
||||
### عملاء مُولَّدون مضبوطو الأنواع
|
||||
|
||||
يتم توليد عميلين مضبوطي الأنواع تلقائيًا بواسطة `yarn twenty app:dev` وتخزينهما في `node_modules/twenty-sdk/generated` استنادًا إلى مخطط مساحة العمل لديك:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
title: التوسيع
|
||||
description: وسّع وظائف Twenty باستخدام واجهات برمجة التطبيقات، وخطافات الويب، والتطبيقات المخصصة.
|
||||
redirect: /developers/introduction
|
||||
---
|
||||
|
||||
<Frame>
|
||||
@@ -20,13 +21,13 @@ description: وسّع وظائف Twenty باستخدام واجهات برمجة
|
||||
## البدء
|
||||
|
||||
<CardGroup cols={٢}>
|
||||
<Card title="واجهات برمجة التطبيقات" icon="كود" href="/l/ar/developers/extend/capabilities/apis">
|
||||
<Card title="واجهات برمجة التطبيقات" icon="كود" href="/l/ar/developers/api">
|
||||
اتصل بـ Twenty برمجياً
|
||||
</Card>
|
||||
<Card title="الويب هوكس" icon="bell" href="/l/ar/developers/extend/capabilities/webhooks">
|
||||
<Card title="الويب هوكس" icon="bell" href="/l/ar/developers/webhooks">
|
||||
احصل على إشعارات بالأحداث في الوقت الفعلي
|
||||
</Card>
|
||||
<Card title="التطبيقات" icon="puzzle-piece" href="/l/ar/developers/extend/capabilities/apps">
|
||||
<Card title="التطبيقات" icon="puzzle-piece" href="/l/ar/developers/apps/apps">
|
||||
أنشئ تخصيصات كرمز برمجي (ألفا)
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@@ -5,18 +5,28 @@ description: مرحبًا بك في وثائق المطوّرين الخاصة
|
||||
|
||||
import { CardTitle } from "/snippets/card-title.mdx"
|
||||
|
||||
<CardGroup cols={٣}>
|
||||
<Card href="/l/ar/developers/extend/extend" img="/images/user-guide/integrations/plug.png">
|
||||
<CardTitle>التوسيع</CardTitle>
|
||||
أنشئ عمليات تكامل مع واجهات برمجة التطبيقات وخطافات الويب والتطبيقات المخصصة.
|
||||
<CardGroup cols={2}>
|
||||
<Card href="/l/ar/developers/api" icon="code">
|
||||
<CardTitle>API</CardTitle>
|
||||
استعلام وتعديل بيانات CRM الخاصة بك باستخدام REST أو GraphQL.
|
||||
</Card>
|
||||
|
||||
<Card href="/l/ar/developers/self-host/self-host" img="/images/user-guide/what-is-twenty/20.png">
|
||||
<Card href="/l/ar/developers/webhooks" icon="bell">
|
||||
<CardTitle>Webhooks</CardTitle>
|
||||
استقبل إشعارات في الوقت الفعلي عند حدوث الأحداث.
|
||||
</Card>
|
||||
|
||||
<Card href="/l/ar/developers/apps/apps" icon="puzzle-piece">
|
||||
<CardTitle>Apps</CardTitle>
|
||||
أنشئ تطبيقات مخصصة توسّع قدرات Twenty.
|
||||
</Card>
|
||||
|
||||
<Card href="/l/ar/developers/self-host/self-host" icon="desktop">
|
||||
<CardTitle>الاستضافة الذاتية</CardTitle>
|
||||
قم بنشر Twenty وإدارته على البنية التحتية الخاصة بك.
|
||||
</Card>
|
||||
|
||||
<Card href="/l/ar/developers/contribute/contribute" img="/images/user-guide/github/github-header.png">
|
||||
<Card href="/l/ar/developers/contribute/contribute" icon="github">
|
||||
<CardTitle>المساهمة</CardTitle>
|
||||
انضم إلى مجتمعنا مفتوح المصدر وساهم في Twenty.
|
||||
</Card>
|
||||
|
||||
@@ -24,7 +24,7 @@ import { VimeoEmbed } from '/snippets/vimeo-embed.mdx';
|
||||
* يتم تصدير **الأعمدة المرئية** فقط
|
||||
* يتم تصدير **السجلات المصفّاة** فقط (استنادًا إلى العرض الحالي لديك)
|
||||
|
||||
<Note>بالنسبة لعمليات التصدير الأكبر (أكثر من 20,000 سجل)، استخدم عوامل التصفية للتصدير على دفعات أو استخدم [واجهة برمجة التطبيقات (API)](/l/ar/developers/extend/capabilities/apis).</Note>
|
||||
<Note>بالنسبة لعمليات التصدير الأكبر (أكثر من 20,000 سجل)، استخدم عوامل التصفية للتصدير على دفعات أو استخدم [واجهة برمجة التطبيقات (API)](/l/ar/developers/api).</Note>
|
||||
|
||||
### الصلاحيات
|
||||
|
||||
@@ -148,7 +148,7 @@ import { VimeoEmbed } from '/snippets/vimeo-embed.mdx';
|
||||
2. استخدم واجهة برمجة تطبيقات GraphQL للاستعلام عن السجلات
|
||||
3. عالج النتائج في تطبيقك
|
||||
|
||||
راجع: [وثائق واجهة برمجة التطبيقات (API)](/l/ar/developers/extend/capabilities/apis)
|
||||
راجع: [وثائق واجهة برمجة التطبيقات (API)](/l/ar/developers/api)
|
||||
|
||||
## نصائح وأفضل الممارسات
|
||||
|
||||
@@ -206,4 +206,4 @@ import { VimeoEmbed } from '/snippets/vimeo-embed.mdx';
|
||||
|
||||
* [كيفية تحديث السجلات الموجودة](/l/ar/user-guide/data-migration/how-tos/update-existing-records-via-import) — حرّر وأعد استيراد ملف التصدير الخاص بك
|
||||
* [كيفية استيراد البيانات عبر واجهة برمجة التطبيقات (API)](/l/ar/user-guide/data-migration/how-tos/import-data-via-api) — لمجموعات البيانات الكبيرة
|
||||
* [وثائق واجهة برمجة التطبيقات (API)](/l/ar/developers/extend/capabilities/apis) — أنشئ عمليات سير عمل تصدير مخصصة
|
||||
* [وثائق واجهة برمجة التطبيقات (API)](/l/ar/developers/api) — أنشئ عمليات سير عمل تصدير مخصصة
|
||||
|
||||
@@ -59,8 +59,8 @@ description: متى وكيف تستخدم واجهات API الخاصة بـ Twe
|
||||
|
||||
| واجهة برمجة التطبيقات | الأفضل لـ | التوثيق |
|
||||
| --------------------- | ------------------------------------------------------ | ------------------------------------------------- |
|
||||
| **GraphQL** | استعلامات مرنة، وجلب البيانات المرتبطة، وعمليات معقّدة | [وثائق API](/l/ar/developers/extend/capabilities/apis) |
|
||||
| **REST** | عمليات CRUD بسيطة، وأنماط REST مألوفة | [وثائق API](/l/ar/developers/extend/capabilities/apis) |
|
||||
| **GraphQL** | استعلامات مرنة، وجلب البيانات المرتبطة، وعمليات معقّدة | [وثائق API](/l/ar/developers/api) |
|
||||
| **REST** | عمليات CRUD بسيطة، وأنماط REST مألوفة | [وثائق API](/l/ar/developers/api) |
|
||||
|
||||
كلتا واجهتي API تدعمان:
|
||||
|
||||
@@ -173,4 +173,4 @@ description: متى وكيف تستخدم واجهات API الخاصة بـ Twe
|
||||
|
||||
للحصول على تفاصيل التنفيذ الكاملة وأمثلة الشيفرة ومرجع المخطط (schema):
|
||||
|
||||
* [وثائق API](/l/ar/developers/extend/capabilities/apis)
|
||||
* [وثائق API](/l/ar/developers/api)
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ description: Twenty هو نظام إدارة علاقات العملاء (CRM)
|
||||
* **لوحات التحكم:** تتبع الأداء باستخدام تقارير مخصصة وتصوّرات مرئية. [عرض لوحات التحكم](/l/ar/user-guide/dashboards/overview).
|
||||
* **الأذونات والوصول:** تحكّم في مَن يمكنه عرض بياناتك وتحريرها وإدارتها باستخدام أذونات مستندة إلى الأدوار. [تكوين الوصول](/l/ar/user-guide/permissions-access/overview).
|
||||
* **الملاحظات والمهام:** أنشئ ملاحظات ومهام مرتبطة بسجلاتك لتحسين التعاون.
|
||||
* **واجهة برمجة التطبيقات والويب هوكس:** الاتصال بالتطبيقات الأخرى وإنشاء عمليات تكامل مخصصة. [ابدأ التكامل](/l/ar/developers/extend/capabilities/apis).
|
||||
* **واجهة برمجة التطبيقات والويب هوكس:** الاتصال بالتطبيقات الأخرى وإنشاء عمليات تكامل مخصصة. [ابدأ التكامل](/l/ar/developers/api).
|
||||
|
||||
## انضم الآن
|
||||
|
||||
|
||||
+1
-1
@@ -95,7 +95,7 @@ description: اعرض بيانات من سجلات مرتبطة (مثل معلو
|
||||
* حجم الشركة: `{{searchRecords[0].employees}}`
|
||||
|
||||
<Note>
|
||||
**قيود المهام والملاحظات**: العلاقات في المهام والملاحظات مُحدّدة في الشفرة كعلاقات متعدّدة-لمتعدّدة وليست متاحة بعد في محفّزات أو إجراءات سير العمل. للوصول إلى هذه العلاقات، استخدم بدلًا من ذلك [API](/l/ar/developers/extend/capabilities/apis).
|
||||
**قيود المهام والملاحظات**: العلاقات في المهام والملاحظات مُحدّدة في الشفرة كعلاقات متعدّدة-لمتعدّدة وليست متاحة بعد في محفّزات أو إجراءات سير العمل. للوصول إلى هذه العلاقات، استخدم بدلًا من ذلك [API](/l/ar/developers/api).
|
||||
</Note>
|
||||
|
||||
## مزامنة ثنائية الاتجاه
|
||||
|
||||
@@ -15,7 +15,7 @@ Aplikace vám umožňují vytvářet a spravovat přizpůsobení Twenty **jako k
|
||||
|
||||
* Definujte vlastní objekty a pole jako kód (spravovaný datový model)
|
||||
* Vytvářejte logické funkce s vlastními spouštěči
|
||||
* Definujte dovednosti agentů AI
|
||||
* Definujte dovednosti a agenty AI!
|
||||
* Nasazujte stejnou aplikaci do více pracovních prostorů
|
||||
|
||||
## Předpoklady
|
||||
@@ -39,7 +39,7 @@ yarn twenty app:dev
|
||||
Nástroj pro generování kostry podporuje dva režimy pro řízení toho, které ukázkové soubory jsou zahrnuty:
|
||||
|
||||
```bash filename="Terminal"
|
||||
# Výchozí (úplný): všechny příklady (objekt, pole, logická funkce, front-endová komponenta, zobrazení, položka navigační nabídky, dovednost)
|
||||
# Výchozí (úplný): všechny příklady (objekt, pole, logická funkce, front-endová komponenta, zobrazení, položka navigační nabídky, dovednost, agent)
|
||||
npx create-twenty-app@latest my-app
|
||||
|
||||
# Minimální: pouze základní soubory (application-config.ts a default-role.ts)
|
||||
@@ -115,8 +115,10 @@ my-twenty-app/
|
||||
│ └── example-view.ts # Ukázková definice uloženého zobrazení
|
||||
├── navigation-menu-items/
|
||||
│ └── example-navigation-menu-item.ts # Ukázkový odkaz postranní navigace
|
||||
└── skills/
|
||||
└── example-skill.ts # Ukázková definice dovednosti agenta AI
|
||||
├── skills/
|
||||
│ └── example-skill.ts # Ukázková definice dovednosti agenta AI
|
||||
└── agents/
|
||||
└── example-agent.ts # Ukázková definice agenta AI
|
||||
```
|
||||
|
||||
S volbou `--minimal` se vytvoří pouze základní soubory (`application-config.ts`, `roles/default-role.ts`, `logic-functions/pre-install.ts` a `logic-functions/post-install.ts`).
|
||||
@@ -148,6 +150,7 @@ SDK detekuje entity analýzou vašich souborů TypeScript a hledá volání **`e
|
||||
| `defineView()` | Definice uložených zobrazení |
|
||||
| `defineNavigationMenuItem()` | Definice položek navigační nabídky |
|
||||
| `defineSkill()` | Definice dovedností agenta AI |
|
||||
| `defineAgent()` | Definice agentů AI |
|
||||
|
||||
<Note>
|
||||
**Pojmenování souborů je flexibilní.** Detekce entit je založená na AST — SDK prochází vaše zdrojové soubory a hledá vzor `export default define<Entity>({...})`. Soubory a složky můžete organizovat, jak chcete. Seskupování podle typu entity (např. `logic-functions/`, `roles/`) je pouze konvence pro organizaci kódu, nikoli požadavek.
|
||||
@@ -225,6 +228,7 @@ SDK poskytuje pomocné funkce pro definování entit vaší aplikace. Jak je pop
|
||||
| `defineView()` | Definujte uložená zobrazení pro objekty |
|
||||
| `defineNavigationMenuItem()` | Definujte odkazy postranní navigace |
|
||||
| `defineSkill()` | Definuje dovednosti agenta AI |
|
||||
| `defineAgent()` | Define AI agents with system prompts |
|
||||
|
||||
Tyto funkce validují vaši konfiguraci v době sestavení a poskytují automatické doplňování v IDE a typovou bezpečnost.
|
||||
|
||||
@@ -802,6 +806,41 @@ Nové dovednosti můžete vytvářet dvěma způsoby:
|
||||
* **Vygenerované**: Spusťte `yarn twenty entity:add` a zvolte možnost přidat novou dovednost.
|
||||
* **Ruční**: Vytvořte nový soubor a použijte `defineSkill()` podle stejného vzoru.
|
||||
|
||||
### Agenti
|
||||
|
||||
Agents define AI agents with system prompts that can operate within your workspace. Use `defineAgent()` to define agents with built-in validation:
|
||||
|
||||
```typescript
|
||||
// src/agents/example-agent.ts
|
||||
import { defineAgent } from 'twenty-sdk';
|
||||
|
||||
export default defineAgent({
|
||||
universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
|
||||
name: 'sales-assistant',
|
||||
label: 'Sales Assistant',
|
||||
description: 'An AI agent that helps with sales tasks',
|
||||
icon: 'IconRobot',
|
||||
prompt: `You are a sales assistant. Help users with:
|
||||
1. Researching prospects and companies
|
||||
2. Drafting personalized outreach messages
|
||||
3. Tracking follow-ups and next steps
|
||||
4. Analyzing deal pipeline and suggesting actions`,
|
||||
});
|
||||
```
|
||||
|
||||
Hlavní body:
|
||||
|
||||
* `name` is a unique identifier string for the agent (kebab-case recommended).
|
||||
* `label` je uživatelsky čitelný název zobrazovaný v UI.
|
||||
* `prompt` contains the system prompt — this is the instruction text that defines the agent's behavior.
|
||||
* `icon` (volitelné) nastavuje ikonu zobrazovanou v UI.
|
||||
* `description` (optional) provides additional context about the agent's purpose.
|
||||
|
||||
You can create new agents in two ways:
|
||||
|
||||
* **Scaffolded**: Run `yarn twenty entity:add` and choose the option to add a new agent.
|
||||
* **Manual**: Create a new file and use `defineAgent()`, following the same pattern.
|
||||
|
||||
### Generované typované klienty
|
||||
|
||||
Dva typované klienty jsou automaticky generovány pomocí `yarn twenty app:dev` a ukládají se do `node_modules/twenty-sdk/generated` podle schématu vašeho pracovního prostoru:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
title: Rozšiřte
|
||||
description: Rozšiřte funkčnost Twenty pomocí rozhraní API, webhooků a vlastních aplikací.
|
||||
redirect: /developers/introduction
|
||||
---
|
||||
|
||||
<Frame>
|
||||
@@ -20,13 +21,13 @@ Twenty je navrženo tak, aby bylo rozšiřitelné. Použijte naše rozhraní API
|
||||
## Začínáme
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="API" icon="kód" href="/l/cs/developers/extend/capabilities/apis">
|
||||
<Card title="API" icon="kód" href="/l/cs/developers/api">
|
||||
Programově se připojte k Twenty
|
||||
</Card>
|
||||
<Card title="Webhooky" icon="bell" href="/l/cs/developers/extend/capabilities/webhooks">
|
||||
<Card title="Webhooky" icon="bell" href="/l/cs/developers/webhooks">
|
||||
Dostávejte oznámení o událostech v reálném čase
|
||||
</Card>
|
||||
<Card title="Aplikace" icon="puzzle-piece" href="/l/cs/developers/extend/capabilities/apps">
|
||||
<Card title="Aplikace" icon="puzzle-piece" href="/l/cs/developers/apps/apps">
|
||||
Vytvářejte přizpůsobení jako kód (Alpha)
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@@ -5,18 +5,28 @@ description: Vítejte v dokumentaci pro vývojáře Twenty, která je vaším zd
|
||||
|
||||
import { CardTitle } from "/snippets/card-title.mdx"
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card href="/l/cs/developers/extend/extend" img="/images/user-guide/integrations/plug.png">
|
||||
<CardTitle>Rozšiřte</CardTitle>
|
||||
Vytvářejte integrace pomocí API, webhooků a vlastních aplikací.
|
||||
<CardGroup cols={2}>
|
||||
<Card href="/l/cs/developers/api" icon="code">
|
||||
<CardTitle>API</CardTitle>
|
||||
Dotazujte a upravujte data CRM pomocí REST nebo GraphQL.
|
||||
</Card>
|
||||
|
||||
<Card href="/l/cs/developers/self-host/self-host" img="/images/user-guide/what-is-twenty/20.png">
|
||||
<Card href="/l/cs/developers/webhooks" icon="bell">
|
||||
<CardTitle>Webhooks</CardTitle>
|
||||
Přijímejte oznámení v reálném čase při výskytu událostí.
|
||||
</Card>
|
||||
|
||||
<Card href="/l/cs/developers/apps/apps" icon="puzzle-piece">
|
||||
<CardTitle>Apps</CardTitle>
|
||||
Vytvářejte vlastní aplikace rozšiřující možnosti Twenty.
|
||||
</Card>
|
||||
|
||||
<Card href="/l/cs/developers/self-host/self-host" icon="desktop">
|
||||
<CardTitle>Hostujte sami</CardTitle>
|
||||
Nasaďte a spravujte Twenty na vlastní infrastruktuře.
|
||||
</Card>
|
||||
|
||||
<Card href="/l/cs/developers/contribute/contribute" img="/images/user-guide/github/github-header.png">
|
||||
<Card href="/l/cs/developers/contribute/contribute" icon="github">
|
||||
<CardTitle>Přispějte</CardTitle>
|
||||
Připojte se k naší open-source komunitě a přispívejte do Twenty.
|
||||
</Card>
|
||||
|
||||
@@ -24,7 +24,7 @@ Exportujte data svého pracovního prostoru do CSV pro zálohování, vytvářen
|
||||
* Exportují se pouze **viditelné sloupce**
|
||||
* Exportují se pouze **filtrované záznamy** (podle vašeho aktuálního zobrazení)
|
||||
|
||||
<Note>U větších exportů (20 000+ záznamů) použijte filtry pro export po dávkách nebo použijte [API](/l/cs/developers/extend/capabilities/apis).</Note>
|
||||
<Note>U větších exportů (20 000+ záznamů) použijte filtry pro export po dávkách nebo použijte [API](/l/cs/developers/api).</Note>
|
||||
|
||||
### Oprávnění
|
||||
|
||||
@@ -148,7 +148,7 @@ API nemá limit počtu záznamů:
|
||||
2. Použijte GraphQL API k dotazování na záznamy
|
||||
3. Zpracujte výsledky ve své aplikaci
|
||||
|
||||
Viz: [Dokumentace API](/l/cs/developers/extend/capabilities/apis)
|
||||
Viz: [Dokumentace API](/l/cs/developers/api)
|
||||
|
||||
## Tipy a osvědčené postupy
|
||||
|
||||
@@ -206,4 +206,4 @@ Exportované soubory mohou obsahovat citlivá data:
|
||||
|
||||
* [Jak aktualizovat existující záznamy](/l/cs/user-guide/data-migration/how-tos/update-existing-records-via-import) — upravte a znovu importujte svůj export
|
||||
* [Jak importovat data přes API](/l/cs/user-guide/data-migration/how-tos/import-data-via-api) — pro velké datové sady
|
||||
* [Dokumentace API](/l/cs/developers/extend/capabilities/apis) — vytvářejte vlastní pracovní postupy pro export
|
||||
* [Dokumentace API](/l/cs/developers/api) — vytvářejte vlastní pracovní postupy pro export
|
||||
|
||||
@@ -59,8 +59,8 @@ Twenty podporuje dva typy API:
|
||||
|
||||
| API | Vhodné pro | Dokumentace |
|
||||
| ----------- | ----------------------------------------------------------------- | ------------------------------------------------------- |
|
||||
| **GraphQL** | Flexibilní dotazy, získávání souvisejících dat, komplexní operace | [Dokumentace API](/l/cs/developers/extend/capabilities/apis) |
|
||||
| **REST** | Jednoduché CRUD operace, známé postupy REST | [Dokumentace API](/l/cs/developers/extend/capabilities/apis) |
|
||||
| **GraphQL** | Flexibilní dotazy, získávání souvisejících dat, komplexní operace | [Dokumentace API](/l/cs/developers/api) |
|
||||
| **REST** | Jednoduché CRUD operace, známé postupy REST | [Dokumentace API](/l/cs/developers/api) |
|
||||
|
||||
Obě API podporují:
|
||||
|
||||
@@ -173,4 +173,4 @@ Kontaktujte nás na [[email protected]](mailto:[email protected]) nebo prozkou
|
||||
|
||||
Úplné podrobnosti implementace, ukázky kódu a referenci schématu najdete zde:
|
||||
|
||||
* [Dokumentace API](/l/cs/developers/extend/capabilities/apis)
|
||||
* [Dokumentace API](/l/cs/developers/api)
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ Open-source je základ našeho přístupu, zajišťuje, že Twenty se vyvíjí s
|
||||
* **Přehledy:** Sledujte výkon pomocí vlastních sestav a vizualizací. [Zobrazit přehledy](/l/cs/user-guide/dashboards/overview).
|
||||
* **Oprávnění a přístup:** Ovládejte, kdo může zobrazit, upravovat a spravovat vaše data pomocí oprávnění založených na rolích. [Nastavte přístup](/l/cs/user-guide/permissions-access/overview).
|
||||
* **Poznámky a úkoly:** Vytvářejte poznámky a úkoly propojené s vašimi záznamy pro lepší spolupráci.
|
||||
* **API & Webhooks:** Připojte se k dalším aplikacím a vytvářejte vlastní integrace. [Začněte integraci](/l/cs/developers/extend/capabilities/apis).
|
||||
* **API & Webhooks:** Připojte se k dalším aplikacím a vytvářejte vlastní integrace. [Začněte integraci](/l/cs/developers/api).
|
||||
|
||||
## Připojte se nyní
|
||||
|
||||
|
||||
+1
-1
@@ -95,7 +95,7 @@ Vytvořte cílová pole v **Nastavení → Datový model → Příležitosti**:
|
||||
* Velikost společnosti: `{{searchRecords[0].employees}}`
|
||||
|
||||
<Note>
|
||||
**Omezení pro Úkoly a Poznámky**: Relace u Úkolů a Poznámek jsou napevno nastaveny jako mnoho k mnoha a zatím nejsou k dispozici ve spouštěčích ani akcích pracovních postupů. Pro přístup k těmto relacím použijte místo toho [API](/l/cs/developers/extend/capabilities/apis).
|
||||
**Omezení pro Úkoly a Poznámky**: Relace u Úkolů a Poznámek jsou napevno nastaveny jako mnoho k mnoha a zatím nejsou k dispozici ve spouštěčích ani akcích pracovních postupů. Pro přístup k těmto relacím použijte místo toho [API](/l/cs/developers/api).
|
||||
</Note>
|
||||
|
||||
## Oboustranná synchronizace
|
||||
|
||||
@@ -15,7 +15,7 @@ Mit Apps können Sie Twenty-Anpassungen **als Code** erstellen und verwalten. An
|
||||
|
||||
* Benutzerdefinierte Objekte und Felder als Code definieren (verwaltetes Datenmodell)
|
||||
* Logikfunktionen mit benutzerdefinierten Triggern erstellen
|
||||
* Fähigkeiten für KI-Agenten definieren
|
||||
* Skills und Agenten für KI definieren
|
||||
* Dieselbe App in mehreren Workspaces bereitstellen
|
||||
|
||||
## Voraussetzungen
|
||||
@@ -39,7 +39,7 @@ yarn twenty app:dev
|
||||
Das Scaffolding-Tool unterstützt zwei Modi, um zu steuern, welche Beispieldateien enthalten sind:
|
||||
|
||||
```bash filename="Terminal"
|
||||
# Standard (umfassend): alle Beispiele (Objekt, Feld, Logikfunktion, Frontend-Komponente, View, Navigationsmenüeintrag, Skill)
|
||||
# Standard (umfassend): alle Beispiele (Objekt, Feld, Logikfunktion, Frontend-Komponente, View, Navigationsmenüeintrag, Skill, Agent)
|
||||
npx create-twenty-app@latest my-app
|
||||
|
||||
# Minimal: nur Kerndateien (application-config.ts und default-role.ts)
|
||||
@@ -96,27 +96,29 @@ my-twenty-app/
|
||||
.oxlintrc.json
|
||||
tsconfig.json
|
||||
README.md
|
||||
public/ # Public assets folder (images, fonts, etc.)
|
||||
public/ # Ordner für öffentliche Assets (Bilder, Schriftarten usw.)
|
||||
src/
|
||||
├── application-config.ts # Required - main application configuration
|
||||
├── application-config.ts # Erforderlich - Hauptkonfiguration der Anwendung
|
||||
├── roles/
|
||||
│ └── default-role.ts # Default role for logic functions
|
||||
│ └── default-role.ts # Standardrolle für Logikfunktionen
|
||||
├── objects/
|
||||
│ └── example-object.ts # Example custom object definition
|
||||
│ └── example-object.ts # Beispiel für eine benutzerdefinierte Objektdefinition
|
||||
├── fields/
|
||||
│ └── example-field.ts # Example standalone field definition
|
||||
│ └── example-field.ts # Beispiel für eine eigenständige Felddefinition
|
||||
├── logic-functions/
|
||||
│ ├── hello-world.ts # Example logic function
|
||||
│ ├── pre-install.ts # Pre-install logic function
|
||||
│ └── post-install.ts # Post-install logic function
|
||||
│ ├── hello-world.ts # Beispiel für eine Logikfunktion
|
||||
│ ├── pre-install.ts # Pre-Installations-Logikfunktion
|
||||
│ └── post-install.ts # Post-Installations-Logikfunktion
|
||||
├── front-components/
|
||||
│ └── hello-world.tsx # Example front component
|
||||
│ └── hello-world.tsx # Beispiel für eine Frontend-Komponente
|
||||
├── views/
|
||||
│ └── example-view.ts # Example saved view definition
|
||||
│ └── example-view.ts # Beispiel für eine gespeicherte View-Definition
|
||||
├── navigation-menu-items/
|
||||
│ └── example-navigation-menu-item.ts # Example sidebar navigation link
|
||||
└── skills/
|
||||
└── example-skill.ts # Example AI agent skill definition
|
||||
│ └── example-navigation-menu-item.ts # Beispiel für einen Navigationslink in der Seitenleiste
|
||||
├── skills/
|
||||
│ └── example-skill.ts # Beispiel für eine Skill-Definition eines KI-Agenten
|
||||
└── agents/
|
||||
└── example-agent.ts # Beispiel für eine KI-Agenten-Definition
|
||||
```
|
||||
|
||||
Mit `--minimal` werden nur die Kerndateien erstellt (`application-config.ts`, `roles/default-role.ts`, `logic-functions/pre-install.ts` und `logic-functions/post-install.ts`).
|
||||
@@ -148,6 +150,7 @@ Das SDK erkennt Entitäten, indem es Ihre TypeScript-Dateien nach Aufrufen von *
|
||||
| `defineView()` | Gespeicherte View-Definitionen |
|
||||
| `defineNavigationMenuItem()` | Definitionen von Navigationsmenüeinträgen |
|
||||
| `defineSkill()` | Skill-Definitionen für KI-Agenten |
|
||||
| `defineAgent()` | KI-Agenten-Definitionen |
|
||||
|
||||
<Note>
|
||||
**Dateibenennung ist flexibel.** Die Entitätserkennung ist AST-basiert — das SDK durchsucht Ihre Quelldateien nach dem Muster `export default define<Entity>({...})`. Sie können Ihre Dateien und Ordner nach Belieben organisieren. Die Gruppierung nach Entitätstyp (z. B. `logic-functions/`, `roles/`) ist lediglich eine Konvention zur Codeorganisation, keine Voraussetzung.
|
||||
@@ -225,6 +228,7 @@ Das SDK stellt Hilfsfunktionen bereit, um die Entitäten Ihrer App zu definieren
|
||||
| `defineView()` | Gespeicherte Views für Objekte definieren |
|
||||
| `defineNavigationMenuItem()` | Seitenleisten-Navigationslinks definieren |
|
||||
| `defineSkill()` | Definieren Sie Skills für KI-Agenten |
|
||||
| `defineAgent()` | Define AI agents with system prompts |
|
||||
|
||||
Diese Funktionen validieren Ihre Konfiguration zur Build-Zeit und bieten IDE-Autovervollständigung sowie Typsicherheit.
|
||||
|
||||
@@ -802,6 +806,41 @@ Sie können neue Skills auf zwei Arten erstellen:
|
||||
* **Generiert**: Führen Sie `yarn twenty entity:add` aus und wählen Sie die Option zum Hinzufügen eines neuen Skills.
|
||||
* **Manuell**: Erstellen Sie eine neue Datei und verwenden Sie `defineSkill()` nach demselben Muster.
|
||||
|
||||
### Agenten
|
||||
|
||||
Agents define AI agents with system prompts that can operate within your workspace. Use `defineAgent()` to define agents with built-in validation:
|
||||
|
||||
```typescript
|
||||
// src/agents/example-agent.ts
|
||||
import { defineAgent } from 'twenty-sdk';
|
||||
|
||||
export default defineAgent({
|
||||
universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
|
||||
name: 'sales-assistant',
|
||||
label: 'Sales Assistant',
|
||||
description: 'An AI agent that helps with sales tasks',
|
||||
icon: 'IconRobot',
|
||||
prompt: `You are a sales assistant. Help users with:
|
||||
1. Researching prospects and companies
|
||||
2. Drafting personalized outreach messages
|
||||
3. Tracking follow-ups and next steps
|
||||
4. Analyzing deal pipeline and suggesting actions`,
|
||||
});
|
||||
```
|
||||
|
||||
Hauptpunkte:
|
||||
|
||||
* `name` is a unique identifier string for the agent (kebab-case recommended).
|
||||
* `label` ist der menschenlesbare Anzeigename, der in der UI angezeigt wird.
|
||||
* `prompt` contains the system prompt — this is the instruction text that defines the agent's behavior.
|
||||
* `icon` (optional) legt das in der UI angezeigte Symbol fest.
|
||||
* `description` (optional) provides additional context about the agent's purpose.
|
||||
|
||||
You can create new agents in two ways:
|
||||
|
||||
* **Scaffolded**: Run `yarn twenty entity:add` and choose the option to add a new agent.
|
||||
* **Manual**: Create a new file and use `defineAgent()`, following the same pattern.
|
||||
|
||||
### Generierte typisierte Clients
|
||||
|
||||
Zwei typisierte Clients werden von `yarn twenty app:dev` automatisch generiert und basierend auf Ihrem Arbeitsbereichs-Schema in `node_modules/twenty-sdk/generated` gespeichert:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
title: Erweitern
|
||||
description: Erweitern Sie die Funktionalität von Twenty mit APIs, Webhooks und benutzerdefinierten Apps.
|
||||
redirect: /developers/introduction
|
||||
---
|
||||
|
||||
<Frame>
|
||||
@@ -20,13 +21,13 @@ Twenty ist darauf ausgelegt, erweiterbar zu sein. Verwenden Sie unsere APIs, Web
|
||||
## Erste Schritte
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="APIs" icon="code" href="/l/de/developers/extend/capabilities/apis">
|
||||
<Card title="APIs" icon="code" href="/l/de/developers/api">
|
||||
Verbinden Sie sich programmgesteuert mit Twenty
|
||||
</Card>
|
||||
<Card title="Webhooks" icon="bell" href="/l/de/developers/extend/capabilities/webhooks">
|
||||
<Card title="Webhooks" icon="bell" href="/l/de/developers/webhooks">
|
||||
Erhalten Sie Benachrichtigungen über Ereignisse in Echtzeit
|
||||
</Card>
|
||||
<Card title="Apps" icon="puzzle-piece" href="/l/de/developers/extend/capabilities/apps">
|
||||
<Card title="Apps" icon="puzzle-piece" href="/l/de/developers/apps/apps">
|
||||
Erstellen Sie Anpassungen als Code (Alpha)
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@@ -5,18 +5,28 @@ description: Willkommen in der Twenty-Entwicklerdokumentation, Ihren Ressourcen
|
||||
|
||||
import { CardTitle } from "/snippets/card-title.mdx"
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card href="/l/de/developers/extend/extend" img="/images/user-guide/integrations/plug.png">
|
||||
<CardTitle>Erweitern</CardTitle>
|
||||
Erstellen Sie Integrationen mit APIs, Webhooks und benutzerdefinierten Apps.
|
||||
<CardGroup cols={2}>
|
||||
<Card href="/l/de/developers/api" icon="code">
|
||||
<CardTitle>API</CardTitle>
|
||||
Abfragen und modifizieren Sie Ihre CRM-Daten mit REST oder GraphQL.
|
||||
</Card>
|
||||
|
||||
<Card href="/l/de/developers/self-host/self-host" img="/images/user-guide/what-is-twenty/20.png">
|
||||
<Card href="/l/de/developers/webhooks" icon="bell">
|
||||
<CardTitle>Webhooks</CardTitle>
|
||||
Erhalten Sie Echtzeit-Benachrichtigungen bei Ereignissen.
|
||||
</Card>
|
||||
|
||||
<Card href="/l/de/developers/apps/apps" icon="puzzle-piece">
|
||||
<CardTitle>Apps</CardTitle>
|
||||
Erstellen Sie benutzerdefinierte Anwendungen, die die Möglichkeiten von Twenty erweitern.
|
||||
</Card>
|
||||
|
||||
<Card href="/l/de/developers/self-host/self-host" icon="desktop">
|
||||
<CardTitle>Selbst hosten</CardTitle>
|
||||
Stellen Sie Twenty auf Ihrer eigenen Infrastruktur bereit und verwalten Sie es.
|
||||
</Card>
|
||||
|
||||
<Card href="/l/de/developers/contribute/contribute" img="/images/user-guide/github/github-header.png">
|
||||
<Card href="/l/de/developers/contribute/contribute" icon="github">
|
||||
<CardTitle>Mitwirken</CardTitle>
|
||||
Treten Sie unserer Open-Source-Community bei und tragen Sie zu Twenty bei.
|
||||
</Card>
|
||||
|
||||
@@ -24,7 +24,7 @@ Exportieren Sie die Daten Ihres Arbeitsbereichs als CSV für Backups, Berichte o
|
||||
* Nur **sichtbare Spalten** werden exportiert
|
||||
* Nur **gefilterte Datensätze** werden exportiert (basierend auf Ihrer aktuellen Ansicht)
|
||||
|
||||
<Note>Für größere Exporte (mehr als 20.000 Datensätze) verwenden Sie Filter, um stapelweise zu exportieren, oder nutzen Sie die [API](/l/de/developers/extend/capabilities/apis).</Note>
|
||||
<Note>Für größere Exporte (mehr als 20.000 Datensätze) verwenden Sie Filter, um stapelweise zu exportieren, oder nutzen Sie die [API](/l/de/developers/api).</Note>
|
||||
|
||||
### Berechtigungen
|
||||
|
||||
@@ -148,7 +148,7 @@ Die API hat kein Datensatzlimit:
|
||||
2. Verwenden Sie die GraphQL-API, um Datensätze abzufragen
|
||||
3. Verarbeiten Sie die Ergebnisse in Ihrer Anwendung
|
||||
|
||||
Siehe: [API-Dokumentation](/l/de/developers/extend/capabilities/apis)
|
||||
Siehe: [API-Dokumentation](/l/de/developers/api)
|
||||
|
||||
## Tipps und Best Practices
|
||||
|
||||
@@ -206,4 +206,4 @@ Exportierte Dateien können sensible Daten enthalten:
|
||||
|
||||
* [So aktualisieren Sie vorhandene Datensätze](/l/de/user-guide/data-migration/how-tos/update-existing-records-via-import) — bearbeiten Sie Ihren Export und importieren Sie ihn erneut
|
||||
* [So importieren Sie Daten über die API](/l/de/user-guide/data-migration/how-tos/import-data-via-api) — für große Datensätze
|
||||
* [API-Dokumentation](/l/de/developers/extend/capabilities/apis) — erstellen Sie benutzerdefinierte Export-Workflows
|
||||
* [API-Dokumentation](/l/de/developers/api) — erstellen Sie benutzerdefinierte Export-Workflows
|
||||
|
||||
@@ -59,8 +59,8 @@ Twenty unterstützt zwei API-Typen:
|
||||
|
||||
| API | Am besten geeignet für | Dokumentation |
|
||||
| ----------- | ---------------------------------------------------------------- | --------------------------------------------------------- |
|
||||
| **GraphQL** | Flexible Abfragen, Abruf verknüpfter Daten, komplexe Operationen | [API-Dokumentation](/l/de/developers/extend/capabilities/apis) |
|
||||
| **REST** | Einfache CRUD-Operationen, vertraute REST-Muster | [API-Dokumentation](/l/de/developers/extend/capabilities/apis) |
|
||||
| **GraphQL** | Flexible Abfragen, Abruf verknüpfter Daten, komplexe Operationen | [API-Dokumentation](/l/de/developers/api) |
|
||||
| **REST** | Einfache CRUD-Operationen, vertraute REST-Muster | [API-Dokumentation](/l/de/developers/api) |
|
||||
|
||||
Beide APIs unterstützen:
|
||||
|
||||
@@ -173,4 +173,4 @@ Kontaktieren Sie uns unter [[email protected]](mailto:[email protected]) oder
|
||||
|
||||
Für vollständige Implementierungsdetails, Codebeispiele und Schema-Referenz:
|
||||
|
||||
* [API-Dokumentation](/l/de/developers/extend/capabilities/apis)
|
||||
* [API-Dokumentation](/l/de/developers/api)
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ Open-Source ist das Fundament unseres Ansatzes, das sicherstellt, dass Twenty si
|
||||
* **Dashboards:** Verfolgen Sie die Leistung mit benutzerdefinierten Berichten und Visualisierungen. [Dashboards anzeigen](/l/de/user-guide/dashboards/overview).
|
||||
* **Berechtigungen & Zugriff:** Steuern Sie mithilfe rollenbasierter Berechtigungen, wer Ihre Daten anzeigen, bearbeiten und verwalten kann. [Zugriff konfigurieren](/l/de/user-guide/permissions-access/overview).
|
||||
* **Notizen & Aufgaben:** Erstellen Sie Notizen und Aufgaben, die mit Ihren Datensätzen verknüpft sind, für eine bessere Zusammenarbeit.
|
||||
* **API & Webhooks:** Verbinden Sie sich mit anderen Apps und erstellen Sie benutzerdefinierte Integrationen. [Integration starten](/l/de/developers/extend/capabilities/apis).
|
||||
* **API & Webhooks:** Verbinden Sie sich mit anderen Apps und erstellen Sie benutzerdefinierte Integrationen. [Integration starten](/l/de/developers/api).
|
||||
|
||||
## Jetzt beitreten
|
||||
|
||||
|
||||
+1
-1
@@ -95,7 +95,7 @@ Erstellen Sie die Zielfelder in **Settings → Data Model → Opportunities**:
|
||||
* Unternehmensgröße: `{{searchRecords[0].employees}}`
|
||||
|
||||
<Note>
|
||||
**Einschränkung bei Aufgaben und Notizen**: Beziehungen bei Aufgaben und Notizen sind fest als Viele-zu-Viele implementiert und stehen in Workflow-Auslösern oder -Aktionen noch nicht zur Verfügung. Um auf diese Beziehungen zuzugreifen, verwenden Sie stattdessen die [API](/l/de/developers/extend/capabilities/apis).
|
||||
**Einschränkung bei Aufgaben und Notizen**: Beziehungen bei Aufgaben und Notizen sind fest als Viele-zu-Viele implementiert und stehen in Workflow-Auslösern oder -Aktionen noch nicht zur Verfügung. Um auf diese Beziehungen zuzugreifen, verwenden Sie stattdessen die [API](/l/de/developers/api).
|
||||
</Note>
|
||||
|
||||
## Bidirektionale Synchronisierung
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
title: Ampliar
|
||||
description: Amplía la funcionalidad de Twenty con APIs, webhooks y aplicaciones personalizadas.
|
||||
redirect: /developers/introduction
|
||||
---
|
||||
|
||||
<Frame>
|
||||
@@ -20,15 +21,15 @@ Twenty está diseñado para ser extensible. Usa nuestras APIs, webhooks y el fra
|
||||
## Primeros pasos
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="APIs" icon="código" href="/l/es/developers/extend/capabilities/apis">
|
||||
<Card title="APIs" icon="código" href="/l/es/developers/api">
|
||||
Conéctate a Twenty de forma programática
|
||||
</Card>
|
||||
|
||||
<Card title="Webhooks" icon="bell" href="/l/es/developers/extend/capabilities/webhooks">
|
||||
<Card title="Webhooks" icon="bell" href="/l/es/developers/webhooks">
|
||||
Recibe notificaciones de eventos en tiempo real
|
||||
</Card>
|
||||
|
||||
<Card title="Aplicaciones" icon="puzzle-piece" href="/l/es/developers/extend/capabilities/apps">
|
||||
<Card title="Aplicaciones" icon="puzzle-piece" href="/l/es/developers/apps/apps">
|
||||
Crea personalizaciones como código (Alpha)
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@@ -5,18 +5,28 @@ description: Bienvenido a la documentación para desarrolladores de Twenty, tus
|
||||
|
||||
import { CardTitle } from "/snippets/card-title.mdx"
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card href="/l/es/developers/extend/extend" img="/images/user-guide/integrations/plug.png">
|
||||
<CardTitle>Ampliar</CardTitle>
|
||||
Crea integraciones con APIs, webhooks y aplicaciones personalizadas.
|
||||
<CardGroup cols={2}>
|
||||
<Card href="/l/es/developers/api" icon="code">
|
||||
<CardTitle>API</CardTitle>
|
||||
Consulta y modifica los datos de tu CRM con REST o GraphQL.
|
||||
</Card>
|
||||
|
||||
<Card href="/l/es/developers/self-host/self-host" img="/images/user-guide/what-is-twenty/20.png">
|
||||
<Card href="/l/es/developers/webhooks" icon="bell">
|
||||
<CardTitle>Webhooks</CardTitle>
|
||||
Recibe notificaciones en tiempo real cuando ocurran eventos.
|
||||
</Card>
|
||||
|
||||
<Card href="/l/es/developers/apps/apps" icon="puzzle-piece">
|
||||
<CardTitle>Apps</CardTitle>
|
||||
Crea aplicaciones personalizadas que amplíen las capacidades de Twenty.
|
||||
</Card>
|
||||
|
||||
<Card href="/l/es/developers/self-host/self-host" icon="desktop">
|
||||
<CardTitle>Autoalojar</CardTitle>
|
||||
Despliega y administra Twenty en tu propia infraestructura.
|
||||
</Card>
|
||||
|
||||
<Card href="/l/es/developers/contribute/contribute" img="/images/user-guide/github/github-header.png">
|
||||
<Card href="/l/es/developers/contribute/contribute" icon="github">
|
||||
<CardTitle>Contribuir</CardTitle>
|
||||
Únete a nuestra comunidad de código abierto y contribuye a Twenty.
|
||||
</Card>
|
||||
|
||||
@@ -24,7 +24,7 @@ Exporta los datos de tu espacio de trabajo a CSV para copias de seguridad, infor
|
||||
* Solo se exportan las **columnas visibles**
|
||||
* Solo se exportan los **registros filtrados** (según tu vista actual)
|
||||
|
||||
<Note>Para exportaciones más grandes (más de 20.000 registros), usa filtros para exportar por lotes o usa la [API](/l/es/developers/extend/capabilities/apis).</Note>
|
||||
<Note>Para exportaciones más grandes (más de 20.000 registros), usa filtros para exportar por lotes o usa la [API](/l/es/developers/api).</Note>
|
||||
|
||||
### Permisos
|
||||
|
||||
@@ -148,7 +148,7 @@ La API no tiene límite de registros:
|
||||
2. Usa la API de GraphQL para consultar registros
|
||||
3. Procesa los resultados en tu aplicación
|
||||
|
||||
Consulta: [Documentación de la API](/l/es/developers/extend/capabilities/apis)
|
||||
Consulta: [Documentación de la API](/l/es/developers/api)
|
||||
|
||||
## Consejos y mejores prácticas
|
||||
|
||||
@@ -206,4 +206,4 @@ Los archivos exportados pueden contener datos sensibles:
|
||||
|
||||
* [Cómo actualizar registros existentes](/l/es/user-guide/data-migration/how-tos/update-existing-records-via-import) — edita y vuelve a importar tu exportación
|
||||
* [Cómo importar datos mediante la API](/l/es/user-guide/data-migration/how-tos/import-data-via-api) — para conjuntos de datos grandes
|
||||
* [Documentación de la API](/l/es/developers/extend/capabilities/apis) — crea flujos de trabajo de exportación personalizados
|
||||
* [Documentación de la API](/l/es/developers/api) — crea flujos de trabajo de exportación personalizados
|
||||
|
||||
@@ -59,8 +59,8 @@ Twenty admite dos tipos de API:
|
||||
|
||||
| API | Ideal para | Documentación |
|
||||
| ----------- | --------------------------------------------------------------------------- | --------------------------------------------------------------- |
|
||||
| **GraphQL** | Consultas flexibles, obtención de datos relacionados, operaciones complejas | [Documentación de la API](/l/es/developers/extend/capabilities/apis) |
|
||||
| **REST** | Operaciones CRUD simples, patrones REST familiares | [Documentación de la API](/l/es/developers/extend/capabilities/apis) |
|
||||
| **GraphQL** | Consultas flexibles, obtención de datos relacionados, operaciones complejas | [Documentación de la API](/l/es/developers/api) |
|
||||
| **REST** | Operaciones CRUD simples, patrones REST familiares | [Documentación de la API](/l/es/developers/api) |
|
||||
|
||||
Ambas APIs admiten:
|
||||
|
||||
@@ -173,4 +173,4 @@ Contáctanos en [[email protected]](mailto:[email protected]) o explora nuestr
|
||||
|
||||
Para conocer todos los detalles de implementación, ejemplos de código y referencia de esquemas:
|
||||
|
||||
* [Documentación de la API](/l/es/developers/extend/capabilities/apis)
|
||||
* [Documentación de la API](/l/es/developers/api)
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ El código abierto es la base de nuestro enfoque, asegurando que Twenty evolucio
|
||||
* **Tableros:** Rastree el rendimiento con informes y visualizaciones personalizadas. [Ver tableros](/l/es/user-guide/dashboards/overview).
|
||||
* **Permisos y acceso:** Controle quién puede ver, editar y administrar sus datos con permisos basados en roles. [Configurar el acceso](/l/es/user-guide/permissions-access/overview).
|
||||
* **Notas y tareas:** Cree notas y tareas vinculadas a sus registros para una mejor colaboración.
|
||||
* **API y Webhooks:** Conéctese con otras aplicaciones y cree integraciones personalizadas. [Comienza a integrar](/l/es/developers/extend/capabilities/apis).
|
||||
* **API y Webhooks:** Conéctese con otras aplicaciones y cree integraciones personalizadas. [Comienza a integrar](/l/es/developers/api).
|
||||
|
||||
## Únete ahora
|
||||
|
||||
|
||||
+1
-1
@@ -95,7 +95,7 @@ Crea los campos de destino en **Configuración → Modelo de datos → Oportunid
|
||||
* Tamaño de la empresa: `{{searchRecords[0].employees}}`
|
||||
|
||||
<Note>
|
||||
**Limitación de Tareas y Notas**: Las relaciones en Tareas y Notas están codificadas como de muchos a muchos y aún no están disponibles en los desencadenantes o acciones de flujos de trabajo. Para acceder a estas relaciones, usa la [API](/l/es/developers/extend/capabilities/apis).
|
||||
**Limitación de Tareas y Notas**: Las relaciones en Tareas y Notas están codificadas como de muchos a muchos y aún no están disponibles en los desencadenantes o acciones de flujos de trabajo. Para acceder a estas relaciones, usa la [API](/l/es/developers/api).
|
||||
</Note>
|
||||
|
||||
## Sincronización bidireccional
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
title: Étendre
|
||||
description: Étendez les fonctionnalités de Twenty avec des API, des webhooks et des applications personnalisées.
|
||||
redirect: /developers/introduction
|
||||
---
|
||||
|
||||
<Frame>
|
||||
@@ -20,15 +21,15 @@ Twenty est conçu pour être extensible. Utilisez nos API, nos webhooks et notre
|
||||
## Prise en main
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="API" icon="code" href="/l/fr/developers/extend/capabilities/apis">
|
||||
<Card title="API" icon="code" href="/l/fr/developers/api">
|
||||
Connectez-vous à Twenty par programmation
|
||||
</Card>
|
||||
|
||||
<Card title="Webhooks" icon="bell" href="/l/fr/developers/extend/capabilities/webhooks">
|
||||
<Card title="Webhooks" icon="bell" href="/l/fr/developers/webhooks">
|
||||
Recevez des notifications d'événements en temps réel
|
||||
</Card>
|
||||
|
||||
<Card title="Applications" icon="puzzle-piece" href="/l/fr/developers/extend/capabilities/apps">
|
||||
<Card title="Applications" icon="puzzle-piece" href="/l/fr/developers/apps/apps">
|
||||
Créez des personnalisations sous forme de code (Alpha)
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@@ -5,18 +5,28 @@ description: Bienvenue dans la documentation pour développeurs de Twenty, vos r
|
||||
|
||||
import { CardTitle } from "/snippets/card-title.mdx"
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card href="/l/fr/developers/extend/extend" img="/images/user-guide/integrations/plug.png">
|
||||
<CardTitle>Étendre</CardTitle>
|
||||
Créez des intégrations avec des API, des webhooks et des applications personnalisées.
|
||||
<CardGroup cols={2}>
|
||||
<Card href="/l/fr/developers/api" icon="code">
|
||||
<CardTitle>API</CardTitle>
|
||||
Interrogez et modifiez vos données CRM avec REST ou GraphQL.
|
||||
</Card>
|
||||
|
||||
<Card href="/l/fr/developers/self-host/self-host" img="/images/user-guide/what-is-twenty/20.png">
|
||||
<Card href="/l/fr/developers/webhooks" icon="bell">
|
||||
<CardTitle>Webhooks</CardTitle>
|
||||
Recevez des notifications en temps réel lors d'événements.
|
||||
</Card>
|
||||
|
||||
<Card href="/l/fr/developers/apps/apps" icon="puzzle-piece">
|
||||
<CardTitle>Apps</CardTitle>
|
||||
Créez des applications personnalisées qui étendent les capacités de Twenty.
|
||||
</Card>
|
||||
|
||||
<Card href="/l/fr/developers/self-host/self-host" icon="desktop">
|
||||
<CardTitle>Auto-héberger</CardTitle>
|
||||
Déployez et gérez Twenty sur votre propre infrastructure.
|
||||
</Card>
|
||||
|
||||
<Card href="/l/fr/developers/contribute/contribute" img="/images/user-guide/github/github-header.png">
|
||||
<Card href="/l/fr/developers/contribute/contribute" icon="github">
|
||||
<CardTitle>Contribuer</CardTitle>
|
||||
Rejoignez notre communauté open source et contribuez à Twenty.
|
||||
</Card>
|
||||
|
||||
@@ -24,7 +24,7 @@ Exportez les données de votre espace de travail en CSV pour des sauvegardes, de
|
||||
* Seules les **colonnes visibles** sont exportées
|
||||
* Seuls les **enregistrements filtrés** sont exportés (selon votre vue actuelle)
|
||||
|
||||
<Note>Pour des exports plus volumineux (plus de 20 000 enregistrements), utilisez des filtres pour exporter par lots ou utilisez l'[API](/l/fr/developers/extend/capabilities/apis).</Note>
|
||||
<Note>Pour des exports plus volumineux (plus de 20 000 enregistrements), utilisez des filtres pour exporter par lots ou utilisez l'[API](/l/fr/developers/api).</Note>
|
||||
|
||||
### Autorisations
|
||||
|
||||
@@ -148,7 +148,7 @@ L'API n'a pas de limite d'enregistrements :
|
||||
2. Utilisez l'API GraphQL pour interroger les enregistrements
|
||||
3. Traitez les résultats dans votre application
|
||||
|
||||
Voir : [Documentation de l'API](/l/fr/developers/extend/capabilities/apis)
|
||||
Voir : [Documentation de l'API](/l/fr/developers/api)
|
||||
|
||||
## Conseils et bonnes pratiques
|
||||
|
||||
@@ -206,4 +206,4 @@ Les fichiers exportés peuvent contenir des données sensibles :
|
||||
|
||||
* [Comment mettre à jour des enregistrements existants](/l/fr/user-guide/data-migration/how-tos/update-existing-records-via-import) — modifiez et réimportez votre export
|
||||
* [Comment importer des données via l'API](/l/fr/user-guide/data-migration/how-tos/import-data-via-api) — pour de grands jeux de données
|
||||
* [Documentation de l'API](/l/fr/developers/extend/capabilities/apis) — créez des flux de travail d'exportation personnalisés
|
||||
* [Documentation de l'API](/l/fr/developers/api) — créez des flux de travail d'exportation personnalisés
|
||||
|
||||
@@ -59,8 +59,8 @@ Twenty prend en charge deux types d'API :
|
||||
|
||||
| API | Idéal pour | Documentation |
|
||||
| ----------- | ----------------------------------------------------------------------- | -------------------------------------------------------------- |
|
||||
| **GraphQL** | Requêtes flexibles, récupération de données liées, opérations complexes | [Documentation de l'API](/l/fr/developers/extend/capabilities/apis) |
|
||||
| **REST** | Opérations CRUD simples, modèles REST familiers | [Documentation de l'API](/l/fr/developers/extend/capabilities/apis) |
|
||||
| **GraphQL** | Requêtes flexibles, récupération de données liées, opérations complexes | [Documentation de l'API](/l/fr/developers/api) |
|
||||
| **REST** | Opérations CRUD simples, modèles REST familiers | [Documentation de l'API](/l/fr/developers/api) |
|
||||
|
||||
Les deux API prennent en charge :
|
||||
|
||||
@@ -173,4 +173,4 @@ Contactez-nous à [[email protected]](mailto:[email protected]) ou découvrez
|
||||
|
||||
Pour les détails complets de mise en œuvre, des exemples de code et la référence du schéma :
|
||||
|
||||
* [Documentation de l'API](/l/fr/developers/extend/capabilities/apis)
|
||||
* [Documentation de l'API](/l/fr/developers/api)
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ L'open-source est la pierre angulaire de notre approche, garantissant que Twenty
|
||||
* **Tableaux de bord :** Suivez les performances grâce à des rapports et des visualisations personnalisés. [Voir les tableaux de bord](/l/fr/user-guide/dashboards/overview).
|
||||
* **Autorisations et accès :** Contrôlez qui peut voir, modifier et gérer vos données grâce à des autorisations basées sur les rôles. [Configurer l'accès](/l/fr/user-guide/permissions-access/overview).
|
||||
* **Notes et tâches :** Créez des notes et des tâches liées à vos enregistrements pour une meilleure collaboration.
|
||||
* **API & Webhooks :** Connectez-vous à d'autres applications et créez des intégrations personnalisées. [Commencez l'intégration](/l/fr/developers/extend/capabilities/apis).
|
||||
* **API & Webhooks :** Connectez-vous à d'autres applications et créez des intégrations personnalisées. [Commencez l'intégration](/l/fr/developers/api).
|
||||
|
||||
## Rejoignez maintenant
|
||||
|
||||
|
||||
+1
-1
@@ -95,7 +95,7 @@ Créez les champs de destination dans **Paramètres → Modèle de données →
|
||||
* Taille de l'entreprise : `{{searchRecords[0].employees}}`
|
||||
|
||||
<Note>
|
||||
**Limitation concernant les tâches et les notes** : Les relations sur les tâches et les notes sont codées en dur en plusieurs-à-plusieurs et ne sont pas encore disponibles dans les déclencheurs ou actions de workflows. Pour accéder à ces relations, utilisez plutôt l'[API](/l/fr/developers/extend/capabilities/apis).
|
||||
**Limitation concernant les tâches et les notes** : Les relations sur les tâches et les notes sont codées en dur en plusieurs-à-plusieurs et ne sont pas encore disponibles dans les déclencheurs ou actions de workflows. Pour accéder à ces relations, utilisez plutôt l'[API](/l/fr/developers/api).
|
||||
</Note>
|
||||
|
||||
## Synchronisation bidirectionnelle
|
||||
|
||||
@@ -15,7 +15,7 @@ Le app ti consentono di creare e gestire le personalizzazioni di Twenty **come c
|
||||
|
||||
* Definisci oggetti e campi personalizzati come codice (modello dati gestito)
|
||||
* Crea funzioni logiche con trigger personalizzati
|
||||
* Definire le abilità per gli agenti IA
|
||||
* Definire skill e agenti per l'IA
|
||||
* Distribuisci la stessa app su più spazi di lavoro
|
||||
|
||||
## Prerequisiti
|
||||
@@ -39,7 +39,7 @@ yarn twenty app:dev
|
||||
Lo strumento di scaffolding supporta due modalità per controllare quali file di esempio vengono inclusi:
|
||||
|
||||
```bash filename="Terminal"
|
||||
# Predefinita (esaustiva): tutti gli esempi (oggetto, campo, funzione logica, componente front-end, vista, voce del menu di navigazione, skill)
|
||||
# Predefinita (esaustiva): tutti gli esempi (oggetto, campo, funzione logica, componente front-end, vista, voce del menu di navigazione, skill, agente)
|
||||
npx create-twenty-app@latest my-app
|
||||
|
||||
# Minimale: solo i file principali (application-config.ts e default-role.ts)
|
||||
@@ -96,27 +96,29 @@ my-twenty-app/
|
||||
.oxlintrc.json
|
||||
tsconfig.json
|
||||
README.md
|
||||
public/ # Public assets folder (images, fonts, etc.)
|
||||
public/ # Cartella delle risorse pubbliche (immagini, font, ecc.)
|
||||
src/
|
||||
├── application-config.ts # Required - main application configuration
|
||||
├── application-config.ts # Obbligatorio - configurazione principale dell'applicazione
|
||||
├── roles/
|
||||
│ └── default-role.ts # Default role for logic functions
|
||||
│ └── default-role.ts # Ruolo predefinito per le funzioni logiche
|
||||
├── objects/
|
||||
│ └── example-object.ts # Example custom object definition
|
||||
│ └── example-object.ts # Definizione di oggetto personalizzato di esempio
|
||||
├── fields/
|
||||
│ └── example-field.ts # Example standalone field definition
|
||||
│ └── example-field.ts # Definizione di campo autonomo di esempio
|
||||
├── logic-functions/
|
||||
│ ├── hello-world.ts # Example logic function
|
||||
│ ├── pre-install.ts # Pre-install logic function
|
||||
│ └── post-install.ts # Post-install logic function
|
||||
│ ├── hello-world.ts # Funzione logica di esempio
|
||||
│ ├── pre-install.ts # Funzione logica di pre-installazione
|
||||
│ └── post-install.ts # Funzione logica di post-installazione
|
||||
├── front-components/
|
||||
│ └── hello-world.tsx # Example front component
|
||||
│ └── hello-world.tsx # Componente front-end di esempio
|
||||
├── views/
|
||||
│ └── example-view.ts # Example saved view definition
|
||||
│ └── example-view.ts # Definizione di vista salvata di esempio
|
||||
├── navigation-menu-items/
|
||||
│ └── example-navigation-menu-item.ts # Example sidebar navigation link
|
||||
└── skills/
|
||||
└── example-skill.ts # Example AI agent skill definition
|
||||
│ └── example-navigation-menu-item.ts # Link di navigazione della barra laterale di esempio
|
||||
├── skills/
|
||||
│ └── example-skill.ts # Definizione di skill per agente IA di esempio
|
||||
└── agents/
|
||||
└── example-agent.ts # Definizione di agente IA di esempio
|
||||
```
|
||||
|
||||
Con `--minimal`, vengono creati solo i file principali (`application-config.ts`, `roles/default-role.ts`, `logic-functions/pre-install.ts` e `logic-functions/post-install.ts`).
|
||||
@@ -148,6 +150,7 @@ L'SDK rileva le entità analizzando i tuoi file TypeScript alla ricerca di chiam
|
||||
| `defineView()` | Definizioni di viste salvate |
|
||||
| `defineNavigationMenuItem()` | Definizioni delle voci del menu di navigazione |
|
||||
| `defineSkill()` | AI agent skill definitions |
|
||||
| `defineAgent()` | Definizioni di agenti IA |
|
||||
|
||||
<Note>
|
||||
**La denominazione dei file è flessibile.** Il rilevamento delle entità è basato sull'AST — l'SDK esegue la scansione dei file sorgente alla ricerca del pattern `export default define<Entity>({...})`. Puoi organizzare file e cartelle come preferisci. Raggruppare per tipo di entità (ad es., `logic-functions/`, `roles/`) è solo una convenzione per l'organizzazione del codice, non un requisito.
|
||||
@@ -225,6 +228,7 @@ L'SDK fornisce funzioni helper per definire le entità della tua app. Come descr
|
||||
| `defineView()` | Definisce viste salvate per gli oggetti |
|
||||
| `defineNavigationMenuItem()` | Definisce i link di navigazione della barra laterale |
|
||||
| `defineSkill()` | Define AI agent skills |
|
||||
| `defineAgent()` | Define AI agents with system prompts |
|
||||
|
||||
Queste funzioni convalidano la configurazione in fase di build e offrono il completamento automatico nell'IDE e la sicurezza dei tipi.
|
||||
|
||||
@@ -802,6 +806,41 @@ You can create new skills in two ways:
|
||||
* **Scaffolded**: Run `yarn twenty entity:add` and choose the option to add a new skill.
|
||||
* **Manual**: Create a new file and use `defineSkill()`, following the same pattern.
|
||||
|
||||
### Agenti
|
||||
|
||||
Agents define AI agents with system prompts that can operate within your workspace. Use `defineAgent()` to define agents with built-in validation:
|
||||
|
||||
```typescript
|
||||
// src/agents/example-agent.ts
|
||||
import { defineAgent } from 'twenty-sdk';
|
||||
|
||||
export default defineAgent({
|
||||
universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
|
||||
name: 'sales-assistant',
|
||||
label: 'Sales Assistant',
|
||||
description: 'An AI agent that helps with sales tasks',
|
||||
icon: 'IconRobot',
|
||||
prompt: `You are a sales assistant. Help users with:
|
||||
1. Researching prospects and companies
|
||||
2. Drafting personalized outreach messages
|
||||
3. Tracking follow-ups and next steps
|
||||
4. Analyzing deal pipeline and suggesting actions`,
|
||||
});
|
||||
```
|
||||
|
||||
Punti chiave:
|
||||
|
||||
* `name` is a unique identifier string for the agent (kebab-case recommended).
|
||||
* `label` is the human-readable display name shown in the UI.
|
||||
* `prompt` contains the system prompt — this is the instruction text that defines the agent's behavior.
|
||||
* `icon` (optional) sets the icon displayed in the UI.
|
||||
* `description` (optional) provides additional context about the agent's purpose.
|
||||
|
||||
You can create new agents in two ways:
|
||||
|
||||
* **Scaffolded**: Run `yarn twenty entity:add` and choose the option to add a new agent.
|
||||
* **Manual**: Create a new file and use `defineAgent()`, following the same pattern.
|
||||
|
||||
### Client tipizzati generati
|
||||
|
||||
Due client tipizzati sono generati automaticamente da `yarn twenty app:dev` e salvati in `node_modules/twenty-sdk/generated` in base allo schema della tua area di lavoro:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
title: Estendi
|
||||
description: Estendi le funzionalità di Twenty con API, webhook e app personalizzate.
|
||||
redirect: /developers/introduction
|
||||
---
|
||||
|
||||
<Frame>
|
||||
@@ -20,13 +21,13 @@ Twenty è progettato per essere estensibile. Usa le nostre API, i webhook e il f
|
||||
## Per iniziare
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="API" icon="codice" href="/l/it/developers/extend/capabilities/apis">
|
||||
<Card title="API" icon="codice" href="/l/it/developers/api">
|
||||
Connettiti a Twenty in modo programmatico
|
||||
</Card>
|
||||
<Card title="Webhooks" icon="bell" href="/l/it/developers/extend/capabilities/webhooks">
|
||||
<Card title="Webhooks" icon="bell" href="/l/it/developers/webhooks">
|
||||
Ricevi notifiche sugli eventi in tempo reale
|
||||
</Card>
|
||||
<Card title="App" icon="puzzle-piece" href="/l/it/developers/extend/capabilities/apps">
|
||||
<Card title="App" icon="puzzle-piece" href="/l/it/developers/apps/apps">
|
||||
Crea personalizzazioni come codice (Alpha)
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@@ -5,18 +5,28 @@ description: Benvenuto nella documentazione per sviluppatori di Twenty, le tue r
|
||||
|
||||
import { CardTitle } from "/snippets/card-title.mdx"
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card href="/l/it/developers/extend/extend" img="/images/user-guide/integrations/plug.png">
|
||||
<CardTitle>Estendi</CardTitle>
|
||||
Crea integrazioni con API, webhook e app personalizzate.
|
||||
<CardGroup cols={2}>
|
||||
<Card href="/l/it/developers/api" icon="code">
|
||||
<CardTitle>API</CardTitle>
|
||||
Interroga e modifica i dati del tuo CRM con REST o GraphQL.
|
||||
</Card>
|
||||
|
||||
<Card href="/l/it/developers/self-host/self-host" img="/images/user-guide/what-is-twenty/20.png">
|
||||
<Card href="/l/it/developers/webhooks" icon="bell">
|
||||
<CardTitle>Webhooks</CardTitle>
|
||||
Ricevi notifiche in tempo reale quando si verificano eventi.
|
||||
</Card>
|
||||
|
||||
<Card href="/l/it/developers/apps/apps" icon="puzzle-piece">
|
||||
<CardTitle>Apps</CardTitle>
|
||||
Crea applicazioni personalizzate che estendono le capacità di Twenty.
|
||||
</Card>
|
||||
|
||||
<Card href="/l/it/developers/self-host/self-host" icon="desktop">
|
||||
<CardTitle>Self-hosting</CardTitle>
|
||||
Distribuisci e gestisci Twenty sulla tua infrastruttura.
|
||||
</Card>
|
||||
|
||||
<Card href="/l/it/developers/contribute/contribute" img="/images/user-guide/github/github-header.png">
|
||||
<Card href="/l/it/developers/contribute/contribute" icon="github">
|
||||
<CardTitle>Contribuisci</CardTitle>
|
||||
Unisciti alla nostra community open source e contribuisci a Twenty.
|
||||
</Card>
|
||||
|
||||
@@ -24,7 +24,7 @@ Esporta i dati del tuo spazio di lavoro in CSV per backup, reportistica o migraz
|
||||
* Vengono esportate solo le **colonne visibili**
|
||||
* Vengono esportati solo i **record filtrati** (in base alla vista corrente)
|
||||
|
||||
<Note>Per esportazioni più grandi (oltre 20.000 record), usa i filtri per esportare a lotti oppure usa le [API](/l/it/developers/extend/capabilities/apis).</Note>
|
||||
<Note>Per esportazioni più grandi (oltre 20.000 record), usa i filtri per esportare a lotti oppure usa le [API](/l/it/developers/api).</Note>
|
||||
|
||||
### Permessi
|
||||
|
||||
@@ -148,7 +148,7 @@ Le API non hanno un limite di record:
|
||||
2. Usa le API GraphQL per interrogare i record
|
||||
3. Elabora i risultati nella tua applicazione
|
||||
|
||||
Vedi: [Documentazione API](/l/it/developers/extend/capabilities/apis)
|
||||
Vedi: [Documentazione API](/l/it/developers/api)
|
||||
|
||||
## Suggerimenti e buone pratiche
|
||||
|
||||
@@ -206,4 +206,4 @@ I file esportati possono contenere dati sensibili:
|
||||
|
||||
* [Come aggiornare i record esistenti](/l/it/user-guide/data-migration/how-tos/update-existing-records-via-import) — modifica e reimporta la tua esportazione
|
||||
* [Come importare i dati tramite API](/l/it/user-guide/data-migration/how-tos/import-data-via-api) — per set di dati di grandi dimensioni
|
||||
* [Documentazione API](/l/it/developers/extend/capabilities/apis) — crea flussi di lavoro di esportazione personalizzati
|
||||
* [Documentazione API](/l/it/developers/api) — crea flussi di lavoro di esportazione personalizzati
|
||||
|
||||
@@ -59,8 +59,8 @@ Twenty supporta due tipi di API:
|
||||
|
||||
| API | Ideale per | Documentazione |
|
||||
| ----------- | ------------------------------------------------------------------ | ---------------------------------------------------------- |
|
||||
| **GraphQL** | Query flessibili, recupero di dati correlati, operazioni complesse | [Documentazione API](/l/it/developers/extend/capabilities/apis) |
|
||||
| **REST** | Operazioni CRUD semplici, pattern REST familiari | [Documentazione API](/l/it/developers/extend/capabilities/apis) |
|
||||
| **GraphQL** | Query flessibili, recupero di dati correlati, operazioni complesse | [Documentazione API](/l/it/developers/api) |
|
||||
| **REST** | Operazioni CRUD semplici, pattern REST familiari | [Documentazione API](/l/it/developers/api) |
|
||||
|
||||
Entrambe le API supportano:
|
||||
|
||||
@@ -173,4 +173,4 @@ Contattaci a [[email protected]](mailto:[email protected]) oppure scopri i nos
|
||||
|
||||
Per i dettagli completi di implementazione, esempi di codice e riferimento allo schema:
|
||||
|
||||
* [Documentazione API](/l/it/developers/extend/capabilities/apis)
|
||||
* [Documentazione API](/l/it/developers/api)
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ L'open-source è la base del nostro approccio, garantendo che Twenty evolva con
|
||||
* **Dashboard:** Monitora le prestazioni con report e visualizzazioni personalizzati. [Visualizza le dashboard](/l/it/user-guide/dashboards/overview).
|
||||
* **Autorizzazioni e accesso:** Controlla chi può visualizzare, modificare e gestire i tuoi dati con autorizzazioni basate sui ruoli. [Configura l'accesso](/l/it/user-guide/permissions-access/overview).
|
||||
* **Note e attività:** Crea note e attività collegate ai tuoi record per una collaborazione migliore.
|
||||
* **API e Webhooks:** Connettiti ad altre app e crea integrazioni personalizzate. [Inizia a integrare](/l/it/developers/extend/capabilities/apis).
|
||||
* **API e Webhooks:** Connettiti ad altre app e crea integrazioni personalizzate. [Inizia a integrare](/l/it/developers/api).
|
||||
|
||||
## Unisciti ora
|
||||
|
||||
|
||||
+1
-1
@@ -95,7 +95,7 @@ Crea i campi di destinazione in **Impostazioni → Modello dati → Opportunità
|
||||
* Dimensione aziendale: `{{searchRecords[0].employees}}`
|
||||
|
||||
<Note>
|
||||
**Limitazione di Attività e Note**: Le relazioni su Attività e Note sono codificate come molte-a-molte e non sono ancora disponibili nei trigger o nelle azioni dei flussi di lavoro. Per accedere a queste relazioni, usa invece le [API](/l/it/developers/extend/capabilities/apis).
|
||||
**Limitazione di Attività e Note**: Le relazioni su Attività e Note sono codificate come molte-a-molte e non sono ancora disponibili nei trigger o nelle azioni dei flussi di lavoro. Per accedere a queste relazioni, usa invece le [API](/l/it/developers/api).
|
||||
</Note>
|
||||
|
||||
## Sincronizzazione bidirezionale
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
title: 拡張
|
||||
description: API、Webhook、カスタムアプリで Twenty の機能を拡張できます。
|
||||
redirect: /developers/introduction
|
||||
---
|
||||
|
||||
<Frame>
|
||||
@@ -20,15 +21,15 @@ Twenty は拡張性を念頭に設計されています。 当社の API、Webho
|
||||
## 始めに
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="API" icon="コード" href="/l/ja/developers/extend/capabilities/apis">
|
||||
<Card title="API" icon="コード" href="/l/ja/developers/api">
|
||||
プログラムから Twenty に接続
|
||||
</Card>
|
||||
|
||||
<Card title="ウェブフック" icon="bell" href="/l/ja/developers/extend/capabilities/webhooks">
|
||||
<Card title="ウェブフック" icon="bell" href="/l/ja/developers/webhooks">
|
||||
イベントの通知をリアルタイムで受け取る
|
||||
</Card>
|
||||
|
||||
<Card title="アプリ" icon="puzzle-piece" href="/l/ja/developers/extend/capabilities/apps">
|
||||
<Card title="アプリ" icon="puzzle-piece" href="/l/ja/developers/apps/apps">
|
||||
カスタマイズをコードとして構築(アルファ版)
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@@ -1,23 +1,33 @@
|
||||
---
|
||||
title: 始めに
|
||||
description: Welcome to Twenty Developer Documentation, your resources for extending, self-hosting, and contributing to Twenty.
|
||||
description: Twenty 開発者ドキュメントへようこそ。Twenty の拡張、セルフホスティング、貢献のためのリソースです。
|
||||
---
|
||||
|
||||
import { CardTitle } from "/snippets/card-title.mdx"
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card href="/l/ja/developers/extend/extend" img="/images/user-guide/integrations/plug.png">
|
||||
<CardTitle>Extend</CardTitle>
|
||||
Build integrations with APIs, webhooks, and custom apps.
|
||||
<CardGroup cols={2}>
|
||||
<Card href="/l/ja/developers/api" icon="code">
|
||||
<CardTitle>API</CardTitle>
|
||||
REST または GraphQL で CRM データをクエリおよび変更します。
|
||||
</Card>
|
||||
|
||||
<Card href="/l/ja/developers/self-host/self-host" img="/images/user-guide/what-is-twenty/20.png">
|
||||
<Card href="/l/ja/developers/webhooks" icon="bell">
|
||||
<CardTitle>Webhooks</CardTitle>
|
||||
イベント発生時にリアルタイムで通知を受け取ります。
|
||||
</Card>
|
||||
|
||||
<Card href="/l/ja/developers/apps/apps" icon="puzzle-piece">
|
||||
<CardTitle>Apps</CardTitle>
|
||||
Twenty の機能を拡張するカスタムアプリケーションを構築します。
|
||||
</Card>
|
||||
|
||||
<Card href="/l/ja/developers/self-host/self-host" icon="desktop">
|
||||
<CardTitle>Self-Host</CardTitle>
|
||||
Deploy and manage Twenty on your own infrastructure.
|
||||
ご自身のインフラストラクチャで Twenty をデプロイおよび管理します。
|
||||
</Card>
|
||||
|
||||
<Card href="/l/ja/developers/contribute/contribute" img="/images/user-guide/github/github-header.png">
|
||||
<Card href="/l/ja/developers/contribute/contribute" icon="github">
|
||||
<CardTitle>Contribute</CardTitle>
|
||||
Join our open-source community and contribute to Twenty.
|
||||
オープンソースコミュニティに参加し、Twenty に貢献しましょう。
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@@ -24,7 +24,7 @@ import { VimeoEmbed } from '/snippets/vimeo-embed.mdx';
|
||||
* **表示されている列**のみがエクスポートされます
|
||||
* **フィルターで絞り込まれたレコード**のみがエクスポートされます(現在のビューに基づきます)
|
||||
|
||||
<Note>大規模なエクスポート(20,000 件超)では、フィルターを使ってバッチに分けてエクスポートするか、[API](/l/ja/developers/extend/capabilities/apis) を使用してください。</Note>
|
||||
<Note>大規模なエクスポート(20,000 件超)では、フィルターを使ってバッチに分けてエクスポートするか、[API](/l/ja/developers/api) を使用してください。</Note>
|
||||
|
||||
### 権限
|
||||
|
||||
@@ -148,7 +148,7 @@ API にはレコード数の上限がありません:
|
||||
2. GraphQL API を使用してレコードをクエリします
|
||||
3. アプリケーションで結果を処理
|
||||
|
||||
参照:[API ドキュメント](/l/ja/developers/extend/capabilities/apis)
|
||||
参照:[API ドキュメント](/l/ja/developers/api)
|
||||
|
||||
## ヒントとベストプラクティス
|
||||
|
||||
@@ -206,4 +206,4 @@ API にはレコード数の上限がありません:
|
||||
|
||||
* [既存レコードを更新する方法](/l/ja/user-guide/data-migration/how-tos/update-existing-records-via-import) — エクスポートを編集して再インポート
|
||||
* [API でデータをインポートする方法](/l/ja/user-guide/data-migration/how-tos/import-data-via-api) — 大規模データセット向け
|
||||
* [API ドキュメント](/l/ja/developers/extend/capabilities/apis) — カスタムのエクスポートワークフローを構築
|
||||
* [API ドキュメント](/l/ja/developers/api) — カスタムのエクスポートワークフローを構築
|
||||
|
||||
@@ -59,8 +59,8 @@ Twenty は 2 種類の API をサポートしています:
|
||||
|
||||
| API | 最適な用途 | ドキュメント |
|
||||
| ----------- | ------------------------------ | -------------------------------------------------- |
|
||||
| **GraphQL** | 柔軟なクエリ、関連データの取得、複雑な操作に最適 | [API ドキュメント](/l/ja/developers/extend/capabilities/apis) |
|
||||
| **REST** | シンプルな CRUD 操作、馴染みのある REST パターン | [API ドキュメント](/l/ja/developers/extend/capabilities/apis) |
|
||||
| **GraphQL** | 柔軟なクエリ、関連データの取得、複雑な操作に最適 | [API ドキュメント](/l/ja/developers/api) |
|
||||
| **REST** | シンプルな CRUD 操作、馴染みのある REST パターン | [API ドキュメント](/l/ja/developers/api) |
|
||||
|
||||
両方の API でサポートされる内容:
|
||||
|
||||
@@ -173,4 +173,4 @@ GraphQL API は **バッチ アップサート**をサポートしています
|
||||
|
||||
実装の詳細、コード例、スキーマリファレンスについては次を参照してください:
|
||||
|
||||
* [API ドキュメント](/l/ja/developers/extend/capabilities/apis)
|
||||
* [API ドキュメント](/l/ja/developers/api)
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ description: Twenty is an open-source CRM that gives you the building blocks to
|
||||
* **ダッシュボード:** カスタムレポートや可視化でパフォーマンスを追跡します。 [ダッシュボードを表示](/l/ja/user-guide/dashboards/overview)。
|
||||
* **権限とアクセス:** ロールベースの権限で、誰がデータを閲覧、編集、管理できるかを制御します。 [アクセスを設定](/l/ja/user-guide/permissions-access/overview)。
|
||||
* **ノートとタスク:** より良いコラボレーションのために、レコードに関連付けられたノートやタスクを作成します。
|
||||
* **APIおよびWebhooks:** 他のアプリと接続し、カスタム統合を構築します。 [統合を開始](/l/ja/developers/extend/capabilities/apis).
|
||||
* **APIおよびWebhooks:** 他のアプリと接続し、カスタム統合を構築します。 [統合を開始](/l/ja/developers/api).
|
||||
|
||||
## 今すぐ参加
|
||||
|
||||
|
||||
+1
-1
@@ -95,7 +95,7 @@ description: ワークフローを使用して、関連レコードのデータ
|
||||
* 会社規模: `{{searchRecords[0].employees}}`
|
||||
|
||||
<Note>
|
||||
**タスクとノートの制限**: タスクとノートのリレーションは多対多としてハードコードされており、ワークフローのトリガーやアクションではまだ使用できません。 これらのリレーションにアクセスするには、代わりに[API](/l/ja/developers/extend/capabilities/apis)を使用してください。
|
||||
**タスクとノートの制限**: タスクとノートのリレーションは多対多としてハードコードされており、ワークフローのトリガーやアクションではまだ使用できません。 これらのリレーションにアクセスするには、代わりに[API](/l/ja/developers/api)を使用してください。
|
||||
</Note>
|
||||
|
||||
## 双方向同期
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
title: 확장
|
||||
description: API, 웹훅 및 맞춤형 앱으로 Twenty의 기능을 확장하세요.
|
||||
redirect: /developers/introduction
|
||||
---
|
||||
|
||||
<Frame>
|
||||
@@ -20,15 +21,15 @@ Twenty는 확장 가능하도록 설계되었습니다. 당사의 API, 웹훅
|
||||
## 시작하기
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="API" icon="코드" href="/l/ko/developers/extend/capabilities/apis">
|
||||
<Card title="API" icon="코드" href="/l/ko/developers/api">
|
||||
프로그래밍 방식으로 Twenty에 연결하세요
|
||||
</Card>
|
||||
|
||||
<Card title="웹훅" icon="bell" href="/l/ko/developers/extend/capabilities/webhooks">
|
||||
<Card title="웹훅" icon="bell" href="/l/ko/developers/webhooks">
|
||||
이벤트에 대한 실시간 알림을 받으세요
|
||||
</Card>
|
||||
|
||||
<Card title="앱" icon="puzzle-piece" href="/l/ko/developers/extend/capabilities/apps">
|
||||
<Card title="앱" icon="puzzle-piece" href="/l/ko/developers/apps/apps">
|
||||
코드로 사용자 지정을 구축하세요(알파)
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@@ -5,18 +5,28 @@ description: Twenty 개발자 문서에 오신 것을 환영합니다. 이 문
|
||||
|
||||
import { CardTitle } from "/snippets/card-title.mdx"
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card href="/l/ko/developers/extend/extend" img="/images/user-guide/integrations/plug.png">
|
||||
<CardTitle>확장</CardTitle>
|
||||
API, 웹훅 및 맞춤형 앱과의 통합을 구축하세요.
|
||||
<CardGroup cols={2}>
|
||||
<Card href="/l/ko/developers/api" icon="code">
|
||||
<CardTitle>API</CardTitle>
|
||||
REST 또는 GraphQL로 CRM 데이터를 쿼리하고 수정합니다.
|
||||
</Card>
|
||||
|
||||
<Card href="/l/ko/developers/self-host/self-host" img="/images/user-guide/what-is-twenty/20.png">
|
||||
<Card href="/l/ko/developers/webhooks" icon="bell">
|
||||
<CardTitle>Webhooks</CardTitle>
|
||||
이벤트 발생 시 실시간 알림을 받습니다.
|
||||
</Card>
|
||||
|
||||
<Card href="/l/ko/developers/apps/apps" icon="puzzle-piece">
|
||||
<CardTitle>Apps</CardTitle>
|
||||
Twenty의 기능을 확장하는 맞춤형 애플리케이션을 구축하세요.
|
||||
</Card>
|
||||
|
||||
<Card href="/l/ko/developers/self-host/self-host" icon="desktop">
|
||||
<CardTitle>자체 호스팅</CardTitle>
|
||||
자체 인프라에 Twenty를 배포하고 관리하세요.
|
||||
</Card>
|
||||
|
||||
<Card href="/l/ko/developers/contribute/contribute" img="/images/user-guide/github/github-header.png">
|
||||
<Card href="/l/ko/developers/contribute/contribute" icon="github">
|
||||
<CardTitle>기여</CardTitle>
|
||||
오픈 소스 커뮤니티에 참여하고 Twenty에 기여하세요.
|
||||
</Card>
|
||||
|
||||
@@ -24,7 +24,7 @@ import { VimeoEmbed } from '/snippets/vimeo-embed.mdx';
|
||||
* **표시된 열**만 내보내집니다
|
||||
* **필터링된 레코드**만 내보내집니다(현재 보기 기준)
|
||||
|
||||
<Note>더 큰 내보내기(20,000개 이상의 레코드)에는 필터를 사용해 배치로 내보내거나 [API](/l/ko/developers/extend/capabilities/apis)를 사용하세요.</Note>
|
||||
<Note>더 큰 내보내기(20,000개 이상의 레코드)에는 필터를 사용해 배치로 내보내거나 [API](/l/ko/developers/api)를 사용하세요.</Note>
|
||||
|
||||
### 권한
|
||||
|
||||
@@ -148,7 +148,7 @@ API에는 레코드 수 한도가 없습니다:
|
||||
2. GraphQL API를 사용해 레코드를 쿼리하세요
|
||||
3. 애플리케이션에서 결과를 처리하세요
|
||||
|
||||
참고: [API 문서](/l/ko/developers/extend/capabilities/apis)
|
||||
참고: [API 문서](/l/ko/developers/api)
|
||||
|
||||
## 팁 및 모범 사례
|
||||
|
||||
@@ -206,4 +206,4 @@ API에는 레코드 수 한도가 없습니다:
|
||||
|
||||
* [기존 레코드를 업데이트하는 방법](/l/ko/user-guide/data-migration/how-tos/update-existing-records-via-import) — 내보낸 파일을 편집한 뒤 다시 가져오세요
|
||||
* [API로 데이터 가져오는 방법](/l/ko/user-guide/data-migration/how-tos/import-data-via-api) — 대용량 데이터셋용
|
||||
* [API 문서](/l/ko/developers/extend/capabilities/apis) — 맞춤 내보내기 워크플로우를 구축하세요
|
||||
* [API 문서](/l/ko/developers/api) — 맞춤 내보내기 워크플로우를 구축하세요
|
||||
|
||||
@@ -59,8 +59,8 @@ Twenty는 두 가지 유형의 API를 지원합니다:
|
||||
|
||||
| API | 적합한 용도 | 문서 |
|
||||
| ----------- | ----------------------------- | ---------------------------------------------- |
|
||||
| **GraphQL** | 유연한 쿼리, 연관 데이터 조회, 복잡한 작업에 적합 | [API 문서](/l/ko/developers/extend/capabilities/apis) |
|
||||
| **REST** | 단순한 CRUD 작업, 익숙한 REST 패턴 | [API 문서](/l/ko/developers/extend/capabilities/apis) |
|
||||
| **GraphQL** | 유연한 쿼리, 연관 데이터 조회, 복잡한 작업에 적합 | [API 문서](/l/ko/developers/api) |
|
||||
| **REST** | 단순한 CRUD 작업, 익숙한 REST 패턴 | [API 문서](/l/ko/developers/api) |
|
||||
|
||||
두 API 모두 다음을 지원합니다:
|
||||
|
||||
@@ -173,4 +173,4 @@ GraphQL API는 **배치 업서트**를 지원합니다 — 레코드가 있으
|
||||
|
||||
전체 구현 세부정보, 코드 예제, 스키마 참조는 다음을 확인하세요:
|
||||
|
||||
* [API 문서](/l/ko/developers/extend/capabilities/apis)
|
||||
* [API 문서](/l/ko/developers/api)
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ description: Twenty는 비즈니스에 필요한 것을 정확히 만들 수 있
|
||||
* **대시보드:** 맞춤형 보고서와 시각화를 통해 성과를 추적하세요. [대시보드 보기](/l/ko/user-guide/dashboards/overview).
|
||||
* **권한 및 액세스:** 역할 기반 권한을 통해 누가 데이터를 보기, 편집, 관리할 수 있는지 제어하세요. [액세스 구성](/l/ko/user-guide/permissions-access/overview).
|
||||
* **노트 및 작업:** 더 나은 협업을 위해 레코드에 연결된 노트와 작업을 생성하세요.
|
||||
* **API 및 웹훅:** 다른 앱과 연결하고 맞춤형 통합을 구축하세요. [통합 시작하기](/l/ko/developers/extend/capabilities/apis).
|
||||
* **API 및 웹훅:** 다른 앱과 연결하고 맞춤형 통합을 구축하세요. [통합 시작하기](/l/ko/developers/api).
|
||||
|
||||
## 지금 가입하세요
|
||||
|
||||
|
||||
+1
-1
@@ -95,7 +95,7 @@ description: "워크플로우를 사용해 관련 레코드의 데이터를 표
|
||||
* 회사 규모: `{{searchRecords[0].employees}}`
|
||||
|
||||
<Note>
|
||||
**작업 및 노트 제한 사항**: 작업과 노트의 관계는 다대다로 하드코딩되어 있으며, 워크플로우 트리거 또는 액션에서 아직 사용할 수 없습니다. 이러한 관계에 액세스하려면 대신 [API](/l/ko/developers/extend/capabilities/apis)를 사용하세요.
|
||||
**작업 및 노트 제한 사항**: 작업과 노트의 관계는 다대다로 하드코딩되어 있으며, 워크플로우 트리거 또는 액션에서 아직 사용할 수 없습니다. 이러한 관계에 액세스하려면 대신 [API](/l/ko/developers/api)를 사용하세요.
|
||||
</Note>
|
||||
|
||||
## 양방향 동기화
|
||||
|
||||
@@ -15,7 +15,7 @@ Os aplicativos permitem criar e gerenciar personalizações do Twenty **como có
|
||||
|
||||
* Defina objetos e campos personalizados como código (modelo de dados gerenciado)
|
||||
* Crie funções de lógica com gatilhos personalizados
|
||||
* Definir habilidades para agentes de IA
|
||||
* Defina habilidades e agentes de IA
|
||||
* Implemente o mesmo aplicativo em vários espaços de trabalho
|
||||
|
||||
## Pré-requisitos
|
||||
@@ -36,13 +36,13 @@ cd my-twenty-app
|
||||
yarn twenty app:dev
|
||||
```
|
||||
|
||||
The scaffolder supports two modes for controlling which example files are included:
|
||||
O gerador de estrutura oferece suporte a dois modos para controlar quais arquivos de exemplo são incluídos:
|
||||
|
||||
```bash filename="Terminal"
|
||||
# Default (exhaustive): all examples (object, field, logic function, front component, view, navigation menu item, skill)
|
||||
# Padrão (exhaustivo): todos os exemplos (objeto, campo, função de lógica, componente de front-end, visualização, item do menu de navegação, habilidade, agente)
|
||||
npx create-twenty-app@latest my-app
|
||||
|
||||
# Minimal: only core files (application-config.ts and default-role.ts)
|
||||
# Mínimo: apenas arquivos principais (application-config.ts e default-role.ts)
|
||||
npx create-twenty-app@latest my-app --minimal
|
||||
```
|
||||
|
||||
@@ -96,27 +96,29 @@ my-twenty-app/
|
||||
.oxlintrc.json
|
||||
tsconfig.json
|
||||
README.md
|
||||
public/ # Pasta de recursos públicos (imagens, fontes, etc.)
|
||||
public/ # Public assets folder (images, fonts, etc.)
|
||||
src/
|
||||
├── application-config.ts # Obrigatório - configuração principal da aplicação
|
||||
├── application-config.ts # Required - main application configuration
|
||||
├── roles/
|
||||
│ └── default-role.ts # Papel padrão para funções de lógica
|
||||
│ └── default-role.ts # Default role for logic functions
|
||||
├── objects/
|
||||
│ └── example-object.ts # Exemplo de definição de objeto personalizado
|
||||
│ └── example-object.ts # Example custom object definition
|
||||
├── fields/
|
||||
│ └── example-field.ts # Exemplo de definição de campo independente
|
||||
│ └── example-field.ts # Example standalone field definition
|
||||
├── logic-functions/
|
||||
│ ├── hello-world.ts # Exemplo de função de lógica
|
||||
│ ├── pre-install.ts # Função de lógica de pré-instalação
|
||||
│ └── post-install.ts # Função de lógica de pós-instalação
|
||||
│ ├── hello-world.ts # Example logic function
|
||||
│ ├── pre-install.ts # Pre-install logic function
|
||||
│ └── post-install.ts # Post-install logic function
|
||||
├── front-components/
|
||||
│ └── hello-world.tsx # Exemplo de componente de front-end
|
||||
│ └── hello-world.tsx # Example front component
|
||||
├── views/
|
||||
│ └── example-view.ts # Exemplo de definição de visualização salva
|
||||
│ └── example-view.ts # Example saved view definition
|
||||
├── navigation-menu-items/
|
||||
│ └── example-navigation-menu-item.ts # Exemplo de link de navegação da barra lateral
|
||||
└── skills/
|
||||
└── example-skill.ts # Exemplo de definição de habilidade de agente de IA
|
||||
│ └── example-navigation-menu-item.ts # Example sidebar navigation link
|
||||
├── skills/
|
||||
│ └── example-skill.ts # Example AI agent skill definition
|
||||
└── agents/
|
||||
└── example-agent.ts # Example AI agent definition
|
||||
```
|
||||
|
||||
With `--minimal`, only the core files are created (`application-config.ts`, `roles/default-role.ts`, `logic-functions/pre-install.ts`, and `logic-functions/post-install.ts`).
|
||||
@@ -148,6 +150,7 @@ O SDK detecta entidades analisando seus arquivos TypeScript em busca de chamadas
|
||||
| `defineView()` | Definições de visualizações salvas |
|
||||
| `defineNavigationMenuItem()` | Definições de itens do menu de navegação |
|
||||
| `defineSkill()` | Definições de habilidades de agente de IA |
|
||||
| `defineAgent()` | Definições de agentes de IA |
|
||||
|
||||
<Note>
|
||||
**A nomeação de arquivos é flexível.** A detecção de entidades é baseada em AST — o SDK varre seus arquivos fonte em busca do padrão `export default define<Entity>({...})`. Você pode organizar seus arquivos e pastas como quiser. Agrupar por tipo de entidade (por exemplo, `logic-functions/`, `roles/`) é apenas uma convenção para organização do código, não um requisito.
|
||||
@@ -225,6 +228,7 @@ O SDK fornece funções utilitárias para definir as entidades do seu app. Confo
|
||||
| `defineView()` | Define visualizações salvas para objetos |
|
||||
| `defineNavigationMenuItem()` | Define links de navegação da barra lateral |
|
||||
| `defineSkill()` | Define habilidades de agente de IA |
|
||||
| `defineAgent()` | Define AI agents with system prompts |
|
||||
|
||||
Essas funções validam sua configuração em tempo de compilação e oferecem autocompletar na IDE e segurança de tipos.
|
||||
|
||||
@@ -803,6 +807,41 @@ Você pode criar novas habilidades de duas formas:
|
||||
* **Gerado automaticamente**: Execute `yarn twenty entity:add` e escolha a opção para adicionar uma nova habilidade.
|
||||
* **Manual**: Crie um novo arquivo e use `defineSkill()`, seguindo o mesmo padrão.
|
||||
|
||||
### Agentes
|
||||
|
||||
Agents define AI agents with system prompts that can operate within your workspace. Use `defineAgent()` to define agents with built-in validation:
|
||||
|
||||
```typescript
|
||||
// src/agents/example-agent.ts
|
||||
import { defineAgent } from 'twenty-sdk';
|
||||
|
||||
export default defineAgent({
|
||||
universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
|
||||
name: 'sales-assistant',
|
||||
label: 'Sales Assistant',
|
||||
description: 'An AI agent that helps with sales tasks',
|
||||
icon: 'IconRobot',
|
||||
prompt: `You are a sales assistant. Help users with:
|
||||
1. Researching prospects and companies
|
||||
2. Drafting personalized outreach messages
|
||||
3. Tracking follow-ups and next steps
|
||||
4. Analyzing deal pipeline and suggesting actions`,
|
||||
});
|
||||
```
|
||||
|
||||
Pontos-chave:
|
||||
|
||||
* `name` is a unique identifier string for the agent (kebab-case recommended).
|
||||
* `label` é o nome de exibição legível por humanos mostrado na UI.
|
||||
* `prompt` contains the system prompt — this is the instruction text that defines the agent's behavior.
|
||||
* `icon` (opcional) define o ícone exibido na UI.
|
||||
* `description` (optional) provides additional context about the agent's purpose.
|
||||
|
||||
You can create new agents in two ways:
|
||||
|
||||
* **Scaffolded**: Run `yarn twenty entity:add` and choose the option to add a new agent.
|
||||
* **Manual**: Create a new file and use `defineAgent()`, following the same pattern.
|
||||
|
||||
### Clientes tipados gerados
|
||||
|
||||
Dois clientes tipados são gerados automaticamente pelo `yarn twenty app:dev` e armazenados em `node_modules/twenty-sdk/generated` com base no esquema do seu espaço de trabalho:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
title: Estender
|
||||
description: Amplie a funcionalidade do Twenty com APIs, webhooks e aplicativos personalizados.
|
||||
redirect: /developers/introduction
|
||||
---
|
||||
|
||||
<Frame>
|
||||
@@ -20,13 +21,13 @@ O Twenty foi projetado para ser extensível. Use nossas APIs, webhooks e o frame
|
||||
## Primeiros passos
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="APIs" icon="código" href="/l/pt/developers/extend/capabilities/apis">
|
||||
<Card title="APIs" icon="código" href="/l/pt/developers/api">
|
||||
Conecte-se ao Twenty programaticamente
|
||||
</Card>
|
||||
<Card title="Webhooks" icon="bell" href="/l/pt/developers/extend/capabilities/webhooks">
|
||||
<Card title="Webhooks" icon="bell" href="/l/pt/developers/webhooks">
|
||||
Receba notificações de eventos em tempo real
|
||||
</Card>
|
||||
<Card title="Aplicativos" icon="puzzle-piece" href="/l/pt/developers/extend/capabilities/apps">
|
||||
<Card title="Aplicativos" icon="puzzle-piece" href="/l/pt/developers/apps/apps">
|
||||
Crie personalizações como código (Alpha)
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@@ -5,18 +5,28 @@ description: Bem-vindo à Documentação para Desenvolvedores da Twenty, seus re
|
||||
|
||||
import { CardTitle } from "/snippets/card-title.mdx"
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card href="/l/pt/developers/extend/extend" img="/images/user-guide/integrations/plug.png">
|
||||
<CardTitle>Estender</CardTitle>
|
||||
Crie integrações com APIs, webhooks e aplicativos personalizados.
|
||||
<CardGroup cols={2}>
|
||||
<Card href="/l/pt/developers/api" icon="code">
|
||||
<CardTitle>API</CardTitle>
|
||||
Consulte e modifique os dados do seu CRM com REST ou GraphQL.
|
||||
</Card>
|
||||
|
||||
<Card href="/l/pt/developers/self-host/self-host" img="/images/user-guide/what-is-twenty/20.png">
|
||||
<Card href="/l/pt/developers/webhooks" icon="bell">
|
||||
<CardTitle>Webhooks</CardTitle>
|
||||
Receba notificações em tempo real quando eventos ocorrerem.
|
||||
</Card>
|
||||
|
||||
<Card href="/l/pt/developers/apps/apps" icon="puzzle-piece">
|
||||
<CardTitle>Apps</CardTitle>
|
||||
Crie aplicativos personalizados que estendem as capacidades do Twenty.
|
||||
</Card>
|
||||
|
||||
<Card href="/l/pt/developers/self-host/self-host" icon="desktop">
|
||||
<CardTitle>Auto-hospedar</CardTitle>
|
||||
Implante e gerencie o Twenty na sua própria infraestrutura.
|
||||
</Card>
|
||||
|
||||
<Card href="/l/pt/developers/contribute/contribute" img="/images/user-guide/github/github-header.png">
|
||||
<Card href="/l/pt/developers/contribute/contribute" icon="github">
|
||||
<CardTitle>Contribuir</CardTitle>
|
||||
Junte-se à nossa comunidade de código aberto e contribua para o Twenty.
|
||||
</Card>
|
||||
|
||||
@@ -24,7 +24,7 @@ Exporte os dados do seu espaço de trabalho para CSV para backups, relatórios o
|
||||
* Apenas **as colunas visíveis** são exportadas
|
||||
* Apenas **os registros filtrados** são exportados (com base na sua visualização atual)
|
||||
|
||||
<Note>Para exportações maiores (20,000+ registros), use filtros para exportar em lotes ou use a [API](/l/pt/developers/extend/capabilities/apis).</Note>
|
||||
<Note>Para exportações maiores (20,000+ registros), use filtros para exportar em lotes ou use a [API](/l/pt/developers/api).</Note>
|
||||
|
||||
### Permissões
|
||||
|
||||
@@ -148,7 +148,7 @@ A API não tem limite de registros:
|
||||
2. Use a API GraphQL para consultar registros
|
||||
3. Processe os resultados no seu aplicativo
|
||||
|
||||
Veja: [Documentação da API](/l/pt/developers/extend/capabilities/apis)
|
||||
Veja: [Documentação da API](/l/pt/developers/api)
|
||||
|
||||
## Dicas e Boas Práticas
|
||||
|
||||
@@ -206,4 +206,4 @@ Arquivos exportados podem conter dados sensíveis:
|
||||
|
||||
* [Como Atualizar Registros Existentes](/l/pt/user-guide/data-migration/how-tos/update-existing-records-via-import) — edite e reimporte sua exportação
|
||||
* [Como Importar Dados via API](/l/pt/user-guide/data-migration/how-tos/import-data-via-api) — para conjuntos de dados grandes
|
||||
* [Documentação da API](/l/pt/developers/extend/capabilities/apis) — crie fluxos de trabalho de exportação personalizados
|
||||
* [Documentação da API](/l/pt/developers/api) — crie fluxos de trabalho de exportação personalizados
|
||||
|
||||
@@ -59,8 +59,8 @@ A Twenty suporta dois tipos de API:
|
||||
|
||||
| API | Melhor para | Documentação |
|
||||
| ----------- | ------------------------------------------------------------------------ | ----------------------------------------------------------- |
|
||||
| **GraphQL** | Consultas flexíveis, obtenção de dados relacionados, operações complexas | [Documentação da API](/l/pt/developers/extend/capabilities/apis) |
|
||||
| **REST** | Operações CRUD simples, padrões REST familiares | [Documentação da API](/l/pt/developers/extend/capabilities/apis) |
|
||||
| **GraphQL** | Consultas flexíveis, obtenção de dados relacionados, operações complexas | [Documentação da API](/l/pt/developers/api) |
|
||||
| **REST** | Operações CRUD simples, padrões REST familiares | [Documentação da API](/l/pt/developers/api) |
|
||||
|
||||
Ambas as APIs suportam:
|
||||
|
||||
@@ -173,4 +173,4 @@ Contacte-nos em [[email protected]](mailto:[email protected]) ou explore os no
|
||||
|
||||
Para detalhes completos de implementação, exemplos de código e referência de esquema:
|
||||
|
||||
* [Documentação da API](/l/pt/developers/extend/capabilities/apis)
|
||||
* [Documentação da API](/l/pt/developers/api)
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ O código aberto é a base da nossa abordagem, garantindo que o Twenty evolua co
|
||||
* **Painéis:** Acompanhe o desempenho com relatórios personalizados e visualizações personalizadas. [Ver painéis](/l/pt/user-guide/dashboards/overview).
|
||||
* **Permissões e Acesso:** Controle quem pode visualizar, editar e gerenciar seus dados com permissões baseadas em funções. [Configurar acesso](/l/pt/user-guide/permissions-access/overview).
|
||||
* **Notas e Tarefas:** Crie notas e tarefas vinculadas aos seus registros para uma melhor colaboração.
|
||||
* **API e Webhooks:** Conecte-se a outros aplicativos e crie integrações personalizadas. [Comece a integrar](/l/pt/developers/extend/capabilities/apis).
|
||||
* **API e Webhooks:** Conecte-se a outros aplicativos e crie integrações personalizadas. [Comece a integrar](/l/pt/developers/api).
|
||||
|
||||
## Participe agora
|
||||
|
||||
|
||||
+1
-1
@@ -95,7 +95,7 @@ Crie os campos de destino em **Definições → Modelo de Dados → Oportunidade
|
||||
* Tamanho da Empresa: `{{searchRecords[0].employees}}`
|
||||
|
||||
<Note>
|
||||
**Limitação de Tarefas e Notas**: As relações em Tarefas e Notas são pré-definidas como muitos-para-muitos e ainda não estão disponíveis em gatilhos ou ações de fluxos de trabalho. Para aceder a estas relações, use a [API](/l/pt/developers/extend/capabilities/apis).
|
||||
**Limitação de Tarefas e Notas**: As relações em Tarefas e Notas são pré-definidas como muitos-para-muitos e ainda não estão disponíveis em gatilhos ou ações de fluxos de trabalho. Para aceder a estas relações, use a [API](/l/pt/developers/api).
|
||||
</Note>
|
||||
|
||||
## Sincronização Bidirecional
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user