Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.twenty.com/llms.txt

Use this file to discover all available pages before exploring further.

Funcțiile de logică sunt funcții TypeScript pe partea de server care rulează pe platforma Twenty. Acestea pot fi declanșate de solicitări HTTP, programări cron sau evenimente din baza de date — și pot fi, de asemenea, expuse ca instrumente pentru agenți AI.
Fiecare fișier de funcție folosește defineLogicFunction() pentru a exporta o configurație cu un handler și declanșatoare opționale.
src/logic-functions/createPostCard.logic-function.ts
import { defineLogicFunction } from 'twenty-sdk/define';
import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk/define';
import { CoreApiClient, type Person } from 'twenty-client-sdk/core';

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,
  httpRouteTriggerSettings: {
    path: '/post-card/create',
    httpMethod: 'GET',
    isAuthRequired: true,
  },
  /*databaseEventTriggerSettings: {
    eventName: 'people.created',
  },*/
  /*cronTriggerSettings: {
    pattern: '0 0 1 1 *',
  },*/
});
Tipuri de declanșatoare disponibile:
  • httpRoute: Expune funcția pe o cale și metodă HTTP sub endpoint-ul /s/:
de ex. path: '/post-card/create' este apelabil la https://your-twenty-server.com/s/post-card/create
  • cron: Rulează funcția pe un program folosind o expresie CRON.
  • databaseEvent: Rulează la evenimentele ciclului de viață ale obiectelor din spațiul de lucru. Când operațiunea evenimentului este updated, câmpurile specifice de urmărit pot fi specificate în array-ul updatedFields. Dacă este lăsat nedefinit sau gol, orice actualizare va declanșa funcția.
de ex. person.updated, *.created, company.*
Puteți, de asemenea, să executați manual o funcție folosind CLI:
yarn twenty exec -n create-new-post-card -p '{"key": "value"}'
yarn twenty exec -y e56d363b-0bdc-4d8a-a393-6f0d1c75bdcf
Puteți urmări jurnalele cu:
yarn twenty logs

Payload-ul declanșatorului de rută

Când un declanșator de rută invocă funcția logică, aceasta primește un obiect RoutePayload care urmează AWS HTTP API v2 format. Importați tipul RoutePayload din twenty-sdk:
import { defineLogicFunction, type RoutePayload } from 'twenty-sdk/define';

const handler = async (event: RoutePayload) => {
  const { headers, queryStringParameters, pathParameters, body } = event;
  const { method, path } = event.requestContext.http;

  return { message: 'Success' };
};
Tipul RoutePayload are următoarea structură:
ProprietateTipDescriereExemplu
headersRecord\<string, string | undefined>Anteturi HTTP (doar cele listate în forwardedRequestHeaders)consultați secțiunea de mai jos
queryStringParametersRecord\<string, string | undefined>Parametri query string (valorile multiple unite cu virgule)/users?ids=1&ids=2&ids=3&name=Alice -> { ids: '1,2,3', name: 'Alice' }
pathParametersRecord\<string, string | undefined>Parametri de cale extrași din modelul rutei/users/:id, /users/123 -> { id: '123' }
bodyobject | nullCorpul cererii analizat (JSON){ id: 1 } -> { id: 1 }
rawBodystring | undefinedCorpul original al cererii în UTF-8, înainte de parsarea JSON. Util pentru verificarea semnăturilor de tip HMAC pentru webhook-uri (de exemplu, X-Hub-Signature-256 de la GitHub, Stripe). undefined atunci când mediul de execuție nu a păstrat-o.
isBase64EncodedbooleanIndică dacă corpul este codificat în base64
requestContext.http.methodstringMetoda HTTP (GET, POST, PUT, PATCH, DELETE)
requestContext.http.pathstringCalea brută a cererii

forwardedRequestHeaders

În mod implicit, anteturile HTTP din cererile de intrare nu sunt transmise funcției dvs. de logică din motive de securitate. Pentru a accesa anumite anteturi, listați-le explicit în array-ul forwardedRequestHeaders:
export default defineLogicFunction({
  universalIdentifier: 'e56d363b-0bdc-4d8a-a393-6f0d1c75bdcf',
  name: 'webhook-handler',
  handler,
  httpRouteTriggerSettings: {
    path: '/webhook',
    httpMethod: 'POST',
    isAuthRequired: false,
    forwardedRequestHeaders: ['x-webhook-signature', 'content-type'],
  },
});
În handler, accesați anteturile transmise mai departe astfel:
const handler = async (event: RoutePayload) => {
  const signature = event.headers['x-webhook-signature'];
  const contentType = event.headers['content-type'];

  // Validate webhook signature...
  return { received: true };
};
Numele anteturilor sunt normalizate la litere mici. Accesați-le folosind chei cu litere mici (de exemplu, event.headers['content-type']).

