Advanced No Code

Advanced No Code

Overview

Zilla includes a powerful module that can connect to any system that has API endpoints for accounts, permissions, resources, groups, group memberships and permission sets. This capability can be leveraged for both internal applications as well as SaaS applications.

What do we support with No Code V2 Config at the moment

  • Authorization

    • OAuth 2.0 Authorization Code Flow

    • OAuth 2.0 Client Credentials Flow

      • Client Credentials Flow with content-type JSON

      • Client Credentials Flow with content-type URL Encoded

      • Client Credentials Flow with content-type Multipart Form

      • Client Credentials Flow with credentials in the body with custom additional attributes like scope for the token API call

    • Basic Auth

    • Custom Headers Auth (API Key, etc.)

    • Custom Body

    • No Auth

  • API Pagination Strategy

    • Limit - Offset Strategy

    • Cursor Based Strategy

    • Next URL Strategy

    • Page Number Strategy

  • Getting accounts, permissions and account details from multiple endpoints

    • Supports all type of API methods (e.g. GET, POST, etc.)

    • Can have dynamic path (can use values from the previous API responses of the same data type)

    • Can have extra query params with dynamic variables (can use values from the previous API responses of the same data type)

    • Can have endpoint specific headers

    • Can have body with dynamic variables (can use values from the previous API responses of the same data type)

  • Getting groups, permissions and group details from multiple endpoints

    • Supports all type of API methods (e.g. GET, POST, etc.)

    • Can have dynamic path (can use values from the previous API responses of the same data type)

    • Can have extra query params with dynamic variables (can use values from the previous API responses of the same data type)

    • Can have endpoint specific headers

    • Can have body with dynamic variables (can use values from the previous API responses of the same data type)

  • Getting group members from an endpoint

    • Supports all type of API methods (e.g. GET, POST, etc.)

    • Can have dynamic path (can use group details like groupId and groupName)

    • Can have extra query params with dynamic variables (can use group details like groupId and groupName)

    • Can have endpoint specific headers

    • Can have body with dynamic variables (can use group details like groupId and groupName)

NOTE - In case of accounts sync, we expect that API response should contain list of accounts with its entitlements, not the other-way around.

// Supported [ { "id": "1", "name": "John Doe", "roles": ["Admin", "Read Only"] } ]
// Not supported [ { "role_id": "1" "role": "Admin", "users": ["John Doe", "Brody White"] } ]

How to create Advanced No Code config

Required details to create No Code V2 config

  • Base URL of the APIs

  • Authentication details of the APIs

  • Pagination strategy of the APIs

  • Details of the APIs including the sample responses

Sample Template Advanced No Code Config

