From 71a97c99fe1bd445cc8cb5d82f3a67f914651062 Mon Sep 17 00:00:00 2001 From: boxmoji Date: Wed, 7 Feb 2024 12:36:07 -0800 Subject: [PATCH] Moji: Update translations --- guides/box-sign/create-sign-request.md | 2 +- .../powershell-script-templates.md | 2 +- guides/embed/ui-elements/explorer.md | 287 ++++++-- guides/embed/ui-elements/index.md | 2 +- guides/embed/ui-elements/open-with.md | 2 +- pages/index.md | 20 +- pages/sign/index.md | 71 ++ pages/sign/quick-start/api-basics.md | 57 ++ pages/sign/quick-start/index.md | 30 + pages/sign/quick-start/your-first-request.md | 221 ++++++ pages/sign/request-options/custom-email.md | 272 ++++++++ pages/sign/request-options/custom-urls.md | 108 +++ pages/sign/request-options/extra-security.md | 229 ++++++ pages/sign/request-options/in-person.md | 358 ++++++++++ pages/sign/request-options/index.md | 20 + .../sign/request-options/multiple-signers.md | 317 +++++++++ .../request-options/request-expiration.md | 87 +++ pages/sign/request-options/resend-requests.md | 149 ++++ pages/sign/technical-use-cases/index.md | 40 ++ .../sign-structured-docs.md | 566 +++++++++++++++ .../sign/technical-use-cases/sign-template.md | 653 ++++++++++++++++++ .../sign-unstructured-docs.md | 194 ++++++ pages/sign/webhooks/index.md | 39 ++ 23 files changed, 3672 insertions(+), 54 deletions(-) create mode 100644 pages/sign/index.md create mode 100644 pages/sign/quick-start/api-basics.md create mode 100644 pages/sign/quick-start/index.md create mode 100644 pages/sign/quick-start/your-first-request.md create mode 100644 pages/sign/request-options/custom-email.md create mode 100644 pages/sign/request-options/custom-urls.md create mode 100644 pages/sign/request-options/extra-security.md create mode 100644 pages/sign/request-options/in-person.md create mode 100644 pages/sign/request-options/index.md create mode 100644 pages/sign/request-options/multiple-signers.md create mode 100644 pages/sign/request-options/request-expiration.md create mode 100644 pages/sign/request-options/resend-requests.md create mode 100644 pages/sign/technical-use-cases/index.md create mode 100644 pages/sign/technical-use-cases/sign-structured-docs.md create mode 100644 pages/sign/technical-use-cases/sign-template.md create mode 100644 pages/sign/technical-use-cases/sign-unstructured-docs.md create mode 100644 pages/sign/webhooks/index.md diff --git a/guides/box-sign/create-sign-request.md b/guides/box-sign/create-sign-request.md index f9e4f3a95..232460fc0 100644 --- a/guides/box-sign/create-sign-request.md +++ b/guides/box-sign/create-sign-request.md @@ -65,7 +65,7 @@ Box Signの各リクエストは、署名が必要なファイルから始まり * 画像: `png`、`jpg`、`jpeg`、`tiff`のみ * テキストベースのファイル: `.csv`、`.txt`のみ -すべてのファイルタイプは、署名の処理のために`.pdf`に変換されます。この変換後のドキュメントは、リクエストの送信が成功した場合は、`parent_folder`に見つかります。つまり、元のファイルタイプに関係なく、最終的な署名済みドキュメントは`.pdf`になります。各署名者がリクエストを完了すると、Box Signにより新しいファイルバージョンが自動的に追加されます。 +すべてのファイルタイプは、署名の処理のために`.pdf`に変換されます。この変換後のドキュメントは、リクエストの送信が成功した場合に`parent_folder`で見つかります。つまり、元のファイルタイプに関係なく、最終的な署名済みドキュメントは`.pdf`になります。各署名者がリクエストを完了すると、Box Signにより新しいファイルバージョンが自動的に追加されます。 ファイルサイズの上限は、アカウントの種類によって決まります。詳細については、[アップロードガイド][uploads]を参照してください。 diff --git a/guides/cli/quick-start/powershell-script-templates.md b/guides/cli/quick-start/powershell-script-templates.md index db9f9cde4..2c93a4fc8 100644 --- a/guides/cli/quick-start/powershell-script-templates.md +++ b/guides/cli/quick-start/powershell-script-templates.md @@ -131,7 +131,7 @@ Isaac,Newton,abc@abc.local,INewton23 #### JSONファイルを使用する -`Folder_Structure.json`ファイルは、作成するフォルダ構造を含んでいます。たとえば、`Market Research`フォルダと`Sales Plays`フォルダを作成し、それぞれにサブフォルダ`Statistics`と`Big Pharma`を作成するとします。このスクリプトは、このフォルダ構造を、指定した親フォルダ内の当該ユーザーの`Personal Folder`フォルダの下に配置します。 +`Folder_Structure.json`ファイルは、作成するフォルダ構造を含んでいます。たとえば、`Market Research`フォルダと`Sales Plays`フォルダを作成し、それぞれにサブフォルダ`Statistics`と`Big Pharma`を作成するとします。このスクリプトは、このフォルダ構造を、指定した親フォルダ内にある当該ユーザーの`Personal Folder`フォルダの下に配置します。 `FolderStructureJSONPath`パラメータを使用して、`Folder_Structure.json`ファイルの場所を指定します。 diff --git a/guides/embed/ui-elements/explorer.md b/guides/embed/ui-elements/explorer.md index ec123a7c8..eb9d0c657 100644 --- a/guides/embed/ui-elements/explorer.md +++ b/guides/embed/ui-elements/explorer.md @@ -27,6 +27,8 @@ fullyTranslated: true Box Content Explorer UI Elementを使用すると、開発者は、Boxに保存されているコンテンツのフォルダビューをデスクトップまたはモバイルウェブアプリに埋め込むことができます。ライブラリはBox APIを介して指定されたフォルダに関する情報を取得した後、メインのBoxウェブアプリと同様にそのコンテンツをフォルダビューにレンダリングします。ユーザーは、そのフォルダ階層内を移動し、名前の変更、削除、共有などのファイル操作を実行できます。 +Content Explorer comes with a metadata view that uses metadata query to find files and folders based on their metadata. The data is then displayed in the embedded view. + ## インストール NPMまたはBox CDN経由でBox UI Elementsをインストールする方法は、[こちら](g://embed/ui-elements/installation)を参照してください。 @@ -48,29 +50,28 @@ UI Elementは認証に依存しない方法で設計されているため、Box ```html - - - Box Content Explorer Demo - - - - - -
- - - - + + + Box Content Explorer Demo + + + + + +
+ + + + ``` @@ -157,29 +158,33 @@ contentExplorer.removeAllListeners(); ### オプション -| パラメータ | 型 | デフォルト | 説明 | -| ---------------------- | -------- | --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `container` | String | `document.body` | コンテンツエクスプローラが配置されるコンテナのCSSセレクタ。hide() を呼び出すと、このコンテナは空になります。 | -| `sortBy` | String | `name` | コンテンツリストの最初の並べ替え基準オプション。値は`id`、`name`、`date`または`size`になります。 | -| `sortDirection` | String | `ASC` | コンテンツリストの最初の並べ替え方向オプション。値は`ASC`または`DESC`になります。 | -| `logoUrl` | String | | ヘッダーに表示するカスタムロゴのURL。この値が「box」という文字列の場合は、Boxのロゴが表示されます。 | -| `canPreview` | Boolean | `true` | このオプションが`true`に設定されていて、ファイルに対する`can_preview`権限が`true`の場合、コンテンツエクスプローラでファイルをクリックできます。ファイルをクリックするとそのファイルのプレビューが開始されます。ファイルに対する権限`can_preview`が`false`に設定されている場合、このオプションによる効果はありません。このオプションは、プレビュー可能なファイルのみに適用できます。 | -| `canDownload` | Boolean | `true` | これを`false`に設定すると、ダウンロードオプションが非表示になります。このオプションを非表示にするだけではダウンロードを防ぐことはできず、ファイルに対する権限でも`can_download`を`false`に設定する必要があります。ファイルに対する権限`can_download`が`false`に設定されている場合、このオプションによる効果はありません。このオプションは、ファイルのみに適用できます。 | -| `canDelete` | Boolean | `true` | これを`false`に設定すると、削除オプションが非表示になります。このオプションを非表示にするだけでは削除を防ぐことはできず、項目に対する権限でも`can_delete`を`false`に設定する必要があります。項目に対する権限`can_delete`が`false`に設定されている場合、このオプションによる効果はありません。 | -| `canRename` | Boolean | `true` | これを`false`に設定すると、名前の変更オプションが非表示になります。このオプションを非表示にするだけでは名前の変更を防ぐことはできず、項目に対する権限でも`can_rename`を`false`に設定する必要があります。 | -| `canUpload` | Boolean | `true` | これを`false`に設定すると、アップロードオプションが非表示になります。このオプションを非表示にするだけではアップロードを防ぐことはできず、現在のフォルダに対する権限でも`can_upload`を`false`に設定する必要があります。フォルダに対する権限`can_upload`が`false`に設定されている場合、このオプションによる効果はありません。 | -| `canCreateNewFolder` | Boolean | `true` | フォルダの新規作成オプションが非表示になります。このオプションを非表示にするだけではフォルダの新規作成を防ぐことはできず、フォルダ項目に対する権限でも`can_upload`を`false`に設定する必要があります。フォルダ項目に対する権限`can_upload`が`false`に設定されている場合、このオプションによる効果はありません。 | -| `canShare` | Boolean | `true` | `false`に設定すると、共有ボタンが非表示になります。このボタンを非表示にするだけでは共有を防ぐことはできず、項目の`permissions`でも`can_share`をfalseに設定する必要があります。項目に対する権限`can_share`が`false`に設定されている場合、このオプションによる効果はありません。 | -| `canSetShareAccess` | Boolean | `true` | `false`に設定すると、共有権限の変更を許可する共有ドロップダウン選択が非表示になります。この選択のドロップダウンを非表示にするだけでは共有権限の変更を防ぐことはできず、項目に対する権限でも`can_set_share_access`を`false`に設定する必要があります。項目に対する権限`can_set_share_access`が`false`に設定されている場合、このオプションによる効果はありません。 | -| `sharedLink` | String | | 共有リンクのURL。フォルダが共有されており、アクセストークンがファイルの所有者またはコラボレータに属していない場合は必須です。 | -| `sharedLinkPassword` | String | | 共有リンクのパスワード。共有リンクにパスワードが設定されている場合は必須です。 | -| `size` | String | `undefined` | コンテンツエクスプローラがコンテナの幅の大小に合わせて表示されるように示します。値には空白か、`small`または`large`を指定できます。空白にした場合、UI Elementはそのコンテナに合わせて調整され、自動で`small`の幅と`large`の幅が切り替わります。 | -| `isTouch` | Boolean | デフォルトでは、ブラウザとデバイスのデフォルトのタッチサポートが設定されます。 | コンテンツエクスプローラがタッチ対応デバイスにレンダリングされることを示します。 | -| `autoFocus` | Boolean | `false` | `true`に設定すると、初回読み込み時に項目グリッドに焦点が当てられます。 | -| `defaultView` | String | `files` | 値は`files`または`recents`になります。`recents`に設定すると、デフォルトで、通常のファイル/フォルダ構造ではなく最近使用した項目が表示されます。 | -| `requestInterceptor` | Function | | リクエストをインターセプトする関数。例については、[このCodePen](https://codepen.io/box-platform/pen/jLdxEv)を参照してください。基盤となるXHRライブラリは`axios.js`で、[インターセプタでは同様のアプローチ](https://github.com/axios/axios#interceptors)に従っています。 | -| `responseInterceptor` | Function | | レスポンスをインターセプトする関数。例については、[このCodePen](https://codepen.io/box-platform/pen/jLdxEv)を参照してください。基盤となるXHRライブラリは`axios.js`で、[インターセプタでは同様のアプローチ](https://github.com/axios/axios#interceptors)に従っています。 | -| `ContentOpenWithProps` | Object | `{ show: false }` | エクスプローラからプレビューする際にOpen With Elementを表示できます。 | +| パラメータ | 型 | デフォルト | 説明 | +| ---------------------- | -------- | --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `container` | String | `document.body` | コンテンツエクスプローラが配置されるコンテナのCSSセレクタ。hide() を呼び出すと、このコンテナは空になります。 | +| `sortBy` | String | `name` | コンテンツリストの最初の並べ替え基準オプション。値は`id`、`name`、`date`または`size`になります。 | +| `sortDirection` | String | `ASC` | コンテンツリストの最初の並べ替え方向オプション。値は`ASC`または`DESC`になります。 | +| `logoUrl` | String | | ヘッダーに表示するカスタムロゴのURL。この値が「box」という文字列の場合は、Boxのロゴが表示されます。 | +| `canPreview` | Boolean | `true` | このオプションが`true`に設定されていて、ファイルに対する`can_preview`権限が`true`の場合、コンテンツエクスプローラでファイルをクリックできます。ファイルをクリックするとそのファイルのプレビューが開始されます。ファイルに対する権限`can_preview`が`false`に設定されている場合、このオプションによる効果はありません。このオプションは、プレビュー可能なファイルのみに適用できます。 | +| `canDownload` | Boolean | `true` | これを`false`に設定すると、ダウンロードオプションが非表示になります。このオプションを非表示にするだけではダウンロードを防ぐことはできず、ファイルに対する権限でも`can_download`を`false`に設定する必要があります。ファイルに対する権限`can_download`が`false`に設定されている場合、このオプションによる効果はありません。このオプションは、ファイルのみに適用できます。 | +| `canDelete` | Boolean | `true` | これを`false`に設定すると、削除オプションが非表示になります。このオプションを非表示にするだけでは削除を防ぐことはできず、項目に対する権限でも`can_delete`を`false`に設定する必要があります。項目に対する権限`can_delete`が`false`に設定されている場合、このオプションによる効果はありません。 | +| `canRename` | Boolean | `true` | これを`false`に設定すると、名前の変更オプションが非表示になります。このオプションを非表示にするだけでは名前の変更を防ぐことはできず、項目に対する権限でも`can_rename`を`false`に設定する必要があります。 | +| `canUpload` | Boolean | `true` | これを`false`に設定すると、アップロードオプションが非表示になります。このオプションを非表示にするだけではアップロードを防ぐことはできず、現在のフォルダに対する権限でも`can_upload`を`false`に設定する必要があります。フォルダに対する権限`can_upload`が`false`に設定されている場合、このオプションによる効果はありません。 | +| `canCreateNewFolder` | Boolean | `true` | フォルダの新規作成オプションが非表示になります。このオプションを非表示にするだけではフォルダの新規作成を防ぐことはできず、フォルダ項目に対する権限でも`can_upload`を`false`に設定する必要があります。フォルダ項目に対する権限`can_upload`が`false`に設定されている場合、このオプションによる効果はありません。 | +| `canShare` | Boolean | `true` | `false`に設定すると、共有ボタンが非表示になります。このボタンを非表示にするだけでは共有を防ぐことはできず、項目の`permissions`でも`can_share`をfalseに設定する必要があります。項目に対する権限`can_share`が`false`に設定されている場合、このオプションによる効果はありません。 | +| `canSetShareAccess` | Boolean | `true` | `false`に設定すると、共有権限の変更を許可する共有ドロップダウン選択が非表示になります。この選択のドロップダウンを非表示にするだけでは共有権限の変更を防ぐことはできず、項目に対する権限でも`can_set_share_access`を`false`に設定する必要があります。項目に対する権限`can_set_share_access`が`false`に設定されている場合、このオプションによる効果はありません。 | +| `sharedLink` | String | | 共有リンクのURL。フォルダが共有されており、アクセストークンがファイルの所有者またはコラボレータに属していない場合は必須です。 | +| `sharedLinkPassword` | String | | 共有リンクのパスワード。共有リンクにパスワードが設定されている場合は必須です。 | +| `size` | String | `undefined` | コンテンツエクスプローラがコンテナの幅の大小に合わせて表示されるように示します。値には空白か、`small`または`large`を指定できます。空白にした場合、UI Elementはそのコンテナに合わせて調整され、自動で`small`の幅と`large`の幅が切り替わります。 | +| `isTouch` | Boolean | デフォルトでは、ブラウザとデバイスのデフォルトのタッチサポートが設定されます。 | Indicates to the Content Explorer that it's is being rendered on a touch enabled device. | +| `autoFocus` | Boolean | `false` | `true`に設定すると、初回読み込み時に項目グリッドに焦点が当てられます。 | +| `defaultView` | String | `files` | Value can be either be `files`, `recents` or `metadata`. When set to `recents`, by default you will see recent items instead of the regular file/folder structure. `metadata` is required to display the metadata view in Content Explorer. If not provided, you'll get a regular folder view. | +| `requestInterceptor` | Function | | リクエストをインターセプトする関数。例については、[このCodePen](https://codepen.io/box-platform/pen/jLdxEv)を参照してください。基盤となるXHRライブラリは`axios.js`で、[インターセプタでは同様のアプローチ](https://github.com/axios/axios#interceptors)に従っています。 | +| `responseInterceptor` | Function | | レスポンスをインターセプトする関数。例については、[このCodePen](https://codepen.io/box-platform/pen/jLdxEv)を参照してください。基盤となるXHRライブラリは`axios.js`で、[インターセプタでは同様のアプローチ](https://github.com/axios/axios#interceptors)に従っています。 | +| `ContentOpenWithProps` | Object | `{ show: false }` | エクスプローラからプレビューする際にOpen With Elementを表示できます。 | +| `token` | String | | Developer token generated in the Developer Console. | +| `metadataQuery` | Object | | Metadata query used to get the information for the metadata view. | +| `rootFolderID` | String | | Folder ID with a metadata template applied. `metadataQuery` will apply to this folder. | +| `fieldsToShow` | Object | | The metadata fields/columns to view - must be valid field names from the metadata template. | ### イベント @@ -252,8 +257,198 @@ contentExplorer.removeAllListeners(); | ユーザーが基本機能、プレビュー、ダウンロード、およびファイル/フォルダ名の変更を必要とする | `base_explorer` + `item_preview` + `item_download` + `item_rename` | | ユーザーがすべての機能 (基本、プレビュー、ダウンロード、名前の変更、共有、アップロード、および削除) を必要とする | `base_explorer` + `item_preview` + `item_download` + `item_rename` + `item_delete` + `item_share` + `item_upload` | +## Metadata view + +With Content Explorer you can also display files and folders based on their metadata. This view is called the metadata view and uses metadata template and metadata query to find the data you want to display. + +### 前提条件 + +Make sure you have the following installed: + +* Node version: `>=18.18.2 <20.11.0` +* React version `>=17.0.2 <18.0.0` +* BUIE version `19.0.0` + +### Create and configure an app + +1. [Create a Box app][box-app]. +2. Add the local development address in the CORS Domains: + ![CORSドメイン](./images/box-app-cors.png) +3. Generate a [developer token][token]. + +### メタデータテンプレートの作成 + +The next step is to create a metadata template you will use to populate the Content Explorer. + +1. Create a metadata template. You can use [Metadata API][creating-templates-api] or [Admin Console][creating-templates-ui] to do so. +2. Apply an already created template to a Box folder. Make sure you enable the cascade policy. For detailed instructions, see [instructions on customizing and applying templates][apply-templates]. + +### Display metadata view + +To make things easier, you can use a [sample project][metadata-project] to launch metadata view. + +1. Clone the metadata sample project. +2. Update the placeholders in [`App.js`][appjs] with actual values: + +| パラメータ | 説明 | +| ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `DEVELOPER_TOKEN` | [Developer token][token] generated in the the Developer Console. | +| `ENTERPRISE_ID` | Enterprise ID copied from the **General Settings** tab of your application. | +| `METADATA_TEMPLATE_NAME` | Name of your already created metadata template. **Note**: To make sure you provided the proper name, use the [metadata API][get-template] to retrieve the name, or copy it from the URL in the Admin Console. ![Metadata name in Admin Console](./images/metadata-template-name.png) If you decide to change the template name in the UI, you change the label only. The name to use in the component is always the you provided at the beginning. | +| `ROOTFOLDER_ID` | ID of Box folder to which you applied the metadata template. | + +The `defaultView`, `fieldsToShow`, and `metadataQuery` parameters are already defined in the sample project, as in the example below. + +For additional information on metadata queries, see [this guide][metadata-query]. + +3. Pass the required parameters to the Content Explorer component. + +```js + +[...] + + function App() { + [...] + + return ( + +
+
+

Metadata view in Content Explorer

+
+
+
+ +
+
+
+
+ ); + } + + export default App; + +``` + +A sample code for a React component including the Content Explorer metadata view would look as follows: + +```js +function App() { + // Get the token from Developer Console (app's configuration tab) + const token = ""; + + // Folder ID with a metadata template applied + // The metadataQuery will apply to this folder + const rootFolderID = ""; + + // Get ENTERPRISE_ID from Developer Console (app's general settings) + const EID = ""; + + // Get templatekey from Admin Console (Content -> Metadata -> check url for ID) + const templateName = ""; + + // Define metadata source + // Example: enterprise_123456789.metadatatemplate + const metadataSource = `metadata.enterprise_${EID}.${templateName}`; + + const metadataQuery = { + from: metadataSource, + + // Filter items in the folder by existing metadata key + query: "key = :arg1", + + // Display items with value + query_params: { arg1: "value" }, + + // Define the ancestor folder ID + ancestor_folder_id: 0, + + // Define which other metadata fields you'd like to display + fields: [ + `${metadataSource}.name`, + `${metadataSource}.last_contacted_at`, + `${metadataSource}.industry`, + `${metadataSource}.role`, + ], + }; + + // The metadata fields/columns to view - must be valid field names from the metadata template + const fieldsToShow = [ + // Determine if the user can edit the metadata directly from Content Explorer component + { key: `${metadataSource}.name`, canEdit: false }, + + // Determine label alias on metadata column with displayName prop + { key: `${metadataSource}.industry`, canEdit: false, displayName: "alias" }, + { key: `${metadataSource}.last_contacted_at`, canEdit: true }, + { key: `${metadataSource}.role`, canEdit: true }, + ]; + + // defaultView - a required prop to paint the metadata view. + // If not provided, you'll get regular folder view. + const defaultView = "metadata"; + + return ( + +
+
+

Metadata view in Content Explorer

+
+
+
+ +
+
+
+
+ ); +} + +export default App; + +``` + + + +**TIP**: For a detailed flow, see [Metadata view blog post][blogpost]. + + + [downscope]: guide://authentication/tokens/downscope [scopes]: guide://api-calls/permissions-and-errors/scopes + +[box-app]: g:///applications/app-types + +[token]: g://authentication/tokens/developer-tokens + +[templates]: g://metadata/templates + +[metadata-project]: https://github.com/box-community/content-explorer-metadata/tree/main + +[creating-templates-api]: g:///metadata/templates/create + +[creating-templates-ui]: https://support.box.com/hc/en-us/articles/360044194033-Customizing-Metadata-Templates + +[apply-templates]: https://support.box.com/hc/en-us/articles/360044196173-Using-Metadata + +[appjs]: https://github.com/box-community/content-explorer-metadata/blob/main/src/App.js + +[blogpost]: https://medium.com/box-developer-blog/metadata-view-in-box-content-explorer-4978e47e97e9 + +[metadata-query]: g://metadata/queries + +[get-template]: g://metadata/templates/get/#get-a-metadata-template-by-name diff --git a/guides/embed/ui-elements/index.md b/guides/embed/ui-elements/index.md index de735bbfc..532917b55 100644 --- a/guides/embed/ui-elements/index.md +++ b/guides/embed/ui-elements/index.md @@ -35,7 +35,7 @@ Boxには、アプリケーションでファイルやフォルダに共通す -We no longer support the `OpenWith` UI element for any new customers as of December 21, 2021. +日本時間2021年12月22日をもって、新規のお客様に対する`OpenWith` UI Elementのサポートは終了しました。 diff --git a/guides/embed/ui-elements/open-with.md b/guides/embed/ui-elements/open-with.md index d24d4f517..55934e2a0 100644 --- a/guides/embed/ui-elements/open-with.md +++ b/guides/embed/ui-elements/open-with.md @@ -26,7 +26,7 @@ fullyTranslated: true -We no longer support the `OpenWith` UI element for any new customers as of December 21, 2021. +日本時間2021年12月22日をもって、新規のお客様に対する`OpenWith` UI Elementのサポートは終了しました。 diff --git a/pages/index.md b/pages/index.md index 4f5de8995..682299d27 100644 --- a/pages/index.md +++ b/pages/index.md @@ -434,9 +434,11 @@ BoxとSalesforceを統合しましょう。最近、Boxでは、ローコード/ --> -
+ diff --git a/pages/sign/index.md b/pages/sign/index.md new file mode 100644 index 000000000..2b0ec2737 --- /dev/null +++ b/pages/sign/index.md @@ -0,0 +1,71 @@ +--- +centered: true +rank: 0 +category_id: sign +subcategory_id: null +is_index: true +id: sign +type: page +total_steps: 0 +sibling_id: pages +parent_id: pages +next_page_id: '' +previous_page_id: '' +source_url: 'https://github.com/box/developer.box.com/blob/main/content/pages/sign/index.md' +fullyTranslated: true +--- +# Working with Box Sign + + + +![Working with box sign image](images/working-with-box-sign.png) + + + +This learning page provides developers with practical insights into working with [Box Sign][sign], aiming to facilitate the integration of the Box Platform Sign engine into their applications. + +## クイックスタート + +Use the [Quick start][quick-start] to go straight into the creation of a signature request. + +## Technical use cases + +In the [Technical use cases][technical-use-cases], you will learn how to handle the different types of documents that can be used in a signature request: from unstructured documents that require a preparation step, through templates, to generated ready to sign documents. + +## Request Options + +In the [Request options][request-options], you will find a detailed exploration of the available customization and configuration options when sending signing requests through the Box Sign API. Learn how to tailor the signing experience to match your application's user interface, workflow, and specific requirements. + + + +Let's get started! + +[sign]: https://www.box.com/esignature + +[quick-start]: page://sign/quick-start + +[request-options]: page://sign/request-options + +[technical-use-cases]: page://sign/technical-use-cases + + diff --git a/pages/sign/quick-start/api-basics.md b/pages/sign/quick-start/api-basics.md new file mode 100644 index 000000000..adc086bea --- /dev/null +++ b/pages/sign/quick-start/api-basics.md @@ -0,0 +1,57 @@ +--- +centered: true +rank: 1 +category_id: sign +subcategory_id: sign/10-quick-start +is_index: false +id: sign/quick-start/api-basics +type: page +total_steps: 2 +sibling_id: sign/quick-start +parent_id: sign/quick-start +next_page_id: sign/quick-start/your-first-request +previous_page_id: '' +source_url: >- + https://github.com/box/developer.box.com/blob/main/content/pages/sign/10-quick-start/10-api-basics.md +fullyTranslated: true +--- +# API Basics + +## Sign API + +The Sign request endpoint is used to create and manage signature requests. You can create, resend, and cancel signature requests. You can also list all signature requests and get details of a specific signature request. + +The endpoint is `https://{api.box.com}/2.0/sign_requests`. The following table lists the operations that you can perform on this endpoint. + +| 操作 | エンドポイント | 説明 | +| ---- | ------------------------- | -------------------------------------------- | +| GET | /sign_requests | List all signature requests. | +| GET | /sign_requests/:id | Get details of a specific signature request. | +| POST | /sign_requests | Create a signature request. | +| POST | /sign_requests/:id/resend | Resend a signature request. | +| POST | /sign_requests/:id/cancel | Cancel a signature request. | + +For full details on the request and response parameters, see the [Sign request API reference][sign-api-reference]. + +## Sign templates API + +The Sign templates endpoint is used to list and get details of a template. + + + +You can not create, edit, or delete templates using the API. These templates are exclusively managed in the Box web application. + + + +The endpoint is `https://{api.box.com}/2.0/sign_templates`. The following table lists the operations that you can perform on this endpoint. + +| 操作 | エンドポイント | 説明 | +| --- | ------------------- | ----------------------------------- | +| GET | /sign_templates | List all templates. | +| GET | /sign_templates/:id | Get details of a specific template. | + +For a full details on the request and response parameters, see the [Sign template request API reference][sign-api-template-ref] + +[sign-api-reference]: https://developer.box.com/reference/resources/sign-request/ + +[sign-api-template-ref]: https://developer.box.com/reference/resources/sign-template/ diff --git a/pages/sign/quick-start/index.md b/pages/sign/quick-start/index.md new file mode 100644 index 000000000..94a2dc053 --- /dev/null +++ b/pages/sign/quick-start/index.md @@ -0,0 +1,30 @@ +--- +centered: true +rank: 10 +category_id: sign +subcategory_id: sign/10-quick-start +is_index: true +id: sign/quick-start +type: page +total_steps: 2 +sibling_id: sign +parent_id: sign +next_page_id: '' +previous_page_id: sign/quick-start/your-first-request +source_url: >- + https://github.com/box/developer.box.com/blob/main/content/pages/sign/10-quick-start/index.md +fullyTranslated: true +--- +# クイックスタート + +Get a sense of how the [Box Sign API][api-basics] is structured and how to create your first signature request. + +The Sign API does not follow the traditional CRUD model. You can create, resend, and cancel signature requests. You can also list all signature requests and get details of a specific signature request. + +Sign Templates API is read-only. You can list all templates and get details of a specific template. + +Once you get a sense of the API, you can create [your first signature request][quick-start]. + +[api-basics]: page://sign/quick-start/api-basics + +[quick-start]: page://sign/quick-start/your-first-request diff --git a/pages/sign/quick-start/your-first-request.md b/pages/sign/quick-start/your-first-request.md new file mode 100644 index 000000000..c5ac1bf6c --- /dev/null +++ b/pages/sign/quick-start/your-first-request.md @@ -0,0 +1,221 @@ +--- +centered: true +rank: 2 +category_id: sign +subcategory_id: sign/10-quick-start +is_index: false +id: sign/quick-start/your-first-request +type: page +total_steps: 2 +sibling_id: sign/quick-start +parent_id: sign/quick-start +next_page_id: sign/quick-start +previous_page_id: sign/quick-start/api-basics +source_url: >- + https://github.com/box/developer.box.com/blob/main/content/pages/sign/10-quick-start/20-your-first-request.md +fullyTranslated: true +--- +# Your first request + +Imagine that you have a document stored in Box and you want to send it to a customer for signature. At a minimum your app needs to know what document to sign, where to store the signed document, and the signer email. + +## Creating a signature request + +You can use the Box Sign API or one of the available SDKs to create a signature request. See the example: + + + + + +```bash + +curl --location 'https://api.box.com/2.0/sign_requests' \ +--header 'Content-Type: application/json' \ +--header 'Authorization: Bearer ' +--data-raw '{ + "is_document_preparation_needed": true, + "parent_folder": { + "id": "234102987614", + "type": "folder" + }, + "source_files": [ + { + "id": "1355143830404", + "type": "file" + } + ], + "signers": [ + { + "email": "signer@example.com", + "role": "signer" + } + ] +}' + +``` + + + + + +```python + +def sign_doc_single( + client: Client, + document_id: str, + destination_folder_id: str, + signer_email: str, + prep_needed: bool = False, +) -> SignRequest: + # Sign request params + source_file = FileBase(id=document_id, type=FileBaseTypeField.FILE) + destination_folder = FolderMini( + id=destination_folder_id, type=FolderBaseTypeField.FOLDER + ) + signer = SignRequestCreateSigner(signer_email) + # sign document + sign_request = client.sign_requests.create_sign_request( + signers=[signer], + parent_folder=destination_folder, + source_files=[source_file], + is_document_preparation_needed=prep_needed, + ) + + return sign_request + +def main(): + conf = ConfigOAuth() + client = get_client_oauth(conf) + + # Simple sign a pdf request with preparation + sign_pdf_prep = sign_doc_single( + client, SIMPLE_PDF, SIGN_DOCS_FOLDER, SIGNER_A, True + ) + + if sign_pdf_prep.prepare_url is not None: + open_browser(sign_pdf_prep.prepare_url) + +``` + + + + + +This will result in a signature request with a prepare document URL (simplified): + + + + + +```json + +{ + "is_document_preparation_needed": true, + "signers": [ + { + "email": "requester@example.com", + "role": "final_copy_reader", + }, + { + "email": "signer@example.com", + "role": "signer", + } + ], + "id": "348decab-48a8-4f2c-9436-8967afebf7bb", + "prepare_url": "https://app.box.com/sign/document/xyz-abc-123/.../prepare_doc/", + "source_files": [ + { + "id": "1355143830404", + "type": "file", + } + ], + "parent_folder": { + "id": "234102987614", + "type": "folder", + }, + "name": "Simple-PDF.pdf", + "type": "sign-request", + "status": "converting", + "sign_files": { + "files": [ + { + "id": "1381301154812", + "type": "file", + } + ], + "is_ready_for_download": true + }, + "template_id": null +} + +``` + + + + + +```YAML + +Simple sign request with prep: xyz-abc-123 + Status: converting + Signers: signer@example.com +Prepare url: https://app.box.com/sign/document/xyz-abc-123/.../prepare_doc/ + +``` + + + + + +## Check the status of the signature request + +Creating the signature request is an asynchronous process, and can generate errors. Your application should check the status of the request before proceeding, and handle any errors. + +A signature request can have the following statuses: + +![Signature flow](images/basic-sign-flow.png) + +* `converting`: 署名リクエストが送信された後、ファイルが署名プロセスのために`.pdf`に変換されている。 +* `error_converting`: An issue occurred while converting the file to a `.pdf`. +* `created`: When the `document_preparation_is_needed` is set to `true`, but the `prepare_url` has not yet been visited. +* `sent`: リクエストが正常に送信されたが、どの署名者も対応していない。 +* `error_sending`: An issue occurred while sending the request. +* `viewed`: The first, or only, signer clicked on **Review document** in the signing email or visited the signing URL. +* `downloaded`: The document was downloaded by the signer. +* `signed`: すべての署名者がリクエストの処理を完了した。 +* `signed and downloaded`: The document was signed and downloaded by the signer. +* `declined`: いずれかの署名者がリクエストを拒否した。 +* `cancelled`: リクエストがUIまたはAPIを介してキャンセルされた。 +* `expired`: 署名が未完了、不十分のまま、有効期限が過ぎた。 +* `finalizing`: All signers have signed the request, but the final document with signatures and the signing log have not been generated yet. +* `error_finalizing`: The `finalizing` phase did not complete successfully. + +## Preparing the document + +Depending on your technical use case you may need to prepare the document. In this specific example, we are signing a PDF, and the Box Sign engine has no idea where to place the signature pad field or any other inputs. This is why we used the `is_document_preparation_needed` flag. + +If a prepare URL is present, then your application should open the prepare URL in a browser, where the requester can add the signature pad field and any other inputs needed for the signer to complete the document. + +Once the document is prepared, the requester can send the signature request to the signer. + +This preparation step is not always necessary. Take a look at the [technical use cases][technical-use-cases] for more information. + +## Completing the signature request + +The signer then receives an email from Box with a link to the signature request. The signer can click the link and sign the document. + +When the process is completed, both a signature log containing metadata and the signed document are stored in the destination folder. + +Congratulations! You have successfully created your first signature request. + + + +This represents the basic use case for Box Sign. The `create` method has many options that you can use to customize your signature request. + +Be sure to check the [request options][request-options], and the [technical use cases][technical-use-cases] sections for more information. + + + +[request-options]: page://sign/request-options + +[technical-use-cases]: page://sign/technical-use-cases diff --git a/pages/sign/request-options/custom-email.md b/pages/sign/request-options/custom-email.md new file mode 100644 index 000000000..190e60755 --- /dev/null +++ b/pages/sign/request-options/custom-email.md @@ -0,0 +1,272 @@ +--- +centered: true +rank: 6 +category_id: sign +subcategory_id: sign/30-request-options +is_index: false +id: sign/request-options/custom-email +type: page +total_steps: 7 +sibling_id: sign/request-options +parent_id: sign/request-options +next_page_id: sign/request-options/in-person +previous_page_id: sign/request-options/request-expiration +source_url: >- + https://github.com/box/developer.box.com/blob/main/content/pages/sign/30-request-options/60-custom-email.md +fullyTranslated: true +--- +# Custom email and notifications + +## Email subject and body + +By default, the email sent to the signers contains a link to the document, a generic subject, and a generic message. + +If you are using templates managed within Box, the subject and message body can be set in the template itself. + +However, if you are not using templates, you can still customize the email messages sent to the signers by passing the `email_subject` and the `email_message` parameters. + +Both parameters accept strings, but the `email_message` parameter also accepts HTML with some limitations. + +Only some HTML tags are allowed. Links included in the message are also converted to hyperlinks in the email. + +The message parameter may contain the following HTML tags: + +* `a`, `abbr`, `acronym`, `b`, `blockquote`, `code`, `em`, `i`, `ul`, `li`, + `ol`, `strong` + +Custom styles on these tags are not allowed. + + + +Be aware that when the text to HTML ratio is too high, the email may end up in spam filters or clipped. + + + +例: + + + + + +```bash + +curl --location 'https://api.box.com/2.0/sign_requests' \ +--header 'Content-Type: application/json' \ +--header 'Authorization: Bearer ej...3t' +--data-raw '{ + "email_subject":"All we need is your signature to get started", + "parent_folder": { + "id": "234102987614", + "type": "folder" + }, + "source_files": [ + { + "id": "1358047520478", + "type": "file" + } + ], + "signers": [ + { + "email": "signer@example.com", + "role": "signer" + } + ] +}' + +``` + + + + + +```python + +def sign_doc_single_more_options( + client: Client, + ... + + email_subject: str = None, + email_message: str = None, +) -> SignRequest: + ... + + # sign document + sign_request = client.sign_requests.create_sign_request( + ... + + email_subject=email_subject, + email_message=email_message, + ) + + return sign_request + +def main(): + ... + + # Sign with custom email subject + sign_custom_email_subject = sign_doc_single_more_options( + client, + SIMPLE_PDF, + SIGN_DOCS_FOLDER, + SIGNER_A, + prep_needed=False, + email_subject="All we need is your signature to get started", + ) + +``` + + + + + +## Manual notification + +By now, you've noticed that the signature request sends an email notification to the signers by default. This email is sent from a `box.com` domain and email system. + +You can take over the notification process by setting the `embed_url_external_user_id` parameter to an identifier of your choice for a specific signer. + +By setting this parameter, the signer will not receive an email notification, and within the signature request, you get back both an `embed_url` and an `iframeable_embed_url`. + +The `embed_url` can be opened directly, so it is suitable for your app to send it in an email, or by any other notifications system for the signer to open. + +The `iframeable_embed_url` is suited to be used with the [Box Embedded Sign Client][embed], which allows you to embed the Box Sign client on an iframe within your web app. + +For example see this request: + + + + + +```bash + +--header 'Content-Type: application/json' \ +--header 'Authorization: Bearer fN...dD' +--data-raw '{ + "is_document_preparation_needed": false, + "parent_folder": { + "id": "234102987614", + "type": "folder" + }, + "source_files": [ + { + "id": "1355143830404", + "type": "file" + } + ], + "signers": [ + { + "email": "signer@example.com", + "embed_url_external_user_id":"1234", + "role": "signer" + } + ] +}' + +``` + + + + + +```python + +def sign_doc_embed_url( + client: Client, + document_id: str, + destination_folder_id: str, + signer_email: str, + signer_embed_url_id: str, +) -> SignRequest: + # Sign request params + source_file = FileBase(id=document_id, type=FileBaseTypeField.FILE) + destination_folder = FolderMini( + id=destination_folder_id, type=FolderBaseTypeField.FOLDER + ) + + signer = SignRequestCreateSigner( + email=signer_email, + embed_url_external_user_id=signer_embed_url_id, + ) + + # sign document + sign_request = client.sign_requests.create_sign_request( + signers=[signer], + parent_folder=destination_folder, + source_files=[source_file], + ) + + return sign_request + + +def main(): + """Simple script to demonstrate how to use the Box SDK""" + conf = ConfigOAuth() + client = get_client_oauth(conf) + # Sign with phone verification + sign_with_embed_url = sign_doc_embed_url( + client, + SIMPLE_PDF, + SIGN_DOCS_FOLDER, + SIGNER_A, + SIGNER_A_EXTERNAL_ID, + ) + check_sign_request(sign_with_embed_url) + +``` + + + + + +Returns (simplified): + + + + + +```json + +{ + "is_document_preparation_needed": false, + "signers": [ + { + "email": "sender@example.com", + "role": "final_copy_reader", + }, + { + "email": "signer@example.com", + "role": "signer", + "embed_url_external_user_id": "1234", + "embed_url": "https://app.box.com/sign/document/22a990ce-4e24-463b-b2f4-124820fe161a/9331fe9ac85650d61645d4b0fd30fe3e0ebee7921720ab6ecca587654d3cd875/", + "iframeable_embed_url": "https://app.box.com/embed/sign/document/22a990ce-4e24-463b-b2f4-124820fe161a/9331fe9ac85650d61645d4b0fd30fe3e0ebee7921720ab6ecca587654d3cd875/" + } + ], + "id": "22a990ce-4e24-463b-b2f4-124820fe161a", +} + +``` + + + + + +```yaml + +Simple sign request: 22a990ce-4e24-463b-b2f4-124820fe161a-defddc79c946 + Status: created + Signers: 2 + final_copy_reader: sender@example.com + signer: signer@example.com + embed_url: https://app.box.com/sign/document/... + iframeable_embed_url: https://app.box.com/embed/sign/document/... + Prepare url: None + +``` + + + + + +You can now take the embedded URLs and use your own notification process or embed the signature client within your own app. + +[embed]: guide://box-sign/embedded-sign-client diff --git a/pages/sign/request-options/custom-urls.md b/pages/sign/request-options/custom-urls.md new file mode 100644 index 000000000..9ce49edb6 --- /dev/null +++ b/pages/sign/request-options/custom-urls.md @@ -0,0 +1,108 @@ +--- +centered: true +rank: 3 +category_id: sign +subcategory_id: sign/30-request-options +is_index: false +id: sign/request-options/custom-urls +type: page +total_steps: 7 +sibling_id: sign/request-options +parent_id: sign/request-options +next_page_id: sign/request-options/resend-requests +previous_page_id: sign/request-options/extra-security +source_url: >- + https://github.com/box/developer.box.com/blob/main/content/pages/sign/30-request-options/30-custom-urls.md +fullyTranslated: true +--- +# Redirect URLs + +Often after signing a document your company might want to redirect the user to a specific web page like a thank you or an onboarding page. There are two features to support these requirements. + +When the signer completes the signature process, they can be redirected to a web page. The same can happen when the signer declines the signature request. + +We can customize these pages by passing the `redirect_url` and `decline_redirect_url` parameters. + +![Custom redirect pages](images/sign-flow-custom-url.png) + +例: + + + + + +```bash + +curl --location 'https://api.box.com/2.0/sign_requests' \ +--header 'Content-Type: application/json' \ +--header 'Authorization: Bearer ej...3t' +--data-raw '{ + "is_document_preparation_needed": true, + "redirect_url": "https://forum.box.com/", + "declined_redirect_url":"https://developer.box.com/", + "parent_folder": { + "id": "234102987614", + "type": "folder" + }, + "source_files": [ + { + "id": "1358047520478", + "type": "file" + } + ], + "signers": [ + { + "email": "signer@example.com", + "role": "signer" + } + ] +}' + +``` + + + + + +```python + +def sign_doc_single_more_options( + ... + + redirect_url: str = None, + declined_redirect_url: str = None, +) -> SignRequest: + ... + + # sign document + sign_request = client.sign_requests.create_sign_request( + ... + + redirect_url=redirect_url, + declined_redirect_url=declined_redirect_url, + ) + + return sign_request + +def main(): + ... + + # Sign with redirects + sign_with_redirects = sign_doc_single_more_options( + client, + SIMPLE_PDF, + SIGN_DOCS_FOLDER, + SIGNER_A, + prep_needed=False, + redirect_url="https://forum.box.com/", + declined_redirect_url="https://developer.box.com/", + ) + check_sign_request(sign_with_redirects) + +``` + + + + + +If you sign you’ll be redirected to our forum page. If you decline you’ll be redirected to our developer page. diff --git a/pages/sign/request-options/extra-security.md b/pages/sign/request-options/extra-security.md new file mode 100644 index 000000000..e8859120e --- /dev/null +++ b/pages/sign/request-options/extra-security.md @@ -0,0 +1,229 @@ +--- +centered: true +rank: 2 +category_id: sign +subcategory_id: sign/30-request-options +is_index: false +id: sign/request-options/extra-security +type: page +total_steps: 7 +sibling_id: sign/request-options +parent_id: sign/request-options +next_page_id: sign/request-options/custom-urls +previous_page_id: sign/request-options/multiple-signers +source_url: >- + https://github.com/box/developer.box.com/blob/main/content/pages/sign/30-request-options/20-extra-security.md +fullyTranslated: true +--- +# Extra security (2FA) + +Imagine you want an [additional layer of security][2FA] for your signature requests, by requesting the signer to use a password or a phone verification in the document signing step. + +![2FA Signature request](images/sign-flow-2fa.png) + +## Phone verification + +You can require the signer to use 2FA through their mobile phone to complete the signature request by passing the `is_phone_verification_required_to_view` parameter. + +例: + + + + + +```bash + +curl --location 'https://api.box.com/2.0/sign_requests' \ +--header 'Content-Type: application/json' \ +--header 'Authorization: Bearer ej...3t' +--data-raw '{ + "is_document_preparation_needed": true, + "parent_folder": { + "id": "234102987614", + "type": "folder" + }, + "source_files": [ + { + "id": "1358047520478", + "type": "file" + } + ], + "signers": [ + { + "email": "verify@example.com", + "role": "signer", + "verification_phone_number":"+15551232190" + } + ] +}' + +``` + + + + + +```python + +def sign_doc_verify_phone( + client: Client, + document_id: str, + destination_folder_id: str, + signer_email: str, + signer_phone: str, +) -> SignRequest: + + # Sign request params + source_file = FileBase(id=document_id, type=FileBaseTypeField.FILE) + destination_folder = FolderMini( + id=destination_folder_id, type=FolderBaseTypeField.FOLDER + ) + + signer = SignRequestCreateSigner( + email=signer_email, + verification_phone_number=signer_phone, + ) + + # sign document + sign_request = client.sign_requests.create_sign_request( + signers=[signer], + parent_folder=destination_folder, + source_files=[source_file], + is_phone_verification_required_to_view=True, + ) + + return sign_request + +def main(): + ... + + # Sign with phone verification + sign_with_phone_verification = sign_doc_verify_phone( + client, + SIMPLE_PDF, + SIGN_DOCS_FOLDER, + SIGNER_A, + SIGNER_A_PHONE, + ) + check_sign_request(sign_with_phone_verification) + +``` + + + + + +When the signer tries to complete the signature request a phone verification pops up: + +![Phone verification](images/sign-simple-phone-verification.png) + +Then the signer is prompted to enter the code sent in a SMS: + +![Entering the SMS code](images/sign-simple-phone-verification-enter-code.png) + + + +This check is done as the last step, so it does not prevent the signer from accessing the document. + + + +## Password verification + +You can require the signer to use a password to open the signature request by passing the `password` parameter in the `signer` object. For example: + + + + + +```bash + +curl --location 'https://api.box.com/2.0/sign_requests' \ +--header 'Content-Type: application/json' \ +--header 'Authorization: Bearer ej...3t' +--data-raw '{ + "is_document_preparation_needed": true, + "parent_folder": { + "id": "234102987614", + "type": "folder" + }, + "source_files": [ + { + "id": "1358047520478", + "type": "file" + } + ], + "signers": [ + { + "email": "verify@example.com", + "role": "signer", + "password":"1234" + } + ] +}' + +``` + + + + + +```python + +def sign_doc_verify_password( + client: Client, + document_id: str, + destination_folder_id: str, + signer_email: str, + signer_password: str, +) -> SignRequest: + + # Sign request params + source_file = FileBase(id=document_id, type=FileBaseTypeField.FILE) + destination_folder = FolderMini( + id=destination_folder_id, type=FolderBaseTypeField.FOLDER + ) + + # signer + signer = SignRequestCreateSigner( + email=signer_email, + password=signer_password, + ) + + # sign document + sign_request = client.sign_requests.create_sign_request( + signers=[signer], + parent_folder=destination_folder, + source_files=[source_file], + ) + + return sign_request + +def main(): + ... + + # Sign with phone verification + sign_with_password_verification = sign_doc_verify_password( + client, + SIMPLE_PDF, + SIGN_DOCS_FOLDER, + SIGNER_A, + "1234", + ) + +``` + + + + + +Once the signer opens the signature request they should see something like this: + +![Password verification pop-up](images/sign-simple-password.png) + + + +As the password verification is done on the first step, it prevents the signer from accessing the document until the correct password is provided. + + + +[2FA]: https://support.box.com/hc/en-us/articles/4406861109907-Additional-Signer-Authentication diff --git a/pages/sign/request-options/in-person.md b/pages/sign/request-options/in-person.md new file mode 100644 index 000000000..09d19c95c --- /dev/null +++ b/pages/sign/request-options/in-person.md @@ -0,0 +1,358 @@ +--- +centered: true +rank: 7 +category_id: sign +subcategory_id: sign/30-request-options +is_index: false +id: sign/request-options/in-person +type: page +total_steps: 7 +sibling_id: sign/request-options +parent_id: sign/request-options +next_page_id: sign/request-options +previous_page_id: sign/request-options/custom-email +source_url: >- + https://github.com/box/developer.box.com/blob/main/content/pages/sign/30-request-options/70-in-person.md +fullyTranslated: true +--- +# In person signatures + +Imagine your application is used by a salesperson when they are face to face with a customer and an immediate signature is required, for example, to subscribe to a service or to confirm a purchase. + +In this case, the salesperson can use your application to create a signature request and then hand over the device to the customer to sign the document, immediately closing the deal. + +Doing this using the Box web application, for example from a template, is very straightforward. You set the signer or signers email so they can receive a copy of the signed document, flag them as in person, and as soon as you send the request, the Sign interface opens requesting the signature for the first signer, then for the second signer, and so on. + +In order to use this within your application, you need to create a signature request with the `is_in_person` flag set to `true` for each signer. + +However because your application needs to show the Sign interface to the signer, you also need to use the `embed_url_external_user_id`so that you get back the embedded URLs, and then either open a browser window or use an iframe to display the signature interface. + +![In person signing loops through signers](images/sign-flow-in-person.png) + +## Create an in person signature request + +Let's use a template with a single signer as an example: + + + + + +```bash + +curl --location 'https://api.box.com/2.0/sign_requests' \ +--header 'Content-Type: application/json' \ +--header 'Authorization: Bearer Le...Cb' +--data-raw '{ + "template_id":"ee9a689e-96b6-4076-92a0-b9b765eb09ca", + "parent_folder": { + "id": "234102987614", + "type": "folder" + }, + "signers": [ + { + "email": "signer@example.com", + "role": "signer", + "is_in_person":true, + "embed_url_external_user_id":"1234" + } + ] +}' + +``` + + + + + +```python + +def sign_doc_in_person( + client: Client, + document_id: str, + destination_folder_id: str, + signer_email: str, + signer_embed_url_id: str, +) -> SignRequest: + # Sign request params + source_file = FileBase(id=document_id, type=FileBaseTypeField.FILE) + destination_folder = FolderMini( + id=destination_folder_id, type=FolderBaseTypeField.FOLDER + ) + + signer = SignRequestCreateSigner( + email=signer_email, + embed_url_external_user_id=signer_embed_url_id, + is_in_person=True, + ) + + # sign document + sign_request = client.sign_requests.create_sign_request( + signers=[signer], + parent_folder=destination_folder, + source_files=[source_file], + ) + + return sign_request + + +def main(): + """Simple script to demonstrate how to use the Box SDK""" + conf = ConfigOAuth() + client = get_client_oauth(conf) + # Sign with phone verification + sign_with_embed_url = sign_doc_embed_url( + client, + SIMPLE_PDF, + SIGN_DOCS_FOLDER, + SIGNER_A, + SIGNER_A_EXTERNAL_ID, + ) + check_sign_request(sign_with_embed_url) + +``` + + + + + +Resulting in (simplified): + + + + + +```json + +{ + "signers": [ + { + "email": "sender@example.com", + "role": "final_copy_reader", + "is_in_person": false, + }, + { + "email": "signer@example.com", + "role": "signer", + "is_in_person": true, + "embed_url_external_user_id": "1234", + "embed_url": "https://app.box.com/sign/document/...", + "iframeable_embed_url": "https://app.box.com/embed/sign/document/..." + } + ], + "id": "a9159d31-d2fb-4e88-9306-02c00de013d1", + "parent_folder": { + "id": "234102987614", + "type": "folder", + "name": "signed docs" + }, + "name": "Simple-PDF (1).pdf", + "type": "sign-request", + "status": "created", + "template_id": "ee9a689e-96b6-4076-92a0-b9b765eb09ca" +} + +``` + + + + + +```yaml + +Simple sign request: a9159d31-d2fb-4e88-9306-02c00de013d1 + Status: created + Signers: 2 + final_copy_reader: sender@example.com + signer: signer@example.com + embed_url: https://app.box.com/sign/document/... + iframeable_embed_url: https://app.box.com/embed/sign/document/... + Prepare url: None + +``` + + + + + +Notice the `embed_url` and `iframeable_embed_url` in the response. Now when we browse to the embed URL, you see the signature interface: + +![In person signing](images/sign-in-person.png) + +Once finished the signer will receive a copy of the signed document via their email. + +## Multiple in person signers + +As long as the signer is flagged as `is_in_person`, the signing interface cycles through all the signers in the request. + +For example, if you add a second signer to the request: + + + + + +```bash + +curl --location 'https://api.box.com/2.0/sign_requests' \ +--header 'Content-Type: application/json' \ +--header 'Authorization: Bearer Le...Cb' +--data-raw '{ + "template_id":"ee9a689e-96b6-4076-92a0-b9b765eb09ca", + "parent_folder": { + "id": "234102987614", + "type": "folder" + }, + "signers": [ + { + "email": "signer_a@example.com", + "role": "signer", + "is_in_person":true, + "embed_url_external_user_id":"1234" + }, + { + "email": "signer_b@example.com", + "role": "signer", + "is_in_person":true + } + ] +}' + +``` + + + + + +```python + +def sign_doc_in_person_multiple( + client: Client, + document_id: str, + destination_folder_id: str, + signer_a_email: str, + signer_a_embed_url_id: str, + signer_b_email: str, +) -> SignRequest: + # Sign request params + source_file = FileBase(id=document_id, type=FileBaseTypeField.FILE) + destination_folder = FolderMini( + id=destination_folder_id, type=FolderBaseTypeField.FOLDER + ) + + signer_a = SignRequestCreateSigner( + email=signer_email, + embed_url_external_user_id=signer_embed_url_id, + is_in_person=True, + ) + + signer_b = SignRequestCreateSigner( + email=signer_email, + is_in_person=True, + ) + + # sign document + sign_request = client.sign_requests.create_sign_request( + signers=[signer_a, signer_b], + parent_folder=destination_folder, + source_files=[source_file], + ) + + return sign_request + + +def main(): + """Simple script to demonstrate how to use the Box SDK""" + conf = ConfigOAuth() + client = get_client_oauth(conf) + # Sign with phone verification + sign_with_embed_url = sign_doc_embed_url( + client, + SIMPLE_PDF, + SIGN_DOCS_FOLDER, + SIGNER_A, + SIGNER_A_EXTERNAL_ID, + SIGNER_B + ) + check_sign_request(sign_with_embed_url) + +``` + + + + + +Results in (simplified): + + + + + +```json + +{ + "signers": [ + { + "email": "sender@example.com", + "role": "final_copy_reader", + "is_in_person": false, + }, + { + "email": "signer_a@example.com", + "role": "signer", + "is_in_person": true, + "embed_url": "https://app.box.com/sign/document/...", + "iframeable_embed_url": "https://app.box.com/embed/sign/document/..." + }, + { + "email": "signer_b@example.com", + "role": "signer", + "is_in_person": true, + "embed_url": null, + "iframeable_embed_url": null + } + ], + "id": "d066575f-f22b-42fc-b9e2-701468776475", + "parent_folder": { + "id": "234102987614", + "type": "folder", + "name": "signed docs" + }, + "name": "Simple-PDF (3).pdf", + "type": "sign-request", + "status": "created", + "template_id": "ee9a689e-96b6-4076-92a0-b9b765eb09ca" +} + +``` + + + + + +```yaml + +Simple sign request: d066575f-f22b-42fc-b9e2-701468776475 + Status: created + Signers: 3 + final_copy_reader: sender@example.com + + signer: signer_a@example.com + embed_url: https://app.box.com/sign/document/... + iframeable_embed_url: https://app.box.com/embed/sign/document/... + + signer: signer_b@example.com + + Prepare url: None + +``` + + + + + +Browsing to the embedded URL shows the signature interface for the first signer: + +![First in person signer](images/sign-inperson-first.png) + +Once the first signer has signed, the signature interface automatically switches to the second signer: + +![Alt text](images/sign-inperson-second.png) diff --git a/pages/sign/request-options/index.md b/pages/sign/request-options/index.md new file mode 100644 index 000000000..66d1729f1 --- /dev/null +++ b/pages/sign/request-options/index.md @@ -0,0 +1,20 @@ +--- +centered: true +rank: 30 +category_id: sign +subcategory_id: sign/30-request-options +is_index: true +id: sign/request-options +type: page +total_steps: 7 +sibling_id: sign +parent_id: sign +next_page_id: '' +previous_page_id: sign/request-options/in-person +source_url: >- + https://github.com/box/developer.box.com/blob/main/content/pages/sign/30-request-options/index.md +fullyTranslated: true +--- +# Request options + +The Box Sign API offers a wide range of customization and configuration options when sending signature requests. These options allow developers to tailor the user experience and workflow to match their application's specific requirements. diff --git a/pages/sign/request-options/multiple-signers.md b/pages/sign/request-options/multiple-signers.md new file mode 100644 index 000000000..5dd5462f0 --- /dev/null +++ b/pages/sign/request-options/multiple-signers.md @@ -0,0 +1,317 @@ +--- +centered: true +rank: 1 +category_id: sign +subcategory_id: sign/30-request-options +is_index: false +id: sign/request-options/multiple-signers +type: page +total_steps: 7 +sibling_id: sign/request-options +parent_id: sign/request-options +next_page_id: sign/request-options/extra-security +previous_page_id: '' +source_url: >- + https://github.com/box/developer.box.com/blob/main/content/pages/sign/30-request-options/10-multiple-signers.md +fullyTranslated: true +--- +# Multiple signers and roles + +## Multiple signers + +What if you have a document that needs to be signed by multiple people? This is typical for contracts between two or more entities. + +Having multiple signers introduces another dimension to the Box Sign process, the order in which the signers need to sign the document. + +If you do not specify the order, the request is sent to everyone at the same time, and when all parties have signed the document, they each receive a copy with all signatures. + +If you specify the signing order, the signature request is sent to the first signer. Only when the first signer signs the document, the request is sent to the second signer, and so on. + +Let’s see this working with an example scholarship contract between a university and a student. In this case the institution/teacher must sign the document first. + +Creating a method specific for this: + + + + + +```bash + +curl --location 'https://api.box.com/2.0/sign_requests' \ +--header 'Content-Type: application/json' \ +--header 'Authorization: Bearer ej...3t' +--data-raw '{ + "is_document_preparation_needed": true, + "parent_folder": { + "id": "234102987614", + "type": "folder" + }, + "source_files": [ + { + "id": "1358047520478", + "type": "file" + } + ], + "signers": [ + { + "email": "institution@example.com", + "role": "signer", + "order":1 + }, + { + "email": "student@example.com", + "role": "signer", + "order":2 + }, + ] +}' + +``` + + + + + +```python + +def sign_contract( + client: Client, + document_id: str, + destination_folder_id: str, + institution_email: str, + student_email: str, + prep_needed: bool = False, +) -> SignRequest: + """Sign contract""" + + # Sign request params + source_file = FileBase(id=document_id, type=FileBaseTypeField.FILE) + destination_folder = FolderMini( + id=destination_folder_id, type=FolderBaseTypeField.FOLDER + ) + + # signers + institution = SignRequestCreateSigner( + email=institution_email, + role=SignRequestCreateSignerRoleField.SIGNER, + order=1, + ) + + student = SignRequestCreateSigner( + email=student_email, + role=SignRequestCreateSignerRoleField.SIGNER, + order=2, + ) + + # create sign request + sign_request = client.sign_requests.create_sign_request( + signers=[institution, student], + parent_folder=destination_folder, + source_files=[source_file], + is_document_preparation_needed=prep_needed, + ) + + return sign_request + +def main(): + ... + + # Multiple signers + sign_contract_multi = sign_contract( + client, + CONTRACT, + SIGN_DOCS_FOLDER, + institution_email=SIGNER_A, + student_email=SIGNER_B, + prep_needed=True, + ) + if sign_contract_multi.prepare_url is not None: + open_browser(sign_contract_multi.prepare_url) + +``` + + + + + +In this particular example the document needs to be prepared, so the browser to the prepare URL opens. + +Drag the signature pad, the full name and the date to the appropriate places in the document, and click Send Request: + +![Preparing the contract](images/sign-multi-prep.png) + +Notice you now have two signers, with the order already specified. The `color` is also important to identify which signer is which (in this case the institution is blue and the student is green), determining which signature pad, name and date belongs to which signer. + +If you look at the signature request details, you should see something like this: + +![Signature request details showing the document and signers](images/sign-multi-prep-details.png) + +Indicating that the first request was sent, but the second is waiting for the first to be completed. + +Go ahead and complete the signature process for both signers. + +Notice that when you get the second request it is already signed by the first signer. + +## ロール + +So far we have been working with the `signer` role. However there are [other roles][roles] that you can use to customize the signature process. + +The available roles are, `signer`, `approver`, and `final copy reader` + +From a developer perspective, this means: + +* **Signer**: Any person who is allowed to add data to the document. This includes adding a signature, initials, date, but also filling out text fields, check boxes, and radio buttons, even if it does not include a signature. + +* **Approver**: This role will be asked if they approve the signature request. This approval happens before the preparation step, if enabled, and before the request is sent to any of the signers. This role is useful if you need to get approval from someone before sending the document to the signers. + +* **Final copy reader**: This role does not interact with the signature process, but will receive a copy of the signed document. + +Let's use roles to be a bit more creative in the scholarship example. + +Imagine that the scholarship needs to be approved by the dean, and the legal department receives a final copy of the contract. + +The flow starts with the signature request, flowed by the dean approval, the institution signature, the student signature, and finally the legal department receives a copy of the signed document: + +![Multiple signers and roles](images/sign-flow-multi-role.png) + +Let's create a method for this: + + + + + +```bash + +curl --location 'https://api.box.com/2.0/sign_requests' \ +--header 'Content-Type: application/json' \ +--header 'Authorization: Bearer ej...3t' +--data-raw '{ + "is_document_preparation_needed": true, + "parent_folder": { + "id": "234102987614", + "type": "folder" + }, + "source_files": [ + { + "id": "1358047520478", + "type": "file" + } + ], + "signers": [ + { + "email": "institution@example.com", + "role": "signer", + "order":1 + }, + { + "email": "student@example.com", + "role": "signer", + "order":2 + }, + { + "email": "dean@example.com", + "role": "approver" + }, + { + "email": "legal@example.com", + "role": "final_copy_reader" + } + ] +}' + +``` + + + + + +```python + +def sign_contract_step( + client: Client, + document_id: str, + destination_folder_id: str, + institution_email: str, + student_email: str, + dean_email: str, + legal_email: str, +) -> SignRequest: + """Sign contract""" + + # Sign request params + source_file = FileBase(id=document_id, type=FileBaseTypeField.FILE) + destination_folder = FolderMini( + id=destination_folder_id, type=FolderBaseTypeField.FOLDER + ) + + # signers + institution = SignRequestCreateSigner( + email=institution_email, + role=SignRequestCreateSignerRoleField.SIGNER, + order=1, + ) + + student = SignRequestCreateSigner( + email=student_email, + role=SignRequestCreateSignerRoleField.SIGNER, + order=2, + ) + + dean = SignRequestCreateSigner( + email=dean_email, + role=SignRequestCreateSignerRoleField.APPROVER, + ) + + legal = SignRequestCreateSigner( + email=legal_email, + role=SignRequestCreateSignerRoleField.FINAL_COPY_READER, + ) + + # create sign request + sign_request = client.sign_requests.create_sign_request( + signers=[institution, student, dean, legal], + parent_folder=destination_folder, + source_files=[source_file], + is_document_preparation_needed=True, + ) + + return sign_request + +def main(): + ... + + # Multiple signers and steps + sign_contract_multi_step = sign_contract_step( + client, + CONTRACT, + SIGN_DOCS_FOLDER, + institution_email=SIGNER_A, + student_email=SIGNER_B, + dean_email=APPROVER, + legal_email=FINAL_COPY, + ) + if sign_contract_multi_step.prepare_url is not None: + open_browser(sign_contract_multi_step.prepare_url) + +``` + + + + + +Like before you need to prepare the document, so open the prepare URL in your browser. + +Notice in the example the institution is represented by blue on the left, and the student by green on the right, and both are signers. + +Neither the `approver` nor the `final copy reader` can have inputs associated with them. If you do this, their roles will be adjusted to `signer`: + +![Multiple role preparation](images/sign_multi-steps-prep.png) + +Continuing the signature process: + +* The dean approves the scholarship +* The institution signs the scholarship +* The student signs the scholarship +* The legal department receives a copy of the signed document. + +[roles]: https://support.box.com/hc/en-us/articles/4404105660947-Roles-for-signers diff --git a/pages/sign/request-options/request-expiration.md b/pages/sign/request-options/request-expiration.md new file mode 100644 index 000000000..6c457a8b5 --- /dev/null +++ b/pages/sign/request-options/request-expiration.md @@ -0,0 +1,87 @@ +--- +centered: true +rank: 5 +category_id: sign +subcategory_id: sign/30-request-options +is_index: false +id: sign/request-options/request-expiration +type: page +total_steps: 7 +sibling_id: sign/request-options +parent_id: sign/request-options +next_page_id: sign/request-options/custom-email +previous_page_id: sign/request-options/resend-requests +source_url: >- + https://github.com/box/developer.box.com/blob/main/content/pages/sign/30-request-options/50-request-expiration.md +fullyTranslated: true +--- +# Request expiration + +There are situations where you might need to [set an expiration date][exp-date] for the signature request. + +For example, imagine a quote for a service that is valid for 30 days. This proposal has to be signed by a certain date, and if not, the signature request for the quote is no longer valid. + +All you need to do is pass the `days_valid` parameter. + +例: + + + + + +```bash + +curl --location 'https://api.box.com/2.0/sign_requests' \ +--header 'Content-Type: application/json' \ +--header 'Authorization: Bearer ej...3t' +--data-raw '{ + "days_valid":30, + "parent_folder": { + "id": "234102987614", + "type": "folder" + }, + "source_files": [ + { + "id": "1358047520478", + "type": "file" + } + ], + "signers": [ + { + "email": "signer@example.com", + "role": "signer" + } + ] +}' + +``` + + + + + +```python + +def sign_doc_single_more_options( + ... + + days_valid: int = None, +) -> SignRequest: + ... + + # sign document + sign_request = client.sign_requests.create_sign_request( + ... + + days_valid=days_valid, + ) + + return sign_request + +``` + + + + + +[exp-date]: https://support.box.com/hc/en-us/articles/4404105810195-Sending-a-document-for-signature#:~:text=Step%205%3A%20Setting%20an%20expiration diff --git a/pages/sign/request-options/resend-requests.md b/pages/sign/request-options/resend-requests.md new file mode 100644 index 000000000..4552ba04a --- /dev/null +++ b/pages/sign/request-options/resend-requests.md @@ -0,0 +1,149 @@ +--- +centered: true +rank: 4 +category_id: sign +subcategory_id: sign/30-request-options +is_index: false +id: sign/request-options/resend-requests +type: page +total_steps: 7 +sibling_id: sign/request-options +parent_id: sign/request-options +next_page_id: sign/request-options/request-expiration +previous_page_id: sign/request-options/custom-urls +source_url: >- + https://github.com/box/developer.box.com/blob/main/content/pages/sign/30-request-options/40-resend-requests.md +fullyTranslated: true +--- +# Resend requests + +What if the signer did not receive the email, the email was lost, or the signer deleted the email by mistake? + +You can resend the signature request email to the `signer` , either manually or you can turn on the automatic resend option. + +## Manual resend + +To manually resend the signature request email to the signer, call the `resend_sign_request` method on the `sign_requests` object. You can only do it once every 10 minutes. + +Here is an example: + + + + + +```bash + +curl --location --request POST 'https://api.box.com/2.0/sign_requests/ +52f6f86c-c0b3-401e-a4ec-1709f277c469/resend' \ +--header 'Authorization: Bearer ej...3t' + +``` + + + + + +```python + +def sign_send_reminder(client: Client, sign_request_id: str): + """Send reminder to signers""" + sign_request = client.sign_requests.resend_sign_request(sign_request_id) + return sign_request + +``` + + + + + +## Automatic resend + +The automatic resend option sends a reminder email to signers that have not signed the document yet, after 3, 8, 13, and 18 days. + +To enable automatic resend set the `are_reminders_enabled` parameter to `true`. For example: + + + + + +```bash + +curl --location 'https://api.box.com/2.0/sign_requests' \ +--header 'Content-Type: application/json' \ +--header 'Authorization: Bearer ' +--data-raw '{ + "are_reminders_enabled": true, + "parent_folder": { + "id": "234102987614", + "type": "folder" + }, + "source_files": [ + { + "id": "1355143830404", + "type": "file" + } + ], + "signers": [ + { + "email": "signer@example.com", + "role": "signer" + } + ] +}' + +``` + + + + + +```python + +def sign_doc_single_more_options( + client: Client, + document_id: str, + destination_folder_id: str, + signer_email: str, + prep_needed: bool = False, + auto_reminder: bool = False, +) -> SignRequest: + """Single doc sign by single signer""" + + # Sign request params + source_file = FileBase(id=document_id, type=FileBaseTypeField.FILE) + destination_folder = FolderMini( + id=destination_folder_id, type=FolderBaseTypeField.FOLDER + ) + + # signer + signer = SignRequestCreateSigner(signer_email) + + # sign document + sign_request = client.sign_requests.create_sign_request( + signers=[signer], + parent_folder=destination_folder, + source_files=[source_file], + is_document_preparation_needed=prep_needed, + are_reminders_enabled=auto_reminder, + ) + + return sign_request + +def main(): + ... + + # Sign with redirects + sign_with_auto_reminder = sign_doc_single_more_options( + client, + SIMPLE_PDF, + SIGN_DOCS_FOLDER, + SIGNER_A, + prep_needed=False, + auto_reminder = True, + ) + +``` + + + + diff --git a/pages/sign/technical-use-cases/index.md b/pages/sign/technical-use-cases/index.md new file mode 100644 index 000000000..5441c1d3e --- /dev/null +++ b/pages/sign/technical-use-cases/index.md @@ -0,0 +1,40 @@ +--- +centered: true +rank: 20 +category_id: sign +subcategory_id: sign/20-technical-use-cases +is_index: true +id: sign/technical-use-cases +type: page +total_steps: 3 +sibling_id: sign +parent_id: sign +next_page_id: '' +previous_page_id: sign/technical-use-cases/sign-structured-docs +source_url: >- + https://github.com/box/developer.box.com/blob/main/content/pages/sign/20-technical-use-cases/index.md +fullyTranslated: true +--- +# Technical use cases + +In your application you will be signing different documents from many sources. How can your application process such documents in order for them to be recognized by the Box Sign service? + +A signature request can have multiple requirements, or inputs, beyond the traditional signature, such as name, date, and initials. These inputs are called signature properties. The Box Sign service needs to know where to place these inputs in the document, and how to recognize them. + +The first step is to consider if the document has the necessary information for the Box Sign service to recognize the signature properties. + +If not, then the [document is unstructured][unstructured-docs], and should be prepared before sending the signature request. This is called document preparation, and is an extra step automatically created by the Box Sign service. + +There are two other types of documents that already have the necessary information for the Box Sign service to recognize the signature properties. The [sign templates][sign-templates], managed in the Box application, and the [structured documents][sign-structured-docs], which are typically generated documents, containing specific tags representing the signature properties. + + + +Signing unstructured docs + + + +[unstructured-docs]: page://sign/technical-use-cases/sign-unstructured-docs + +[sign-templates]: page://sign/technical-use-cases/sign-template + +[sign-structured-docs]: page://sign/technical-use-cases/sign-structured-docs diff --git a/pages/sign/technical-use-cases/sign-structured-docs.md b/pages/sign/technical-use-cases/sign-structured-docs.md new file mode 100644 index 000000000..801a74d1e --- /dev/null +++ b/pages/sign/technical-use-cases/sign-structured-docs.md @@ -0,0 +1,566 @@ +--- +centered: true +rank: 3 +category_id: sign +subcategory_id: sign/20-technical-use-cases +is_index: false +id: sign/technical-use-cases/sign-structured-docs +type: page +total_steps: 3 +sibling_id: sign/technical-use-cases +parent_id: sign/technical-use-cases +next_page_id: sign/technical-use-cases +previous_page_id: sign/technical-use-cases/sign-template +source_url: >- + https://github.com/box/developer.box.com/blob/main/content/pages/sign/20-technical-use-cases/30-sign-structured-docs.md +fullyTranslated: true +--- +# Signing structured docs + +A structured document in the context of Box Sign is a document that includes specific tags that can be recognized by the Box Sign API. These tags are used to place the signature properties associated with a specific signer in the document, such as name, date, and signature. + +This allows your app to handle a dynamic generated document that is ready to be signed, which has a couple of advantages: + +* The document can be dynamically generated, and the signature properties can be added to the document before creating the signature request, effectively bypassing the document preparation step. + +* The document format can be handled outside of Box Sign templates, allowing higher flexibility and integration with external document management systems. + +## Anatomy of a structured document + +Here is an example of a structured document, showing the formatting used to place tags in a Microsoft Word document: + +![Using tags in a Microsoft Word document](images/sing-structured-tags-sample.png) + +In the sample above `[[c|1]]` means a checkbox assigned to signer 1, and `[[s| +1]]` means a signature pad assigned to signer 1. Notice how the signature pad is using font size 48 to reserve space vertically for the signature. + +The `[[t|1|id:tag_full_name|n:enter your complete name]]` means a name tag assigned to signer 1, with the label `enter your complete name`, and using an id of `tag_full_name`. + +Check out this [document][support-tags] for a complete description of all the tags available. + +Setting the tags to the same `color` as the background will make them invisible, but they will still be there. + +The number in the tags refer to the signer number, not the signing order, so `[[c|1]]` is the checkbox for signer 1, `[[c|2]]` is the checkbox for signer 2, and so on. + +Tag 0 is reserved for the sender, and always exists. So even if the sender does not need to input any data into the document, the other signers must start with 1. + +## Create a signature request from a structured document + +This is the same as creating a signature request from an unstructured document. At minimum, you will need to specify the document, the receiving folder and the email of the `signer`. + +Since the structured document already contains the signature properties details and location, you can bypass the document preparation. + +This is how the flow would look like, from the generated document, create the signature request and finally sign the document: + +![Signing a structured document](images/sign-flow-tags.png) + +Consider this method: + + + + + +```bash + +curl --location 'https://api.box.com/2.0/sign_requests' \ +--header 'Content-Type: application/json' \ +--header 'Authorization: Bearer nQ...xY' +--data-raw '{ + "source_files": [ + { + "type": "file", + "id": "1363379762284" + } + ], + "parent_folder": { + "id": "234102987614", + "type": "folder" + }, + "signers": [ + { + "email": "signer@example.com", + "role": "signer" + } + ] +}' + +``` + + + + + +```python + +def create_sign_request_structured( + client: Client, file_id: str, signer_email: str +) -> SignRequest: + """Create a sign request with structured data""" + + # Sign request params + source_file = FileBase(id=file_id, type=FileBaseTypeField.FILE) + parent_folder = FolderMini( + id=SIGN_DOCS_FOLDER, type=FolderBaseTypeField.FOLDER + ) + signer = SignRequestCreateSigner(signer_email) + + # Create a sign request + sign_request = client.sign_requests.create_sign_request( + signers=[signer], + parent_folder=parent_folder, + source_files=[source_file], + ) + + return sign_request + +def main(): + ... + + # Create a sign request with structured data + sign_request = create_sign_request_structured( + client, STRUCTURED_DOC, SIGNER_A + ) + check_sign_request(sign_request) + +``` + + + + + +Resulting in (simplified): + + + + + +```json +{ + "is_document_preparation_needed": false, + "signers": [ + { + "email": "sender@example.com", + "role": "final_copy_reader", + }, + { + "email": "signer@example.com", + "role": "signer", + } + ], + "id": "28199d6c-4662-471e-8426-4cbba9affcf1", + "source_files": [ + { + "id": "1363379762284", + "type": "file", + "name": "Box-Dive-Waiver.docx", + } + ], + "parent_folder": { + "id": "234102987614", + "type": "folder", + "name": "signed docs" + }, + "name": "Box-Dive-Waiver.pdf", + "type": "sign-request", + "status": "converting", + "sign_files": { + "files": [ + { + "id": "1393138856442", + "type": "file", + "name": "Box-Dive-Waiver.pdf", + } + ], + }, +} + +``` + + + + + +```yaml + +Simple sign request: 6878e048-e9bd-4fb1-88c6-8e502783e8d0 + Status: converting + Signers: 2 + final_copy_reader: sender@example.com + signer: signer@example.com + Prepare url: None + +``` + + + + + +If you go to the `signer` email inbox, open the email from Box Sign, click on the `Review and Sign` button, you'll see the document with the signature properties in place: + +![Document with the properties in place](images/sign-structured-signing-document.png) + +After completing the process the signed document looks like this: + +![Signed document](images/sign-structured-doc-finished.png) + +## Pre-populate the signature attributes + +If you have an external id in the document tags you can use it to pre-populate their values. For example, you can use the `tag_full_name` to pre-populate the name of the signer. + +See this method: + + + + + +```bash +curl --location 'https://api.box.com/2.0/sign_requests' \ +--header 'Content-Type: application/json' \ +--header 'Authorization: Bearer nQ...xY' +--data-raw '{ + "prefill_tags": [ + { + "document_tag_id": "tag_full_name", + "text_value": "Signer A" + } + ], + "source_files": [ + { + "type": "file", + "id": "1363379762284" + } + ], + "parent_folder": { + "id": "234102987614", + "type": "folder" + }, + "signers": [ + { + "email": "signer@example.com", + "role": "signer" + } + ] +}' + +``` + + + + + +```python + +def create_sign_request_structured_with_prefill( + client: Client, file_id: str, signer_name, signer_email: str +) -> SignRequest: + """Create a sign request with structured data""" + + # Sign request params + source_file = FileBase(id=file_id, type=FileBaseTypeField.FILE) + parent_folder = FolderMini( + id=SIGN_DOCS_FOLDER, type=FolderBaseTypeField.FOLDER + ) + signer = SignRequestCreateSigner(signer_email) + + # tags + tag_full_name = SignRequestPrefillTag( + document_tag_id="tag_full_name", + text_value=signer_name, + ) + + # Create a sign request + sign_request = client.sign_requests.create_sign_request( + signers=[signer], + parent_folder=parent_folder, + source_files=[source_file], + prefill_tags=[tag_full_name], + ) + + return sign_request + +def main(): + ... + + # Create a sign request with name pre populate + sign_request_pre_pop = create_sign_request_structured_with_prefill( + client, STRUCTURED_DOC, "Signer A", SIGNER_A + ) + check_sign_request(sign_request_pre_pop) + +``` + + + + + +Resulting in (simplified): + + + + + +```json + +{ + "is_document_preparation_needed": false, + "redirect_url": null, + "declined_redirect_url": null, + "are_text_signatures_enabled": true, + "signature_color": null, + "is_phone_verification_required_to_view": false, + "email_subject": null, + "email_message": null, + "are_reminders_enabled": false, + "signers": [ + { + "email": "sender@example.com", + "role": "final_copy_reader", + }, + { + "email": "signer@example.com", + "role": "signer", + } + ], + "id": "11ecebc0-a2b2-4c14-a892-3f56333cc4fa", + "prefill_tags": [ + { + "document_tag_id": "tag_full_name", + "text_value": "Signer A", + } + ], + "source_files": [ + { + "id": "1363379762284", + "type": "file", + "name": "Box-Dive-Waiver.docx", + } + ], + "parent_folder": { + "id": "234102987614", + "type": "folder", + "name": "signed docs" + }, + "name": "Box-Dive-Waiver (1).pdf", + "type": "sign-request", + "status": "converting", + "sign_files": { + "files": [ + { + "id": "1393142670032", + "type": "file", + "name": "Box-Dive-Waiver (1).pdf", + } + ], + }, +} + +``` + + + + + +```yaml + +Simple sign request: 7b86e46c-72ba-4568-a6ff-787077cca007 + Status: converting + Signers: 2 + final_copy_reader: sender@example.com + signer: signer@example.com + Prepare url: None + +``` + + + + + +The document now has the name pre-populated: + +![Document ready for sign with the name pre-populated](images/sign-structure-name-pre-pop.png) + +## Extract information from a signed document + +Let's say you want to extract the name of the signer and the other properties from the signed document. This is useful if you need to tie the information from the signature request back into your systems. + +Let's create a method to extract the information from the signed request: + + + + + +```bash + +curl --location 'https://api.box.com/2.0/sign_requests/ +11ecebc0-a2b2-4c14-a892-3f56333cc4fa' \ +--header 'Authorization: Bearer nQ...xY' + +``` + + + + + +```python + +def check_sign_request_by_id(client: Client, sign_request_id: str): + """Check sign request by id""" + sign_request = client.sign_requests.get_sign_request_by_id(sign_request_id) + + print(f"\nSimple sign request: {sign_request.id}") + print(f" Status: {sign_request.status.value}") + + print(f" Signers: {len(sign_request.signers)}") + for signer in sign_request.signers: + print(f" {signer.role.value}: {signer.email}") + for input in signer.inputs: + content_type = input.content_type + value = None + + if content_type == SignRequestSignerInputTypeField.CHECKBOX: + value = input.checkbox_value + elif content_type == SignRequestSignerInputTypeField.TEXT: + value = input.text_value + elif content_type == SignRequestSignerInputTypeField.DATE: + value = input.date_value + + print( + f" {input.type.value}: {value if value is not None else ''}" + ) + + print(f" Prepare url: {sign_request.prepare_url}") + +def main(): + ... + + # Latest sign request + LATEST_SIGN_REQUEST = "7b86e46c-72ba-4568-a6ff-787077cca007" + check_sign_request_by_id(client, LATEST_SIGN_REQUEST) + +``` + + + + + +Resulting in (simplified): + + + + + +```json + +{ + "signers": [ + { + "email": "sender@example.com", + "role": "final_copy_reader", + }, + { + "email": "signer@example.com", + "role": "signer", + "signer_decision": { + "type": "signed", + "finalized_at": "2023-12-19T14:53:10.547Z", + }, + "inputs": [ + { + "document_tag_id": null, + "checkbox_value": true, + "type": "checkbox", + "content_type": "checkbox", + }, + { + "document_tag_id": "tag_full_name", + "text_value": "Signer A", + "type": "text", + "content_type": "text", + }, + { + "document_tag_id": null, + "text_value": "Dec 19, 2023", + "date_value": "2023-12-19", + "type": "date", + "content_type": "date", + }, + { + "document_tag_id": null, + "type": "signature", + "content_type": "signature", + } + ], + } + ], + "id": "11ecebc0-a2b2-4c14-a892-3f56333cc4fa", + "prefill_tags": [ + { + "document_tag_id": "tag_full_name", + "text_value": "Signer A", + } + ], + "source_files": [ + { + "id": "1363379762284", + "type": "file", + "name": "Box-Dive-Waiver.docx", + } + ], + "parent_folder": { + "id": "234102987614", + "type": "folder", + "name": "signed docs" + }, + "name": "Box-Dive-Waiver (1).pdf", + "type": "sign-request", + "signing_log": { + "id": "1393140642252", + "type": "file", + "name": "Box-Dive-Waiver (1) Signing Log.pdf", + }, + "status": "signed", + "sign_files": { + "files": [ + { + "id": "1393142670032", + "type": "file", + "name": "Box-Dive-Waiver (1).pdf", + } + ], + }, +} + +``` + + + + + +```yaml + +Simple sign request: 7b86e46c-72ba-4568-a6ff-787077cca007 + Status: signed + Signers: 2 + final_copy_reader: sender@example.com + signer: signer@example.com + checkbox: True + text: Rui Barbosa + date: 2023-11-15 + signature: + Prepare url: None + +``` + + + + + +## まとめ + +Structured documents are a great way to integrate with external document management systems, creating dynamic documents that are ready for signature. + +If your document signature requirements have a lot of options, you can pre-populate these from another data source and save the user's time, but remember that the user who owns these properties can always change them. + +After the document is signed you can extract the information from the signature request, which is useful if you need to tie it back into your systems. + +[support-tags]: https://support.box.com/hc/en-us/articles/4404085855251-Creating-templates-using-tags diff --git a/pages/sign/technical-use-cases/sign-template.md b/pages/sign/technical-use-cases/sign-template.md new file mode 100644 index 000000000..cdb5a40f2 --- /dev/null +++ b/pages/sign/technical-use-cases/sign-template.md @@ -0,0 +1,653 @@ +--- +centered: true +rank: 2 +category_id: sign +subcategory_id: sign/20-technical-use-cases +is_index: false +id: sign/technical-use-cases/sign-template +type: page +total_steps: 3 +sibling_id: sign/technical-use-cases +parent_id: sign/technical-use-cases +next_page_id: sign/technical-use-cases/sign-structured-docs +previous_page_id: sign/technical-use-cases/sign-unstructured-docs +source_url: >- + https://github.com/box/developer.box.com/blob/main/content/pages/sign/20-technical-use-cases/20-sign-template.md +fullyTranslated: true +--- +# Signing using templates + +A [Box Sign template][template] is a specific type of document that not only contains the text, but also the signature requirements and placement. It is prepared for signing in advance, and as such can be sent directly to the signer or signers. + +Required fields include, for example, the signature pad field, the full name, and the date. + +These fields have an owner, meaning they are populated by a specific signer and cannot be shared between them. They can be `mandatory` or `optional` , and be pre-populated by your application. However even if pre-populated, they can always be changed by the `signer`. + +Within the Box web app, the template not only sets the signature fields, but also the number of signers, the order in which they sign, other roles and recipients such as `approver`, and `final_copy_recipient`, email notification settings, and a few more options. + +For a complete set of options of the signature request please refer to the [request options][request-options] section. + +These templates are exclusively created and managed in the Box Sign web app, and can be used to create signature requests using the API or the web app. + +Let's start by creating a template. + +## Creating a template + +From the Box app navigate to the sign menu on the left, then select templates. + +![Navigating to templates under Box Sign](images/sign-template-navigate.png) + +Then, click on the New Template button, and choose or upload the document from Box. + +![Selecting a document when creating a template](images/sign-template-selecting-template.png) + +For example, drag and drop a date, a name and a signature pad to the template, like so: + +![Adding the signature, name, and date to the template](images/sign-template-signature-props.png) + +Save the template. + +## Identify the template + +In order to work with templates in the Box Sign API we are going to need the `template_id` . Consider this method to list all the templates available to the user: + + + + + +```bash + +curl --location 'https://api.box.com/2.0/sign_templates' \ +--header 'Authorization: Bearer E9...Q0' + +``` + + + + + +```python + +def sign_templates_list(client: Client): + """List all sign templates""" + sign_templates = client.sign_templates.get_sign_templates() + print(f"\nSign templates: {len(sign_templates.entries)}") + for sign_template in sign_templates.entries: + print(f" {sign_template.id} - {sign_template.name}") + +def main(): + """Simple script to demonstrate how to use the Box SDK""" + conf = ConfigOAuth() + client = get_client_oauth(conf) + + user = client.users.get_user_me() + print(f"\nHello, I'm {user.name} ({user.login}) [{user.id}]") + + sign_templates_list(client) + +``` + + + + + +Returns something similar to (simplified): + + + + + +```json + +{ + "limit": 10, + "next_marker": null, + "prev_marker": null, + "entries": [ + { + "type": "sign-template", + "id": "f2ec720d-47a6-4052-8210-9bfa8d6c349c", + "name": "Simple-DOC.pdf", + "parent_folder": { + "id": "157064745449", + "type": "folder", + "name": "My Sign Requests" + }, + "source_files": [ + { + "id": "1393013714313", + "type": "file", + } + ], + "signers": [ + { + "email": "", + "label": "", + "role": "final_copy_reader", + "inputs": [] + }, + { + "email": "", + "label": "Signer", + "role": "signer", + "inputs": [ + { + "document_tag_id": null, + "id": "d02c8e16-5050-475e-b74b-9a952193e4f8", + "type": "date", + "date_value": null, + "content_type": "date", + }, + { + "document_tag_id": null, + "id": "bdcc966e-2ebf-4b3b-aaee-99d4e1161a9e", + "type": "text", + "text_value": null, + "is_required": true, + "content_type": "full_name", + }, + { + "document_tag_id": null, + "id": "1a8f4cb1-5c09-46bd-96f5-0ab449f19640", + "type": "signature", + "text_value": null, + "is_required": true, + "content_type": "signature", + } + ] + } + ], + } + ] +} + +``` + + + + + +```yaml + +Hello, I'm Rui Barbosa [18622116055] + +Sign templates: 1 + 94e3815b-f7f5-4c2c-8a26-e9ba5c486031 - Simple-PDF.pdf + +``` + + + + + +## Creating a signature request from a template + +The big advantage of using templates is that we do not need to worry about document preparation. Most of the signature options can be set in the template itself. + +This is how the flow would look like: + +![Signing using a template](images/sign-flow-template.png) +Using a signature template, create the signature request, and finally sign the document. + +See this example: + + + + + +```bash + +curl --location 'https://api.box.com/2.0/sign_requests' \ +--header 'Content-Type: application/json' \ +--header 'Authorization: Bearer E9...Q0' +--data-raw '{ + "template_id":"f2ec720d-47a6-4052-8210-9bfa8d6c349c", + "parent_folder": { + "id": "234102987614", + "type": "folder" + }, + "signers": [ + { + "email": "signer@example.com", + "role": "signer" + } + ] +}' + +``` + + + + + +```python + +def create_sign_request(client: Client, template_id: str, signer_email: str): + """Create sign request from template""" + parent_folder = FolderMini( + id=SIGN_DOCS_FOLDER, type=FolderBaseTypeField.FOLDER + ) + + signer = SignRequestCreateSigner( + email=signer_email, + ) + + sign_request = client.sign_requests.create_sign_request( + signers=[signer], + parent_folder=parent_folder, + template_id=template_id, + ) + + return sign_request + +def main(): + ... + + # Create sign request from template + sign_request = create_sign_request(client, TEMPLATE_SIMPLE, SIGNER_A) + check_sign_request(sign_request) + +``` + + + + + +Resulting in (simplified): + + + + + +```json + +{ + "signers": [ + { + "email": "sender@example.com", + "role": "final_copy_reader", + }, + { + "email": "signer@example.com", + "role": "signer", + } + ], + "id": "71e86670-5850-44cc-8b4d-9f5eab6c04de", + "parent_folder": { + "id": "234102987614", + "type": "folder", + "name": "signed docs" + }, + "name": "Simple-DOC (1).pdf", + "type": "sign-request", + "status": "created", + "sign_files": { + "files": [ + { + "id": "1393030489686", + "type": "file", + "name": "Simple-DOC (1).pdf", + } + ], + }, + "template_id": "f2ec720d-47a6-4052-8210-9bfa8d6c349c" +} + +``` + + + + + +```yaml + +Simple sign request: b25674a2-540b-4201-ae18-a78f05ef1a9a + Status: created + Signers: 2 + final_copy_reader: sender@example.com + signer: signer@example.com + Prepare url: None + +``` + + + + + +The signer receives an email from Box.com with a link to the document, and can sign it. + + + +Since the template already had the signature requirements, document preparation was not needed. Notice the date was automatically populated with the current date. + + + +## Pre-populate the signature attributes + +From a usability perspective, it is a good idea to pre-populate the inputs you require from your users. + + + +Some inputs may be intentionally left unpopulated. For example, when your legal department specifies that the “Yes, I agree” field must be explicitly set by the signer. + + + +Using the Box app sign template editor, you can assign an `external_id` to each of the inputs, and have the app populate them from any data source. + +Let’s implement this for the name. + +Go back to the template design and add an id to the name field: + +![Assigning a tag id to a signature property input](images/sign-template-add-id-to-name-prop.png) + +Save the template. + +Let’s create a new method to pre-populate the name: + + + + + +```bash + +curl --location 'https://api.box.com/2.0/sign_requests' \ +--header 'Content-Type: application/json' \ +--header 'Authorization: Bearer E9..Q0' +--data-raw '{ + "template_id": "f2ec720d-47a6-4052-8210-9bfa8d6c349c", + "parent_folder": { + "id": "234102987614", + "type": "folder" + }, + "signers": [ + { + "email": "signer@example.com", + "role": "signer" + } + ], + "prefill_tags": [ + { + "document_tag_id": "signer_full_name", + "text_value": "Signer A" + } + ] +}' + +``` + + + + + +```python + +def create_sign_request_name_default( + client: Client, template_id: str, signer_name, signer_email: str +): + """Create sign request from template""" + parent_folder = FolderMini( + id=SIGN_DOCS_FOLDER, type=FolderBaseTypeField.FOLDER + ) + + signer = SignRequestCreateSigner( + email=signer_email, + ) + + # tags + tag_full_name = SignRequestPrefillTag( + document_tag_id="signer_full_name", + text_value=signer_name, + ) + + sign_request = client.sign_requests.create_sign_request( + signers=[signer], + parent_folder=parent_folder, + prefill_tags=[tag_full_name], + template_id=template_id, + ) + + return sign_request + +def main(): + ... + + # Create sign request from template with name + sign_request_name = create_sign_request_name_default( + client, TEMPLATE_SIMPLE, "Signer A", SIGNER_A + ) + check_sign_request(sign_request_name) + +``` + +Resulting in (simplified): + + + + + + + + + +```json +{ + "signers": [ + { + "email": "sender@example.com", + "role": "final_copy_reader", + }, + { + "email": "signer@example.com", + "role": "signer", + "is_in_person": false, + } + ], + "id": "6f42a041-7ed8-4e08-9958-78a97259f80d", + "prefill_tags": [ + { + "document_tag_id": "signer_full_name", + "text_value": "Signer A", + } + ], + "parent_folder": { + "id": "234102987614", + "type": "folder", + "name": "signed docs" + }, + "name": "Simple-DOC (2).pdf", + "type": "sign-request", + "status": "created", + "sign_files": { + "files": [ + { + "id": "1393047116817", + "type": "file", + "name": "Simple-DOC (2).pdf", + } + ], + }, + "template_id": "f2ec720d-47a6-4052-8210-9bfa8d6c349c" +} + +``` + + + + + +```yaml + +Simple sign request: adab1740-eeba-4392-a3f5-defddc79c946 + Status: created + Signers: 2 + final_copy_reader: sender@example.com + signer: signer@example.com + Prepare url: None + +``` + + + + + +Open the signer inbox and complete the sign request. + +![Signing the document](images/sign-template-name-populated.png) + +When the signer views the document, the `signer` can still change it. + +## Get more information about a template + +You've seen that you can list the templates available to a user. But you can also get more information about a specific template. + +Let’s create a method that returns basic information of a template, but details all the signature requirements: + + + + + +```bash + +curl --location 'https://api.box.com/2.0/sign_templates/ +f2ec720d-47a6-4052-8210-9bfa8d6c349c' \ +--header 'Authorization: Bearer OL..BQ' + +``` + + + + + +```python + +def sign_template_print_info(client: Client, template_id: str): + sign_template = client.sign_templates.get_sign_template_by_id(template_id) + print(f"\nSign template: {sign_template.id} - {sign_template.name}") + print(f" Signers: {len(sign_template.signers)}") + for signer in sign_template.signers: + print(f" {signer.role.value}") + if len(signer.inputs) > 0: + print(" Tag ID\t Type\t Required") + for input in signer.inputs: + print( + f" {input.document_tag_id} {input.type.value} {input.is_required}" + ) + +def main(): + ... + + # Print sign template details + sign_template_print_info(client, TEMPLATE_SIMPLE) + +``` + +Resulting in (simplified): + + + + + + + + + +```json + +{ + "type": "sign-template", + "id": "f2ec720d-47a6-4052-8210-9bfa8d6c349c", + "name": "Simple-DOC.pdf", + "parent_folder": { + "id": "234102987614", + "type": "folder", + "name": "signed docs" + }, + "source_files": [ + { + "id": "1393013714313", + "type": "file", + } + ], + "signers": [ + { + "email": "", + "label": "", + "role": "final_copy_reader", + }, + { + "email": "", + "label": "Signer", + "role": "signer", + "inputs": [ + { + "document_tag_id": null, + "id": "d02c8e16-5050-475e-b74b-9a952193e4f8", + "type": "date", + "is_required": true, + "date_value": null, + "content_type": "date", + }, + { + "document_tag_id": "signer_full_name", + "id": "bdcc966e-2ebf-4b3b-aaee-99d4e1161a9e", + "type": "text", + "text_value": null, + "is_required": true, + "content_type": "full_name", + }, + { + "document_tag_id": null, + "id": "1a8f4cb1-5c09-46bd-96f5-0ab449f19640", + "type": "signature", + "is_required": true, + "content_type": "signature", + } + ] + } + ], +} + +``` + + + + + +```yaml + +Sign template: 94e3815b-f7f5-4c2c-8a26-e9ba5c486031 - Simple-PDF.pdf + Signers: 2 + final_copy_reader + signer + Tag ID Type Required + None date True + signer_full_name text True + None signature True + +``` + + + + + + + +Notice that the `signer_full_name` is the `tag_id` we used to pre-populate the name. + + + +## まとめ + +Templates are a form of signing structured documents where the signature requirements are already defined and placed on the document. + +This not only keeps your contract management team happy, but it also creates a process which is consistent and requires a low level of effort from your users. + +Finally if your document signature requirements have a lot of options, you can pre-populate these from another data source and save the user some time. Remember that the user who owns these properties can always change them. + +There is no API entry point to create a template, so you will have to create and manage them manually from the Box app, unless the document already includes signature tags that can be used by the Box Sign engine. Take a look at our [Structured Docs][structured-docs] section for more information. + +[template]: https://support.box.com/hc/en-us/sections/21356768117651-Templates + +[request-options]: page://sign/request-options + +[structured-docs]: page://sign/technical-use-cases/sign-structured-docs diff --git a/pages/sign/technical-use-cases/sign-unstructured-docs.md b/pages/sign/technical-use-cases/sign-unstructured-docs.md new file mode 100644 index 000000000..3ecd0858d --- /dev/null +++ b/pages/sign/technical-use-cases/sign-unstructured-docs.md @@ -0,0 +1,194 @@ +--- +centered: true +rank: 1 +category_id: sign +subcategory_id: sign/20-technical-use-cases +is_index: false +id: sign/technical-use-cases/sign-unstructured-docs +type: page +total_steps: 3 +sibling_id: sign/technical-use-cases +parent_id: sign/technical-use-cases +next_page_id: sign/technical-use-cases/sign-template +previous_page_id: '' +source_url: >- + https://github.com/box/developer.box.com/blob/main/content/pages/sign/20-technical-use-cases/10-sign-unstructured-docs.md +fullyTranslated: true +--- +# Signing unstructured docs + +Imagine a document management app, where users can upload a document and ask anyone to sign it. In this case your app will know what document to sign and who needs to sign, but it has no idea where to put the signature or its properties like name, date, initial, and so on. + +This contrasts with [using templates][sign-templates] or [structured documents][structured documents] [sign-structured-docs][sign-structured-docs] where your app knows what they are, and where the signature properties go. + +In these cases, and because each document can have a different structure, it is a good idea to always set the `is_document_preparation_needed` flag set to `true`, so that the sender has a chance to select and place the signature properties in the document before the signer gets the request. + +There are three steps to this flow, creating the signature request, then preparing the document, and finally signing it. This is how the flow looks like: +![Sign unstructured docs flow](images/unstructured-docs-flow.png) + +Consider this example: + + + + + +```bash +curl --location 'https://api.box.com/2.0/sign_requests' \ +--header 'Content-Type: application/json' \ +--header 'Authorization: Bearer ' +--data-raw '{ + "is_document_preparation_needed": true, + "parent_folder": { + "id": "234102987614", + "type": "folder" + }, + "source_files": [ + { + "id": "1355143830404", + "type": "file" + } + ], + "signers": [ + { + "email": "signer@example.com", + "role": "signer" + } + ] +}' + +``` + + + + + +```python + +def sign_doc_single( + client: Client, + document_id: str, + destination_folder_id: str, + signer_email: str, + prep_needed: bool = False, +) -> SignRequest: + # Sign request params + source_file = FileBase(id=document_id, type=FileBaseTypeField.FILE) + destination_folder = FolderMini( + id=destination_folder_id, type=FolderBaseTypeField.FOLDER + ) + signer = SignRequestCreateSigner(signer_email) + # sign document + sign_request = client.sign_requests.create_sign_request( + signers=[signer], + parent_folder=destination_folder, + source_files=[source_file], + is_document_preparation_needed=prep_needed, + ) + + return sign_request + +def main(): + conf = ConfigOAuth() + client = get_client_oauth(conf) + + # Simple sign a pdf request with preparation + sign_pdf_prep = sign_doc_single( + client, SIMPLE_PDF, SIGN_DOCS_FOLDER, SIGNER_A, True + ) + + if sign_pdf_prep.prepare_url is not None: + open_browser(sign_pdf_prep.prepare_url) + +``` + + + + + +This results in a signature request with a prepare document URL (simplified): + + + + + +```json + +{ + "is_document_preparation_needed": true, + "signers": [ + { + "email": "requester@example.com", + "role": "final_copy_reader", + }, + { + "email": "signer@example.com", + "role": "signer", + } + ], + "id": "348decab-48a8-4f2c-9436-8967afebf7bb", + "prepare_url": "https://app.box.com/sign/document/xyz-abc-123/.../prepare_doc/", + "source_files": [ + { + "id": "1355143830404", + "type": "file", + } + ], + "parent_folder": { + "id": "234102987614", + "type": "folder", + }, + "name": "Simple-PDF.pdf", + "type": "sign-request", + "status": "converting", + "sign_files": { + "files": [ + { + "id": "1381301154812", + "type": "file", + } + ], + "is_ready_for_download": true + }, + "template_id": null +} + +``` + + + + + +```yaml + +Simple sign request with prep: xyz-abc-123 + Status: converting + Signers: signer@example.com +Prepare url: https://app.box.com/sign/document/xyz-abc-123/.../prepare_doc/ + +``` + + + + + +Notice in the above script that, if a prepare document URL was generated by the signature request, then the app opens a browser for it. The requester can then apply the different signature properties, for example: + +![Preparing the document using drag and drop on the template editor](images/sign-pdf-prep-doc.png) + +Once the document is prepared, the requester can send the signature request to the signer. + +Back in the Box app you can see the status `In Progress`. + +![Pending signature request](images/sign-request-pending.png) + +The signer then receives an email from Box with a link to the signature request. + +![Signing the document](images/sign-pdf-prep-finish-sign.png) + +When the process is completed, both a signature log containing metadata and the signed document are stored in the destination folder. + +![Log and signed document](images/sign-pdf-signed-docs.png) + +[sign-templates]: page://sign/technical-use-cases/sign-template + +[sign-structured-docs]: page://sign/technical-use-cases/sign-structured-docs diff --git a/pages/sign/webhooks/index.md b/pages/sign/webhooks/index.md new file mode 100644 index 000000000..3e20dda61 --- /dev/null +++ b/pages/sign/webhooks/index.md @@ -0,0 +1,39 @@ +--- +centered: true +rank: 40 +related_guides: + - webhooks/v2/create-v2 + - webhooks/triggers + - webhooks/v2 +category_id: sign +subcategory_id: sign/40-webhooks +is_index: true +id: sign/webhooks +type: page +total_steps: 0 +sibling_id: sign +parent_id: sign +next_page_id: '' +previous_page_id: '' +source_url: >- + https://github.com/box/developer.box.com/blob/main/content/pages/sign/40-webhooks/index.md +fullyTranslated: true +--- +# Sign webhooks + +Sign webhooks allow you to receive notifications about events that happen with the signature requests. You can use them to trigger actions in your own application, or to notify your users about events that happen in Sign. + +This is particularly important since the signature requests are asynchronous, and the signers can interact with them at any time, possibly outside of your application. + +## Sign related events + +There are Sign related events that can trigger the webhooks. Like most of Box events the listeners are set at folder or document level. + +The most common use case is to listen to the events at the folder where the sign requests are created. This way you can listen to all the signature requests created in that folder. + +Some examples of events that can be listened to are: + +* `SIGN_REQUEST.COMPLETED`, when a signature request is completed. +* `SIGN_REQUEST.DECLINED`, when a signature request is declined. +* `SIGN_REQUEST.EXPIRED`, when a signature request expires. +* `SIGN_REQUEST.SIGNER_EMAIL_BOUNCED`, when a signer's email is bounced.