GraphQL Guide

The GraphQL API gives you insight into your account and the objects it owns, allow you to create, update, start, and submit data to both workflows Etch e-sign packets.

First check out the API getting started article to learn how to get an API key and use it to authenticate to the API. Additionally, brushing up on our terminology will be helpful in understanding the queries below.

GraphQL Reference

This guide will help you get started using common queries and mutations. For a complete list of queries, mutations, and types see the GraphQL reference.

Postman Collection

To get you and running with the GraphQL API without writing code, see the examples in our GraphQL Postman Collection.

Node Client

We have created the @anvilco/anvil Node.js client to help our users interact with our API more easily. It helps to simplify.

  • Authentication
  • Common GraphQL calls
  • Raw REST and GraphQL calls
  • GraphQL calls involving binary file uploads

Your First Query

All queries are POSTs to a single URL: https://graphql.useanvil.com.

A good place to start is with the currentUser query. This query will return your API user with all the main objects (etchPackets: Etch e-sign packets, casts: PDF templates, welds: workflows, and forges: web forms) on your account.

POST https://graphql.useanvil.com
{
currentUser {
eid
organizations {
eid
name
slug
casts {
eid
name
config
}
etchPackets {
eid
name
isTest
status
detailsURL
}
welds {
eid
title
config
forges {
eid
name
config
}
}
}
}
}

Queries of Note

currentUser

Returns the currently logged in user. You can generally get a lot of what you may need from this query.

currentUser: User

Workflow Queries

weld

Fetching the weld is the best way to fetch the data submitted to a given workflow (weld). An instance of a workflow is called a weldData.

weld(
organizationSlug: String!,
slug: String!,
): Weld
POST https://graphql.useanvil.com
{
weld(organizationSlug: ..., slug: ...) {
id
eid
slug
title
// weldDatas is paginated via the limit & offset options
// Other options:
// * isTest - show only test items; default: false
// * isArchived - show only archived items; default: false
// * statuses - Array use like ['completed'] to get only completed items
weldDatas (offset: $offset, limit: $limit, ...) {
rowCount
pageCount
page
pageSize
items {
id
eid
displayTitle // The title of the submission
status // created, in-progress, ready-to-sign, awaiting-signatures, completed
isComplete // true when submissions complete, but not yet signed
isCompleteAndSigned
isTest
completionPercentage // 0 to 1
numberRemainingSigners
// DocumentGroup is the group of output PDFs. This will be null until
// all submissions are complete and the signature process has been
// kicked off
documentGroup {
id
eid
status // uninitialized, sent, partial, completed, voided, declined
currentRoutingStep // where in the routing order things are
signers {
id
eid
status // sent, completed, voided
name
email
routingOrder
}
}
}
}
}
}

See our example on Postman here.

weldData

Fetch a single weldData from a weld.

weldData(
eid: String!,
): WeldData
POST https://graphql.useanvil.com
{
weldData(eid: ...) {
id
eid
displayTitle // The household name
status // created, in-progress, ready-to-sign, awaiting-signatures, completed
isComplete // true when submissions complete, but not yet signed
isCompleteAndSigned // true when status === 'completed'
isTest
completionPercentage // 0 to 1
numberRemainingSigners
// DocumentGroup is the group of output PDFs
documentGroup {
...
}
// There will be one submission for Admin Details, Client Details, each account
submissions {
id
eid
// created, in-progress, completed, waiting-to-sign,
// users-turn-to-sign-email, users-turn-to-sign-ui,
// user-signed-and-waiting, someone-else-signed-and-waiting
status
// On Client Details, this is the URL the client will fill out
continueURL
forge {
id
eid
name // Client Details, Account Transfer, etc.
}
}
}
}

See our example on Postman here.

Workflow Mutations

forgeSubmit

forgeSubmit allows you to create new submissions and update data for a given workflow. Use forgeSubmit only if you need total programmatic control. A simpler way to start workflows is with our Form UI URLs.

Any time data is submitted to a workflow, it flows through forgeSubmit. There are a couple situations forgeSubmit handles:

  1. Starting a workflow. Use forgeSubmit to create a brand new WeldData and Submission on a given Weld. e.g.
  2. Submitting data to an existing Submission. After a workflow has been started, you can submit data to the Submission, adding data to the payload or overwriting data already in the payload
  3. Continuing a workflow. When there are multiple web forms that need to be filled to complete a workflow, forgeSubmit can create a Submission for an unstarted Forge.
forgeSubmit (
forgeEid: String!,
weldDataEid: String,
submissionEid: String,
payload: JSON!,
currentStep: Int,
complete: Boolean,
isTest: Boolean=false,
timezone: String,
webhookURL: String,
): Submission

Starting A Workflow

Starting a workflow entails passing a forgeEid and an optional payload. It will return a new Submission on the specified Forge with a new WeldData. Learn about how to enable webhooks in the webhook docs.

// Create a Submission and a WeldData
forgeSubmit({
variables: {
forgeEid: forge.eid,
complete: false,
isTest: false,
// Seed the submission with data here...
payload: {},
// optional webhook URL for actions taken on the new
// WeldData, Submission, and Signers. You must first
// enable webhooks.
webhookURL: 'https://mysite.com/anvil-webhook',
},
})
// => submission: {
// eid: 'abc123'
// payload: {} // the actual data
// weldData: {
// eid: 'def456'
// }
// forge: {
// eid: 'ghi789'
// }
// }
// UI URL for this Forge Submission is
// https://app.useanvil.com/form/${organization.slug}/${forge.slug}/abc123