{ "version": "2", "baseUrl": "<Provide Base URL Here>", "pagination": { "paginationStrategy": "<LIMIT_OFFSET / CURSOR_BASED / NEXT_URL / PAGE_NUMBER_BASED>", "paginationOverrides": { "limit": "count <Required for LIMIT_OFFSET/CURSOR_BASED/NEXT_URL>", "offset": "startIndex <Required for LIMIT_OFFSET>", "cursorKey": "cursor <Required for CURSOR_BASED>", "cursorPath": "cursor <Required for CURSOR_BASED>", "nextUrlKey": "nextPage <Required for NEXT_URL>", "pageSizeKey": "pageSize <Required for PAGE_NUMBER_BASED" "pageNumberKey": "pageNumber <Required for PAGE_NUMBER_BASED>", } }, "authorization": { "authorizationType": "<OAUTH / CLIENT_CREDENTIALS / BASIC / CUSTOM_HEADERS / NO_AUTH>", "tokenURL": "<Provide Token URL Here (Incase of OAUTH & CLIENT_CREDENTIALS)>", "clientID": "$.secrets.clientID <clientID should be provided in Secrets config>", "clientSecret": "$.secrets.clientSecret <clientSecret should be provided in Secrets config>", "scopes": "Space separated scopes <In case of OAUTH>" "authorizationHeaders": { "content-type": "application/x-www-form-urlencoded" }, "headers": { "Authorization": "'Bearer' & $.secrets.token" }, "authorizationBody": { "client_id": "$.secrets.clientID", "client_secret" : "$.secrets.clientSecret", "grant_type" : "client_credentials", "scopes": "<scopes>" } }, "accounts": { "sync": { "endpoints": [ { "name": "allusers", "path": "'Users'", "query": { "startIndex": "1", "count": "100" }, "method": "GET", "responseProperty": "Resources", "isPaginated": true, "hasMultipleItems": true }, { "name": "user_roles", "path": "'Users/' & $.allusers.id", "method": "GET", "responseProperty": "", "isPaginated": false, "hasMultipleItems": false } ], "propertyMappings": { "id": "$.allusers.id", "username": "$.allusers.displayName", "active": "$.allusers.active = true", "email": "$.allusers.emails.value[0]", "firstName": "$.allusers.name.givenName", "lastName": "$.allusers.name.familyName", "roles": "$.user_roles.entitlements.display" } }, "provision": { "endpoints": [ { "name": "checkUserExists", "path": "'Users'", "method": "GET", "query": { "filter": "'userName eq ' & $.zillaUser.email" }, "throwError": [ { "condition": "NON_EMPTY_RESPONSE", "message": "Account already exists" } ], "responseProperty": "Resources", "isPaginated": false, "hasMultipleItems": false }, { "name": "createNewUser", "path": "'Users'", "method": "POST", "body": { "userName": "$.zillaUser.email", "name": { "formatted": "$.zillaUser.displayName", "familyName": "$.zillaUser.lastName", "givenName": "$.zillaUser.firstName", "middleName": "$.zillaUser.middleName" }, "displayName": "$.zillaUser.displayName", "emails": [ { "value": "$.zillaUser.email", "type": "'work'", "primary": true } ], "active": "$.zillaUser.status = 'active'" }, "responseProperty": "", "isPaginated": false, "hasMultipleItems": false } ], "propertyMappings": { "accountId": "$.createNewUser.id", "status": "$.createNewUser.active ? 'active' : 'inactive'", "displayName": "$.createNewUser.displayName" } }, "revoke": { "endpoints": [ { "name": "revokeUser", "path": "'Users/' & $.zillaAccount.accountId", "method": "PATCH", "body": { "schemas": [ "'urn:ietf:params:scim:api:messages:2.0:PatchOp'" ], "Operations": [ { "op": "'replace'", "value": { "active": false } } ] }, "responseProperty": "", "isPaginated": false, "hasMultipleItems": false } ], "propertyMappings": { "accountId": "$.revokeUser.id", "status": "$.revokeUser.active ? 'active' : 'inactive'", "displayName": "$.revokeUser.displayName" } }, "provisionPermission": { "endpoints": [ { "name": "assignPermission", "path": "'Users/' & $.zillaAccount.accountId", "method": "PATCH", "body": { "schemas": [ "'urn:ietf:params:scim:api:messages:2.0:PatchOp'" ], "Operations": [ { "op": "'add'", "value": { "entitlements": [ { "value": "$.zillaPermission.name" } ] } } ] }, "responseProperty": "", "isPaginated": false, "hasMultipleItems": false } ] }, "revokePermission": { "endpoints": [ { "name": "revokePermission", "path": "'Users/' & $.zillaAccount.accountId", "method": "GET", "body": { "schemas": [ "'urn:ietf:params:scim:api:messages:2.0:PatchOp'" ], "Operations": [ { "op": "'remove'", "path": "'entitlements'", "value": { "entitlements": [ { "value": "$.zillaPermission.name" } ] } } ] }, "responseProperty": "", "isPaginated": false, "hasMultipleItems": false } ] } }, "groups": { "sync": { "endpoints": [ { "name": "allgroups", "path": "'Groups'", "method": "GET", "query": { "startIndex": "'1'", "count": "'100'" }, "responseProperty": "Resources", "isPaginated": true, "hasMultipleItems": true } ], "propertyMappings": { "id": "$.allgroups.id", "displayName": "$.allgroups.displayName", "description": "$.allgroups.description", "email": "$.allgroups.email", "roles": "$.allgroups.entitlements.display" } } }, "groupMembers": { "sync": { "endpoints": [ { "name": "group_members", "path": "'Groups/' & $.groupId", "method": "GET", "responseProperty": "", "isPaginated": false, "hasMultipleItems": false } ], "propertyMappings": { "userIds": "$.group_members.members" } } } }

