{
  "application": {
    "universalIdentifier": "dcbd3557-85e1-4707-a634-38bc7b93691e",
    "displayName": "sajn",
    "description": "Create sajn documents from Twenty opportunities and keep signing status visible in your CRM.",
    "logo": "public/sajn-logo.png",
    "author": "sajn",
    "category": "Productivity",
    "websiteUrl": "https://www.sajn.se",
    "termsUrl": "https://www.sajn.se/allmanna-villkor",
    "emailSupport": "hej@sajn.se",
    "serverVariables": {
      "SAJN_OAUTH_CLIENT_ID": {
        "description": "The OAuth client ID registered in sajn for this Twenty server.",
        "isSecret": false,
        "isRequired": true
      },
      "SAJN_OAUTH_CLIENT_SECRET": {
        "description": "The OAuth client secret registered in sajn for this Twenty server.",
        "isSecret": true,
        "isRequired": true
      }
    },
    "galleryImages": [
      "public/cover.generated.png"
    ],
    "defaultRoleUniversalIdentifier": "3eeb054b-0fce-42de-bf2a-621c25dfffab",
    "aboutDescription": "# sajn for Twenty\n\nCreate, send, and track e-signature documents directly from your CRM.\n\n## Turn opportunities into signed agreements\n\nsajn connects your Twenty opportunities with your signing workflow. Start a\ndocument from a sajn template, prefill it with the opportunity and point of\ncontact, and send it for signing without copying customer details between\nsystems.\n\n## What you can do\n\n- Create a draft or send a document from an Opportunity.\n- Use the Opportunity name, value, and point-of-contact details automatically.\n- See every related sajn document inside Twenty.\n- Follow signing progress from draft to completion.\n- Open the document in sajn whenever you need to review or edit it.\n\n## Get started\n\nOnce your workspace administrator has connected sajn, open an Opportunity and\nchoose **Create sajn document** from the command menu.\n\nNeed help? Contact [hej@sajn.se](mailto:hej@sajn.se).\n",
    "yarnLockChecksum": null,
    "packageJsonChecksum": "359660af8db32be90da61bdb4c800b6b",
    "requiredServerVersionRange": ">=2.30.0",
    "settingsFrontComponent": {
      "universalIdentifier": "9acda8f5-1063-465d-bbcb-f2aca2592fab"
    }
  },
  "objects": [
    {
      "universalIdentifier": "9183a06f-f26e-4668-a7d5-b2c7b610c2c7",
      "nameSingular": "sajnDocument",
      "namePlural": "sajnDocuments",
      "labelSingular": "sajn document",
      "labelPlural": "sajn documents",
      "description": "An e-signature document created and managed in sajn.",
      "icon": "IconSignature",
      "labelIdentifierFieldMetadataUniversalIdentifier": "21bb0641-85a6-4481-8b48-d386c52e430c",
      "fields": [
        {
          "universalIdentifier": "21bb0641-85a6-4481-8b48-d386c52e430c",
          "type": "TEXT",
          "name": "name",
          "label": "Name",
          "icon": "IconFileText"
        },
        {
          "universalIdentifier": "825ccb9a-3633-4788-a58e-9902ed903d3e",
          "type": "TEXT",
          "name": "sajnDocumentId",
          "label": "sajn document ID",
          "icon": "IconId"
        },
        {
          "universalIdentifier": "735aadd1-0461-47dd-ace2-5e8df2612d40",
          "type": "SELECT",
          "name": "status",
          "label": "Signing status",
          "icon": "IconProgress",
          "defaultValue": "'DRAFT'",
          "options": [
            {
              "id": "f0bfc693-e3ac-4816-b9a1-0e6f324dfdea",
              "value": "DRAFT",
              "label": "Draft",
              "color": "gray",
              "position": 0
            },
            {
              "id": "19fa1fd9-04e7-44e8-b692-a3dfea2abf5e",
              "value": "PENDING",
              "label": "Awaiting signatures",
              "color": "blue",
              "position": 1
            },
            {
              "id": "39c29a2b-daf5-48b4-bcaa-e19ff06e1f09",
              "value": "ACTION_REQUIRED",
              "label": "Action required",
              "color": "orange",
              "position": 2
            },
            {
              "id": "42d5d3ec-ba7e-465a-8389-aa69b17a05f8",
              "value": "COMPLETED",
              "label": "Completed",
              "color": "green",
              "position": 3
            },
            {
              "id": "98f3c604-2cd0-4ca7-970e-e03e80eae9ab",
              "value": "CLOSED",
              "label": "Closed",
              "color": "red",
              "position": 4
            }
          ]
        },
        {
          "universalIdentifier": "b00b934e-3ad9-482b-98c4-e04784b67ed6",
          "type": "TEXT",
          "name": "recipientEmail",
          "label": "Recipient email",
          "icon": "IconMail"
        },
        {
          "universalIdentifier": "ca34d779-1f3a-457a-bd1d-2a821fc1ba51",
          "type": "TEXT",
          "name": "sajnUrl",
          "label": "Open in sajn",
          "icon": "IconExternalLink"
        }
      ]
    }
  ],
  "fields": [
    {
      "universalIdentifier": "195a970e-2dd4-4d7c-aa97-d71a30131b5e",
      "objectUniversalIdentifier": "20202020-9549-49dd-b2b2-883999db8938",
      "type": "RELATION",
      "name": "sajnDocuments",
      "label": "sajn documents",
      "icon": "IconSignature",
      "relationTargetObjectMetadataUniversalIdentifier": "9183a06f-f26e-4668-a7d5-b2c7b610c2c7",
      "relationTargetFieldMetadataUniversalIdentifier": "7020eaeb-e994-4fcf-8d23-ae697eeac2b3",
      "universalSettings": {
        "relationType": "ONE_TO_MANY"
      }
    },
    {
      "universalIdentifier": "7020eaeb-e994-4fcf-8d23-ae697eeac2b3",
      "objectUniversalIdentifier": "9183a06f-f26e-4668-a7d5-b2c7b610c2c7",
      "type": "RELATION",
      "name": "opportunity",
      "label": "Opportunity",
      "icon": "IconTargetArrow",
      "relationTargetObjectMetadataUniversalIdentifier": "20202020-9549-49dd-b2b2-883999db8938",
      "relationTargetFieldMetadataUniversalIdentifier": "195a970e-2dd4-4d7c-aa97-d71a30131b5e",
      "universalSettings": {
        "relationType": "MANY_TO_ONE",
        "onDelete": "SET_NULL",
        "joinColumnName": "opportunityId"
      }
    }
  ],
  "indexes": [],
  "permissionFlags": [],
  "roles": [
    {
      "universalIdentifier": "3eeb054b-0fce-42de-bf2a-621c25dfffab",
      "label": "sajn integration role",
      "description": "Reads opportunities and their linked contact, then creates and updates sajn document records. It cannot delete CRM data.",
      "canReadAllObjectRecords": false,
      "canUpdateAllObjectRecords": false,
      "canSoftDeleteAllObjectRecords": false,
      "canDestroyAllObjectRecords": false,
      "canUpdateAllSettings": false,
      "canBeAssignedToAgents": false,
      "canBeAssignedToUsers": false,
      "canBeAssignedToApiKeys": false,
      "objectPermissions": [
        {
          "objectUniversalIdentifier": "20202020-9549-49dd-b2b2-883999db8938",
          "canReadObjectRecords": true,
          "canUpdateObjectRecords": false,
          "canSoftDeleteObjectRecords": false,
          "canDestroyObjectRecords": false,
          "universalIdentifier": "14bc7f09-d5c3-5da7-a9eb-97f28dab44d1"
        },
        {
          "objectUniversalIdentifier": "20202020-e674-48e5-a542-72570eee7213",
          "canReadObjectRecords": true,
          "canUpdateObjectRecords": false,
          "canSoftDeleteObjectRecords": false,
          "canDestroyObjectRecords": false,
          "universalIdentifier": "195c6a9c-112d-57f0-82d2-161a82ab3315"
        },
        {
          "objectUniversalIdentifier": "20202020-b374-4779-a561-80086cb2e17f",
          "canReadObjectRecords": true,
          "canUpdateObjectRecords": false,
          "canSoftDeleteObjectRecords": false,
          "canDestroyObjectRecords": false,
          "universalIdentifier": "9930d1f3-100a-52f5-9d59-8645610bce78"
        },
        {
          "objectUniversalIdentifier": "9183a06f-f26e-4668-a7d5-b2c7b610c2c7",
          "canReadObjectRecords": true,
          "canUpdateObjectRecords": true,
          "canSoftDeleteObjectRecords": false,
          "canDestroyObjectRecords": false,
          "universalIdentifier": "46c7022e-ee47-57bc-99a2-60814af58678"
        }
      ],
      "fieldPermissions": [],
      "permissionFlagUniversalIdentifiers": [
        "9faa55f7-2606-566b-9e1d-aefbedbd0136"
      ],
      "rowLevelPermissionPredicateGroups": [],
      "rowLevelPermissionPredicates": []
    }
  ],
  "skills": [],
  "agents": [],
  "connectionProviders": [
    {
      "universalIdentifier": "21f01ea2-4169-4146-9074-8bb17bd6653a",
      "name": "sajn",
      "displayName": "sajn",
      "type": "oauth",
      "oauth": {
        "authorizationEndpoint": "https://app.sajn.se/oauth/authorize",
        "tokenEndpoint": "https://app.sajn.se/api/oauth/token",
        "revokeEndpoint": "https://app.sajn.se/api/oauth/revoke",
        "scopes": [
          "documents:read",
          "documents:write",
          "templates:read",
          "webhooks:read",
          "webhooks:write"
        ],
        "clientIdVariable": "SAJN_OAUTH_CLIENT_ID",
        "clientSecretVariable": "SAJN_OAUTH_CLIENT_SECRET",
        "tokenRequestContentType": "form-urlencoded",
        "usePkce": true
      },
      "onConnectLogicFunction": {
        "universalIdentifier": "338a86df-d122-45fe-aa40-ad6a447da33d"
      },
      "onDisconnectLogicFunction": {
        "universalIdentifier": "f090c423-29b5-44f3-8f54-5401b85b0b46"
      }
    }
  ],
  "logicFunctions": [
    {
      "universalIdentifier": "14542f60-d122-41f9-acbc-9f9f8c601e4a",
      "name": "create-sajn-document",
      "description": "Creates a sajn document from a Twenty opportunity and stores the linked CRM record.",
      "timeoutSeconds": 30,
      "httpRouteTriggerSettings": {
        "path": "/sajn/documents",
        "httpMethod": "POST",
        "isAuthRequired": true
      },
      "handlerName": "default.config.handler",
      "sourceHandlerPath": "src/logic-functions/create-document-route.ts",
      "builtHandlerPath": "src/logic-functions/create-document-route.mjs",
      "builtHandlerChecksum": "edf564a993b25ae8c5884286197ca2be"
    },
    {
      "universalIdentifier": "2af6d521-d51e-4b5d-b784-df71f1d2e4e5",
      "name": "list-sajn-templates",
      "description": "Lists sajn templates using the current user's OAuth connection.",
      "timeoutSeconds": 15,
      "httpRouteTriggerSettings": {
        "path": "/sajn/templates",
        "httpMethod": "GET",
        "isAuthRequired": true
      },
      "handlerName": "default.config.handler",
      "sourceHandlerPath": "src/logic-functions/list-templates-route.ts",
      "builtHandlerPath": "src/logic-functions/list-templates-route.mjs",
      "builtHandlerChecksum": "3448ae25cc645dd3a0e3dec129a52b67"
    },
    {
      "universalIdentifier": "338a86df-d122-45fe-aa40-ad6a447da33d",
      "name": "configure-sajn-after-connect",
      "description": "Creates the sajn status webhook after OAuth connection.",
      "timeoutSeconds": 30,
      "handlerName": "default.config.handler",
      "sourceHandlerPath": "src/logic-functions/on-sajn-connect.ts",
      "builtHandlerPath": "src/logic-functions/on-sajn-connect.mjs",
      "builtHandlerChecksum": "79fcbf6db0e2d100816798feb462df4d"
    },
    {
      "universalIdentifier": "40a24893-12e3-4d0a-82e1-af0c56032b26",
      "name": "sajn-webhook",
      "description": "Synchronizes sajn document lifecycle events into Twenty.",
      "timeoutSeconds": 15,
      "httpRouteTriggerSettings": {
        "path": "/webhook/sajn",
        "httpMethod": "POST",
        "isAuthRequired": false,
        "forwardedRequestHeaders": [
          "x-sajn-secret",
          "x-sajn-environment"
        ]
      },
      "handlerName": "default.config.handler",
      "sourceHandlerPath": "src/logic-functions/webhook-route.ts",
      "builtHandlerPath": "src/logic-functions/webhook-route.mjs",
      "builtHandlerChecksum": "1728d6178273054b7e52a23b5bd5ca77"
    },
    {
      "universalIdentifier": "b6ef4071-91af-48d4-8b3d-bb96d0e88f78",
      "name": "sync-sajn-document",
      "description": "Refreshes one sajn document's signing status in Twenty.",
      "timeoutSeconds": 15,
      "httpRouteTriggerSettings": {
        "path": "/sajn/documents/sync",
        "httpMethod": "POST",
        "isAuthRequired": true
      },
      "handlerName": "default.config.handler",
      "sourceHandlerPath": "src/logic-functions/sync-document-route.ts",
      "builtHandlerPath": "src/logic-functions/sync-document-route.mjs",
      "builtHandlerChecksum": "4a703c0104f121a0b8c9b605dddb7134"
    },
    {
      "universalIdentifier": "f090c423-29b5-44f3-8f54-5401b85b0b46",
      "name": "cleanup-sajn-after-disconnect",
      "description": "Stops accepting sajn webhooks when the last OAuth connection is removed.",
      "timeoutSeconds": 30,
      "handlerName": "default.config.handler",
      "sourceHandlerPath": "src/logic-functions/on-sajn-disconnect.ts",
      "builtHandlerPath": "src/logic-functions/on-sajn-disconnect.mjs",
      "builtHandlerChecksum": "771470936b85883392242587e21321a3"
    },
    {
      "universalIdentifier": "f980188b-de4c-4a67-b688-0925765f8483",
      "name": "setup-sajn-webhook",
      "description": "Creates or updates the sajn document-status webhook for this Twenty server.",
      "timeoutSeconds": 20,
      "httpRouteTriggerSettings": {
        "path": "/sajn/setup-webhook",
        "httpMethod": "POST",
        "isAuthRequired": true
      },
      "handlerName": "default.config.handler",
      "sourceHandlerPath": "src/logic-functions/setup-webhook-route.ts",
      "builtHandlerPath": "src/logic-functions/setup-webhook-route.mjs",
      "builtHandlerChecksum": "52bf98b0a82d296f28e6b77e7a297864"
    }
  ],
  "frontComponents": [
    {
      "universalIdentifier": "0b235b4b-1314-4c5d-bee9-5b2c26b89678",
      "name": "create-sajn-document",
      "description": "Creates a sajn document from the selected opportunity.",
      "componentName": "CreateSajnDocument",
      "sourceComponentPath": "src/front-components/create-sajn-document.front-component.tsx",
      "builtComponentPath": "src/front-components/create-sajn-document.front-component.mjs",
      "builtComponentChecksum": "d1bf2c5745992e0b0abbbc4025b4f051d80331b8be2bab3296cdbb6ea82b7a17",
      "isHeadless": false,
      "usesSdkClient": false
    },
    {
      "universalIdentifier": "315cf9d6-9c5f-4d52-8053-11485988f1a3",
      "name": "sajn-document-details",
      "description": "Shows the linked sajn document and refreshes its status.",
      "componentName": "DocumentDetails",
      "sourceComponentPath": "src/front-components/document-details.front-component.tsx",
      "builtComponentPath": "src/front-components/document-details.front-component.mjs",
      "builtComponentChecksum": "bf88f62542d51e8b02b60253264c704737fa72d6d8750a582a19c074acdd57e6",
      "isHeadless": false,
      "usesSdkClient": true
    },
    {
      "universalIdentifier": "9acda8f5-1063-465d-bbcb-f2aca2592fab",
      "name": "sajn-settings",
      "description": "Test the sajn OAuth connection and repair status synchronization.",
      "componentName": "Settings",
      "sourceComponentPath": "src/front-components/settings.front-component.tsx",
      "builtComponentPath": "src/front-components/settings.front-component.mjs",
      "builtComponentChecksum": "25a2ca35a2f051794f4b9b376b6bc0d5fc59b8c5792bb0ee4c025dd772653ef2",
      "isHeadless": false,
      "usesSdkClient": false
    }
  ],
  "publicAssets": [
    {
      "filePath": "public/sajn-logo.png",
      "fileName": "sajn-logo.png",
      "fileType": "png",
      "checksum": "ea604f0505c868582790485f0d9cbf75"
    },
    {
      "filePath": "public/cover.generated.png",
      "fileName": "cover.generated.png",
      "fileType": "png",
      "checksum": "f5de709efa61c7d3e7b9ee036e4337bb"
    }
  ],
  "views": [
    {
      "universalIdentifier": "7f3b4a1e-1004-4e95-9ace-e065773d5d5a",
      "name": "All sajn documents",
      "objectUniversalIdentifier": "9183a06f-f26e-4668-a7d5-b2c7b610c2c7",
      "icon": "IconSignature",
      "position": 0,
      "fields": [
        {
          "universalIdentifier": "cab61baa-0092-4fc9-9e30-ca3e8c06a240",
          "fieldMetadataUniversalIdentifier": "21bb0641-85a6-4481-8b48-d386c52e430c",
          "position": 0,
          "isVisible": true,
          "size": 280
        },
        {
          "universalIdentifier": "5e5bb902-856e-48aa-ae6d-a22d5163beb4",
          "fieldMetadataUniversalIdentifier": "735aadd1-0461-47dd-ace2-5e8df2612d40",
          "position": 1,
          "isVisible": true,
          "size": 160
        },
        {
          "universalIdentifier": "57e1e044-b272-463d-9959-e6e7494ee69c",
          "fieldMetadataUniversalIdentifier": "b00b934e-3ad9-482b-98c4-e04784b67ed6",
          "position": 2,
          "isVisible": true,
          "size": 220
        }
      ]
    }
  ],
  "viewFields": [],
  "navigationMenuItems": [
    {
      "universalIdentifier": "7ea0d13e-9da7-41a1-b508-cf85cbb65bd4",
      "name": "sajn documents",
      "icon": "IconSignature",
      "color": "green",
      "position": 2,
      "type": "VIEW",
      "viewUniversalIdentifier": "7f3b4a1e-1004-4e95-9ace-e065773d5d5a"
    }
  ],
  "pageLayouts": [
    {
      "universalIdentifier": "bc1034c3-3b30-4655-ae57-b533d2bcfa52",
      "name": "sajn document record page",
      "type": "RECORD_PAGE",
      "objectUniversalIdentifier": "9183a06f-f26e-4668-a7d5-b2c7b610c2c7",
      "tabs": [
        {
          "universalIdentifier": "acbffeef-f4cb-4374-8d35-b7ac2780bc95",
          "title": "Fields",
          "position": 0,
          "icon": "IconList",
          "layoutMode": "VERTICAL_LIST",
          "widgets": [
            {
              "universalIdentifier": "a168b6c0-fd62-4949-b508-c9af05a946ab",
              "title": "Document fields",
              "type": "FIELDS",
              "configuration": {
                "configurationType": "FIELDS"
              }
            }
          ]
        },
        {
          "universalIdentifier": "25100475-396b-4bee-b353-0647ff361868",
          "title": "sajn",
          "position": 10,
          "icon": "IconSignature",
          "layoutMode": "CANVAS",
          "widgets": [
            {
              "universalIdentifier": "fc95bfcc-c857-4e4f-b063-d793643c2540",
              "title": "sajn document",
              "type": "FRONT_COMPONENT",
              "configuration": {
                "configurationType": "FRONT_COMPONENT",
                "frontComponentUniversalIdentifier": "315cf9d6-9c5f-4d52-8053-11485988f1a3"
              }
            }
          ]
        }
      ]
    }
  ],
  "pageLayoutTabs": [],
  "commandMenuItems": [
    {
      "universalIdentifier": "3bb047b7-bcb9-4bbe-a89d-caa43785e0f2",
      "label": "Create sajn document",
      "shortLabel": "Create document",
      "isPinned": true,
      "availabilityType": "RECORD_SELECTION",
      "availabilityObjectUniversalIdentifier": "20202020-9549-49dd-b2b2-883999db8938",
      "frontComponentUniversalIdentifier": "0b235b4b-1314-4c5d-bee9-5b2c26b89678"
    }
  ]
}
