INTRODUCTION
Welcome to the Juro API!
Juro is a platform for automating legal contract workflows, integrating contracts with data sources and managing contract lifecycles.
The Juro API allows you to integrate, generate, and e-sign contracts, be notified of contract activity and query your existing contract stack for structured data about the contract itself and any associated metadata. Gain insight into your contract pipeline, obligations and terms in a machine readable form.
We have setup webhooks so that you can have an easy way of subscribing to events happening on your account, with your contracts.
TUTORIAL
Templates and contracts
A contract in Juro usually is built on top of a generic template. You can create unlimited number of contracts based on a template with infinite variations to either the text of the contract or it's input data.
Contract templates in Juro consist of two main elements, body and smartfields:
(1) Main body
The main body is where most of the legal language is typically incorporated in templates and this part doesn’t change with each instance of a contract created from that template.
(2) Smartfields
Smartfields are dynamic elements in a template, which can either be integrated with data sources (smartfield replacements) or linked to a Q&A and help texts in our user interface.
Smartfields can be populated by either the contract owner and/or the counterparty. Populating smartfields is done through the contract create method sending fields property or the counterparty answering questions in a Q&A flow immediately prior to signing.
In the latter case, before signing, the counterparty will be prompted to answer a few questions when the signing link is clicked, which will populate smartfields or potentially affect smartfield replacements.
Signatures
The counterparty signature should be acquired by the counterparty following a Juro signing link reading the terms and signing the contract in accordance with Juro’s electronic signing tool. This will verify the identity of the signatory and deliver an immutable audit trail.
Electronic signature for the owner side should be sent in base64 format. It should be image/png encoded in base64 format with the dimensions (475x175 pixels).
Contract lifecycle
The first phase of the lifecycle of your contract starts when you first create a draft contract instance from a template and ends in the fully_signed status, at which point all participants have signed the contract and it becomes legally binding and immutable.
After all signatures are saved and updated on your contract, the contract will automatically be moved to fully signed status. That will indicate that you can now access a pdf of the contract signed by all parties (which is emailed to both parties by default) and the contract and its audit trail becomes immutable.
If you get any comments on the contract in question from your counterparties, the contract owner will be notified via email (or Slack if integrated) and will need to reply to comments via Juro’s UI.
The second phase of your contract (post signing) incorporates key obligation milestones, execution of particular contract terms and culminates in a renewal of that contract. Coming soon to the Juro API...
- draft - until you sign yourself or send to someone for signing
- sent for approval - you have sent the contract and waiting for it to be approved
- approved - everyone has approved the contract
- rejected - one of the approvers has rejected the contract
- sent for signing - you have sent the contract and waiting for it to be signed
- signed by us - signed by a Juro user but not a counterparty
- signed by them - signed by counterparty but not a Juro user
- fully signed - everyone has signed the contract
Getting started
To process your first contract you will need to follow these steps:
- Get your
API Key
; - Get the id of your template to use for the contract generation (e.g. sample NDA template);
- Pass all the necessary information for the contract to be created;
- After you have generated the contract you can now send it for signing as well as sign yourself;
- When the contract is signed you will be able to download the pdf of the fully signed contract.
Responding to events
A lot of integration cases revolve around syncing information between multiple systems (for example, pulling data out of an opportunity in Salesforce) and triggering events (for example uploading a pdf of fully signed contract to an opportunity in Salesforce).
You can use webhooks to subscribe to events and then decide what you want to do when that event happens. The following is a list of events currently supported by Juro.
Sandbox
Sandbox is an environment to let developers build and test application without any disruption and risk to live data.
To start using sandbox environment simply replace URL from https://api.juro.com
to https://api-sandbox.juro.io
.
Please contact us to get access to sandbox environment.
AUTHENTICATION
Getting an authentication token
Open API page
Click
Generate API key
API setup is now complete!
Authenticating your API calls
Make sure to replace <API_KEY> with your API key.
You have multiple ways of authenticating with Juro API. The simplest way is to use an API key provided to you when you have created an account within Juro.
Please don't forget to include the API key in all of your requests. You can easily do that by adding x-api-key
to your headers.
x-api-key: YourAPIKey
HEALTH
Check Juro health
Request
request.get({
headers: { 'x-api-key': <API_KEY> },
url: 'https://api.juro.com/v3/health'
})
Example Response
{
"message": "ok"
}
It's really easy to see if Juro is experiencing any health related issues. Fingers crossed. Use this to quickly check that your API key is correct and you have access to the API.
HTTP Request
GET /v3/health
TEMPLATES
Templates are a core part of your contract management flow. You should have a template to create your contracts from. No template, no contract it's that simple.
Get all available templates
Request
request.get({
headers: { 'x-api-key': <API_KEY> },
url: 'https://api.juro.com/v3/templates'
})
Example Response
{
"templates": [
{
"id": "5de9227402e24204247757c4",
"createdDate": "2018-06-25T14:04:08.804Z",
"name": "Infinity template",
"status": "published",
"updatedDate": "2018-06-25T14:20:39.564Z"
}
]
}
You first want to get all templates to correctly select the one that you are going to use to create your contract.
HTTP Request
GET /v3/templates
Get a specific template
Request
request.get({
headers: { 'x-api-key': <API_KEY> },
url: 'https://api.juro.com/v3/templates/:template_id'
})
Example Response
{
"template": {
"id": "5de9227402e24204247757c4",
"createdDate": "2019-12-05T15:29:56.821Z",
"draftLink": {
"url": "https://app.juro.com/s1tEGduYQ",
"isEnabled": true,
"enabledUntilDate": "2019-12-13T00:00:00.000Z"
},
"fields": [
{
"title": "address",
"type": "text",
"uid": "2d6f2279-dee8-4e17-ad1d-e18cb6b8acc0",
"value": ""
},
{
"choices": [
{
"value": "private"
},
{
"value": "public"
}
],
"title": "address type",
"type": "choice",
"uid": "076fafa9-ff61-4eeb-b8a5-a8dfe0e2ae58",
"value": "private"
}
],
"internalUrl": "https://app.juro.com/sign/5de9227402e24204247757c4",
"name": "Infinity template",
"sharingUrl": "https://app.juro.com/RYlhvBEgN",
"status": "published",
"updatedDate": "2019-12-05T15:53:40.069Z",
"questions": [
{
"isRequired": true,
"signingSideUids": [
"491c1a5a-7db2-400f-ae34-ab1405027763"
],
"text": "",
"title": "What is the name of the other party?",
"uid": "counterparty_legal_name"
},
{
"isRequired": true,
"signingSideUids": [],
"text": "This is to help us verify your identity and for security reasons",
"title": "For access, please confirm your name",
"uid": "signatory_name"
},
{
"isRequired": true,
"signingSideUids": [],
"text": "This is the email address that we will send the signed contract to",
"title": "What is your email address?",
"uid": "signatory_email"
},
{
"fieldUid": "2d6f2279-dee8-4e17-ad1d-e18cb6b8acc0",
"isRequired": true,
"signingSideUids": [
"fcfedf27-2b20-49ef-b408-3544c16dc064"
],
"text": "",
"title": "Please provide your address",
"uid": "f6459a85-ba52-4fd5-94d2-27cf27d11c55"
},
{
"fieldUid": "076fafa9-ff61-4eeb-b8a5-a8dfe0e2ae58",
"isRequired": false,
"signingSideUids": [
"fcfedf27-2b20-49ef-b408-3544c16dc064"
],
"text": "",
"title": "Is this your public or private address?",
"uid": "7addc6ac-2076-43af-8346-d5d137993c45"
}
],
"signingSides": [
{
"name": "Juro Unlimited",
"signatures": [
{
"signingUrl": "https://app.juro.com/sign/5de9227402e24204247757c4",
"uid": "c9a78e60-8522-4ecc-a3fb-22da233f249d",
"username": "user@juro.com"
}
],
"uid": "491c1a5a-7db2-400f-ae34-ab1405027763"
},
{
"name": "Infinity industries",
"signatures": [
{
"email": null,
"signingUrl": "https://app.juro.com/counterparty/sign/lXDZeHvAy",
"name": null,
"uid": "7b17e670-6c74-4d00-aa1c-54ead6666044"
}
],
"uid": "fcfedf27-2b20-49ef-b408-3544c16dc064"
}
],
"state": {
"approval": {
"approvers": [
{
"username": "user@juro.com"
}
]
}
},
"tables": [
{
"rows": [
[
{
"value": "first header"
},
{
"value": "second header"
}
],
[
{
"value": "first value"
},
{
"value": "second header value"
}
]
],
"uid": "8d5a30ab-0249-4735-b033-df06ea7facf1"
}
]
}
}
This endpoint retrieves a specific template.
HTTP Request
GET /v3/templates/:template_id
Response Body
Field | Description |
---|---|
id | template id |
createdDate | document creation date |
draftLink.url | draft link you would share with the outside world e.g. anonymous users |
draftLink.isEnabled | draft link can be disabled which cuts contract's access from the outside world |
draftLink.enabledUntilDate | draft link can be enabled until provided date which cuts contract's access from the outside world after date has passed |
fields | list of field items |
internalUrl | url for signed in Juro users |
name | template name |
questions | list of question items |
sharingUrl | url you would share with the outside world e.g. anonymous users |
signingSides | list of signing side items |
state | document state |
status | edit in progress or published document status |
updateDate | date when document was last updated |
CONTRACTS
Create a contract
Request
request.post({
headers: {
'content-type': 'application/json',
'x-api-key': <API_KEY>
},
url: 'https://api.juro.com/v3/contracts',
json: {
"templateId": "5de9227402e24204247757c4",
"contract": {
"answers": [
{
"uid": "counterparty_legal_name",
"value": "Infinity industries"
}
]
}
}
})
Example Response
{
"contract": {
"id": "5de92ae0bb0bf42c5ce2fe7c",
"createdDate": "2019-12-05T16:05:52.659Z",
"draftLink": {
"url": "https://app.juro.com/s1tEGduYQ",
"isEnabled": true,
"enabledUntilDate": "2019-12-13T00:00:00.000Z"
},
"fields": [
{
"title": "address",
"type": "text",
"uid": "2d6f2279-dee8-4e17-ad1d-e18cb6b8acc0",
"value": ""
},
{
"choices": [
{
"value": "private"
},
{
"value": "public"
}
],
"title": "address type",
"type": "choice",
"uid": "076fafa9-ff61-4eeb-b8a5-a8dfe0e2ae58",
"value": "private"
}
],
"internalUrl": "https://app.juro.com/sign/5de92ae0bb0bf42c5ce2fe7c",
"sharingUrl": "https://app.juro.com/s1tEGduYQ",
"name": "Infinity industries",
"owner": {
"name": "Name Surname",
"username": "user@juro.com"
},
"status": "draft",
"updatedDate": "2019-12-05T16:05:53.399Z",
"questions": [
{
"isRequired": true,
"signingSideUids": [
"491c1a5a-7db2-400f-ae34-ab1405027763"
],
"text": "",
"title": "What is the name of the other party?",
"uid": "counterparty_legal_name"
},
{
"isRequired": true,
"signingSideUids": [],
"text": "This is to help us verify your identity and for security reasons",
"title": "For access, please confirm your name",
"uid": "signatory_name"
},
{
"isRequired": true,
"signingSideUids": [],
"text": "This is the email address that we will send the signed contract to",
"title": "What is your email address?",
"uid": "signatory_email"
},
{
"fieldUid": "2d6f2279-dee8-4e17-ad1d-e18cb6b8acc0",
"isRequired": true,
"signingSideUids": [
"fcfedf27-2b20-49ef-b408-3544c16dc064"
],
"text": "",
"title": "Please provide your address",
"uid": "f6459a85-ba52-4fd5-94d2-27cf27d11c55"
},
{
"fieldUid": "076fafa9-ff61-4eeb-b8a5-a8dfe0e2ae58",
"isRequired": false,
"signingSideUids": [
"fcfedf27-2b20-49ef-b408-3544c16dc064"
],
"text": "",
"title": "Is this your public or private address?",
"uid": "7addc6ac-2076-43af-8346-d5d137993c45"
}
],
"signingSides": [
{
"name": "Juro Unlimited",
"signatures": [
{
"signingUrl": "https://app.juro.com/sign/5de92ae0bb0bf42c5ce2fe7c",
"name": null,
"uid": "c9a78e60-8522-4ecc-a3fb-22da233f249d",
"username": "user@juro.com"
}
],
"uid": "491c1a5a-7db2-400f-ae34-ab1405027763"
},
{
"name": "Infinity industries",
"signatures": [
{
"email": null,
"signingUrl": "https://app.juro.com/counterparty/sign/Mbl9vNYIk",
"name": null,
"uid": "7b17e670-6c74-4d00-aa1c-54ead6666044"
}
],
"uid": "fcfedf27-2b20-49ef-b408-3544c16dc064"
}
],
"state": {
"approval": {
"approvers": [
{
"username": "user@juro.com"
}
]
}
},
"tables": [
{
"rows": [
[
{
"value": "first header"
},
{
"value": "second header"
}
],
[
{
"value": "first value"
},
{
"value": "second header value"
}
]
],
"uid": "8d5a30ab-0249-4735-b033-df06ea7facf1"
}
],
"template": {
"id": "5de9227402e24204247757c4",
"name": "Infinity template"
}
}
}
This endpoint creates a contract.
Let's create a contract based on an example template. In example template we have just one question set as required, in this case it's an absolute minimum of inputs we should provide in order to create a contract.
HTTP Request
POST /v3/contracts
Body
Parameter | Required | Description |
---|---|---|
templateId | * | id of template |
answers | list of answer items | |
fields | list of field items | |
owner.username | contract owner | |
name | contract name | |
signingSides | list of signing side items | |
tables | list of table items |
Response Body
Parameter | Description |
---|---|
id | contract id |
createdDate | document creation date |
draftLink.url | draft link you would share with the outside world e.g. anonymous users |
draftLink.isEnabled | draft link can be disabled which cuts contract's access from the outside world |
draftLink.enabledUntilDate | draft link can be enabled until provided date which cuts contract's access from the outside world after date has passed |
fields | list of field items |
internalUrl | url for signed in Juro users |
name | contract name |
owner.name | |
owner.username | |
questions | list of question items |
sharingUrl | url you would share with the outside world e.g. anonymous users |
signingSides | list of signing side items |
state | document state |
status | contract status |
template.id | template id |
template.name | template name |
updateDate | date when document was last updated |
Get a specific contract
Request
request.get({
headers: { 'x-api-key': <API_KEY> },
url: 'https://api.juro.com/v3/contracts/:contract_id'
})
This endpoint retrieves a specific contract.
HTTP Request
GET /v3/contracts/:contract_id
Path params
Parameter | Required | Description |
---|---|---|
contract_id | * | The ID of the contract to retrieve |
Response body
For response body please refer to Create a contract
Update a contract
Request
request.patch({
headers: {
'content-type': 'application/json',
'x-api-key': <API_KEY>
},
url: 'https://api.juro.com/v3/contracts/:contract_id',
json: {
"contract": {
"fields": [
{
"uid": "2d6f2279-dee8-4e17-ad1d-e18cb6b8acc0",
"value": "Infinity Street"
},
{
"uid": "076fafa9-ff61-4eeb-b8a5-a8dfe0e2ae58",
"value": "public"
}
],
"name": "Infinity industries",
"signingSides": [
{
"signatures": [
{
"uid": "c9a78e60-8522-4ecc-a3fb-22da233f249d",
"username": "user@juro.com"
}
],
"uid": "491c1a5a-7db2-400f-ae34-ab1405027763"
},
{
"name": "Infinity industries",
"signatures": [
{
"email": "customer@infinity.uk",
"uid": "7b17e670-6c74-4d00-aa1c-54ead6666044"
}
],
"uid": "fcfedf27-2b20-49ef-b408-3544c16dc064"
}
],
"tables": [
{
"rows": [
[
{
"value": "updated"
},
{
"value": "table"
}
]
],
"uid": "8d5a30ab-0249-4735-b033-df06ea7facf1"
}
]
}
})
This endpoint updates an existing contract.
HTTP Request
PATCH /v3/contracts/:contract_id
Path params
Parameter | Required | Description |
---|---|---|
contract_id | * | The ID of the contract to make update request |
Body
Parameter | Required | Description |
---|---|---|
fields | list of field items | |
name | contract name | |
signingSides | list of signing side items | |
tables | list of table items |
Response body
For response body please refer to Create a contract
Delete a contract
Request
request.delete({
headers: {
'content-type': 'application/json',
'x-api-key': <API_KEY>
},
url: 'https://api.juro.com/v3/contracts/:contract_id'
})
Example Response
{
"message": "ok"
}
This endpoint deletes a specific contract.
HTTP Request
DELETE /v3/contracts/:contract_id
Path params
Parameter | Required | Description |
---|---|---|
contract_id | * | The ID of the contract to delete |
Sign your contract
Request
request.post({
headers: {
'content-type': 'application/json',
'x-api-key': <API_KEY>
},
url: 'https://api.juro.com/v3/contracts/:contract_id/sign',
json: {
"signatureBase64": "iVBORw0KGgoAAAANSUhEUgAAAdgAAAC4CAYAAABAWv13AAAWdElEQVR4Xu3df4gk+VnH8U/1zK1rArlNiJhE5e4CGhU1G8U7QpDbU4TN7Yy3h2BUhNuFQ/xHbheCgv/cnvhHVDCziAhidBckRFBul+k9FiPcbn5gUMLNxkT9IzFzgQvBeLK5mOTMznTJ8+2umerq6l/T9cx09/NuOHK5qXqqvq9vdT9V9f2ViQ8CCAQXOHtC2nlGyi41AHFX6lyQblxtIBYhEFhogWyhz56TRwCBGQUePymtvCjphJRLKv8k5HekbEvKt7sHyU5K+Ukpe2D4QS1G+rwm5WvSjU/OeILsjsDCCpBgF7bqOHEEmhBY25Kyd+9HSgnyjtQ+OTz66Z+SVs5KrXdK+Vkpu79//74kfUlqP9fEmRIDgUUTIMEuWo1xvgjMLJBeCT8lyV4LP1RKjvbEuiFtXpnuEOkpeEPKH+1/Ai6i5FvS6mPStbvTxWXrwxc48yGpdVHK70lak9q3Dv8clueIJNjlqUtKgsAEAmcuSK1nB18J5y9LqydnS4IWO/sTKav5XcmvSe0nJzhBNjkSgfWzUv6MpFP7N0n5c1K7iXb5IynRPByUBDsPtcA5IOAukH5An+22o+49WZbbXJ+UNq/Nfhr2NJu9ILXe3o211yZr//6sdOP3Zz8GEZoVWLc3FvZGo1dfe2lhW9osveFo9qgRopFgI9QyZQws8PjTUutPpex4DcJVaffvpGOfmu3JtY63+NEud5zKvy213xi4Muaw6GsbUmZPrr1PtaPb7nukF7bm8MQX4pRIsAtRTZwkAgcRsKfJ1j8NJld7Haxz/u1rZ/5Bav1i/5nfe0i62euVfJAysU9zAvZWQ8/3x8v/Xsp+uZRwH/O/Tpor0bxFIsHOW41wPgg0IlAMv8lPdMPZV73zcan10ek7MR30hE4/KN335coPOD/YB+VsdL9UNy912+L3nl4vS/nrUva7+9cMT7CzsJNgZ9FjXwTmUqDckWnvBK9Lm/bEcsiftbuVYTx0djrkGqg/3Lq1tz9R+ttVafOctPYlKXvn/n/njcMs1UWCnUWPfRGYK4E0/ObF/o5MdoI2YcSoca2ehSh3oNl7UqJ3qif52NjpBuzDpSfXUg/y9XKvNEmb5IixnsM3AG8GPHZFYH4ERiXX1VPNd2KatOR17Xy2L09Gkwo2v9361yR9/37c8mtgEmyT3iTYJjWJhcCRCazbhACPVg5/XVo5d3TJtTibte3u9IrFw5H97ORflPQ3Uud6t5fq+z8graxL2del3av0XPW8kM58R2r1epXn/yK1H94/Ggm2SXkSbJOaxELg0AXWz0mdP5BaP1B65fcNKb8k3dg49NOpPWDqzWw3APfXz/RkO/UND7kr5RvS6uWjvzmYD8HmzqJ4Pbz3Jrjyup4E25z18Ku9yWMQCwEEGhewxCqbkenBmtDnD6+n8KQFS72arddqzac69rJvExvSc42n2kmdR223ZrM02cIOpU+1lzAJtgnpIgZPsE1qEgsBd4G6xNo3mcMcdyBae0XK3jF9kt172vqKpP+Ust5NRW49lLekzi0pe5nxmuMuvmqPbt2WNk/177VW6eTUJkeMYx3xd/BmwGNXBA5PoG6qw/LRO69Iux+Ubn7s8M5p2iPZ2EtbhScrxl7av/dW8rHfdRuDWbQNlmOPfMKtnESxrcXSh1jJp+CpdjbLvyF1TvW3dadX+S+V5iK2sdPM5DTtZV7angQ7Ax67IuAvYK/17FVwVnnSKI5sP5TZhfl7JTypTOr9fHL/6TM9odt43fIYzUmDVdtybb/tbnvuzvW4M0iZ8e6nJf34PmTn4mAbfd1rfHp7T3HxDWxKgp1Fb+H3tS/UsW06ksxjRVqiyZ8anljTOc9JL2Evv3RzcUrKf09q3TfZUco9lat72LJ5uhjrVbK9NVi16RBtEYYeSP5Nqf2mQc90c/PX/f+dcbCTXXf1WwVLsO//Y2nlV6R01/8RqX15FrzF2ze9ArKhHNbZoTSrj3noc1Ln09KxP5w84aYvrz1pnJCyW9LKncn3XTw9/zNO9fNBKXvfkM5LxQ+kXb/nmln9xr9Usx/BrrPWr0mt75FUWZ80t8RRnu7PeiD/r7TyGzXDlorVfT4jtd87+3k1FcGeMO9Z+R6WUnmKFY+sLLek3c9J9z4u/eOnpjti6tRkyfVEfy/tfFNq/9JgrLVLUmYd54rPXWnzzdMdk63LAgESbJEE8t+UWqVXJMYQaY3KMy9JrdJSZcO+CHaX3zk/fBximsPUxjRarD+SsmOVSLao9jUpvxrrSWHWH5b09PARSa3RkfLL0uolbmQm8U6vPC9IubX13l9JMl+V9BdHOxQo/TbZMnG/I2VvqC9RX/vzhrR5cXzJ02v3Z6SsspZrerr/gtT+ifoYAwmW5erGY4/cYokTbLrInh/zis1wrI3m/PImg+IVUXkd0LFXjd05b0mZ2WxJr39WOv4L3aem2mEhQwLa3ffO+bhtX2OdrbnRrlN7LWdJYJijvWG4Iu1sYDmJaXWb1AZpN32P1hvbjXb6547/BBfpqdKSqr3+rhtiNaaA9p3KivHN9oR5u7tDegp+QmpZXHs7VXqq3ws5pkmhOoWi7ccr4oNcccU+S5pg052rvRopXcDjeiKm9hn7EVuSzhDVu9hq+e3HxIY4JKPqDECla2pkm1Z5we7KdbjX2/81KV+Tbnxylgt1OfetTspfV0f5Fem+KzyxNnEFrP2blP3YmEh2c/n57rvk3Ca+t5vMbalVWmJv523Sqk03WPO590ap9dX+RG1JtfMBKTsttaZMqqN+t9J37Dvdf7K3jCnX7W4P7mv2hmnIJ7V5V8bJMkxnlitvCRNseoVpF0n5Qr4t5fb/H5hwbo0r0r3nFvNpIZXf2lFq7mLTF7Jm4vfHH5BafytljwxeTGO/4MWX/LuVVVNKyTf/b2n1h0kShW56irGn1sqP7d5Nyb9LnV/3f5qa5adjUfdNr+LtnxE3laPKNu77MPQtxIib0eJ4nc9L2W/3v02zG+XvXpJWSouiF9uPe2jYK8fV7qvyUcnVtq0bpkOCneVKX8IEW25HSJ13zvZfsKl35kZ/MqgltDu9i4sz/CG9BrPEemHEBTFmybI01tI6OpTGJo66ROwpuPyElZL7pV7v1+oT7TVp9fz4L/ksl/O875te11+RsmE/7lele5cW88Zu3u2r55fqwr4r9mr+gaM7+/zlbp+FzpXRN1TV7+ZEZ3y9+1vXrnQMG7VvdSYnhulMJD1koyVMsOku7Eq3DWLnVP2PVUpG1o5hbSHjPnM47Vztj4W1N4/oxJRPMcNP+vGxpyt7CrbOEr0D5va618Zkbkk728MTQbqJ+UspW6mcqd20mKetRRnoU3RmsfGqdW1jVjerG7FvPo7ycki/GZZo7RXpmCfbJp5g7Xtkw2EO0qa+992sGb6URkfYd8t69F872PW09hUp+6H92qgbL3uUdbVYx17CBDtNBaREa0mkZmD73oww1hxjHX6u9dosrY3mtKSft2lOJNmMMaVP57jUsp6gX5Oy/+n/W27tJDb+7LXK3+5KnTdJ2dsl2R1tr33HpoSz9p/chsG8S7JXSPpo9043PS2+W9q1dp1f7R+qUBy1+MLN8lR05uek7LckfX38XXa5tANrThZ/NC+7AfoPqXNb6th0d49IrfdJ2atDas+2sTYwc+pINo7P9ks3AfbqzdrLsm7SP3538h+W4sdq5w3Sfd+qHNtu0H5aalmPS/vRqbRdFXVi9ZXd7J7b3sf2PS6tvK37OrJ849P3A31duneBJ9ZpvrOHsa1d8zojZb3vdpqasZiecUvavSfln61vh03X0rFeL/vy74J9h39U6vyrlP9ZM3VeHr7UudZMk8LA93ZLar/nMNSX8RjBE2y5SlPCsqfa3gwyTdypVi+Zw4w5D8M5ykuoHbTsZcOJ25yKGX3sBmjcsJcxHbUO0qY27jwXYVrDZfy5o0zjBepmc1p58+Q3reOPEGkLEuxAbdsdXPbhCZfVmsNrpa7d+ShP09rErV3YxiHO+hmXuA6ajGc9r0n3t/Y2axOjV/CkYmx3FALF+r17x34yXrNOM+4k2FrH1Ib4V1I2xOegT2Pe++WvSJ21Zl4VNXOBdaOkSd7vSK2a6dns75Mmzkm3K2Ja4GF1WJTPvU7u9DqxNPQKr8l6IRYCdQLr1oRT7p9yVdq0ntd8phQgwQ4Fs6EUafand/TaQHs9a/d+vK3NztoGv9gfwtpg9X9SZu2sr0ppSS2bqsza6H5Qyr+v/m+pDdaW8tqWskobbKfXfpO9Vcp+Zv946YnItrW2yQbbdqa8iibafG8llQe7bZI2bKrovWltqlaW7Avdttnqx+xsHKL9b7472AZbbL9q43otn40Y61eOXW6DXf324HE775Wyn5Ty/5JalZh7dWLT99l0ctZGZ3W31W0337FyfKaZtraJgNkIgYYEqivv2HW9+VBDwUOFIcFOXN3Fqh+2g3WwsY5GR/Vhkv6jkue4CMQQGFg79pBeE6c24Kd6N6kLP+kPCTbGt4VSIoAAAlMIVF8T2xSN7cemCHDATfvafxf+1TQJ9oCXAbshgAACyyuQRlV8uV"
}
})
Example Response
{
"message": "ok"
}
This endpoint allows for signing of a contract.
HTTP Request
POST /v3/contracts/:contract_id/sign
Path params
Parameter | Required | Description |
---|---|---|
contract_id | * | The ID of the contract to sign |
Body
Parameter | Required | Description |
---|---|---|
signatureBase64 | * | signature image encoded in base64 |
Send contract for signing
Request
request.post({
headers: {
'content-type': 'application/json',
'x-api-key': <API_KEY>
},
url: 'https://api.juro.com/v3/contracts/:contract_id/signing-request/:signing_side_uid',
json: {
"message": "We have the best contracts, you should sign them!"
}
})
Example Response
{
"message": "ok"
}
You can send a contract for signing with this. Cool, right?
- When contract signing order option is disabled the API client has full control of when to send contract for signing
- When contract signing order option is enabled the API client can initiate the signing process by sending contract for signing to the top priority signing side but all consequential signing requests will be sent automatically by Juro as soon previous signing side has signed the contract, so API client should provide message for each signing side prior the signing process has started or else recipients will receive signing requests without message.
HTTP Request
POST /v3/contracts/:contract_id/signing-request/:signing_side_uid
Path params
Parameter | Required | Description |
---|---|---|
contract_id | * | The ID of the contract to send for signing |
signing_side_uid | * | The UID of the signing side to send to for signing |
Body
Parameter | Required | Description |
---|---|---|
message | * | personalized message included in email body |
Send contract for signing by certain signatory
Request
request.post({
headers: {
'content-type': 'application/json',
'x-api-key': <API_KEY>
},
url: 'https://api.juro.com/v3/contracts/:contract_id/signing-request/:signing_side_uid/signatures/:signature_uid',
json: {
"message": "We have the best contracts, you should sign them!"
}
})
Example Response
{
"message": "ok"
}
You can send a contract for signing to a certain signatory with this. Cool, right?
- When contract signing order option is disabled the API client has full control of when to send contract for signing
- When contract signing order option is enabled the API client can initiate the signing process by sending contract for signing to the top priority signing side but all consequential signing requests will be sent automatically by Juro as soon previous signing side has signed the contract, so API client should provide message for each signing side prior the signing process has started or else recipients will receive signing requests without message.
HTTP Request
POST /v3/contracts/:contract_id/signing-request/:signing_side_uid/signatures/:signature_uid
Path params
Parameter | Required | Description |
---|---|---|
contract_id | * | The ID of the contract to send for signing |
signature_uid | * | The UID of the signing side's signature to send to for signing |
signing_side_uid | * | The UID of the signing side to send to for signing |
Body
Parameter | Required | Description |
---|---|---|
message | * | personalized message included in email body |
Download a PDF of your contract
Request
request.get({
headers: { 'x-api-key': <API_KEY> },
url: 'https://api.juro.com/v3/contracts/:contract_id/pdf/binary'
})
Example Response
content-disposition: attachment; filename="Pichael Mennington + Juro contract.pdf"
content-type: application/pdf
status: 200
binary data
This endpoint allows to download a PDF version of your contract.
- This method is rate limited with 1 req/s & burst of 5 requests
- When contract is an uploaded PDF the server will return ZIP instead. This is to preserve originals PDF AdES/QES
- Make sure that "follow redirects" is enabled on your end, because some PDFs are served from an external source, so the server will redirect instead of serving binary in response.
HTTP Request
GET /v3/contracts/:contract_id/pdf/binary
Path params
Parameter | Required | Description |
---|---|---|
contract_id | * | The ID of the contract |
ENTITY TYPES
Answer
{
"uid": "counterparty_legal_name",
"value": "Pichael Mennington"
}
An answer item is an answer to the question item and is particularly used only during contract creation. answer will populate field refered as fieldUid
in question
uid
- question uidvalue
- value for particular answer. Value will be propagated to the field linked in the question
Field
Request
{
"uid": "1530036548211_2cc498d4c72e442a81d0caeb709bbec3",
"value": "Pichael Mennington"
}
Response
{
"uid": "1530036548211_2cc498d4c72e442a81d0caeb709bbec3",
"title": "full name",
"type": "text",
"value": "Pichael Mennington"
}
A field entity looks like this:
uid
- unique idtitle
- smartfield titletype
- smartfield typecalendar
,choice
,companies
,email
,number
,text
,text area
value
- smartfield valuechoices
- list of values and is particularly used only forchoice
type field
Table
{
"uid": "8d5a30ab-0249-4735-b033-df06ea7facf1",
"rows": [
[
{ "value": "first header" },
{ "value": "second header" },
{ "value": "third header" }
]
]
}
Table in Juro is more like grid than a table, meaning it doesn't have headers, just a two-dimensional array of rows and columns in it, making it easier to utilize table api.
A table entity looks like this:
uid
- unique idrows
- two-dimensional array, where first dimension represents rows, and second dimension is an array of columns. Each column has avalue
property which is column's value - e.g. text in table's cell
Question
{
"uid": "counterparty_legal_name",
"isRequired": true,
"signingSideUids": ["491c1a5a-7db2-400f-ae34-ab1405027763"],
"title": "What is the legal name of the other party?"
}
A question entity looks like this:
uid
- unique question idfieldUid
- a field uid, which will be populated after passing Q&AisRequired
- signals that this question cannot be skipped in Q&A for a list of signing side ssigningSideUids
- this question s takes part for a list of signing side s when they are passing Q&Atext
- question text helper, which should assist person with how this question should be answeredtitle
- main question text - e.g. What is your name?
Signing side
Request(internal type)
{
"signatures": [
{
"uid": "c9a78e60-8522-4ecc-a3fb-22da233f249d",
"username": "user@juro.com"
}
],
"uid": "491c1a5a-7db2-400f-ae34-ab1405027763"
}
Request(external type)
{
"name": "Infinity industries",
"signatures": [
{
"email": "customer@infinity.uk",
"uid": "7b17e670-6c74-4d00-aa1c-54ead6666044"
}
],
"uid": "fcfedf27-2b20-49ef-b408-3544c16dc064"
}
Response
{
"name": "Juro Unlimited",
"signatures": [
{
"uid": "c9a78e60-8522-4ecc-a3fb-22da233f249d",
"username": "user@juro.com"
}
],
"uid": "491c1a5a-7db2-400f-ae34-ab1405027763"
}
A signing side entity looks like this:
uid
- unique idname
- name of the signing sidesignatures
- list ofsignature
items. Eachsignature
represents a person on either "your" or "their" sideuid
- unique idemail
- email of the person that that is on "their" sidename
- name of the person on "their" sidesigningUrl
- url you would share with the person on "their" side to capture a signature or gather data from completing Q&Ausername
- signed in Juro username on "your" side
WEBHOOKS
Webhooks provides an easy way to receive asynchronous events. This allows you to receive push notifications for contract events as they happen in an account.
Setting up webhooks
Open Webhooks page
Enter Webhook's name, URL, Security and Events
Save
Webhook setup is now complete!
Events
Example contract event body
{
"event": {
"type": "contract.commented",
"by": {
"email": "user@juro.com",
"name": "Name Surname",
"side": "internal"
},
"message": "@john.snow can you take a look?",
"thread": "internal comments"
},
"contract": {
"id": "5de92ae0bb0bf42c5ce2fe7c",
"createdDate": "2019-12-05T16:05:52.659Z",
"draftLink": {
"url": "https://app.juro.com/s1tEGduYQ",
"isEnabled": true,
"enabledUntilDate": "2019-12-13T00:00:00.000Z"
},
"fields": [
{
"title": "address",
"type": "text",
"uid": "2d6f2279-dee8-4e17-ad1d-e18cb6b8acc0",
"value": ""
},
{
"title": "address type",
"type": "choice",
"uid": "076fafa9-ff61-4eeb-b8a5-a8dfe0e2ae58",
"value": "private"
}
],
"internalUrl": "https://app.juro.com/sign/5de92ae0bb0bf42c5ce2fe7c",
"name": "Infinity industries",
"owner": {
"name": "Name Surname",
"username": "user@juro.com"
},
"sharingUrl": "https://app.juro.com/s1tEGduYQ",
"signingSides": [
{
"name": "Juro Unlimited",
"signatures": [
{
"signingUrl": "https://app.juro.com/sign/5de92ae0bb0bf42c5ce2fe7c",
"name": null,
"uid": "c9a78e60-8522-4ecc-a3fb-22da233f249d",
"username": "user@juro.com"
}
],
"uid": "491c1a5a-7db2-400f-ae34-ab1405027763"
},
{
"name": "Infinity industries",
"signatures": [
{
"email": null,
"signingUrl": "https://app.juro.com/counterparty/sign/Mbl9vNYIk",
"name": null,
"uid": "7b17e670-6c74-4d00-aa1c-54ead6666044"
}
],
"uid": "fcfedf27-2b20-49ef-b408-3544c16dc064"
}
],
"status": "draft",
"template": {
"id": "5de9227402e24204247757c4",
"name": "Infinity template"
},
"updatedDate": "2019-12-05T16:05:53.399Z"
},
}
We are providing all the relevant events associated with the currently exposed lifecycle of the contract. A more exhaustive list of events hapenning to your account and all related entities associated with it can be found in the activities section of the application. We will be rolling out additional events as we further develop the API.
- contract.created - a contract instance has been generated
- contract.deleted - a contract instance has been deleted
- contract.edit - an edit has been made to the body text of a contract instance
- contract.commented - a contract instance was commented on
- contract.viewed - a contract instance was viewed
- contract.pdf_generated - a pdf of a contract instance has been created from html
- contract.sent_link_to_counterparty - a signing link to a contract was sent out by email
- contract.signed - a contract instance was signed
- contract.approval_requested - an approval request to a contract was sent out by email
- contract.approval_in_progress - an approval process is pending
- contract.approval_process_finished - everyone has approved the contract
- contract.approval_denied - one of the approvers has rejected the contract
- contract.approval_request_cancelled - approval process has been cancelled and all approvers were removed from the contract
Security
Basic
Basic algorithm
const hash = Buffer.from(`${username}:${password}`).toString('base64');
The client sends HTTP requests with the Authorization
header that contains the word Basic
followed by a space and a base64-encoded string username:password.
Authorization: Basic ${hash}
Secret key
Secret key algorithm
const hash = crypto.createHmac('sha256', secret)
.update(body)
.digest('hex');
Secret key ensures that the payload is coming from a trusted source since secret is known only by the provider and consumer. The typical flow of the provider would be to calculate signature
by generating hash
from payload body
and secret
. This hash
then will be pushed in a signature
header along with the webhook body.
signature: sha256 ${hash}
Consumer on the other hand should calculate hash
on their end and compare it to the one they have received.
ERRORS
Juro API error descriptions
Error | Description |
---|---|
Bad Request | Request has malformed syntax or invalid message framing. |
Contract already signed | Unable to perform action because contract is already signed. |
Contract processing in progress | Unable to perform action on contract because it is being used by another process. Try again later. |
Contract not found | Contract with provided id not found. |
Field not found | contract.fields with provided uid not found. |
Forbidden | Invalid API key submitted. Check that you have provided x-api-key header with valid API key. |
Incompatible state error | Contract is in an incompatible state to perform underlying action. |
Internal server error | Something has gone wrong on the server, but the server could not be more specific on what that exact problem is. |
Invalid question signing side | This error indicates that you are answering questions that are linked to other signing side and not linked to your signing side. Check that questions that you are trying to answer are linked to your signing side by comparing uids(contract.questions.signingSideUids =contract.signingSides[0].uid ). |
Invalid email format error | Malformed email provided. |
Invalid value format error | Provided value does not conform expected type, e.g. providing decimal in text field will throw this error. |
Missing Authentication Token | This error indicates that request is missing authentication token or provides an unsupported API method or resource. Check that your API method(GET , POST , ...) and URL is correct. |
Missing required answer | This error indicates that some of the crucial answers were not provided when creating a contract. All required answers(contract.questions.isRequired ) that are linked to your signing side should be provided when creating a contract. |
Limit Exceeded | Monthly quota exceeded. |
Question not found | contract.questions not found for provided answer. |
Restricted signing provider | This contract can only be sent using external signing providers. Sending signing requests with external signing providers is not supported. |
Signature not found | contract.signingSides.signatures with provided uid not found. |
Template not found | template with provided id not found. |
Template not published | Unable to create contract when underlying template is not published. Go to https://app.juro.com and publish template. |
Too Many Requests | Too many requests in short time exceeded throttling limits. |
Unauthorized | Integration account linked to API key is not authorized. Deactivate your API key and activate it back again in Juro > Settings > Integrations > API . |
User not found | The user associated with the provided email is not registered in Juro's system. |