Zilla Context Object

We should use the Zilla Context Object to form the API details (path, query, body) for the provisioning APIs. Copy the below json and past it into the jsonata exerciser or the jsonata studio playground. Then you can create the jsonata expressions and use them in the API details.

{ "zillaUser": { "id": "internal-zilla-user-id", "firstName": "Anneke", "middleName": "P", "lastName": "Preusig", "displayName": "Anneke Preusig", "email": "anneke.preusig@zsec.io", "allEmails": [ "anneke.preusig@zsec.io" ], "title": "Sales Engineer", "department": "Engineering", "manager": "georgi.facello@zsec.io", "status": "active", "hasManager": true, "isUserOnboarded": false, "universalIds": [{ "key": "aadEmployeeId", "value": "1234" }] }, "zillaAccount": { "id": "internal-zilla-account-id", "accountId": "anneke.preusig@zsec.io", "firstName": "Anneke", "middleName": "P", "lastName": "Preusig", "displayName": "Anneke Preusig", "email": "anneke.preusig@zsec.io", "metadata": { }, "status": "active", "accountType": "user" }, "zillaPermission": { "name": "Admin / member (incase of group membership)", "resource": "name-of-the-group", "sourceData": { "groupId": "group-id-from-the-source-system" }, "groupId": "group-id-from-the-source-system", "groupName": "name-of-the-group" } }

Example Advanced No Code Config

Salesforce

