Go to file
Paul Huliganga 7aac78f3a4 docs: document Adobe Sign non-standard refresh token endpoint
Adobe Sign uses /oauth/v2/refresh (not /oauth/v2/token) for token
refresh — a deviation from the OAuth2 spec that caused all refresh
attempts to fail with a misleading "Invalid grant_type" error.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-16 12:35:17 -04:00
docs docs: README, platform quirks, validation notes, and sample reference data 2026-04-15 19:45:46 -04:00
sample-templates docs: README, platform quirks, validation notes, and sample reference data 2026-04-15 19:45:46 -04:00
src feat: map Adobe Sign conditional logic to DocuSign conditionalParentLabel/Value 2026-04-16 12:18:48 -04:00
tests docs: document Adobe Sign non-standard refresh token endpoint 2026-04-16 12:35:17 -04:00
validation docs: README, platform quirks, validation notes, and sample reference data 2026-04-15 19:45:46 -04:00
.env-sample chore: add .env-sample with all required environment variables 2026-04-16 10:10:28 -04:00
.gitignore chore: exclude generated outputs and binary assets from git 2026-04-15 19:44:26 -04:00
PRODUCT-SPEC.md Initial project scaffold (Cleo) 2026-04-14 19:21:17 -04:00
PROJECT-SETUP.md Initial project scaffold (Cleo) 2026-04-14 19:21:17 -04:00
README.md docs: update README — reference .env-sample and mention conditional logic 2026-04-16 12:35:13 -04:00
api-samples.md Initial project scaffold (Cleo) 2026-04-14 19:21:17 -04:00
field-mapping.md feat: map Adobe Sign conditional logic to DocuSign conditionalParentLabel/Value 2026-04-16 12:18:48 -04:00
requirements.txt feat: DocuSign JWT auth and pure-Python template upload client 2026-04-15 19:45:23 -04:00

README.md

Adobe Sign → DocuSign Migrator

A Python toolkit for migrating library templates from Adobe Sign (Acrobat Sign) to DocuSign. It downloads templates via the Adobe Sign API, converts them to DocuSign format, and uploads them via the DocuSign API.


What it does

  1. Authenticates with Adobe Sign via OAuth (one-time browser flow, tokens saved to .env)
  2. Downloads templates — PDF, metadata, and form field definitions
  3. Converts each template to a DocuSign envelopeTemplate JSON, mapping all field types, coordinates, recipient roles, and conditional field logic
  4. Authenticates with DocuSign via JWT grant (one-time browser consent, then fully automated)
  5. Uploads the converted template to DocuSign via the REST API

Prerequisites

  • Python 3.10+
  • An Adobe Sign OAuth app (EU2 shard) with scopes: library_read:self library_write:self user_read:self
  • A DocuSign developer account with an integration key and RSA keypair

Setup

1. Install Python dependencies:

pip install -r requirements.txt

2. Create a .env file in the project root (never commit this):

cp .env-sample .env

Then fill in your credentials. See .env-sample for the full list of variables with descriptions. Use account-d.docusign.com and https://demo.docusign.net/restapi for sandbox; for production replace with account.docusign.com and your account's base URL (e.g. https://na3.docusign.net/restapi).

3. Authenticate with Adobe Sign (one-time):

python3 src/adobe_auth.py

Opens a browser. After authorizing, paste the redirect URL back into the terminal. Tokens are saved to .env and auto-refreshed on subsequent runs.

4. Grant consent for DocuSign (one-time per user):

python3 src/docusign_auth.py --consent

Opens a browser for the DocuSign OAuth consent screen. After approving, paste the redirect URL back into the terminal. This grants the impersonation scope required for JWT grant. After this runs once, all subsequent API calls use JWT automatically — no further browser interaction needed.


Running a migration

List available templates in Adobe Sign:

python3 src/download_templates.py list

Download templates:

python3 src/download_templates.py download                  # all templates
python3 src/download_templates.py download "Template Name" # one specific template

Downloads to downloads/<template-name>__<id>/ — one folder per template containing metadata.json, form_fields.json, documents.json, and the PDF.

Convert a downloaded template to DocuSign format:

python3 src/compose_docusign_template.py

Writes DocuSign template JSONs to migration-output/<template-name>/docusign-template.json.

Upload to DocuSign:

python3 src/upload_docusign_template.py --file migration-output/<name>/docusign-template.json

Or run the full pipeline end-to-end:

python3 src/migrate_template.py --list                      # show available templates
python3 src/migrate_template.py --template "Template Name"  # download → convert → upload
python3 src/migrate_template.py --template "Template Name" --skip-upload  # convert only

If multiple templates share the same name, the most recently modified one is used.


Field type mapping

See field-mapping.md for the full Adobe Sign → DocuSign tab type table, conditional logic mapping, and known gaps.

Known API quirks and bugs

See tests/PLATFORM-QUIRKS.md for documented platform bugs, unexpected API behaviors, and the fixes applied.


Project structure

src/
  adobe_auth.py                  # One-time OAuth flow for Adobe Sign
  adobe_api.py                   # Adobe Sign API client (auto token refresh)
  download_templates.py          # List and download templates from Adobe Sign
  compose_docusign_template.py   # Core conversion: Adobe Sign → DocuSign JSON
  docusign_auth.py               # DocuSign JWT auth + one-time consent flow
  upload_docusign_template.py    # Upload a template JSON to DocuSign REST API
  migrate_template.py            # End-to-end runner (download → convert → upload)
  create_adobe_template.py       # Utility: create a test template in Adobe Sign
  generate_pdfs.py               # Utility: generate sample PDFs for offline testing

downloads/                       # Downloaded Adobe Sign templates (gitignored)
migration-output/                # Converted DocuSign template JSONs (gitignored)
sample-templates/                # JSON fixtures for offline testing (PDFs gitignored)

field-mapping.md                 # Field type mapping table + edge case log
tests/PLATFORM-QUIRKS.md         # Known bugs and API quirks
requirements.txt                 # Python dependencies