Expunerea unei funcții ca instrument AI sau ca acțiune în fluxul de lucru

Funcțiile logice pot fi expuse în două locuri, fiecare cu propriul declanșator:
  • toolTriggerSettings — face funcția descoperibilă de către funcționalitățile AI ale Twenty (chat, MCP, apelarea de funcții). Folosește JSON Schema standard, formatul pe care LLM-urile îl înțeleg nativ.
  • workflowActionTriggerSettings — determină ca funcția să apară ca un pas în constructorul vizual de fluxuri de lucru. Folosește InputSchema bogat al Twenty, astfel încât constructorul să poată afișa editori de câmp adecvați, selectoare de variabile și etichete.
O funcție poate opta pentru una, cealaltă sau ambele. Acestea stau alături de cronTriggerSettings, databaseEventTriggerSettings și httpRouteTriggerSettings — același tipar, aceeași formă.
src/logic-functions/enrich-company.logic-function.ts
import { defineLogicFunction } from 'twenty-sdk/define';
import { CoreApiClient } from 'twenty-client-sdk/core';

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,
  toolTriggerSettings: {},
});
Puncte cheie:
  • O funcție poate combina suprafețele — declară atât toolTriggerSettings, cât și workflowActionTriggerSettings pentru a o expune atât în chat, cât și în constructorul de fluxuri de lucru.
  • toolTriggerSettings.inputSchema și workflowActionTriggerSettings.inputSchema sunt ambele opționale. Când sunt omise, generatorul de manifest le deduce din codul sursă al handlerului (JSON Schema pentru instrumentul AI, InputSchema al Twenty pentru acțiunea de flux de lucru). Furnizează unul în mod explicit atunci când dorești o tipizare mai bogată — de exemplu, cu câmpuri compatibile cu FieldMetadataType, precum CURRENCY sau RELATION pentru constructorul de fluxuri de lucru, sau cu câmpuri description pe care agentul AI le poate citi:
export default defineLogicFunction({
  ...,
  toolTriggerSettings: {
    inputSchema: {
      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'],
    },
  },
});
Scrieți o description bună. Agenții AI se bazează pe câmpul description al funcției pentru a decide când să folosească instrumentul. Fiți specifici cu privire la ceea ce face instrumentul și când ar trebui apelat.
O funcție post-instalare este o funcție logică care rulează automat după instalarea aplicației într-un spațiu de lucru. Serverul o execută după ce metadatele aplicației au fost sincronizate și clientul SDK a fost generat, astfel încât spațiul de lucru este complet pregătit pentru utilizare, iar noua schemă este disponibilă. Cazuri tipice de utilizare includ popularea cu date implicite, crearea de înregistrări inițiale, configurarea setărilor spațiului de lucru sau provizionarea resurselor în cadrul serviciilor terților.
src/logic-functions/post-install.ts
import { definePostInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';

const handler = async (payload: InstallPayload): Promise<void> => {
  console.log('Post install logic function executed successfully!', payload.previousVersion);
};

export default definePostInstallLogicFunction({
  universalIdentifier: 'f7a2b9c1-3d4e-5678-abcd-ef9876543210',
  name: 'post-install',
  description: 'Runs after installation to set up the application.',
  timeoutSeconds: 300,
  shouldRunOnVersionUpgrade: false,
  shouldRunSynchronously: false,
  handler,
});
Puteți, de asemenea, să executați manual funcția post-instalare oricând folosind CLI:
yarn twenty exec --postInstall
Puncte cheie:
  • Funcțiile de post-instalare folosesc definePostInstallLogicFunction() — o variantă specializată care omite setările de declanșare (cronTriggerSettings, databaseEventTriggerSettings, httpRouteTriggerSettings, toolTriggerSettings, workflowActionTriggerSettings).
  • Handlerul primește un InstallPayload cu { previousVersion?: string; newVersion: string }newVersion este versiunea care este instalată, iar previousVersion este versiunea instalată anterior (sau undefined la o instalare nouă). Folosiți aceste valori pentru a distinge instalările noi de actualizări și pentru a rula logică de migrare specifică versiunii.
  • Când rulează hook-ul: doar la instalări noi, în mod implicit. Transmiteți shouldRunOnVersionUpgrade: true dacă doriți să ruleze și atunci când aplicația este actualizată de la o versiune anterioară. Când este omis, indicatorul are implicit valoarea false, iar actualizările sar peste hook.
  • Model de execuție — implicit asincron, sincron opțional: indicatorul shouldRunSynchronously controlează modul în care este executat post-install.
    • shouldRunSynchronously: false (implicit) — hook-ul este pus în coadă în message queue cu retryLimit: 3 și rulează asincron într-un worker. Răspunsul la instalare revine imediat ce jobul este pus în coadă, astfel încât un handler lent sau care eșuează nu blochează apelantul. Workerul va reîncerca de până la trei ori. Folosiți acest mod pentru joburi de lungă durată — popularea unor seturi mari de date, apelarea API-urilor lente ale terților, provizionarea resurselor externe, orice ar putea depăși o fereastră rezonabilă de răspuns HTTP.
    • shouldRunSynchronously: true — hook-ul este executat inline în timpul fluxului de instalare (același executor ca pre-install). Cererea de instalare blochează până când handlerul se termină, iar dacă acesta aruncă o eroare, apelantul instalării primește un POST_INSTALL_ERROR. Fără reîncercări automate. Folosiți acest mod pentru sarcini rapide, care trebuie să se finalizeze înainte de răspuns — de exemplu, emiterea unei erori de validare către utilizator sau o configurare rapidă de care clientul va depinde imediat după ce apelul de instalare revine. Reține că migrarea metadatelor a fost deja aplicată până când rulează post-install, astfel încât un eșec în modul sincron nu anulează modificările de schemă — doar expune eroarea.
  • Asigurați-vă că handlerul dvs. este idempotent. În modul asincron, coada poate reîncerca de până la trei ori; în oricare mod, hook-ul poate rula din nou la actualizări când shouldRunOnVersionUpgrade: true.
  • Variabilele de mediu APPLICATION_ID, APP_ACCESS_TOKEN și API_URL sunt disponibile în interiorul handlerului (la fel ca în orice altă funcție logică), astfel încât puteți apela API-ul Twenty cu un token de acces al aplicației limitat la aplicația dvs.
  • Este permisă o singură funcție de post-instalare per aplicație. Construirea manifestului va genera o eroare dacă este detectată mai mult de una.
  • universalIdentifier, shouldRunOnVersionUpgrade și shouldRunSynchronously ale funcției sunt atașate automat la manifestul aplicației în câmpul postInstallLogicFunction în timpul build-ului — nu este nevoie să le referi în defineApplication().
  • Timpul de expirare implicit este setat la 300 de secunde (5 minute) pentru a permite sarcini de configurare mai lungi, cum ar fi popularea datelor.
  • Nu se execută în modul dev: când o aplicație este înregistrată local (prin yarn twenty dev), serverul sare complet peste fluxul de instalare și sincronizează fișierele direct prin watcher-ul CLI — astfel încât post-install nu rulează niciodată în modul dev, indiferent de shouldRunSynchronously. Folosiți yarn twenty exec --postInstall pentru a-l declanșa manual într-un workspace care rulează.
O funcție de pre-instalare este o funcție logică ce rulează automat în timpul instalării, înainte ca migrarea metadatelor workspace-ului să fie aplicată. Are aceeași structură a payload-ului ca post-install (InstallPayload), dar este plasată mai devreme în fluxul de instalare, astfel încât poate pregăti starea de care depinde migrarea iminentă — utilizări tipice includ realizarea unui backup al datelor, validarea compatibilității cu noua schemă sau arhivarea înregistrărilor care urmează să fie restructurate sau eliminate.
src/logic-functions/pre-install.ts
import { definePreInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';

const handler = async (payload: InstallPayload): Promise<void> => {
  console.log('Pre install logic function executed successfully!', payload.previousVersion);
};

export default definePreInstallLogicFunction({
  universalIdentifier: 'a1b2c3d4-5678-90ab-cdef-1234567890ab',
  name: 'pre-install',
  description: 'Runs before installation to prepare the application.',
  timeoutSeconds: 300,
  shouldRunOnVersionUpgrade: true,
  handler,
});
Puteți, de asemenea, să executați manual funcția de pre-instalare oricând folosind CLI:
yarn twenty exec --preInstall
Puncte cheie:
  • Funcțiile de pre-instalare folosesc definePreInstallLogicFunction() — aceeași configurare specializată ca pentru post-install, doar că atașată la un alt punct din ciclul de viață.
  • Atât handlerele de pre-install, cât și cele de post-install primesc același tip InstallPayload: { previousVersion?: string; newVersion: string }. Importați-l o singură dată și reutilizați-l pentru ambele hook-uri.
  • Când rulează hook-ul: poziționat chiar înainte de migrarea metadatelor workspace-ului (synchronizeFromManifest). Înainte de execuție, serverul rulează un “sync redus”, pur aditiv, care înregistrează funcția de pre-instalare a versiunii noi în metadatele workspace-ului — nimic altceva nu este atins — și apoi o execută. Deoarece acest sync este doar aditiv, obiectele, câmpurile și datele versiunii precedente sunt încă intacte când rulează handlerul dvs.: puteți citi și face backup în siguranță stării pre-migrare.
  • Model de execuție: pre-install este executat sincron și blochează instalarea. Dacă handlerul aruncă o eroare, instalarea este întreruptă înainte ca orice modificări de schemă să fie aplicate — workspace-ul rămâne la versiunea anterioară într-o stare consistentă. Acest lucru este intenționat: pre-install este ultima dvs. șansă de a refuza o actualizare riscantă.
  • La fel ca la post-install, este permisă o singură funcție de pre-instalare per aplicație. Este atașată automat la manifestul aplicației sub preInstallLogicFunction în timpul build-ului.
  • Nu se execută în modul dev: la fel ca post-install — fluxul de instalare este sărit complet pentru aplicațiile înregistrate local, astfel încât pre-install nu rulează niciodată sub yarn twenty dev. Folosiți yarn twenty exec --preInstall pentru a-l declanșa manual.
Ambele hook-uri fac parte din același flux de instalare și primesc același InstallPayload. Diferența constă în momentul în care rulează în raport cu migrarea metadatelor workspace-ului, iar asta schimbă ce date pot atinge în siguranță.
┌─────────────────────────────────────────────────────────────┐
│ install flow                                                │
│                                                             │
│   upload package → [pre-install] → metadata migration →     │
│   generate SDK → [post-install]                             │
│                                                             │
│                  old schema visible    new schema visible   │
└─────────────────────────────────────────────────────────────┘
Pre-install este întotdeauna sincron (blochează instalarea și o poate întrerupe). Post-install este implicit asincron — pus în coadă pe un worker cu reîncercări automate — dar poate opta pentru execuție sincronă cu shouldRunSynchronously: true. Consultați acordeonul definePostInstallLogicFunction de mai sus pentru când să folosiți fiecare mod.Folosiți post-install pentru orice are nevoie ca noua schemă să existe. Acesta este cazul obișnuit:
  • Popularea datelor implicite (crearea înregistrărilor inițiale, a vizualizărilor implicite, a conținutului demo) pentru obiectele și câmpurile adăugate recent.
  • Înregistrarea webhook-urilor la servicii terțe, acum că aplicația are acreditările sale.
  • Apelarea propriului tău API pentru a finaliza configurarea care depinde de metadatele sincronizate.
  • Logică idempotentă de tipul “asigurați-vă că acest lucru există” care ar trebui să reconcilieze starea la fiecare actualizare — combină cu shouldRunOnVersionUpgrade: true.
Exemplu — populează o înregistrare PostCard implicită după instalare:
src/logic-functions/post-install.ts
import { definePostInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
import { createClient } from './generated/client';

const handler = async ({ previousVersion }: InstallPayload): Promise<void> => {
  if (previousVersion) return; // fresh installs only

  const client = createClient();
  await client.postCard.create({
    data: { title: 'Welcome to Postcard', content: 'Your first card!' },
  });
};

export default definePostInstallLogicFunction({
  universalIdentifier: 'f7a2b9c1-3d4e-5678-abcd-ef9876543210',
  name: 'post-install',
  description: 'Seeds a welcome post card after install.',
  timeoutSeconds: 300,
  shouldRunOnVersionUpgrade: false,
  handler,
});
Folosiți pre-install atunci când o migrare altfel ar distruge sau ar corupe datele existente. Deoarece pre-install rulează pe schema anterioară și eșecul său anulează actualizarea, acesta este locul potrivit pentru orice este riscant:
  • Crearea unui backup al datelor care urmează să fie eliminate sau restructurate — de exemplu, elimini un câmp în v2 și trebuie să-i copiezi valorile într-un alt câmp sau să le exporți în stocare înainte de rularea migrării.
  • Arhivarea înregistrărilor pe care o nouă constrângere le-ar invalida — de exemplu, un câmp devine NOT NULL și trebuie mai întâi să ștergi sau să corectezi rândurile cu valori nule.
  • Validarea compatibilității și refuzarea actualizării dacă datele curente nu pot fi migrate fără probleme — aruncă din handler și instalarea se oprește fără ca modificări să fie aplicate. Aceasta este mai sigur decât să descoperi incompatibilitatea în mijlocul migrării.
  • Redenumirea sau schimbarea cheilor datelor înaintea unei modificări de schemă care ar pierde asocierile.
Exemplu — arhivează înregistrări înainte de o migrare distructivă:
src/logic-functions/pre-install.ts
import { definePreInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
import { createClient } from './generated/client';

const handler = async ({ previousVersion, newVersion }: InstallPayload): Promise<void> => {
  // Only the 1.x → 2.x upgrade drops the legacy `notes` field.
  if (!previousVersion?.startsWith('1.') || !newVersion.startsWith('2.')) {
    return;
  }

  const client = createClient();
  const legacyRecords = await client.postCard.findMany({
    where: { notes: { isNotNull: true } },
  });

  if (legacyRecords.length === 0) return;

  // Copy legacy `notes` into the new `description` field before the migration
  // drops the `notes` column. If this fails, the upgrade is aborted and the
  // workspace stays on v1 with all data intact.
  await Promise.all(
    legacyRecords.map((record) =>
      client.postCard.update({
        where: { id: record.id },
        data: { description: record.notes },
      }),
    ),
  );
};

export default definePreInstallLogicFunction({
  universalIdentifier: 'a1b2c3d4-5678-90ab-cdef-1234567890ab',
  name: 'pre-install',
  description: 'Backs up legacy notes into description before the v2 migration.',
  timeoutSeconds: 300,
  shouldRunOnVersionUpgrade: true,
  handler,
});
Regulă practică:
Vrei să…Folosiți
Populați date implicite, configurați workspace-ul, înregistrați resurse externepost-install
Rulați populări de durată sau apeluri către terți care nu ar trebui să blocheze răspunsul la instalarepost-install (implicit — shouldRunSynchronously: false, cu reîncercări ale workerului)
Rulați o configurare rapidă de care apelantul va depinde imediat după ce apelul de instalare revinepost-install cu shouldRunSynchronously: true
Citești sau faci backup datelor pe care migrarea iminentă le-ar pierdepre-install
Respingeți o actualizare care ar corupe datele existentepre-install (aruncă din handler)
Rulați o reconciliere la fiecare actualizarepost-install cu shouldRunOnVersionUpgrade: true
Faceți o configurare unică doar la prima instalarepost-install cu shouldRunOnVersionUpgrade: false (implicit)
Dacă aveți dubii, alegeți implicit post-install. Apelați la pre-install doar când migrarea în sine este distructivă și trebuie să interceptați starea anterioară înainte să dispară.

Clienți API tipizați (twenty-client-sdk)

Pachetul twenty-client-sdk oferă doi clienți GraphQL tipați pentru a interacționa cu API-ul Twenty din funcțiile de logică și componentele Front.
ClientImportațiEndpointGenerat?
CoreApiClienttwenty-client-sdk/core/graphql — date ale spațiului de lucru (înregistrări, obiecte)Da, în timpul dev/build
MetadataApiClienttwenty-client-sdk/metadata/metadata — configurarea spațiului de lucru, încărcări de fișiereNu, este livrat preconstruit
CoreApiClient este clientul principal pentru interogarea și modificarea datelor din spațiul de lucru. Este generat din schema spațiului de lucru în timpul yarn twenty dev sau yarn twenty build, astfel încât este complet tipizat pentru a corespunde obiectelor și câmpurilor dvs.
import { CoreApiClient } from 'twenty-client-sdk/core';

const client = new CoreApiClient();

// Query records
const { companies } = await client.query({
  companies: {
    edges: {
      node: {
        id: true,
        name: true,
        domainName: {
          primaryLinkLabel: true,
          primaryLinkUrl: true,
        },
      },
    },
  },
});

// Create a record
const { createCompany } = await client.mutation({
  createCompany: {
    __args: {
      data: {
        name: 'Acme Corp',
      },
    },
    id: true,
    name: true,
  },
});
Clientul folosește o sintaxă de tip selection-set: transmiteți true pentru a include un câmp, folosiți __args pentru argumente și imbricați obiecte pentru relații. Obțineți autocompletare și verificare a tipurilor complete, pe baza schemei spațiului dvs. de lucru.
CoreApiClient este generat în timpul dev/build. Dacă îl utilizați fără a rula mai întâi yarn twenty dev sau yarn twenty build, va arunca o eroare. Generarea are loc automat — CLI inspectează schema GraphQL a spațiului dvs. de lucru și generează un client tipizat folosind @genql/cli.

Folosirea CoreSchema pentru adnotări de tip

CoreSchema oferă tipuri TypeScript care corespund obiectelor din spațiul dvs. de lucru — utile pentru tiparea stării componentelor sau a parametrilor funcțiilor:
import { CoreApiClient, CoreSchema } from 'twenty-client-sdk/core';
import { useState } from 'react';

const [company, setCompany] = useState<
  Pick<CoreSchema.Company, 'id' | 'name'> | undefined
>(undefined);

const client = new CoreApiClient();
const result = await client.query({
  company: {
    __args: { filter: { position: { eq: 1 } } },
    id: true,
    name: true,
  },
});
setCompany(result.company);
MetadataApiClient este livrat preconstruit împreună cu SDK-ul (nu este necesară generarea). Interoghează endpointul /metadata pentru configurarea spațiului de lucru, aplicații și încărcări de fișiere.
import { MetadataApiClient } from 'twenty-client-sdk/metadata';

const metadataClient = new MetadataApiClient();

// List first 10 objects in the workspace
const { objects } = await metadataClient.query({
  objects: {
    edges: {
      node: {
        id: true,
        nameSingular: true,
        namePlural: true,
        labelSingular: true,
        isCustom: true,
      },
    },
    __args: {
      filter: {},
      paging: { first: 10 },
    },
  },
});

Încărcarea fișierelor

MetadataApiClient include o metodă uploadFile pentru atașarea fișierelor la câmpuri de tip fișier:
import { MetadataApiClient } from 'twenty-client-sdk/metadata';
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
  '58a0a314-d7ea-4865-9850-7fb84e72f30b',            // field universalIdentifier
);

console.log(uploadedFile);
// { id: '...', path: '...', size: 12345, createdAt: '...', url: 'https://...' }
ParametruTipDescriere
fileBufferBufferConținutul brut al fișierului
filenamestringNumele fișierului (folosit pentru stocare și afișare)
contentTypestringTipul MIME (implicit application/octet-stream dacă este omis)
fieldMetadataUniversalIdentifierstringuniversalIdentifier al câmpului de tip fișier de pe obiectul dvs.
Puncte cheie:
  • Folosește universalIdentifier al câmpului (nu ID-ul specific spațiului de lucru), astfel încât codul dvs. de încărcare funcționează în orice spațiu de lucru în care aplicația dvs. este instalată.
  • url returnat este un URL semnat pe care îl puteți folosi pentru a accesa fișierul încărcat.
Când codul dvs. rulează pe Twenty (funcții de logică sau componente Front), platforma injectează acreditările ca variabile de mediu:
  • TWENTY_API_URL — URL-ul de bază al API-ului Twenty
  • TWENTY_APP_ACCESS_TOKEN — Cheie cu durată scurtă, limitată la rolul implicit de funcție al aplicației
Nu trebuie să le transmiteți clienților — aceștia citesc automat din process.env. Permisiunile cheii API sunt determinate de rolul referențiat în defaultRoleUniversalIdentifier din application-config.ts.