{ "version": "v2", "baseUrl": "https://computing-platform-4092.my.salesforce.com/services/scim/v2", "pagination": { "paginationStrategy": "LIMIT_OFFSET", "paginationOverrides": { "limit": "count", "offset": "startIndex" } }, "authorization": { "authorizationType": "CLIENT_CREDENTIALS", "tokenURL": "https://computing-platform-4092.my.salesforce.com/services/oauth2/token", "clientID": "$.secrets.clientID", "clientSecret": "$.secrets.clientSecret", "authorizationHeaders": { "content-type": "application/x-www-form-urlencoded" } }, "accounts": { "sync": { "endpoints": [ { "name": "allUsers", "path": "'Users'", "method": "GET", "query": { "startIndex": "'1'", "count": "'100'" }, "responseProperty": "Resources", "isPaginated": true, "hasMultipleItems": true } ], "propertyMappings": { "id": "$.allUsers.id", "username": "$.allUsers.displayName", "active": "$.allUsers.active", "email": "$.allUsers.emails.value[0]", "firstName": "$.allUsers.name.givenName", "lastName": "$.allUsers.name.familyName", "roles": "$.allUsers.entitlements.display" } }, "provision": { "endpoints": [ { "name": "checkUserExists", "path": "'Users'", "method": "GET", "query": { "filter": "'userName eq ' & '\"' & $.zillaUser.email & '\"'" }, "throwError": [ { "condition": "NON_EMPTY_RESPONSE", "message": "Account already exists" } ], "responseProperty": "Resources", "isPaginated": false, "hasMultipleItems": false }, { "name": "createNewUser", "path": "'Users'", "method": "POST", "body": { "userName": "$.zillaUser.email", "name": { "formatted": "$.zillaUser.displayName", "familyName": "$.zillaUser.lastName", "givenName": "$.zillaUser.firstName", "middleName": "$.zillaUser.middleName" }, "displayName": "$.zillaUser.displayName", "emails": [ { "value": "$.zillaUser.email", "type": "'work'", "primary": true } ], "active": "$.zillaUser.status = 'active'", "entitlements": [ { "value": "'00edN000001iEMvQAM'" } ] }, "responseProperty": "", "isPaginated": false, "hasMultipleItems": false } ], "propertyMappings": { "accountId": "$.createNewUser.id", "status": "$.createNewUser.active ? 'active' : 'inactive'", "displayName": "$.createNewUser.userName" } }, "revoke": { "endpoints": [ { "name": "revokeUser", "path": "'Users/' & $.zillaAccount.accountId", "method": "PATCH", "body": { "schemas": [ "'urn:ietf:params:scim:api:messages:2.0:PatchOp'" ], "Operations": [ { "op": "'replace'", "value": { "active": false } } ] }, "responseProperty": "Resources", "isPaginated": false, "hasMultipleItems": false } ], "propertyMappings": { "accountId": "$.revokeUser.id", "status": "$.revokeUser.active ? 'active' : 'inactive'", "displayName": "$.revokeUser.displayName" } }, "provisionPermission": { "endpoints": [ { "name": "permissionDetails", "path": "'Entitlements'", "method": "GET", "query": { "filter": "'displayName eq ' & '\"' & $.zillaPermission.name & '\"'" }, "responseProperty": "Resources", "isPaginated": false, "hasMultipleItems": false }, { "name": "assignPermission", "path": "'Users/' & $.zillaAccount.accountId", "method": "PATCH", "body": { "schemas": [ "'urn:ietf:params:scim:api:messages:2.0:PatchOp'" ], "Operations": [ { "op": "'add'", "value": { "entitlements": [ { "value": "$.permissionDetails.id" } ] } } ] }, "responseProperty": "", "isPaginated": false, "hasMultipleItems": false } ] }, "revokePermission": { "endpoints": [ { "name": "permissionDetails", "path": "'Entitlements'", "method": "GET", "query": { "filter": "'displayName eq ' & '\"' & $.zillaPermission.name & '\"'" }, "responseProperty": "Resources", "isPaginated": false, "hasMultipleItems": false }, { "name": "revokePermission", "path": "'Users/' & $.zillaAccount.accountId", "method": "GET", "body": { "schemas": [ "'urn:ietf:params:scim:api:messages:2.0:PatchOp'" ], "Operations": [ { "op": "'remove'", "path": "'entitlements'", "value": { "entitlements": [ { "value": "$.permissionDetails.id" } ] } } ] }, "responseProperty": "", "isPaginated": false, "hasMultipleItems": false } ] } }, "groups": { "sync": { "endpoints": [ { "name": "allgroups", "path": "'Groups'", "method": "GET", "query": { "startIndex": "'1'", "count": "'100'" }, "responseProperty": "Resources", "isPaginated": true, "hasMultipleItems": true } ], "propertyMappings": { "id": "$.allgroups.id", "displayName": "$.allgroups.displayName" } } }, "groupMembers": { "sync": { "endpoints": [ { "name": "group_members", "path": "'Groups/' & $.groupId", "method": "GET", "responseProperty": "", "isPaginated": false, "hasMultipleItems": false } ], "propertyMappings": { "userIds": "$.group_members.members" } } } }

 

