July 2, 2026 · Migration Guide

Migrating from Dropbox Sign (HelloSign) API: A Developer's Guide

Dropbox Sign — the product formerly known as HelloSign — has pushed developers through a rebrand, an OAuth migration, and SDK deprecations. If you're evaluating whether to keep migrating or switch to something simpler, this guide maps every endpoint, webhook, and auth flow side-by-side so you can make the call.

Michael Beckett
Michael Beckett

Founder, Signbee

TL;DR

HelloSign became Dropbox Sign. The API got more complex, not simpler. If you're migrating anyway, consider switching to a simpler HelloSign alternative instead of re-implementing OAuth flows and template management. Signbee replaces the entire Dropbox Sign SDK with a single POST /api/v1/send call.

The HelloSign → Dropbox Sign rebrand: what actually changed

HelloSign launched in 2010 as a developer-friendly e-signature API. Dropbox acquired it in 2019 for $230 million, and in 2022 rebranded it to Dropbox Sign. For API users, the rebrand introduced three concrete changes:

1. New base URL. The API moved from api.hellosign.com to api.dropboxsign.com. The old domain still resolves with 301 redirects, but Dropbox has signalled it will be sunset entirely. If your integration relies on the old domain, every request is taking a redirect penalty.

2. OAuth 2.0 enforcement. HelloSign's original API used simple API key authentication — you passed your key as the username in HTTP Basic auth. Dropbox Sign now requires OAuth 2.0 for any integration that accesses accounts on behalf of users. For embedded signing flows, you need to implement the full authorization code grant with PKCE.

3. SDK overhaul. The legacy hellosign-sdk npm package was deprecated. The replacement, @dropbox/sign, is auto-generated from an OpenAPI spec and has a significantly different API surface. Method names, parameter structures, and error handling all changed. If you were using the HelloSign SDK, you are effectively learning a new SDK from scratch.

The net effect: developers who chose HelloSign for its simplicity are now maintaining an integration with the complexity of DocuSign. Many teams use this forced migration as an opportunity to re-evaluate their e-signature API entirely.

Authentication: Dropbox Sign OAuth vs Signbee Bearer auth

This is where the migration pain concentrates. Here's what each flow requires:

StepDropbox Sign OAuthSignbee Bearer
1. SetupRegister app in Dropbox developer console, configure redirect URIs, generate client secretCopy API key from dashboard
2. Auth flowRedirect user to consent screen → receive auth code → exchange for access tokenAdd Bearer token header
3. Token managementStore refresh token, implement token refresh before expiry, handle revocationNo expiry, no refresh
4. ScopingRequest specific OAuth scopes per operationFull API access with key
5. Error handlingHandle expired tokens, revoked consent, scope errors, redirect mismatches401 = bad key

For server-to-server integrations (the most common use case for e-signature APIs), Dropbox Sign's OAuth adds roughly 200-400 lines of token management code that serves no functional purpose beyond authentication. Signbee eliminates this entirely.

Endpoint mapping: Dropbox Sign → Signbee

Here is a direct mapping of the Dropbox Sign API endpoints you are most likely using to their Signbee equivalents. The key difference: Signbee collapses most of these into a single endpoint with different request body parameters.

OperationDropbox Sign endpointSignbee endpoint
Send for signingPOST /signature_request/sendPOST /api/v1/send
Send with templatePOST /signature_request/send_with_templatePOST /api/v1/send (markdown body)
Get signature requestGET /signature_request/{id}GET /api/v1/documents/{id}
List requestsGET /signature_request/listGET /api/v1/documents
Cancel requestPOST /signature_request/cancel/{id}DELETE /api/v1/documents/{id}
Download signed PDFGET /signature_request/files/{id}GET /api/v1/documents/{id}/pdf
Create embedded signingPOST /signature_request/create_embeddedPOST /api/v1/send (returns signing URL)
Get embedded sign URLGET /embedded/sign_url/{id}Included in send response
Create templatePOST /template/create_embedded_draftN/A (use markdown)

Notice the pattern: Dropbox Sign requires 9+ endpoints for a standard signing workflow. Signbee uses 3 (/send, /documents, /documents/:id/pdf). Templates are not a separate API resource — they are markdown strings in your codebase, which means they are version-controlled, testable, and do not require a separate dashboard.

Code migration: before and after

Here is a real-world example — sending a document for signature using a template. This is the most common Dropbox Sign API operation.

Before: Dropbox Sign SDK with template
import * as DropboxSign from "@dropbox/sign";

const signatureRequestApi = new DropboxSign.SignatureRequestApi();
signatureRequestApi.username = "YOUR_ACCESS_TOKEN"; // OAuth token

