# Blueink eSignature API — Full Documentation
> Blueink is an eSignature platform. APIv2 is a RESTful JSON API for creating and sending Bundles (signature requests), managing Document Templates, embedding signing and preparation experiences, and receiving webhooks. This documentation is indexed here for AI agents.
---
Source: https://developer.blueink.com/docs/api/add-bundle-tags/
# Add Tags to a bundle
**PUT** `/bundles/{bundleSlug}/add_tags/`
Add additional tags to a Bundle. No existing tags on the Bundle are removed. The result
of this call is that Bundle.tags is the union of the set of previous tags with the set of new tags.
Duplicate tags are ignored.
## Request
### Parameters
- `bundleSlug` (path, required, string): The slug that uniquely identifies the Bundle
### Request Body
- `application/json` — (object)
### Responses
- `200`: The modified Bundle
- Content types: `application/json`
- `400`: Bad Request
- Content types: `application/json`
- `404`: Not found response
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/
# Blueink API v2
# Overview
This document contains the detailed specification for version 2 of the Blueink eSignature API.
If just starting with the Blueink API, you might want to checkout the How-to Guides
and Guides that supplement this API specification.
> **Try it sends live requests**
>
>
> The interactive **Try it** panel sends real requests to the production API
> (`https://api.blueink.com`). Requests can create billable, legally-binding
> signature records and send real emails to signers. Use a test or restricted
> API key, and never run mutating endpoints unless you intend the side effects.
>
## Authentication
#### API Key
Authenticated requests require an `Authorization` header with the value `Token `. Example: `Authorization: Token abcd1234`.
Security Scheme Type:
apiKey
Header parameter name:
Authorization
---
Source: https://developer.blueink.com/docs/api/bundles/
A Bundle is the central object in the Blueink API — it represents one or more
Documents being sent to one or more Signers in a single signing workflow. When
a Bundle is created, it is launched immediately, sending the documents to the
signers for signature.
**Related guides:**
[Send an Envelope with an Uploaded PDF File](/docs/guides/send-envelope-with-uploaded-pdf/) ·
[Send an Envelope with Templates](/docs/guides/send-envelope-with-templates/) ·
[Generate PDFs from HTML](/docs/guides/html-to-pdf/) ·
[Auto Field Placement](/docs/guides/auto-placement/)
```mdx-code-block
import DocCardList from '@theme/DocCardList';
import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
```
---
Source: https://developer.blueink.com/docs/api/cancel-bundle/
# Cancel a Bundle
**PUT** `/bundles/{bundleSlug}/cancel/`
Cancel a Bundle
## Request
### Parameters
- `bundleSlug` (path, required, string): The slug that uniquely identifies the Bundle
### Responses
- `200`: The cancelled Bundle object
- Content types: `application/json`
- `400`: Bad Request
- Content types: `application/json`
- `404`: Not found response
- Content types: `application/json`
- `409`: Cannot cancel the bundle, probably because it is completed
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/check-rate-limit/
# Check Rate Limit Status
**GET** `/rate_limit/`
Check the current rate limit status for your API key. This endpoint provides information
about your current rate limit usage and remaining capacity.
### Responses
- `200`: Rate limit status information
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/create-bundle-from-envelope-template/
# Create a Bundle from an Envelope Template
**POST** `/bundles/create_from_envelope_template/`
Create a Bundle from an Envelope Template
## Request
### Request Body
- `application/json` — BundleTemplateRequest (object) required: envelope_template, packets
### Responses
- `201`: The created Bundle
- Content types: `application/json`
- `400`: Bad Request
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/create-bundle-preparation-session/
# Create an embedded Bundle preparation session
**POST** `/bundles/preparation_session/`
Create a short-lived, single-use URL that hosts the Blueink Bundle
preparation experience inside an iframe in your application. The end
user can upload PDFs, select from your Document Templates, place
fields, configure signers, and submit the prepared Bundle — all
without leaving your app.
At least one document source must be enabled. Set `upload_pdf=true`
to allow the user to upload a PDF, and/or restrict their template
selection by passing `template_ids` or `folder_ids`. To resume work
on an existing Draft Bundle, pass its slug as `draft_bundle`.
The returned `url` is valid until `expires`; load it in an iframe to
start the session.
## Request
### Request Body
- `application/json` — BundlePreparationSessionRequest (object)
### Responses
- `201`: The preparation session was created.
- Content types: `application/json`
- `400`: Bad Request
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/create-bundle/
# Create a Bundle
**POST** `/bundles/`
Create a new Bundle (signing workflow) consisting of one or more Documents and one
or more Signers. The Bundle is launched immediately upon creation, sending the
documents to the signers for signature.
## Document sources
Each Document in the `documents` array can be provided in one of several ways. Specify
exactly one source per document:
- **`file_url`** — a publicly accessible URL of a PDF file that Blueink will download.
- **`file_b64`** — a base64-encoded PDF file embedded directly in the request.
- **`file_html`** — an HTML string that Blueink converts to a PDF and inspects for
form fields. See [Generate PDFs from HTML](/docs/guides/html-to-pdf/).
- **`file_index`** — when uploading files via `multipart/form-data`, the index of the
file in the `files` array. See the multipart request schema below.
To create a Bundle from a pre-built Envelope Template instead, use the
[Create a Bundle from an Envelope Template](/docs/api/create-bundle-from-envelope-template)
endpoint.
## Request
### Request Body
- `application/json` — BundleRequest (object) required: packets, documents
- `multipart/form-data` — (object)
### Responses
- `201`: Returned when the Bundle is successfully created. Note that some Bundle processing (like
parsing tags in documents, or processing large documents) can be time consuming. Therefore
this request return a '201' success message after preliminary data validation has been performed.
At this point, not all documents are guaranteed to have been processed, so it is possible
that Bundle creation could fail with a document processing error. If that is the case,
the error status will be reflected in the Bundle response returned by a subsequent call
to retrieve a Bundle.
Any errors are also reported via webhooks, so your App or integration
does not need to poll to confirm successful Bunde creation.
- Content types: `application/json`
- `400`: Bad Request
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/create-packet-embed-url/
# Create an Embedded Signing URL
**POST** `/packets/{packetId}/embed_url/`
Create a URL which can be used for embedded signing
**Example Websites**
- [JavaScript Example Website](https://js-example.blueink.com)
- [PHP Example Website](https://php-example.blueink.com)
## Request
### Parameters
- `packetId` (path, required, string): The slug that uniquely identifies the Packet
### Responses
- `201`: Created response
- Content types: `application/json`
- `400`: Bad Request
- Content types: `application/json`
- `404`: Not found response
- Content types: `application/json`
- `409`: Cannot get an embedded url for this packet
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/create-person/
# Create a Person
**POST** `/persons/`
Create a Person
## Request
### Request Body
- `application/json` — Person (object)
### Responses
- `201`: The created Person
- Content types: `application/json`
- `400`: Bad Request
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/create-template-preparation-session/
# Create an embedded Document Template preparation session
**POST** `/templates/preparation_session/`
Create a short-lived, single-use URL that hosts the Blueink Document
Template authoring experience inside an iframe in your application.
The end user can upload a PDF, define roles, place fields, and save
the template — all without leaving your app.
Pass `template_id` to open an existing Document Template for
editing. Omit it to start a new-template authoring flow; `team` and
`library` are only applied in that case (they are ignored when
`template_id` is provided).
The returned `url` is valid until `expires`; load it in an iframe to
start the session.
Requires the `API_PREPARE_DOC_TEMPLATE` account feature; the request
returns `403` if the feature is not enabled.
## Request
### Request Body
- `application/json` — TemplatePreparationSessionRequest (object)
### Responses
- `201`: The template preparation session was created.
- Content types: `application/json`
- `400`: Bad Request
- Content types: `application/json`
- `403`: The `API_PREPARE_DOC_TEMPLATE` feature is not enabled for this account.
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/create-webhook-extra-header/
# Create a WebhookExtraHeader
**POST** `/webhooks/headers/`
Create a WebhookExtraHeader
## Request
### Request Body
- `application/json` — WebhookExtraHeader (object)
### Responses
- `201`: The created WebhookExtraHeader
- Content types: `application/json`
- `400`: Bad Request
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/create-webhook/
# Create a Webhook
**POST** `/webhooks/`
Create a Webhook
## Request
### Request Body
- `application/json` — WebhookRequest (object) required: name, url, event_types
### Responses
- `201`: The created Webhook
- Content types: `application/json`
- `400`: Bad Request
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/delete-person/
# Delete a Person
**DELETE** `/persons/{personId}/`
Delete a Person
## Request
### Parameters
- `personId` (path, required, string): The ID that uniquely identifies the Person
### Responses
- `204`: The Person was deleted. No content is returned
- `400`: Bad Request
- Content types: `application/json`
- `404`: Not found response
- Content types: `application/json`
- `409`: Cannot delete the Person, probably because it is associated with live Bundles
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/delete-webhook-extra-header/
# Delete a WebhookExtraHeader
**DELETE** `/webhooks/headers/{webhookExtraHeaderId}/`
Delete a WebhookExtraHeader
## Request
### Parameters
- `webhookExtraHeaderId` (path, required, string): The ID that uniquely identifies the WebhookExtraHeader
### Responses
- `204`: The WebhookExtraHeader was deleted. No content is returned
- `400`: Bad Request
- Content types: `application/json`
- `404`: Not found response
- Content types: `application/json`
- `409`: Cannot delete the WebhookExtraHeader
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/delete-webhook/
# Delete a Webhook
**DELETE** `/webhooks/{webhookId}/`
Delete a Webhook
## Request
### Parameters
- `webhookId` (path, required, string): The ID that uniquely identifies the Webhook
### Responses
- `204`: The Webhook was deleted. No content is returned
- `400`: Bad Request
- Content types: `application/json`
- `404`: Not found response
- Content types: `application/json`
- `409`: Cannot delete the Webhook
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/envelope-templates/
An Envelope Template is a reusable Bundle definition — one or more Documents,
a defined set of Signer roles, and any default settings — that can be instantiated
by providing only the runtime values (signer names, emails, etc.). Use these when
the same multi-document workflow is sent repeatedly. Bundles are created from
Envelope Templates via the
[Create a Bundle from an Envelope Template](/docs/api/create-bundle-from-envelope-template)
endpoint.
```mdx-code-block
import DocCardList from '@theme/DocCardList';
import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
```
---
Source: https://developer.blueink.com/docs/api/get-bundle-data/
# Retrieve Bundle Data
**GET** `/bundles/{bundleSlug}/data/`
Get data entered into fields for a completed Bundle
## Request
### Parameters
- `bundleSlug` (path, required, string): The slug that uniquely identifies the Bundle
### Responses
- `200`: Data response
- Content types: `application/json`
- `404`: Not found response
- Content types: `application/json`
- `409`: Files not ready
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/get-bundle-files/
# Retrieve Bundle Files
**GET** `/bundles/{bundleSlug}/files/`
Get downloadable files for a completed Bundle
## Request
### Parameters
- `bundleSlug` (path, required, string): The slug that uniquely identifies the Bundle
### Responses
- `200`: File response
- Content types: `application/json`
- `404`: Not found response
- Content types: `application/json`
- `409`: Files not ready
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/get-packet-coe/
# Retrieve Packet Certificate of Evidence
**GET** `/packets/{packetId}/coe/`
Get a link and checksum of the Certificate of Evidence for this Packet
## Request
### Parameters
- `packetId` (path, required, string): The slug that uniquely identifies the Packet
### Responses
- `200`: COE response
- Content types: `application/json`
- `400`: Bad Request
- Content types: `application/json`
- `404`: Not found response
- Content types: `application/json`
- `409`: COE not available
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/get-person/
# Retrieve a Person
**GET** `/persons/{personId}/`
Retrieve a Person
## Request
### Parameters
- `personId` (path, required, string): The ID that uniquely identifies the Person
### Responses
- `200`: A response with a Person
- Content types: `application/json`
- `404`: Not found response
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/get-webhook-delivery/
# Retrieve a WebhookDelivery
**GET** `/webhooks/deliveries/{webhookDeliveryId}/`
Retrieve a WebhookDelivery
## Request
### Parameters
- `webhookDeliveryId` (path, required, string): The ID that uniquely identifies the WebhookDelivery
### Responses
- `200`: A WebhookDelivery object
- Content types: `application/json`
- `404`: Not found response
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/get-webhook-event/
# Retrieve a WebhookEvent
**GET** `/webhooks/events/{webhookEventId}/`
Retrieve a WebhookEvent
## Request
### Parameters
- `webhookEventId` (path, required, string): The ID that uniquely identifies the WebhookEvent
### Responses
- `200`: A WebhookEvent object
- Content types: `application/json`
- `404`: Not found response
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/get-webhook-extra-header/
# Retrieve a WebhookExtraHeader
**GET** `/webhooks/headers/{webhookExtraHeaderId}/`
Retrieve a WebhookExtraHeader
## Request
### Parameters
- `webhookExtraHeaderId` (path, required, string): The ID that uniquely identifies the WebhookExtraHeader
### Responses
- `200`: A response with a WebhookExtraHeader
- Content types: `application/json`
- `404`: Not found response
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/get-webhook-secret/
# Get Webhook Shared Secret
**GET** `/webhooks/secret/`
Get Webhook Shared Secret
### Responses
- `200`: A response with the secret contained.
- Content types: `application/json`
- `403`: User is not priviliged to view the shared secret.
- `404`: Shared secret has not been generated yet.
---
Source: https://developer.blueink.com/docs/api/get-webhook/
# Retrieve a Webhook
**GET** `/webhooks/{webhookId}/`
Retrieve a Webhook
## Request
### Parameters
- `webhookId` (path, required, string): The ID that uniquely identifies the Webhook
### Responses
- `200`: A response with a Webhook
- Content types: `application/json`
- `404`: Not found response
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/list-bundle-events/
# List Bundle Events
**GET** `/bundles/{bundleSlug}/events/`
Get a list of Events that are associated with the Bundle
## Request
### Parameters
- `bundleSlug` (path, required, string): The slug that uniquely identifies the Bundle
### Responses
- `200`: A list of events associated with this bundle
- Content types: `application/json`
- `404`: Not found response
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/list-bundles/
# List Bundles
**GET** `/bundles/`
Returns a paginated list of Bundles in your Account, ordered by created date (from most recent to
least recent). Pagination can be controlled via Pagination paramaters (see Overview->Pagination).
Querystring filters paramaters can be combined, e.g.
`/bundles/?search=Gibbons&status__in=se,co&tag=needs-attention`. When combining filters, only Bundles
matching ALL the filters are returned.
## Request
### Parameters
- `search` (query, string): A search query. Only bundles matching the search will be returned. The following data in the
the Bundle is searched:
- bundle slug
- bundle label
- bundle custom_key
- signer name
- signer email
- signer phones
E.g. `/bundles/?search=foobar@example.com`
- `status` (query, string): Limit bundles to those with the specified status.
* ne: New - the Bundle was newly created
* dr: Draft - the Bundle has not yet been sent
* pr: Provisioning - the Bundle is being cloned or processed in the background
* pe: Pending - the Bundle is queued to be launched while documents are processing
* se: Sent - the Bundle has been sent, but not yet started by any Signers
* st: Started - at least one Signer has started reviewing the document(s)
* co: Complete - all Signers have completed reviewing / signing
* ca: Cancelled - the Bundle was cancelled
* ex: Expired - the Bundle expired before it was Complete
* fa: Failed - an error occurred and the Bundle could not be created or completed
* de: Declined - at least one Signer declined to sign
E.g. `/bundles/?status=co`
- `status__in` (query, string): Limit bundles to those with one of the specified statuses. Statuses should be comma separated.
E.g. `/bundles/?status=co,se,st`
- `tag` (query, string): Return Bundles that have the given tag. E.g. `/bundles/?tag=some-tag`
- `tag__in` (query, string): Return Bundles that have at least one of the given tags. Tags should be comma separated.
E.g. `/bundles/?tag=some-tag,another-tag`
- `ordering` (query, string): Control the sort order of Bundles. Prefix with "-" to reverse the sort order.
By default Bundles are sorted by "-created", ie the Bundle creation date from most
to least recent.
- `created` (query, string): Retrieve Bundles created within a specified date range
Note: Dates are expressed as YYYY-MM-DD format.
E.g. `/bundles/?created_after=2024-10-01&created_before=2024-10-08`
- `sent` (query, string): E.g. `/bundles/?sent_after=2024-10-01&sent_before=2024-10-08`
- `completed` (query, string): E.g. `/bundles/?completed_after=2024-10-01&completed_before=2024-10-08`
- `template` (query, string): Filter bundles by template ID. Only bundles created from the specified template will be returned.
E.g. `/bundles/?template=a053644f-e371-4883-ac17-534445993346`
### Responses
- `200`: A paged array of Bundles
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/list-envelope-templates/
# List Envelope Templates
**GET** `/envelope-templates/`
Retrieve a paginated list of Envelope Templates available to your account.
Envelope Templates are reusable document workflows that contain predefined documents,
field layouts, signer roles, and configuration settings. They allow you to quickly
generate new bundles with consistent formatting and behavior.
**Filtering:**
- Only enabled templates are returned by default
- Templates are ordered by creation date (newest first)
**Use Cases:**
- Browse available templates for bundle creation
- Integrate template selection into your application
- Audit available document workflows
### Responses
- `200`: Successfully retrieved envelope templates
- Content types: `application/json`
- `401`: Authentication credentials were not provided or are invalid
- Content types: `application/json`
- `403`: You do not have permission to access envelope templates
- Content types: `application/json`
- `429`: Rate limit exceeded
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/list-persons/
# List Persons
**GET** `/persons/`
List Persons
## Request
### Parameters
- `search` (query, string): A search query.
- `email` (query, string): Filter persons by email address. Only persons with the specified email will be returned.
E.g. `/persons/?email=john@example.com`
- `phone` (query, string): Filter persons by phone number. Only persons with the specified phone number will be returned.
E.g. `/persons/?phone=+1234567890`
### Responses
- `200`: A response with a list of Persons
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/list-templates/
# List Document Templates
**GET** `/templates/`
List Document Templates
## Request
### Parameters
- `metadata[key]` (query, string): Filter templates by a metadata value. Replace `key` with the metadata
key name (e.g. `metadata[department]=legal`). Only templates whose
stored metadata contains the matching key/value pair are returned.
Multiple `metadata[key]` filters are ANDed together.
### Responses
- `200`: A response with a list or Document Templates
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/list-webhook-deliveries/
# List WebhookEvents
**GET** `/webhooks/deliveries/`
List WebhookEvents
## Request
### Parameters
- `webhook` (query, string): Only WebhookDeliveries matching the selected webhook ID will be returned.
E.g. `/webhooks/deliveries/?webhook=a053644f-e371-4883-ac17-534445993346`
- `webhook_event` (query, string): Only WebhookDeliveries matching the selected webhook_event ID will be returned.
E.g. `/webhooks/deliveries/?webhook_event=a053644f-e371-4883-ac17-534445993346`
- `event_type` (query, string): Only WebhookDeliveries with webhooks matching the selected event_type or event_types will be returned.
E.g. `/webhooks/deliveries/?event_type=bundle_sent`
E.g. `/webhooks/deliveries/?event_type__in=bundle_error,bundle_cancelled`
- `status` (query, integer): Only WebhookDeliveries matching the selected status will be returned.
E.g. `/webhooks/deliveries/?status=1`
E.g. `/webhooks/deliveries/?status__in=0,1,2`
- `date` (query, string): Only WebhookDeliveries occurring between a date range will be returned.
Note: Dates are expressed as YYYY-MM-DD format.
E.g. `/webhooks/deliveries/?date_after=2022-10-01&date_before=2022-10-31`
### Responses
- `200`: A response with a list of WebhookEvents
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/list-webhook-events/
# List WebhookEvents
**GET** `/webhooks/events/`
List WebhookEvents
## Request
### Parameters
- `webhook` (query, string): Only WebhookEvents matching the selected webhook ID will be returned.
E.g. `/webhooks/events/?webhook=a053644f-e371-4883-ac17-534445993346`
- `event_type` (query, string): Only WebhookEvents with webhooks matching the selected event_type or event_types will be returned.
E.g. `/webhooks/events/?event_type=bundle_sent`
E.g. `/webhooks/events/?event_type__in=bundle_error,bundle_cancelled`
- `status` (query, integer): Only WebhookEvents matching the selected status will be returned.
E.g. `/webhooks/events/?status=1`
E.g. `/webhooks/events/?status__in=0,1,2`
- `success` (query, boolean): Only WebhookEvents matching the selected success status will be returned.
E.g. `/webhooks/events/?success=true`
- `date` (query, string): Only WebhookEvents occurring between a date range will be returned.
Note: Dates are expressed as YYYY-MM-DD format.
E.g. `/webhooks/events/?date_after=2022-10-01&date_before=2022-10-31`
### Responses
- `200`: A response with a list of WebhookEvents
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/list-webhook-extra-headers/
# List WebhookExtraHeaders
**GET** `/webhooks/headers/`
List WebhookExtraHeaders
## Request
### Parameters
- `webhook` (query, string): Only WebhookExtraHeaders matching the selected webhook ID will be returned.
E.g. `/webhooks/headers/?webhook=a053644f-e371-4883-ac17-534445993346`
- `event_type` (query, string): Only WebhookExtraHeaders with webhooks matching the selected event_type or event_types will be returned.
E.g. `/webhooks/headers/?event_type=bundle_sent`
E.g. `/webhooks/headers/?event_type__in=bundle_error,bundle_cancelled`
### Responses
- `200`: A response with a list of WebhookExtraHeaders
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/list-webhooks/
# List Webhooks
**GET** `/webhooks/`
List Webhooks
## Request
### Parameters
- `enabled` (query, boolean): Only Webhooks matching the selected 'enabled' state will be returned.
E.g. `/webhooks/?enabled=true`
- `event_type` (query, string): Only Webhooks matching the selected event_type or event_types will be returned.
E.g. `/webhooks/?event_type=bundle_sent`
E.g. `/webhooks/?event_type__in=bundle_error,bundle_cancelled`
### Responses
- `200`: A response with a list of Webhooks
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/packet/
A Packet represents a single Signer's relationship to a Bundle — their assigned
fields, their place in the signing order, the URL they receive, and their signing
status. Packets are created automatically as part of Bundle creation; this section
covers retrieving and updating individual Packets after the Bundle is sent,
including generating embedded signing URLs and resending notifications.
**Related guides:** [Implement Embedded Signing](/docs/guides/embedded-signing/)
```mdx-code-block
import DocCardList from '@theme/DocCardList';
import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
```
---
Source: https://developer.blueink.com/docs/api/person/
A Person is a saved contact in your Blueink account. Persons can be referenced
as signers when creating a Bundle, eliminating the need to re-enter contact
information for repeat recipients.
```mdx-code-block
import DocCardList from '@theme/DocCardList';
import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
```
---
Source: https://developer.blueink.com/docs/api/rate-limiting/
The Blueink API enforces rate limits per API key. Use this endpoint to inspect
your current rate-limit status (limit, remaining requests, reset time) without
consuming a request against another endpoint.
```mdx-code-block
import DocCardList from '@theme/DocCardList';
import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
```
---
Source: https://developer.blueink.com/docs/api/regenerate-webhook-secret/
# Regenerate Webhook Shared Secret
**POST** `/webhooks/secret/regenerate/`
Regenerate Webhook Shared Secret
### Responses
- `200`: A response with the new secret contained.
- Content types: `application/json`
- `403`: User is not priviliged to regenerate the secret.
---
Source: https://developer.blueink.com/docs/api/remove-bundle-tags/
# Remove Tags from a bundle
**PUT** `/bundles/{bundleSlug}/remove_tags/`
Remove tags from a Bundle. If a tag in the request does not exist on the Bundle, it is ignored.
## Request
### Parameters
- `bundleSlug` (path, required, string): The slug that uniquely identifies the Bundle
### Request Body
- `application/json` — (object)
### Responses
- `200`: The modified Bundle
- Content types: `application/json`
- `400`: Bad Request
- Content types: `application/json`
- `404`: Not found response
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/retrieve-bundle/
# Retrieve a Bundle
**GET** `/bundles/{bundleSlug}/`
Retrieve a Bundle by its slug. Optionally include additional related data such as form field data,
audit events, and downloadable files using the `include` query parameter.
## Using the include parameter
The `include` parameter allows you to fetch related data in a single API call instead of making
separate requests to the `/data`, `/events`, and `/files` endpoints. This can significantly
reduce the number of API calls needed and improve performance.
### Examples:
**Basic bundle retrieval:**
```
GET /api/v2/bundles/abc123/
```
**Include form data only:**
```
GET /api/v2/bundles/abc123/?include=data
```
**Include events and files:**
```
GET /api/v2/bundles/abc123/?include=events,files
```
**Include all additional data:**
```
GET /api/v2/bundles/abc123/?include=data,events,files
```
### Data Availability
- **data**: Only available for completed bundles, unless early data access is enabled for your account
- **events**: Always available for any bundle
- **files**: Only available for completed bundles with final documents ready, unless early file access is enabled
When data or files are not available, the corresponding field will be `null` in the response.
## Request
### Parameters
- `bundleSlug` (path, required, string): The slug that uniquely identifies the Bundle
- `include` (query, string): Comma-separated list of additional data to include in the response.
Allows you to retrieve related information in a single request instead of making separate API calls.
Supported values:
- `data`: Include form field data entered by signers (same as /data endpoint)
- `events`: Include audit events for the bundle (same as /events endpoint)
- `files`: Include downloadable files for the bundle (same as /files endpoint)
Examples:
- `?include=data` - Include only form data
- `?include=events,files` - Include both events and files
- `?include=data,events,files` - Include all additional data
### Responses
- `200`: A Bundle object, optionally with additional included data
- Content types: `application/json`
- `400`: Bad Request - Invalid include parameter values
- Content types: `application/json`
- `404`: Not found response
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/retrieve-envelope-template/
# Retrieve Envelope Template
**GET** `/envelope-templates/{envelopeTemplateId}/`
Retrieve detailed information about a specific Envelope Template by its unique identifier.
This endpoint provides complete details about an Envelope Template, including:
- Template metadata (name, description, creation date)
- Document structure and ordering
- Signer roles and authentication requirements
- Portal configuration (if applicable)
**Use Cases:**
- Get template details before creating a bundle
- Display template information in your application
- Validate template structure and requirements
- Access smart link URL for portal templates
## Request
### Parameters
- `envelopeTemplateId` (path, required, string): The slug that uniquely identifies the Envelope Template
### Responses
- `200`: Successfully retrieved envelope template details
- Content types: `application/json`
- `401`: Authentication credentials were not provided or are invalid
- Content types: `application/json`
- `403`: You do not have permission to access this envelope template
- Content types: `application/json`
- `404`: Envelope template not found
- Content types: `application/json`
- `429`: Rate limit exceeded
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/retrieve-packet/
# Retrieve a Packet
**GET** `/packets/{packetId}/`
Retrieve details for a specific Packet (signer). This endpoint provides information about
the signer including their contact information, signing status, authentication requirements,
and associated Bundle information.
## Request
### Parameters
- `packetId` (path, required, string): The slug that uniquely identifies the Packet
### Responses
- `200`: Packet details
- Content types: `application/json`
- `404`: Not found response
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/retrieve-template/
# Retrieve a Document Template
**GET** `/templates/{templateId}/`
Retrieve a Document Template
## Request
### Parameters
- `templateId` (path, required, string): The ID that uniquely identifies the Template
### Responses
- `200`: A Document Templates
- Content types: `application/json`
- `404`: Not found response
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/send-bundle/
# Send a Bundle
**POST** `/bundles/{bundleSlug}/send/`
Attempt to send a draft or pending Bundle. If successful, the Bundle's status will change to `se` (Sent).
## Request
### Parameters
- `bundleSlug` (path, required, string): The slug that uniquely identifies the Bundle
### Responses
- `200`: The sent Bundle object
- Content types: `application/json`
- `400`: Bad Request
- Content types: `application/json`
- `404`: Not found response
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/send-packet-reminder/
# Send a Reminder
**PUT** `/packets/{packetId}/remind/`
Send a Reminder email or SMS to a Signer. A reminder can only be sent once every hour. The reminder will be sent via the delivery method (email or SMS) and to the email address (or phone number) previously designated for this Packet.
## Request
### Parameters
- `packetId` (path, required, string): The slug that uniquely identifies the Packet
### Responses
- `200`: Ok, the reminder was sent
- Content types: `application/json`
- `400`: Bad Request
- Content types: `application/json`
- `404`: Not found response
- Content types: `application/json`
- `409`: Cannot send a reminder to this packet, probably because the packet is complete (ie, the signer has already finished signing)
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/templates/
A Document Template is a reusable PDF document with predefined field positions
and signer roles. Document Templates let you create Bundles from a known shape
without re-uploading the PDF or re-placing fields each time.
**Related guides:** [Send an Envelope with Templates](/docs/guides/send-envelope-with-templates/)
```mdx-code-block
import DocCardList from '@theme/DocCardList';
import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
```
---
Source: https://developer.blueink.com/docs/api/update-bundle-partial/
# Partially Update a Bundle
**PATCH** `/bundles/{bundleSlug}/`
Partially update selected Bundle fields.
Allowed fields:
- `team`
- `expires`
- `cc_sender`
- `cc_emails`
- `send_reminders`
- `reminder_offset`
- `reminder_interval`
- `reminder_expires`
- `owner`
- `signing_brand`
- `allow_signer_reassign`
- `allow_chained_signer_reassign`
Notes:
- Only Bundles in `dr` (Draft) or `se` (Sent) status can be updated.
- Full updates (`PUT`) are not supported. Use `PATCH`.
- `owner` updates are restricted to account admins.
- `team` updates require the Teams feature.
- Reminder fields require the Reminders feature.
- For Sent (`se`) Bundles, updating `expires` changes the date while preserving the existing time-of-day.
- For Sent (`se`) Bundles, the resulting merged expiration datetime must be in the future.
## Request
### Parameters
- `bundleSlug` (path, required, string): The slug that uniquely identifies the Bundle
### Request Body
- `application/json` — BundlePatchRequest (object)
### Responses
- `200`: The updated Bundle
- Content types: `application/json`
- `400`: Bad Request. Possible causes include:
- invalid or disallowed fields in request body
- Bundle status does not allow updates
- account feature requirements not met (Teams or Reminders)
- invalid owner/team/`expires` value (an unparseable `expires` value
yields 400; previously this could produce a 500)
- for Sent (`se`) Bundles, the merged expiration datetime is not in
the future
- Content types: `application/json`
- `404`: Not found response
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/update-packet/
# Update a Packet
**PATCH** `/packets/{packetId}/`
Update a Packet (aka signer) with a new email, phone number, name or authentication options
The updated packet must still be deliverable. For instance, if you specify a `deliver_via`
value of 'phone', but there was no phone number set in the original PacketRequest, then
this request must include a `phone` as well, or an error will be returned.
You can change a Packet that was originally configured for embedded signing (that is, deliver_via was
'embed') to be delivered via email or SMS. However, no signing notifications or reminders will be
automatically sent. You must call /packet/\{packetId\}/remind/ to send a signing notification email (or SMS).
If this Signer is associated with a Person, the person will be updated as well - the Person name
will be changed (if provided) and any new email or phone number will be added.
## Request
### Parameters
- `packetId` (path, required, string): The slug that uniquely identifies the Packet
### Request Body
- `application/json` — PacketCommon (object)
### Responses
- `200`: Ok, the Packet was updated
- Content types: `application/json`
- `400`: Bad Request
- Content types: `application/json`
- `404`: Not found response
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/update-person-partial/
# Partially update a Person
**PATCH** `/persons/{personId}/`
Partially update the Person with new data.
To add a new email or phone to the Person, include a ContactChannel in the 'channels' array
without an 'id'.
To update an existing ContactChannel associated with the Person, include an 'id'. That existing
ContactChannel will be updated with the new email or phone. This will update any live Bundles
associated with the Person that are sending to that email (or phone).
If a ContactChannel does not include an 'id', but the email (or phone) matches an existing
ContactChannel, then that ContactChannel will not be changed.
## Request
### Parameters
- `personId` (path, required, string): The ID that uniquely identifies the Person
### Request Body
- `application/json` — Person (object)
### Responses
- `200`: The Person was updated
- Content types: `application/json`
- `400`: Bad Request
- Content types: `application/json`
- `404`: Not found response
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/update-person/
# Update a Person
**PUT** `/persons/{personId}/`
Update the Person with new data. NOTE that any contact channels that are omitted from this request will be DELETED. If you don't want to replace all data on the Person, you probably want to use PATCH instead.
## Request
### Parameters
- `personId` (path, required, string): The ID that uniquely identifies the Person
### Request Body
- `application/json` — Person (object)
### Responses
- `200`: The Person was updated
- Content types: `application/json`
- `400`: Bad Request
- Content types: `application/json`
- `404`: Not found response
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/update-template/
# Update a Document Template
**PATCH** `/templates/{templateId}/`
Update writable fields on a Document Template. Currently only `metadata`
is writable via this endpoint; all other fields (name, roles, fields, etc.)
are managed through the Blueink UI or the template preparation session.
## Request
### Parameters
- `templateId` (path, required, string): The ID that uniquely identifies the Template
### Request Body
- `application/json` — (object)
### Responses
- `200`: The updated Document Template.
- Content types: `application/json`
- `400`: Bad Request
- Content types: `application/json`
- `404`: Not found response
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/update-webhook-extra-header-partial/
# Partially update a WebhookExtraHeader
**PATCH** `/webhooks/headers/{webhookExtraHeaderId}/`
Partially update the WebhookExtraHeader with new data.
## Request
### Parameters
- `webhookExtraHeaderId` (path, required, string): The ID that uniquely identifies the WebhookExtraHeader
### Request Body
- `application/json` — WebhookExtraHeader (object)
### Responses
- `200`: The WebhookExtraHeader was updated
- Content types: `application/json`
- `400`: Bad Request
- Content types: `application/json`
- `404`: Not found response
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/update-webhook-extra-header/
# Update a WebhookExtraHeader
**PUT** `/webhooks/headers/{webhookExtraHeaderId}/`
Update the WebhookExtraHeader with new data
## Request
### Parameters
- `webhookExtraHeaderId` (path, required, string): The ID that uniquely identifies the WebhookExtraHeader
### Request Body
- `application/json` — WebhookExtraHeader (object)
### Responses
- `200`: The WebhookExtraHeader was updated
- Content types: `application/json`
- `400`: Bad Request
- Content types: `application/json`
- `404`: Not found response
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/update-webhook-partial/
# Partially update a Webhook
**PATCH** `/webhooks/{webhookId}/`
Partially update the Webhook with new data.
## Request
### Parameters
- `webhookId` (path, required, string): The ID that uniquely identifies the Webhook
### Request Body
- `application/json` — Webhook (object)
### Responses
- `200`: The Webhook was updated
- Content types: `application/json`
- `400`: Bad Request
- Content types: `application/json`
- `404`: Not found response
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/update-webhook/
# Update a Webhook
**PUT** `/webhooks/{webhookId}/`
Update the Webhook with new data. NOTE that any subscriptions that are omitted from this request will be DELETED. If you don't want to replace all data on the Webhook, you probably want to use PATCH instead.
## Request
### Parameters
- `webhookId` (path, required, string): The ID that uniquely identifies the Webhook
### Request Body
- `application/json` — Webhook (object)
### Responses
- `200`: The Webhook was updated
- Content types: `application/json`
- `400`: Bad Request
- Content types: `application/json`
- `404`: Not found response
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/validate-bundle/
# Validate a Bundle
**PUT** `/bundles/{bundleSlug}/validate/`
Check if a given draft or pending Bundle is ready to be sent.
Returns validation status and a message.
## Request
### Parameters
- `bundleSlug` (path, required, string): The slug that uniquely identifies the Bundle
### Responses
- `200`: Validation result
- Content types: `application/json`
- `404`: Not found response
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/verification/
Public, unauthenticated endpoint for verifying that a PDF was produced and
signed through Blueink. Submit the SHA-256 hash of a PDF file; Blueink checks
whether it matches any signed PDF, combined PDF, or Certificate of Execution
associated with a completed Bundle.
```mdx-code-block
import DocCardList from '@theme/DocCardList';
import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
```
---
Source: https://developer.blueink.com/docs/api/verify-document/
# Verify a signed document
**POST** `/verify/`
Public, unauthenticated endpoint for verifying that a PDF was signed
through Blueink.
Submit the SHA-256 hash of a PDF file. Blueink checks whether the
hash matches any signed PDF, combined PDF, or Certificate of Execution
(COE) produced for a completed Bundle.
**Authentication**: none required. The endpoint is rate-limited for
anonymous callers. Because no API key is involved, the examples below use
plain HTTP requests rather than the official Blueink client SDKs.
**Use cases**
- Let recipients self-verify a document they received.
- Build a verification widget into your own portal.
- Audit-trail checks by third parties without API credentials.
**Response codes**
- `200` — Hash matched a Blueink-produced document (`status: verified`).
- `400` — Hash did not match any document (`status: invalid`) or the
request was malformed (missing / invalid hash).
- `429` — Rate limit exceeded.
## Request
### Request Body
- `application/json` — VerifyRequest (object) required: hash
### Responses
- `200`: The document was verified successfully.
- Content types: `application/json`
- `400`: The hash did not match any Blueink document (`status: invalid`),
the `hash` field was absent, or the value is not a valid
64-character hex SHA-256 digest.
- Content types: `application/json`
- `429`: Rate limit exceeded.
- Content types: `application/json`
---
Source: https://developer.blueink.com/docs/api/webhook-event/
A WebhookEvent represents a single event that occurred in your account and the
record of its delivery attempts to subscribed Webhooks. Use this section to inspect
past events and their delivery status, including any retried or failed deliveries.
```mdx-code-block
import DocCardList from '@theme/DocCardList';
import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
```
---
Source: https://developer.blueink.com/docs/api/webhook-extra-header/
WebhookExtraHeaders are custom HTTP headers that Blueink will include when
delivering events to a Webhook. Common uses include attaching a shared secret or
bearer token so your receiver can authenticate the incoming request as originating
from Blueink.
```mdx-code-block
import DocCardList from '@theme/DocCardList';
import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
```
---
Source: https://developer.blueink.com/docs/api/webhook-secret/
A WebhookSecret is a shared secret that Blueink uses to sign Webhook payloads. Your
receiver verifies the signature on incoming requests to confirm that the payload
originated from Blueink and was not tampered with in transit.
```mdx-code-block
import DocCardList from '@theme/DocCardList';
import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
```
---
Source: https://developer.blueink.com/docs/api/webhook/
Webhooks let your application receive real-time notifications when events occur
in your Blueink account, such as a Bundle being completed or a Signer viewing a
document. Each Webhook subscribes to one or more event types and is delivered as
an HTTP POST to a URL you specify.
**Related guides:** [Webhooks](/docs/esignature-api/webhook/)
```mdx-code-block
import DocCardList from '@theme/DocCardList';
import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
```
---
Source: https://developer.blueink.com/docs/esignature-api/authentication/
# Authentication
The Blueink API uses API keys to authenticate requests.
You can view and manage your API keys in the Blueink Dashboard, in the API->Apps section.
**Be sure to keep your API key secret!** An API key identifies your App and allows it to make calls to the
Blueink API on your behalf, including sending documents for eSignature. It should never be exposed publicly
in client-side code (e.g. javascript source files that are downloaded to a browser) or committed into
source control (e.g. a github repo).
> **Notice**
>
>
> If an API key is ever compromised or exposed publicly, you should immediately disable or delete the compromised
> API key in the Blueink Dashboard and generate a new one.
>
## Authentication in API Requests
All requests to the Blueink API must include an `Authorization` header with the value `Token `.
For example (using `curl`):
```bash
curl -X GET https://api.blueink.com/api/v2/bundles/ \
-H "Authorization: Token YOUR_API_KEY"
```
**Quick Links:**
- [Postman Collection](https://postman.com/blueink) - A collection of Blueink API requests that
you can use to test and explore the API. The Blueink Postman collection shows the proper way to
authenticate requests, and includes an environment variable where you can set your API key.
- [OpenAPI](/docs/api/)
---
Source: https://developer.blueink.com/docs/esignature-api/concepts/
# Core Concepts
Before diving into the API, it's helpful to understand the basic objects and terminology used in the Blueink ecosystem.
## Bundle (Envelope)
A **Bundle** is the primary container for a signing workflow. It represents a single request for signatures and can contain:
- One or more **Documents** to be signed.
- One or more **Packets** (signers).
- Validation rules and metadata.
## Packet (Signer)
A **Packet** represents an individual signer within a Bundle. Each Packet contains:
- The signer's contact information (name, email, phone).
- The signer's assigned role in the documents.
- A unique signing link.
## Person (Contact)
A **Person** is a reusable contact record in your Blueink account. While Packets are specific to a Bundle, Persons are long-lived and can be referenced across multiple Bundles to avoid re-entering signer details.
## Template
A **Template** is a reusable document definition that includes pre-placed signature and form fields. Using templates allows you to automate repetitive signing tasks by simply mapping signers to pre-defined roles.
- **Document Template**: A single document with fields.
- **Envelope Template**: A collection of document templates and signer roles ready to be launched as a Bundle.
---
Source: https://developer.blueink.com/docs/esignature-api/error-handling/
# Error Handling
When an API request fails, Blueink returns a structured JSON response to help you identify and resolve the issue.
## Error Response Format
All error responses (400, 401, 403, 404, 409, 429, 500) follow a consistent format:
```json
{
"errorMessage": "A human-readable description of the error",
"errorCode": "E_CODE_NAME",
"fieldErrors": {
"field_name": ["List of errors for this specific field"]
}
}
```
- **`errorMessage`**: A clear explanation of what went wrong.
- **`errorCode`**: A machine-readable string identifying the error type.
- **`fieldErrors`**: (Optional) For 400 Bad Request errors, this object contains validation errors for specific input fields.
## Common Error Codes
| Error Code | Description |
| :--- | :--- |
| `INVALID_DATA` | One or more fields in the request body failed validation. |
| `MISSING_REQUIRED` | A required field was not provided. |
| `NOT_FOUND` | The specified resource ID does not exist. |
| `PERMISSION_DENIED` | Your API key does not have access to this resource. |
| `LIMIT_EXCEEDED` | You have reached your account's usage or rate limits. |
| `CONFLICT` | The request could not be completed due to a conflict with the current state of the resource. |
## Best Practices
- Always check the `errorCode` for automated error handling.
- Log the `errorMessage` and `fieldErrors` for debugging purposes.
- Implement retry logic with exponential backoff for `503` or `429` errors.
---
Source: https://developer.blueink.com/docs/esignature-api/
# Blueink API Overview
## Introduction
This section contains an overview of concepts and usage of the Blueink API, including Authentication, Pagination, etc.
You can find a detailed documentation on API endpoints and operations in the [API Reference](/docs/api/) section.
If just starting with the Blueink API, you might want to check out the [Guides](/docs/guides/)
that supplement this API Overview.
## Versioning
The Blueink API uses semantic versioning. All minor and patch versions of the v2 API should be backwards
compatible.
- The latest version of the v2.X.X API is available at the path `/api/v2/`.
> **Deprecation**
>
>
> Old minor and patch versions are not accessible.
>
## HTTPS Only
> **Note**
>
>
> The Blueink API is only accessible via HTTPS.
>
## Rate Limits
- By default, Bundle creation requests (e.g a POST to /bundles) are limited to 200 / hour.
- Other API requests are limited to 2000 / hour.
- If you need higher limits, we are happy to accommodate. Please contact our team at [apisupport@blueink.com](mailto:apisupport@blueink.com).
## Test Mode
When creating envelopes with `is_test: true`, there are important restrictions to ensure test envelopes remain within your organization:
> **Test Mode Email Restrictions**
>
>
> **Email Verification Required**: Test envelopes can only be sent to email addresses that belong to users who exist in your Blueink account with verified email addresses.
>
> **Account User Restriction**: Test envelopes cannot be sent to arbitrary external email addresses - they must match existing account users.
>
> This ensures test envelopes stay within your organization during development and testing, preventing accidental delivery to external recipients.
>
## Additional Topics
---
Source: https://developer.blueink.com/docs/esignature-api/pagination/
# Pagination
## Overview
Lists of objects are returned as a flat list - that is, the objects are not wrapped in a container in the HTTP response.
For example, if you retrieve a list of Bundles, the response content will consist of:
```
[
{
... First Bundle object ...
},
{
... Second Bundle object ...
}
]
```
## Example Responses
Most requests for a list of resources are paginated, typically returning 50 results per page.
Pagination is implemented via a Link header. For example:
```
Link: ; rel="next",
; rel="last",
; rel="first",
; rel="prev"
```
Your client should use the URLs returned in the Link header to navigate through pages of results.
However, while not recommended, paginated URLs can be constructed manually. Page numbers are 1-indexed
(starting at 1, not 0). The pagination parameter in the querystring is `page`. Many API endpoints also
take a `per_page` parameter that lets a client control how many results are returned per page.
The maximum allowed value of `per_page` is typically 100.
For example:
```
https://api.blueink.com/api/v2/bundles?search=Bob&page=3&per_page=20
```
To make working with pagination easier, API responses with paginated results also include a
custom HTTP header: X-BlueInk-Pagination. The format of this header value is like so:
```
X-BlueInk-Pagination: ,,,
```
For example, if the response was for page 2 out of 4, with 50 results per page and 176 total results,
the header would be as follows.
```
X-BlueInk-Pagination: 2,4,50,176
```
All [Blueink API client libraries](/docs/libraries/) include convenience methods to work with paged results.
---
Source: https://developer.blueink.com/docs/esignature-api/restful-api/
# RESTful API Principles
The Blueink API is built on RESTful principles, using standard HTTP methods and status codes to manage resources.
## Base URL
All API requests are made to:
`https://api.blueink.com/api/v2/`
## HTTP Verbs
We use standard HTTP methods for different types of operations:
| Method | Description |
| :--- | :--- |
| `GET` | Retrieve a resource or a list of resources. |
| `POST` | Create a new resource. |
| `PUT` | Update an existing resource (full update). |
| `PATCH` | Partially update an existing resource. |
| `DELETE` | Remove a resource. |
## HTTP Status Codes
The API returns standard HTTP status codes to indicate the success or failure of a request:
| Code | Status | Description |
| :--- | :--- | :--- |
| `200` | OK | Request succeeded. |
| `201` | Created | Resource was successfully created. |
| `204` | No Content | Request succeeded, but there is no content to return. |
| `400` | Bad Request | The request was invalid or missing required parameters. |
| `401` | Unauthorized | Authentication failed or was missing. |
| `403` | Forbidden | You do not have permission to access the resource. |
| `404` | Not Found | The requested resource could not be found. |
| `429` | Too Many Requests | Rate limit exceeded. |
| `500` | Server Error | An internal error occurred on our servers. |
---
Source: https://developer.blueink.com/docs/esignature-api/webhook/
# Webhooks
Webhooks allow Blueink to notify your application when specific events occur, such as a signer viewing a packet,
completing a signing session, or a packet being sent. Rather than polling our API for updates, webhooks allow your
system to respond in real-time to events as they happen.
You can configure webhook endpoints and view your secret key (which can be used for
[verifying the webhook](#verifying-webhooks)) in the Blueink dashboard in the **API Section**.
You can also configure webhooks via the Blueink API. See the [API Documentation](/docs/api/webhook)
for details.
We suggest using HTTPS URLs for your webhook endpoints, but HTTP URLs are also supported.
## Webhook Event Types
Blueink supports the following event types for webhooks:
- `bundle_sent` - Bundle has been sent to signers
- `bundle_complete` - All signers have completed the bundle
- `bundle_docs_ready` - Documents are ready for download
- `bundle_error` - An error occurred with the bundle
- `bundle_cancelled` - Bundle was cancelled
- `packet_viewed` - A signer has viewed their packet
- `packet_complete` - A signer has completed their packet
- `packet_declined` - A signer has declined to sign their packet
## Receiving Webhooks
Upon receiving a Webhook HTTP Request from Blueink, your Webhook receiver should return an HTTP Response
with a status of 200, 201, 202 or 204 to indicate successful receipt of the webhook. If any other status
code is returned, or if no response is received within 10 seconds, the HTTP Request is deemed to have failed.
After an initial failed request, Blueink will retry the request with exponential backoff,
on the following schedule:
- 4 minutes
- 12 minutes
- 36 minutes
- 108 minutes
- 324 minutes
If any of the retry attempts results in a status of 200, 201, 202 or 204, the webhook event is deemed to
have been successfully delivered, and no additional delivery attempts are made.
You can view error codes for failed webhook deliveries in the Blueink dashboard in the **API Section**.
If all webhook delivery attempts fail for enough consecutive events for a particular webhook, Blueink will
disable the webhookand the Webhook status will be set to `DISABLED_DUE_TO_FAILED_DELIVERIES` (or `df`).
Admins on the accountare notified via email when a Webhook is disabled due to failed deliveries.
The webhook can be re-enabled by an admin in the Blueink dashboard. The Webhook can also be re-enabled
via updating the `status` can also be set updated
via the API witha PUT request to `/webhooks/[webhookId]/` to re-enable the Webhook
### Payload structure
Each Blueink event will have the following fields:
- **`event_id`**: A unique UUID identifying the webhook event.
- **`event_type`**: The type of event that occurred (e.g., `bundle_sent`, `bundle_complete`, `packet_viewed`, `packet_declined`).
- **`event_date`**: The ISO 8601 timestamp indicating when the event occurred in Blueink.
- **`account_id`**: The UUID of the Blueink account associated with the event.
- **`payload`**: An object containing additional metadata related to the event.
The contents of `payload` vary depending on the `event_type`.
```
// Example packet_viewed
{
"event_id": "c163d38f-e7ff-4e1b-b7dc-1fc027bf35ae",
"event_type": "packet_viewed",
"event_date": "2025-04-07 15:43:08.646752+00:00",
"account_id": "1b837b55-b16a-4d34-b422-f43a67d886d7",
"payload": {
"bundle_id": "HMXKQ0jhdJ",
"packet_id": "dtipO7RrCw"
}
}
// Example bundle_complete
{
"event_id": "f413734e-e832-49f2-a09e-a89c5cf4aa39",
"event_type": "bundle_complete",
"event_date": "2025-04-04 00:31:28.824236+00:00",
"account_id": "1b837b55-b16a-4d34-b422-f43a67d886d7",
"payload": {
"bundle_id": "plHoBZRHwM"
}
}
// Example packet_declined
{
"event_id": "a7b2c3d4-e5f6-4789-a012-b3c4d5e6f789",
"event_type": "packet_declined",
"event_date": "2025-04-07 16:22:15.123456+00:00",
"account_id": "1b837b55-b16a-4d34-b422-f43a67d886d7",
"payload": {
"bundle_id": "HMXKQ0jhdJ",
"packet_id": "dtipO7RrCw"
}
}
```
### Verifying Webhooks
To ensure that webhook requests come from Blueink and haven't been tampered with, you should verify the webhook signature on every request.
Blueink includes the following headers in each webhook request:
- `x-blueink-signature`: The HMAC SHA-256 signature of the request
- `x-blueink-request-timestamp`: The UNIX timestamp when the request was sent
In addition, you can configure a Webhook to include additional headers, e.g. to bypass firewall rules
or for custom verification.
Here’s an example of how to verify the webhook in Python:
```python
import hmac
import hashlib
WEBHOOK_SIGNATURE_VERSION = "v0"
WEBHOOK_SIGNATURE_ENCODING = "utf-8"
def verify_webhook_signature(body, secret, timestamp, webhook_signature, version="v0"):
"""
Computes the HMAC SHA-256 signature for verifying the authenticity of a webhook request.
Parameters:
- body (str): The JSON-encoded request body.
- secret (str): The webhook secret (found on the API screen).
- timestamp (str): The timestamp of the request (from the `x-blueink-request-timestamp` header).
- version (str, optional): The version of the signature format. Defaults to "v0".
"""
msg = f"{version}:{timestamp}:{body}"
signature = (
f"{WEBHOOK_SIGNATURE_VERSION}="
+ hmac.new(
key=bytes(secret, WEBHOOK_SIGNATURE_ENCODING),
msg=bytes(msg, WEBHOOK_SIGNATURE_ENCODING),
digestmod=hashlib.sha256,
).hexdigest()
)
return hmac.compare_digest(signature, webhook_signature)
body = json.dumps({
"event_id": "98cc7914-85f1-4695-83db-7cb81c575b85",
"event_type": "packet_viewed",
"event_date": "2025-03-30 19:48:27.123181+00:00",
"account_id": "1b837b55-b16a-4d34-b422-f43a67d886d7",
"payload": {"bundle_id": "TYkytOOwtN", "packet_id": "RmJIHGem3k"}
})
secret = "your_webhook_secret"
timestamp = "1711822107"
valid = verify_webhook_signature(body, secret, timestamp, webhook_signature)
```
---
Source: https://developer.blueink.com/docs/faq/
# FAQs
## Do you offer API support? {#faq-api-support}
Yes! We provide robust API support, enabling seamless integration of our e-signature capabilities into your products
or applications. Our dedicated API support team, kick-off calls, and assigned developer experts ensure a smooth
experience.
## Can I test the API for free? {#faq-free-testing}
Absolutely, API customers have the opportunity to thoroughly test Blueink's API at no cost. There's no time limit for
API testing, ensuring you can assess the API's performance and features at your own pace.
On an API Trial account, you are limited to sending Bundles in "test mode" (where `Bundle.is_test` is set to `true`).
These Bundles can be sent to verified email addresses in your account.
When testing or building out your integration is complete, you can purchase production API Envelopes
to start sending live Bundles / Envelopes, without test limitations.
## Can I Send non-API Bundles when I sign up for an API Plan? {#non-api-bundles}
API plans include a limited number of “regular” Bundles, allowing you to send Bundles from the Blueink Dashboard and
via the API. However, if you need to regularly send Bundles from the Dashboard and via our API, an Enterprise plan is
probably the best fit for your organization. Please contact [our sales team](https://www.blueink.com/contact-us) to
discuss options.
## Do you have a Postman Collection? {#faq-postman}
Yes! Checkout the [Blueink Postman Collection](https://www.postman.com/blueink/blueink-public-workspace/collection/t4tnyus/blueink-api-v2)
at Postman, or take a look at [Docs](/docs/libraries/postman_collection/) here in the Blueink Developer Site.
## Do you have an SDK for my preferred programming language? {#sdk}
You can find our growing collection of SDKs and code examples here:
- [Blueink SDKs Documentation](/docs/libraries/)
- [Blueink Github Page](https://github.com/blueinkhq)
- Something you can’t find? Please reach out to our API support team from inside the Blueink App.
---
Source: https://developer.blueink.com/docs/guides/auto-placement/
# Auto Placement of Fields
The Auto Field Placement feature in our API allows you to automatically place fields on your PDFs based on specific string inputs. This means that if your document contains a phrase like "Sign Here," our system can automatically detect this string and place a signature field right next to it. This feature is designed to save you time and make it easier to automate placing signatures on a variety of documents.
Using this feature is straightforward. You simply need to specify the string you want the system to look for in your document. Once the string is identified, the corresponding field is placed automatically. This can be particularly useful for documents where the exact location of fields like signatures may vary, but the strings indicating where they should be placed, such as "Sign Here," remain consistent. By automating the placement of these fields, you can save time and avoid the need to manually locate and place each field in every document, ensuring accuracy and efficiency in your workflow.
## Search Pattern Rules
When using auto placement, the `search` property defines the text pattern that Blueink will look for in your PDF document. Understanding the rules for valid search patterns will help you create reliable and accurate field placements.
### Case Sensitivity
Search patterns are **case-insensitive**. This means:
- `"Signature"` will match `"signature"`, `"SIGNATURE"`, or `"SiGnAtUrE"`
- You don't need to worry about the exact capitalization in your PDF
### Allowed Characters
Search patterns support a wide range of characters to accommodate various document formats:
- **Letters**: a-z, A-Z
- **Numbers**: 0-9
- **Spaces**: Regular spaces between words
- **Punctuation and Delimiters**: `:` `{{` `}}` `[` `]` `{` `}`
### String Length
- **Minimum**: 1 character
- **Maximum**: 255 characters
### Common Pattern Examples
Here are some common patterns developers use to distinguish different fields:
```json
{
"search": "Signature"
}
```
```json
{
"search": "Signature:"
}
```
```json
{
"search": "[Signature]"
}
```
```json
{
"search": "{Signature}"
}
```
```json
{
"search": "{{Signature 1}}"
}
```
```json
{
"search": "{{Signature 2}}"
}
```
```json
{
"search": "Tenant Signature"
}
```
### Best Practices
1. **Use Unique Patterns**: Make your search patterns specific enough to avoid unintended matches elsewhere in the document.
2. **Include Delimiters**: Adding brackets, colons, or other delimiters makes patterns more distinctive:
- ✅ `"[Signature]"` is more specific than `"Signature"`
- ✅ `"Signature:"` is more specific than `"Signature"`
3. **Number Similar Fields**: When you have multiple similar fields, use numbered patterns:
- `"{{Signature 1}}"`, `"{{Signature 2}}"`, `"{{Signature 3}}"`
- `"[Tenant Signature]"`, `"[Landlord Signature]"`
4. **Test Your Patterns**: Always test your patterns with actual PDF documents to ensure they match correctly and don't create false positives.
5. **Be Descriptive**: Use clear, descriptive text that matches what's actually in your PDF:
- ✅ `"Tenant Signature"` clearly indicates the purpose
- ❌ `"Sig1"` might be ambiguous
## Implementation Examples
The following examples show how to configure `auto_placements` in your Bundle request using the Client SDKs.
#### Python
```python
from blueink.client import Client
client = Client(api_key="your_api_key_here")
# Define bundle details with auto-placement
bundle_data = {
"label": "Auto-Placement Example",
"packets": [
{
"key": "signer-1",
"name": "John Doe",
"email": "john.doe@example.com"
}
],
"documents": [
{
"key": "contract-doc",
"file_url": "https://example.com/form.pdf",
"auto_placements": [
{
"kind": "sig",
"search": "Tenant Signature",
"h": 3,
"w": 25,
"offset_y": 2,
"editors": ["signer-1"]
},
{
"kind": "tms",
"search": "Tenant Date",
"h": 3,
"w": 25,
"offset_y": 2,
"editors": ["signer-1"]
}
]
}
]
}
response = client.bundles.create(data=bundle_data)
if response.status == 201:
print(f"✅ Envelope created! Bundle ID: {response.data.id}")
```
#### JavaScript
```javascript
const { Client } = require('@blueink360/blueink-client-js');
const client = new Client('your_api_key_here');
const bundleData = {
label: 'Auto-Placement Example',
packets: [
{
key: 'signer-1',
name: 'John Doe',
email: 'john.doe@example.com'
}
],
documents: [
{
key: 'contract-doc',
file_url: 'https://example.com/form.pdf',
auto_placements: [
{
kind: 'sig',
search: 'Tenant Signature',
h: 3,
w: 25,
offset_y: 2,
editors: ['signer-1']
},
{
kind: 'tms',
search: 'Tenant Date',
h: 3,
w: 25,
offset_y: 2,
editors: ['signer-1']
}
]
}
]
};
client.bundles.create(bundleData)
.then(response => {
console.log(`✅ Envelope created! Bundle ID: ${response.data.id}`);
});
```
#### PHP
```php
"Auto-Placement Example",
"packets" => [
[
"key" => "signer-1",
"name" => "John Doe",
"email" => "john.doe@example.com"
]
],
"documents" => [
[
"key" => "contract-doc",
"file_url" => "https://example.com/form.pdf",
"auto_placements" => [
[
"kind" => "sig",
"search" => "Tenant Signature",
"h" => 3,
"w" => 25,
"offset_y" => 2,
"editors" => ["signer-1"]
],
[
"kind" => "tms",
"search" => "Tenant Date",
"h" => 3,
"w" => 25,
"offset_y" => 2,
"editors" => ["signer-1"]
]
]
]
]
];
$response = $client->bundles->create($bundleData);
if ($response->status === 201) {
echo "✅ Envelope created! Bundle ID: " . $response->data->id;
}
```
## Interactive Example
Try it out using this [example Postman request](https://www.postman.com/blueink/workspace/blueink/request/8410429-56522a19-3e60-4a20-b32c-60fc6f308a7f).
## Related Resources
- [API Reference](/docs/api/) - Complete API documentation for all endpoints and operations
- [Send Envelope with Uploaded PDF](/docs/guides/send-envelope-with-uploaded-pdf/) - How to create envelopes by uploading PDF files
- [Field Types](/docs/api/) - Learn about all available field types (sig, ini, dat, txt, etc.)
---
Source: https://developer.blueink.com/docs/guides/blueink-mcp-server/
# Connect the Blueink MCP Server
The Blueink MCP server lets AI assistants interact with your Blueink account — search envelopes, check signer status, download documents, and more — all through natural language.
**Server URL:** `https://mcp.blueink.com/mcp`
**Authentication:** Uses the same API key as the Blueink REST API, passed as an `Authorization: Token ` header.
> **Tip**
>
> If you don't have an API key yet, visit the [Authentication guide](/docs/esignature-api/authentication/) to learn how to obtain one.
## Setup by Client
#### Claude Code
Run this command in your terminal:
```bash
claude mcp add --transport http blueink https://mcp.blueink.com/mcp \
--header "Authorization: Token your_api_key_here"
```
That's it — the server will be available the next time you start a Claude Code session.
#### Cursor
1. Open **Cursor Settings** → **MCP**.
2. Click **Add new MCP server**.
3. Choose **Type**: `http` (streamable HTTP).
4. Enter the URL: `https://mcp.blueink.com/mcp`
5. Add the header `Authorization: Token your_api_key_here`.
Or add it directly to your project's `.cursor/mcp.json`:
```json
{
"mcpServers": {
"blueink": {
"type": "http",
"url": "https://mcp.blueink.com/mcp",
"headers": {
"Authorization": "Token your_api_key_here"
}
}
}
}
```
#### Windsurf
Edit your Windsurf MCP configuration file at `~/.codeium/windsurf/mcp_config.json`:
```json
{
"mcpServers": {
"blueink": {
"type": "http",
"serverUrl": "https://mcp.blueink.com/mcp",
"headers": {
"Authorization": "Token your_api_key_here"
}
}
}
}
```
Restart Windsurf after saving.
#### VS Code (Copilot)
Add the server to your VS Code `settings.json` (open via **Cmd/Ctrl + Shift + P** → **Preferences: Open User Settings (JSON)**):
```json
{
"mcp": {
"servers": {
"blueink": {
"type": "http",
"url": "https://mcp.blueink.com/mcp",
"headers": {
"Authorization": "Token your_api_key_here"
}
}
}
}
}
```
#### Other Clients
Any MCP client that supports **Streamable HTTP** transport can connect. Use these settings:
| Setting | Value |
|---|---|
| **URL** | `https://mcp.blueink.com/mcp` |
| **Transport** | Streamable HTTP |
| **Auth Header** | `Authorization: Token your_api_key_here` |
## What You Can Do
Once connected, ask your AI assistant things like:
- *"Show me my recent envelopes"*
- *"What's the status of envelope abc123?"*
- *"Find envelopes sent to john@example.com"*
- *"Download the signed PDF for envelope xyz789"*
## Need Help?
- [Authentication guide](/docs/esignature-api/authentication/) — Get your API key
- [API Reference](/docs/api/) — Full endpoint documentation
- [Support Center](https://help.blueink.com) — Additional resources
---
Source: https://developer.blueink.com/docs/guides/checkbox-groups/
# How to Create Checkbox Groups
Checkbox Groups (`cbg`) allow you to group multiple individual checkboxes (`chk`) together. This is useful when you want to enforce validation rules across a set of options, such as "select at least one" or "select no more than three".
## Overview
Creating a checkbox group involves two main components:
1. **A Parent Checkbox Group field**: A field with `kind: "cbg"`. This field holds the validation rules (`v_min`, `v_max`) but is not visible on the document.
2. **Child Checkbox fields**: Multiple fields with `kind: "chk"` that reference the parent group using the `related_to_key` property.
## Validation Rules
You can use the following properties on the parent `cbg` field to control selection:
- `v_min`: The minimum number of checkboxes that must be selected.
- `v_max`: The maximum number of checkboxes that can be selected.
For example, to create a "Select exactly 2" rule, set both `v_min` and `v_max` to `2`.
## Implementation Example
The following example shows how to create an envelope with a checkbox group containing three options, requiring the signer to select between 1 and 2 of them.
#### Python
```python
import requests
API_KEY = "your-api-key"
API_URL = "https://api.blueink.com/api/v2/bundles/"
payload = {
"label": "Checkbox Group Example",
"packets": [
{
"name": "John Doe",
"email": "john.doe@example.com",
"key": "signer-1"
}
],
"documents": [
{
"key": "doc-1",
"file_url": "https://example.com/form.pdf",
"fields": [
{
"key": "color-group",
"kind": "cbg",
"label": "Pick 1 or 2 colors",
"v_min": 1,
"v_max": 2,
"editors": ["signer-1"],
"page": 1, "x": 0, "y": 0, "w": 0, "h": 0
},
{
"key": "color-red",
"kind": "chk",
"label": "Red",
"related_to_key": "color-group",
"editors": ["signer-1"],
"page": 1, "x": 10, "y": 10, "w": 5, "h": 5
},
{
"key": "color-blue",
"kind": "chk",
"label": "Blue",
"related_to_key": "color-group",
"editors": ["signer-1"],
"page": 1, "x": 10, "y": 20, "w": 5, "h": 5
},
{
"key": "color-green",
"kind": "chk",
"label": "Green",
"related_to_key": "color-group",
"editors": ["signer-1"],
"page": 1, "x": 10, "y": 30, "w": 5, "h": 5
}
]
}
]
}
headers = {
"Authorization": f"Token {API_KEY}",
"Content-Type": "application/json"
}
response = requests.post(API_URL, json=payload, headers=headers)
print(response.json())
```
#### JavaScript
```javascript
const axios = require('axios');
const API_KEY = 'your-api-key';
const API_URL = 'https://api.blueink.com/api/v2/bundles/';
const payload = {
label: 'Checkbox Group Example',
packets: [
{
name: 'John Doe',
email: 'john.doe@example.com',
key: 'signer-1'
}
],
documents: [
{
key: 'doc-1',
file_url: 'https://example.com/form.pdf',
fields: [
{
key: 'color-group',
kind: 'cbg',
label: 'Pick 1 or 2 colors',
v_min: 1,
v_max: 2,
editors: ['signer-1'],
page: 1, x: 0, y: 0, w: 0, h: 0
},
{
key: 'color-red',
kind: 'chk',
label: 'Red',
related_to_key: 'color-group',
editors: ['signer-1'],
page: 1, x: 10, y: 10, w: 5, h: 5
},
{
key: 'color-blue',
kind: 'chk',
label: 'Blue',
related_to_key: 'color-group',
editors: ['signer-1'],
page: 1, x: 10, y: 20, w: 5, h: 5
},
{
key: 'color-green',
kind: 'chk',
label: 'Green',
related_to_key: 'color-group',
editors: ['signer-1'],
page: 1, x: 10, y: 30, w: 5, h: 5
}
]
}
]
};
axios.post(API_URL, payload, {
headers: {
'Authorization': `Token ${API_KEY}`,
'Content-Type': 'application/json'
}
})
.then(response => console.log(response.data))
.catch(error => console.error(error));
```
#### PHP
```php
"Checkbox Group Example",
"packets" => [
[
"name" => "John Doe",
"email" => "john.doe@example.com",
"key" => "signer-1"
]
],
"documents" => [
[
"key" => "doc-1",
"file_url" => "https://example.com/form.pdf",
"fields" => [
[
"key" => "color-group",
"kind" => "cbg",
"label" => "Pick 1 or 2 colors",
"v_min" => 1,
"v_max" => 2,
"editors" => ["signer-1"],
"page" => 1, "x" => 0, "y" => 0, "w" => 0, "h" => 0
],
[
"key" => "color-red",
"kind" => "chk",
"label" => "Red",
"related_to_key" => "color-group",
"editors" => ["signer-1"],
"page" => 1, "x" => 10, "y" => 10, "w" => 5, "h" => 5
],
[
"key" => "color-blue",
"kind" => "chk",
"label" => "Blue",
"related_to_key" => "color-group",
"editors" => ["signer-1"],
"page" => 1, "x" => 10, "y" => 20, "w" => 5, "h" => 5
],
[
"key" => "color-green",
"kind" => "chk",
"label" => "Green",
"related_to_key" => "color-group",
"editors" => ["signer-1"],
"page" => 1, "x" => 10, "y" => 30, "w" => 5, "h" => 5
]
]
]
]
];
$response = $client->bundles->create($payload);
if ($response->status === 201) {
print_r($response->data);
} else {
echo "Error: " . $response->error;
}
```
## Important Notes
- **Coordinate Requirements**: Although the parent `cbg` field is not visible on the document, the API still requires coordinates (`x`, `y`, `w`, `h`) and a `page` number. You can safely set these to `0`.
- **Unique Keys**: All field keys (including both the parent group and the checkboxes) must be unique within the document.
- **Reference Accuracy**: Ensure that the `related_to_key` on each checkbox exactly matches the `key` of the parent group field.
---
Source: https://developer.blueink.com/docs/guides/embedded-signing/
# How to Implement Embedded Signing
This guide demonstrates how to create envelopes with embedded signing and generate iframe URLs for seamless integration into your application. You'll learn how to create a single signer envelope that delivers via embed and how to retrieve the embedded signing URL.
## Overview
Embedded signing allows you to integrate the signing experience directly into your application without redirecting users to external pages:
1. **Create an envelope** with `deliver_via: "embed"` for the signer
2. **Retrieve the embedded URL** using the packet ID
3. **Embed the signing interface** in your application using an iframe
**Envelopes are automatically sent in the background after creation, though they initially show pending status while processing.**
## Prerequisites
Before you begin, ensure you have:
- A Blueink account with API access
- Your API key (available in the Blueink Dashboard under Apps)
- A PDF file or document template for signing
- Basic knowledge of HTTP requests and your chosen programming language
- Understanding of iframe integration in web applications
> **Tip**
>
> If you don't have an API key yet, visit the [Authentication guide](/docs/esignature-api/authentication/) to learn how to obtain one.
> **Test Mode Email Restrictions**
>
> When using `is_test: true`, envelopes can only be sent to email addresses that belong to users in your Blueink account. Make sure the signer email addresses match existing users in your account when testing.
## Step 1: Prepare Your Environment
### Authentication Setup
All requests to the Blueink API require authentication using your API key in the Authorization header:
```
Authorization: Token YOUR_API_KEY_HERE
```
### Required Information
For this guide, you'll need:
- **PDF file path**: The local path to your PDF file (or template ID)
- **Signer information**: Name and email address of the person who will sign
- **Embed configuration**: Setting up the packet for embedded delivery
## Step 2: Create Envelope with Embedded Signing
Create an envelope with a single signer configured for embedded delivery using `deliver_via: "embed"`.
#### Python
### Using the Python SDK
```python
from blueink.client import Client
client = Client(api_key="your_api_key_here")
# Define bundle details
bundle_data = {
"label": "Embedded Signature Request",
"is_test": True,
"packets": [
{
"key": "signer-1",
"name": "John Doe",
"email": "john.doe@example.com",
"deliver_via": "embed" # This enables embedded signing
}
],
"documents": [
{
"key": "contract-doc",
"file_index": 0,
"filename": "contract.pdf"
}
]
}
# Open the file and send
with open("path/to/document.pdf", "rb") as f:
files = [{"file": f, "filename": "contract.pdf"}]
response = client.bundles.create(data=bundle_data, files=files)
if response.status == 201:
packet_id = response.data.packets[0].id
print(f"✅ Envelope created! Packet ID: {packet_id}")
```
#### JavaScript
### Using the JavaScript SDK
```javascript
const { Client } = require('@blueink360/blueink-client-js');
const fs = require('fs');
const client = new Client('your_api_key_here');
const bundleData = {
label: 'Embedded Signature Request',
is_test: true,
packets: [
{
key: 'signer-1',
name: 'John Doe',
email: 'john.doe@example.com',
deliver_via: 'embed'
}
],
documents: [
{
key: 'contract-doc',
file_index: 0,
filename: 'contract.pdf'
}
]
};
const files = [
{
file: fs.createReadStream('path/to/document.pdf'),
filename: 'contract.pdf'
}
];
client.bundles.create(bundleData, files)
.then(response => {
const packetId = response.data.packets[0].id;
console.log(`✅ Envelope created! Packet ID: ${packetId}`);
});
```
#### PHP
### Using the PHP SDK
```php
"Embedded Signature Request",
"is_test" => true,
"packets" => [
[
"key" => "signer-1",
"name" => "John Doe",
"email" => "john.doe@example.com",
"deliver_via" => "embed"
]
],
"documents" => [
[
"key" => "contract-doc",
"file_index" => 0,
"filename" => "contract.pdf"
]
]
];
$files = [
[
"file" => fopen("path/to/document.pdf", "r"),
"filename" => "contract.pdf"
]
];
$response = $client->bundles->create($bundleData, $files);
if ($response->status === 201) {
$packetId = $response->data->packets[0]->id;
echo "✅ Envelope created! Packet ID: " . $packetId;
}
```
## Step 3: Retrieve the Embedded Signing URL
Once the envelope is created, use the packet ID to retrieve the embedded signing URL that can be used in an iframe.
#### Python
### Using the Python SDK
```python
from blueink.client import Client
client = Client(api_key="your_api_key_here")
# Get embedded signing URL for a specific packet
response = client.packets.embed_url(packet_id="packet-id-here")
if response.status == 200:
print(f"✅ Embedded URL: {response.data.url}")
```
#### JavaScript
### Using the JavaScript SDK
```javascript
const { Client } = require('blueink-client-js');
const client = new Client('your_api_key_here');
client.packets.embedUrl('packet-id-here')
.then(response => {
console.log(`✅ Embedded URL: ${response.data.url}`);
});
```
#### PHP
### Using the PHP SDK
```php
packets->embedURL("packet-id-here");
if ($response->status === 200) {
echo "✅ Embedded URL: " . $response->data->url;
}
```
## API Response Examples
### Envelope Creation Response
When successful, the envelope creation returns a `201 Created` status with the envelope details:
```json
{
"id": "lL7g5Hn2Ni",
"created": "2025-09-04T23:18:57.615334Z",
"sent": null,
"completed_at": null,
"label": "Embedded Signature Request",
"in_order": false,
"is_test": true,
"status": "pe",
"custom_key": null,
"custom_text": "",
"packets": [
{
"id": "a6v1qN4z8T",
"key": "signer-1",
"name": "John Doe",
"email": "john.doe@example.com",
"phone": "",
"auth_sms": false,
"auth_selfie": false,
"auth_secrets": null,
"auth_id": false,
"person_id": "db600721-d8e7-42d3-8ebe-a180b4864eb8",
"status": "ne",
"deliver_via": "embed",
"completed_at": null,
"last_accessed_at": null,
"order": 1,
"signing_complete_redirect": "",
"suppress_all": false,
"suppress_docs_ready": false,
"suppress_signing": false,
"suppress_reminder": false
}
],
"documents": [
{
"id": "doc456",
"key": "contract-doc",
"filename": "contract.pdf",
"status": "pr"
}
],
"errors": null,
"cc_emails": [],
"email_message": "",
"email_subject": "",
"team": null,
"tags": [],
"send_reminders": false,
"reminder_offset": 0,
"reminder_interval": 0,
"reminder_expires": 0,
"expires": null,
"sms_message": "",
"requester_name": "",
"requester_email": "",
"payment": null
}
```
### Embedded URL Response
The embed URL endpoint returns a `200 OK` status with the signing URL:
```json
{
"url": "https://app.blueink.com/packets/a6v1qN4z8T/embed/?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
}
```
## Frontend Integration
### HTML iframe Integration
Once you have the embedded URL, integrate it into your web application:
```html
Document Signing
);
};
export default EmbeddedSigning;
```
## Error Handling and Best Practices
### Common Error Scenarios
1. **Packet Not Found (404 Not Found)**
```json
{
"detail": "Packet not found."
}
```
2. **Authentication Error (401 Unauthorized)**
```json
{
"detail": "Invalid token."
}
```
3. **Packet Not Ready for Embedding (400 Bad Request)**
```json
{
"detail": "Packet is not configured for embedded delivery."
}
```
### Best Practices
1. **Security Considerations**
- Never expose your API key in frontend code
- Use server-side endpoints to generate embed URLs
- Implement proper CORS policies
- Validate packet ownership before generating URLs
2. **User Experience**
- Provide loading states while generating embed URLs
- Handle iframe loading errors gracefully
- Implement responsive iframe sizing
- Listen for completion events to redirect users
3. **Error Handling**
- Always check response status codes
- Implement retry logic for transient failures
- Provide meaningful error messages to users
- Log errors for debugging purposes
4. **Performance**
- Cache embed URLs when appropriate (they have limited lifetime)
- Preload signing interfaces when possible
- Optimize iframe dimensions for your layout
## Security and Compliance
### iframe Security
- **Content Security Policy**: Configure CSP headers to allow Blueink domains
- **X-Frame-Options**: Ensure your application allows iframe embedding
- **HTTPS Required**: Embedded signing requires HTTPS for security
### Data Protection
- Embedded signing maintains the same security standards as regular signing
- All data transmission is encrypted
- Audit trails are preserved for embedded signatures
- Compliance certifications apply to embedded workflows
## Next Steps
Now that you've learned how to implement embedded signing, you might want to explore:
- **[Send Envelope with Uploaded PDF](/docs/guides/send-envelope-with-uploaded-pdf/)** - How to create envelopes by uploading PDF files
- **[Send Envelope with Templates](/docs/guides/send-envelope-with-templates/)** - How to use templates for embedded signing
- **[API Reference](/docs/api/)** - Complete API documentation for all endpoints and operations
- **[Webhook Integration](/docs/esignature-api/webhook/)** - How to receive real-time notifications about signing events
## Need Help?
If you encounter issues or have questions:
- Check the [API Reference](/docs/api/) for detailed endpoint documentation
- Visit our [Support Center](https://help.blueink.com) for additional resources
- Contact our support team through the Blueink Dashboard
Embedded signing provides a seamless user experience by keeping users within your application throughout the signing process. By following this guide, you can integrate professional e-signature capabilities directly into your workflow.
---
Source: https://developer.blueink.com/docs/guides/html-to-pdf/
# Generate PDFs from HTML
Generate a PDF from HTML and send it for electronic signature in a single Blueink API call — no need to render the PDF yourself, host it, or upload it as a file. Provide HTML (with optional CSS for layout and `data-blu-*` annotations for signature, initial, date, and form fields), and Blueink converts the HTML to a PDF and detects the fields automatically.
This is useful for dynamically generating signable documents from templates, building HTML forms that map directly to e-signature fields, and any workflow where the source-of-truth document lives in HTML rather than as a pre-rendered PDF.
This guide describes how to create a Bundle Document from HTML and documents the rules Blueink uses to convert your HTML to a PDF and extract form fields.
## Basic Usage
When creating a new Bundle in Blueink via the [Create Bundle](/docs/api/create-bundle) endpoint (`POST /api/v2/bundles/`), you can create a document from HTML by including a `file_html` parameter on any document. The value should be the escaped HTML of your document.
### SDK Implementation Example
The following example demonstrates how to create a Bundle using an HTML string with a signature field.
#### Python
```python
from blueink.client import Client
client = Client(api_key="your_api_key_here")
# Define bundle details with HTML content
bundle_data = {
"label": "Contract from HTML",
"is_test": True,
"packets": [
{
"key": "signer-1",
"name": "John Doe",
"email": "john.doe@example.com"
}
],
"documents": [
{
"key": "contract-doc",
"file_html": "