Sample API Responses of the endpoints used in the above example -
{ "Resources": [ [ { "schemas": [ "urn:ietf:params:scim:schemas:core:2.0:User", "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User" ], "id": "005RM000002FZAlYAO", "userName": "scimuser@mycompany.com", "externalId": "scimUser", "name": { "formatted": "User Scim", "familyName": "Scim", "givenName": "User" }, "displayName": "User Scim", "nickName": "scimUser@mycompany.com", "emails": [ { "type": "work", "primary": true, "value": "user@mycompany.com" } ], "photos": [], "userType": "Standard", "preferredLanguage": "en_US", "emailEncodingKey": "UTF-8", "locale": "en_US", "timezone": "America/Los_Angeles", "active": true, "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User": { "organization": "00DRM000000HOcw2AG" }, "urn:salesforce:schemas:extension:2.0": { "alias": "45512346" }, "meta": { "created": "2020-10-19T10:11:52Z", "lastModified": "2020-10-19T16:11:52Z", "location": "https://mycompany.my.salesforce.com/services/scim/v2/Users/005RM0...", "resourceType": "User", "version": "f63f4831a8747d4bd0de70fcca991553be4b2e01" } } ] ] }
{ "schemas": [ "urn:ietf:params:scim:schemas:core:2.0:User", "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User" ], "id": "005RM000002FZAlYAO", "userName": "scimuser@mycompany.com", "externalId": "scimUser", "entitlements": [ { "value": "00eRM000001VtbnYAC", "$ref": "/Entitlements/00eRM000001VtbnYAC", "display": "System Administrator", "type": "Profile", "primary": true } ], "userType": "Standard", "preferredLanguage": "en_US", "active": true, "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User": { "organization": "00DRM000000HOcw2AG" }, "urn:salesforce:schemas:extension:2.0": { "alias": "45512346" } }
{ "schemas": [ "urn:ietf:params:scim:schemas:core:2.0:Group" ], "id": "00G4W000006IKBnUAO", "displayName": "mycompany-West", "type": "Regular", "members": [ { "value": "0054W00000CVREkQAP", "type": "User", "$ref": "https://mycompany.my.salesforce.com/services/scim/v2/Users/0054W00..." } ], "meta": { "created": "2020-10-25T09:27:40Z", "lastModified": "2020-10-25T09:27:40Z", "location": "https://mycompany.my.salesforce.com/services/scim/v2/Groups/00G4W000006IKBnUAO", "resourceType": "Group", "version": "2aa9ea6605cb4c31403cdfd1b020cde5dd255300" } }