const signer: DropboxSign.SubSignatureRequestTemplateSigner = {
  role: "Client",
  emailAddress: "jane@example.com",
  name: "Jane Smith",
};

const customField: DropboxSign.SubCustomField = {
  name: "project_name",
  value: "Website Redesign",
  editor: "sender",
  required: true,
};

const data: DropboxSign.SignatureRequestSendWithTemplateRequest = {
  templateIds: ["tmpl_abc123def456"],
  subject: "Service Agreement",
  message: "Please review and sign this agreement.",
  signers: [signer],
  customFields: [customField],
  clientId: "YOUR_CLIENT_ID",  // Required for embedded
  testMode: true,
};

try {
  const result = await signatureRequestApi.signatureRequestSendWithTemplate(data);
  const signatureRequestId = result.body.signatureRequest?.signatureRequestId;
  
  // Now get the embedded signing URL (separate API call)
  const signerId = result.body.signatureRequest?.signatures?.[0]?.signatureId;
  const embeddedApi = new DropboxSign.EmbeddedApi();
  embeddedApi.username = "YOUR_ACCESS_TOKEN";
  const signUrl = await embeddedApi.embeddedSignUrl(signerId!);
  
  console.log("Sign URL:", signUrl.body.embedded?.signUrl);
} catch (error) {
  if (error instanceof DropboxSign.HttpError) {
    // Handle OAuth token expiry, rate limits, etc.
    console.error(error.statusCode, error.body);
  }
}
After: Signbee single POST
const res = await fetch("https://signb.ee/api/v1/send", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_API_KEY",  // No OAuth. No refresh.
  },
  body: JSON.stringify({
    markdown: [
      "# Service Agreement",
      "",
      "**Project:** Website Redesign",
      "",
      "This agreement confirms that the undersigned agrees to the terms",
      "outlined in the attached statement of work.",
      "",
      "---",
      "",
      "**Client signature:**",
    ].join("\n"),
    recipient_name: "Jane Smith",
    recipient_email: "jane@example.com",
    subject: "Service Agreement",
  }),
});

const { document_id, signing_url, status } = await res.json();
console.log("Sign URL:", signing_url);
// That's it. No second API call. No SDK. No template dashboard.

The Dropbox Sign version requires an SDK import, OAuth token management, template ID lookup, a separate API call for the embedded signing URL, and typed error handling for OAuth edge cases. The Signbee version is a single fetch call. The template is a markdown string — if you need to change the wording, you change a string in your codebase, not a template in a dashboard.

Webhook migration: Dropbox Sign vs Signbee events

Webhook events are where migrations get tricky if you have downstream logic that depends on specific event names or payload shapes. Here is a direct mapping of Dropbox Sign callback events to Signbee webhook events:

Dropbox Sign eventSignbee eventNotes
signature_request_sentdocument.sentFired when signing email is delivered
signature_request_vieweddocument.viewedRecipient opened signing link
signature_request_signeddocument.signedSignature applied
signature_request_all_signeddocument.completedPDF and certificate ready for download
signature_request_declineddocument.declinedSigner declined to sign
signature_request_remindN/ASignbee handles reminders automatically
signature_request_invalidN/ASignbee validates at send time, not async

Key difference: verification. Dropbox Sign uses an API key hash to verify webhook authenticity — you compute an HMAC of the event type using your API key and compare it to the hash in the payload. Signbee uses HMAC-SHA256 with a dedicated webhook secret sent in the X-Signbee-Signature header. The verification logic is simpler and follows the same pattern used by Stripe and GitHub:

Dropbox Sign webhook verification
// Dropbox Sign: hash-based verification
const crypto = require('crypto');

app.post('/webhook/dropboxsign', (req, res) => {
  const eventHash = req.body.event.event_hash;
  const eventType = req.body.event.event_type;
  const apiKey = process.env.DROPBOX_SIGN_API_KEY;
  
  const computedHash = crypto
    .createHmac('sha256', apiKey)
    .update(eventType)
    .digest('hex');
  
  if (computedHash !== eventHash) {
    return res.status(401).send('Invalid signature');
  }
  
  // Process event...
  res.send('Hello API Event Received');  // Must return this exact string
});
Signbee webhook verification
// Signbee: HMAC-SHA256, same pattern as Stripe
const crypto = require('crypto');

app.post('/webhook/signbee', (req, res) => {
  const signature = req.headers['x-signbee-signature'];
  const rawBody = req.rawBody;  // Must use raw body, not parsed JSON
  
  const expected = crypto
    .createHmac('sha256', process.env.SIGNBEE_WEBHOOK_SECRET)
    .update(rawBody)
    .digest('hex');
  
  if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) {
    return res.status(401).send('Invalid signature');
  }
  
  const event = JSON.parse(rawBody);
  // event.type === "document.signed" | "document.completed" | etc.
  res.status(200).send('ok');
});

