SignNow trades a client credential for a Bearer token on every call, then copies, prefills, and invites in three separate steps. Anvil is one key and one call.
Type both into Claude Code: the first adds Anvil's plugin catalog, the second installs the SignNow plugin. Then ask Claude to migrate.
The mental model
A SignNow document built from a template becomes an Anvil Etch packet built from a Cast, and SignNow’s roles, coordinate fields, field invites, embedded invites, and event subscriptions 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.
Two handshakes disappear
Most of this migration is deletion. The OAuth token exchange goes away against Anvil’s long-lived key, and the three-step copy, prefill, invite send becomes one createEtchPacket.
export-signnow-templates.ts
Exports your templates as PDFs with a metadata manifest of roles, fields, and coordinates. Standalone, with no SignNow SDK required.
SignNow 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.
SignNow
Anvil
What it is
Document
Etch packet
The signing transaction. createEtchPacket returns an etchPacketEid.
Template (template id)
Cast (castEid)
A reusable PDF with positioned fields.
Role ("Signer 1")
Signer id
A named signing slot; in Anvil an arbitrary signer id you map to fields.
Field / element
Field
A positioned box with x, y, and page number, assigned to a role.
field_name / label
Field alias (aliasId)
Your data key for a field.
prefill-texts
Fill data (data.payloads)
Prefilled field values.
Field invite
createEtchPacket signers + fields[]
Sends the document to role-mapped signers.
Invite order
routingOrder
Signing order; equal values sign in parallel.
Embedded invite + /link
signerType: 'embedded' + generateEtchSignURL
In-app signing, with no email sent.
Event subscription
createWebhookAction
Event delivery.
document.complete
etchPacketComplete
All recipients signed; documents downloadable.
OAuth2 Bearer token
ANVIL_API_KEY
Auth. One key, with no token exchange and no client id or secret.
What the rewrite looks like
SignNow needs three calls to send from a template: copy, prefill, then invite. Anvil does all three in one synchronous call.
Before – SignNow
// 1. Create a document from the template.const copyRes =awaitfetch(`https://api.signnow.com/template/${templateId}/copy`,{ method:'POST', headers:{...headers,'Content-Type':'application/json'}, body:JSON.stringify({ document_name:'NDA for Acme Corp'}),})const{ id: documentId }=await copyRes.json()// 2. Prefill non-signature fields.awaitfetch(`https://api.signnow.com/v2/documents/${documentId}/prefill-texts`,{ method:'PUT', headers:{...headers,'Content-Type':'application/json'}, body:JSON.stringify({ fields:[{ field_name:'CompanyName', prefilled_text:'Acme Corp',}],}),})// 3. Send a role-based field invite.awaitfetch(`https://api.signnow.com/document/${documentId}/invite`,{ method:'POST', headers:{...headers,'Content-Type':'application/json'}, body:JSON.stringify({from:'sender@yourco.com', to:[{ email:'jane@example.com', role:'Signer 1', order:1,}], subject:'Please sign this NDA', message:'Hi, please review and sign the attached NDA.',}),})
Anvil sends synchronously on create unless isDraft is true, so the copy, prefill, and invite sequence collapses into this one call.
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 SignNow 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 SignNow 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 same – A direct equivalent – nothing to decide.
Minor change – The same capability, reached a different way in the API call.
Plan for rework – Supported, but you will write code for it.
Two-step OAuth
Works the same
Replaced by a single long-lived API key. The token exchange and refresh logic are deleted, not ported.
Signing order
Works the same
routingOrder is a direct equivalent; equal values sign in parallel.
Embedded signing
Works the same
An embedded invite plus its /link becomes generateEtchSignURL in AnvilEmbedFrame.
Roles and prefill
Minor change
Roles become signer ids and prefill-texts becomes a data payload keyed by field alias.
Signing history and audit trail
Minor change
Anvil bundles the certificate into the download zip, so it is one download instead of two.
CC and non-signing recipients
Minor change
Becomes a non-signing recipient or an app-level notification; a one-time decision per flow.
Invite expiration and reminders
Plan for rework
Handled as app-level scheduling if hard deadlines or reminders matter.
Bulk and mass send
Plan for rework
A loop over createEtchPacket instead of a batch call; the client handles rate limiting.
Signer authentication (phone, SMS, password)
Plan for rework
Build an auth wall in front of the sign URL if verification is compliance-critical.
OAuth multi-tenant
Plan for rework
SignNow’s 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.