{"info":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","description":"<html><head></head><body><h2 id=\"key-terms-in-the-knackly-api\">Key Terms in the Knackly API</h2>\n<ul>\n<li><p><strong>Workspace</strong> - a given customer's site on Knackly.</p>\n</li>\n<li><p><a href=\"#873f9e6e-0829-4ef2-a585-eef2e1f1bd4f\"><b>Catalogs</b></a> - a database / repository / table where the customer's data is stored and related documents are generated. One workspace can contain any number of catalogs. A catalog is the boundary for data access permissions in Knackly: groups of users have rights to view/modify data, or see the documents produced from that data, based on whether they have access to the catalog or not. API keys are also granted access on a per-Catalog basis.</p>\n</li>\n<li><p><a href=\"#d106dd99-062a-4c48-a444-99d0bb4ff8f8\"><b>Schema</b></a> - Knackly's term for a schema (also called a Model). Each catalog has (or is based on) a model. Different catalogs may be based on different models, or multiple catalogs may be based on the same model. A model defines Variables, which in turn define the \"shape\" of an instance of that model. Models are object-based. Variables can be scalars or arrays; data types include \"text\", \"number\", \"date\", \"true/false\", and \"object\". (Object-type variables also define which model the object data must adhere to.) There are also \"selection\" variables, where the answer acts as a foreign key (usually a text string) referring by key to some other object (which itself is stored in either a Table, an external Query, or elsewhere within the record itself).</p>\n</li>\n<li><p><a href=\"#74f947c7-2d45-47be-893a-4391dec2d33e\"><b>Records</b></a> - a single item in a catalog -- a data object that adheres to the model of the catalog in which it is stored. In other words, the records in a catalog are <em>instances</em> of the catalog's model.</p>\n</li>\n<li><p><strong>Template</strong> - Knackly generates documents based on Templates. Templates are created and maintained by workspace administrators in Knackly. 1 template x 1 record (or other object) = 1 document.</p>\n</li>\n<li><p><a href=\"#7e4867f1-f236-4099-93f3-8fa05b9b9033\"><b>Apps</b></a> (Knackly App) - a process within Knackly, defined by a workspace administrator, that interactively gathers data from an end-user, stores it in a record (in a catalog), and generates some number of documents from that data. There is no limit to how many documents (based on templates) that a given app can produce; it can be fixed in the app's definition or dynamic based on the data provided. Multiple different apps can also be run against the same record at different times. Note: This is different from your application (the software you're building that integrates with Knackly).</p>\n</li>\n</ul>\n<h2 id=\"api-v1-terminology-note\">API v1 Terminology Note</h2>\n<p><strong>Important:</strong> The v1 API uses <code>/items/</code> in URL paths, but throughout this documentation we refer to these as \"records\" (the official Knackly terminology). For example:</p>\n<ul>\n<li><p>API path: <code>GET /:workspace/api/v1/catalogs/:catalog/items/:record_id</code></p>\n</li>\n<li><p>Documentation location: \"Catalogs &gt; Records &gt; Get record\"</p>\n</li>\n</ul>\n<p>This terminology mismatch is a legacy issue from before terminology was standardized. It will be corrected in API v2.</p>\n<h2 id=\"quick-start\">Quick Start</h2>\n<ol>\n<li><p><strong>Get API Credentials:</strong> Obtain your API Key ID and Secret from your Knackly workspace administrator (see <a href=\"#api-keys-and-permissions\">API Keys and Permissions</a> for more information)</p>\n</li>\n<li><p><strong>Authenticate:</strong> Call <a href=\"#74af1701-f9f8-4c87-81f2-cafdb96160ef\">Request an Access Token</a> (<code>POST /:workspace/api/v1/auth/login</code>) with your credentials to get an access token</p>\n</li>\n<li><p><strong>List Catalogs:</strong> Call <a href=\"#dbb8772a-5e30-454d-8b6e-65433efc553a\">List catalogs</a> (<code>GET /:workspace/api/v1/catalogs</code>) to see available catalogs</p>\n</li>\n<li><p><strong>Get App Schema:</strong> Call <a href=\"#821e771c-0b1f-434f-9055-ff6a28b48b40\">Get app model(s)</a> (<code>GET /:workspace/api/v1/catalogs/:catalog/apps/:app_name/types</code>) to understand the data structure (see also <a href=\"#data-structure-nested-vs-flat\">Data Structure: Nested vs Flat</a>)</p>\n</li>\n<li><p><strong>Create Record:</strong> Call <a href=\"#e063d16f-9204-476a-be7d-c70de2cfd813\">Create record by running app</a> (<code>POST /:workspace/api/v1/catalogs/:catalog/apps/:app_name</code>) with your data</p>\n</li>\n<li><p><strong>Check Status:</strong> Poll <a href=\"#773b8d31-af3a-42f7-9262-bfbcb1a6c3fe\">Get app status</a> (<code>GET /:workspace/api/v1/catalogs/:catalog/items/:record_id/apps/:app_name</code>) until status is \"Completed\" (note: path says \"items\" but this is a \"record\"; see <a href=\"#status-values\">Status Values</a> for all status values)</p>\n</li>\n<li><p><strong>Download Documents:</strong> Use the <code>files[].url</code> from the status response to download generated documents</p>\n</li>\n</ol>\n<h2 id=\"api-keys-and-permissions\">API Keys and Permissions</h2>\n<p>In Knackly, API keys exist <em>alongside</em> Users as entities that can be assigned permissions. There are two types of API keys:</p>\n<h3 id=\"regular-api-keys\">Regular API Keys</h3>\n<p>Regular API keys allow operations analogous to what a regular/internal user can do in Knackly:</p>\n<ul>\n<li><p>View and modify records in catalogs they have access to</p>\n</li>\n<li><p>Run apps on records</p>\n</li>\n<li><p>Generate documents</p>\n</li>\n<li><p>Access catalog/app metadata</p>\n</li>\n</ul>\n<p>Regular API keys are granted access on a per-catalog basis via the <code>permissions</code> array (list of catalog IDs).</p>\n<h3 id=\"admin-api-keys\">Admin API Keys</h3>\n<p>Admin API keys allow operations analogous to what an admin user can do:</p>\n<ul>\n<li><p>All operations available to regular API keys, PLUS:</p>\n</li>\n<li><p>Create, modify, and delete elements (Models, Tables, Queries)</p>\n</li>\n<li><p>Manage template upload jobs (update DOCX or PDF binaries for templates in models)</p>\n</li>\n<li><p>Create, modify, and delete users (admin, regular, or external)</p>\n</li>\n<li><p>Create, modify, and delete groups</p>\n</li>\n<li><p>Create, modify, and delete other API keys (both regular and admin)</p>\n</li>\n</ul>\n<p>Admin API keys are created with <code>hasAdminAccess: true</code> when using the <a href=\"#2678618d-68f7-43eb-87d9-eb354d481a64\">Create API key</a> endpoint (requires an admin API key to call).</p>\n<p><strong>Which API key type do you need?</strong></p>\n<ul>\n<li><p>Use a <strong>regular API key</strong> if you're building an integration that reads/writes records and generates documents</p>\n</li>\n<li><p>Use an <strong>admin API key</strong> if you need to manage the workspace structure (catalogs, models, users, etc.) or if you're building administrative tooling</p>\n</li>\n</ul>\n<p><strong>In this documentation:</strong><br>Operations that require an admin API key are marked with \"(admin)\" in their title.</p>\n<h2 id=\"data-structure-nested-vs-flat\">Data Structure: Nested vs Flat</h2>\n<p>Knackly supports two ways to structure data when creating or updating records. The <code>flat</code> query parameter (default: <code>false</code>) should align with the format you're using.</p>\n<h4 id=\"nested-structure-default-flatfalse-or-omitted\">Nested Structure (default, <code>flat=false</code> or omitted):</h4>\n<p>This matches standard JSON with nested objects and arrays, corresponding to the object-based view you get from the \"Get app model(s)\" endpoint:</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-json\">{\n  \"Client\": {\n    \"Name\": \"John Doe\",\n    \"Address\": {\n      \"Street\": \"123 Main St\",\n      \"City\": \"Anytown\"\n    }\n  },\n  \"Children\": [\n    { \"Name\": \"Child 1\", \"Age\": 10 },\n    { \"Name\": \"Child 2\", \"Age\": 8 }\n  ]\n}\n\n</code></pre>\n<h4 id=\"flat-structure-flattrue\">Flat Structure (<code>flat=true</code>):</h4>\n<p>This uses a flat object where property names are dot-separated paths to the data points, corresponding to the flat list you get from the \"Get app data points\" (fields) endpoint:</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-json\">{\n  \"Client.Name\": \"John Doe\",\n  \"Client.Address.Street\": \"123 Main St\",\n  \"Client.Address.City\": \"Anytown\",\n  \"Children[0].Name\": \"Child 1\",\n  \"Children[0].Age\": 10,\n  \"Children[1].Name\": \"Child 2\",\n  \"Children[1].Age\": 8\n}\n\n</code></pre>\n<h4 id=\"which-format-should-you-use\">Which format should you use?</h4>\n<ul>\n<li><p>Use <strong>nested</strong> (the default) if you're working with the model/schema information from <a href=\"#821e771c-0b1f-434f-9055-ff6a28b48b40\">Get app model(s)</a> (<code>GET /catalogs/:catalog/apps/:app_name/types</code>) - the structure naturally matches</p>\n</li>\n<li><p>Use <strong>flat</strong> if you're working with the fields/data points from <a href=\"#5a06e5a3-df76-42bf-bf86-3987df7a2b02\">Get app data points</a> (<code>GET /catalogs/:catalog/apps/:app_name/fields</code>) - the dot-separated property names match the field paths</p>\n</li>\n<li><p>Consider using <strong>flat</strong> if your application natively stores data in a flattened format (e.g., form submissions, CSV imports, key-value stores)</p>\n</li>\n</ul>\n<h4 id=\"endpoints-that-support-flat-parameter\">Endpoints that support flat parameter:</h4>\n<h5 id=\"for-postput-requests-where-youre-sending-data\">For POST/PUT requests (where you're sending data):</h5>\n<ul>\n<li><p><code>POST /catalogs/:catalog/apps/:app_name</code> (Create record by running app) - instructs Knackly how to interpret request body</p>\n</li>\n<li><p><code>POST /catalogs/:catalog/items</code> (Create record) - instructs Knackly how to interpret request body</p>\n</li>\n<li><p><code>PUT /catalogs/:catalog/items/:record_id</code> (Modify record) - instructs Knackly how to interpret request body</p>\n</li>\n</ul>\n<h5 id=\"for-get-requests-where-youre-receiving-data\">For GET requests (where you're receiving data):</h5>\n<ul>\n<li><p><code>GET /catalogs/:catalog/items/:record_id (Get record)</code> - controls response format</p>\n</li>\n<li><p><code>GET /catalogs/:catalog/items (List records)</code> - controls response format</p>\n</li>\n</ul>\n<h2 id=\"launching-user-app-sessions\">Launching User App Sessions</h2>\n<p>You can send users from your application into Knackly by redirecting their browser to specific URLs. Use this when you want them to:</p>\n<ul>\n<li><p>Run an app to review, change, or add data in an existing record, or to create a new record in a catalog; or</p>\n</li>\n<li><p>Open the record details page to view metadata and documents for an existing record that has had one or more apps run on it.</p>\n</li>\n</ul>\n<p>Knackly exposes the following URL patterns and optional query parameters to support these flows.</p>\n<h3 id=\"open-an-app-in-the-browser\">Open an app in the browser</h3>\n<ul>\n<li>New record (create a record in a catalog with a given app):</li>\n</ul>\n<p><code>https://go.knackly.io/{workspace}/{catalog}/{app_name}</code></p>\n<ul>\n<li>Existing record (run an app on an existing record):</li>\n</ul>\n<p><code>https://go.knackly.io/{workspace}/{catalog}/{record_id}/{app_name}</code></p>\n<p>Replace {workspace}, {catalog}, {app_name}, and {record_id} with your workspace name, catalog name, app name, and record ID. You can get app URLs for a catalog from List catalogs or List apps; the “run app on existing record” URL is also returned in the apps[].url field when you get a record or app status.</p>\n<h4 id=\"app-page--optional-query-parameters\">App page – optional query parameters</h4>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Parameter</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>return_complete</code></td>\n<td>(Optional) URL to send the user to when they complete the app. Must be URL-encoded.</td>\n</tr>\n<tr>\n<td><code>return_incomplete</code></td>\n<td>(Optional) URL to send the user to when they leave without completing (e.g. “Finish Later”). Must be URL-encoded.</td>\n</tr>\n<tr>\n<td><code>disable_finish_later</code> (or <code>dfl</code> alias)</td>\n<td>(Optional) Hides the “Finish Later” button. Example: ?disable_finish_later=true or ?dfl=true.</td>\n</tr>\n<tr>\n<td><code>external</code></td>\n<td>(Optional) Valid external token for an external user; see External Tokens.</td>\n</tr>\n</tbody>\n</table>\n</div><p>Example (with return URL and suppressing “Finish Later”):</p>\n<p><code>https://go.knackly.io/{workspace}/{catalog}/{app_name}?return_complete={url}&amp;dfl=1</code></p>\n<h3 id=\"record-details-page-view-metadata-and-documents\">Record details page (view metadata and documents)</h3>\n<p>To let users view metadata and generated documents for an existing record (without running an app), redirect them to the record details page: <code>{base_url}/{workspace}/records/{catalog}/{record_id}</code> (use your workspace base URL, e.g. <code>https://go.knackly.io</code>).</p>\n<p>Example: <code>https://go.knackly.io/acme/records/Contracts/507f1f77bcf86cd799439011</code></p>\n<h4 id=\"record-details-page--optional-query-parameters\">Record details page – optional query parameters</h4>\n<p>Update: New URL parameters are available to control UI behavior and a custom action button that triggers a webhook.</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Parameter</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>disable_download</code> (or <code>dd</code>)</td>\n<td>(Optional) Hides the download button and disables download links for individual documents.</td>\n</tr>\n<tr>\n<td><code>disable_download_all</code> (or <code>dda</code>)</td>\n<td>(Optional) Hides the \"download all\" button that normally lets users download a zip file including multiple documents.</td>\n</tr>\n<tr>\n<td><code>custom_button_label</code> (or <code>cbl</code>)</td>\n<td>(Optional) Label for a custom button.</td>\n</tr>\n<tr>\n<td><code>custom_button_action</code> (or <code>cba</code>)</td>\n<td>(Optional) Webhook ID to invoke when the button is clicked.</td>\n</tr>\n</tbody>\n</table>\n</div><p>When the custom button is clicked, Knackly sends a webhook event of type <code>catalog.app.custom_action</code> to the webhook specified by custom_button_action (e.g. cba=wh_123456).</p>\n<p>Example (hide download, add “Send to CRM” button):</p>\n<p><code>?disable_download_all=true&amp;custom_button_label=Send+to+CRM&amp;custom_button_action=wh_123456</code></p>\n<p>This shows a button labeled “Send to CRM” that triggers webhook <code>wh_123456</code>.</p>\n<h2 id=\"status-values\">Status Values</h2>\n<p>Knackly uses status values to indicate the current state of Records and Apps. Each Record has a status, and each App run on that record also has its own status.</p>\n<p><strong>Important:</strong> Status values are <strong>read-only</strong> - you never need to provide status values in API requests. They are returned by the API in responses, and you need to understand them to correctly interpret the state of records and apps.</p>\n<h4 id=\"record-status-values\">Record Status Values</h4>\n<p>Record status indicates whether the record is available for operations:</p>\n<ul>\n<li><p><strong><code>Available</code></strong> - The record is available for operations (read, modify, run apps, etc.)</p>\n<ul>\n<li><strong>Legacy mapping:</strong> Previously \"Ok\" or \"Needs Updating\"</li>\n</ul>\n</li>\n<li><p><strong><code>In Use</code></strong> - The record is currently locked because a user is actively working with it. You should NOT attempt to modify the record while it's in this state.</p>\n<ul>\n<li><strong>Legacy mapping:</strong> Previously \"In Progress\"</li>\n</ul>\n</li>\n</ul>\n<h5 id=\"when-checking-record-status\"><strong>When checking record status:</strong></h5>\n<ul>\n<li><p>Use <code>Available</code> to determine if it's safe to perform operations on the record</p>\n</li>\n<li><p>If status is <code>In Use</code>, wait before attempting modifications (the user may be in an interactive app session)</p>\n</li>\n</ul>\n<h4 id=\"app-status-values\">App Status Values</h4>\n<p>App status indicates the state of a specific app run on a record. Each app within a record can have its own status:</p>\n<ul>\n<li><p><strong><code>In Use</code></strong> - A user is currently interactively filling out the interview for this app. The record is locked.</p>\n<ul>\n<li><strong>Legacy mapping:</strong> Previously \"Needs Updating\" (but you couldn't tell if a user was actively in the app)</li>\n</ul>\n</li>\n<li><p><strong><code>Running</code></strong> - The user clicked Complete and documents are currently being generated.</p>\n<ul>\n<li><strong>Legacy mapping:</strong> Previously \"In Progress\"</li>\n</ul>\n</li>\n<li><p><strong><code>Completed</code></strong> - Documents were generated successfully and the app has not been run since then.</p>\n<ul>\n<li><strong>Legacy mapping:</strong> Previously \"Ok\"</li>\n</ul>\n</li>\n<li><p><strong><code>Error</code></strong> - One or more documents FAILED to generate, and the app has not been run since then.</p>\n<ul>\n<li><strong>New status</strong> - No legacy equivalent</li>\n</ul>\n</li>\n<li><p><strong><code>Modified</code></strong> - The app was run and data was modified, but the user did NOT click Complete (either clicked \"Finish Later\" or the interview session timed out).</p>\n<ul>\n<li><strong>Legacy mapping:</strong> Previously \"Needs Updating\" OR \"Incomplete\" (but you couldn't tell if a user was still in the app)</li>\n</ul>\n</li>\n</ul>\n<h5 id=\"when-checking-app-status\"><strong>When checking app status:</strong></h5>\n<ul>\n<li><p>Use <code>Completed</code> to know documents are ready to download</p>\n</li>\n<li><p>Use <code>Error</code> to know document generation failed and may need attention</p>\n</li>\n<li><p>Use <code>Modified</code> to know data was changed but documents weren't generated yet</p>\n</li>\n<li><p>Use <code>In Use</code> or <code>Running</code> to know you should wait before running the app again</p>\n</li>\n</ul>\n<h2 id=\"rate-limiting-and-api-usage\">Rate Limiting and API Usage</h2>\n<p>To ensure fair usage and avoid potential issues:</p>\n<ul>\n<li><p>Avoid rapid polling or unnecessarily frequent API calls</p>\n</li>\n<li><p>Implement reasonable delays between requests when checking status or polling for completion</p>\n</li>\n<li><p>If rate limits are implemented in the future, you may receive a <code>429 Too Many Requests</code> response with headers indicating when you can retry</p>\n</li>\n</ul>\n<h5 id=\"api-use-cases-and-pricing\"><strong>API Use Cases and Pricing:</strong></h5>\n<p><strong>Interactive:</strong> Provide data as a starting point for users who want to interactively review/modify that data, and potentially enter additional data, prior to documents being generated.</p>\n<p><strong>Headless:</strong> Generate documents based purely on data you provide, bypassing the standard Knackly interactive app experience. This use case may be subject to different pricing models.</p>\n<p>Talk to Sales about API pricing and confirm whether your intended use case is supported.</p>\n</body></html>","schema":"https://schema.getpostman.com/json/collection/v2.0.0/collection.json","toc":[],"owner":"6868588","collectionId":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","publishedId":"SzS7QReU","public":true,"customColor":{"top-bar":"FFFFFF","right-sidebar":"303030","highlight":"EF5B25"},"publishDate":"2020-03-20T13:17:24.000Z"},"item":[{"name":"Access","item":[{"name":"Request an Access Token","event":[{"listen":"test","script":{"type":"text/javascript","exec":["if (pm.response.text().startsWith(\"{\")) {\r\n  var jsonData = pm.response.json()\r\n  pm.environment.set(\"token\", jsonData.token);\r\n}\r\n"]}}],"id":"653b97a6-35eb-463a-bf4f-541684268bd3","request":{"auth":{"type":"noauth","isInherited":false},"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n\t\"KeyID\": \"{{key_id}}\",\n\t\"Secret\": \"{{secret}}\"\n}","options":{"raw":{"language":"json"}}},"url":"{{base_url}}/:workspace/api/v1/auth/login","description":"<p>Given an API key and secret (posted in the request body) for a given Knackly workspace, returns an access token that must be included in the \"Authorization\" header of subsequent requests.</p>\n<p><strong>Authorization Header Format:</strong></p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code>Authorization: Bearer {token}\n</code></pre><p>Example:</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code>Authorization: \n</code></pre><p><strong>Token Expiration:</strong>\nAccess tokens expire after a period of inactivity (typically 1 hour). When a token expires, you'll receive a 401 Unauthorized response. You must request a new token using the same endpoint with your API key credentials.</p>\n<p><strong>Best Practice:</strong> Store your API key and secret securely, and implement token refresh logic that automatically requests a new token when you receive a 401 response.</p>\n","urlObject":{"path":[":workspace","api","v1","auth","login"],"host":["{{base_url}}"],"query":[],"variable":[{"id":"098bf003-ec90-4a7e-87a5-55ba1344288c","type":"any","value":"{{workspace}}","key":"workspace"}]}},"response":[{"id":"3a1b75f1-61c0-4d18-b7c2-9eda0ff68941","name":"Request an Access Token (200)","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n\t\"KeyID\": \"{{key_id}}\",\n\t\"Secret\": \"{{secret}}\"\n}","options":{"raw":{"language":"json"}}},"url":{"raw":"{{base_url}}/:workspace/api/v1/auth/login","host":["{{base_url}}"],"path":[":workspace","api","v1","auth","login"],"variable":[{"key":"workspace","value":"{{workspace}}","description":"(Required) The name of a Knackly workspace"}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Powered-By","value":"Express"},{"key":"x-dns-prefetch-control","value":"off"},{"key":"x-frame-options","value":"SAMEORIGIN"},{"key":"strict-transport-security","value":"max-age=15552000; includeSubDomains"},{"key":"x-download-options","value":"noopen"},{"key":"x-content-type-options","value":"nosniff"},{"key":"x-xss-protection","value":"1; mode=block"},{"key":"access-control-allow-origin","value":"*"},{"key":"surrogate-control","value":"no-store"},{"key":"cache-control","value":"no-store, no-cache, must-revalidate, proxy-revalidate"},{"key":"pragma","value":"no-cache"},{"key":"expires","value":"0"},{"key":"content-type","value":"application/json; charset=utf-8"},{"key":"content-length","value":"205"},{"key":"etag","value":"W/\"cd-FLJ7af9TR1PEfX+w4IX74kXo4cE\""},{"key":"date","value":"Wed, 20 Apr 2022 22:22:25 GMT"},{"key":"connection","value":"close"},{"key":"Vary","value":"Accept-Encoding"}],"cookie":[],"responseTime":null,"body":"{\n    \"token\": \"...\"\n}"}],"_postman_id":"653b97a6-35eb-463a-bf4f-541684268bd3"}],"id":"1eb138dc-1333-4076-b648-d29a02601ebf","description":"<p>Any 3rd-party application must \"sign in\" to a Knackly workspace by requesting an access token.</p>\n<p>Before this can happen, an API key must be provisioned by the administrator of that workspace. The administrator may then share that API key (and its associated secret) with a 3rd party application developer, granting that application access to the workspace's data.</p>\n","_postman_id":"1eb138dc-1333-4076-b648-d29a02601ebf","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}}},{"name":"Catalogs","item":[{"name":"Apps","item":[{"name":"Schema","item":[{"name":"Get app model(s)","id":"57d51af2-b6cf-410d-b674-267e65f0e65f","request":{"method":"GET","header":[],"url":"{{base_url}}/:workspace/api/v1/catalogs/:catalog/apps/:app_name/types/:model_name","description":"<p>Retrieves information about a model (object definition or schema) in Knackly, which primarily includes a list of the variables (data points) defined by that model. If no model name is supplied, retrieves the information about <em>all</em> models pertinent to the indicated app.</p>\n<p>This endpoint is similar to <a href=\"#5a06e5a3-df76-42bf-bf86-3987df7a2b02\">Get app data points</a>, but this returns hierarchical schema information, whereas that one provides a flattened list of data points that may be more convenient or appropriate for some needs.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}},"urlObject":{"path":[":workspace","api","v1","catalogs",":catalog","apps",":app_name","types",":model_name"],"host":["{{base_url}}"],"query":[],"variable":[{"id":"92790441-efc3-440d-9622-c92bd70d3fd4","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"},{"id":"a603cbc1-c313-48c6-a59b-18a2308a5744","description":{"content":"<p>(Required) The name of the catalog where the app is defined</p>\n","type":"text/plain"},"type":"any","value":"{{catalog_name}}","key":"catalog"},{"id":"f3bebb50-57ba-49a1-9d56-36379b36a6c9","description":{"content":"<p>(Required) The name of the app for which you want schema info</p>\n","type":"text/plain"},"type":"any","value":"{{app_name}}","key":"app_name"},{"id":"c75ab48d-9a17-4159-b1cd-b3cb6121de3b","description":{"content":"<p>(Optional) The name of the model you wish to retrieve; omit to retrieve all models used by this app</p>\n","type":"text/plain"},"type":"any","value":"","key":"model_name"}]}},"response":[{"id":"f63d2df4-1274-431e-a78d-3d7cfbc0825b","name":"Get information for a specific object type","originalRequest":{"method":"GET","header":[],"url":{"raw":"{{base_url}}/:workspace/api/v1/catalogs/:catalog/apps/:app/types/:type","host":["{{base_url}}"],"path":[":workspace","api","v1","catalogs",":catalog","apps",":app","types",":type"],"variable":[{"key":"workspace","value":"{{workspace}}","description":"(Required) The name of a Knackly workspace"},{"key":"catalog","value":"{{catalog_name}}","description":"(Required) The name of the catalog containing the app"},{"key":"app","value":"{{app_name}}","description":"(Required) The name of the app for which you want type metadata"},{"key":"type","value":"top","description":"(Optional) The name of the type about which you want metadata"}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Powered-By","value":"Express"},{"key":"x-dns-prefetch-control","value":"off"},{"key":"x-frame-options","value":"SAMEORIGIN"},{"key":"strict-transport-security","value":"max-age=15552000; includeSubDomains"},{"key":"x-download-options","value":"noopen"},{"key":"x-content-type-options","value":"nosniff"},{"key":"x-xss-protection","value":"1; mode=block"},{"key":"access-control-allow-origin","value":"*"},{"key":"surrogate-control","value":"no-store"},{"key":"cache-control","value":"no-store, no-cache, must-revalidate, proxy-revalidate"},{"key":"pragma","value":"no-cache"},{"key":"expires","value":"0"},{"key":"content-type","value":"application/json; charset=utf-8"},{"key":"content-length","value":"673"},{"key":"etag","value":"W/\"2a1-+7/OTuH5yC98JSAFPcOBVTWwiQw\""},{"key":"date","value":"Fri, 27 Mar 2020 02:12:41 GMT"},{"key":"connection","value":"close"},{"key":"Vary","value":"Accept-Encoding"}],"cookie":[],"responseTime":null,"body":"{\n    \"name\": \"top\",\n    \"version\": 46,\n    \"variables\": [\n        {\n            \"name\": \"_id\",\n            \"type\": \"id\"\n        },\n        {\n            \"name\": \"Client\",\n            \"type\": \"object\",\n            \"typeName\": \"person\",\n            \"isList\": false,\n            \"label\": \"Client\"\n        },\n        {\n            \"name\": \"IsMarried\",\n            \"type\": \"boolean\",\n            \"isList\": false,\n            \"label\": \"Is married\"\n        },\n        {\n            \"name\": \"Spouse\",\n            \"type\": \"object\",\n            \"typeName\": \"person\",\n            \"isList\": false,\n            \"label\": \"Spouse\"\n        },\n        {\n            \"name\": \"Children\",\n            \"type\": \"object\",\n            \"typeName\": \"person\",\n            \"isList\": true,\n            \"label\": \"Children\"\n        }\n    ]\n}"},{"id":"eb78ec77-defa-4e3a-bbcf-a53d9e29aeef","name":"Get information for all types in an app","originalRequest":{"method":"GET","header":[],"url":{"raw":"{{base_url}}/:workspace/api/v1/catalogs/:catalog/apps/:app/types/:type","host":["{{base_url}}"],"path":[":workspace","api","v1","catalogs",":catalog","apps",":app","types",":type"],"variable":[{"key":"workspace","value":"{{workspace}}","description":"(Required) The name of a Knackly workspace"},{"key":"catalog","value":"{{catalog_name}}","description":"(Required) The name of the catalog containing the app"},{"key":"app","value":"{{app_name}}","description":"(Required) The name of the app for which you want type metadata"},{"key":"type","value":"","description":"(Optional) The name of the type about which you want metadata"}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Powered-By","value":"Express"},{"key":"x-dns-prefetch-control","value":"off"},{"key":"x-frame-options","value":"SAMEORIGIN"},{"key":"strict-transport-security","value":"max-age=15552000; includeSubDomains"},{"key":"x-download-options","value":"noopen"},{"key":"x-content-type-options","value":"nosniff"},{"key":"x-xss-protection","value":"1; mode=block"},{"key":"access-control-allow-origin","value":"*"},{"key":"surrogate-control","value":"no-store"},{"key":"cache-control","value":"no-store, no-cache, must-revalidate, proxy-revalidate"},{"key":"pragma","value":"no-cache"},{"key":"expires","value":"0"},{"key":"content-type","value":"application/json; charset=utf-8"},{"key":"etag","value":"W/\"b8c-hABDbRBGcc23f91eLdf0Y3b1Z5Y\""},{"key":"date","value":"Fri, 27 Mar 2020 02:14:00 GMT"},{"key":"connection","value":"close"},{"key":"Vary","value":"Accept-Encoding"},{"key":"Content-Encoding","value":"gzip"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":"[\n    {\n        \"name\": \"top\",\n        \"version\": 46,\n        \"variables\": [\n            {\n                \"name\": \"_id\",\n                \"type\": \"id\"\n            },\n            {\n                \"name\": \"Client\",\n                \"type\": \"object\",\n                \"typeName\": \"person\",\n                \"isList\": false,\n                \"label\": \"Client\"\n            },\n            {\n                \"name\": \"IsMarried\",\n                \"type\": \"boolean\",\n                \"isList\": false,\n                \"label\": \"Is married\"\n            },\n            {\n                \"name\": \"Spouse\",\n                \"type\": \"object\",\n                \"typeName\": \"person\",\n                \"isList\": false,\n                \"label\": \"Spouse\"\n            },\n            {\n                \"name\": \"Children\",\n                \"type\": \"object\",\n                \"typeName\": \"person\",\n                \"isList\": true,\n                \"label\": \"Children\"\n            }\n        ]\n    },\n    {\n        \"name\": \"person\",\n        \"version\": 41,\n        \"variables\": [\n            {\n                \"name\": \"id$\",\n                \"type\": \"id\"\n            },\n            {\n                \"name\": \"Name\",\n                \"type\": \"string\",\n                \"isList\": false,\n                \"label\": \"Name\",\n                \"instances\": [\n                    \"Client\",\n                    \"Spouse\",\n                    \"Children[]\"\n                ]\n            },\n            {\n                \"name\": \"State\",\n                \"type\": \"string\",\n                \"isList\": false,\n                \"label\": \"State\",\n                \"selectFrom\": [\"Alabama\", \"Alaska\", ...],\n                \"selectOnly\": true,\n                \"instances\": [\n                    \"Client\"\n                ]\n            }\n        ],\n        \"instances\": [\n            \"Client\",\n            \"Spouse\",\n            \"Children[]\"\n        ]\n    }\n]"}],"_postman_id":"57d51af2-b6cf-410d-b674-267e65f0e65f"},{"name":"Get app data points","id":"f4dc4be8-623e-423a-b073-02ad468733cf","request":{"method":"GET","header":[],"url":"{{base_url}}/:workspace/api/v1/catalogs/:catalog/apps/:app_name/fields","description":"<p>Retrieves an array (flat list) of the data points that may be relevant to or required by the indicated app. Each property has a key and simple data type (string, number, date, boolean).</p>\n<p>This endpoint is similar to <a href=\"#821e771c-0b1f-434f-9055-ff6a28b48b40\">Get app model(s)</a>, but this returns a flat array of data points, whereas that one returns hierarchical schema information. Which endpoint you use depends on your application's architecture and what is more convenient for your needs.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}},"urlObject":{"path":[":workspace","api","v1","catalogs",":catalog","apps",":app_name","fields"],"host":["{{base_url}}"],"query":[],"variable":[{"id":"b8d2d016-1132-4eb7-80dc-a4e565f84c91","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"},{"id":"41341d78-a4ce-43c4-b0bf-08c6bc69787c","description":{"content":"<p>(Required) The name of the catalog containing the app</p>\n","type":"text/plain"},"type":"any","value":"{{catalog_name}}","key":"catalog"},{"id":"011c8236-62be-45e4-8468-138784874b34","description":{"content":"<p>(Required) The name of the app for which you intend to supply data</p>\n","type":"text/plain"},"type":"any","value":"{{app_name}}","key":"app_name"}]}},"response":[],"_postman_id":"f4dc4be8-623e-423a-b073-02ad468733cf"},{"name":"Get app table(s)","id":"6032a064-ca73-40bf-9666-4190ea6f283b","request":{"method":"GET","header":[],"url":"{{base_url}}/:workspace/api/v1/catalogs/:catalog/apps/:app_name/tables/:table_name","description":"<p>Retrieves information about a static table in Knackly. If no table name is supplied, retrieves the information about <em>all</em> static tables used by the indicated app.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}},"urlObject":{"path":[":workspace","api","v1","catalogs",":catalog","apps",":app_name","tables",":table_name"],"host":["{{base_url}}"],"query":[],"variable":[{"id":"a7ddfcde-2096-441a-86e4-d4c5eaebe505","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"},{"id":"2884f13a-b30b-457b-b98e-6d3c1705e982","description":{"content":"<p>(Required) The name of the catalog containing the app</p>\n","type":"text/plain"},"type":"any","value":"{{catalog_name}}","key":"catalog"},{"id":"2122c9b9-11c1-40b3-8d91-54cdfc32656f","description":{"content":"<p>(Required) The name of the app for which you want table data</p>\n","type":"text/plain"},"type":"any","value":"{{app_name}}","key":"app_name"},{"id":"701463db-a518-47c9-8a05-c1a83e345fd1","description":{"content":"<p>(Optional) The name of the specific table whose data you want to retrieve. If omitted, all tables defined in the app will be returned.</p>\n","type":"text/plain"},"type":"any","value":"","key":"table_name"}]}},"response":[],"_postman_id":"6032a064-ca73-40bf-9666-4190ea6f283b"}],"id":"c120ace8-be95-4b13-a713-585610a025e3","description":"<p>Schema information for apps. In Knackly, schema information is defined by</p>\n<ul>\n<li><p>Models</p>\n</li>\n<li><p>Tables</p>\n</li>\n<li><p>Queries</p>\n</li>\n</ul>\n<p>Generally, these are referred to as 'Elements' of a Knackly system. Of them, the API currently exposes Models and Tables.</p>\n<p>Each catalog has a Model. Different catalogs may be based on different models, or multiple catalogs may be based on the same model. A model defines Variables, which in turn define the \"shape\" of an instance of that model.</p>\n<p>Models are object-based. Variables can be scalars or arrays (lists); scalar data types include \"text\", \"number\", \"date\", \"true/false\", and \"object\". (Object-type variables also define which model the object data must adhere to.) There are also \"selection\" variables, where the answer is basically a foreign key (usually a text string) referring to some other object (which itself is stored in either a Table, an external Query, or elsewhere within the record).</p>\n<p>Knackly supports two ways of inspecting and thinking about the schema used by apps: nested and flat. For a nested view of the data, see <a href=\"#821e771c-0b1f-434f-9055-ff6a28b48b40\">Get app model(s)</a>. For a flat view, see <a href=\"#5a06e5a3-df76-42bf-bf86-3987df7a2b02\">Get app data points</a>.</p>\n","_postman_id":"c120ace8-be95-4b13-a713-585610a025e3","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}}},{"name":"List apps","id":"23ec6402-9674-4568-ad1f-e323e53f8a87","request":{"method":"GET","header":[],"url":"{{base_url}}/:workspace/api/v1/catalogs/:catalog/apps/:app_name","description":"<p>List the apps available for creating or editing records in the given catalog of the given Knackly workspace, or retrieve the details of a specific app from that catalog. </p>\n<p>An app can be used to create a new record in a catalog, or to generate (or re-generate) documents in an existing record in a catalog.</p>\n<p>If you have previously called <a href=\"#dbb8772a-5e30-454d-8b6e-65433efc553a\">List catalogs</a>, the metadata it returned about each catalog's apps is the same as what is returned by this request.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}},"urlObject":{"path":[":workspace","api","v1","catalogs",":catalog","apps",":app_name"],"host":["{{base_url}}"],"query":[],"variable":[{"id":"6252c75d-1ca7-40ba-a42a-5d31191a6654","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"},{"id":"7a22d521-8b80-4a7e-82a4-907fa0f1c69f","description":{"content":"<p>(Required) The name of the catalog containing the app(s)</p>\n","type":"text/plain"},"type":"any","value":"{{catalog_name}}","key":"catalog"},{"id":"9b7b185d-5638-41d9-b0c5-269661b9201b","description":{"content":"<p>(Optional) The name of a specific app available in this catalog. If no app name is included, information about all apps will be returned.</p>\n","type":"text/plain"},"type":"any","value":"{{app_name}}","key":"app_name"}]}},"response":[{"id":"00b21aef-4db6-4081-9eef-6658324e6f35","name":"Get a specific app","originalRequest":{"method":"GET","header":[],"url":{"raw":"{{base_url}}/:workspace/api/v1/catalogs/:catalog/apps/:app","host":["{{base_url}}"],"path":[":workspace","api","v1","catalogs",":catalog","apps",":app"],"variable":[{"key":"workspace","value":"{{workspace}}","description":"(Required) The name of a Knackly workspace"},{"key":"catalog","value":"{{catalog_name}}","description":"(Required) The name of the catalog containing the app(s)"},{"key":"app","value":"{{app_name}}","description":"(Optional) The name of a specific app in this collection. If no app name is included, information about all apps will be returned."}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Powered-By","value":"Express"},{"key":"x-dns-prefetch-control","value":"off"},{"key":"x-frame-options","value":"SAMEORIGIN"},{"key":"strict-transport-security","value":"max-age=15552000; includeSubDomains"},{"key":"x-download-options","value":"noopen"},{"key":"x-content-type-options","value":"nosniff"},{"key":"x-xss-protection","value":"1; mode=block"},{"key":"access-control-allow-origin","value":"*"},{"key":"surrogate-control","value":"no-store"},{"key":"cache-control","value":"no-store, no-cache, must-revalidate, proxy-revalidate"},{"key":"pragma","value":"no-cache"},{"key":"expires","value":"0"},{"key":"content-type","value":"application/json; charset=utf-8"},{"key":"content-length","value":"129"},{"key":"etag","value":"W/\"81-rAd7lQjU9JkQMcpRYMM+ri8vLHw\""},{"key":"date","value":"Fri, 27 Mar 2020 02:07:33 GMT"},{"key":"connection","value":"close"},{"key":"Vary","value":"Accept-Encoding"}],"cookie":[],"responseTime":null,"body":"{\n    \"name\": \"App1\",\n    \"label\": \"First App\",\n    \"typeName\": \"top\",\n    \"version\": \"latest\",\n    \"url\": \"https://test.go.knackly.io/localtest/Testing/App1\"\n}"},{"id":"09cda53d-84f4-426f-87ae-acc9027dbd71","name":"Get all apps","originalRequest":{"method":"GET","header":[],"url":{"raw":"{{base_url}}/:workspace/api/v1/catalogs/:catalog/apps/:app","host":["{{base_url}}"],"path":[":workspace","api","v1","catalogs",":catalog","apps",":app"],"variable":[{"key":"workspace","value":"{{workspace}}","description":"(Required) The name of a Knackly workspace"},{"key":"catalog","value":"{{catalog_name}}","description":"(Required) The name of the catalog containing the app(s)"},{"key":"app","value":"{{app_name}}","description":"(Optional) The name of a specific app in this collection. If no app name is included, information about all apps will be returned."}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Powered-By","value":"Express"},{"key":"x-dns-prefetch-control","value":"off"},{"key":"x-frame-options","value":"SAMEORIGIN"},{"key":"strict-transport-security","value":"max-age=15552000; includeSubDomains"},{"key":"x-download-options","value":"noopen"},{"key":"x-content-type-options","value":"nosniff"},{"key":"x-xss-protection","value":"1; mode=block"},{"key":"access-control-allow-origin","value":"*"},{"key":"surrogate-control","value":"no-store"},{"key":"cache-control","value":"no-store, no-cache, must-revalidate, proxy-revalidate"},{"key":"pragma","value":"no-cache"},{"key":"expires","value":"0"},{"key":"content-type","value":"application/json; charset=utf-8"},{"key":"content-length","value":"257"},{"key":"etag","value":"W/\"101-7ucH8NhOMfnB7g6iPHHpAN9+jm4\""},{"key":"date","value":"Fri, 27 Mar 2020 02:08:37 GMT"},{"key":"connection","value":"close"},{"key":"Vary","value":"Accept-Encoding"}],"cookie":[],"responseTime":null,"body":"[\n    {\n        \"name\": \"App1\",\n        \"label\": \"First App\",\n        \"typeName\": \"top\",\n        \"version\": \"latest\",\n        \"url\": \"https://test.go.knackly.io/localtest/Testing/App1\"\n    },\n    {\n        \"name\": \"App2\",\n        \"label\": \"App 2\",\n        \"typeName\": \"top\",\n        \"version\": \"latest\",\n        \"url\": \"https://test.go.knackly.io/localtest/Testing/App2\"\n    }\n]"}],"_postman_id":"23ec6402-9674-4568-ad1f-e323e53f8a87"},{"name":"Get current app version","id":"99929f68-332d-46d1-9daa-3c38c3fa3512","request":{"method":"GET","header":[],"url":"{{base_url}}/:workspace/api/v1/catalogs/:catalog/apps/:app_name/current_version","description":"<p>Retrieve the current version marker for a specific app in a catalog.</p>\n<p>If that app is pinned to a specific snapshot, this endpoint returns the pinned snapshot's version value (the version that will be used when retrieving and running the app definition). If the app is not pinned, it returns the current environment version for the workspace.</p>\n<p>This is useful for determining whether an app has changed on the server -- and thus whether schema information previously retrieved for that app is still current or may need to be refreshed.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}},"urlObject":{"path":[":workspace","api","v1","catalogs",":catalog","apps",":app_name","current_version"],"host":["{{base_url}}"],"query":[],"variable":[{"id":"7561f5e0-4e1b-4eec-a88c-2da626f24d94","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"},{"id":"942733b5-df57-438a-8a67-e4933a307449","description":{"content":"<p>(Required) The name of the catalog containing the app</p>\n","type":"text/plain"},"type":"any","value":"{{catalog_name}}","key":"catalog"},{"id":"1b32a72c-374f-42f3-bcb0-ab924b3759dc","description":{"content":"<p>(Required) The name of the app</p>\n","type":"text/plain"},"type":"any","value":"{{app_name}}","key":"app_name"}]}},"response":[{"id":"ed83398b-ecb6-40de-bee8-cdd6ae1736ca","name":"Get current app version","originalRequest":{"method":"GET","header":[],"url":{"raw":"{{base_url}}/:workspace/api/v1/catalogs/:catalog/apps/:app_name/current_version","host":["{{base_url}}"],"path":[":workspace","api","v1","catalogs",":catalog","apps",":app_name","current_version"],"variable":[{"key":"workspace","value":"{{workspace}}","description":"(Required) The name of a Knackly workspace"},{"key":"catalog","value":"{{catalog_name}}","description":"(Required) The name of the catalog containing the app"},{"key":"app_name","value":"{{app_name}}","description":"(Required) The name of the app"}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Powered-By","value":"Express"},{"key":"x-dns-prefetch-control","value":"off"},{"key":"x-frame-options","value":"SAMEORIGIN"},{"key":"strict-transport-security","value":"max-age=15552000; includeSubDomains"},{"key":"x-download-options","value":"noopen"},{"key":"x-content-type-options","value":"nosniff"},{"key":"x-xss-protection","value":"1; mode=block"},{"key":"access-control-allow-origin","value":"*"},{"key":"surrogate-control","value":"no-store"},{"key":"cache-control","value":"no-store, no-cache, must-revalidate, proxy-revalidate"},{"key":"pragma","value":"no-cache"},{"key":"expires","value":"0"},{"key":"content-type","value":"application/json; charset=utf-8"},{"key":"content-length","value":"24"},{"key":"etag","value":"W/\"18-vQ6VxqfQj99vMZew3fxxjSB2LGs\""},{"key":"date","value":"Wed, 01 Apr 2026 19:35:00 GMT"},{"key":"connection","value":"close"},{"key":"Vary","value":"Accept-Encoding"}],"cookie":[],"responseTime":null,"body":"{\n    \"version\": 1711996720391\n}"}],"_postman_id":"99929f68-332d-46d1-9daa-3c38c3fa3512"}],"id":"8c47fb72-0d3e-41d7-a721-7d56e6966c12","description":"<p>An <strong>app</strong> is a process, defined by a workspace administrator, that interactively gathers data from an end-user, stores that data in a record (in a catalog), and generates some number of documents from that data.</p>\n<p>There is no limit to how many documents (based on templates) a given app can produce; it can be dynamic based on the data provided. Multiple apps can also be run against the same record (and thus be based on the same shared data) at different times.</p>\n","_postman_id":"8c47fb72-0d3e-41d7-a721-7d56e6966c12","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}}},{"name":"Records","item":[{"name":"App Jobs","item":[{"name":"Get app status","id":"83d85c29-af69-47d6-804d-84620633fb61","request":{"method":"GET","header":[],"url":"{{base_url}}/:workspace/api/v1/catalogs/:catalog/items/:record_id/apps/:app_name","description":"<p>Get information about the status of an app that was run (or is still running) on the given record in the given catalog.</p>\n<p>This can be used to check whether the app completed successfully (status==\"Ok\"), to check whether the app produced documents, and to get the URLs from which each resulting document may be retrieved. The result also includes the URL to which a user may navigate, in order to run the app interactively and review or update this record's data.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}},"urlObject":{"path":[":workspace","api","v1","catalogs",":catalog","items",":record_id","apps",":app_name"],"host":["{{base_url}}"],"query":[],"variable":[{"id":"d158feae-f087-4c27-802a-d33dfdf3f5df","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"},{"id":"400eb813-053e-4595-b151-36ba9a6858e6","description":{"content":"<p>(Required) The name of the catalog</p>\n","type":"text/plain"},"type":"any","value":"{{catalog_name}}","key":"catalog"},{"id":"bcf73ec8-e9b9-4b44-b07d-07a023229b3e","description":{"content":"<p>(Required) The id of a record in that catalog</p>\n","type":"text/plain"},"type":"any","value":"{{record_id}}","key":"record_id"},{"id":"c716b688-8130-4142-8b86-347e5c526504","description":{"content":"<p>(Required) The name of an app that has previously been run on that record</p>\n","type":"text/plain"},"type":"any","value":"{{app_name}}","key":"app_name"}]}},"response":[{"id":"17d1d554-bda5-43e7-8eb4-fb59419d22e5","name":"Get app status","originalRequest":{"method":"GET","header":[],"url":{"raw":"{{base_url}}/:workspace/api/v1/catalogs/:catalog/items/:item/apps/:app","host":["{{base_url}}"],"path":[":workspace","api","v1","catalogs",":catalog","items",":item","apps",":app"],"variable":[{"key":"workspace","value":"{{workspace}}","description":"(Required) The name of a Knackly workspace"},{"key":"catalog","value":"{{catalog_name}}","description":"(Required) The name of the catalog"},{"key":"item","value":"{{item_id}}","description":"(Required) The id of an item in that catalog"},{"key":"app","value":"{{app_name}}","description":"(Required) The name of an app that has previously been run on that catalog item"}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Powered-By","value":"Express"},{"key":"x-dns-prefetch-control","value":"off"},{"key":"x-frame-options","value":"SAMEORIGIN"},{"key":"strict-transport-security","value":"max-age=15552000; includeSubDomains"},{"key":"x-download-options","value":"noopen"},{"key":"x-content-type-options","value":"nosniff"},{"key":"x-xss-protection","value":"1; mode=block"},{"key":"access-control-allow-origin","value":"*"},{"key":"surrogate-control","value":"no-store"},{"key":"cache-control","value":"no-store, no-cache, must-revalidate, proxy-revalidate"},{"key":"pragma","value":"no-cache"},{"key":"expires","value":"0"},{"key":"content-type","value":"application/json; charset=utf-8"},{"key":"content-length","value":"338"},{"key":"etag","value":"W/\"152-snHHt+iYUC4dUHOmUaL+0oiSJdc\""},{"key":"date","value":"Fri, 27 Mar 2020 02:23:09 GMT"},{"key":"connection","value":"close"},{"key":"Vary","value":"Accept-Encoding"}],"cookie":[],"responseTime":null,"body":"{\n    \"name\": \"Test\",\n    \"label\": \"Test\",\n    \"status\": \"Ok\",\n    \"lastRun\": \"2020-03-21T08:11:14.426Z\",\n    \"lastRunBy\": \"apitest\",\n    \"files\": [\n        {\n            \"name\": \"Dummy.docx\",\n            \"url\": \"https://test.go.knackly.io/localtest/download/Testing/5e75c7ae96594337c81ad6ce/5e75cc22eea55634b894c15c/0\"\n        }\n    ],\n    \"url\": \"https://test.go.knackly.io/localtest/Testing/items/5e75c7ae96594337c81ad6ce/Test\"\n}"}],"_postman_id":"83d85c29-af69-47d6-804d-84620633fb61"},{"name":"Run an app","id":"972999e0-b4a7-4225-90c9-2d3c931336c9","request":{"method":"POST","header":[],"url":"{{base_url}}/:workspace/api/v1/catalogs/:catalog/items/:record_id/apps/:app_name","description":"<p>Silently run a specified app on a specified record to immediately generate (or re-generate) documents. The request body must be empty; documents are generated using the data that is already stored in the indicated record.</p>\n<p>A response is returned immediately with the record's metadata. Use <a href=\"#773b8d31-af3a-42f7-9262-bfbcb1a6c3fe\">Get app status</a> to monitor the status of documents being generated.</p>\n<p>If you want to modify data before generating (or re-generating) documents, retrieve the existing record (using <a href=\"#3c486aa9-7fe1-4d7b-8951-9e911de4061a\">Get record (including data)</a>), make the modifications you desire using <a href=\"#427f4d9e-3b21-4a61-94b6-9a7f255d72ed\">Modify record</a>, and then <a href=\"#6c07e6ce-02de-470f-8007-dc6e982f4928\">run an app</a> with the modified data. Knackly currently requires this approach to prevent integrators from interfering with users who may be working through interactive app sessions.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}},"urlObject":{"path":[":workspace","api","v1","catalogs",":catalog","items",":record_id","apps",":app_name"],"host":["{{base_url}}"],"query":[{"disabled":true,"description":{"content":"<p>(Optional) Data in body uses flat structure instead of nesting</p>\n","type":"text/plain"},"key":"flat","value":""},{"disabled":true,"description":{"content":"<p>(Optional) Transitions record to the \"Needs Updating\" state; document generation is not initiated</p>\n","type":"text/plain"},"key":"suspend","value":""}],"variable":[{"id":"83b23197-4005-413c-8e23-a7304ac5c43d","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"},{"id":"46e1ab0b-5534-4545-8f63-f99ee5b11e43","description":{"content":"<p>(Required) The name of the catalog containing the app</p>\n","type":"text/plain"},"type":"any","value":"{{catalog_name}}","key":"catalog"},{"id":"6b98f953-7d80-456d-bbb1-06c5d18ef4bc","description":{"content":"<p>(Required) The id of a record in that catalog</p>\n","type":"text/plain"},"type":"any","value":"{{record_id}}","key":"record_id"},{"id":"958afec2-19fe-4315-afd5-a3e9751627a9","description":{"content":"<p>(Required) The name of an app (from this catalog) that will be added to or re-run on the indicated record</p>\n","type":"text/plain"},"type":"any","value":"{{app_name}}","key":"app_name"}]}},"response":[{"id":"8c695cd6-f63d-4e68-b314-d1712be50320","name":"Run an app on a catalog item","originalRequest":{"method":"POST","header":[],"url":{"raw":"{{base_url}}/:workspace/api/v1/catalogs/:catalog/items/:item/apps/:app","host":["{{base_url}}"],"path":[":workspace","api","v1","catalogs",":catalog","items",":item","apps",":app"],"variable":[{"key":"workspace","value":"{{workspace}}"},{"key":"catalog","value":"{{catalog_name}}"},{"key":"item","value":"{{item_id}}"},{"key":"app","value":"{{app_name}}"}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"x-powered-by","value":"Express"},{"key":"access-control-allow-origin","value":"*"},{"key":"surrogate-control","value":"no-store"},{"key":"cache-control","value":"no-store, no-cache, must-revalidate, proxy-revalidate"},{"key":"pragma","value":"no-cache"},{"key":"expires","value":"0"},{"key":"content-type","value":"application/json; charset=utf-8"},{"key":"content-length","value":"552"},{"key":"etag","value":"W/\"228-D+EMOlYoahTLSgLr0PsZ5ENB0rY\""},{"key":"date","value":"Sat, 21 Mar 2020 08:11:13 GMT"},{"key":"connection","value":"close"},{"key":"Vary","value":"Accept-Encoding"}],"cookie":[],"responseTime":null,"body":"{\n    \"id\": \"5e75c7ae96594337c81ad6ce\",\n    \"label\": \"\",\n    \"detail\": \"\",\n    \"status\": \"In Progress\",\n    \"lastModified\": \"2020-03-21T08:11:13.689Z\",\n    \"lastModifiedBy\": \"apitest\",\n    \"data\": { ... data that was already in the item ... },\n    \"apps\": [\n        {\n            \"name\": \"Test\",\n            \"label\": \"Test\",\n            \"status\": \"In Progress\",\n            \"lastRun\": \"2020-03-21T08:11:13.690Z\",\n            \"files\": [],\n            \"url\": \"https://test.go.knackly.io/localtest/Testing/items/5e75c7ae96594337c81ad6ce/Test\"\n        }\n    ]\n}"}],"_postman_id":"972999e0-b4a7-4225-90c9-2d3c931336c9"},{"name":"Create record and run an app","event":[{"listen":"test","script":{"type":"text/javascript","exec":["if (responseBody.startsWith(\"{\")) {\r\n  var jsonData = JSON.parse(responseBody);\r\n  postman.setEnvironmentVariable(\"record_id\", jsonData.id);\r\n}\r\n"]}}],"id":"e0b8e8c7-76a4-462e-91dc-951f2f537e12","request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n\t\"var1\": \"Sample\",\n\t\"var2\": \"data\",\n\t\"datevar\": \"2020-03-20\",\n\t\"numvar\": 35.5,\n\t\"boolvar\": true,\n\t\"textarray\": [\"one\", \"two\", \"three\"],\n\t\"objarray\": [\n\t\t{ \"id$\": \"id1\", \"name\": \"Andrew\" },\n\t\t{ \"id$\": \"id2\", \"name\": \"Lowell\" }\n\t],\n\t\"selvar\": \"id2\"\n}","options":{"raw":{"language":"json"}}},"url":"{{base_url}}/:workspace/api/v1/catalogs/:catalog/apps/:app_name","description":"<p>Create a new data record in the given catalog of the given Knackly workspace, AND (optionally) immediately run the given app on that item to generate documents. The request body should contain JSON constituting the new record's data object.</p>\n<p>The response is returned immediately with the newly created record's metadata. By default (that is, if the \"suspend\" key is not included in the query string) any documents that are part of the indicated app will immediately begin being generated. Use <a href=\"#773b8d31-af3a-42f7-9262-bfbcb1a6c3fe\">Get app status</a> to monitor the status of documents being generated; status will change to \"Completed\" (and file downloads will become available) when document generation is complete.</p>\n<p>The other alternative is to include the \"suspend\" key in the query string. In this case, document generation is NOT initiated; the new record will have a status of \"Needs Updating\". In this situation, the recommended course of action is to redirect the end user (in their browser) to the app URL that is included in the response. Doing so allows the user to run the app, review the data you have provided, optionally make changes or add additional data, and documents will be generated when they complete the app interactively.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}},"urlObject":{"path":[":workspace","api","v1","catalogs",":catalog","apps",":app_name"],"host":["{{base_url}}"],"query":[{"disabled":true,"description":{"content":"<p>(Optional) Create the record in the \"Needs Updating\" state; document generation is not initiated</p>\n","type":"text/plain"},"key":"suspend","value":""},{"disabled":true,"description":{"content":"<p>(Optional) Data in body uses flat structure instead of nesting</p>\n","type":"text/plain"},"key":"flat","value":""},{"disabled":true,"description":{"content":"<p>(Optional) Valid external authentication token, if record is to be open to an external user</p>\n","type":"text/plain"},"key":"external","value":"{{external_token}}"}],"variable":[{"id":"55425069-f9c0-4e42-bc27-c374af7d64b8","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"},{"id":"9c786126-c2b9-4bed-8efc-cda467769e62","description":{"content":"<p>(Required) The name of the catalog in which the record will be created</p>\n","type":"text/plain"},"type":"any","value":"{{catalog_name}}","key":"catalog"},{"id":"5166a012-4334-4a70-ae39-f3502b82f280","description":{"content":"<p>(Required) The name of an app (in this catalog) that will be run against the newly created record</p>\n","type":"text/plain"},"type":"any","value":"{{app_name}}","key":"app_name"}]}},"response":[{"id":"91198147-7098-4ef2-87d3-d68449a0d57b","name":"Create record by running app","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n\t\"var1\": \"Sample\",\n\t\"var2\": \"data\",\n\t\"datevar\": \"2020-03-20\",\n\t\"numvar\": 35.5,\n\t\"boolvar\": true,\n\t\"textarray\": [\"one\", \"two\", \"three\"],\n\t\"objarray\": [\n\t\t{ \"id$\": \"id1\", \"name\": \"Andrew\" },\n\t\t{ \"id$\": \"id2\", \"name\": \"Lowell\" }\n\t],\n\t\"selvar\": \"id2\"\n}","options":{"raw":{"language":"json"}}},"url":{"raw":"{{base_url}}/:workspace/api/v1/catalogs/:catalog/apps/:app","host":["{{base_url}}"],"path":[":workspace","api","v1","catalogs",":catalog","apps",":app"],"variable":[{"key":"workspace","value":"{{workspace}}","description":"(Required) The name of a Knackly workspace"},{"key":"catalog","value":"{{catalog_name}}","description":"(Required) The name of the catalog in which the item will be created"},{"key":"app","value":"{{app_name}}","description":"(Required) The name of an app (in this catalog) that will be run on the newly created item"}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Powered-By","value":"Express"},{"key":"x-dns-prefetch-control","value":"off"},{"key":"x-frame-options","value":"SAMEORIGIN"},{"key":"strict-transport-security","value":"max-age=15552000; includeSubDomains"},{"key":"x-download-options","value":"noopen"},{"key":"x-content-type-options","value":"nosniff"},{"key":"x-xss-protection","value":"1; mode=block"},{"key":"access-control-allow-origin","value":"*"},{"key":"surrogate-control","value":"no-store"},{"key":"cache-control","value":"no-store, no-cache, must-revalidate, proxy-revalidate"},{"key":"pragma","value":"no-cache"},{"key":"expires","value":"0"},{"key":"content-type","value":"application/json; charset=utf-8"},{"key":"content-length","value":"572"},{"key":"etag","value":"W/\"23c-oCoI+iQqOwDvumUGywGFQolvgUk\""},{"key":"date","value":"Fri, 27 Mar 2020 02:09:57 GMT"},{"key":"connection","value":"close"},{"key":"Vary","value":"Accept-Encoding"}],"cookie":[],"responseTime":null,"body":"{\n    \"id\": \"5e7d60758e7eda3138c41f5f\",\n    \"detail\": \"\",\n    \"status\": \"In Progress\",\n    \"lastModified\": \"2020-03-27T02:09:57.968Z\",\n    \"lastModifiedBy\": \"apitest\",\n    \"data\": { ... posted data ... },\n    \"apps\": [\n        {\n            \"name\": \"App1\",\n            \"label\": \"App1\",\n            \"status\": \"In Progress\",\n            \"lastRun\": \"2020-03-27T02:09:57.968Z\",\n            \"lastRunBy\": \"apitest\",\n            \"files\": [],\n            \"url\": \"https://test.go.knackly.io/localtest/Testing/items/5e7d60758e7eda3138c41f5f/App1\"\n        }\n    ]\n}"}],"_postman_id":"e0b8e8c7-76a4-462e-91dc-951f2f537e12"}],"id":"12da7239-0881-4115-8417-637aa1333744","description":"<p>Apps, in Knackly, refer to the processes (defined by workspace administrators) that control gathering data and producing documents.</p>\n<p><strong>App Jobs</strong> are how you instruct Knackly to run apps and (accordingly) generate documents.</p>\n<p><strong>Note</strong>: although you can poll the Get app status endpoint to wait for large or complex sets of documents to be produced, it is strongly recommended that you instead register a webhook and simply rely on that to notify you whenever documents are produced.</p>\n","_postman_id":"12da7239-0881-4115-8417-637aa1333744","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}}},{"name":"List records","id":"1577933d-a057-4d5c-beb2-1c9bc62e4994","request":{"method":"GET","header":[],"url":"{{base_url}}/:workspace/api/v1/catalogs/:catalog/items?skip=0&limit=10","description":"<p>List the records in the given catalog of the given Knackly workspace. Most recently created or modified records are listed first.</p>\n<p>This request returns only metadata about the records; to get the actual data or documents embedded in a record, you must call <a href=\"#3c486aa9-7fe1-4d7b-8951-9e911de4061a\">Get record (including data)</a> for that specific record.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}},"urlObject":{"path":[":workspace","api","v1","catalogs",":catalog","items"],"host":["{{base_url}}"],"query":[{"disabled":true,"description":{"content":"<p>Status filter (Optional)</p>\n","type":"text/plain"},"key":"status","value":"Ok"},{"description":{"content":"<p>Offset of first record to be listed (Optional, default 0)</p>\n","type":"text/plain"},"key":"skip","value":"0"},{"description":{"content":"<p>Page size (Optional, default 20)</p>\n","type":"text/plain"},"key":"limit","value":"10"},{"disabled":true,"description":{"content":"<p>Specific record ID for which to retrieve details (Optional)</p>\n","type":"text/plain"},"key":"id","value":"5e5f14cb1f844467b6fae106"},{"disabled":true,"description":{"content":"<p>Use flat structure instead of nesting for data (Optional)</p>\n","type":"text/plain"},"key":"flat","value":""}],"variable":[{"id":"e834d0db-5716-4da2-bd4d-dc9355f77462","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"},{"id":"5445a234-538e-4ae2-9e76-d472c8b21b4f","description":{"content":"<p>(Required) The name of the catalog containing the records you wish to enumerate</p>\n","type":"text/plain"},"type":"any","value":"{{catalog_name}}","key":"catalog"}]}},"response":[{"id":"d31ed8d7-f174-4eda-8088-96c1690b1894","name":"Example: List records","originalRequest":{"method":"GET","header":[],"url":{"raw":"{{base_url}}/:workspace/api/v1/catalogs/:catalog/items?skip=0&limit=3","host":["{{base_url}}"],"path":[":workspace","api","v1","catalogs",":catalog","items"],"query":[{"key":"skip","value":"0","description":"Offset of first record to be listed (Optional, default 0)"},{"key":"limit","value":"3","description":"Page size (Optional, default 20)"}],"variable":[{"key":"workspace","value":"{{workspace}}","description":"(Required) The name of a Knackly workspace"},{"key":"catalog","value":"{{catalog_name}}","description":"(Required) The name of the catalog containing the records you wish to enumerate"}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Powered-By","value":"Express"},{"key":"x-dns-prefetch-control","value":"off"},{"key":"x-frame-options","value":"SAMEORIGIN"},{"key":"strict-transport-security","value":"max-age=15552000; includeSubDomains"},{"key":"x-download-options","value":"noopen"},{"key":"x-content-type-options","value":"nosniff"},{"key":"x-xss-protection","value":"1; mode=block"},{"key":"access-control-allow-origin","value":"*"},{"key":"surrogate-control","value":"no-store"},{"key":"cache-control","value":"no-store, no-cache, must-revalidate, proxy-revalidate"},{"key":"pragma","value":"no-cache"},{"key":"expires","value":"0"},{"key":"content-type","value":"application/json; charset=utf-8"},{"key":"content-length","value":"449"},{"key":"etag","value":"W/\"1c1-dPCXIrOgGaK/HwM7nZ47Xqio1+Y\""},{"key":"date","value":"Fri, 27 Mar 2020 02:19:05 GMT"},{"key":"connection","value":"close"},{"key":"Vary","value":"Accept-Encoding"}],"cookie":[],"responseTime":null,"body":"[\n    {\n        \"id\": \"5e7d62788e7eda3138c41f64\",\n        \"label\": \"\",\n        \"detail\": \"\",\n        \"status\": \"Needs Updating\",\n        \"lastModified\": \"2020-03-27T02:18:32.365Z\",\n        \"lastModifiedBy\": \"apitest\"\n    },\n    {\n        \"id\": \"5e7d60758e7eda3138c41f5f\",\n        \"label\": \"[Client.Name]\",\n        \"detail\": \"\",\n        \"status\": \"Ok\",\n        \"lastModified\": \"2020-03-27T02:09:59.881Z\",\n        \"lastModifiedBy\": \"apitest\"\n    },\n    {\n        \"id\": \"5e73e452d003173344898512\",\n        \"label\": \"John\",\n        \"detail\": \"\",\n        \"status\": \"Ok\",\n        \"lastModified\": \"2020-03-23T19:06:57.477Z\",\n        \"lastModifiedBy\": \"Lowell\"\n    }\n]"}],"_postman_id":"1577933d-a057-4d5c-beb2-1c9bc62e4994"},{"name":"Get record (including data)","id":"40cafa8f-b184-412b-b9b0-3411b3c8c506","request":{"method":"GET","header":[],"url":"{{base_url}}/:workspace/api/v1/catalogs/:catalog/items/:record_id","description":"<p>Get the content of the given record in the given catalog of the given Knackly workspace. <strong>Includes user data</strong> captured by the apps run against that record, as well as a listing of the documents (files) generated by each app.</p>\n<p>Generated documents can be retrieved through another API request.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}},"urlObject":{"path":[":workspace","api","v1","catalogs",":catalog","items",":record_id"],"host":["{{base_url}}"],"query":[{"disabled":true,"description":{"content":"<p>(Optional) Use flat structure instead of nesting for data</p>\n","type":"text/plain"},"key":"flat","value":""}],"variable":[{"id":"519f5d19-e394-4304-b782-c5d54feeac46","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"},{"id":"b0887402-c698-4235-a0c4-cf855713c6be","description":{"content":"<p>(Required) The name of the catalog</p>\n","type":"text/plain"},"type":"any","value":"{{catalog_name}}","key":"catalog"},{"id":"382fe4cb-30b0-4379-b971-cc8213f56dea","description":{"content":"<p>(Required) The ID of the desired record</p>\n","type":"text/plain"},"type":"any","value":"{{record_id}}","key":"record_id"}]}},"response":[{"id":"0393d6f7-9008-46e2-882a-2b607187d045","name":"Example: Get record details","originalRequest":{"method":"GET","header":[],"url":{"raw":"{{base_url}}/:workspace/api/v1/catalogs/:catalog/items/:record_id","host":["{{base_url}}"],"path":[":workspace","api","v1","catalogs",":catalog","items",":record_id"],"variable":[{"key":"workspace","value":"{{workspace}}","description":"(Required) The name of a Knackly workspace"},{"key":"catalog","value":"{{catalog_name}}","description":"(Required) The name of the catalog"},{"key":"record_id","value":"{{record_id}}","description":"(Required) The ID of the desired record"}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Server","value":"nginx/1.14.0 (Ubuntu)"},{"key":"Date","value":"Fri, 20 Mar 2020 16:43:47 GMT"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"Transfer-Encoding","value":"chunked"},{"key":"Connection","value":"keep-alive"},{"key":"X-Powered-By","value":"Express"},{"key":"Access-Control-Allow-Origin","value":"*"},{"key":"Surrogate-Control","value":"no-store"},{"key":"Cache-Control","value":"no-store, no-cache, must-revalidate, proxy-revalidate"},{"key":"Pragma","value":"no-cache"},{"key":"Expires","value":"0"},{"key":"ETag","value":"W/\"32f-wCV/fXtiA9GBg0yo7YMx18wR96E\""},{"key":"Content-Encoding","value":"gzip"}],"cookie":[],"responseTime":null,"body":"{\n    \"id\": \"{{record_id}}\",\n    \"label\": \"Estate Plan for Norville Barnes\",\n    \"detail\": \"\",\n    \"status\": \"Ok\",\n    \"lastModified\": \"2020-02-25T15:22:36.763Z\",\n    \"lastModifiedBy\": \"Amy\",\n    \"data\": {\n        \"Client\": {\n            \"id$\": \"5e553967afa8f34e96c5ffac\",\n            \"PartyType\": \"Individual\",\n            \"First\": \"Norville\",\n            \"Last\": \"Barnes\",\n            \"Gender\": \"male\",\n            \"Birthdate\": \"1927-08-05\"\n        },\n        \"Docs\": [\n            \"Pourover Will\",\n            \"SingleRevTrust\",\n            \"HPOA\"\n        ],\n        \"TrustName\": \"You Know, For Kids!\"\n    },\n    \"apps\": [\n        {\n            \"name\": \"EstatePlan\",\n            \"label\": \"Estate Planning Documents\",\n            \"status\": \"Ok\",\n            \"lastRun\": \"2020-02-25T15:22:36.763Z\",\n            \"lastRunBy\": \"Amy\",\n            \"files\": [\n                {\n                    \"name\": \"Barnes.docx\",\n            \t\t\"url\": \"https://go.knackly.io/.../Barnes.docx\"\n                }\n            ],\n            \"url\": \"https://go.knackly.io/{{workspace}}/{{catalog_name}}/items/{{record_id}}/{{app_name}}\"\n        }\n    ]\n}"}],"_postman_id":"40cafa8f-b184-412b-b9b0-3411b3c8c506"},{"name":"Create record","event":[{"listen":"test","script":{"type":"text/javascript","exec":["if (responseBody.startsWith(\"{\")) {\r\n  var jsonData = JSON.parse(responseBody);\r\n  postman.setEnvironmentVariable(\"record_id\", jsonData.id);\r\n}\r\n"]}}],"id":"315775d1-b1df-4228-ad57-b6294ee32dd8","request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n                \"label\": \"Totally a Test\",\n                \"detail\": \"12345\"\n}","options":{"raw":{"language":"json"}}},"url":"{{base_url}}/:workspace/api/v1/catalogs/:catalog/items","description":"<p>Create a new record in the given catalog of the given Knackly workspace. The request body should contain JSON to constitute the new record's embedded data (see <a href=\"#821e771c-0b1f-434f-9055-ff6a28b48b40\">Get app model(s)</a> to retrieve schema information for this data).</p>\n<p>To automatically generate documents based on this record (after it has been created), make a subsequent request to <a href=\"#6c07e6ce-02de-470f-8007-dc6e982f4928\">run an app</a> on it. Alternatively, you can also create a record <strong>and</strong> run an app on it <a href=\"#e063d16f-9204-476a-be7d-c70de2cfd813\">in a single step</a> using <a href=\"#e063d16f-9204-476a-be7d-c70de2cfd813\">Create record by running app</a>.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}},"urlObject":{"path":[":workspace","api","v1","catalogs",":catalog","items"],"host":["{{base_url}}"],"query":[{"disabled":true,"description":{"content":"<p>(Optional) Data in body uses flat structure instead of nesting</p>\n","type":"text/plain"},"key":"flat","value":""},{"disabled":true,"description":{"content":"<p>(Optional) Valid external authentication token, if record is to be open to an external user</p>\n","type":"text/plain"},"key":"external","value":"{{external_token}}"}],"variable":[{"id":"3c880e21-e389-4cfc-99c1-3106a4dc7ee4","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"},{"id":"95562931-d9fc-4adb-992c-3010b0604e26","description":{"content":"<p>(Required) The name of the catalog in which to create the record</p>\n","type":"text/plain"},"type":"any","value":"{{catalog_name}}","key":"catalog"}]}},"response":[{"id":"63cd63d9-9fe0-463e-b76d-f037c49bc559","name":"Example: Create record","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n\t\"var1\": \"Sample\",\n\t\"var2\": \"data\",\n\t\"datevar\": \"2020-03-20\",\n\t\"numvar\": 35.5,\n\t\"boolvar\": true,\n\t\"textarray\": [\"one\", \"two\", \"three\"],\n\t\"objarray\": [\n\t\t{ \"id$\": \"id1\", \"name\": \"Andrew\" },\n\t\t{ \"id$\": \"id2\", \"name\": \"Lowell\" }\n\t],\n\t\"selvar\": \"id2\"\n}","options":{"raw":{"language":"json"}}},"url":{"raw":"{{base_url}}/:workspace/api/v1/catalogs/:catalog/items","host":["{{base_url}}"],"path":[":workspace","api","v1","catalogs",":catalog","items"],"variable":[{"key":"workspace","value":"{{workspace}}","description":"(Required) The name of a Knackly workspace"},{"key":"catalog","value":"{{catalog_name}}","description":"(Required) The name of the catalog in which the record will be created"}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Powered-By","value":"Express"},{"key":"x-dns-prefetch-control","value":"off"},{"key":"x-frame-options","value":"SAMEORIGIN"},{"key":"strict-transport-security","value":"max-age=15552000; includeSubDomains"},{"key":"x-download-options","value":"noopen"},{"key":"x-content-type-options","value":"nosniff"},{"key":"x-xss-protection","value":"1; mode=block"},{"key":"access-control-allow-origin","value":"*"},{"key":"surrogate-control","value":"no-store"},{"key":"cache-control","value":"no-store, no-cache, must-revalidate, proxy-revalidate"},{"key":"pragma","value":"no-cache"},{"key":"expires","value":"0"},{"key":"content-type","value":"application/json; charset=utf-8"},{"key":"content-length","value":"374"},{"key":"etag","value":"W/\"176-80ENqkLeAo68lnzzwZ+jfirUh6w\""},{"key":"date","value":"Fri, 27 Mar 2020 02:18:32 GMT"},{"key":"connection","value":"close"},{"key":"Vary","value":"Accept-Encoding"}],"cookie":[],"responseTime":null,"body":"{\n    \"id\": \"5e7d62788e7eda3138c41f64\",\n    \"label\": \"\",\n    \"detail\": \"\",\n    \"status\": \"Needs Updating\",\n    \"lastModified\": \"2020-03-27T02:18:32.365Z\",\n    \"lastModifiedBy\": \"apitest\",\n    \"data\": {\n        \"var1\": \"Sample\",\n        \"var2\": \"data\",\n        \"datevar\": \"2020-03-20\",\n        \"numvar\": 35.5,\n        \"boolvar\": true,\n        \"textarray\": [\n            \"one\",\n            \"two\",\n            \"three\"\n        ],\n        \"objarray\": [\n            {\n                \"id$\": \"id1\",\n                \"name\": \"Andrew\"\n            },\n            {\n                \"id$\": \"id2\",\n                \"name\": \"Lowell\"\n            }\n        ],\n        \"selvar\": \"id2\"\n    },\n    \"apps\": []\n}"}],"_postman_id":"315775d1-b1df-4228-ad57-b6294ee32dd8"},{"name":"Modify record","id":"c0444dcf-ee95-4dc0-8e5b-bd86ce74fa10","request":{"method":"PUT","header":[],"url":"{{base_url}}/:workspace/api/v1/catalogs/:catalog/items/:record_id","description":"<p>Modify <strong>the data</strong> in an already-existing record in the given catalog of the given Knackly workspace. The request body should contain JSON that will <strong>REPLACE</strong> the record's embedded data (see <a href=\"#821e771c-0b1f-434f-9055-ff6a28b48b40\">Get app model(s)</a> to retrieve schema information for this data).</p>\n<p>If you want to ADD data to what already exists within the record, you should first retrieve the current data, then modify/mutate that data in whatever way you want, and use this endpoint to REPLACE what was there with your mutated version.</p>\n<p>To generate documents based on this new data (after it has been updated), make a subsequent request to <a href=\"#6c07e6ce-02de-470f-8007-dc6e982f4928\">run an app</a> on it.</p>\n<p>Note: a record is <strong>locked</strong> whenever a user is currently using an app to view and/or modify that record's data. Attempts to modify a record that is locked should not succeed, because such modifications would either interfere with, OR immediately be clobbered by, the user's current activity.</p>\n<p><em><strong>Important note:</strong></em> <em>This endpoint should be considered BETA. Its behavior may be refined over time. In particular, it may allow modifications that are later rejected as errors, and it may reject modifications that could later be allowed. This is because the rules for exactly when and how records are locked and unlocked are not 100% solid yet. So, expect minor adjustments moving forward.</em></p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}},"urlObject":{"path":[":workspace","api","v1","catalogs",":catalog","items",":record_id"],"host":["{{base_url}}"],"query":[{"disabled":true,"description":{"content":"<p>(Optional) Data in body uses flat structure instead of nesting</p>\n","type":"text/plain"},"key":"flat","value":""}],"variable":[{"id":"fd5e2a79-d4a8-4900-9691-4035d644b9e8","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"},{"id":"88f418f9-0147-4452-87e9-01c94a4e3773","description":{"content":"<p>(Required) The name of the catalog</p>\n","type":"text/plain"},"type":"any","value":"{{catalog_name}}","key":"catalog"},{"id":"bb8a52eb-a8c4-466a-8227-b42596324f00","description":{"content":"<p>(Required) The id of a record in that catalog</p>\n","type":"text/plain"},"type":"any","value":"{{record_id}}","key":"record_id"}]}},"response":[],"_postman_id":"c0444dcf-ee95-4dc0-8e5b-bd86ce74fa10"},{"name":"Delete record","id":"66659cb6-22a1-4cf3-9a6e-c96909eb4b38","request":{"method":"DELETE","header":[],"url":"{{base_url}}/:workspace/api/v1/catalogs/:catalog/items/:record_id","description":"<p>Delete a single record from the given catalog of the given Knackly workspace. Also removes all metadata and previously generated documents associated with the record.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}},"urlObject":{"path":[":workspace","api","v1","catalogs",":catalog","items",":record_id"],"host":["{{base_url}}"],"query":[],"variable":[{"id":"b9103d61-e596-47dc-96af-2f819fb5ffe6","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"},{"id":"ebd9beba-60f3-4727-843f-5cde694145ca","description":{"content":"<p>(Required) The name of the catalog</p>\n","type":"text/plain"},"type":"any","value":"{{catalog_name}}","key":"catalog"},{"id":"2fa6fe56-3674-4135-a6be-1d836ee2ada6","description":{"content":"<p>(Required) The id of a record in that catalog</p>\n","type":"text/plain"},"type":"any","value":"{{record_id}}","key":"record_id"}]}},"response":[],"_postman_id":"66659cb6-22a1-4cf3-9a6e-c96909eb4b38"}],"id":"871c33bd-6980-4fc8-88ef-5be3c598270e","description":"<p>A <strong>record</strong> is a single item in a <a href=\"#873f9e6e-0829-4ef2-a585-eef2e1f1bd4f\">catalog</a>. Each record is a data object that typically adheres to the <a href=\"#d106dd99-062a-4c48-a444-99d0bb4ff8f8\">model</a> of the catalog in which it is stored. In other words, a record (in a catalog) is an instance of the catalog's data Model.</p>\n<p>Records consist of 3 types of data:</p>\n<ul>\n<li><p>Metadata about the record (status, modified date, modified by user, etc.)</p>\n</li>\n<li><p>Data -- the actual data (whether entered by end-users via an app's user interface, or passed in via the API) on which documents will be based</p>\n</li>\n<li><p>Documents generated by apps</p>\n</li>\n</ul>\n<p>When you <a href=\"#5a54c6fe-5d68-4c77-bca9-6e4ac22c4415\">List records</a>, you will only get Metadata about the records. To obtain the full data in a record (including its data and documents), you must call <a href=\"#3c486aa9-7fe1-4d7b-8951-9e911de4061a\">Get record (including data)</a> for a specific record.</p>\n","_postman_id":"871c33bd-6980-4fc8-88ef-5be3c598270e","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}}},{"name":"List catalogs","id":"fbd0ed33-4cde-4e13-84e7-d34c84adb81a","request":{"method":"GET","header":[],"url":"{{base_url}}/:workspace/api/v1/catalogs","description":"<p>List the catalogs defined in the given Knackly workspace. The response includes metadata about all catalogs accessible via the current API key, as well as the <a href=\"#c5c258a3-27f8-4d1c-89a5-2f13c8d8e70e\">apps</a> available for each catalog.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}},"urlObject":{"path":[":workspace","api","v1","catalogs"],"host":["{{base_url}}"],"query":[],"variable":[{"id":"1da68acf-ae53-4edf-b05c-f64b6522cc26","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"}]}},"response":[{"id":"c8873440-8dc7-45de-9892-bf949ecf93d0","name":"Get available catalogs (200)","originalRequest":{"method":"GET","header":[],"url":{"raw":"{{base_url}}/:workspace/api/v1/catalogs","host":["{{base_url}}"],"path":[":workspace","api","v1","catalogs"],"variable":[{"key":"workspace","value":"{{workspace}}","description":"(Required) The name of a Knackly workspace"}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Powered-By","value":"Express"},{"key":"x-dns-prefetch-control","value":"off"},{"key":"x-frame-options","value":"SAMEORIGIN"},{"key":"strict-transport-security","value":"max-age=15552000; includeSubDomains"},{"key":"x-download-options","value":"noopen"},{"key":"x-content-type-options","value":"nosniff"},{"key":"x-xss-protection","value":"1; mode=block"},{"key":"access-control-allow-origin","value":"*"},{"key":"surrogate-control","value":"no-store"},{"key":"cache-control","value":"no-store, no-cache, must-revalidate, proxy-revalidate"},{"key":"pragma","value":"no-cache"},{"key":"expires","value":"0"},{"key":"content-type","value":"application/json; charset=utf-8"},{"key":"content-length","value":"355"},{"key":"etag","value":"W/\"163-4Mh0JBKUrfl/94kCo8linTRehB8\""},{"key":"date","value":"Fri, 27 Mar 2020 02:05:31 GMT"},{"key":"connection","value":"close"},{"key":"Vary","value":"Accept-Encoding"}],"cookie":[],"responseTime":null,"body":"[\n    {\n        \"name\": \"Testing\",\n        \"label\": \"Catalog 1\",\n        \"typeName\": \"top\",\n        \"apps\": [\n            {\n                \"name\": \"App1\",\n                \"label\": \"First App\",\n                \"version\": \"latest\",\n                \"url\": \"https://test.go.knackly.io/localtest/Testing/App1\"\n            },\n            {\n                \"name\": \"Test\",\n                \"label\": \"Test\",\n                \"version\": \"latest\",\n                \"url\": \"https://test.go.knackly.io/localtest/Testing/Test\"\n            }\n        ]\n    },\n    {\n        \"name\": \"Catalog2\",\n        \"label\": \"Catalog 2\",\n        \"typeName\": \"top\",\n        \"apps\": [\n            {\n                \"name\": \"Test\",\n                \"label\": \"Test\",\n                \"version\": \"latest\",\n                \"url\": \"https://test.go.knackly.io/localtest/Catalog2/Test\"\n            }\n        ]\n    }\n]"}],"_postman_id":"fbd0ed33-4cde-4e13-84e7-d34c84adb81a"}],"id":"5cf9b818-72fa-40cc-b904-129f0dd13f1c","description":"<p>A <strong>catalog</strong> is a database/repository/table where a customer's data is stored <em>and</em> related documents are generated. A catalog is essentially a collection of <a href=\"#74f947c7-2d45-47be-893a-4391dec2d33e\">records</a>.</p>\n<p>One workspace can contain any number of catalogs.</p>\n<p>A catalog is the boundary for data access permissions in Knackly: groups of users have rights to view/modify data, or see the documents produced from that data, based on whether they have access to the catalog or not.</p>\n<p>API keys are also granted access on a per-catalog basis.</p>\n","_postman_id":"5cf9b818-72fa-40cc-b904-129f0dd13f1c","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}}},{"name":"Webhooks","item":[{"name":"List webhooks","id":"215bb7b6-f83a-47da-b687-3043fbd6dc66","request":{"method":"GET","header":[],"url":"{{base_url}}/:workspace/api/v1/webhooks","description":"<p>List all webhooks registered in the workspace. Returns information about all webhooks including their URLs, subscribed events, and associated catalogs.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}},"urlObject":{"path":[":workspace","api","v1","webhooks"],"host":["{{base_url}}"],"query":[],"variable":[{"id":"111e9d39-244a-4c58-8707-42d895778fab","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"}]}},"response":[],"_postman_id":"215bb7b6-f83a-47da-b687-3043fbd6dc66"},{"name":"Get webhook","id":"c976abee-8ace-4def-8c23-ddb817e11c3f","request":{"method":"GET","header":[],"url":"{{base_url}}/:workspace/api/v1/webhooks/:id","description":"<p>Get details for a specific webhook in the workspace. Returns information about the webhook including its URL, subscribed events, associated catalogs, and custom headers.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}},"urlObject":{"path":[":workspace","api","v1","webhooks",":id"],"host":["{{base_url}}"],"query":[],"variable":[{"id":"8ab40e69-cfd1-44ac-9dbc-56c3da91afd6","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"},{"id":"34d856f7-3c76-449f-85f8-16645d9a5879","description":{"content":"<p>(Required) The ID of the webhook to retrieve</p>\n","type":"text/plain"},"type":"any","value":"{{webhook_id}}","key":"id"}]}},"response":[],"_postman_id":"c976abee-8ace-4def-8c23-ddb817e11c3f"},{"name":"Create (register) webhook","event":[{"listen":"test","script":{"type":"text/javascript","exec":["if (responseBody.startsWith(\"{\")) {\r\n  var jsonData = JSON.parse(responseBody);\r\n  postman.setEnvironmentVariable(\"webhook_id\", jsonData.id);\r\n}\r\n"]}}],"id":"6359b0e4-0dbf-4325-832e-0a4c70c8ecdf","request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\r\n    \"url\": \"{{webhook_url}}\",\r\n    \"events\": [\"catalog.app.completed\"],\r\n    \"catalogs\": [\"all\"]\r\n}","options":{"raw":{"language":"json"}}},"url":"{{base_url}}/:workspace/api/v1/webhooks","description":"<p>Register/create a new webhook in the given Knackly workspace. The request body should contain JSON indicating...</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th><strong>property</strong></th>\n<th><strong>description</strong></th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>url</td>\n<td>When the requested type of event occurs, Knackly will post a JSON object with metadata about the event to whatever HTTP server may be listening at this URL.  <br />Must use the HTTPS protocol and have a valid certificate.</td>\n</tr>\n<tr>\n<td>events</td>\n<td>A JSON Array of strings, where each string is the name of an event your application wants to be notified of. See below for valid event names.</td>\n</tr>\n<tr>\n<td>catalogs</td>\n<td>A JSON array of strings, where each string is the name of a catalog in your Knackly workspace, OR the word \"all\" to indicate all catalogs.  <br />For example, if you have one Knackly catalog for development and/or test data, and a different catalog for production data, you might register a webhook for only the production catalog, so as not to receive notifications based on events occurring in development or test catalogs.</td>\n</tr>\n<tr>\n<td>customHeaders <em>(optional)</em></td>\n<td>If included, a JSON object. Each property of this object will be added as a custom HTTP header when Knackly invokes the webhook. Keys must be valid names for HTTP headers, and corresponding values must be a strings that are likewise valid in HTTP headers.</td>\n</tr>\n</tbody>\n</table>\n</div><h2 id=\"event-names\">Event Names</h2>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th><strong>event name</strong></th>\n<th><strong>triggered when...</strong></th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>catalog.app.completed</td>\n<td>an app has finished running and documents have been generated.  <br />The app may have been run as a result of a user interactively filling out data and clicking Complete, or the app being initiated via the API.</td>\n</tr>\n<tr>\n<td>catalog.app.modified</td>\n<td>a record's data has been modified by a user running an app, but the user chose \"Finish Later\" so no documents were produced.</td>\n</tr>\n<tr>\n<td>catalog.app.custom_action</td>\n<td>the user clicks a custom button that has been added to the record view in Knackly.</td>\n</tr>\n</tbody>\n</table>\n</div><p>Support for additional events may be added in the future.</p>\n<h3 id=\"payload\">Payload</h3>\n<p>The following metadata is posted to the webhook:</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th><strong>property</strong></th>\n<th><strong>description</strong></th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>eventId</td>\n<td>a unique ID identifying this event (not currently used for much)</td>\n</tr>\n<tr>\n<td>eventName</td>\n<td>the name of the event</td>\n</tr>\n<tr>\n<td>catalog</td>\n<td>the name of the Knackly catalog in which the event occurred</td>\n</tr>\n<tr>\n<td>record</td>\n<td>the ID of the record in the above catalog, on which the event occurred. Use this to retrieve data or documents.</td>\n</tr>\n<tr>\n<td>app</td>\n<td>the name of the app</td>\n</tr>\n<tr>\n<td>docsStarted</td>\n<td><em>catalog.app.completed only:</em> the date/time stamp when the user completed the app (documents started generating)</td>\n</tr>\n<tr>\n<td>docsFinished</td>\n<td><em>catalog.app.completed only:</em> the date/time stamp when documents finished generating for the app</td>\n</tr>\n<tr>\n<td>docCount</td>\n<td><em>catalog.app.completed only:</em> the number of documents generated by the app</td>\n</tr>\n<tr>\n<td>userType</td>\n<td>either \"regular\", \"external\", or \"api\"</td>\n</tr>\n<tr>\n<td>userName</td>\n<td>the user's name (for regular or external users) or the API key name (if app was run directly from the API)</td>\n</tr>\n<tr>\n<td>userEmail</td>\n<td>the user's email address (for regular and external users only)</td>\n</tr>\n</tbody>\n</table>\n</div>","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}},"urlObject":{"path":[":workspace","api","v1","webhooks"],"host":["{{base_url}}"],"query":[],"variable":[{"id":"cf344663-7117-40dd-af2c-c48e97376693","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"}]}},"response":[{"id":"d6a5d0f7-5694-4f50-a28f-f8ac4c0fac48","name":"Register webhook","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\r\n    \"url\": \"{{webhook_url}}\",\r\n    \"events\": [\"catalog.app.completed\"],\r\n    \"catalogs\": [\"all\"],\r\n    \"customHeaders\": {\r\n        \"X-My-Custom-Header\": \"abcdefg\"\r\n    }\r\n}","options":{"raw":{"language":"json"}}},"url":{"raw":"{{base_url}}/:workspace/api/v1/webhooks","host":["{{base_url}}"],"path":[":workspace","api","v1","webhooks"],"variable":[{"key":"workspace","value":"{{workspace}}","description":"(Required) The name of a Knackly workspace"}]}},"status":"Created","code":201,"_postman_previewlanguage":"json","header":[{"key":"X-Powered-By","value":"Express"},{"key":"x-dns-prefetch-control","value":"off"},{"key":"x-frame-options","value":"SAMEORIGIN"},{"key":"strict-transport-security","value":"max-age=15552000; includeSubDomains"},{"key":"x-download-options","value":"noopen"},{"key":"x-content-type-options","value":"nosniff"},{"key":"x-xss-protection","value":"1; mode=block"},{"key":"access-control-allow-origin","value":"*"},{"key":"surrogate-control","value":"no-store"},{"key":"cache-control","value":"no-store, no-cache, must-revalidate, proxy-revalidate"},{"key":"pragma","value":"no-cache"},{"key":"expires","value":"0"},{"key":"content-type","value":"application/json; charset=utf-8"},{"key":"content-length","value":"202"},{"key":"etag","value":"W/\"ca-ML23kxe4UgQ7CHIXmUVB5DRgVeM\""},{"key":"date","value":"Thu, 13 Apr 2023 22:29:48 GMT"},{"key":"connection","value":"close"},{"key":"Vary","value":"Accept-Encoding"}],"cookie":[],"responseTime":null,"body":"{\n    \"id\": \"6438825c91acaf47eaa33737\",\n    \"url\": \"https://webhook.site/fca77de2-335a-4b94-b651-f6128db30c36\",\n    \"catalogs\": [\n        \"all\"\n    ],\n    \"events\": [\n        \"catalog.app.completed\"\n    ],\n    \"customHeaders\": {\n        \"X-My-Custom-Header\": \"abcdefg\"\n    }\n}"}],"_postman_id":"6359b0e4-0dbf-4325-832e-0a4c70c8ecdf"},{"name":"Delete (unregister) webhook","id":"46cf1c2a-1493-4a34-9e48-0878f85b4404","request":{"method":"DELETE","header":[],"url":"{{base_url}}/:workspace/api/v1/webhooks/:id","description":"<p>Unregister/delete a previously-registered webhook in the given Knackly workspace.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}},"urlObject":{"path":[":workspace","api","v1","webhooks",":id"],"host":["{{base_url}}"],"query":[],"variable":[{"id":"5a094d31-11ff-4f80-9eba-4fcd665b3855","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"},{"id":"db350ae0-e293-4613-a95c-c76456b957f2","description":{"content":"<p>(Required) The id of the webhook you wish to unregister/delete</p>\n","type":"text/plain"},"type":"any","value":"{{webhook_id}}","key":"id"}]}},"response":[],"_postman_id":"46cf1c2a-1493-4a34-9e48-0878f85b4404"}],"id":"b233b3d4-9b9f-419d-881b-b8434a3da7cc","description":"<p><strong>Webhooks</strong> are HTTP-based callback functions that allow lightweight, event-driven communication between two APIs.</p>\n<p>In Knackly, your application can register a webhook to be notified when certain events take place. When your application receives this notification, it includes data you can use in making subsequent API calls, depending on your application's needs.</p>\n<h3 id=\"events\">Events</h3>\n<p>Knackly allows webhooks to be registered for the following events:</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th><strong>event name</strong></th>\n<th><strong>triggered when...</strong></th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>catalog.app.completed</td>\n<td>an app has finished running and documents have been generated.  <br />The app may have been run as a result of a user interactively filling out data and clicking Complete, or the app being initiated via the API.</td>\n</tr>\n<tr>\n<td>catalog.app.modified</td>\n<td>a record's data has been modified by a user running an app, but the user chose \"Finish Later\" so no documents were produced.</td>\n</tr>\n<tr>\n<td>catalog.app.custom_action</td>\n<td>the user clicks a custom button that has been added to the record view in Knackly.</td>\n</tr>\n</tbody>\n</table>\n</div>","_postman_id":"b233b3d4-9b9f-419d-881b-b8434a3da7cc","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}}},{"name":"External Tokens","item":[{"name":"Create external user and token","event":[{"listen":"test","script":{"type":"text/javascript","exec":["if (responseBody.startsWith(\"{\")) {\r\n  var jsonData = JSON.parse(responseBody);\r\n  postman.setEnvironmentVariable(\"refresh_token\", jsonData.Refresh_Token);\r\n  postman.setEnvironmentVariable(\"external_token\", jsonData.Token);\r\n}\r\n"]}}],"id":"aa925e4b-25fd-4094-a492-46bfb2611c9a","request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\r\n\t\"Email\": \"{{user_email}}\",\r\n\t\"Name\": \"{{user_name}}\"\r\n}","options":{"raw":{"language":"json"}}},"url":"{{base_url}}/:workspace/api/v1/externals","description":"<p>Provision/create a new external user in the given Knackly workspace. The request body should contain JSON indicating the new user's email address and user name.</p>\n<p>The response will include a time-limited token that can be passed on the query string to authorize the current user to access the indicated app in lieu of logging in. The response also includes a refresh token that can be used to <a href=\"#32ed5386-529c-41fb-aed4-0e21f9a5f4a6\">Refresh external token</a> once it has expired (check validity using <a href=\"#e27f82f4-4102-4b67-91a2-7925936e514d\">Validate external token</a>).</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}},"urlObject":{"path":[":workspace","api","v1","externals"],"host":["{{base_url}}"],"query":[],"variable":[{"id":"5ea7520e-5aa1-4069-9de9-62ee91b43765","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"}]}},"response":[{"id":"62010354-79ff-4512-9026-ce41b1d304df","name":"Create external user","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\r\n\t\"Email\": \"{{user_email}}\",\r\n\t\"Name\": \"{{user_name}}\"\r\n}","options":{"raw":{"language":"json"}}},"url":{"raw":"{{base_url}}/:workspace/api/v1/externals","host":["{{base_url}}"],"path":[":workspace","api","v1","externals"],"variable":[{"key":"workspace","value":"{{workspace}}","description":"(Required) The name of a Knackly workspace"}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Server","value":"nginx/1.14.0 (Ubuntu)"},{"key":"Date","value":"Tue, 03 Aug 2021 17:19:08 GMT"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"Transfer-Encoding","value":"chunked"},{"key":"Connection","value":"keep-alive"},{"key":"X-DNS-Prefetch-Control","value":"off"},{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"Strict-Transport-Security","value":"max-age=15552000; includeSubDomains"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-XSS-Protection","value":"1; mode=block"},{"key":"Access-Control-Allow-Origin","value":"*"},{"key":"Surrogate-Control","value":"no-store"},{"key":"Cache-Control","value":"no-store, no-cache, must-revalidate, proxy-revalidate"},{"key":"Pragma","value":"no-cache"},{"key":"Expires","value":"0"},{"key":"ETag","value":"W/\"6f-LVVYWXo/BKtFSvr1wbycxUagmTQ\""},{"key":"Content-Encoding","value":"gzip"}],"cookie":[],"responseTime":null,"body":"{\n    \"Token\": \"bb838d0c27a81f2b2d809ca8af569bd1c03aa03b\",\n    \"Refresh_Token\": \"30888a0584f0a91a388103d4c06e05f425a756c3\"\n}"}],"_postman_id":"aa925e4b-25fd-4094-a492-46bfb2611c9a"},{"name":"Create external token by user id","event":[{"listen":"test","script":{"type":"text/javascript","exec":["if (responseBody.startsWith(\"{\")) {\r\n  var jsonData = JSON.parse(responseBody);\r\n  postman.setEnvironmentVariable(\"refresh_token\", jsonData.Refresh_Token);\r\n  postman.setEnvironmentVariable(\"external_token\", jsonData.Token);\r\n}\r\n"]}}],"id":"0b64ce9d-1709-4ea3-986d-319e888a7413","request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\r\n    \"User_id\": \"{{user_id}}\",\r\n    \"Token_Lifetime\": 86400 //5 min\r\n}","options":{"raw":{"language":"json"}}},"url":"{{base_url}}/:workspace/api/v1/externals","description":"<p>Provision/create a new external user in the given Knackly workspace. The request body should contain JSON indicating the new user's email address and user name.</p>\n<p>The response will include a time-limited token that can be passed on the query string to authorize the current user to access the indicated app in lieu of logging in. The response also includes a refresh token that can be used to <a href=\"#32ed5386-529c-41fb-aed4-0e21f9a5f4a6\">Refresh external token</a> once it has expired (check validity using <a href=\"#e27f82f4-4102-4b67-91a2-7925936e514d\">Validate external token</a>).</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}},"urlObject":{"path":[":workspace","api","v1","externals"],"host":["{{base_url}}"],"query":[],"variable":[{"id":"25baebf3-fae8-4975-9edc-3fcfe7a8965c","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"}]}},"response":[],"_postman_id":"0b64ce9d-1709-4ea3-986d-319e888a7413"},{"name":"Validate external token","id":"a2d21dce-fee1-416b-8ae1-4ba7eea807cd","request":{"method":"GET","header":[],"url":"{{base_url}}/:workspace/api/v1/externals/valid/:token","description":"<p>Validates whether a token returned by a prior call to <a href=\"#e07f2313-5b5d-43bc-8140-f2664df5e889\">Create external user and token</a> or <a href=\"#32ed5386-529c-41fb-aed4-0e21f9a5f4a6\">Refresh external token</a> is still valid. If the token is valid, that token can be passed on the query string to a Knackly app's URL, to substitute for the current user needing to explicitly log in before they run the app.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}},"urlObject":{"path":[":workspace","api","v1","externals","valid",":token"],"host":["{{base_url}}"],"query":[],"variable":[{"id":"4c46faed-9f84-463f-b0d6-96ba1f1c5188","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"},{"id":"d4de85b0-f796-4c19-8808-107ee741907b","description":{"content":"<p>(Required) A token returned by a previous call to 'Create external user' or 'Refresh external token'</p>\n","type":"text/plain"},"type":"any","value":"{{external_token}}","key":"token"}]}},"response":[],"_postman_id":"a2d21dce-fee1-416b-8ae1-4ba7eea807cd"},{"name":"Refresh external token","event":[{"listen":"test","script":{"type":"text/javascript","exec":["if (responseBody.startsWith(\"{\")) {\r\n  var jsonData = JSON.parse(responseBody);\r\n  postman.setEnvironmentVariable(\"external_token\", jsonData.Token);\r\n}\r\n"]}}],"id":"7ccb55c0-48ac-44a0-b4df-9e42857a13f8","request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\r\n    \"Refresh_Token\":\"{{refresh_token}}\"\r\n}","options":{"raw":{"language":"json"}}},"url":"{{base_url}}/:workspace/api/v1/externals/refresh","description":"<p>If a call to <a href=\"#e27f82f4-4102-4b67-91a2-7925936e514d\">validate an external token</a> fails -- meaning the given token is no longer valid -- the <a href=\"#e07f2313-5b5d-43bc-8140-f2664df5e889\">previously generated</a> Refresh_Token must be used to refresh it before the current user can be redirected to a Knackly app.</p>\n<p>The body of the POST must include the current user's Refresh_Token, as returned from the original call to <a href=\"#e07f2313-5b5d-43bc-8140-f2664df5e889\">create the external user</a>. The response will include a refreshed Token that can replace the prior Token stored with that user's other information in your app.</p>\n<p>Note that the Refresh_Token itself remains the same for each user -- it is used to refresh the normal authorization Token, but the Refresh_Token itself should not be replaced.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}},"urlObject":{"path":[":workspace","api","v1","externals","refresh"],"host":["{{base_url}}"],"query":[],"variable":[{"id":"98858ec8-15db-4bbb-a5fe-17ee3d17558b","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"}]}},"response":[],"_postman_id":"7ccb55c0-48ac-44a0-b4df-9e42857a13f8"}],"id":"4d2751f7-65b9-4810-a5bf-06cca741c1a8","description":"<p>This is a provisional API that can replace the registration and login process for a new \"external user\" in Knackly.</p>\n<p>If you maintain your own web app with authenticated users, and you want to link one of your users to an interactive app inside a Knackly workspace <em>without them needing to log in</em>, your app must basically log in on behalf of that user:</p>\n<ol>\n<li><p>Initially, your app must call the <a href=\"#e07f2313-5b5d-43bc-8140-f2664df5e889\">Create external user</a> API, passing in your user's email address and user name. The response will include a token and a refresh token, both of which you must store in your app associated with that user.</p>\n</li>\n<li><p>For newly-created users, that token will be fresh, so the user can be redirected (in their browser) to the appropriate app URL without further steps. (See below for details on app URLs.)</p>\n</li>\n<li><p>If the current user was authorized with Knackly at some point in the past, you must <a href=\"#e27f82f4-4102-4b67-91a2-7925936e514d\">check whether their token is still valid</a>, and if it is not, you must <a href=\"#32ed5386-529c-41fb-aed4-0e21f9a5f4a6\">refresh the token</a> <strong>before</strong> redirecting the user to the app URL.</p>\n</li>\n</ol>\n<h2 id=\"external-access-to-records\">External Access to Records</h2>\n<p>External users in Knackly have limited access to the system. Such a user can only access the records created by (or specifically for) her or him, and only so long as external access on each of those records has not been closed.</p>\n<p>How you navigate an external user to an app, depends on whether you intend them to interactively create a new record from scratch, or whether you intend them to edit an existing record to which they have access.</p>\n<h3 id=\"creating-a-new-record\">Creating a new record</h3>\n<p>For an external user to create a new record in a given catalog, using a given app, redirect them to the Knackly workspace using a URL as follows:</p>\n<blockquote>\n<p><code>https://go.knackly.io/{workspace}/{catalog}/{app_name}?external={external_token}&amp;return_complete={complete_url}&amp;return_incomplete={incomplete_url}</code> </p>\n</blockquote>\n<p>Note the (optional) <code>return_complete</code> and <code>return_incomplete</code> parameters on the query string. If present, these will cause the external user to be navigated back to the indicated URL immediately when they leave the app, whether they complete it (<code>return_complete</code>) or opt to save their answers for later (<code>return_incomplete</code>). You must properly URL-encode these parameters.</p>\n<h3 id=\"revisiting-an-existing-record\">Revisiting an existing record</h3>\n<p>An external user may access an existing record ONLY if one of the following is true:</p>\n<ul>\n<li><p>the external user previously created the record (as above)</p>\n</li>\n<li><p>the record was <a href=\"#c67bc53b-efa1-4dcd-bd54-93a338f1bc29\">created via the API</a> on behalf of that specific external user</p>\n</li>\n<li><p>an internal user created a record specifically for the external user (using Knackly's <code>appLink</code> feature)</p>\n</li>\n</ul>\n<p>... AND external access to that record remains open. (External access may be closed automatically when the user completes an app, or it may be closed manually by a privileged user.)</p>\n<p>Use the following URL to navigate an external user to run the indicated app against the indicated record:</p>\n<blockquote>\n<p><code>https://go.knackly.io/{workspace}/{catalog}/{record_id}/{app_name}?external={external_token}&amp;return_complete={url_on_complete}&amp;return_incomplete={url_on_exit}</code> </p>\n</blockquote>\n<p>The user will receive an error message if you navigate them to a record they are not permitted to access.</p>\n<p>The <code>return_complete</code> and <code>return_incomplete</code> parameters operate as described above.</p>\n","_postman_id":"4d2751f7-65b9-4810-a5bf-06cca741c1a8","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}}},{"name":"Users (admin)","item":[{"name":"List users","id":"e0f74c29-00a0-4eae-ade0-e58b4b6eada5","request":{"method":"GET","header":[],"url":"{{base_url}}/{{workspace}}/api/v1/users","description":"<p>List all users in the workspace. Returns information about all users (admin, regular/internal, and external users). Requires an admin API key.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}},"urlObject":{"path":["{{workspace}}","api","v1","users"],"host":["{{base_url}}"],"query":[],"variable":[{"id":"334eabcb-f314-40f1-982b-ccfdf6f49e12","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"}]}},"response":[],"_postman_id":"e0f74c29-00a0-4eae-ade0-e58b4b6eada5"},{"name":"Get user","id":"1448c089-b07b-4626-898f-f833660072d3","request":{"method":"GET","header":[],"url":"{{base_url}}/{{workspace}}/api/v1/users/{{user_id}}","description":"<p>Get details for a specific user in the workspace. Returns information about the user including their type (admin, regular/internal, or external), email, and other metadata. Requires an admin API key.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}},"urlObject":{"path":["{{workspace}}","api","v1","users","{{user_id}}"],"host":["{{base_url}}"],"query":[],"variable":[{"id":"b5dc9427-e8e1-4515-b5b9-661848a54085","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"},{"id":"bfd85978-045d-4602-8020-f2f68222d1a3","description":{"content":"<p>(Required) The ID of the user to retrieve</p>\n","type":"text/plain"},"type":"any","value":"{{user_id}}","key":"user_id"}]}},"response":[],"_postman_id":"1448c089-b07b-4626-898f-f833660072d3"},{"name":"Create user","id":"967d9e37-69e6-4cab-8eab-82cc2e93f5a1","request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n    \"name\": \"{{user_name}}\",\n    \"email\": \"{{user_email}}\",\n    \"password\": \"{{user_password}}\",\n    \"type\": \"user\" //\"user\" \"admin\", or \"external user\"\n}","options":{"raw":{"language":"json"}}},"url":"{{base_url}}/{{workspace}}/api/v1/users/","description":"<p>Create a new user in the workspace. The request body should include <code>name</code>, <code>email</code>, <code>password</code>, and <code>type</code> (\"user\" for regular/internal user, \"admin\" for admin user, or \"external user\" for external user). Requires an admin API key.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}},"urlObject":{"path":["{{workspace}}","api","v1","users",""],"host":["{{base_url}}"],"query":[],"variable":[{"id":"ef045188-f23a-4240-ab56-25ab482ff118","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"}]}},"response":[],"_postman_id":"967d9e37-69e6-4cab-8eab-82cc2e93f5a1"},{"name":"Modify user","id":"4ea5938c-9e11-4b15-8cd3-ef489b7f7ed3","request":{"method":"PUT","header":[],"body":{"mode":"raw","raw":"{\n    \"name\": \"Lowell-O\",\n    \"email\": \"lowello@gmail.com\",\n    \"type\": \"admin\" //\"user\" \"admin\", or \"external user\"\n}","options":{"raw":{"language":"json"}}},"url":"{{base_url}}/:workspace/api/v1/users/:user_id","description":"<p>Modify an existing user in the workspace. The request body can include <code>name</code>, <code>email</code>, <code>password</code>, and <code>type</code> to update user properties. Requires an admin API key.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}},"urlObject":{"path":[":workspace","api","v1","users",":user_id"],"host":["{{base_url}}"],"query":[],"variable":[{"id":"873eed2d-e976-4f3f-bfb8-b2d9a9a7208c","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"},{"id":"049e51b0-3591-419b-9c2f-e895079a00e5","description":{"content":"<p>(Required) The ID of the user to modify</p>\n","type":"text/plain"},"type":"any","value":"6529702ff5c1ad3ed4e69e7a","key":"user_id"}]}},"response":[],"_postman_id":"4ea5938c-9e11-4b15-8cd3-ef489b7f7ed3"},{"name":"Delete user","id":"b0fde6a0-ac14-44fd-8414-08be9b86e4f1","request":{"method":"DELETE","header":[],"url":"{{base_url}}/{{workspace}}/api/v1/users/{{user_id}}","description":"<p>Delete a user from the workspace. This permanently removes the user and their access. Requires an admin API key.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}},"urlObject":{"path":["{{workspace}}","api","v1","users","{{user_id}}"],"host":["{{base_url}}"],"query":[],"variable":[{"id":"c528e696-6d2c-47d6-a421-aa154ea6bf02","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"},{"id":"aaf8aecd-2b6b-4400-a9ba-0e47035912cc","description":{"content":"<p>(Required) The ID of the user to delete</p>\n","type":"text/plain"},"type":"any","value":"{{user_id}}","key":"user_id"}]}},"response":[],"_postman_id":"b0fde6a0-ac14-44fd-8414-08be9b86e4f1"}],"id":"47c6abd7-dbe5-4871-8298-e04ce0d21958","description":"<p>Manage users in a Knackly workspace. These endpoints allow you to create, modify, and delete users of all types (admin, regular/internal, or external users). Requires an admin API key.</p>\n<p><strong>User Types:</strong></p>\n<ul>\n<li><strong>Admin users</strong> - Administrators for their organization's workspace</li>\n<li><strong>Regular/Internal users</strong> - Members of the customer's organization with access to Knackly</li>\n<li><strong>External users</strong> - Customers/clients of the Knackly customer, outside the organization, with very limited access (can only see data they entered, except when specifically granted access to a record)</li>\n</ul>\n","_postman_id":"47c6abd7-dbe5-4871-8298-e04ce0d21958","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}}},{"name":"Groups (admin)","item":[{"name":"List groups","id":"725c4bd8-df4b-4015-b011-6a8d79b5a2e5","request":{"method":"GET","header":[],"url":"{{base_url}}/:workspace/api/v1/groups","description":"<p>List all user groups in the workspace. Groups are used to organize users and assign catalog permissions. Returns information about all groups including their members and permissions. Requires an admin API key.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}},"urlObject":{"path":[":workspace","api","v1","groups"],"host":["{{base_url}}"],"query":[],"variable":[{"id":"3693554c-e76b-4d08-910b-346081f256ff","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"}]}},"response":[],"_postman_id":"725c4bd8-df4b-4015-b011-6a8d79b5a2e5"},{"name":"Get group","id":"a6c6f8f7-4326-476f-9fd7-22dbe567fb87","request":{"method":"GET","header":[],"url":"{{base_url}}/:workspace/api/v1/groups/:group_id","description":"<p>Get details for a specific user group in the workspace. Returns information about the group including its name, members, and catalog permissions. Requires an admin API key.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}},"urlObject":{"path":[":workspace","api","v1","groups",":group_id"],"host":["{{base_url}}"],"query":[],"variable":[{"id":"eda0e1d9-6792-4328-ad87-23931dd6b0bc","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"},{"id":"c8da7c7a-2f8e-400a-bcd0-2a24f685765a","description":{"content":"<p>(Required) The ID of the group to retrieve</p>\n","type":"text/plain"},"type":"any","value":"","key":"group_id"}]}},"response":[],"_postman_id":"a6c6f8f7-4326-476f-9fd7-22dbe567fb87"},{"name":"Create group","id":"a73c7fa4-38a1-4e7a-9ff0-6ab2248e4d08","request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n    \"name\": \"text\",\n    \"users\": [\n        \"ObjectId\"\n    ],\n    \"permissions\": [\n        \"Catalog NAME\"\n    ]\n}","options":{"raw":{"language":"json"}}},"url":"{{base_url}}/:workspace/api/v1/groups","description":"<p>Create a new user group in the workspace. Groups are used to organize users and assign catalog permissions. The request body should include <code>name</code>, <code>users</code> (array of user IDs), and <code>permissions</code> (array of catalog names). Requires an admin API key.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}},"urlObject":{"path":[":workspace","api","v1","groups"],"host":["{{base_url}}"],"query":[],"variable":[{"id":"1e111f63-bd4c-4e85-8710-18c35ded1b8a","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"}]}},"response":[],"_postman_id":"a73c7fa4-38a1-4e7a-9ff0-6ab2248e4d08"},{"name":"Modify group","id":"1f397db4-cf09-40f2-b8e6-8d479d423ba6","request":{"method":"PUT","header":[],"body":{"mode":"raw","raw":"{\n    \"name\": \"text\",\n    \"users\": [\n        \"ObjectId\"\n    ],\n    \"permissions\": [\n        \"Catalog NAME\"\n    ]\n}","options":{"raw":{"language":"json"}}},"url":"{{base_url}}/:workspace/api/v1/groups/:group_id","description":"<p>Modify an existing user group in the workspace. The request body can include <code>name</code>, <code>users</code> (array of user IDs), and <code>permissions</code> (array of catalog names) to update group properties. Requires an admin API key.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}},"urlObject":{"path":[":workspace","api","v1","groups",":group_id"],"host":["{{base_url}}"],"query":[],"variable":[{"id":"11033cf0-8b1f-4a4b-a628-9e3a1c7f2fe2","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"},{"id":"19d6aacc-b39c-4443-8ff2-d21b8e32d5d1","description":{"content":"<p>(Required) The ID of the group to modify</p>\n","type":"text/plain"},"type":"any","value":"","key":"group_id"}]}},"response":[],"_postman_id":"1f397db4-cf09-40f2-b8e6-8d479d423ba6"},{"name":"Delete group","id":"47fd49a7-64f9-49a2-9784-02dd026ce925","request":{"method":"DELETE","header":[],"url":"{{base_url}}/:workspace/api/v1/groups/:group_id","description":"<p>Delete a user group from the workspace. This permanently removes the group and all its permissions. Requires an admin API key.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}},"urlObject":{"path":[":workspace","api","v1","groups",":group_id"],"host":["{{base_url}}"],"query":[],"variable":[{"id":"de9c67d0-36d9-4cac-b489-a376461bcbe4","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"},{"id":"0e56acaa-e4b7-4db6-a78d-533d60cba0d8","description":{"content":"<p>(Required) The ID of the group to delete</p>\n","type":"text/plain"},"type":"any","value":"","key":"group_id"}]}},"response":[],"_postman_id":"47fd49a7-64f9-49a2-9784-02dd026ce925"},{"name":"Modify group (deprecated)","id":"7eee9b15-a66d-4082-941e-83ab2334ceb7","request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n    \"name\": \"text\",\n    \"users\": [\n        \"ObjectId\"\n    ],\n    \"permissions\": [\n        \"Catalog NAME\"\n    ]\n}","options":{"raw":{"language":"json"}}},"url":"{{base_url}}/:workspace/api/v1/groups/:group_id","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}},"urlObject":{"path":[":workspace","api","v1","groups",":group_id"],"host":["{{base_url}}"],"query":[],"variable":[{"id":"0e80f2ae-ce6a-4b08-80f3-94e86505a740","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"},{"id":"c6c2df02-610b-4020-97a2-7175260e8f57","type":"any","value":"","key":"group_id"}]}},"response":[],"_postman_id":"7eee9b15-a66d-4082-941e-83ab2334ceb7"}],"id":"6db58323-7a7c-47a4-999b-2867569bd9c5","description":"<p>Manage user groups in a Knackly workspace. Groups are used to organize users and assign permissions to catalogs. Requires an admin API key.</p>\n","_postman_id":"6db58323-7a7c-47a4-999b-2867569bd9c5","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}}},{"name":"Elements (admin)","item":[{"name":"Template Jobs (admin)","item":[{"name":"List template jobs","id":"e07b0819-db23-4284-8e91-6cfd0cd5ecb4","request":{"method":"GET","header":[],"url":"{{base_url}}/{{workspace}}/api/v1/template-jobs","description":"<p>List all template jobs in the workspace. Template jobs are used to upload or update template binaries (DOCX or PDF files) for templates in models. Returns information about all template jobs including their status. Requires an admin API key.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}},"urlObject":{"path":["{{workspace}}","api","v1","template-jobs"],"host":["{{base_url}}"],"query":[],"variable":[{"id":"61f00bec-3f4b-4239-a8d5-1e3481db599b","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"}]}},"response":[],"_postman_id":"e07b0819-db23-4284-8e91-6cfd0cd5ecb4"},{"name":"Get template job","id":"8221a103-48ad-41cf-b69f-87cbadfa9ea6","request":{"method":"GET","header":[],"url":"{{base_url}}/{{workspace}}/api/v1/template-jobs/:id","description":"<p>Get details for a specific template job in the workspace. Returns information about the template job including its status, associated model and template names, and upload progress. Requires an admin API key.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}},"urlObject":{"path":["{{workspace}}","api","v1","template-jobs",":id"],"host":["{{base_url}}"],"query":[],"variable":[{"id":"82ab58ef-3980-4b6d-b561-f2cadff35e3d","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"},{"id":"d954a37f-6441-4a05-9be4-1f9601850fb1","description":{"content":"<p>(Required) The ID of the template job to retrieve</p>\n","type":"text/plain"},"type":"any","value":"","key":"id"}]}},"response":[],"_postman_id":"8221a103-48ad-41cf-b69f-87cbadfa9ea6"},{"name":"Create template job","id":"36ed3a88-58b3-4635-8e90-6da0f592c256","request":{"method":"POST","header":[],"body":{"mode":"formdata","formdata":[{"key":"modelName","value":"","type":"text","description":"<p>(Required) Name of the model of which this template is a part</p>\n"},{"key":"templateName","value":"","type":"text","description":"<p>(Required) Name (identifier) of the template that is part of the above model</p>\n"},{"key":"binary","type":"file","description":"<p>(Required) The new or updated binary (DOCX or PDF file) to associate with this template</p>\n","src":[]}]},"url":"{{base_url}}/{{workspace}}/api/v1/template-jobs","description":"<p>Create a new template job to upload or update a template binary (DOCX or PDF file) for a template in a model. The request must be sent as multipart/form-data with <code>modelName</code>, <code>templateName</code>, and <code>binary</code> (the file). The template job will be processed asynchronously. Requires an admin API key.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}},"urlObject":{"path":["{{workspace}}","api","v1","template-jobs"],"host":["{{base_url}}"],"query":[],"variable":[{"id":"c7b4661a-b7b5-4a21-9b8d-365b40c9b530","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"}]}},"response":[],"_postman_id":"36ed3a88-58b3-4635-8e90-6da0f592c256"}],"id":"3f7bc5f0-a768-4e42-8230-5bd088f53692","description":"<p>Template Jobs are how you upload binary templates (DOCX or PDF files) that are associated with a compatible template definition inside a Knackly model. The workflow for creating a new template is:</p>\n<ol>\n<li><p>All templates in Knackly are part of a specific Model. So first, make sure you know which model the template should be part of, and make sure that model exists (or add it if it does not yet exist). You need the <strong>model name</strong>.</p>\n</li>\n<li><p>Before a template binary can be uploaded, a definition for the template must be added to the model. You will need the <strong>template name</strong>.</p>\n</li>\n<li><p>Once you have these two names, use <strong>Create template job</strong> to post the binary itself, which will initiate the upload and validation processes within Knackly.</p>\n</li>\n</ol>\n","_postman_id":"3f7bc5f0-a768-4e42-8230-5bd088f53692","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}}},{"name":"List elements","id":"2e2f9c6b-8bfd-456f-9a1d-7fdcd5633848","request":{"method":"GET","header":[],"url":"{{base_url}}/{{workspace}}/api/v1/types","description":"<p>List all elements (Models, Tables, and Queries) in the workspace. Returns information about all elements including their names, types, and metadata. <strong>Warning:</strong> Modifying elements can render the system non-functional. Requires an admin API key.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}},"urlObject":{"path":["{{workspace}}","api","v1","types"],"host":["{{base_url}}"],"query":[],"variable":[{"id":"6e0ed01b-fc99-4997-b177-d92b23b7fe7d","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"}]}},"response":[],"_postman_id":"2e2f9c6b-8bfd-456f-9a1d-7fdcd5633848"},{"name":"Get element","id":"649e82b8-5f6e-4c8a-bcc7-cb673b00b9f9","request":{"method":"GET","header":[],"url":"{{base_url}}/{{workspace}}/api/v1/types/{{element_id}}","description":"<p>Get details for a specific element (Model, Table, or Query) in the workspace. Returns the full element definition including variables, formulas, templates, and other metadata. <strong>Warning:</strong> Modifying elements can render the system non-functional. Requires an admin API key.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}},"urlObject":{"path":["{{workspace}}","api","v1","types","{{element_id}}"],"host":["{{base_url}}"],"query":[],"variable":[{"id":"17f1ca02-e235-4aff-868b-632b5fd06c9c","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"},{"id":"6aea4376-dfdb-4a6f-b4fc-905c43c77a1c","description":{"content":"<p>(Required) The ID or name of the element to retrieve</p>\n","type":"text/plain"},"type":"any","value":"{{element_id}}","key":"element_id"}]}},"response":[],"_postman_id":"649e82b8-5f6e-4c8a-bcc7-cb673b00b9f9"},{"name":"Create and modify element(s)","id":"2f1358a7-5d8d-47cc-b6b2-e1eb3150516e","request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"    {\r\n        \"kind\": \"model\",\r\n        \"name\": \"apitest\",\r\n        \"summaryTemplate\": \"\",\r\n        \"variables\": [\r\n            {\r\n                \"name\": \"name\",\r\n                \"type\": \"text\",\r\n                \"isList\": false,\r\n                \"style\": \"textbox\",\r\n                \"pattern\": \"\",\r\n                \"height\": 1,\r\n                \"allowBreaks\": false,\r\n                \"processMarkdown\": false,\r\n                \"label\": \"updated label\",\r\n                \"helpText\": \"\",\r\n                \"forceRelevance\": \"\"\r\n            }\r\n        ],\r\n        \"templates\": [\r\n        ],\r\n        \"formulas\": [],\r\n        \"apps\": [],\r\n        \"layouts\": [],\r\n        \"__v\": 0\r\n    }","options":{"raw":{"language":"json"}}},"url":"{{base_url}}/{{workspace}}/api/v1/types?op=update&ns=test","description":"<p>Create new elements (Models, Tables, or Queries) or modify existing ones in the workspace. The request body should contain the full element definition as JSON. Use the <code>op</code> query parameter to control whether to add, replace, or update elements.</p>\n<ul>\n<li><p>\"add\" operation -- used when your intent is only to add new elements that do not exist. If you specify \"add\" and something you post already exists, you will receive an error response.</p>\n</li>\n<li><p>\"replace\" operation -- used when your intent is to replace any elements you post with new versions.</p>\n</li>\n<li><p>\"update\" operation -- used to <em>merge</em> the element(s) you post with the elements already defined in the system. You can use this, for example, to add a new template or variable to a model, without disrupting other templates and models that exist.</p>\n</li>\n</ul>\n<p>A note about <strong>namespaces</strong>: endpoints that work with elements typically allow specifying a namespace (the <strong>ns</strong> parameter). Namespaces allow partners and integrators who define their own schemas (models) to specify a namespace, to help prevent name collisions and facilitate safer type sharing across organizations. Additional documentation is forthcoming. Namespaces must be assigned by Knackly; please do not specify a namespace unless you have been specifically instructed by Knackly support to do so.</p>\n<p><strong>Warning:</strong> Modifying elements can render the system non-functional. Test carefully before deploying to production. Requires an admin API key.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}},"urlObject":{"path":["{{workspace}}","api","v1","types"],"host":["{{base_url}}"],"query":[{"description":{"content":"<p>(Optional) Either \"add\" (the default), \"replace\" or \"update\". Add will add whatever element or elements you post, and will throw an error if an element by any of those names already exists. \"replace\" will replace the named model(s) in their entirety if they already exist, or add them if not. \"update\" will update existing models, allowing limited customizations (made via the Designer UI) to survive the update IF the \"ns\" parameter is also specified.</p>\n","type":"text/plain"},"key":"op","value":"update"},{"description":{"content":"<p>(Optional) A prefix for the pushed models; use this if you intend to update the models over time while potentially allowing for limited customization via the Designer UI</p>\n","type":"text/plain"},"key":"ns","value":"test"}],"variable":[{"id":"c8edd7f3-ba85-4d9c-a637-e15904845b37","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"}]}},"response":[],"_postman_id":"2f1358a7-5d8d-47cc-b6b2-e1eb3150516e"},{"name":"Delete element","id":"58bcab44-7a77-44e6-96fc-4ab7f618ce58","request":{"method":"DELETE","header":[],"url":"{{base_url}}/{{workspace}}/api/v1/types/{{element_id}}","description":"<p>Delete an element (Model, Table, or Query) from the workspace. This permanently removes the element and may break any catalogs, apps, or other elements that depend on it. <strong>Warning:</strong> Deleting elements can render the system non-functional. Test carefully before deploying to production. Requires an admin API key.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}},"urlObject":{"path":["{{workspace}}","api","v1","types","{{element_id}}"],"host":["{{base_url}}"],"query":[],"variable":[{"id":"f9a9da47-7d75-4b6c-9471-23b3cc46884d","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"},{"id":"4c3693ff-7534-4c74-9cd5-bd43e9b6e1b6","description":{"content":"<p>(Required) The ID or name of the element to delete</p>\n","type":"text/plain"},"type":"any","value":"{{element_id}}","key":"element_id"}]}},"response":[],"_postman_id":"58bcab44-7a77-44e6-96fc-4ab7f618ce58"},{"name":"Delete namespaced elements","id":"4d991f53-8f57-4535-bea1-ff6b78c6f2ba","request":{"method":"DELETE","header":[],"url":"{{base_url}}/{{workspace}}/api/v1/types/all?ns=test","description":"<p>Delete all elements (Models, Tables, or Queries) in the workspace that have the specified namespace prefix. This permanently removes all matching elements and may break any catalogs, apps, or other elements that depend on them. <strong>Warning:</strong> Deleting elements can render the system non-functional. Test carefully before deploying to production. Requires an admin API key.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}},"urlObject":{"path":["{{workspace}}","api","v1","types","all"],"host":["{{base_url}}"],"query":[{"description":{"content":"<p>(Required) The namespace prefix of elements to delete</p>\n","type":"text/plain"},"key":"ns","value":"test"}],"variable":[{"id":"61c5accf-7111-404d-9dd5-43628bc92477","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"}]}},"response":[],"_postman_id":"4d991f53-8f57-4535-bea1-ff6b78c6f2ba"}],"id":"3aeb3200-910c-47d2-a3e3-98038bc90bbd","description":"<p>An Element is a building-block of a Knackly document automation system. Elements are typically defined in the Designer within the Knackly UI. However, they can be listed and manipulated to some extent using an administrative API key. There are three kinds of elements in Knackly:</p>\n<ul>\n<li><p>Models</p>\n</li>\n<li><p>Tables</p>\n</li>\n<li><p>Queries</p>\n</li>\n</ul>\n<p>A <strong>Model</strong> is Knackly's term for a schema. Each catalog is based on a Model. Different catalogs may be based on different models, or multiple catalogs may be based on the same model. A model defines Variables (which define the \"shape\" of each instance of that model), Formulas (which can compute, transform, and draw inferences from those variables), and Templates (which define the documents that can be produced from the model).</p>\n<p>Models are object-based. Variables can be scalars (single-instance) or arrays (\"lists\"); scalar data types include <em>text</em>, <em>number</em>, <em>date</em>, <em>true/false</em>, and <em>object</em>. (Object-type variables also define which Model the object data must adhere to.) There are also <em>selection</em> variables, where the answer is basically a foreign key (usually a text string) referring to some other object within a list of objects (which itself is stored in either a Table, an external Query, or elsewhere within the same record's list variables or formulas).</p>\n<p><strong>Tables</strong> are basically static (infrequently-changing) tables of information that can be used for various purposes in Knacly systems: most frequently to provide a list of values (rows) to choose from in a selection variable (as well as other text values related to each value -- additional columns). Common examples are States or Genders.</p>\n<p><strong>Queries</strong> (if available in your plan) are like external tables -- they allow data to be fetched from somewhere outside of the current record. Queries can target other Knackly catalogs in the same workspace, or external systems for which integrations exist, such as Clio. Queries are an advanced feature of Knackly.</p>\n<p>The endpoints documented below allow callers with an appropriate administrative API key to view and modify the fundamental elements of a Knackly document automation system. Warning: adding, removing, or modifying the elements in a Knackly workspace has the potential to render that system non-functional. You should know exactly what you're doing, and test carefully, before deploying code that uses these APIs to modify or update a working system in production environments!</p>\n","_postman_id":"3aeb3200-910c-47d2-a3e3-98038bc90bbd","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}}},{"name":"API keys (admin)","item":[{"name":"List API keys","id":"b6aae60f-f9d3-4c81-9d63-02e86ac9f9ea","request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":"{{token}}"}]},"isInherited":false},"method":"GET","header":[],"url":"{{base_url}}/:workspace/api/v1/api_keys","description":"<p>List all API keys in the workspace. Returns information about all API keys (both regular and admin) including their labels, permissions, and creation dates. Note that the secret is never returned for security reasons. Requires an admin API key.</p>\n","urlObject":{"path":[":workspace","api","v1","api_keys"],"host":["{{base_url}}"],"query":[],"variable":[{"id":"5902a080-cf3a-4a5f-9735-a66425f782f3","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"}]}},"response":[],"_postman_id":"b6aae60f-f9d3-4c81-9d63-02e86ac9f9ea"},{"name":"Get API key","id":"d369b5cd-2931-4888-84c9-b173e78115a9","request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":"{{token}}"}]},"isInherited":false},"method":"GET","header":[],"url":"{{base_url}}/:workspace/api/v1/api_keys/:key_id","description":"<p>Get details for a specific API key in the workspace. Returns information about the API key including its label, type (regular or admin), permissions, and creation date. Note that the secret is never returned for security reasons. Requires an admin API key.</p>\n","urlObject":{"path":[":workspace","api","v1","api_keys",":key_id"],"host":["{{base_url}}"],"query":[],"variable":[{"id":"818f90f0-d0d4-40a1-98b8-4bea43c20a86","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"},{"id":"2e946752-69f4-47c1-80a0-af9f75faa2a9","description":{"content":"<p>(Required) The ID of the API key to retrieve</p>\n","type":"text/plain"},"type":"any","value":"","key":"key_id"}]}},"response":[],"_postman_id":"d369b5cd-2931-4888-84c9-b173e78115a9"},{"name":"Create API key","id":"9e0771d1-ccb5-4408-8ce4-e1d83b0a5d02","request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":"{{token}}"}]},"isInherited":false},"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n    \"label\": \"{{key_label}}\",\n    \"hasAdminAccess\": true, // Allow this API key to create/modify/delete elements and catalogs\n    \"permissions\": [] // Array of Catalog Ids, like this [ \"664b3d960e702fd5213aad12\" ]\n}","options":{"raw":{"language":"json"}}},"url":"{{base_url}}/:workspace/api/v1/api_keys","description":"<p>Create a new API key in the workspace. The request body should include <code>label</code> (a human-readable name for the key), <code>hasAdminAccess</code> (true for admin API key, false or omitted for regular API key), and <code>permissions</code> (array of catalog IDs for regular API keys - empty array for admin API keys). The response includes the API key ID and secret - store the secret securely as it cannot be retrieved later. Requires an admin API key.</p>\n","urlObject":{"path":[":workspace","api","v1","api_keys"],"host":["{{base_url}}"],"query":[],"variable":[{"id":"8a0be1bf-93d2-41b5-b915-81504cca829b","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"}]}},"response":[],"_postman_id":"9e0771d1-ccb5-4408-8ce4-e1d83b0a5d02"},{"name":"Modify API key","id":"b583e668-c663-4878-8e45-04cde2cc0016","request":{"method":"PUT","header":[],"body":{"mode":"raw","raw":"{\n    \"label\": \"{{key_label}}\",\n    \"hasAdminAccess\": true, // Allow this API key to create/modify/delete elements and catalogs\n    \"permissions\": [] // Array of Catalog Ids, like this [ \"664b3d960e702fd5213aad12\" ]\n}\n","options":{"raw":{"language":"json"}}},"url":"{{base_url}}/:workspace/api/v1/api_keys/:key_id","description":"<p>Modify an existing API key in the workspace. The request body can include <code>label</code>, <code>hasAdminAccess</code>, and <code>permissions</code> to update the API key properties. Note that you cannot change the API key secret - if you need a new secret, delete and recreate the API key. Requires an admin API key.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}},"urlObject":{"path":[":workspace","api","v1","api_keys",":key_id"],"host":["{{base_url}}"],"query":[],"variable":[{"id":"5ecbc621-7ce9-43ec-8589-ea2f4716926d","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"},{"id":"bbc1951a-2bfb-4bf6-8f7f-6ed34c0d30b2","description":{"content":"<p>(Required) The ID of the API key to modify</p>\n","type":"text/plain"},"type":"any","value":"","key":"key_id"}]}},"response":[],"_postman_id":"b583e668-c663-4878-8e45-04cde2cc0016"},{"name":"Delete API key","id":"40a33e32-61d0-4f10-827b-c487d919c36d","request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":"{{token}}"}]},"isInherited":false},"method":"DELETE","header":[],"url":"{{base_url}}/:workspace/api/v1/api_keys/:key_id","description":"<p>Delete an API key from the workspace. This permanently removes the API key and revokes all access. Any applications using this API key will immediately lose access. Requires an admin API key.</p>\n","urlObject":{"path":[":workspace","api","v1","api_keys",":key_id"],"host":["{{base_url}}"],"query":[],"variable":[{"id":"d0bcf9dc-5f20-4ade-bc9f-99c3219d9c7c","description":{"content":"<p>(Required) The name of a Knackly workspace</p>\n","type":"text/plain"},"type":"any","value":"{{workspace}}","key":"workspace"},{"id":"b0108dfd-b7cf-4303-ae99-4eb5810d4faf","description":{"content":"<p>(Required) The ID of the API key to delete</p>\n","type":"text/plain"},"type":"any","value":"","key":"key_id"}]}},"response":[],"_postman_id":"40a33e32-61d0-4f10-827b-c487d919c36d"}],"id":"06d0759f-97aa-4841-8821-6058e1c05402","description":"<p>Manage API keys in a Knackly workspace. These endpoints allow you to create, modify, and delete both regular and admin API keys. Requires an admin API key.</p>\n<p><strong>API Key Types:</strong></p>\n<ul>\n<li><strong>Regular API keys</strong> - Allow operations analogous to regular/internal users (read/write records, generate documents)</li>\n<li><strong>Admin API keys</strong> - Allow all regular operations plus administrative operations (manage catalogs, elements, users, groups, etc.)</li>\n</ul>\n<p>When creating an API key, set <code>hasAdminAccess: true</code> to create an admin API key, or omit it (or set to <code>false</code>) to create a regular API key. Regular API keys are granted access to specific catalogs via the <code>permissions</code> array (list of catalog IDs).</p>\n","_postman_id":"06d0759f-97aa-4841-8821-6058e1c05402","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]},"isInherited":true,"source":{"_postman_id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","id":"080248a6-e94a-46e0-bbb6-5dbd8d0ec4c6","name":"Knackly API (v1)","type":"collection"}}}],"auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"Authorization"},{"key":"value","value":"{{token}}"}]}},"variable":[{"key":"base_url","type":"string"},{"key":"workspace","type":"string"},{"key":"key_id","type":"string"},{"key":"secret","type":"string"},{"key":"token","type":"string"},{"key":"catalog_name","type":"string"},{"key":"app_name","type":"string"},{"key":"record_id","type":"string"},{"key":"external_token","type":"string"},{"key":"refresh_token","type":"string"}]}