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 POST
s 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 {eidorganizations {eidnameslugcasts {eidnameconfig}etchPackets {eidnameisTeststatusdetailsURL}welds {eidtitleconfigforges {eidnameconfig}}}}}
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!,): WeldPOST https://graphql.useanvil.com{weld(organizationSlug: ..., slug: ...) {ideidslugtitle// 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 itemsweldDatas (offset: $offset, limit: $limit, ...) {rowCountpageCountpagepageSizeitems {ideiddisplayTitle // The title of the submissionstatus // created, in-progress, ready-to-sign, awaiting-signatures, completedisComplete // true when submissions complete, but not yet signedisCompleteAndSignedisTestcompletionPercentage // 0 to 1numberRemainingSigners// DocumentGroup is the group of output PDFs. This will be null until// all submissions are complete and the signature process has been// kicked offdocumentGroup {ideidstatus // uninitialized, sent, partial, completed, voided, declinedcurrentRoutingStep // where in the routing order things aresigners {ideidstatus // sent, completed, voidednameroutingOrder}}}}}}
See our example on Postman here.
weldData
Fetch a single weldData from a weld.
weldData(eid: String!,): WeldDataPOST https://graphql.useanvil.com{weldData(eid: ...) {ideiddisplayTitle // The household namestatus // created, in-progress, ready-to-sign, awaiting-signatures, completedisComplete // true when submissions complete, but not yet signedisCompleteAndSigned // true when status === 'completed'isTestcompletionPercentage // 0 to 1numberRemainingSigners// DocumentGroup is the group of output PDFsdocumentGroup {...}// There will be one submission for Admin Details, Client Details, each accountsubmissions {ideid// 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-waitingstatus// On Client Details, this is the URL the client will fill outcontinueURLforge {ideidname // 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:
- Starting a workflow. Use
forgeSubmit
to create a brand newWeldData
andSubmission
on a givenWeld
. e.g. - Submitting data to an existing
Submission
. After a workflow has been started, you can submit data to theSubmission
, adding data to thepayload
or overwriting data already in thepayload
- Continuing a workflow. When there are multiple web forms that need to be filled to complete a workflow,
forgeSubmit
can create aSubmission
for an unstartedForge
.
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 WeldDataforgeSubmit({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 fieldemail: '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 Forge
s, 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 earlierpayload: {},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: <GraphQLUpload>, // See GraphQLUpload reference for more detailsfontSize: 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' } }}}}})