← All migration plugins

Migrate from Xodo Sign to Anvil

Xodo Sign is eversign under the hood, and your integration still calls api.eversign.com. The plugin maps that API surface to Anvil and moves your templates across.
Install in Claude Code
/plugin marketplace add anvilco/anvil-plugins
/plugin install xodosign-anvil-migration@anvil-plugins
Type both into Claude Code: the first adds Anvil's plugin catalog, the second installs the Xodo Sign plugin. Then ask Claude to migrate.
The mental model
An eversign document built from a template becomes an Anvil Etch packet built from a Cast, and its signer roles, positioned form fields, merge fields, embedded signing, and log events become Anvil signer IDs, field aliases, embedded signers, and webhook actions.
Cast is Anvil's word for a template: a reusable document with named fields your code fills through the API.

Xodo Sign is eversign

Xodo Sign is the current brand for eversign, now part of Apryse. There is no separate API – same api.eversign.com host, same eversign package – so the plugin triggers on both names.
export-xodosign-templates.ts
Lists your templates, downloads each as a PDF, and writes a manifest of roles, recipients, and fields. Uses fetch, with no eversign SDK required.

Xodo Sign to Anvil, term by term

Most of a migration is vocabulary. Here is the map the plugin works from – it keeps these names straight so you do not have to.
Xodo SignAnvilWhat it is
DocumentEtch packetThe signing transaction. createEtchPacket returns an etchPacketEid.
document_hashetchPacketEidThe document identifier.
Template (template_id)Cast (castEid)A reusable PDF template with positioned fields.
Signer roleSigner idA named signing slot; in Anvil an arbitrary signer id you map to fields.
Form fieldFieldA positioned signable or fillable box, each with a type and x, y, and page.
Field identifierField alias (aliasId)Your data key for a field.
Merge field valueFill data (data.payloads)Prefilled field values.
order + use_signer_orderroutingOrderSigning order; equal values sign in parallel.
embedded_signing_urlsignerType: 'embedded' + generateEtchSignURLIn-app signing, with no email sent.
document_completedetchPacketCompleteAll signers done; documents downloadable.
sandboxisTestWatermarked, non-billed test documents.
access_key + business_idANVIL_API_KEYAuth. One key, with no business selection.

What the rewrite looks like

The eversign SDK builds a document from Template, Signer, and Field objects. Anvil takes the same information as one plain variables object.
Before – Xodo Sign (eversign)
const { Client, Template, Signer, Field } = require('eversign')
const client = new Client(apiKey, businessId)

const template = new Template()
template.setTemplateId('tmpl_abc123')
template.setTitle('NDA for Acme Corp')
template.setMessage('Please review and sign the attached NDA.')

const signer = new Signer()
signer.setRole('Client')
signer.setName('Jane Smith')
signer.setEmail('jane@example.com')
template.appendSigner(signer)

const field = new Field()
field.setIdentifier('company_name')
field.setValue('Acme Corp')
template.appendField(field)

const doc = await client.createDocumentFromTemplate(template)
const documentHash = doc.getDocumentHash()
After – Anvil
const {
  data,
  errors,
} = await anvilClient.createEtchPacket({
  variables: {
    files: [ ... ],
    data: { ... },
    signers: [ ... ],
  },
})

How the migration runs

The plugin works through six steps, showing you what it found and what it plans to change before it touches your Xodo Sign integration.
Step 1 of 6
Discovery
Scans your codebase for every integration point – SDK imports, API calls, environment variables, webhook handlers, and database columns holding provider IDs.

Where Xodo Sign and Anvil differ

No migration is a pure find-and-replace. These are the gaps the plugin raises during mapping – each tagged with what it will cost you to close, from a straight swap to a decision worth making up front.
Works the sameA direct equivalent – nothing to decide.
Minor changeThe same capability, reached a different way in the API call.
Plan for reworkSupported, but you will write code for it.
Signing order
Works the same
routingOrder is a direct equivalent; equal values sign in parallel.
Embedded signing
Works the same
The embedded signing URL becomes generateEtchSignURL in AnvilEmbedFrame.
Signer roles and merge fields
Minor change
Roles become signer ids; field identifiers and values become a data payload keyed by alias.
Cancelling a document
Minor change
Handled as an app-level state change or a packet void.
White labeling
Minor change
Anvil uses CSS themes: more powerful, but you supply a CSS file.
"Require all signers"
Minor change
Implicit in Anvil. Worth confirming whether the flag carried real behaviour in your flow.
Recipients (CC)
Minor change
Becomes a non-signing recipient or an app-level notification; a one-time decision per template.
Document metadata (meta)
Plan for rework
Anvil packets have no metadata bag, so this becomes a schema addition on your side. The data is not lost, just stored by you.
Expiration and auto-reminders
Plan for rework
Handled as app-level scheduling if hard deadlines or reminders matter.
Bulk sending
Plan for rework
A loop over createEtchPacket instead of a batch call; the client handles rate limiting.
Signer authentication (PIN, SMS)
Plan for rework
Build an auth wall in front of the sign URL if verification is compliance-critical.
Multiple businesses
Plan for rework
eversign scopes calls to a business id, and OAuth lets your app act for other accounts. Anvil supports this: register an Anvil OAuth app for each tenant to authorize, or give each tenant a child organization with its own API key. Both are Enterprise features.

Coming from somewhere else?

We publish a purpose-built migration plugin for each of these too.
See every migration plugin

Get a demo
(from a real person)

Schedule some time on our calendar to talk through your specific use case and see which Anvil products can help.
    Want to try Anvil first?
    Want to try Anvil first?