Description of No Code V2 Config

  • version :: It specifies the version of the config. For No Code V2 config as name suggests, version will be 2.

  • baseUrl :: Base URL for an application API which we can be found in the developer documentation for the application (Example: For Github, the API base URL would be https://api.github.com ).

  • pagination :: It specifies the pagination config of the paginated APIs. It contains,

    • paginationStrategy :: The pagination strategy of the paginated APIs. Supported pagination strategies are LIMIT_OFFSET, CURSOR_BASED, NEXT_URL and PAGE_NUMBER_BASED.

    • paginationOverrides ::

      • In case of LIMIT_OFFSET strategy,

        • limit - name of the limit key that can be passed as query in the paginated APIs

        • offset - name of the offset key that can be passed as query in the paginated APIs

      • In case of CURSOR_BASED strategy,

        • limit - name of the limit key that can be passed as query in the paginated APIs

        • cursorKey - name of the cursor key that can be passed in the query of next page’s API call

        • cursorPath - path of the cursor in response from where we can get the cursor for next page’s API call

      • In case of NEXT_URL,

        • nextUrlKey - path of the next page’s URL in response

      • In case of PAGE_NUMBER_BASED,

        • pageSizeKey - name of the page size key that can be passed as a query in the paginated APIs.

        • pageNumberKey - name of the page number key that can be passed as a query in the paginated APIs.

  • authorization :: This block describes the authorization of the APIs.

    • authorizationType :: The type of the authorization. Supported types are CLIENT_CREDENTIALS, OAUTH, BASIC, CUSTOM_HEADERS and NO_AUTH. (NOTE - In case of OAUTH, redirect URL will be https://app.zillasecurity.com/api/auth/callback/nocode_v2_oauth)

    • clientID :: An optional field to specify the client ID or username (In case of basic authentication). It supports the secret variables (e.g. $.secrets.clientId , clientId should be specified in the Secrets config).

    • clientSecret :: An optional field to specify the client secret or password (In case of basic authentication). It supports the secret variables (e.g. $.secrets.clientSecret, clientSecret should be specified in the Secrets config).

    • scopes :: An optional field to specify space separated scopes in case of OAUTH authorization type. To specify scopes for CLIENT_CREDENTIALS authorization type, please use authorizationBody.

    • headers :: An optional object of headers to pass to all API calls. Works only when authorizationType is CUSTOM_HEADERS.

    • authorizationHeaders :: An optional object of headers like Content-Type to pass to Token API call. Works only when authorizationType is CLIENT_CREDENTIALS.

    • authorizationBody :: An optional object of body to pass to Token API call. Works only when authorizationType is CLIENT_CREDENTIALS. By default, the authorizationBody in API calls includes the following:

{ "client_id": "$.secrets.clientID", "client_secret" : "$.secrets.clientSecret", "grant_type" : "client_credentials }

If any other body parameters are necessary, ALL body parameters necessary for the Token API Call need to be specified in this object.

 

  • accounts :: This block describes the configurations to collect or provision the particular data type. It is an option config and define it only if you want to collect or provision.

    • sync / provision / revoke / provisionPermission / revokePermission ::
      The sync block specifies the configs to collect the accounts from the source system. It is an optional block and define it only if you want to collect the data.
      The provision block specifies the configs to provision a new account.
      The revoke block specifies the configs to revoke an account.
      The provisionPermission block specifies the configs to add new permission to the account.
      The revokePermission block specifies the configs to revoke the permission from the account.

      • endpoints :: An ordered array of endpoint details. The first endpoint in this array should be a list endpoint and the others can be the endpoints to get details of specific entity. Certain fields like path, query and body supports dynamic variables to use values from the response of the previous API calls.

        • name :: A name of the endpoint. Name will be used to refer the response of this endpoint in the propertyMappings and other endpoint's path, query or body where you want to use dynamic variables.

        • path :: A path of the endpoint appended by baseUrl. It supports dynamic variables to use values from the responses of previous endpoint calls of that data type. (e.g. "\"Users/\" & $.allusers.id")

        • method :: A method of the API call. Supported methods are GET, POST, PATCH, PUT, DELETE.

        • query :: An optional object of query params to pass with the endpoint. It supports dynamic variables to use values from the responses of previous endpoint calls of that data type. (e.g. { "userId": "$.allusers.id", "includeInactive": true }).

        • headers :: An optional object of headers to pass with the endpoint. (e.g. { "x-org-name": "zilla" }).

        • responseProperty :: To define the path of the expected object/array in the response. Empty string will be considered as the expected object/array is at the root level in the response.

        • isPaginated :: To define whether this endpoint supports pagination or not. pagination block should be define if any one of the endpoint has isPaginated true.

        • hasMultipleItems :: To define whether it should expect an array or object at the given path via responseProperty.

        • throwError :: To throw the error and discontinue the execution of the endpoints array. The error will be thrown if the given condition is met.

          • condition :: To define the condition in the form of jsonata expression or any of the predefined enums. The predefined enum is NON_EMPTY_RESPONSE. This condition will be applied on the response body.

          • message :: To define the error message in the thrown error.

      • propertyMappings :: An object to map response properties to the zilla fields. It supports JSONATA expressions. For example, in case of account -

        "propertyMappings": { "id": "$.allusers.id", "username": "$.allusers.displayName", "active": "$.allusers.active = true", "email": "$.allusers.emails.value[0]", "firstName": "$.allusers.name.givenName", "lastName": "$.allusers.name.familyName", "roles": "$.user_roles.entitlements.display" }

         

  • groups :: This block describes the configurations to collect the groups. It is an option config and define it only if you want to collect groups data.

    • sync ::
      The sync block specifies the configs to collect the groups from the source system. It is an optional block and define it only if you want to collect the data. If you define this block, group memberships sync block becomes required to sync groups.

      • endpoints :: An ordered array of endpoint details. The first endpoint in this array should be a list endpoint and the others can be the endpoints to get details of specific entity. Certain fields like path, query and body supports dynamic variables to use values from the response of the previous API calls.

        • name :: A name of the endpoint. Name will be used to refer the response of this endpoint in the propertyMappings and other endpoint's path, query or body where you want to use dynamic variables.

        • path :: A path of the endpoint appended by baseUrl. It supports dynamic variables to use values from the responses of previous endpoint calls of that data type. (e.g. "\"Groups/\" & $.allgroups.id")

        • method :: A method of the API call. Supported methods are GET, POST, PATCH, PUT, DELETE.

        • query :: An optional object of query params to pass with the endpoint. It supports dynamic variables to use values from the responses of previous endpoint calls of that data type. (e.g. { "groupId": "$.allgroups.id", "includeInactive": true }).

        • headers :: An optional object of headers to pass with the endpoint. (e.g. { "x-org-name": "zilla" }).

        • responseProperty :: To define the path of the expected object/array in the response. Empty string will be considered as the expected object/array is at the root level in the response.

        • isPaginated :: To define whether this endpoint supports pagination or not. pagination block should be define if any one of the endpoint has isPaginated true.

        • hasMultipleItems :: To define whether it should expect an array or object at the given path via responseProperty.

      • propertyMappings :: An object to map response properties to the zilla fields. It supports JSONATA expressions. For example, in case of group -

        "propertyMappings": { "id": "$.allgroups.id", "displayName": "$.allgroups.displayName", "email": "$.allgroups.emails.value[0]", "description": "$.allgroups.description", "roles": "$.group_roles.entitlements.display" }
  • groupMembers :: This block describes the configurations to collect or provision the particular data type. It is an option config and define it only if you want to collect or provision group member.

    • sync / provision / revoke ::
      The sync block specifies the configs to collect or provision group members. It is an optional block but required if you have defined groups sync configuration.
      The provision block specifies the configs to provision a group membership.
      The revoke block specifies the configs to revoke a group membership.

      • endpoints :: An ordered array of endpoint details. It supports only 1 endpoint to get group members. Certain fields like path, query and body supports dynamic variables to use group details like groupId and groupName.

        • name :: A name of the endpoint. Name will be used to refer the response of this endpoint in the propertyMappings and other endpoint's path, query or body where you want to use dynamic variables.

        • path :: A path of the endpoint appended by baseUrl. It supports dynamic variables to use values from the responses of previous endpoint calls of that data type. (e.g. "\"Groups/\" & $.groupId & '/members'")

        • method :: A method of the API call. Supported methods are GET, POST, PATCH, PUT, DELETE.

        • query :: An optional object of query params to pass with the endpoint. It supports dynamic variables to use group details like groupId and groupName. (e.g. { "group": "$.groupName" }).

        • headers :: An optional object of headers to pass with the endpoint. (e.g. { "x-org-name": "zilla" }).

        • responseProperty :: To define the path of the expected object/array in the response. Empty string will be considered as the expected object/array is at the root level in the response.

        • isPaginated :: To define whether this endpoint supports pagination or not. pagination block should be define if any one of the endpoint has isPaginated true.

        • hasMultipleItems :: To define whether it should expect an array or object at the given path via responseProperty.

      • propertyMappings :: An object to map response properties to the zilla fields. It supports JSONATA expressions. For example, in case of group members -

        "propertyMappings": { "userIds": "$.group_members.members" }

How to use No Code V2 Config in the Zilla

Below are the steps to enable No Code v2 integration for applications.

  1. Login to Zilla as admin.

  2. Click Add application in the top right corner.

     

  3. On the Add Application page search for the application you want to add to Zilla and click Add to Applications if found. Otherwise, add a custom application by going to the Custom Application tab.

     

  4. Add details for the custom application and click Add to Applications.

     

  5. You will be redirected to the application details page.

     

  6. Click the Gear icon in the top right to the left of Sync now.

  7. You will see the configuration dialog, click Show Alternate Configuration Options.

     

  8. Enable API Integration, you will see configuration entries to be filled in.

    image-20250627-084443.png

     

  9. Enter the config and secrets you have created from the above steps.

  10. Click Sync now and then Next to start the sync.