Submitting Data

Submitting data to the created submissions requires the forgeEid, weldDataEid, and submissionEid.

forgeSubmit({
variables: {
forgeEid: forge.eid,
weldDataEid: subimssion.weldData.eid,
submissionEid: subimssion.eid,
payload: {
// payload keys correspond to the `id` of a forge field
email: 'bobby@tables.com'
},
complete: false,
},
})

Continuing A Workflow

Say you have a workflow with 2 webforms: Admin Form and Client Form. There will be two Forges, one for Admin Form and one for Client Form. In order to complete the workflow, there needs to be one WeldData with two completed Submissions, one Submission for the Admin Form Forge, and one for the Client Form Forge.

Often in this situation, there will already be a WeldData and one Submission, the other Submission just needs to be created. Create the other submission this way:

forgeSubmit({
variables: {
forgeEid: clientForge.eid,
weldDataEid: subimssion.weldData.eid, // the weldData.eid that was created earlier
payload: {},
complete: false,
isTest: false,
},
})
// => submission: {
// eid: 'abcdef'
// payload: {} // the actual data
// weldData: {
// eid: 'def456'
// }
// }
// UI URL for this Forge Submission is
// https://app.useanvil.com/form/${organization.slug}/${clientForge.slug}/abcdef

Look through our example in code on Postman here.

E-Signature Mutations

createEtchPacket

The createEtchPacket mutation allows you to create and send an Etch Packet in a single API call. This is the most common, and often the only, Etch-related API mutation you will need. This mutation will create an Etch template and related Etch packet, and returns the EtchPacket.

See the main Etch e-sign guide for more details on createEtchPacket and related calls.

Here is the GraphQL schema for the mutation:

createEtchPacket (
name: String,
isDraft: Boolean,
isTest: Boolean,
signatureEmailSubject: String,
signatureEmailBody: String,
signaturePageOptions: JSON,
signers: [JSON!],
data: JSON,
files: [JSON!],
webhookURL: String,
): EtchPacket

In addition to this basic GraphQL schema, there is a more detailed JSON Schema that mutation arguments are also validated against:

name: (string) The name of the Etch Packet to be created
isDraft: (boolean) Boolean indicating whether the newly created Etch Packet is still in draft mode or not. If set to false, a document group will be created and the first email will be sent out (if applicable).
isTest: (boolean) Boolean indicating whether this Etch Packet is just a test. What happens if it is a test? I do not know.
signatureEmailSubject: (string) The subject line for emails sent to Signers. Default: default description here
signatureEmailBody: (string) The body for emails sent to Signers. Default: Some body default
signaturePageOptions: (object) Options for the signature pages.
signers: (array[EtchSigner]) Specify signers, attach them to signature-related fields, and even override default properties for them.
data: (EtchFillData) Structure that allows for providing payload data for PDFs in the Etch Packet, as well as for providing/overriding signer information.
files: (array[EtchUpload|EtchCastReference]) required An array containing the files to be created and/or associated with this Etch Packet. The array can contain a mixture of the supported types.
webhookURL: (string) A custom webhookURL for actions taken by this packet's signers. Webhooks must be enabled in your account before using this.

Here is an example mutation showing a relatively complex setup:

createEtchPacket({
variables: {
draft: false,
isTest: false,
name: 'A New Etch Packet',
signers: [
{
id: 'signer1',
fields: [
{ fileId: 'existingCast1', fieldId: 'signatureOne' },
{ fileId: 'newFile1', fieldId: 'signatureThree' }
],
name: 'Signer One',
email: 'signer1@example.com',
routingOrder: 1,
signerType: 'embedded',
redirectURL: 'https://mysite.com/signup-complete'
},
{
id: 'signer2',
fields: [
{ fileId: 'existingCast1', fieldId: 'signatureTwo' },
{ fileId: 'newFile1', fieldId: 'signatureFour' }
],
name: 'Signer Two',
email: 'signer2@example.com',
routingOrder: 2
}
],
files: [
{
id: 'existingCast1',
castEid: existingCast.eid,,
fontSize: 11,
textColor: '#abc123'
},
{
id: 'newFile1',
file: <Upload>, // See Upload reference for more details
fontSize: 11,
textColor: '#abc123',
fields: [
{
id: 'signatureThree',
type: 'signature',
pageNum: 1,
rect: { x: 203.11, y: 171.11, width: 33.11, height: 27.11 }
},
{
id: 'signatureFour',
type: 'signature',
pageNum: 2,
rect: { x: 253.12, y: 121.12, width: 33.22, height: 27.22 }
},
{
id: 'fieldOne',
type: 'text',
pageNum: 1,
rect: { x: 253.12, y: 121.12, width: 33.22, height: 27.22 }
},
]
},
],
data: {
signers: {
signer1: { email: 'overridden@example.com' },
signer2: { name: 'Overridden Signer Two' }
},
payloads: {
newFile1: { data: { fieldOne: 'New File Field One Value' } },
existingCast1: { data: { fieldOne: 'Existing Cast Field One Value' } }
}
}
}
})

Get started today

Start filling, generating, and signing PDFs from your app. Every account comes with free access to the Developer API.