> ## Documentation Index
> Fetch the complete documentation index at: https://docs.formabledocs.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Docusign → Embedded signing

> Migrate Docusign embedded signing (envelopes, recipient views) to the Formable API.

This guide helps you move a Docusign embedded signing integration to Formable. You still create a send, mint a recipient signing URL, embed it, and download the completed PDF. You drop OAuth account paths, `clientUserId`, and `returnUrl` redirects in favor of Bearer API keys, a simpler create payload, and webhook- or poll-driven completion.

If you also prepare templates inside your product, migrate that first with [Docusign → Embedded templates](/migrations/docusign/embedded-templates). Formable signing always starts from a prepared template.

<Info>
  New to Formable? Complete the [Embedded signing walkthrough](/walkthroughs/embedded-signing) first, then use this page as a translation layer from Docusign envelopes and recipient views.
</Info>

<Tip>
  Prefer a white-glove migration? Email [matt@formabledocs.com](mailto:matt@formabledocs.com) and we'll handle moving your Docusign integration to the Formable API.
</Tip>

## What you're moving

In Docusign you typically:

1. Authenticate with OAuth and call account-scoped REST paths
2. Create an envelope with a recipient that has a `clientUserId` (embedded / captive signer)
3. Call `EnvelopeViews:createRecipientView` with matching identity fields plus a `returnUrl`
4. Redirect or iframe the view URL (often \~5 minute TTL)
5. Detect completion via Connect / `eventNotification` or the `returnUrl` query event, then download documents

In Formable you:

1. Authenticate with a Bearer API key (`fmbl_…`)
2. Create an **embedded signature request** from a `templateId` with a `signers` array (each with `email`, `name`, and `role`)
3. Mint a `signingUrl` from each signer's `recipientSignatureId` (no `clientUserId`, no `returnUrl`)
4. Load it in a plain iframe (URL lasts **1 hour**)
5. Handle [`document_completed`](/webhooks/events#document_completed) or poll `status`, then download the signed envelope

The product journey stays the same: prepare a document, send it, embed signing, react when done. The API surface is smaller and organization-scoped by the key rather than by `accountId` in the path.

## Recommended order of work

<Steps>
  <Step title="Get a Formable API key">
    Create an organization and key in [Settings](https://app.formabledocs.com/settings). See [Authentication](/authentication). You do not need JWT or Authorization Code exchange for the standard integration.
  </Step>

  <Step title="Migrate templates and field IDs">
    Re-upload documents and place fields in Formable. If you embed template editing, follow [Embedded templates migration](/migrations/docusign/embedded-templates).
  </Step>

  <Step title="Replace Envelopes:create">
    Map template roles and tab values to `signers`, `sender`, and optional `fields`.
  </Step>

  <Step title="Replace createRecipientView">
    Call create signing URL; drop `clientUserId`, `returnUrl`, and `authenticationMethod`.
  </Step>

  <Step title="Swap Connect for Formable webhooks">
    Register one org webhook URL and verify `Content-Sha256`. See [Webhooks](/webhooks/overview).
  </Step>
</Steps>

## What's similar

Several Docusign ideas transfer directly:

* A reusable **template** still backs many sends.
* You still create a send unit (envelope → **signature request**), then open a short-lived URL for the signer.
* Prefill / tab values still happen at send time; Formable uses `fields: [{ fieldId, value }]`.
* Demo / non-billing traffic maps to `testMode: true` (instead of relying only on a demo account). Test mode documents are watermarked and are not legally binding.
* After completion you still fetch a combined signed PDF.

If your Docusign flow is "create envelope from template → create recipient view → iframe → Connect → download," you are remapping objects and removing embedded-signer bookkeeping, not redesigning the user journey.

## What's different

These Docusign-specific pieces do not carry over:

| Area            | Docusign                                                     | Formable                                                                    |
| --------------- | ------------------------------------------------------------ | --------------------------------------------------------------------------- |
| Auth            | OAuth access token + `/accounts/{accountId}/...`             | Bearer `fmbl_…`; no `accountId` in the path                                 |
| Embedded marker | Recipient `clientUserId`                                     | Embedded by default once you mint a `signingUrl`                            |
| View request    | Match email / userName / `clientUserId`; require `returnUrl` | POST create URL with the signer's `recipientSignatureId`                    |
| Completion UX   | Often `returnUrl` redirect with an `event` query param       | `onSigningComplete` iframe message for UI; confirm with webhooks or polling |
| View TTL        | Commonly \~5 minutes                                         | **1 hour**                                                                  |
| Webhooks        | Connect / `eventNotification`, `X-DocuSign-Signature-1`      | Org-level URL, `Content-Sha256`                                             |
| Roles           | `templateRoles` / `roleName`                                 | `signers[].role` (match template field roles)                               |

You no longer maintain a parallel "captive signer" identity. Create the request when you're ready to send, mint the URL when the user is ready to sign, and listen for completion out of band.

## Concept map

| Docusign                      | Formable                                     | Notes                                                                      |
| ----------------------------- | -------------------------------------------- | -------------------------------------------------------------------------- |
| OAuth access token            | API key (`Authorization: Bearer fmbl_…`)     | No JWT / Auth Code for the standard integration.                           |
| Account (`accountId`)         | Organization                                 | Implied by the API key.                                                    |
| Envelope                      | Signature request                            | Formable's send unit.                                                      |
| Recipient + `clientUserId`    | `signers[]` with `email`, `name`, and `role` | Embedded by default — no `clientUserId`. Save each `recipientSignatureId`. |
| Recipient view URL            | `signingUrl`                                 | Expires after **1 hour** (Docusign \~5 minutes).                           |
| `returnUrl`                   | `onSigningComplete` `postMessage`            | Close the iframe from the client event; confirm via webhooks or polling.   |
| Connect / `eventNotification` | Webhooks                                     | Org-level URL + `Content-Sha256`.                                          |
| Envelope `completed`          | `document_completed` / status `Completed`    | Then fetch the signed PDF.                                                 |

## Endpoint map

| Docusign                                          | Formable                                                                                         |
| ------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| `POST /v2.1/accounts/{accountId}/envelopes`       | [`POST /v1/signature-requests/embedded`](/api-reference/endpoint/create-signature-request)       |
| `POST .../envelopes/{envelopeId}/views/recipient` | [`POST /v1/recipient-signatures/{id}/url`](/api-reference/endpoint/create-signing-url)           |
| Get document / combined PDF                       | [`GET /v1/signature-requests/{id}/signed-envelope`](/api-reference/endpoint/get-signed-envelope) |
| Connect / `eventNotification`                     | Webhook URL in [Settings](https://app.formabledocs.com/settings)                                 |

## Auth

Docusign:

```bash theme={null}
Authorization: Bearer {access_token}
```

against `/restapi/v2.1/accounts/{accountId}/...`.

Formable:

```bash theme={null}
curl https://api.formabledocs.com/v1/signature-requests \
  --header "Authorization: Bearer fmbl_YOUR_API_KEY"
```

No `accountId` in the path. Create the key in [Settings](https://app.formabledocs.com/settings) and keep it on the server. Full details: [Authentication](/authentication).

## Migrate the flow

### 1. Create the signature request (was: create envelope)

**Docusign** (simplified):

```json theme={null}
{
  "templateId": "DOCUSIGN_TEMPLATE_ID",
  "templateRoles": [
    {
      "email": "jane@example.com",
      "name": "Jane Doe",
      "roleName": "Signer",
      "clientUserId": "1000",
      "tabs": {
        "textTabs": [
          { "tabLabel": "company", "value": "Acme Corporation" }
        ]
      }
    }
  ],
  "status": "sent"
}
```

**Formable:**

```bash theme={null}
curl --request POST \
  --url https://api.formabledocs.com/v1/signature-requests/embedded \
  --header "Authorization: Bearer $TOKEN" \
  --header 'Content-Type: application/json' \
  --data '{
    "templateId": "abc123xyz",
    "signers": [
      { "email": "jane@example.com", "name": "Jane Doe", "role": "Signer" }
    ],
    "sender": { "email": "you@yourcompany.com", "name": "Your Company" },
    "fields": [
      { "fieldId": "field_company_name", "value": "Acme Corporation" }
    ],
    "testMode": true
  }'
```

```json Response theme={null}
{
  "signatureRequestId": "sr_456def",
  "signers": [
    {
      "email": "jane@example.com",
      "name": "Jane Doe",
      "recipientSignatureId": "rsig_789ghi"
    }
  ]
}
```

Pass a `signers` array on every create. Each signer needs `email`, `name`, and `role`. `sender` is optional and defaults to the org owner. Map tab / merge values to `fields` using Formable `fieldId`s from the template editor (not Docusign `tabLabel`s). Save each signer's `recipientSignatureId` to mint their signing URL.

| Docusign                         | Formable                                            |
| -------------------------------- | --------------------------------------------------- |
| `templateId`                     | `templateId`                                        |
| `templateRoles[].email` / `name` | `signers[].email` / `name`                          |
| `roleName`                       | `signers[].role`                                    |
| `clientUserId`                   | Omit                                                |
| Tab values on the role           | `fields: [{ fieldId, value }]`                      |
| `status: "sent"`                 | Create, then mint the URL when ready                |
| Demo account testing             | `testMode: true` (watermarked, not legally binding) |

### 2. Create the signing URL (was: recipient view)

**Docusign:**

```bash theme={null}
POST /v2.1/accounts/{accountId}/envelopes/{envelopeId}/views/recipient
```

```json theme={null}
{
  "returnUrl": "https://yourapp.com/signing-complete",
  "authenticationMethod": "none",
  "email": "jane@example.com",
  "userName": "Jane Doe",
  "clientUserId": "1000"
}
```

**Formable:**

```bash theme={null}
curl --request POST \
  --url https://api.formabledocs.com/v1/recipient-signatures/rsig_789ghi/url \
  --header "Authorization: Bearer $TOKEN"
```

```json Response theme={null}
{
  "signingUrl": "https://app.formabledocs.com/sign/embedded/xyz789abc",
  "expiresAt": "2024-01-16T10:30:00.000Z"
}
```

No `clientUserId`, `returnUrl`, or `authenticationMethod`. You do not re-send the signer's email and name on the URL call — pass their `recipientSignatureId` from the create response. Formable URLs last **1 hour**. Creating a URL for an already completed request returns `409`.

### 3. Embed on the client

```html theme={null}
<iframe
  src="https://app.formabledocs.com/sign/embedded/xyz789abc"
  width="100%"
  height="800"
  allow="fullscreen"
  style="border: none;"
></iframe>
```

```javascript theme={null}
window.addEventListener("message", (event) => {
  if (event.origin !== "https://app.formabledocs.com") return;
  if (!event.data || typeof event.data !== "object") return;

  if (event.data.type === "onSigningComplete") {
    // signer finished — close the iframe or show success
  }
});
```

Use `onSigningComplete` instead of a Docusign `returnUrl` redirect for client UX. Confirm completion with [`document_completed`](/webhooks/events#document_completed) or by polling `status` until `Completed` before downloading. See [Embedded signing](/walkthroughs/embedded-signing#detect-completion).

### 4. Download the signed PDF

```bash theme={null}
curl --request GET \
  --url https://api.formabledocs.com/v1/signature-requests/sr_456def/signed-envelope \
  --header "Authorization: Bearer $TOKEN"
```

```json Response theme={null}
{
  "signedEnvelopePresignedUrl": "https://s3.amazonaws.com/bucket/signed-envelope.pdf?..."
}
```

Webhook verification uses `Content-Sha256` instead of `X-DocuSign-Signature-1`. See [Verifying webhooks](/webhooks/verifying-webhooks) and [Webhooks overview](/webhooks/overview).

## Differences to plan for

<AccordionGroup>
  <Accordion title="API keys instead of OAuth">
    Drop JWT / Auth Code token exchange for a Bearer API key on your server. The organization is implied by the key, so paths omit `accountId`.
  </Accordion>

  <Accordion title="No clientUserId">
    Embedded is the default. Create the request, then mint the URL when the user is ready. You do not mark recipients as captive at create time.
  </Accordion>

  <Accordion title="No returnUrl redirect">
    Listen for `onSigningComplete` to update the client immediately. Confirm with a webhook or poll before downloading, then build any "signing finished" screen in your own app.
  </Accordion>

  <Accordion title="Longer-lived signing URLs">
    Plan refresh logic around a **1 hour** TTL instead of Docusign's shorter recipient-view window. Still mint just in time; don't store URLs for later sessions.
  </Accordion>
</AccordionGroup>

## Checklist

<Steps>
  <Step title="Create a Formable API key">
    In [Settings](https://app.formabledocs.com/settings).
  </Step>

  <Step title="Prepare templates and field IDs">
    Or migrate the [embedded template flow](/migrations/docusign/embedded-templates) separately.
  </Step>

  <Step title="Replace Envelopes:create">
    Use create embedded signature request with `signers` (including `role`), optional `sender`, and optional `fields`.
  </Step>

  <Step title="Replace createRecipientView">
    Call create signing URL with each signer's `recipientSignatureId`; drop `clientUserId`, `returnUrl`, and `authenticationMethod`.
  </Step>

  <Step title="Swap Connect for Formable webhooks">
    Handle `document_completed` and download the signed envelope.
  </Step>
</Steps>

## Next steps

<CardGroup cols={2}>
  <Card title="Embedded templates migration" icon="file-lines" href="/migrations/docusign/embedded-templates">
    Map Docusign template edit views to Formable.
  </Card>

  <Card title="Embedded signing walkthrough" icon="window-maximize" href="/walkthroughs/embedded-signing">
    Full Formable signing walkthrough.
  </Card>

  <Card title="Webhooks" icon="bell" href="/webhooks/overview">
    Register endpoints and understand delivery.
  </Card>

  <Card title="Authentication" icon="key" href="/authentication">
    Bearer `fmbl_` API keys.
  </Card>
</CardGroup>