Note: Dropbox Sign requires you to return the exact string "Hello API Event Received" in your webhook response. Any other response causes retries. Signbee accepts any 2xx status code, which is the industry standard pattern.

Common migration pitfalls

1. Relying on template IDs

Dropbox Sign templates live in their dashboard and are referenced by opaque IDs (tmpl_abc123). If you have dozens of templates, you need to either recreate them in your new provider's dashboard or, better, move templates into your codebase. Signbee uses markdown strings, so your templates are version-controlled code — no dashboard dependency. Start by exporting your Dropbox Sign template content and converting each to a markdown string.

2. OAuth token refresh race conditions

If you are migrating between two OAuth-based providers, you may have concurrent requests trying to refresh the same token. This causes invalid_grant errors when the first refresh invalidates the old refresh token before the second request can use it. With Signbee's Bearer token auth, this entire class of bugs is eliminated — there are no tokens to refresh.

3. Hardcoded webhook response strings

Dropbox Sign requires the exact string "Hello API Event Received" in webhook responses. If your webhook handler returns a generic 200 OK or a JSON body, Dropbox Sign treats it as a failure and retries. When migrating to Signbee, you can remove this quirk — Signbee accepts any 2xx response.

4. Embedded signing URL expiry

Dropbox Sign embedded signing URLs expire after 60 seconds by default and require a separate API call to generate. If your frontend is slow to render the signing iframe, you can hit expiry errors. Signbee returns the signing URL directly in the send response with a configurable expiry window, eliminating the second API call and the tight timing constraint.

5. Multi-signer ordering assumptions

Dropbox Sign uses a order field on signers to enforce signing order. If you are migrating multi-signer flows, make sure you test the signing order logic in your new provider. Signbee supports sequential signing by sending requests in order via webhooks — when document.signed fires for signer 1, your backend sends to signer 2.

6. File attachment size limits

Dropbox Sign accepts PDF uploads up to 40 MB. If your integration uploads pre-built PDFs, verify that your new provider supports your file sizes. Signbee takes a different approach: you send markdown content and Signbee generates the PDF server-side. This means no file uploads at all for most use cases, which simplifies your API calls and eliminates upload timeout issues.

Migration checklist

Inventory all Dropbox Sign API calls in your codebase (grep -r "hellosign\|dropboxsign")
Export template content from Dropbox Sign dashboard
Convert templates to markdown strings
Replace OAuth token management with Bearer token header
Map API calls using the endpoint table above
Update webhook handler to use HMAC-SHA256 verification
Remove the "Hello API Event Received" response string
Update webhook event names (see mapping table)
Remove Dropbox Sign SDK dependency (npm uninstall @dropbox/sign)
Test end-to-end: send → view → sign → download PDF

Frequently Asked Questions

Is the HelloSign API the same as the Dropbox Sign API?

Yes — they are the same product. HelloSign was acquired by Dropbox in 2019 and rebranded in 2022. The base URL changed from api.hellosign.com to api.dropboxsign.com, the SDK was overhauled from hellosign-sdk to @dropbox/sign, and OAuth 2.0 is now required for integrations that access accounts on behalf of users. The old endpoints still work via 301 redirects but are being sunset. If you are evaluating alternatives, see our HelloSign alternative comparison.

What are the best alternatives to the Dropbox Sign API?

For developers prioritising integration speed, Signbee offers a single-endpoint API with Bearer token auth — no OAuth, no SDK, no template dashboard. Other alternatives include BoldSign (API-first with .NET focus), SignWell (API key auth), and PandaDoc (document automation with signing). If you are specifically trying to reduce integration complexity, Signbee and SignWell have the lowest barrier to entry. Read our full developer's guide to e-signature APIs for a detailed comparison.

How long does it take to migrate from Dropbox Sign to Signbee?

Most developers complete the migration in under 2 hours. The steps are: get a Signbee API key (2 minutes), replace API calls with Signbee's single POST endpoint (30 minutes), convert templates to markdown (15-30 minutes), update webhooks (15 minutes), and test end-to-end (15 minutes). The biggest time savings come from eliminating OAuth entirely. If you have complex templates with many merge fields, converting them to markdown is the most time-consuming step. See our webhook events guide for details on setting up Signbee webhooks.

Stop migrating OAuth flows — Bearer token, one endpoint, $0.50/doc.

Last updated: July 7, 2026 · Michael Beckett is the founder of Signbee and B2bee Ltd.

Related resources