Introduction
GoCanvas uses a standard REST API to provide access to a number of useful features. Users can manage Forms, create Submissions, retrieve Reports, and much more.
Looking for a no-code solution?
Check GoCanvas' Integrations for over 1,000 pre-built connectors to popular cloud services.
Base URL
All URLs referenced in the documentation have the following base:
https://www.gocanvas.com/api/v3/
Overview
API Versioning
GoCanvas API versioning follows semantic versioning, treating the published number as a "major" release. As such, best efforts will be made to introduce changes in a reverse-compatible way. Should a "major" change be needed to improve the API, we would announce an API v4 and make a determination at that point if v3 needs to be deprecated with ample warning to allow customers to migrate to a newer version.
Authentication: Basic
To authorize a request, supply a username and password
curl -u "api.user@example.com:supersecretpassword" \
"https://www.gocanvas.com/api/v3/[ENDPOINT]"
username = "api.user@example.com"
password = "supersecretpassword"
endpoint = "https://www.gocanvas.com/api/v3/[ENDPOINT]?username=#{username}&password=#{password}"
uri = URI.parse(endpoint)
req = Net::HTTP::Get.new(endpoint)
response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
http.request(req)
end
const username = "api.user@example.com";
const password = "supersecretpassword";
fetch("https://www.gocanvas.com/api/v3/[ENDPOINT]", {
method: "GET",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
},
})
.then(response => response.json())
.then(data => console.log(data))
GoCanvas supports HTTP basic auth to turn your existing username and password into API access: simply include these parameters with your requests.
| Parameter | Description |
|---|---|
| username | username for the GoCanvas website |
| password | password for the GoCanvas website |
Authentication: Bearer
GoCanvas supports OAuth 2.0 authentication to retrieve a short-lived token for API access. This token can then be passed in the Authorization HTTP header as a Bearer token to authenticate requests.
To use Bearer authentication, you must first create an OAuth application in your profile. GoCanvas offers two OAuth 2.0 flows:
- Client Credentials Flow: For confidential client applications (server-to-server) that can securely store client secrets.
- Authorization Code with PKCE: For public client applications like mobile apps or SPAs; refresh tokens are also available for this flow.
Client Credentials Flow
The Client Credentials flow is ideal for confidential client applications (server-side) where you can securely store a client secret.
Client Credentials Flow Example
TOKEN_RESPONSE=$(curl -X POST "https://www.gocanvas.com/api/v3/oauth/token" \
-d "grant_type=client_credentials" \
-d "client_id=your-client-id" \
-d "client_secret=your-client-secret" \
-d "scope=api")
TOKEN=$(echo $TOKEN_RESPONSE | jq -r '.access_token')
# Use the token in the Authorization header for future requests
curl -X GET \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
"https://www.gocanvas.com/api/v3/[ENDPOINT]"
client_id = "your-client-id"
client_secret = "your-client-secret"
scope = "api"
uri = "https://www.gocanvas.com/api/v3/oauth/token"
uri = URI.parse(uri)
req = Net::HTTP::Post.new(uri)
req.set_form_data(
"grant_type": "client_credentials",
"client_id": client_id,
"client_secret": client_secret,
"scope": scope
)
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
# Use the token from the response in the Authorization header for future requests
token = JSON.parse(response.body)["access_token"]
# Use the token in the Authorization header for future requests
endpoint = "https://www.gocanvas.com/api/v3/[ENDPOINT]"
req = Net::HTTP::Get.new(endpoint)
req["Authorization"] = "Bearer #{token}"
http.request(req)
const client_id = "your-client-id";
const client_secret = "your-client-secret";
const scope = "api";
const data = {
grant_type: "client_credentials",
client_id: client_id,
client_secret: client_secret,
scope: scope,
};
const tokenResponse = await fetch("https://www.gocanvas.com/api/v3/oauth/token", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data)
});
const tokenData = await tokenResponse.json();
const token = tokenData.access_token;
// Use the token in the Authorization header for future requests
const endpoint = "https://www.gocanvas.com/api/v3/[ENDPOINT]";
fetch(endpoint, {
method: "GET",
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
}).then((response) => {
console.log(response);
});
OAuth Token Response
{
"access_token": "30puVebCmI7wbVjIQPt1KIYE81voxKdkKZwSaCWRiZM",
"token_type": "Bearer",
"expires_in": 7200,
"scope": "api",
"created_at": 1733346054
}
HTTP Request
POST https://www.gocanvas.com/api/v3/oauth/token
Request Body Parameters
| Parameter | Type | Description |
|---|---|---|
| grant_type | enum | Using client_credentials |
| client_id | string | The client ID for your application. Available in your API Settings page. |
| client_secret | string | The client secret for your application. Downloaded when you create the OAuth application. |
| scope | string | The scope for the token. Use api for API access. |
Authorization Code Flow with PKCE
The Authorization Code flow with PKCE (Proof Key for Code Exchange) is designed for public client applications where storing a client secret isn't secure. The endpoints for this flow are:
https://www.gocanvas.com/api/v3/oauth/authorize- Used to request user authorizationhttps://www.gocanvas.com/api/v3/oauth/token- Used to exchange the authorization code for tokens and refresh tokens
HTTP Request
POST https://www.gocanvas.com/api/v3/oauth/token
Request Body Parameters
| Parameter | Type | Description |
|---|---|---|
| grant_type | enum | Using authorization_code |
| client_id | string | The client ID for your application. Available in your API Settings page. |
| code | string | The authorization code received from the authorize endpoint |
| code_verifier | string | The original code verifier generated for PKCE |
| redirect_uri | string | The URI to redirect users to after authorization. |
OAuth Token Response (Authorization Code Flow)
{
"access_token": "30puVebCmI7wbVjIQPt1KIYE81voxKdkKZwSaCWRiZM",
"token_type": "Bearer",
"expires_in": 7200,
"refresh_token": "jJt6HS_WmN80kqKXI7ycWRUiQAgyuCHwIkGI0wdpWmw",
"scope": "api",
"created_at": 1733346054
}
Using Refresh Tokens (Optional)
When the access token expires, use the refresh token to get a new one without user interaction. Most OAuth libraries handle this automatically.
Request Body Parameters for Refresh Tokens
| Parameter | Type | Description |
|---|---|---|
| grant_type | enum | Using refresh_token |
| client_id | string | The client ID for your application. Available in your API Settings page. |
| refresh_token | string | The refresh token received when the access token was issued |
Using the Access Token
Regardless of which flow you use, once you have an access token, include it in API requests:
curl https://www.gocanvas.com/api/v3/some_endpoint \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
Response Parameters
| Parameter | Type | Description |
|---|---|---|
| access_token | string | The access token for the request |
| token_type | enum | The type of token. Will be Bearer |
| expires_in | integer | The number of seconds until the token expires |
| refresh_token | string | (Only for authorization code flow) Token used to obtain new access tokens |
| scope | string | The scope(s) for the token |
| created_at | integer | The timestamp when the token was created |
For more information on implementing the authorization code flow with PKCE, see the OAuth 2.0 PKCE documentation and the RFC 7636 specification.
Errors
The GoCanvas API uses the following error codes:
422 ERROR RESPONSE
{
"errors": [
"Invalid department ID provided"
]
}
| Error Code | Meaning | Description |
|---|---|---|
| 400 | Bad Request | Your request is invalid |
| 401 | Unauthorized | Your API key is wrong |
| 403 | Forbidden | The response requested is hidden for administrators only |
| 404 | Not Found | The specified response could not be found |
| 422 | Unprocessable Entity | The request was well-formed but was unable to be followed due to validation errors |
| 429 | Too Many Requests | You've hit the rate limit. Please wait a bit and try again. See Rate Limits for more information |
| 500 | Internal Server Error | We had a problem with our server. Please try again later |
| 503 | Service Unavailable | We're temporarily offline for maintenance. Please try again later |
Pagination
The GoCanvas API uses pagination to limit the number of results returned on "list" methods. The default number of results returned is 100, unless otherwise specified.
Pagination information is included in the response headers, including a RFC-8288 compliant link header.
RESPONSE
link: <https://www.gocanvas.com/api/v3/forms?page=1>; rel="first",
<https://www.gocanvas.com/api/v3/forms?page=2>; rel="next",
<https://www.gocanvas.com/api/v3/forms?page=5>; rel="last"
current_page: 1
page_items: 100
total_count: 500
total_pages: 5
| Header | Description |
|---|---|
| link | A link to the next, previous, first, and last pages |
| current-page | The current page number |
| page-items | The number of results per page |
| total-count | The total number of results available |
| total-pages | The total number of pages available |
Rate Limits
The GoCanvas API uses rate limiting to prevent abuse and ensure system reliability for all users. An HTTP error code of 429 Too Many Requests is used to indicate the current request was over the rate limit. In order to avoid 429 errors, inspect the Response Headers detailed below.
Best Practices
In order to slow down requests API users should ensure that they are rate limiting on their own servers. Calling the API in loops should only be done with a built in delay. Calling the API with multiple concurrent requests may also result in hitting the rate limit, so concurrency and multithreading of requests should be avoided.
If you receive a rate limit error, you should stop making requests temporarily according to these guidelines:
- If the
RateLimit-Resetresponse header is present, you should not retry your request until after that time. - If the
RateLimit-Remainingheader is 0, you should not make another request until after the time specified by theRateLimit-Resetheader. TheRateLimit-Resetheader is in UTC epoch seconds. - Otherwise, wait for at least one minute before retrying. If your request continues to fail due to a secondary rate limit, wait for an exponentially increasing amount of time between retries, and throw an error after a specific number of retries.
429 RESPONSE HEADERS
RateLimit-Limit 10
RateLimit-Remaining 0
RateLimit-Reset 1480000000
| Header | Meaning |
|---|---|
| RateLimit-Limit | Number of requests allowed for the given request |
| RateLimit-Remaining | Number of requests remaining for the given request |
| RateLimit-Reset | Time at which the rate limit will reset (in UTC epoch seconds) |
Customer
Defines a customer's contact information and can either be an individual or a business entity. A Customer is optionally associated with a Site.
The Customer object
EXAMPLE
{
"id": 10,
"type": "customer",
"customer_type": "individual",
"business_name": null,
"contact_role": null,
"contact_first_name": "Ben",
"contact_last_name": "Jackson",
"contact_email": "ben.jackson@example.com",
"contact_phone": "5555555555",
"contact_preference": null,
"notes": null,
"default_site_id": 1,
"code": "NEW00001"
}
A Customer requires a customer_type to be created. If customer_type is individual, you need to provide contact_first_name and contact_last_name. If customer_type is business, you need to provide business_name.
Customers and Sites
A Customer can be associated with many Sites. By passing a default_site_id and/or an array of site_ids in the PATCH request, you can attach Sites to the Customer.
Customers can have multiple Sites associated with them. The first Site associated with the Customer is considered the Primary Site. Any sites added after the first site are considered "Additional Sites".
List all Customers
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X GET \
https://www.gocanvas.com/api/v3/customers
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
uri = URI("https://www.gocanvas.com/api/v3/customers")
req = Net::HTTP::Get.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
customers_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
fetch("https://www.gocanvas.com/api/v3/customers", {
method: "GET",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
}
})
.then(response => response.json())
.then(customers => console.log(customers));
Users can view a list of all the Customers associated with the company.
RESPONSE
[
{
"id": 10,
"type": "customer",
"customer_type": "individual",
"business_name": null,
"contact_role": null,
"contact_first_name": "Ben",
"contact_last_name": "Jackson",
"contact_email": "ben.jackson@example.com",
"contact_phone": "5555555555",
"contact_preference": null,
"notes": null,
"default_site_id": 1,
"code": "NEW00001"
},
{
"id": 11,
"type": "customer",
"customer_type": "business",
"business_name": "Chichago Inc",
"contact_role": null,
"contact_first_name": "Jessica",
"contact_last_name": "Nixon",
"contact_email": "jessica.nixon@example.com",
"contact_phone": "4444444444",
"contact_preference": null,
"notes": null,
"default_site_id": null,
"code": "NEW00002"
},
{
"id": 12,
"type": "customer",
"customer_type": "individual",
"business_name": null,
"contact_role": null,
"contact_first_name": "Sam",
"contact_last_name": "Johnson",
"contact_email": "sam.johnson@example.com",
"contact_phone": "3333333333",
"contact_preference": null,
"notes": null,
"default_site_id": 3,
"code": "NEW00003"
}
]
HTTP Request
GET https://www.gocanvas.com/api/v3/customers
Query Parameters
| Parameter | Type | Description | Default |
|---|---|---|---|
| page | integer (optional) | The page requested, see Pagination | 1 |
Retrieve a Customer
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X GET \
https://www.gocanvas.com/api/v3/customers/10
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
uri = URI("https://www.gocanvas.com/api/v3/customers/10")
req = Net::HTTP::Get.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
customer_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
fetch("https://www.gocanvas.com/api/v3/customers/10", {
method: "GET",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
}
})
.then(response => response.json())
.then(customer => console.log(customer));
Users can retrieve a Customer by its ID.
HTTP Request
GET https://www.gocanvas.com/api/v3/customers/10
RESPONSE
{
"id": 10,
"type": "customer",
"customer_type": "individual",
"business_name": null,
"contact_role": null,
"contact_first_name": "Ben",
"contact_last_name": "Jackson",
"contact_email": "ben.jackson@example.com",
"contact_phone": "5555555555",
"contact_preference": null,
"notes": null,
"default_site_id": 1,
"code": "NEW00001"
}
Response Parameters
| Parameter | Type | Description |
|---|---|---|
| id | integer | The identifier for this exact Customer |
| type | string | The type of the Customer, always customer |
| customer_type | enum | The type of the Customer. Can be individual or business |
| business_name | string | The name of the business, if the customer_type is a business |
| contact_role | string | The role of the contact person for the Customer |
| contact_first_name | string | The first name of the contact person for the Customer |
| contact_last_name | string | The last name of the contact person for the Customer |
| contact_email | string | The email address of the contact person for the Customer |
| contact_phone | string | The phone number of the contact person for the Customer |
| contact_preference | string | The preferred method of contact for the Customer |
| notes | string | A longer string value to describe the Customer |
| default_site_id | integer | The ID of the default site associated with the Customer |
| code | string | An alpha numeric code to uniquely identify the Customer |
Create a Customer
To create a new Customer, the POST body can be sent as JSON. The customer_type field is required. If customer_type is individual, you must also provide contact_first_name and contact_last_name. If customer_type is business, you must also provide business_name.
BODY='{
"customer_type": "business",
"business_name": "LLC Renovation",
"contact_first_name": "Sean",
"contact_last_name": "Mitchel",
"contact_email": "sean.mitchel@example.com",
"contact_phone": "3334445555",
"code": "NEW00001",
"site_id": 7
}'
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X POST \
-d $BODY \
https://www.gocanvas.com/api/v3/customers
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
request_body = {
"customer_type": "business",
"business_name": "LLC Renovation",
"contact_first_name": "Sean",
"contact_last_name": "Mitchel",
"contact_email": "sean.mitchel@example.com",
"contact_phone": "3334445555",
"code": "NEW00001",
"site_id": 7
}
uri = URI("https://www.gocanvas.com/api/v3/customers")
json_request_body = request_body.to_json
req = Net::HTTP::Post.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
req.body = json_request_body
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
customer_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
const data = {
"customer_type": "business",
"business_name": "LLC Renovation",
"contact_first_name": "Sean",
"contact_last_name": "Mitchel",
"contact_email": "sean.mitchel@example.com",
"contact_phone": "3334445555",
"code": "NEW00001",
"site_id": 7
};
fetch("https://www.gocanvas.com/api/v3/customers", {
method: "POST",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(customer => console.log(customer));
RESPONSE
{
"id": 14,
"type": "customer",
"customer_type": "business",
"business_name": "LLC Renovation",
"contact_role": null,
"contact_first_name": "Sean",
"contact_last_name": "Mitchel",
"contact_email": "sean.mitchel@example.com",
"contact_phone": "3334445555",
"contact_preference": null,
"notes": null,
"default_site_id": 7,
"code": "NEW00001"
}
HTTP Request
POST https://www.gocanvas.com/api/v3/customers
Request Body Parameters
| Parameter | Type | Description |
|---|---|---|
| customer_type* | enum | The type of the Customer. Can be individual or business |
| business_name** | string | The name of the business, if the customer_type is a business |
| contact_role | string | The role of the contact person for the Customer |
| contact_first_name** | string | The first name of the contact person for the Customer |
| contact_last_name** | string | The last name of the contact person for the Customer |
| contact_email | string | The email address of the contact person for the Customer |
| contact_phone | string | The phone number of the contact person for the Customer |
| contact_preference | string | The preferred method of contact for the Customer |
| notes | string | A longer string value to describe the Customer |
| code | string | An alpha numeric code to uniquely identify the Customer |
* required field
** If customer_type is individual, you need to provide contact_first_name and contact_last_name. If customer_type is business, you need to provide business_name.
Update a Customer
To update an existing Customer, the PATCH request body can be sent as JSON.
BODY='{
"default_site_id": 12,
"notes": "Unit renovation",
"site_ids": [10, 11, 12]
}'
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X PATCH \
-d $BODY \
https://www.gocanvas.com/api/v3/customers/14
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
request_body = {
"default_site_id": 12,
"notes": "Unit renovation",
"site_ids": [10, 11, 12]
}
uri = URI("https://www.gocanvas.com/api/v3/customers/14")
json_request_body = request_body.to_json
req = Net::HTTP::Patch.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
req.body = json_request_body
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
customer_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
const data = {
"default_site_id": 12,
"notes": "Unit renovation",
"site_ids": [10, 11, 12]
};
fetch("https://www.gocanvas.com/api/v3/customers/14", {
method: "PATCH",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(customer => console.log(customer));
RESPONSE
{
"message": "Customer updated successfully"
}
HTTP Request
PATCH https://www.gocanvas.com/api/v3/customers/14
Request Body Parameters
| Parameter | Type | Description |
|---|---|---|
| customer_type* | enum | The type of the Customer. Can be individual or business |
| business_name** | string | The name of the business, if the customer_type is a business |
| contact_role | string | The role of the contact person for the Customer |
| contact_first_name** | string | The first name of the contact person for the Customer |
| contact_last_name** | string | The last name of the contact person for the Customer |
| contact_email | string | The email address of the contact person for the Customer |
| contact_phone | string | The phone number of the contact person for the Customer |
| contact_preference | string | The preferred method of contact for the Customer |
| notes | string | A longer string value to describe the Customer |
| default_site_id | integer | The ID of the default site associated with the Customer. When multiple site_ids are provided this field denotes the Primary Site. |
| code | string | An alpha numeric code to uniquely identify the Customer |
| site_ids | array | Sites IDs for adding Sites to the Customer. When more than one Site is provided, the first will be used unless a default_site_id is specified |
* required field
** If customer_type is individual, you need to provide contact_first_name and contact_last_name. If customer_type is business, you need to provide business_name.
Delete a Customer
A Customer can be deleted with a DELETE request.
By default, the DELETE request will soft-delete the Customer, which preserves the Customer data but hides it from the web views. To permanently delete a Customer, use the hard_delete=true parameter, e.g. DELETE https://www.gocanvas.com/api/v3/customers/14?hard_delete=true.
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X DELETE \
https://www.gocanvas.com/api/v3/customers/14
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
uri = URI("https://www.gocanvas.com/api/v3/customers/14")
req = Net::HTTP::Delete.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
customer_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
fetch("https://www.gocanvas.com/api/v3/customers/14", {
method: "DELETE",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
}
})
.then(response => response.json())
.then(customer => console.log(customer));
RESPONSE
{
"message": "Customer 14 has been soft deleted successfully"
}
HTTP Request
DELETE https://www.gocanvas.com/api/v3/customers/14
Request Parameters
| Parameter | Type | Description |
|---|---|---|
| hard_delete* | boolean | Will hard delete the Customer record when set to true |
* This is an optional URL parameter. If not provided, the Customer will be soft deleted.
Department
A Department represents an organizational unit within a Company. Users can be assigned to one or multiple Departments. Forms created in one Department can be shared with another.
The Department object
EXAMPLE
{
"id": 114,
"type": "department",
"name": "My New Department",
"description": "This is a new department",
"created_at": "2023-06-02 13:43:08 UTC"
}
| Property | Type | Description |
|---|---|---|
| id | integer | The unique Department id |
| type | string | The type of object |
| name | string | A short string value for name of a new Department |
| description | string | A longer string value describing a new Department |
| created_at | date | A timestamp of when the Department was originally created |
List all Departments
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X GET \
https://www.gocanvas.com/api/v3/departments
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
uri = URI("https://www.gocanvas.com/api/v3/departments")
req = Net::HTTP::Get.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
departments_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
fetch("https://www.gocanvas.com/api/v3/departments", {
method: "GET",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
}
})
.then(response => response.json())
.then(departments => console.log(departments));
Users can view a list of all the Departments associated with their Company.
HTTP Request
GET https://www.gocanvas.com/api/v3/departments
RESPONSE
[
{
"id": -1,
"type": "department",
"name": "All",
"description": "All",
"created_at": null
},
{
"id": 111,
"type": "department",
"name": "First Department",
"description": "My first department",
"created_at": "2023-05-31 15:34:47 UTC"
},
{
"id": 112,
"type": "department",
"name": "Second Department",
"description": "A second department",
"created_at": "2023-05-31 16:24:28 UTC"
},
{
"id": 113,
"type": "department",
"name": "Third Department",
"description": "My third department",
"created_at": "2023-05-31 16:27:30 UTC"
}
]
Create a Department
BODY='{
name: "My New Department",
description: "This is a new Department"
}'
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X POST \
-d $BODY \
https://www.gocanvas.com/api/v3/departments
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
request_body = {
name: "My New Department",
description: "This is a new Department"
}
uri = URI("https://www.gocanvas.com/api/v3/departments")
json_request_body = request_body.to_json
req = Net::HTTP::Post.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
req.body = json_request_body
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
department_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
const data = {
name: "My New Department",
description: "This is a new Department"
};
fetch("https://www.gocanvas.com/api/v3/departments", {
method: "POST",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(department => console.log(department));
Users have the ability to create a Department to a specified Company with a name and a description.
HTTP Request
POST https://www.gocanvas.com/api/v3/departments
RESPONSE
{
"id": 114,
"type": "department",
"name": "My New Department",
"description": "This is a new department",
"created_at": "2023-06-02 13:43:08 UTC"
}
Request Body Parameters
| Parameter | Type | Description |
|---|---|---|
| name | string | A short string value for name of a new Department |
| description | string | A longer string value describing a new Department |
List all Department Users
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X GET \
https://www.gocanvas.com/api/v3/departments/1999/users
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
uri = URI("https://www.gocanvas.com/api/v3/departments/1999/users")
req = Net::HTTP::Get.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
users_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
fetch("https://www.gocanvas.com/api/v3/departments/1999/users", {
method: "GET",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
}
})
.then(response => response.json())
.then(users => console.log(users));
Users can view a list of all the Users within a Department.
HTTP Request
GET https://www.gocanvas.com/api/v3/departments/1999/users
RESPONSE
[
{
"type": "department_user",
"user": {
"id": 5486,
"first_name": "Jane",
"last_name": "Doe",
"email": "jane.doe@gocanvas.com",
"enabled": true
},
"department_role": "department_user",
"created_at": "2022-09-13 17:02:49 UTC",
"updated_at": "2022-09-13 17:02:49 UTC"
},
{
"type": "department_user",
"user": {
"id": 5490,
"first_name": "Smith",
"last_name": "Kane",
"email": "smith.kane@gocanvas.com",
"enabled": false
},
"department_role": "department_admin",
"created_at": "2022-09-13 17:02:49 UTC",
"updated_at": "2022-09-13 17:02:49 UTC"
}
]
Add a User to a Department
BODY='{
"user_id": 5491,
"department_role": "department_user"
}'
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X POST \
-d $BODY \
https://www.gocanvas.com/api/v3/departments/1999/users
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
request_body = {
"user_id": 5491,
"department_role": "department_user"
}
uri = URI("https://www.gocanvas.com/api/v3/departments/1999/users")
json_request_body = request_body.to_json
req = Net::HTTP::Post.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
req.body = json_request_body
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
user_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
const data = {
"user_id": 5491,
"department_role": "department_user"
};
fetch("https://www.gocanvas.com/api/v3/departments/1999/users", {
method: "POST",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(user => console.log(user));
To add an existing User to a Department you'll need to pass a valid user_id and a department_role giving the User specific rights within a Department.
HTTP Request
POST https://www.gocanvas.com/api/v3/departments/1999/users
Request Body Parameters
| Parameter | Type | Description | Options |
|---|---|---|---|
| user_id | integer | The id of the User to add | |
| department_role | string | A string matching a valid departmental role | department_admin department_reporter department_user department_designer department_dispatcher |
Response
RESPONSE
{
"type": "department_user",
"department_role": "department_user",
"created_at": "2023-05-31 14:36:04 UTC",
"updated_at": "2023-05-31 14:36:04 UTC",
"user_id": 5491,
"department_id": 1999
}
| Parameter | Type | Description |
|---|---|---|
| type | string | The type of object |
| department_role | string | A string value for user's role in the Department |
| user_id | integer | The User that was added to the Department |
| department_id | integer | The Department the User joined/had their role updated in |
| already_existed* | boolean | If the User was already in the Department |
* Only returned if the User was already part of the Department
Dispatch
A Dispatch is a pre-populated set of responses to a Form that will become a Submission once the dispatched user completes the Form. Dispatches also have additional capabilities such as scheduling and notifications. Dispatches will closely resemble Submissions.
The Dispatch object
EXAMPLE
{
"id": 194780,
"type": "dispatch_item",
"form_id": 346103,
"user_id": 840365,
"department_id": 11942,
"customer_id": null,
"project_id": null,
"site_id": null,
"submission_id": null,
"name": "Repair request",
"description": "123 Main St Service Request",
"status": "assigned",
"scheduled_at": null,
"scheduled_end": null,
"sent_at": null,
"completed_at": null,
"deleted_at": null,
"send_calendar_invite": false,
"reminder_interval": null,
"created_at": "2024-11-11 21:09:02 UTC",
"responses": [
{ "id": 7894001, "type": "response", "entry_id": 4506586, "value": "Jane" },
{ "id": 7894002, "type": "response", "entry_id": 4506587, "value": "Doe" },
{ "id": 7894003, "type": "response", "entry_id": 4506588, "value": "Main St" },
{ "id": 7894004, "type": "response", "entry_id": 4506589, "value": "Boca Raton" },
{ "id": 7894005, "type": "response", "entry_id": 4506590, "value": "FL" },
{ "id": 7894006, "type": "response", "entry_id": 4506591, "value": "23456" },
{ "id": 7894007, "type": "response", "entry_id": 4506592, "value": "USA" },
{ "id": 7894008, "type": "response", "entry_id": 4506593, "value": "222-333-4444" }
]
}
Dispatches must reference a Form. Responses within a Dispatch align to those within a Submission.
For retrieving a form's entries used for Creating a Dispatch, see the minimal Form format documentation.
List all Dispatches
Users can retrieve a list of all Dispatches that they have access to. Required parameters are user_id, department_id, or form_id.
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X GET \
https://www.gocanvas.com/api/v3/dispatches
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
uri = URI("https://www.gocanvas.com/api/v3/dispatches")
req = Net::HTTP::Get.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
dispatches_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
fetch("https://www.gocanvas.com/api/v3/dispatches", {
method: "GET",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
}
})
.then(response => response.json())
.then(dispatches => console.log(dispatches));
RESPONSE
[
{
"id": 194780,
"type": "dispatch_item",
"form_id": 346103,
"user_id": 840365,
"department_id": 11942,
"customer_id": null,
"project_id": null,
"site_id": null,
"submission_id": null,
"name": "Repair request",
"description": "123 Main St Service Request",
"status": "assigned",
"scheduled_at": "2024-10-01T08:00:00Z",
"scheduled_end": "2024-12-01T12:00:00Z",
"sent_at": null,
"completed_at": null,
"deleted_at": null,
"send_calendar_invite": true,
"reminder_interval": 60,
"created_at": "2024-11-11T21:09:02Z"
},
{
"id": 194781,
"type": "dispatch_item",
"form_id": 346103,
"user_id": 840365,
"department_id": 11942,
"customer_id": null,
"project_id": null,
"site_id": null,
"submission_id": null,
"name": "Fence repair request",
"description": "123 Main St Service Request",
"status": "assigned",
"scheduled_at": "2024-12-03T08:00:00Z",
"scheduled_end": "2024-12-03T10:00:00Z",
"sent_at": null,
"completed_at": null,
"deleted_at": null,
"send_calendar_invite": true,
"reminder_interval": 60,
"created_at": "2024-11-11T21:09:02Z"
},
{
"id": 194782,
"type": "dispatch_item",
"form_id": 346103,
"user_id": 840365,
"department_id": 11942,
"customer_id": null,
"project_id": null,
"site_id": null,
"submission_id": null,
"name": "Tree trimming request",
"description": "123 Main St Service Request",
"status": "assigned",
"scheduled_at": "2024-12-06T08:00:00Z",
"scheduled_end": "2024-12-06T12:00:00Z",
"sent_at": null,
"completed_at": null,
"deleted_at": null,
"send_calendar_invite": true,
"reminder_interval": 60,
"created_at": "2024-11-11T21:09:02Z"
}
]
HTTP Request
GET https://www.gocanvas.com/api/v3/dispatches
Query Parameters
| Parameter | Type | Description | Default |
|---|---|---|---|
| page | integer (optional) | The page requested, see Pagination | 1 |
| user_id* | integer (optional) | The identifier for the User assigned the Dispatch | |
| department_id* | integer (optional) | The identifier for the Department associated with the Dispatch | |
| form_id* | integer (optional) | The identifier for the Form associated with Dispatch | |
| status | enum (optional) | The status of the Dispatch. Can be unassigned,assigned, or received |
|
| start_date** | string (optional) | A DateTime value for the beginning bounds to filter the Dispatches' created_at |
|
| end_date** | string (optional) | A DateTime value for the ending bounds to filter the Dispaches' created_at |
|
| scheduled_start_date** | string (optional) | A DateTime value for the beginning bounds to filter the Dispatches' scheduled_at |
|
| scheduled_end_date** | string (optional) | A DateTime value for the ending bounds to filter the Dispaches' scheduled_end |
* Either user_id, department_id, or form_id must be provided.
** start_date, end_date, scheduled_start_date and scheduled_end_date must be in the ISO-8601 format, e.g. 2024-01-30 or 2024-01-30T23:59:59 or 2024-01-30T23:59:59-04:00
Retrieve a Dispatch
Users can retrieve a Dispatch by its ID.
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X GET \
https://www.gocanvas.com/api/v3/dispatches/194780
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
uri = URI("https://www.gocanvas.com/api/v3/dispatches/194780")
req = Net::HTTP::Get.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
dispatch_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
fetch("https://www.gocanvas.com/api/v3/dispatches/194780", {
method: "GET",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
}
})
.then(response => response.json())
.then(dispatch => console.log(dispatch));
RESPONSE
{
"id": 194780,
"type": "dispatch_item",
"form_id": 346103,
"user_id": 840365,
"department_id": 11942,
"customer_id": null,
"project_id": null,
"site_id": null,
"submission_id": null,
"name": "Repair request",
"description": "123 Main St Service Request",
"status": "assigned",
"scheduled_at": "2024-12-01 08:00:00 UTC",
"scheduled_end": "2024-12-01 12:00:00 UTC",
"sent_at": null,
"completed_at": null,
"deleted_at": null,
"send_calendar_invite": true,
"reminder_interval": 60,
"created_at": "2024-11-11 21:09:02 UTC",
"responses": [
{ "id": 7894001, "type": "response", "entry_id": 4506586, "value": "Jane" },
{ "id": 7894002, "type": "response", "entry_id": 4506587, "value": "Doe" },
{ "id": 7894003, "type": "response", "entry_id": 4506588, "value": "Main St" },
{ "id": 7894004, "type": "response", "entry_id": 4506589, "value": "Boca Raton" },
{ "id": 7894005, "type": "response", "entry_id": 4506590, "value": "FL" },
{ "id": 7894006, "type": "response", "entry_id": 4506591, "value": "23456" },
{ "id": 7894007, "type": "response", "entry_id": 4506592, "value": "USA" },
{ "id": 7894008, "type": "response", "entry_id": 4506593, "value": "222-333-4444" }
]
}
HTTP Request
GET https://www.gocanvas.com/api/v3/dispatches/194780
Response Parameters
| Parameter | Type | Description |
|---|---|---|
| id | integer | The identifier for this exact Dispatch |
| type | string | The type of object returned |
| form_id | integer | The identifier for the Form associated with this Dispatch |
| user_id | integer (optional) | The identifier for the User assigned this Dispatch; Dispatch is considered unassigned if null |
| department_id | integer | The identifier for the Department associated with this Dispatch |
| submission_id | integer (optional) | The identifier for the Submission associated with this completed Dispatch |
| name | string (optional) | A short name for the Dispatch displayed on the Dispatch Calendar and the assigned user's calendar invitation |
| description | string (optional) | A short description of the Dispatch displayed on the assigned user's mobile device |
| status | enum | The state of the Dispatch Can be unassigned, assigned, received, completed, or deleted |
| scheduled_at | datetime (optional) | For Scheduled Dispatches, the scheduled beginning time |
| scheduled_end | datetime (optional) | For Scheduled Dispatches, the scheduled ending time |
| sent_at | datetime (optional) | The time the Dispatch was sent |
| completed_at | datetime (optional) | The time the Dispatch was completed |
| deleted_at | datetime (optional) | The time the Dispatch was soft-deleted |
| send_calendar_invite | boolean (optional) | Whether a calendar invite is sent for the Dispatch |
| reminder_interval | integer (optional) | The period in minutes before the Dispatch event that a reminder will be sent |
| created_at | datetime (optional) | The time the Dispatch was created |
| responses[] | array | A collection of responses against Form Entries used to pre-populate the assignee's Submission |
| responses[].id | integer | The unique identifier for this Dispatch's response |
| responses[].type | string | The type of the object returned |
| responses[].entry_id | integer | The unique identifier of an Entry |
| responses[].value | string | The response data for the Entry |
| responses[].multi_key† | string (optional) | Reference to the looped value |
† Only provided for looped forms
Create an Immediate Dispatch
Creating an Immediate Dispatch is similar to creating a Submission. The Dispatch will be sent to the mobile client immediately.
BODY='{
"assignee_id": 840365,
"name": "Repair request",
"description": "123 Main St Service Request",
"dispatch_type": "immediate_dispatch",
"department_id": 11942,
"form_id": 346103,
"send_notification": true,
"responses": [
{ "entry_id": 4506586, "value": "Jane" },
{ "entry_id": 4506587, "value": "Doe" },
{ "entry_id": 4506588, "value": "Main Street" },
{ "entry_id": 4506589, "value": "Boca Raton" },
{ "entry_id": 4506590, "value": "FL" },
{ "entry_id": 4506591, "value": "23456" },
{ "entry_id": 4506592, "value": "USA" },
{ "entry_id": 4506593, "value": "222-333-4444" }
]
}'
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X POST \
-d $BODY \
https://www.gocanvas.com/api/v3/dispatches
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
request_body = {
"assignee_id": 840365,
"name": "Repair request",
"description": "123 Main St Service Request",
"dispatch_type": "immediate_dispatch",
"department_id": 11942,
"form_id": 346103,
"send_notification": true,
"responses": [
{ "entry_id": 4506586, "value": "Jane" },
{ "entry_id": 4506587, "value": "Doe" },
{ "entry_id": 4506588, "value": "Main Street" },
{ "entry_id": 4506589, "value": "Boca Raton" },
{ "entry_id": 4506590, "value": "FL" },
{ "entry_id": 4506591, "value": "23456" },
{ "entry_id": 4506592, "value": "USA" },
{ "entry_id": 4506593, "value": "222-333-4444" }
]
}
uri = URI("https://www.gocanvas.com/api/v3/dispatches")
json_request_body = request_body.to_json
req = Net::HTTP::Post.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
req.body = json_request_body
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
dispatch_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
const data = {
"assignee_id": 840365,
"name": "Repair request",
"description": "123 Main St Service Request",
"dispatch_type": "immediate_dispatch",
"department_id": 11942,
"form_id": 346103,
"send_notification": true,
"responses": [
{ "entry_id": 4506586, "value": "Jane" },
{ "entry_id": 4506587, "value": "Doe" },
{ "entry_id": 4506588, "value": "Main Street" },
{ "entry_id": 4506589, "value": "Boca Raton" },
{ "entry_id": 4506590, "value": "FL" },
{ "entry_id": 4506591, "value": "23456" },
{ "entry_id": 4506592, "value": "USA" },
{ "entry_id": 4506593, "value": "222-333-4444" }
]
};
fetch("https://www.gocanvas.com/api/v3/dispatches", {
method: "POST",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(dispatch => console.log(dispatch));
RESPONSE
{
"id": 194780,
"type": "dispatch_item",
"form_id": 346103,
"user_id": 840365,
"department_id": 11942,
"customer_id": null,
"project_id": null,
"site_id": null,
"submission_id": null,
"name": "Repair request",
"description": "123 Main St Service Request",
"status": "assigned",
"scheduled_at": null,
"scheduled_end": null,
"sent_at": null,
"completed_at": null,
"deleted_at": null,
"send_calendar_invite": false,
"reminder_interval": null,
"created_at": "2024-11-11 21:09:02 UTC"
}
HTTP Request
POST https://www.gocanvas.com/api/v3/dispatches
Request Body Parameters
| Parameter | Type | Description |
|---|---|---|
| body | hash | The JSON Dispatch body |
| assignee_id | integer (optional) | The identifier for the User assigned the Dispatch; when this is not provided, the Dispatch remains unassigned |
| name | string (optional) | A short name for the Dispatch displayed on the Dispatch Calendar and the assigned user's calendar invitation |
| description | string (optional) | A short description of the Dispatch displayed on the assigned user's mobile device |
| dispatch_type | enum | The type of the Dispatch. Can be immediate_dispatch or scheduled_dispatch |
| department_id* | integer (optional) | The identifier for the Department the Dispatch will be created in |
| form_id | integer | The identifier to specify a Form |
| responses[] | array | A collection of responses against Form Entries used to pre-populate the assignee's Submission |
| responses[].entry_id | integer | The unique identifier of an Entry |
| responses[].entry_guid | string | The unique guid of an Entry. An alternative to entry_id |
| responses[].value | string | The response data for the Entry |
| responses[].multi_key† | string (optional) | Reference to the looped value |
| send_notification | boolean (optional) | Sends a push notification to the mobile app for the Dispatch when true |
| no_form_assignment | boolean (optional) | Allows creation of a Dispatch without the user being assigned to the form when true |
* If no department_id is provided, the User's default department will be used. If the assignee is unassigned or has no default, the Form's originating department is used.
† Only required for looped forms
Create a Scheduled Dispatch
Dispatch scheduling allows for the Dispatch to be sent to the mobile client at a future date and time.
BODY='{
"assignee_id": 840365,
"name": "Repair request",
"description": "123 Main St Service Request",
"dispatch_type": "scheduled_dispatch",
"department_id": 11942,
"form_id": 346103,
"reminder_interval": 60,
"responses": [
{ "entry_id": 4506586, "value": "Jane" },
{ "entry_id": 4506587, "value": "Doe" },
{ "entry_id": 4506588, "value": "Main Street" },
{ "entry_id": 4506589, "value": "Boca Raton" },
{ "entry_id": 4506590, "value": "FL" },
{ "entry_id": 4506591, "value": "23456" },
{ "entry_id": 4506592, "value": "USA" },
{ "entry_id": 4506593, "value": "222-333-4444" }
],
"scheduled_at": "12/1/2024 8:00:00 AM",
"scheduled_end": "12/1/2024 12:00:00 PM"
}'
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X POST \
-d $BODY \
https://www.gocanvas.com/api/v3/dispatches
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
request_body = {
"assignee_id": 840365,
"name": "Repair request",
"description": "123 Main St Service Request",
"dispatch_type": "scheduled_dispatch",
"department_id": 11942,
"form_id": 346103,
"reminder_interval": 60,
"responses": [
{ "entry_id": 4506586, "value": "Jane" },
{ "entry_id": 4506587, "value": "Doe" },
{ "entry_id": 4506588, "value": "Main Street" },
{ "entry_id": 4506589, "value": "Boca Raton" },
{ "entry_id": 4506590, "value": "FL" },
{ "entry_id": 4506591, "value": "23456" },
{ "entry_id": 4506592, "value": "USA" },
{ "entry_id": 4506593, "value": "222-333-4444" }
],
"scheduled_at": "12/1/2024 8:00:00 AM",
"scheduled_end": "12/1/2024 12:00:00 PM"
}
uri = URI("https://www.gocanvas.com/api/v3/dispatches")
json_request_body = request_body.to_json
req = Net::HTTP::Post.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
req.body = json_request_body
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
dispatch_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
const data = {
"assignee_id": 840365,
"name": "Repair request",
"description": "123 Main St Service Request",
"dispatch_type": "scheduled_dispatch",
"department_id": 11942,
"form_id": 346103,
"reminder_interval": 60,
"responses": [
{ "entry_id": 4506586, "value": "Jane" },
{ "entry_id": 4506587, "value": "Doe" },
{ "entry_id": 4506588, "value": "Main Street" },
{ "entry_id": 4506589, "value": "Boca Raton" },
{ "entry_id": 4506590, "value": "FL" },
{ "entry_id": 4506591, "value": "23456" },
{ "entry_id": 4506592, "value": "USA" },
{ "entry_id": 4506593, "value": "222-333-4444" }
],
"scheduled_at": "12/1/2024 8:00:00 AM",
"scheduled_end": "12/1/2024 12:00:00 PM"
};
fetch("https://www.gocanvas.com/api/v3/dispatches", {
method: "POST",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(dispatch => console.log(dispatch));
RESPONSE
{
"id": 194780,
"type": "dispatch_item",
"form_id": 346103,
"user_id": 840365,
"department_id": 11942,
"customer_id": null,
"project_id": null,
"site_id": null,
"submission_id": null,
"name": "Repair request",
"description": "123 Main St Service Request",
"status": "assigned",
"scheduled_at": "2024-12-01 08:00:00 UTC",
"scheduled_end": "2024-12-01 12:00:00 UTC",
"sent_at": null,
"completed_at": null,
"deleted_at": null,
"send_calendar_invite": true,
"reminder_interval": 60,
"created_at": "2024-11-11 21:09:02 UTC"
}
HTTP Request
POST https://www.gocanvas.com/api/v3/dispatches
Request Body Parameters
| Parameter | Type | Description |
|---|---|---|
| body | hash | The JSON Dispatch body |
| assignee_id | integer (optional) | The identifier for the User assigned the Dispatch; when this is not provided, the Dispatch remains unassigned |
| name | string (optional) | A short name for the Dispatch displayed on the Dispatch Calendar and the assigned user's calendar invitation |
| description | string (optional) | A short description of the Dispatch displayed on the assigned user's mobile device |
| dispatch_type | enum | The type of the Dispatch. Can be immediate_dispatch or scheduled_dispatch |
| department_id** | integer (optional) | The identifier for the Department the Dispatch will be created in |
| form_id | integer | The identifier to specify a Form |
| reminder_interval* | integer (optional) | The number of minutes before a Dispatch event that a reminder is sent |
| responses[] | array | A collection of responses against Form Entries used to pre-populate the assignee's Submission |
| responses[].entry_id | integer | The unique identifier of an Entry |
| responses[].value | string | The response data for the Entry |
| responses[].multi_key† | string (optional) | Reference to the looped value |
| scheduled_at* | datetime | The date and time the Dispatch is scheduled to begin. Uses formats "MM/DD/YYYY HH:mm/ss AM" |
| scheduled_end* | datetime | The date and time the Dispatch is scheduled to end. Uses formats "MM/DD/YYYY HH:mm/ss AM" |
| send_calendar_invite | boolean (optional) | Sends a calendar invite for the Dispatch when true |
| no_form_assignment | boolean (optional) | Allows creation of a Dispatch without the user being assigned to the form when true |
* Only required for scheduled_dispatch type
** If no department_id is provided, the User's default department will be used. If the assignee is unassigned or has no default, the Form's originating department is used.
† Only required for looped forms
Create a Recurring Dispatch
Creating a Recurring Dispatch allows for the Dispatch to be sent to the mobile client on a recurring schedule.
BODY='{
"assignee_id": 840365,
"name": "Yearly Maintenance",
"description": "Yearly Maintenance Service Request",
"dispatch_type": "recurring_dispatch",
"department_id": 11942,
"form_id": 346103,
"reminder_interval": 60,
"repeat_interval": "daily",
"repeat_ends_option": "ends_after",
"repeat_ends_on": "12/1/2024",
"repeat_occurrences": 2,
"responses": [
{ "entry_id": 4506586, "value": "Jane" },
{ "entry_id": 4506587, "value": "Doe" },
{ "entry_id": 4506588, "value": "Main Street" },
{ "entry_id": 4506589, "value": "Boca Raton" },
{ "entry_id": 4506590, "value": "FL" },
{ "entry_id": 4506591, "value": "23456" },
{ "entry_id": 4506592, "value": "USA" },
{ "entry_id": 4506593, "value": "222-333-4444" }
],
"scheduled_at": "12/1/2024 8:00:00 AM",
"scheduled_end": "12/1/2024 12:00:00 PM"
}'
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X POST \
-d $BODY \
https://www.gocanvas.com/api/v3/dispatches
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
request_body = {
"assignee_id": 840365,
"name": "Yearly Maintenance",
"description": "Yearly Maintenance Service Request",
"dispatch_type": "recurring_dispatch",
"department_id": 11942,
"form_id": 346103,
"reminder_interval": 60,
"repeat_interval": "daily",
"repeat_ends_option": "ends_after",
"repeat_ends_on": "12/1/2024",
"repeat_occurrences": 2,
"responses": [
{ "entry_id": 4506586, "value": "Jane" },
{ "entry_id": 4506587, "value": "Doe" },
{ "entry_id": 4506588, "value": "Main Street" },
{ "entry_id": 4506589, "value": "Boca Raton" },
{ "entry_id": 4506590, "value": "FL" },
{ "entry_id": 4506591, "value": "23456" },
{ "entry_id": 4506592, "value": "USA" },
{ "entry_id": 4506593, "value": "222-333-4444" }
],
"scheduled_at": "12/1/2024 8:00:00 AM",
"scheduled_end": "12/1/2024 12:00:00 PM"
}
uri = URI("https://www.gocanvas.com/api/v3/dispatches")
json_request_body = request_body.to_json
req = Net::HTTP::Post.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
req.body = json_request_body
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
dispatch_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
const data = {
"assignee_id": 840365,
"name": "Yearly Maintenance",
"description": "Yearly Maintenance Service Request",
"dispatch_type": "recurring_dispatch",
"department_id": 11942,
"form_id": 346103,
"reminder_interval": 60,
"repeat_interval": "daily",
"repeat_ends_option": "ends_after",
"repeat_ends_on": "12/1/2024",
"repeat_occurrences": 2,
"responses": [
{ "entry_id": 4506586, "value": "Jane" },
{ "entry_id": 4506587, "value": "Doe" },
{ "entry_id": 4506588, "value": "Main Street" },
{ "entry_id": 4506589, "value": "Boca Raton" },
{ "entry_id": 4506590, "value": "FL" },
{ "entry_id": 4506591, "value": "23456" },
{ "entry_id": 4506592, "value": "USA" },
{ "entry_id": 4506593, "value": "222-333-4444" }
],
"scheduled_at": "12/1/2024 8:00:00 AM",
"scheduled_end": "12/1/2024 12:00:00 PM"
};
fetch("https://www.gocanvas.com/api/v3/dispatches", {
method: "POST",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(dispatch => console.log(dispatch));
RESPONSE
{
"id": 194781,
"type": "dispatch_item",
"form_id": 346103,
"user_id": 840365,
"department_id": 11942,
"customer_id": null,
"project_id": null,
"site_id": null,
"submission_id": null,
"name": "Repair request",
"description": "123 Main St Service Request",
"status": "assigned",
"scheduled_at": "2024-12-01 08:00:00 UTC",
"scheduled_end": "2024-12-01 12:00:00 UTC",
"sent_at": null,
"completed_at": null,
"deleted_at": null,
"send_calendar_invite": true,
"reminder_interval": 60,
"created_at": "2024-11-11 21:09:02 UTC",
"repeat_dispatch_schedule_id": 37842
}
HTTP Request
POST https://www.gocanvas.com/api/v3/dispatches
Request Body Parameters
| Parameter | Type | Description |
|---|---|---|
| body | hash | The JSON Dispatch body |
| assignee_id | integer (optional) | The identifier for the User assigned the Dispatch; when this is not provided, the Dispatch remains unassigned |
| name | string (optional) | A short name for the Dispatch displayed on the Dispatch Calendar and the assigned user's calendar invitation |
| description | string (optional) | A short description of the Dispatch displayed on the assigned user's mobile device |
| dispatch_type | enum | The type of the Dispatch. Can be immediate_dispatch or scheduled_dispatch or recurring_dispatch |
| department_id** | integer (optional) | The identifier for the Department the Dispatch will be created in |
| form_id | integer | The identifier to specify a Form |
| reminder_interval | integer (optional) | The number of minutes before a Dispatch event that a reminder is sent |
| repeat_ends_option* | enum | The option for when the recurring dispatch ends. Valid values are ends_after, ends_on. |
| repeat_ends_on* | string | The date when the recurring dispatch ends. Required if repeat_ends_option is ends_on. Format: MM/DD/YYYY. |
| repeat_interval* | enum | The interval for the recurring dispatch. Valid values are daily, weekdays, weekly, monthly_day, monthly_date, yearly.*** |
| repeat_occurrences | integer (optional) | The number of occurrences for the recurring dispatch. Required if repeat_ends_option is ends_after. |
| responses[] | array | A collection of responses against Form Entries used to pre-populate the assignee's Submission |
| responses[].entry_id | integer | The unique identifier of an Entry |
| responses[].value | string | The response data for the Entry |
| responses[].multi_key† | string (optional) | Reference to the looped value |
| scheduled_at* | datetime | The date and time the Dispatch is scheduled to begin. Uses formats "MM/DD/YYYY HH:mm/ss AM" |
| scheduled_end* | datetime | The date and time the Dispatch is scheduled to end. Uses formats "MM/DD/YYYY HH:mm/ss AM" |
| send_calendar_invite | boolean (optional) | Sends a calendar invite for the Dispatch when true |
| no_form_assignment | boolean (optional) | Allows creation of a Dispatch without the user being assigned to the form when true |
* Only Required for recurring_dispatch type
** If no department_id is provided, the User's default department will be used. If the assignee is unassigned or has no default, the Form's originating department is used.
*** monthly_date refers to the day of the month (e.g. "Monthly on the 18th"). monthly_day refers to the week of the month and the day of the week (e.g. "Monthly on the 3rd Thursday").
† Only required for looped forms
Create a Dispatch with loops
Loop screens can be configured when designing a form, for information on how to configure loop screens, please refer to Loop Screens. Responses in loop screens use the multi_key field to identify the looped value.
BODY='{
"assignee_id": 840365,
"name": "Repair request",
"description": "123 Main St Service Request",
"dispatch_type": "immediate_dispatch",
"department_id": 11942,
"form_id": 346103,
"responses": [
{ "entry_id": 4506586, "value": "Jane" },
{ "entry_id": 4506587, "value": "Doe" },
{ "entry_id": 4506588, "value": "Main Street" },
{ "entry_id": 4506589, "value": "Boca Raton" },
{ "entry_id": 4506590, "value": "FL" },
{ "entry_id": 4506591, "value": "23456" },
{ "entry_id": 4506592, "value": "USA" },
{ "entry_id": 4506593, "value": "222-333-4444" },
{ "entry_id": 4506600, "value": "Unit 201" },
{ "entry_id": 4506594, "multi_key": "Unit 201", "value": "High" },
{ "entry_id": 4506595, "multi_key": "Unit 201", "value": "Water Leak" }
]
}'
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X POST \
-d $BODY \
https://www.gocanvas.com/api/v3/dispatches
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
request_body = {
"assignee_id": 840365,
"name": "Repair request",
"description": "123 Main St Service Request",
"dispatch_type": "immediate_dispatch",
"department_id": 11942,
"form_id": 346103,
"responses": [
{ "entry_id": 4506586, "value": "Jane" },
{ "entry_id": 4506587, "value": "Doe" },
{ "entry_id": 4506588, "value": "Main Street" },
{ "entry_id": 4506589, "value": "Boca Raton" },
{ "entry_id": 4506590, "value": "FL" },
{ "entry_id": 4506591, "value": "23456" },
{ "entry_id": 4506592, "value": "USA" },
{ "entry_id": 4506593, "value": "222-333-4444" },
{ "entry_id": 4506600, "value": "Unit 201" },
{ "entry_id": 4506594, "multi_key": "Unit 201", "value": "High" },
{ "entry_id": 4506595, "multi_key": "Unit 201", "value": "Water Leak" }
]
}
uri = URI("https://www.gocanvas.com/api/v3/dispatches")
json_request_body = request_body.to_json
req = Net::HTTP::Post.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
req.body = json_request_body
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
dispatch_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
const data = {
"assignee_id": 840365,
"name": "Repair request",
"description": "123 Main St Service Request",
"dispatch_type": "immediate_dispatch",
"department_id": 11942,
"form_id": 346103,
"responses": [
{ "entry_id": 4506586, "value": "Jane" },
{ "entry_id": 4506587, "value": "Doe" },
{ "entry_id": 4506588, "value": "Main Street" },
{ "entry_id": 4506589, "value": "Boca Raton" },
{ "entry_id": 4506590, "value": "FL" },
{ "entry_id": 4506591, "value": "23456" },
{ "entry_id": 4506592, "value": "USA" },
{ "entry_id": 4506593, "value": "222-333-4444" },
{ "entry_id": 4506600, "value": "Unit 201" },
{ "entry_id": 4506594, "multi_key": "Unit 201", "value": "High" },
{ "entry_id": 4506595, "multi_key": "Unit 201", "value": "Water Leak" }
]
};
fetch("https://www.gocanvas.com/api/v3/dispatches", {
method: "POST",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(dispatch => console.log(dispatch));
RESPONSE
{
"id": 194780,
"type": "dispatch_item",
"form_id": 346103,
"user_id": 840365,
"department_id": 11942,
"customer_id": null,
"project_id": null,
"site_id": null,
"submission_id": null,
"name": "Repair request",
"description": "123 Main St Service Request",
"status": "assigned",
"scheduled_at": null,
"scheduled_end": null,
"sent_at": null,
"completed_at": null,
"deleted_at": null,
"send_calendar_invite": false,
"reminder_interval": null,
"created_at": "2024-11-11 21:09:02 UTC"
}
HTTP Request
POST https://www.gocanvas.com/api/v3/dispatches
Request Body Parameters
| Parameter | Type | Description |
|---|---|---|
| body | hash | The JSON Dispatch body |
| assignee_id | integer (optional) | The identifier for the User assigned the Dispatch; when this is not provided, the Dispatch remains unassigned |
| name | string (optional) | A short name for the Dispatch displayed on the Dispatch Calendar and the assigned user's calendar invitation |
| description | string (optional) | A short description of the Dispatch displayed on the assigned user's mobile device |
| dispatch_type | enum | The type of the Dispatch. Can be immediate_dispatch or scheduled_dispatch |
| department_id* | integer (optional) | The identifier for the Department the Dispatch will be created in |
| form_id | integer | The identifier to specify a Form |
| responses[] | array | A collection of responses against Form Entries used to pre-populate the assignee's Submission |
| responses[].entry_id | integer | The unique identifier of an Entry |
| responses[].entry_guid | string | The unique guid of an Entry. An alternative to entry_id |
| responses[].value | string | The response data for the Entry |
| responses[].multi_key† | string (optional) | Reference to the looped value |
| send_notification | boolean (optional) | Sends a push notification to the mobile app for the Dispatch when true |
| no_form_assignment | boolean (optional) | Allows creation of a Dispatch without the user being assigned to the form when true |
* If no department_id is provided, the User's default department will be used. If the assignee is unassigned or has no default, the Form's originating department is used.
† Only required for looped forms
Customers, Projects, and Sites
Dispatches may be created and associated with Customers, Projects, or Sites. This allows for Dispatches to be organized and tracked within the Project Management Views.
Dispatches associated with Customers, Projects, or Sites support the same parameters as Dispatches without associations such as loops and scheduling. Additional parameters such as customer_id are used to create the association.
BODY='{
"assignee_id": 840365,
"name": "Repair request",
"description": "123 Main St Service Request",
"dispatch_type": "immediate_dispatch",
"department_id": 11942,
"form_id": 346103,
"project_id": 11,
"responses": [
{ "entry_id": 4506586, "value": "Jane" },
{ "entry_id": 4506587, "value": "Doe" },
{ "entry_id": 4506588, "value": "Main Street" },
{ "entry_id": 4506589, "value": "Boca Raton" },
{ "entry_id": 4506590, "value": "FL" },
{ "entry_id": 4506591, "value": "23456" },
{ "entry_id": 4506592, "value": "USA" },
{ "entry_id": 4506593, "value": "222-333-4444" }
]
}'
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X POST \
-d $BODY \
https://www.gocanvas.com/api/v3/dispatches
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
request_body = {
"assignee_id": 840365,
"name": "Repair request",
"description": "123 Main St Service Request",
"dispatch_type": "immediate_dispatch",
"department_id": 11942,
"form_id": 346103,
"project_id": 11,
"responses": [
{ "entry_id": 4506586, "value": "Jane" },
{ "entry_id": 4506587, "value": "Doe" },
{ "entry_id": 4506588, "value": "Main Street" },
{ "entry_id": 4506589, "value": "Boca Raton" },
{ "entry_id": 4506590, "value": "FL" },
{ "entry_id": 4506591, "value": "23456" },
{ "entry_id": 4506592, "value": "USA" },
{ "entry_id": 4506593, "value": "222-333-4444" }
]
}
uri = URI("https://www.gocanvas.com/api/v3/dispatches")
json_request_body = request_body.to_json
req = Net::HTTP::Post.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
req.body = json_request_body
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
dispatch_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
const data = {
"assignee_id": 840365,
"name": "Repair request",
"description": "123 Main St Service Request",
"dispatch_type": "immediate_dispatch",
"department_id": 11942,
"form_id": 346103,
"project_id": 11,
"responses": [
{ "entry_id": 4506586, "value": "Jane" },
{ "entry_id": 4506587, "value": "Doe" },
{ "entry_id": 4506588, "value": "Main Street" },
{ "entry_id": 4506589, "value": "Boca Raton" },
{ "entry_id": 4506590, "value": "FL" },
{ "entry_id": 4506591, "value": "23456" },
{ "entry_id": 4506592, "value": "USA" },
{ "entry_id": 4506593, "value": "222-333-4444" }
]
};
fetch("https://www.gocanvas.com/api/v3/dispatches", {
method: "POST",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(dispatch => console.log(dispatch));
RESPONSE
{
"id": 194780,
"type": "dispatch_item",
"form_id": 346103,
"user_id": 840365,
"department_id": 11942,
"customer_id": null,
"project_id": 11,
"site_id": null,
"submission_id": null,
"name": "Repair request",
"description": "123 Main St Service Request",
"status": "assigned",
"scheduled_at": null,
"scheduled_end": null,
"sent_at": null,
"completed_at": null,
"deleted_at": null,
"send_calendar_invite": false,
"reminder_interval": null,
"created_at": "2024-11-11 21:09:02 UTC"
}
HTTP Request
POST https://www.gocanvas.com/api/v3/dispatches
Request Body Parameters
| Parameter | Type | Description |
|---|---|---|
| body | hash | The JSON Dispatch body |
| assignee_id | integer (optional) | The identifier for the User assigned the Dispatch; when this is not provided, the Dispatch remains unassigned |
| name | string (optional) | A short name for the Dispatch displayed on the Dispatch Calendar and the assigned user's calendar invitation |
| description | string (optional) | A short description of the Dispatch displayed on the assigned user's mobile device |
| dispatch_type | enum | The type of the Dispatch. Can be immediate_dispatch or scheduled_dispatch |
| form_id | integer | The identifier to specify a Form |
| customer_id | integer (optional) | The identifier of the Customer to associate the Dispatch with |
| project_id | integer (optional) | The identifier of the Project to associate the Dispatch with |
| site_id | integer (optional) | The identifier of the Site to associate the Dispatch with |
| responses[] | array | A collection of responses against Form Entries used to pre-populate the assignee's Submission |
| responses[].entry_id | integer | The unique identifier of an Entry |
| responses[].value | string | The response data for the Entry |
| responses[].multi_key† | string | Reference to the looped value |
† Only required for looped forms
Delete a Dispatch
A Dispatch can be deleted with a DELETE request.
By default, the DELETE request will only soft delete the Dispatch which preserves the Dispatch data and removes it from mobile device task lists. To permanently delete the Dispatch, include the hard_delete parameter with a value of true, e.g. DELETE https://www.gocanvas.com/api/v3/dispatches/194781?hard_delete=true .
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X DELETE \
https://www.gocanvas.com/api/v3/dispatches/194781
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
uri = URI("https://www.gocanvas.com/api/v3/dispatches/194781")
req = Net::HTTP::Delete.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
dispatch_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
fetch("https://www.gocanvas.com/api/v3/dispatches/194781", {
method: "DELETE",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
}
})
.then(response => response.json())
.then(dispatch => console.log(dispatch));
RESPONSE
{
"message": "Dispatch 194781 has been soft deleted successfully"
}
HTTP Request
DELETE https://www.gocanvas.com/api/v3/dispatches/194781
Request Parameters
| Parameter | Type | Description |
|---|---|---|
| hard_delete* | boolean | Will hard delete the Dispatch record when set to true |
* This is an optional URL parameter. If not provided, the Dispatch will be soft deleted.
Form
A Form is how you capture data with GoCanvas. It defines all data you wish to collect.
The Form object
EXAMPLE
{
"id": 346127,
"type": "form",
"name": "Basic Form",
"description": "User Info",
"status": "published",
"version": 1,
"root_version_id": 346127,
"workflow_enabled": false,
"dispatch_enabled": false,
"web_form": false,
"email_options": 2,
"view_pdf_mobile": true,
"is_locked_by_canvas": false,
"mobile_builder_enabled": false,
"sheet_style_enabled": true,
"builderVersion": "3",
"sections": [
{
"id": 8969,
"type": "section",
"form_id": 346127,
"description": "User Info",
"position": 0,
"section_type_id": 10,
"hides_detailed_description": false,
"sheets": [
{
"id": 10278,
"type": "sheet",
"form_id": 346127,
"section_id": 8969,
"description": "User Info",
"position": 0,
"sheet_type_id": 11,
"inserts_page_break_at_the_end": false,
"show_sheet_name": true,
"allow_duplicate": null,
"style": 0,
"integration_form": false,
"entries": [
{
"id": 51464,
"type": "entry",
"form_id": 346127,
"sheet_id": 10278,
"entry_type_id": 10,
"label": "NAME",
"default": null,
"length": null,
"required": false,
"position": 0,
"guid": "2F04C1F7C3CE7A29F3E7351619181168339182D0",
"original_type_id": 0,
"reference_data_column": null,
"reference_data_id": null,
"live_data_source_id": null,
"live_data_source_column": null,
"data_source_context_id": null,
"read_only": false,
"visible": true,
"pdf_visibility": 0,
"web_visibility": 0,
"receipt_label": null,
"report_label": null,
"export_label": null,
"auto_email_subject": false,
"auto_email_body": false,
"auto_email_filename": false,
"inserts_page_break_at_the_end": false,
"auto_submission_name": false,
"minimum": null,
"maximum": null,
"mask": null,
"style": 0,
"barcode_enabled": null,
"integration_form": false,
"gps_display_type": null,
"zoom_level": null,
"gps_accuracy": null,
"gps_timeout": null,
"gps_accuracy_required": false,
"summary_entry": null,
"reference_image_id": null,
"entry_values": [],
"operations": [],
"dependent_entry": null,
"conditions": []
},
{
"id": 51465,
"type": "entry",
"form_id": 346127,
"sheet_id": 10278,
"entry_type_id": 10,
"label": "ADDRESS",
"default": null,
"length": null,
"required": false,
"position": 1,
"guid": "93C144AD3E0BD7612C7075B43562E752F4247CDF",
"original_type_id": 0,
"reference_data_column": null,
"reference_data_id": null,
"live_data_source_id": null,
"live_data_source_column": null,
"data_source_context_id": null,
"read_only": false,
"visible": true,
"pdf_visibility": 0,
"web_visibility": 0,
"receipt_label": null,
"report_label": null,
"export_label": null,
"auto_email_subject": false,
"auto_email_body": false,
"auto_email_filename": false,
"inserts_page_break_at_the_end": false,
"auto_submission_name": false,
"minimum": null,
"maximum": null,
"mask": null,
"style": 0,
"barcode_enabled": null,
"integration_form": false,
"gps_display_type": null,
"zoom_level": null,
"gps_accuracy": null,
"gps_timeout": null,
"gps_accuracy_required": false,
"summary_entry": null,
"reference_image_id": null,
"entry_values": [],
"operations": [],
"dependent_entry": null,
"conditions": []
},
{
"id": 51466,
"type": "entry",
"form_id": 346127,
"sheet_id": 10278,
"entry_type_id": 10,
"label": "CITY",
"default": null,
"length": null,
"required": false,
"position": 2,
"guid": "21C29FA4B978ACEC738392B99479C41B3AA645C2",
"original_type_id": 0,
"reference_data_column": null,
"reference_data_id": null,
"live_data_source_id": null,
"live_data_source_column": null,
"data_source_context_id": null,
"read_only": false,
"visible": true,
"pdf_visibility": 0,
"web_visibility": 0,
"receipt_label": null,
"report_label": null,
"export_label": null,
"auto_email_subject": false,
"auto_email_body": false,
"auto_email_filename": false,
"inserts_page_break_at_the_end": false,
"auto_submission_name": false,
"minimum": null,
"maximum": null,
"mask": null,
"style": 0,
"barcode_enabled": null,
"integration_form": false,
"gps_display_type": null,
"zoom_level": null,
"gps_accuracy": null,
"gps_timeout": null,
"gps_accuracy_required": false,
"summary_entry": null,
"reference_image_id": null,
"entry_values": [],
"operations": [],
"dependent_entry": null,
"conditions": []
},
{
"id": 51467,
"type": "entry",
"form_id": 346127,
"sheet_id": 10278,
"entry_type_id": 15,
"label": "STATE",
"default": "",
"length": null,
"required": false,
"position": 3,
"guid": "D8A8A397FFAD78F50EB96128B169815A5852F5BF",
"original_type_id": 5,
"reference_data_column": null,
"reference_data_id": null,
"live_data_source_id": null,
"live_data_source_column": null,
"data_source_context_id": null,
"read_only": false,
"visible": true,
"pdf_visibility": 0,
"web_visibility": 0,
"receipt_label": null,
"report_label": null,
"export_label": null,
"auto_email_subject": false,
"auto_email_body": false,
"auto_email_filename": false,
"inserts_page_break_at_the_end": false,
"auto_submission_name": false,
"minimum": 2.0,
"maximum": 5.0,
"mask": null,
"style": 1,
"barcode_enabled": false,
"integration_form": false,
"gps_display_type": null,
"zoom_level": null,
"gps_accuracy": null,
"gps_timeout": null,
"gps_accuracy_required": false,
"summary_entry": null,
"reference_image_id": null,
"entry_values": [
{
"id": 786229650,
"type": "entry_value",
"entry_id": 51467,
"text": "ARIZONA",
"position": 0
},
{
"id": 786229651,
"type": "entry_value",
"entry_id": 51467,
"text": "ALASKA",
"position": 1
},
{
"id": 786229652,
"type": "entry_value",
"entry_id": 51467,
"text": "ALABAMA",
"position": 2
},
{
"id": 786229653,
"type": "entry_value",
"entry_id": 51467,
"text": null,
"position": 3
}
],
"operations": [],
"dependent_entry": null,
"conditions": []
}
],
"conditions": [],
"multi_section": null,
"display_entry": null
}
]
}
]
}
{
"id": 4639578,
"type": "form",
"name": "Loop Screen Form",
"description": null,
"status": "published",
"version": 1,
"root_version_id": 4639578,
"workflow_enabled": false,
"dispatch_enabled": false,
"web_form": false,
"email_options": 2,
"view_pdf_mobile": true,
"is_locked_by_canvas": false,
"mobile_builder_enabled": false,
"sheet_style_enabled": true,
"builderVersion": "3",
"sections": [
{
"id": 8976,
"type": "section",
"form_id": 4639578,
"description": "Customer Information",
"position": 0,
"section_type_id": 10,
"hides_detailed_description": false,
"sheets": [
{
"id": 10285,
"type": "sheet",
"form_id": 4639578,
"section_id": 8976,
"description": "Customer Information",
"position": 0,
"sheet_type_id": 11,
"inserts_page_break_at_the_end": false,
"show_sheet_name": true,
"allow_duplicate": null,
"style": 0,
"integration_form": false,
"entries": [
{
"id": 51484,
"type": "entry",
"form_id": 4639578,
"sheet_id": 10285,
"entry_type_id": 10,
"label": "Phone",
"default": null,
"length": null,
"required": false,
"position": 0,
"guid": "50A2A42F8E73D8740196E7144F345A1259DABBAD",
"original_type_id": 0,
"reference_data_column": null,
"reference_data_id": null,
"live_data_source_id": null,
"live_data_source_column": null,
"data_source_context_id": null,
"read_only": false,
"visible": true,
"pdf_visibility": 0,
"web_visibility": 0,
"receipt_label": null,
"report_label": null,
"export_label": null,
"auto_email_subject": false,
"auto_email_body": false,
"auto_email_filename": false,
"inserts_page_break_at_the_end": false,
"auto_submission_name": false,
"minimum": null,
"maximum": null,
"mask": null,
"style": 0,
"barcode_enabled": null,
"integration_form": false,
"gps_display_type": null,
"zoom_level": null,
"gps_accuracy": null,
"gps_timeout": null,
"gps_accuracy_required": false,
"summary_entry": null,
"reference_image_id": null,
"entry_values": [],
"operations": [],
"dependent_entry": null,
"conditions": []
},
{
"id": 51485,
"type": "entry",
"form_id": 4639578,
"sheet_id": 10285,
"entry_type_id": 10,
"label": "Email",
"default": null,
"length": null,
"required": false,
"position": 1,
"guid": "4F305761009933A5AF3BC62273C1FCA26DB8DD91",
"original_type_id": 0,
"reference_data_column": null,
"reference_data_id": null,
"live_data_source_id": null,
"live_data_source_column": null,
"data_source_context_id": null,
"read_only": false,
"visible": true,
"pdf_visibility": 0,
"web_visibility": 0,
"receipt_label": null,
"report_label": null,
"export_label": null,
"auto_email_subject": false,
"auto_email_body": false,
"auto_email_filename": false,
"inserts_page_break_at_the_end": false,
"auto_submission_name": false,
"minimum": null,
"maximum": null,
"mask": null,
"style": 0,
"barcode_enabled": null,
"integration_form": false,
"gps_display_type": null,
"zoom_level": null,
"gps_accuracy": null,
"gps_timeout": null,
"gps_accuracy_required": false,
"summary_entry": null,
"reference_image_id": null,
"entry_values": [],
"operations": [],
"dependent_entry": null,
"conditions": []
},
{
"id": 51486,
"type": "entry",
"form_id": 4639578,
"sheet_id": 10285,
"entry_type_id": 10,
"label": "Name",
"default": null,
"length": null,
"required": false,
"position": 2,
"guid": "940661D995630AB3FBBEC8F0B22A28F4B359436F",
"original_type_id": 0,
"reference_data_column": null,
"reference_data_id": null,
"live_data_source_id": null,
"live_data_source_column": null,
"data_source_context_id": null,
"read_only": false,
"visible": true,
"pdf_visibility": 0,
"web_visibility": 0,
"receipt_label": null,
"report_label": null,
"export_label": null,
"auto_email_subject": false,
"auto_email_body": false,
"auto_email_filename": false,
"inserts_page_break_at_the_end": false,
"auto_submission_name": false,
"minimum": null,
"maximum": null,
"mask": null,
"style": 0,
"barcode_enabled": null,
"integration_form": false,
"gps_display_type": null,
"zoom_level": null,
"gps_accuracy": null,
"gps_timeout": null,
"gps_accuracy_required": false,
"summary_entry": null,
"reference_image_id": null,
"entry_values": [],
"operations": [],
"dependent_entry": null,
"conditions": []
}
],
"conditions": [],
"multi_section": null,
"display_entry": null
}
]
},
{
"id": 8977,
"type": "section",
"form_id": 4639578,
"description": "Service Request",
"position": 1,
"section_type_id": 10,
"hides_detailed_description": false,
"sheets": [
{
"id": 10287,
"type": "sheet",
"form_id": 4639578,
"section_id": 8977,
"description": "Service Request",
"position": 0,
"sheet_type_id": 15,
"inserts_page_break_at_the_end": false,
"show_sheet_name": true,
"allow_duplicate": null,
"style": 0,
"integration_form": false,
"entries": [
{
"id": 51489,
"type": "entry",
"form_id": 4639578,
"sheet_id": 10287,
"entry_type_id": 10,
"label": "Address",
"default": null,
"length": null,
"required": false,
"position": 0,
"guid": "37AC77CE6AE7FF08F4BAF9BBDA06CCFB6F9820A9",
"original_type_id": 0,
"reference_data_column": null,
"reference_data_id": null,
"live_data_source_id": null,
"live_data_source_column": null,
"data_source_context_id": null,
"read_only": false,
"visible": true,
"pdf_visibility": 0,
"web_visibility": 0,
"receipt_label": null,
"report_label": null,
"export_label": null,
"auto_email_subject": false,
"auto_email_body": false,
"auto_email_filename": false,
"inserts_page_break_at_the_end": false,
"auto_submission_name": false,
"minimum": null,
"maximum": null,
"mask": null,
"style": 0,
"barcode_enabled": null,
"integration_form": false,
"gps_display_type": null,
"zoom_level": null,
"gps_accuracy": null,
"gps_timeout": null,
"gps_accuracy_required": false,
"summary_entry": null,
"reference_image_id": null,
"entry_values": [],
"operations": [],
"dependent_entry": null,
"conditions": []
}
],
"conditions": [],
"multi_section": {
"id": 8978,
"type": "section",
"form_id": 4639578,
"description": "Service Requested",
"position": 2,
"section_type_id": 11,
"hides_detailed_description": true
},
"display_entry": null
}
]
},
{
"id": 8978,
"type": "section",
"form_id": 4639578,
"description": "Service Requested",
"position": 2,
"section_type_id": 11,
"hides_detailed_description": true,
"sheets": [
{
"id": 10286,
"type": "sheet",
"form_id": 4639578,
"section_id": 8978,
"description": "Service Requested",
"position": 0,
"sheet_type_id": 11,
"inserts_page_break_at_the_end": false,
"show_sheet_name": true,
"allow_duplicate": null,
"style": 0,
"integration_form": false,
"entries": [
{
"id": 51487,
"type": "entry",
"form_id": 4639578,
"sheet_id": 10286,
"entry_type_id": 15,
"label": "Priority",
"default": "GC_BLANK_DEFAULT",
"length": null,
"required": false,
"position": 0,
"guid": "1162B07CF6BD1C8406C5B1D418793AB93994CF8C",
"original_type_id": 5,
"reference_data_column": null,
"reference_data_id": null,
"live_data_source_id": null,
"live_data_source_column": null,
"data_source_context_id": null,
"read_only": false,
"visible": true,
"pdf_visibility": 0,
"web_visibility": 0,
"receipt_label": null,
"report_label": null,
"export_label": null,
"auto_email_subject": false,
"auto_email_body": false,
"auto_email_filename": false,
"inserts_page_break_at_the_end": false,
"auto_submission_name": false,
"minimum": 2.0,
"maximum": 5.0,
"mask": null,
"style": 1,
"barcode_enabled": false,
"integration_form": false,
"gps_display_type": null,
"zoom_level": null,
"gps_accuracy": null,
"gps_timeout": null,
"gps_accuracy_required": false,
"summary_entry": null,
"reference_image_id": null,
"entry_values": [
{
"id": 786229668,
"type": "entry_value",
"entry_id": 51487,
"text": "High",
"position": 0
},
{
"id": 786229669,
"type": "entry_value",
"entry_id": 51487,
"text": "Medium",
"position": 1
},
{
"id": 786229670,
"type": "entry_value",
"entry_id": 51487,
"text": "Low",
"position": 2
}
],
"operations": [],
"dependent_entry": null,
"conditions": []
},
{
"id": 51488,
"type": "entry",
"form_id": 4639578,
"sheet_id": 10286,
"entry_type_id": 15,
"label": "Service Requested",
"default": "GC_BLANK_DEFAULT",
"length": null,
"required": false,
"position": 1,
"guid": "AC5B9BF04298B2B0E099680DDDBE17CB04627692",
"original_type_id": 5,
"reference_data_column": null,
"reference_data_id": null,
"live_data_source_id": null,
"live_data_source_column": null,
"data_source_context_id": null,
"read_only": false,
"visible": true,
"pdf_visibility": 0,
"web_visibility": 0,
"receipt_label": null,
"report_label": null,
"export_label": null,
"auto_email_subject": false,
"auto_email_body": false,
"auto_email_filename": false,
"inserts_page_break_at_the_end": false,
"auto_submission_name": false,
"minimum": 2.0,
"maximum": 5.0,
"mask": null,
"style": 1,
"barcode_enabled": false,
"integration_form": false,
"gps_display_type": null,
"zoom_level": null,
"gps_accuracy": null,
"gps_timeout": null,
"gps_accuracy_required": false,
"summary_entry": null,
"reference_image_id": null,
"entry_values": [
{
"id": 786229671,
"type": "entry_value",
"entry_id": 51488,
"text": "Painting",
"position": 0
},
{
"id": 786229672,
"type": "entry_value",
"entry_id": 51488,
"text": "Cleaning",
"position": 1
},
{
"id": 786229673,
"type": "entry_value",
"entry_id": 51488,
"text": "Replacement",
"position": 2
},
{
"id": 786229674,
"type": "entry_value",
"entry_id": 51488,
"text": "Repair / Maintenance",
"position": 3
}
],
"operations": [],
"dependent_entry": null,
"conditions": []
}
],
"conditions": [],
"multi_section": null,
"display_entry": null
}
]
}
]
}
Forms are organized into Sections and Sheets, which hold individual Entries. Entries are questions that the user will answer.
List all Forms
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X GET \
https://www.gocanvas.com/api/v3/forms
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
uri = URI("https://www.gocanvas.com/api/v3/forms")
req = Net::HTTP::Get.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
forms_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
fetch("https://www.gocanvas.com/api/v3/forms", {
method: "GET",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
}
})
.then(response => response.json())
.then(forms => console.log(forms));
Users can view a list of all the Forms to which they have access.
RESPONSE
[
{
"id": 346127,
"type": "form",
"name": "Basic Form",
"description": "User Info",
"status": "published",
"version": 1,
"root_version_id": 346127,
"dispatch_enabled": true,
"workflow_enabled": false,
"web_form": true,
"email_options": 2,
"view_pdf_mobile": true
},
{
"id": 4639578,
"type": "form",
"name": "Loop Screen Form",
"description": null,
"status": "published",
"version": 1,
"root_version_id": 4639578,
"dispatch_enabled": false,
"workflow_enabled": false,
"web_form": false,
"email_options": 2,
"view_pdf_mobile": true
}
]
HTTP Request
GET https://www.gocanvas.com/api/v3/forms
Query Parameters
| Parameter | Type | Description | Default |
|---|---|---|---|
| page | integer (optional) | The page requested, see Pagination | 1 |
Retrieve a Form
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X GET \
https://www.gocanvas.com/api/v3/forms/346127
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
uri = URI("https://www.gocanvas.com/api/v3/forms/346127")
req = Net::HTTP::Get.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
form_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
fetch("https://www.gocanvas.com/api/v3/forms/346127", {
method: "GET",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
}
})
.then(response => response.json())
.then(form => console.log(form));
Users can view basic or looped screen Form.
HTTP Request (Regular Form)
GET https://www.gocanvas.com/api/v3/forms/346127?format=flat
Query Parameters
Most use cases rely on the flat format. This will return a single JSON object with all the information needed to render a Form in a client application. If no format is specified, the default is nested.
| Parameter | Description | Options |
|---|---|---|
| format | Specifies the format of the form definition | nested, flat, minimal, metadata |
Retrieve a Form (nested)
nested: Provides a full understanding of the form definition, presented in a nested format.
Back to Retrieve a Form
RESPONSE
{
"id": 346127,
"type": "form",
"name": "Basic Form",
"description": null,
"status": "published",
"version": 1,
"root_version_id": 346127,
"workflow_enabled": false,
"dispatch_enabled": false,
"web_form": false,
"email_options": 2,
"view_pdf_mobile": true,
"is_locked_by_canvas": false,
"mobile_builder_enabled": false,
"sheet_style_enabled": true,
"builderVersion": "3",
"sections": [
{
"id": 8980,
"type": "section",
"form_id": 346127,
"description": "User Info",
"position": 0,
"section_type_id": 10,
"hides_detailed_description": false,
"sheets": [
{
"id": 10289,
"type": "sheet",
"form_id": 346127,
"section_id": 8980,
"description": "User Info",
"position": 0,
"sheet_type_id": 11,
"inserts_page_break_at_the_end": false,
"show_sheet_name": true,
"allow_duplicate": null,
"style": 0,
"integration_form": false,
"entries": [
{
"id": 51498,
"type": "entry",
"form_id": 346127,
"sheet_id": 10289,
"entry_type_id": 10,
"label": "NAME",
"default": null,
"length": null,
"required": false,
"position": 0,
"guid": "2F04C1F7C3CE7A29F3E7351619181168339182D0",
"original_type_id": 0,
"reference_data_column": null,
"reference_data_id": null,
"live_data_source_id": null,
"live_data_source_column": null,
"data_source_context_id": null,
"read_only": false,
"visible": true,
"pdf_visibility": 0,
"web_visibility": 0,
"receipt_label": null,
"report_label": null,
"export_label": null,
"auto_email_subject": false,
"auto_email_body": false,
"auto_email_filename": false,
"inserts_page_break_at_the_end": false,
"auto_submission_name": false,
"minimum": null,
"maximum": null,
"mask": null,
"style": 0,
"barcode_enabled": null,
"integration_form": false,
"gps_display_type": null,
"zoom_level": null,
"gps_accuracy": null,
"gps_timeout": null,
"gps_accuracy_required": false,
"summary_entry": null,
"reference_image_id": null,
"entry_values": [],
"operations": [],
"dependent_entry": null,
"conditions": []
},
{
"id": 51499,
"type": "entry",
"form_id": 346127,
"sheet_id": 10289,
"entry_type_id": 10,
"label": "ADDRESS",
"default": null,
"length": null,
"required": false,
"position": 1,
"guid": "93C144AD3E0BD7612C7075B43562E752F4247CDF",
"original_type_id": 0,
"reference_data_column": null,
"reference_data_id": null,
"live_data_source_id": null,
"live_data_source_column": null,
"data_source_context_id": null,
"read_only": false,
"visible": true,
"pdf_visibility": 0,
"web_visibility": 0,
"receipt_label": null,
"report_label": null,
"export_label": null,
"auto_email_subject": false,
"auto_email_body": false,
"auto_email_filename": false,
"inserts_page_break_at_the_end": false,
"auto_submission_name": false,
"minimum": null,
"maximum": null,
"mask": null,
"style": 0,
"barcode_enabled": null,
"integration_form": false,
"gps_display_type": null,
"zoom_level": null,
"gps_accuracy": null,
"gps_timeout": null,
"gps_accuracy_required": false,
"summary_entry": null,
"reference_image_id": null,
"entry_values": [],
"operations": [],
"dependent_entry": null,
"conditions": []
},
{
"id": 51500,
"type": "entry",
"form_id": 346127,
"sheet_id": 10289,
"entry_type_id": 10,
"label": "CITY",
"default": null,
"length": null,
"required": false,
"position": 2,
"guid": "21C29FA4B978ACEC738392B99479C41B3AA645C2",
"original_type_id": 0,
"reference_data_column": null,
"reference_data_id": null,
"live_data_source_id": null,
"live_data_source_column": null,
"data_source_context_id": null,
"read_only": false,
"visible": true,
"pdf_visibility": 0,
"web_visibility": 0,
"receipt_label": null,
"report_label": null,
"export_label": null,
"auto_email_subject": false,
"auto_email_body": false,
"auto_email_filename": false,
"inserts_page_break_at_the_end": false,
"auto_submission_name": false,
"minimum": null,
"maximum": null,
"mask": null,
"style": 0,
"barcode_enabled": null,
"integration_form": false,
"gps_display_type": null,
"zoom_level": null,
"gps_accuracy": null,
"gps_timeout": null,
"gps_accuracy_required": false,
"summary_entry": null,
"reference_image_id": null,
"entry_values": [],
"operations": [],
"dependent_entry": null,
"conditions": []
},
{
"id": 51501,
"type": "entry",
"form_id": 346127,
"sheet_id": 10289,
"entry_type_id": 15,
"label": "STATE",
"default": "",
"length": null,
"required": false,
"position": 3,
"guid": "D8A8A397FFAD78F50EB96128B169815A5852F5BF",
"original_type_id": 5,
"reference_data_column": null,
"reference_data_id": null,
"live_data_source_id": null,
"live_data_source_column": null,
"data_source_context_id": null,
"read_only": false,
"visible": true,
"pdf_visibility": 0,
"web_visibility": 0,
"receipt_label": null,
"report_label": null,
"export_label": null,
"auto_email_subject": false,
"auto_email_body": false,
"auto_email_filename": false,
"inserts_page_break_at_the_end": false,
"auto_submission_name": false,
"minimum": 2.0,
"maximum": 5.0,
"mask": null,
"style": 1,
"barcode_enabled": false,
"integration_form": false,
"gps_display_type": null,
"zoom_level": null,
"gps_accuracy": null,
"gps_timeout": null,
"gps_accuracy_required": false,
"summary_entry": null,
"reference_image_id": null,
"entry_values": [
{
"id": 786229679,
"type": "entry_value",
"entry_id": 51501,
"text": "ARIZONA",
"position": 0
},
{
"id": 786229680,
"type": "entry_value",
"entry_id": 51501,
"text": "ALASKA",
"position": 1
},
{
"id": 786229681,
"type": "entry_value",
"entry_id": 51501,
"text": "ALABAMA",
"position": 2
},
{
"id": 786229682,
"type": "entry_value",
"entry_id": 51501,
"text": null,
"position": 3
}
],
"operations": [],
"dependent_entry": null,
"conditions": []
}
],
"conditions": [],
"multi_section": null,
"display_entry": null
}
]
}
]
}
Response Parameters (nested format)
Form responses are organized in a nested format, with the Form at the top level, Sections nested within the Form, Sheets nested within Sections, and Entries nested within Sheets. Each level has its own parameters, detailed in the tables below.
Form Level
| Parameter | Type | Description |
|---|---|---|
| id | integer | The identifier for this exact version of the Form |
| name | string | The name of the Form |
| status * | enum | The status of the Form. Can be new, pending, published, or archived |
| description | string | The description of the Form |
| version | integer | The version number of the Form. When a new version is saved and published, this version counter increments |
| root_version_id | integer | The original Form identifier for all versions of the Form |
| workflow_enabled | boolean | Whether the Form has Workflow enabled |
| dispatch_enabled | boolean | Whether the Form has Dispatch enabled |
| web_form | boolean | Whether the Form is a web form |
| email_options | integer | The email option for mobile submitters of the Form. 0: Cannot email PDF1: Can email PDF to themselves only2: Can email PDF to anyone |
| view_pdf_mobile | boolean | Whether mobile submitters of the Form can view the PDF of their submission on their device |
| is_locked_by_canvas | boolean | Whether the Form is currently locked by the application. Forms may be temporarily locked when being used in integrations. |
| mobile_builder_enabled | boolean | Whether the Form has Mobile Builder (deprecated) enabled |
| sheet_style_enabled | boolean | Whether the Form has the grid sheet style enabled |
| builder_version | integer | The default version of the Form Builder that will be opened when editing the Form, 3 is current Advanced Builder |
| sections[] | array | A list of Sections within the Form |
* Only one version of a Form will be in published status at a time. This is the version of the Form accepting new Submissions.
Section Level
Sections are nested within the Form. The full path for these parameters is sections[].{parameter}.
| Parameter | Type | Description |
|---|---|---|
| id | integer | The identifier to specify a Section |
| form_id | integer | The identifier of the Form that the Section belongs to |
| description | string | The description of a Section |
| position | integer | The ordinal position of the Section, 0-indexed |
| section_type_id | integer | The identifier of the Section Type for the Section 10: Normal Section11: Multiple Entry Section |
| sheets[] | array | A list of Sheets within the Section |
Sheet Level
Sheets are nested within Sections. The full path for these parameters is sections[].sheets[].{parameter}.
| Parameter | Type | Description |
|---|---|---|
| id | integer | The identifier to specify a Sheet |
| form_id | integer | The identifier of the Form that the Sheet belongs to |
| section_id | integer | The identifier of the Section that the Sheet belongs to |
| description | string | The description of a Sheet |
| position | integer | The ordinal position of the Sheet, 0-indexed |
| sheet_type_id | integer | The identifier of the Sheet Type for the Sheet 10: Labels Left11: Labels Above12: Single Entry13: List (Advanced)14: Signature15: List (Simple)16: Drawing Pad |
| inserts_page_break_at_the_end | boolean | Whether basic PDF adds a page break after this Sheet |
| show_sheet_name | boolean | Whether basic PDF displays the Sheet name |
| allow_duplicate | boolean | Whether duplicate key fields are allowed in loops by clients |
| style | integer | The presentation style of the Sheet when looped0: Labels Above1: Table2: Table (pre-populated) |
| integration_form | boolean | (Deprecated) Whether this Sheet came from a Form which came from a public template, usually false for all Forms |
| multi_section | integer | The identifier of the multi-section associated with this Sheet (for loop screens) |
| display_entry | integer | The identifier of the Entry used as the display field (for loop screens) |
| entries[] | array | A list of Entries (fields/questions) within the Sheet |
| conditions[] | array | A list of conditional logic rules for this Sheet |
Entry Level
Entries are nested within Sheets. The full path for these parameters is sections[].sheets[].entries[].{parameter}.
| Parameter | Type | Description |
|---|---|---|
| id | integer | The identifier of the Entry |
| form_id | integer | The identifier of the Form that the Entry belongs to |
| sheet_id | integer | The identifier of the Sheet that the Entry belongs to |
| entry_type_id | integer | (Deprecated) The identifier of the Entry Type for the Entry, original_type_id is preferred |
| label | string | The prompt or question for an Entry |
| default | string | The default value for the Entry |
| length | integer | The maximum character length for Entries |
| required | boolean | Whether the Entry is required to be filled out |
| position | integer | The ordinal position of the Entry within the Sheet, 0-indexed |
| guid | string | A globally unique identifier for the Entry. This persists across versions of the Form if the Entry exists in multiple versions |
| original_type_id | integer | The type identifier for the Entry Type0: Text Box1: Integer2: Decimal3: Date4: Time5: Value List6: Attachment7: Checkbox8: Multi-Line Text9: Static Text10: Image Capture12: Web Link13: Payment20: Summary21: Calculation22: GPS23: Mirror24: Static Image25: Multi Photo98: Drawing99: Signature100: Video200: Dependent Form |
| reference_data_column | string | The column name from Reference Data linked to this Entry |
| reference_data_id | integer | The identifier of the Reference Data source linked to this Entry |
| live_data_source_id | integer | The identifier of the Live Data source linked to this Entry |
| live_data_source_column | string | The column name from Live Data source linked to this Entry |
| data_source_context_id | integer | The identifier for data source context configuration |
| read_only | boolean | Whether the Entry is read-only |
| visible | boolean | Whether the Entry is visible to client users |
| pdf_visibility | integer | The PDF visibility option for this Entry0: Always1: Never2: Only if field is not empty3: Only if default value has been changed4: Only if default value has been changed & field is not empty5: Only to addresses set on email options page |
| web_visibility | integer | The web visibility option for this Entry0: Always1: Never2: Only if field is not empty3: Only if default value has been changed4: Only if default value has been changed & field is not empty |
| receipt_label | string | Custom label for this Entry on receipts |
| report_label | string | Custom label for this Entry in reports |
| export_label | string | Custom label for this Entry in exports |
| auto_email_subject | boolean | Whether this Entry's value is automatically used in email subjects |
| auto_email_body | boolean | Whether this Entry's value is automatically used in email bodies |
| auto_email_filename | boolean | Whether this Entry's value is automatically used in email filenames |
| inserts_page_break_at_the_end | boolean | Whether a page break is inserted after this Entry in standard PDF |
| auto_submission_name | boolean | Whether this Entry's value is automatically used as the Submission name |
| minimum | number | The minimum value for the Entry |
| maximum | number | The maximum value for the Entry |
| mask | string | Input mask pattern for the Entry |
| style | integer | The presentation style for choice-based Entries0: Default1: Dropdown |
| barcode_enabled | boolean | Whether barcode scanning is enabled for this Entry |
| integration_form | boolean | (Deprecated) Whether this Entry came from a Form which came from a public template |
| gps_display_type | integer | The display format for GPS Entries |
| zoom_level | integer | The map zoom level for GPS Entries |
| gps_accuracy | number | The required GPS accuracy in meters |
| gps_timeout | integer | The GPS timeout in milliseconds |
| gps_accuracy_required | boolean | Whether GPS accuracy is enforced |
| summary_entry | object | Reference to the Entry being summarized (for Summary type Entries) |
| reference_image_id | integer | The identifier of the reference image for Static Image Entries |
| entry_values[] | array | List of choice options for Value List, Dropdown, and similar Entries |
| operations[] | array | List of operations (calculations/rules) applied to this Entry |
| dependent_entry | object | Reference to dependent form Entry configuration |
| conditions[] | array | List of conditional logic rules for this Entry |
Entry Values Level
Entry Values are the list of Choices populating Dropdown type Entries. They are nested within Entries. The full path for these parameters is sections[].sheets[].entries[].entry_values[].{parameter}.
| Parameter | Type | Description |
|---|---|---|
| id | integer | The identifier for this choice option |
| entry_id | integer | The identifier of the Entry this choice belongs to |
| text | string | The display text for this choice option |
| position | integer | The ordinal position of this choice, 0-indexed |
Retrieve a Form (flat)
flat: Provides a full understanding of the form definition, presented in a flattened format.
Back to Retrieve a Form
RESPONSE
{
"id": 346127,
"type": "form",
"name": "Basic Form",
"description": null,
"status": "published",
"version": 1,
"root_version_id": 346127,
"workflow_enabled": false,
"dispatch_enabled": false,
"web_form": false,
"email_options": 2,
"view_pdf_mobile": true,
"builderVersion": "3",
"sections": [
{
"id": 8980,
"type": "section",
"form_id": 346127,
"description": "User Info",
"position": 0,
"section_type_id": 10,
"original_type_id": 0
}
],
"sheets": [
{
"id": 10289,
"type": "sheet",
"form_id": 346127,
"section_id": 8980,
"description": "User Info",
"position": 0,
"sheet_type_id": 11,
"allow_duplicate": null,
"style": 0,
"original_type_id": 1,
"conditions": [],
"multi_section": null,
"display_entry": null
}
],
"entries": [
{
"id": 51498,
"type": "Text",
"form_id": 346127,
"sheet_id": 10289,
"entry_type_id": 10,
"label": "NAME",
"default": null,
"length": null,
"required": false,
"position": 0,
"guid": "2F04C1F7C3CE7A29F3E7351619181168339182D0",
"original_type_id": 0,
"minimum": null,
"maximum": null,
"mask": null,
"style": 0,
"gps_timeout": null,
"gps_accuracy": null,
"gps_accuracy_required": false,
"barcode_enabled": null,
"reference_data_column": null,
"reference_data_id": null,
"live_data_source_id": null,
"live_data_source_column": null,
"data_source_context_id": null,
"read_only": false,
"visible": true,
"receipt_label": null,
"summary_entry": null,
"reference_image_id": null,
"entry_values": [],
"dependent_entry": null,
"export_label": null,
"pdf_visibility": 0
},
{
"id": 51499,
"type": "Text",
"form_id": 346127,
"sheet_id": 10289,
"entry_type_id": 10,
"label": "ADDRESS",
"default": null,
"length": null,
"required": false,
"position": 1,
"guid": "93C144AD3E0BD7612C7075B43562E752F4247CDF",
"original_type_id": 0,
"minimum": null,
"maximum": null,
"mask": null,
"style": 0,
"gps_timeout": null,
"gps_accuracy": null,
"gps_accuracy_required": false,
"barcode_enabled": null,
"reference_data_column": null,
"reference_data_id": null,
"live_data_source_id": null,
"live_data_source_column": null,
"data_source_context_id": null,
"read_only": false,
"visible": true,
"receipt_label": null,
"summary_entry": null,
"reference_image_id": null,
"entry_values": [],
"dependent_entry": null,
"export_label": null,
"pdf_visibility": 0
},
{
"id": 51500,
"type": "Text",
"form_id": 346127,
"sheet_id": 10289,
"entry_type_id": 10,
"label": "CITY",
"default": null,
"length": null,
"required": false,
"position": 2,
"guid": "21C29FA4B978ACEC738392B99479C41B3AA645C2",
"original_type_id": 0,
"minimum": null,
"maximum": null,
"mask": null,
"style": 0,
"gps_timeout": null,
"gps_accuracy": null,
"gps_accuracy_required": false,
"barcode_enabled": null,
"reference_data_column": null,
"reference_data_id": null,
"live_data_source_id": null,
"live_data_source_column": null,
"data_source_context_id": null,
"read_only": false,
"visible": true,
"receipt_label": null,
"summary_entry": null,
"reference_image_id": null,
"entry_values": [],
"dependent_entry": null,
"export_label": null,
"pdf_visibility": 0
},
{
"id": 51501,
"type": "Single Choice",
"form_id": 346127,
"sheet_id": 10289,
"entry_type_id": 15,
"label": "STATE",
"default": "",
"length": null,
"required": false,
"position": 3,
"guid": "D8A8A397FFAD78F50EB96128B169815A5852F5BF",
"original_type_id": 5,
"minimum": 2.0,
"maximum": 5.0,
"mask": null,
"style": 1,
"gps_timeout": null,
"gps_accuracy": null,
"gps_accuracy_required": false,
"barcode_enabled": false,
"reference_data_column": null,
"reference_data_id": null,
"live_data_source_id": null,
"live_data_source_column": null,
"data_source_context_id": null,
"read_only": false,
"visible": true,
"receipt_label": null,
"summary_entry": null,
"reference_image_id": null,
"entry_values": [
{
"id": 786229679,
"type": "entry_value",
"entry_id": 51501,
"text": "ARIZONA",
"position": 0
},
{
"id": 786229680,
"type": "entry_value",
"entry_id": 51501,
"text": "ALASKA",
"position": 1
},
{
"id": 786229681,
"type": "entry_value",
"entry_id": 51501,
"text": "ALABAMA",
"position": 2
},
{
"id": 786229682,
"type": "entry_value",
"entry_id": 51501,
"text": null,
"position": 3
}
],
"dependent_entry": null,
"export_label": null,
"pdf_visibility": 0
}
],
"conditions": [],
"operations": [],
"data_source_contexts": [],
"data_source_context_params": []
}
Retrieve a Form (minimal)
minimal: Provides a basic understanding of the form definition.
Back to Retrieve a Form
RESPONSE
{
"id": 346127,
"type": "form",
"name": "Basic Form",
"description": null,
"status": "published",
"version": 1,
"root_version_id": 346127,
"workflow_enabled": false,
"dispatch_enabled": false,
"web_form": false,
"email_options": 2,
"view_pdf_mobile": true,
"entries": [
{
"id": 51498,
"type": "entry",
"sheet_id": 10289,
"entry_type_id": 10,
"label": "NAME",
"entry_type": "text_field"
},
{
"id": 51499,
"type": "entry",
"sheet_id": 10289,
"entry_type_id": 10,
"label": "ADDRESS",
"entry_type": "text_field"
},
{
"id": 51500,
"type": "entry",
"sheet_id": 10289,
"entry_type_id": 10,
"label": "CITY",
"entry_type": "text_field"
},
{
"id": 51501,
"type": "entry",
"sheet_id": 10289,
"entry_type_id": 15,
"label": "STATE",
"entry_type": "drop_down"
}
]
}
Retrieve a Form (metadata)
metadata: Provides information about the form, such as which version is published.
Back to Retrieve a Form
RESPONSE
{
"id": 346127,
"type": "form",
"name": "Basic Form",
"description": null,
"status": "published",
"version": 1,
"root_version_id": 346127,
"dispatch_enabled": true,
"workflow_enabled": false,
"web_form": true,
"email_options": 2,
"view_pdf_mobile": true
}
Create a Form
# First, retrieve the form you want to create
FORM=$(curl -s -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X GET \
https://www.gocanvas.com/api/v3/forms/346127?format=nested)
# Modify the form as needed, example changing the name
MODIFIED_FORM=$(echo $FORM | jq '.name = "New Form Name"')
# Then, POST it to create the new form
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X POST \
-d "$MODIFIED_FORM" \
https://www.gocanvas.com/api/v3/forms
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
# First, retrieve the form you want to create
get_uri = URI("https://www.gocanvas.com/api/v3/forms/346127?format=nested")
get_req = Net::HTTP::Get.new(get_uri)
get_req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
get_req['Content-Type'] = "application/json"
form_definition = Net::HTTP.start(get_uri.hostname, get_uri.port, use_ssl: true) do |http|
res = http.request(get_req)
JSON.parse(res.body)
end
# Modify the form as needed, example changing the name
form_definition['name'] = 'New Form Name'
# Then, POST it to create the new form
post_uri = URI("https://www.gocanvas.com/api/v3/forms")
post_req = Net::HTTP::Post.new(post_uri)
post_req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
post_req['Content-Type'] = "application/json"
post_req.body = form_definition.to_json
res = Net::HTTP.start(post_uri.hostname, post_uri.port, use_ssl: true) do |http|
http.request(post_req)
end
form_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
// First, retrieve the form you want to create
const response = await fetch(`https://www.gocanvas.com/api/v3/forms/346127?format=nested`, {
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json"
}
});
const formDefinition = await response.json();
// Modify the form as needed, example changing the name
formDefinition.name = 'New Form Name';
// Then, POST it to create the new form
fetch(`https://www.gocanvas.com/api/v3/forms`, {
method: "POST",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json"
},
body: JSON.stringify(formDefinition)
})
.then(response => response.json())
.then(form => console.log(form));
Users can create a new Form by sending a JSON representation of the Form definition. The JSON structure is the same as the response from retrieving a nested format of a Form.
This method's response will return the metadata format of the Form, which includes the new Form's id and root_version_id for future use.
HTTP Request
POST https://www.gocanvas.com/api/v3/forms
Request Body Parameters
The request body should be the full JSON response from a GET request (using nested format). You can retrieve an existing Form and POST it to create a new Form.
| Parameter | Type | Description |
|---|---|---|
| name (required) | string | The name of the Form |
| status (required) | enum | The target status of the Form. Must be one of new, pending, or published |
| department_id* | integer | The Department ID for the Form |
| sections | array | Array of sections containing sheets and entries |
* department_id is required when Departments are enabled for the Company.
RESPONSE
{
"id": 346127,
"type": "form",
"name": "Basic Form",
"description": null,
"status": "published",
"version": 1,
"root_version_id": 346127,
"dispatch_enabled": true,
"workflow_enabled": false,
"web_form": true,
"email_options": 2,
"view_pdf_mobile": true
}
Update a Form
# First, retrieve the form you want to update
FORM=$(curl -s -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X GET \
https://www.gocanvas.com/api/v3/forms/346127?format=nested)
# Modify the form as needed, example changing the name
MODIFIED_FORM=$(echo $FORM | jq '.name = "Updated Form Name"')
# Then, POST it to update the form
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X POST \
-d "$MODIFIED_FORM" \
https://www.gocanvas.com/api/v3/forms/346127
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
form_id = 346127
# First, retrieve the form you want to update
get_uri = URI("https://www.gocanvas.com/api/v3/forms/#{form_id}?format=nested")
get_req = Net::HTTP::Get.new(get_uri)
get_req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
get_req['Content-Type'] = "application/json"
form_definition = Net::HTTP.start(get_uri.hostname, get_uri.port, use_ssl: true) do |http|
res = http.request(get_req)
JSON.parse(res.body)
end
# Modify the form as needed, example changing the name
form_definition['name'] = 'Updated Form Name'
# Then, POST it to update the form
post_uri = URI("https://www.gocanvas.com/api/v3/forms/#{form_id}")
post_req = Net::HTTP::Post.new(post_uri)
post_req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
post_req['Content-Type'] = "application/json"
post_req.body = form_definition.to_json
res = Net::HTTP.start(post_uri.hostname, post_uri.port, use_ssl: true) do |http|
http.request(post_req)
end
form_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
const formId = 346127;
// First, retrieve the form you want to update
const response = await fetch(`https://www.gocanvas.com/api/v3/forms/${formId}?format=nested`, {
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json"
}
});
const formDefinition = await response.json();
// Modify the form as needed, example changing the name
formDefinition.name = 'Updated Form Name';
// Then, POST it to update the form
fetch(`https://www.gocanvas.com/api/v3/forms/${formId}`, {
method: "POST",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json"
},
body: JSON.stringify(formDefinition)
})
.then(response => response.json())
.then(form => console.log(form));
Users can update an existing Form by posting the modified JSON from a GET request to the POST endpoint when a form_id is provided in the URL. This will create a new version of the Form with the provided updates. The JSON structure is the same as the response from retrieving a nested format of a Form.
This method's response will return the metadata format of the Form, which includes the new Form's id and root_version_id for future use.
HTTP Request
POST https://www.gocanvas.com/api/v3/forms/346127
Request Body Parameters
The request body should be the full JSON response from a GET request (using nested format) with your modifications applied. You can POST it to update the Form.
| Parameter | Type | Description |
|---|---|---|
| name (required) | string | The name of the Form |
| status (required)** | enum | The target status of the Form. Must be one of pending, published, or archived |
| department_id* | integer | The Department ID for the Form |
| sections | array | Array of sections containing sheets and entries |
* department_id is required when Departments are enabled for the Company.
** Allowed status transitions depend on the Form's current state. For example, archived is only valid for currently published Forms. Updating a published Form automatically creates a new version, and republishing archives the prior version.
RESPONSE
{
"id": 346127,
"type": "form",
"name": "Basic Form",
"description": null,
"status": "published",
"version": 1,
"root_version_id": 346127,
"dispatch_enabled": true,
"workflow_enabled": false,
"web_form": true,
"email_options": 2,
"view_pdf_mobile": true
}
Assigned Users for Form
User can view a list of all the Users the specified Form has been assigned to.
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X GET \
https://www.gocanvas.com/api/v3/forms/4639578/assigned_users
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
uri = URI("https://www.gocanvas.com/api/v3/forms/4639578/assigned_users")
req = Net::HTTP::Get.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
users_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
fetch("https://www.gocanvas.com/api/v3/forms/4639578/assigned_users", {
method: "GET",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
}
})
.then(response => response.json())
.then(users => console.log(users));
HTTP Request
GET https://www.gocanvas.com/api/v3/forms/4639578/assigned_users
RESPONSE
[
{
"id": 5486,
"type": "assigned_user",
"first_name": "Jane",
"last_name": "Doe",
"email": "jane.doe@gocanvas.com"
},
{
"id": 5490,
"type": "assigned_user",
"first_name": "Smith",
"last_name": "Kane",
"email": "smith.kane@gocanvas.com"
}
]
Assign User to Form
BODY='{
user_id: 114,
department_id: 1234
}'
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X POST \
-d $BODY \
https://www.gocanvas.com/api/v3/forms/4639578/assigned_users
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
request_body = {
user_id: 114,
department_id: 1234
}
uri = URI("https://www.gocanvas.com/api/v3/forms/4639578/assigned_users")
json_request_body = request_body.to_json
req = Net::HTTP::Post.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
req.body = json_request_body
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
user_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
const data = {
user_id: 114,
department_id: 1234
};
fetch("https://www.gocanvas.com/api/v3/forms/4639578/assigned_users", {
method: "POST",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(user => console.log(user));
Users can assign another User to a Form.
HTTP Request
POST https://www.gocanvas.com/api/v3/forms/4639578/assigned_users
| Parameter | Type | Description |
|---|---|---|
| user_id | integer | The id of the User to assign |
| department_id* | integer (optional) | The Department of the Form to assign to |
* department_id must be specified when Departments are enabled for the Company.
RESPONSE
{
"type": "assigned_user",
"form_id": 4639578,
"user_id": 114,
"department_id": 1234
}
Unassign User from Form
BODY='{
user_id: 114,
department_id: 1234
}'
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X DELETE \
-d $BODY \
https://www.gocanvas.com/api/v3/forms/4639578/assigned_users/3310
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
request_body = {
user_id: 114,
department_id: 1234
}
uri = URI("https://www.gocanvas.com/api/v3/forms/4639578/assigned_users/3310")
json_request_body = request_body.to_json
req = Net::HTTP::Delete.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
req.body = json_request_body
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
user_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
const data = {
user_id: 114,
department_id: 1234
};
fetch("https://www.gocanvas.com/api/v3/forms/4639578/assigned_users/3310", {
method: "DELETE",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(user => console.log(user));
RESPONSE
{
"message": "User 5652 has been unassigned from form 16043 successfully"
}
Users can unassign another User from a Form.
HTTP Request
DELELTE https://www.gocanvas.com/api/v3/forms/4639578/assigned_users/114
| Parameter | Type | Description |
|---|---|---|
| user_id | integer | The id of the User to assign |
| department_id* | integer (optional) | The Department of the Form to assign to |
* department_id must be specified when Departments are enabled for the Company.
Shared Departments for Form
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X GET \
https://www.gocanvas.com/api/v3/forms/4639578/shared_departments
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
uri = URI("https://www.gocanvas.com/api/v3/forms/4639578/shared_departments")
req = Net::HTTP::Get.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
departments_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
fetch("https://www.gocanvas.com/api/v3/forms/4639578/shared_departments", {
method: "GET",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
}
})
.then(response => response.json())
.then(departments => console.log(departments));
Users can view a list of all the Departments the specified Form has been shared with.
HTTP Request
GET https://www.gocanvas.com/api/v3/forms/4639578/shared_departments
RESPONSE
[
{
"id": 1234,
"type": "department",
"name": "First Department",
"description": "First Department"
},
{
"id": 1235,
"type": "department",
"name": "Second Department",
"description": "Second Department"
},
{
"id": 1236,
"type": "department",
"name": "Third Department",
"description": "Third Department"
}
]
Share Form with Departments
BODY='{
"department_ids": [1234, 1235, 1236]
}'
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X POST \
-d $BODY \
https://www.gocanvas.com/api/v3/forms/4639578/shared_departments
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
request_body = {
"department_ids": [1234, 1235, 1236]
}
uri = URI("https://www.gocanvas.com/api/v3/forms/4639578/shared_departments")
json_request_body = request_body.to_json
req = Net::HTTP::Post.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
req.body = json_request_body
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
departments_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
const data = {
"department_ids": [1234, 1235, 1236]
};
fetch("https://www.gocanvas.com/api/v3/forms/4639578/shared_departments", {
method: "POST",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(departments => console.log(departments));
Users can share a Form with the specified Departments.
HTTP Request
POST https://www.gocanvas.com/api/v3/forms/4639578/shared_departments
| Parameter | Type | Description |
|---|---|---|
| body | JSON | The JSON Submission body |
| body.department_ids | array | An Array of Department Ids to share the Form with (Max of 50) |
RESPONSE
[
{
"id": 1234,
"type": "department",
"name": "First Department",
"description": "First Department"
},
{
"id": 1235,
"type": "department",
"name": "Second Department",
"description": "Second Department"
},
{
"id": 1236,
"type": "department",
"name": "Third Department",
"description": "Third Department"
}
]
Delete a Form
A Form can be deleted with a DELETE request.
By default, the DELETE request will soft-delete the Form, which preserves the Form data but hides it from all views. To permanently delete a Form, use the hard_delete=true parameter, e.g. DELETE https://www.gocanvas.com/api/v3/forms/346127?hard_delete=true.
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X DELETE \
https://www.gocanvas.com/api/v3/forms/346127
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
uri = URI("https://www.gocanvas.com/api/v3/forms/346127")
req = Net::HTTP::Delete.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
form_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
fetch("https://www.gocanvas.com/api/v3/forms/346127", {
method: "DELETE",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
}
})
.then(response => response.json())
.then(form => console.log(form));
RESPONSE
{
"message": "Form 346127 has been soft deleted successfully"
}
HTTP Request
DELETE https://www.gocanvas.com/api/v3/forms/346127
Request Parameters
| Parameter | Type | Description |
|---|---|---|
| hard_delete* | boolean | Will hard delete the Form record when set to true |
* This is an optional URL parameter. If not provided, the Form will be soft deleted.
In addition to removing the Form record itself, a hard delete will also permanently delete the following associated data:
- User and group assignments
- Department shares
- Web form GUIDs
- Workflows
- Assignment settings
- Storage and payment integrations
- Tag assignments
- Custom attachments and custom PDFs
- Submission statuses
- Custom email content
- Form triggers
Group
Groups allow for the organization of users and can be assigned Forms. Groups are a useful way to organize teams, job functions, or common workflows and manage Form assignments in one place rather than individually assigning Forms to each User. Learn more about GoCanvas Groups.
The Group object
EXAMPLE
{
"id": 1873,
"type": "group",
"department_id": 21474,
"created_at": "2025-06-03T17:39:39Z",
"name": "Inspectors",
"description": "Common tasks for inspectors",
"members": [
{
"id": 20079,
"type": "user",
"enabled": true,
"login": "charles.neverdon@example.com"
}
],
"assigned_forms": [
{
"id": 80531,
"type": "form",
"name": "Site Evaluation",
"description": null,
"status": "published",
"version": 6,
"root_version_id": 80526
},
{
"id": 81531,
"type": "form",
"name": "Hazard Assessment",
"description": null,
"status": "published",
"version": 24,
"root_version_id": 74915
},
{
"id": 43671,
"type": "form",
"name": "Timecard",
"description": null,
"status": "published",
"version": 2,
"root_version_id": 34544
}
]
}
Groups may have a helpful name and description to identify the Group's purpose. Groups exist within a specific Department. Group members are Users and assigned_forms are Forms that are assigned to the Group.
List all Groups
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X GET \
https://www.gocanvas.com/api/v3/groups
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
uri = URI("https://www.gocanvas.com/api/v3/groups")
req = Net::HTTP::Get.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
groups_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
fetch("https://www.gocanvas.com/api/v3/groups", {
method: "GET",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
}
})
.then(response => response.json())
.then(groups => console.log(groups));
Users can view and filter a list of Groups.
RESPONSE
[
{
"id": 1873,
"type": "group",
"department_id": 21474,
"created_at": "2025-06-04T00:12:02Z",
"name": "Inspectors",
"description": "Common tasks for inspectors"
},
{
"id": 1891,
"type": "group",
"department_id": 21474,
"created_at": "2025-06-04T00:52:26Z",
"name": "General Contractors",
"description": "GCs, subcontractors, and other workers"
}
]
HTTP Request
GET https://www.gocanvas.com/api/v3/groups
Query Parameters
| Parameter | Type | Description | Default |
|---|---|---|---|
| page | integer (optional) | The page requested, see Pagination | 1 |
| department_id* | integer (optional) | The identifier for the Department associated with the Group | (default department*) |
* If no department_id is provided, the User's default department will be used.
Retrieve a Group
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X GET \
https://www.gocanvas.com/api/v3/groups/1873
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
uri = URI("https://www.gocanvas.com/api/v3/groups/1873")
req = Net::HTTP::Get.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
group_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
fetch("https://www.gocanvas.com/api/v3/groups/1873", {
method: "GET",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
}
})
.then(response => response.json())
.then(group => console.log(group));
Users can retrieve a Group by its ID.
RESPONSE
{
"id": 1873,
"type": "group",
"department_id": 21474,
"created_at": "2025-06-03T17:39:39Z",
"name": "Inspectors",
"description": "Common tasks for inspectors",
"members": [
{
"id": 20079,
"type": "user",
"enabled": true,
"login": "charles.neverdon@example.com"
}
],
"assigned_forms": [
{
"id": 80531,
"type": "form",
"name": "Site Evaluation",
"description": null,
"status": "published",
"version": 6,
"root_version_id": 80526
},
{
"id": 81531,
"type": "form",
"name": "Hazard Assessment",
"description": null,
"status": "published",
"version": 24,
"root_version_id": 74915
},
{
"id": 43671,
"type": "form",
"name": "Timecard",
"description": null,
"status": "published",
"version": 2,
"root_version_id": 34544
}
]
}
HTTP Request
GET https://www.gocanvas.com/api/v3/groups/1873
Response Parameters
| Parameter | Type | Description |
|---|---|---|
| id | integer | The identifier for this Group |
| department_id | integer | The Department the Group is associated with |
| name | string | A short string value for name of the Group |
| description | string | A longer string value describing the Group |
| created_at | datetime | The time the Group was created |
| members | array | An array of Users that are members of the Group |
| members[].id | integer | The unique User id |
| members[].enabled | boolean | Whether a user is allowed to login |
| members[].login | string | The email address of the User |
| assigned_forms | array | An array of Forms that are assigned to the Group |
| assigned_forms[].id | integer | The identifier for this exact version of the Form |
| assigned_forms[].name | string | The name of the Form |
| assigned_forms[].status * | enum | The status of the Form. Can be new, pending, published, archived, or testing |
| assigned_forms[].version | integer | The version number of the Form. When a new version is saved and published, this version counter increments |
| assigned_forms[].root_version_id | integer | The original Form identifier for all versions of the Form |
Create a Group
BODY='{
name: "General Contractors",
description: "GCs, subcontractors, and other workers"
}'
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X POST \
-d $BODY \
https://www.gocanvas.com/api/v3/groups
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
request_body = {
name: "General Contractors",
description: "GCs, subcontractors, and other workers"
}
uri = URI("https://www.gocanvas.com/api/v3/groups")
json_request_body = request_body.to_json
req = Net::HTTP::Post.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
req.body = json_request_body
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
group_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
const data = {
name: "General Contractors",
description: "GCs, subcontractors, and other workers"
};
fetch("https://www.gocanvas.com/api/v3/groups", {
method: "POST",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(group => console.log(group));
RESPONSE
{
"id": 1891,
"type": "group",
"department_id": 21474,
"created_at": "2025-06-04T00:52:26Z",
"name": "General Contractors",
"description": "GCs, subcontractors, and other workers",
"members": [],
"assigned_forms": []
}
To create a new Group, the POST body can be sent as JSON.
Form and User assignments can be added with Update a Group or with the Assign Form to Group and Assign User to Group endpoints.
HTTP Request
POST https://www.gocanvas.com/api/v3/groups
Request Body Parameters
| Parameter | Type | Description |
|---|---|---|
| name | string | A short string value for name of the Group |
| description | string | A longer string value to describe the Group |
| department_id* | integer | The Department the Group is associated with |
* if no department_id is provided, the Group will be associated with the User's default department
Update a Group
BODY='{
name: "Inspectors",
description: "Common tasks for inspectors",
members: [
{
"id": 20079,
"login": "charles.neverdon@example.com"
}
],
assigned_forms: [
{
"id": 80531,
"root_version_id": 80526
},
{
"root_version_id": 74915
},
{
"id": 43671
}
],
send_notification: true
}'
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X PATCH \
-d $BODY \
https://www.gocanvas.com/api/v3/groups
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
request_body = {
name: "Inspectors",
description: "Common tasks for inspectors",
members: [
{
"id": 20079,
"login": "charles.neverdon@example.com"
}
],
assigned_forms: [
{
"id": 80531,
"root_version_id": 80526
},
{
"root_version_id": 74915
},
{
"id": 43671
}
],
send_notification: true
}
uri = URI("https://www.gocanvas.com/api/v3/groups")
json_request_body = request_body.to_json
req = Net::HTTP::Patch.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
req.body = json_request_body
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
group_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
const data = {
name: "Inspectors",
description: "Common tasks for inspectors",
members: [
{
"id": 20079,
"login": "charles.neverdon@example.com"
}
],
assigned_forms: [
{
"id": 80531,
"root_version_id": 80526
},
{
"root_version_id": 74915
},
{
"id": 43671
}
],
send_notification: true
};
fetch("https://www.gocanvas.com/api/v3/groups", {
method: "PATCH",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(group => console.log(group));
RESPONSE
{
"id": 1873,
"type": "group",
"department_id": 21474,
"created_at": "2025-06-03T17:39:39Z",
"name": "Inspectors",
"description": "Common tasks for inspectors",
"members": [
{
"id": 20079,
"type": "user",
"enabled": true,
"login": "charles.neverdon@example.com"
}
],
"assigned_forms": [
{
"id": 80531,
"type": "form",
"name": "Site Evaluation",
"description": null,
"status": "published",
"version": 6,
"root_version_id": 80526
},
{
"id": 81531,
"type": "form",
"name": "Hazard Assessment",
"description": null,
"status": "published",
"version": 24,
"root_version_id": 74915
},
{
"id": 43671,
"type": "form",
"name": "Timecard",
"description": null,
"status": "published",
"version": 2,
"root_version_id": 34544
}
]
}
A group that has already been created can be updated by sending a PATCH request to the group endpoint with the group ID. Groups can not be moved to a different department as Users and Forms are assigned to a group within a specific department.
Form and User assignments updated with this endpoint will overwrite any existing assignments. To add Forms or Users to a Group without overwriting existing assignments, use the Assign Form to Group and Assign User to Group endpoints.
HTTP Request
PATCH https://www.gocanvas.com/api/v3/groups/1873
Request Body Parameters
| Parameter | Type | Description | Default |
|---|---|---|---|
| name | string (optional) | A short string value for name of the Group | |
| description | string (optional) | A longer string value to describe the Group | |
| members | array (optional) | An array of Users to overwrite the current members with Omit members to leave unchangedPass an empty array ( []) to remove all members. |
|
| members[].id* | integer (optional) | The unique User id | |
| members[].login* | string (optional) | The email address of the User | |
| assigned_forms | array (optional) | An array of Forms to overwrite the current assigned forms with Omit assigned_forms to leave unchangedPass an empty array ( []) to remove all assigned forms. |
|
| assigned_forms[].id** | integer (optional) | The identifier for the Form to assign to the Group | |
| assigned_forms[].root_version_id** | integer (optional) | The root_version_id for the Form to assign to the Group.This will assign the latest published version of the Form. |
|
| send_notification | boolean (optional) | When true, a notification will be sent to affected users when their group membership or new form assignments are created.Notification settings configured by users or at the account level are respected, refer to Change GoCanvas Notification Settings |
false |
* One of id or login is required for each members[]
** One of id or root_version_id is required for each assigned_forms[]
Delete a Group
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X DELETE \
https://www.gocanvas.com/api/v3/groups/1874
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
uri = URI("https://www.gocanvas.com/api/v3/groups/1874")
req = Net::HTTP::Delete.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
group_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
fetch("https://www.gocanvas.com/api/v3/groups/1874", {
method: "DELETE",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
}
})
.then(response => response.json())
.then(group => console.log(group));
RESPONSE
{
"message": "Group 1874 has been deleted successfully"
}
A Group can be deleted with a DELETE request. Group deletions are permanent.
HTTP Request
DELETE https://www.gocanvas.com/api/v3/groups/1874
Assign Form to Group
BODY='{
"id": 80531,
"root_version_id": 80526,
"send_notification": true
}'
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X POST \
-d $BODY \
https://www.gocanvas.com/api/v3/groups/1874/forms
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
request_body = {
"id": 80531,
"root_version_id": 80526,
"send_notification": true
}
uri = URI("https://www.gocanvas.com/api/v3/groups/1874/forms")
json_request_body = request_body.to_json
req = Net::HTTP::Post.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
req.body = json_request_body
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
user_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
const data = {
"id": 80531,
"root_version_id": 80526,
"send_notification": true
};
fetch("https://www.gocanvas.com/api/v3/groups/1874/forms", {
method: "POST",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(user => console.log(user));
RESPONSE
{
"message": "Form assigned to group successfully",
}
Forms can be assigned to a Group individually.
HTTP Request
POST https://www.gocanvas.com/api/v3/groups/1874/forms
Request Body Parameters
| Parameter | Type | Description | Default |
|---|---|---|---|
| id* | integer (optional) | The identifier for the Form to assign to the Group | |
| root_version_id* | integer (optional) | The root_version_id for the Form to assign to the Group.This will assign the latest published version of the Form. |
|
| send_notification | boolean (optional) | When true, a notification will be sent to group members about the newly assigned form.Notification settings configured by users or at the account level are respected, refer to Change GoCanvas Notification Settings |
false |
* One of id or root_version_id is required for each assigned_forms[]
Remove Form from Group
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X DELETE \
https://www.gocanvas.com/api/v3/groups/1874/forms/80531
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
uri = URI("https://www.gocanvas.com/api/v3/groups/1874/forms/80531")
req = Net::HTTP::Delete.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
users_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
fetch("https://www.gocanvas.com/api/v3/groups/1874/forms/80531", {
method: "DELETE",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
}
})
.then(response => response.json())
.then(users => console.log(users));
RESPONSE
{
"message": "Form removed from group successfully",
}
Forms can be removed from a Group individually.
HTTP Request
DELETE https://www.gocanvas.com/api/v3/groups/1874/forms/80531
Assign User to Group
BODY='{
"id": 20079,
"login": "charles.neverdon@example.com",
"send_notification": true
}'
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X POST \
-d $BODY \
https://www.gocanvas.com/api/v3/groups/1874/users
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
request_body = {
"id": 20079,
"login": "charles.neverdon@example.com",
"send_notification": true
}
uri = URI("https://www.gocanvas.com/api/v3/groups/1874/users")
json_request_body = request_body.to_json
req = Net::HTTP::Post.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
req.body = json_request_body
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
user_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
const data = {
"id": 20079,
"login": "charles.neverdon@example.com",
"send_notification": true
};
fetch("https://www.gocanvas.com/api/v3/groups/1874/users", {
method: "POST",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(user => console.log(user));
RESPONSE
{
"message": "User assigned to group successfully",
}
Users can be assigned to a Group individually.
HTTP Request
POST https://www.gocanvas.com/api/v3/groups/1874/users
Request Body Parameters
| Parameter | Type | Description | Default |
|---|---|---|---|
| id* | integer (optional) | The identifier for the User to assign to the Group | |
| login* | string (optional) | The email address of the User to assign to the Group | |
| send_notification | boolean (optional) | When true, a notification will be sent to the user about being added to the group.Notification settings configured by users or at the account level are respected, refer to Change GoCanvas Notification Settings |
false |
* Either User's id or login must be provided.
Remove User from Group
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X DELETE \
https://www.gocanvas.com/api/v3/groups/1874/users/20079
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
uri = URI("https://www.gocanvas.com/api/v3/groups/1874/users/20079")
req = Net::HTTP::Delete.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
users_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
fetch("https://www.gocanvas.com/api/v3/groups/1874/users/20079", {
method: "DELETE",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
}
})
.then(response => response.json())
.then(users => console.log(users));
RESPONSE
{
"message": "User removed from group successfully",
}
Users can be removed from a Group individually.
HTTP Request
DELETE https://www.gocanvas.com/api/v3/groups/1874/users/20079
Me
Current User Profile
The /me endpoint is useful for OAuth-authenticated applications to verify the current token's user information and retrieve basic profile data. It can also be helpful to retrieve company_id and default_department_id for subsequent API calls.
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X GET \
https://www.gocanvas.com/api/v3/me
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
uri = URI("https://www.gocanvas.com/api/v3/me")
req = Net::HTTP::Get.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
profile_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
fetch("https://www.gocanvas.com/api/v3/me", {
method: "GET",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
}
})
.then(response => response.json())
.then(profile => console.log(profile));
HTTP Request
GET https://www.gocanvas.com/api/v3/me
RESPONSE
{
"id": 20122,
"type": "user",
"first_name": "John",
"last_name": "Doe",
"login": "john.doe@example.com",
"phone": "555-123-4567",
"address": "123 Main St",
"address2": "Suite 200",
"city": "Denver",
"state": "CO",
"zip": "80202",
"enabled": true,
"created_at": "2023-06-15T10:30:45.000-04:00",
"company_id": 1999,
"company_name": "Example Company",
"default_department_id": 5678,
"default_department_name": "Operations"
}
Response Parameters
| Parameter | Type | Description |
|---|---|---|
| id | integer | The identifier for this User |
| type | string | The type of the object |
| first_name | string | The first name of the User |
| last_name | string | The last name of the User |
| login | string | The login/email address of the User |
| phone | string | The phone number of the User |
| address | string | The street address of the User |
| address2 | string | The second line of the User's street address |
| city | string | The city of the User |
| state | string | The state or province of the User |
| zip | string | The postal code of the User |
| enabled | boolean | Whether the User is allowed to login |
| created_at | datetime | The date and time when the User was created |
| company_id | integer | The identifier for the User's Company |
| company_name | string | The name of the User's Company |
| default_department_id | integer | The identifier for the User's default Department |
| default_department_name | string | The name of the User's default Department |
Project
A Project is created and used to track the progress of a specific task or job. A Project is associated with a Department, and optionally a Customer and Site. A Project can have a status of active, inactive, or draft.
The Project object
EXAMPLE
{
"id": 11,
"name": "My new Project",
"company_id": 135196,
"department_id": 21974,
"customer_id": 25,
"site_id": 6,
"start_date": "2024-10-16 11:30:00 UTC",
"end_date": null,
"status": "active",
"notes": "House renovation",
"code": "NEW00001"
}
A Project requires a name to be created. The name is the only required field. When creating a Project, the user needs to be authorized to access the Department to which the Project is associated.
List all Projects
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X GET \
https://www.gocanvas.com/api/v3/projects
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
uri = URI("https://www.gocanvas.com/api/v3/projects")
req = Net::HTTP::Get.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
projects_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
fetch("https://www.gocanvas.com/api/v3/projects", {
method: "GET",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
}
})
.then(response => response.json())
.then(projects => console.log(projects));
Users can view a list of all the Projects for a specific department to which they have access.
RESPONSE
[
{
"id": 11,
"name": "My new Project",
"company_id": 135196,
"department_id": 21974,
"customer_id": 25,
"site_id": 6,
"start_date": "2023-10-01 00:00:00 UTC",
"end_date": null,
"status": "active",
"notes": "House renovation",
"code": "NEW00001"
},
{
"id": 12,
"name": "Swimming Pool Project",
"company_id": 135196,
"department_id": 21974,
"customer_id": null,
"site_id": null,
"start_date": "2023-10-01 00:00:00 UTC",
"end_date": "2023-12-31 00:00:00 UTC",
"status": "active",
"notes": "Below ground swimming pool",
"code": "PRO033"
},
{
"id": 13,
"name": "Remodel Project",
"company_id": 135196,
"department_id": 21974,
"customer_id": null,
"site_id": null,
"start_date": "2023-10-01 00:00:00 UTC",
"end_date": "2023-12-31 00:00:00 UTC",
"status": "active",
"notes": "House remodel",
"code": "NEW0443"
}
]
HTTP Request
GET https://www.gocanvas.com/api/v3/projects
Query Parameters
| Parameter | Type | Description | Default |
|---|---|---|---|
| page | integer (optional) | The page requested, see Pagination | 1 |
Retrieve a Project
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X GET \
https://www.gocanvas.com/api/v3/projects/11
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
uri = URI("https://www.gocanvas.com/api/v3/projects/11")
req = Net::HTTP::Get.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
project_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
fetch("https://www.gocanvas.com/api/v3/projects/11", {
method: "GET",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
}
})
.then(response => response.json())
.then(project => console.log(project));
Users can retrieve a Project by its ID.
HTTP Request
GET https://www.gocanvas.com/api/v3/projects/11
RESPONSE
{
"id": 11,
"name": "My new Project",
"company_id": 135196,
"department_id": 21974,
"customer_id": 25,
"site_id": 6,
"start_date": "2024-10-16 11:30:00 UTC",
"end_date": null,
"status": "active",
"notes": "House renovation",
"code": "NEW00001"
}
Response Parameters
| Parameter | Type | Description |
|---|---|---|
| id | integer | The identifier for this exact Project |
| name | string | A short string value for name of the Project |
| company_id | integer | The Company the Project is associated with |
| department_id | integer | The Department the Project is associated with |
| customer_id | integer | The Customer the Project is associated with |
| site_id | integer | The Site the Project is associated with |
| start_date | string | A DateTime value of when the Project starts |
| end_date | string | A Datetime value of when the Project concludes |
| status | enum | The status of the Project. Can be active, inactive, or draft |
| notes | string | A longer string value to describe the Project |
| code | string | An alpha numeric code to uniquely identify the Project |
Create a Project
To create a new Project, the POST body can be sent as JSON. The only required field is the name of the Project.
BODY='{
"name": "My newly created Project",
"status": "draft",
"customer_id": 25,
"site_id": 6,
"start_date": "2024-10-01T11:30:00"
}'
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X POST \
-d $BODY \
https://www.gocanvas.com/api/v3/projects
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
request_body = {
"name": "My newly created Project",
"status": "draft",
"customer_id": 25,
"site_id": 6,
"start_date": "2024-10-01T11:30:00"
}
uri = URI("https://www.gocanvas.com/api/v3/projects")
json_request_body = request_body.to_json
req = Net::HTTP::Post.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
req.body = json_request_body
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
project_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
const data = {
"name": "My newly created Project",
"status": "draft",
"customer_id": 25,
"site_id": 6,
"start_date": "2024-10-01T11:30:00"
};
fetch("https://www.gocanvas.com/api/v3/projects", {
method: "POST",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(project => console.log(project));
RESPONSE
{
"id": 21,
"name": "My newly created Project",
"company_id": 135196,
"department_id": 21974,
"customer_id": 25,
"site_id": 6,
"start_date": "2024-10-01 11:30:00 UTC",
"end_date": null,
"status": "draft",
"code": "GAR00001"
}
HTTP Request
POST https://www.gocanvas.com/api/v3/projects
Request Body Parameters
| Parameter | Type | Description |
|---|---|---|
| name* | string | A short string value for name of the Project |
| department_id** | integer | The Department the Project is associated with |
| customer_id*** | integer | The ID of a Customer to associate to the Project |
| site_id* | integer | The ID of a site related to a Customer |
| start_date**** | integer | A DateTime value of when the Project starts |
| end_date**** | integer | A Datetime value of when the Project concludes |
| status | enum | The status of the Project. Can be active, inactive, or draft |
| notes | string | A longer string value to describe the Project |
| code | string | An alpha numeric code to uniquely identify the Project |
* required field
** if no department_id is provided, the Project will be associated with the User's default department
*** make sure that the customer_id and site_id provided are associated with eachother
**** start_date and end_date must be in the ISO-8601 format, e.g. 2024-01-30 or 2024-01-30T23:59:59 or 2024-01-30T23:59:59-04:00
Update a Project
To update an existing Project, the PATCH request body can be sent as JSON.
BODY='{
"status": "active",
"customer_id": null,
"site_id": null,
"start_date": "2024-10-16T11:30:00",
"notes": "Garage renovation"
}'
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X PATCH \
-d $BODY \
https://www.gocanvas.com/api/v3/projects
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
request_body = {
"status": "active",
"customer_id": null,
"site_id": null,
"start_date": "2024-10-16T11:30:00",
"notes": "Garage renovation"
}
uri = URI("https://www.gocanvas.com/api/v3/projects")
json_request_body = request_body.to_json
req = Net::HTTP::Patch.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
req.body = json_request_body
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
project_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
const data = {
"status": "active",
"customer_id": null,
"site_id": null,
"start_date": "2024-10-16T11:30:00",
"notes": "Garage renovation"
};
fetch("https://www.gocanvas.com/api/v3/projects", {
method: "PATCH",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(project => console.log(project));
RESPONSE
{
"message": "Project updated successfully"
}
HTTP Request
PATCH https://www.gocanvas.com/api/v3/projects/21
Request Body Parameters
| Parameter | Type | Description |
|---|---|---|
| name* | string | A short string value for name of the Project |
| department_id** | integer | The Department the Project is associated with |
| customer_id*** | integer | The ID of a Customer to associate to the Project |
| site_id* | integer | The ID of a site related to a Customer |
| start_date**** | integer | A DateTime value of when the Project starts |
| end_date**** | integer | A Datetime value of when the Project concludes |
| status | enum | The status of the Project. Can be active, inactive, or draft |
| notes | string | A longer string value to describe the Project |
| code | string | An alpha numeric code to uniquely identify the Project |
* required field
** if no department_id is provided, the Project will be associated with the User's default department
*** make sure that the customer_id and site_id provided are associated with eachother
**** start_date and end_date must be in the ISO-8601 format, e.g. 2024-01-30 or 2024-01-30T23:59:59 or 2024-01-30T23:59:59-04:00
Delete a Project
A Project can be deleted with a DELETE request.
By default, the DELETE request will soft-delete the project, which preserves the Project data but hides it from the web views. To permanently delete a Project, use the hard_delete=true parameter, e.g. DELETE https://www.gocanvas.com/api/v3/projects/21?hard_delete=true.
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X DELETE \
https://www.gocanvas.com/api/v3/projects/21
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
uri = URI("https://www.gocanvas.com/api/v3/projects/21")
req = Net::HTTP::Delete.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
project_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
fetch("https://www.gocanvas.com/api/v3/projects/21", {
method: "DELETE",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
}
})
.then(response => response.json())
.then(project => console.log(project));
RESPONSE
{
"message": "Project 21 has been soft deleted successfully"
}
HTTP Request
DELETE https://www.gocanvas.com/api/v3/projects/21
Request Parameters
| Parameter | Type | Description |
|---|---|---|
| hard_delete* | boolean | Will hard delete the Project record when set to true |
* This is an optional URL parameter. If not provided, the Project will be soft deleted.
Reference Data
Reference Data is data that is used to populate dropdowns, checkboxes, and other controls in a Form. The two main purposes of Reference Data are to:
- Provide a list of options for a user to select from when filling out a Form.
- Auto-populate fields based on user input to other fields by looking up other values in the Reference Data rows.
The Reference Data object
EXAMPLE
{
"id": 10761,
"type": "reference_data",
"name": "US Zip Codes",
"description": null,
"use_user_groups": null,
"version": 1,
"department_id": 21474,
"headers": ["City", "ZIP Code", "County", "State"],
"rows": [
[ "Jones", "36749", "Autauga", "Alabama" ],
[ "Daphne", "36526", "Baldwin", "Alabama" ],
[ "Spanish Forst", "36527", "Baldwin", "Alabama" ],
[ "Brent", "35034", "Bibb", "Alabama" ],
[ "Birmingham", "35201", "Bibb", "Alabama" ],
[ "Birmingham", "35202", "Bibb", "Alabama" ],
[ "Dinwiddie", "23841", "Dinwiddie", "Virginia" ]
]
}
Reference Data is structured similar to a spreadsheet, with a set of headers and rows. The order of the headers aligns to the order of each row of data.
| Property | Type | Description |
|---|---|---|
| id | integer | The unique reference data id |
| name | string | A short string value for name of a reference data |
| description | string | A longer string value describing a reference data |
| use_user_groups | boolean | Whether the reference data is shared with all users or only users in the same group |
| version | integer | The version of the reference data |
| department_id | integer | The unique department id |
| headers | array | An array of strings that represent the headers of the reference data |
| rows | array | An array of arrays that represent the rows of the reference data |
List all Reference Data
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X GET \
https://www.gocanvas.com/api/v3/reference_data
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
uri = URI("https://www.gocanvas.com/api/v3/reference_data")
req = Net::HTTP::Get.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
reference_data_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
fetch("https://www.gocanvas.com/api/v3/reference_data", {
method: "GET",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
},
})
.then(response => response.json())
.then(referenceData => console.log(referenceData));
Users can view a list of all the reference data associated with their Company.
HTTP Request
GET https://www.gocanvas.com/api/v3/reference_data
Request Parameters
| Property | Type | Description |
|---|---|---|
| department_id* | integer (optional) | The unique Department id |
* If Departments are enabled for the Company, a URL parameter can be provided to list the Reference Data associated with that specific Department. If no department_id is provided, the Reference Data associated with the User's default department.
RESPONSE
[
{
"id": 10760,
"type": "reference_data",
"name": "US State Abbreviations",
"description": null,
"column_count": 2,
"use_user_groups": null,
"version": 27,
"department_id": 21474
}
{
"id": 10761,
"type": "reference_data",
"name": "US Zip Codes",
"description": null,
"column_count": 4,
"use_user_groups": null,
"version": 1,
"department_id": 21474
}
]
Retrieve a Reference Data
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X GET \
https://www.gocanvas.com/api/v3/reference_data/10761?format=rows_with_index
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
uri = URI("https://www.gocanvas.com/api/v3/reference_data/10761?format=rows_with_index")
req = Net::HTTP::Get.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
reference_data_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
fetch("https://www.gocanvas.com/api/v3/reference_data/10761?format=rows_with_index", {
method: "GET",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
},
})
.then(response => response.json())
.then(referenceData => console.log(referenceData));
Users can view a specific Reference Data by its id.
HTTP Request
GET https://www.gocanvas.com/api/v3/reference_data/10761
RESPONSE
{
"id": 10761,
"type": "reference_data",
"name": "US Zip Codes",
"description": null,
"use_user_groups": null,
"version": 1,
"department_id": 21474,
"headers": ["gc_row_index", "City", "ZIP Code", "County", "State"],
"rows": [
[ "0", "Jones", "36749", "Autauga", "Alabama" ],
[ "1", "Daphne", "36526", "Baldwin", "Alabama" ],
[ "2", "Spanish Forst", "36527", "Baldwin", "Alabama" ],
[ "3", "Brent", "35034", "Bibb", "Alabama" ],
[ "4", "Birmingham", "35201", "Bibb", "Alabama" ],
[ "5", "Birmingham", "35202", "Bibb", "Alabama" ],
[ "6", "Dinwiddie", "23841", "Dinwiddie", "Virginia" ]
]
}
Request Parameters
| Parameter | Type | Description |
|---|---|---|
| format * | enum | The format of the returned reference data in JSON. Can be rows or rows_with_index |
* If format is not specified, the default format is rows. If format is specified as rows_with_index, the returned reference data will include an additional header of gc_row_index and each row will include an additional item of its numerical index.
Create Reference Data
BODY='{
"name": "US Zip Codes",
"headers": ["City", "ZIP Code", "County", "State"],
"rows": [
["Jones", "36749", "Autauga", "Alabama"],
["Daphne", "36526", "Baldwin", "Alabama"],
["Spanish Forst", "36527", "Baldwin", "Alabama"],
["Brent", "35034", "Bibb", "Alabama"],
["Birmingham", "35201", "Bibb", "Alabama"],
["Birmingham", "35202", "Bibb", "Alabama"],
["Dinwiddie", "23841", "Dinwiddie", "Virginia"]
]
}'
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X POST \
-d $BODY \
https://www.gocanvas.com/api/v3/reference_data
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
request_body = {
"name": "US Zip Codes",
"headers": ["City", "ZIP Code", "County", "State"],
"rows": [
["Jones", "36749", "Autauga", "Alabama"],
["Daphne", "36526", "Baldwin", "Alabama"],
["Spanish Forst", "36527", "Baldwin", "Alabama"],
["Brent", "35034", "Bibb", "Alabama"],
["Birmingham", "35201", "Bibb", "Alabama"],
["Birmingham", "35202", "Bibb", "Alabama"],
["Dinwiddie", "23841", "Dinwiddie", "Virginia"]
]
}
uri = URI("https://www.gocanvas.com/api/v3/reference_data")
json_request_body = request_body.to_json
req = Net::HTTP::Post.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
req.body = json_request_body
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
reference_data_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
const data = {
"name": "US Zip Codes",
"headers": ["City", "ZIP Code", "County", "State"],
"rows": [
["Jones", "36749", "Autauga", "Alabama"],
["Daphne", "36526", "Baldwin", "Alabama"],
["Spanish Forst", "36527", "Baldwin", "Alabama"],
["Brent", "35034", "Bibb", "Alabama"],
["Birmingham", "35201", "Bibb", "Alabama"],
["Birmingham", "35202", "Bibb", "Alabama"],
["Dinwiddie", "23841", "Dinwiddie", "Virginia"]
]
};
fetch("https://www.gocanvas.com/api/v3/reference_data", {
method: "POST",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(reference_data => console.log(reference_data));
Users can create new Reference Data. New Reference Data must have a unique name.
HTTP Request
POST https://www.gocanvas.com/api/v3/reference_data
RESPONSE
{
"id": 10761,
"type": "reference_data",
"name": "US Zip Codes",
"description": null,
"use_user_groups": null,
"version": 1,
"department_id": 21474,
"headers": ["gc_row_index", "City", "ZIP Code", "County", "State"],
"rows": [
[ "0", "Jones", "36749", "Autauga", "Alabama" ],
[ "1", "Daphne", "36526", "Baldwin", "Alabama" ],
[ "2", "Spanish Forst", "36527", "Baldwin", "Alabama" ],
[ "3", "Brent", "35034", "Bibb", "Alabama" ],
[ "4", "Birmingham", "35201", "Bibb", "Alabama" ],
[ "5", "Birmingham", "35202", "Bibb", "Alabama" ],
[ "6", "Dinwiddie", "23841", "Dinwiddie", "Virginia" ]
]
}
Request Parameters
| Parameter | Type | Description |
|---|---|---|
| format * | enum | The format of the returned reference data in JSON. Can be rows or rows_with_index |
* If format is not specified, the default format is rows. If format is specified as rows_with_index, the returned reference data will include an additional header of gc_row_index and each row will include an additional item of its numerical index.
Request Body Parameters
| Parameter | Type | Description |
|---|---|---|
| name | string | A short string value for name of a new reference data |
| description | string | A longer string value describing a new reference data |
| department_id* | integer (optional) | The unique Department ID to assign a new reference data to a Department |
| headers | array | An array of strings that represent the headers of the reference data |
| rows | array | An array of arrays that represent the rows of the reference data |
* department_id is required when creating a new Reference Data object if Departments are enabled for the Company.
Update Reference Data
BODY='{
"headers": ["gc_row_index", "City", "ZIP Code", "County", "State"],
"rows": [
["2", "Spanish Fort", "36527", "Baldwin", "Alabama"]
],
"delete_rows": ["6"]
}'
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X PATCH \
-d $BODY \
https://www.gocanvas.com/api/v3/reference_data
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
request_body = {
"headers": ["gc_row_index", "City", "ZIP Code", "County", "State"],
"rows": [
["2", "Spanish Fort", "36527", "Baldwin", "Alabama"]
],
"delete_rows": ["6"]
}
uri = URI("https://www.gocanvas.com/api/v3/reference_data")
json_request_body = request_body.to_json
req = Net::HTTP::Patch.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
req.body = json_request_body
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
reference_data_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
const data = {
"headers": ["gc_row_index", "City", "ZIP Code", "County", "State"],
"rows": [
["2", "Spanish Fort", "36527", "Baldwin", "Alabama"]
],
"delete_rows": ["6"]
};
fetch("https://www.gocanvas.com/api/v3/reference_data", {
method: "PATCH",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(reference_data => console.log(reference_data));
Users have the ability to update Reference Data for a specified Company. The default format is rows_with_index. The returned reference data will include an additional header of gc_row_index and each row will include an additional item of its numerical index.
Users may update existing rows by providing a gc_row_index with the row to identify the row to update.
Users may add new rows by either providing a gc_row_index of a blank string ("") or by omitting the gc_row_index column.
Users may delete existing rows by passing an array of indexes corresponding with the gc_row_index of the row.
Users should use the rows_with_index format option when retrieving Reference Data to understand the indexes created by GoCanvas.
HTTP Request
PATCH https://www.gocanvas.com/api/v3/reference_data/10761
RESPONSE
{
"id": 10761,
"type": "reference_data",
"name": "US Zip Codes",
"description": null,
"use_user_groups": null,
"version": 2,
"department_id": 21474,
"headers": ["gc_row_index", "City", "ZIP Code", "County", "State"],
"rows": [
[ "0", "Jones", "36749", "Autauga", "Alabama" ],
[ "1", "Daphne", "36526", "Baldwin", "Alabama" ],
[ "2", "Spanish Fort", "36527", "Baldwin", "Alabama" ],
[ "3", "Brent", "35034", "Bibb", "Alabama" ],
[ "4", "Birmingham", "35201", "Bibb", "Alabama" ],
[ "5", "Birmingham", "35202", "Bibb", "Alabama" ]
]
}
Request Body Parameters
| Parameter | Type | Description |
|---|---|---|
| headers | array | An array of strings that represent the headers of the reference data |
| rows | array | An array of arrays that represent the rows of the reference data to be updated or added |
| delete_rows | array (optional) | An array of integers of rows indexes to delete from the reference data |
Report
Reports assemble Submission data in the desired presentation format (e.g. a PDF) according to their Report Definition.
The Report object
Forms and Submissions may have multiple Report Definitions. Each Report Definition will transform data captured within a Submission into the defined format specified by a provided Report Definition identifier.
For example, a Submission with two Report Definitions could have one definition for an executive summary and one for a full report.
Retrieve the Standard Report
The Standard Report is automatically created for you by default. This is a basic Report with no customized options.
curl -u api.user@example.com:supersecretpassword \
https://www.gocanvas.com/api/v3/submissions/162888280/standard_pdf
HTTP Request
GET https://www.gocanvas.com/api/v3/submissions/160504422/standard_pdf
Retrieve the Default Report
The default Report format is specified by default PDF options
The id field returned by creating a Submission can be used to retrieve the default Report via https://www.gocanvas.com/api/v3/submissions/[SUBMISSION_ID]/pdf
curl -u api.user@example.com:supersecretpassword \
https://www.gocanvas.com/api/v3/submissions/162888280/pdf
HTTP Request
GET https://www.gocanvas.com/api/v3/submissions/160504422/pdf
List of Reports by Form
Forms can be associated with multiple Report Definitions (which are used to generate specific Reports, such as pdf output). This endpoint will return all the Reports currently associated with a particular Form:
GET https://www.gocanvas.com/api/v3/forms/346127/reports
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X GET \
https://www.gocanvas.com/api/v3/forms/346127/reports
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
uri = URI("https://www.gocanvas.com/api/v3/forms/346127/reports")
req = Net::HTTP::Get.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
reports_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
fetch("https://www.gocanvas.com/api/v3/forms/346127/reports", {
method: "GET",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
}
})
.then(response => response.json())
.then(reports => console.log(reports));
RESPONSE
[
{
"id": 7346,
"type": "form_report_definition",
"form_id": 346127,
"name": "Designer",
"created_at": "2021-09-22 19:34:17 UTC",
"updated_at": "2021-09-22 19:34:17 UTC",
"format": "PDF",
"default_emailed": true
}
]
Query Parameters
| Parameter | Type | Description | Default |
|---|---|---|---|
| page | integer (optional) | The page requested, see Pagination | 1 |
Single Report by Form
You can get more detail on a specific Report (including the full definition file) by supplying an id:
GET https://www.gocanvas.com/api/v3/forms/346127/reports/7346
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X GET \
https://www.gocanvas.com/api/v3/forms/346127/reports/7346
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
uri = URI("https://www.gocanvas.com/api/v3/forms/346127/reports/7346")
req = Net::HTTP::Get.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
report_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
fetch("https://www.gocanvas.com/api/v3/forms/346127/reports/7346", {
method: "GET",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
}
})
.then(response => response.json())
.then(report => console.log(report));
{
"id": 7346,
"type": "form_report_definition",
"form_id": 346127,
"name": "Designer",
"definition": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<report xmlns=\"http://www.eclipse.org/birt/2005/design\" version=\"3.2.23\" id=\"1\">\n <data-sources>\n <oda-data-source extensionID=\"org.eclipse.birt.report.data.oda.xml\" name=\"75e0e90b-520a-424c-aa71-7658b22fc4e8\" id=\"4\">\n <property name=\"FILELIST\">empty_submission.xml</property>\n </oda-data-source>\n </data-sources>\n <data-sets>\n <oda-data-set extensionID=\"org.eclipse.birt.report.data.oda.xml.dataSet\" name=\"75e0e90b-520a-424c-aa71-7658b22fc4e8\" id=\"5\">\n <property name=\"dataSource\">75e0e90b-520a-424c-aa71-7658b22fc4e8</property>\n <xml-property name=\"queryText\"><![CDATA[table0#-TNAME-#table0#:#[//Submissions/Submission[1]]#:#{16d4ee9f-b632-45d6-989b-79e8c54b4e36;STRING;//Form/HideConditionalScreen},{bc966d19-d769-445f-b182-2305410553a4;STRING;//Response[@Guid=\"D2E41E105EC47DA8468888CCBC663CB31301506B\"]/Value},{900ead6b-06d2-4e15-898e-5384983c454b;STRING;//Response[@Guid=\"D2E41E105EC47DA8468888CCBC663CB31301506B\"]/Displayed},{2d5647b7-c166-4ec8-8e41-4fb8b43f8fad;STRING;//Response[@Guid=\"D2E41E105EC47DA8468888CCBC663CB31301506B\"]/PDFVisible},{6d0ab69f-16fd-4aca-b2e1-b35938d794ba;STRING;//Form/HideConditionalScreen},{b6601e1a-25cd-4a06-a920-c2993757ca8a;STRING;ResponseID},{0c55f802-e5a3-4b49-970d-679e21920c56;STRING;//Form/HideConditionalScreen},{3089bd7c-0287-4d56-86b1-e21a52e34e6c;STRING;//Form/HideConditionalScreen},{652bb715-39fd-4c9f-b328-1c4650ae5c90;STRING;//Response[@Guid=\"8A9C06D355AE7B762B5CE11CE99135EC9CD486AE\"]/Value},{12a83f67-6234-494b-ad66-82f7d515afcb;STRING;//Response[@Guid=\"8A9C06D355AE7B762B5CE11CE99135EC9CD486AE\"]/Displayed},{7e6a9d44-3791-49d1-8ab2-0aaec42b1394;STRING;//Response[@Guid=\"8A9C06D355AE7B762B5CE11CE99135EC9CD486AE\"]/PDFVisible},{18a0b3d2-f9fa-4fde-97f3-f50d3a013c99;STRING;//Response[@Guid=\"15915D3CAC4DD89B98363A5BB8D776C87E7FDD13\"]/Value},{62cf2d6a-b714-41ee-97be-5a6153430d3b;STRING;//Response[@Guid=\"15915D3CAC4DD89B98363A5BB8D776C87E7FDD13\"]/Displayed},{4a6abda6-d3f7-4431-afec-939d270d0967;STRING;//Response[@Guid=\"15915D3CAC4DD89B98363A5BB8D776C87E7FDD13\"]/PDFVisible},{1e90160e-f503-4d84-999b-a36540841a8c;STRING;//Response[@Guid=\"1E5EDE84EBBD1B86F5BA57790DB8F71B5F528257\"]/Value},{52ab588a-d9d3-4613-b22f-6c989a9b3bed;STRING;//Response[@Guid=\"1E5EDE84EBBD1B86F5BA57790DB8F71B5F528257\"]/Displayed},{f40ff177-4d8e-4707-8fa1-1ecccd44671f;STRING;//Response[@Guid=\"1E5EDE84EBBD1B86F5BA57790DB8F71B5F528257\"]/PDFVisible},{91961290-f362-452d-b90d-8966733e7d3c;STRING;//Response[@Guid=\"9EFF80B7EC8D8B520CD11B988B5825D669AD05FE\"]/Value},{e9a3b434-9ba4-464e-ade7-a68272b34372;STRING;//Response[@Guid=\"9EFF80B7EC8D8B520CD11B988B5825D669AD05FE\"]/Displayed},{d32e0ab9-ea60-4e1e-bb38-bb8426664e7b;STRING;//Response[@Guid=\"9EFF80B7EC8D8B520CD11B988B5825D669AD05FE\"]/PDFVisible},{776f80bb-0293-4d20-8ecd-7597df5e818f;STRING;//Form/HideConditionalScreen},{783c57a7-1d71-424a-b60b-516a7515993c;STRING;//Response[@Guid=\"92AD1EF6A6FEE5D6D5B7CE04B60AD6B2369B1801\"]/Value},{1549cba6-84da-40c7-9f8e-eceb2c044dd7;STRING;//Response[@Guid=\"92AD1EF6A6FEE5D6D5B7CE04B60AD6B2369B1801\"]/Displayed},{584d343d-8a33-4d9a-b069-0e2c1e4d6a2f;STRING;//Response[@Guid=\"92AD1EF6A6FEE5D6D5B7CE04B60AD6B2369B1801\"]/PDFVisible},{e261f86d-76e4-4e29-a8bd-32fd3d1282b3;STRING;//Form/HideConditionalScreen},{c9087be2-4986-4e06-9c35-1b0b97b91b9a;STRING;//Form/HideConditionalScreen},{db68f9d2-123b-4230-b520-8b68405b6e80;STRING;//Response[@Guid=\"B5DF14C193EFAB631401CFE78CC0A15228764B23\"]/Value},{1c936da0-f467-4d43-baa1-6f1662d1fc93;STRING;//Response[@Guid=\"B5DF14C193EFAB631401CFE78CC0A15228764B23\"]/Displayed},{d7bfd25b-f103-4c5e-a98f-1c73c26bf545;STRING;//Response[@Guid=\"B5DF14C193EFAB631401CFE78CC0A15228764B23\"]/PDFVisible},{177f6163-aecc-47a7-9078-97e92c0208b3;STRING;//Response[@Guid=\"E99091AB355574C4A8030BC97C68B81E6EB3F735\"]/Value},{f9fd7cb9-0897-4f6a-9931-97e9295113e7;STRING;//Response[@Guid=\"E99091AB355574C4A8030BC97C68B81E6EB3F735\"]/Displayed},{62df09de-1e60-4c91-a1dd-05a9ccb7a77d;STRING;//Response[@Guid=\"E99091AB355574C4A8030BC97C68B81E6EB3F735\"]/PDFVisible},{5d51abbb-7730-4f69-8ad3-8800f266d125;STRING;//Response[@Guid=\"C4F2C0B1847C5A76BC751E8D1E62488F09A4E7BB\"]/Value},{60afd61b-cebd-4865-b921-c086052340aa;STRING;//Response[@Guid=\"C4F2C0B1847C5A76BC751E8D1E62488F09A4E7BB\"]/Displayed},{efa95347-6369-4766-b0d0-e0d5a908f498;STRING;//Response[@Guid=\"C4F2C0B1847C5A76BC751E8D1E62488F09A4E7BB\"]/PDFVisible},{774fa8b7-4a5b-4731-b3be-8ce3e868a88e;STRING;//Response[@Guid=\"ACFE9A0880B9A9F23F584F837898B23746F9CB75\"]/Value},{4c6a3bed-da52-4ff2-a1e6-ebc731aff3cf;STRING;//Response[@Guid=\"ACFE9A0880B9A9F23F584F837898B23746F9CB75\"]/Displayed},{ffc2811f-dd15-4548-8994-81b161b6fb1e;STRING;//Response[@Guid=\"ACFE9A0880B9A9F23F584F837898B23746F9CB75\"]/PDFVisible}]]></xml-property>\n </oda-data-set>\n </data-sets>\n <styles>\n <style name=\"crosstab\" id=\"2\">\n <property name=\"borderBottomColor\">#CCCCCC</property>\n <property name=\"borderBottomStyle\">solid</property>\n <property name=\"borderBottomWidth\">1pt</property>\n <property name=\"borderLeftColor\">#CCCCCC</property>\n <property name=\"borderLeftStyle\">solid</property>\n <property name=\"borderLeftWidth\">1pt</property>\n <property name=\"borderRightColor\">#CCCCCC</property>\n <property name=\"borderRightStyle\">solid</property>\n <property name=\"borderRightWidth\">1pt</property>\n <property name=\"borderTopColor\">#CCCCCC</property>\n <property name=\"borderTopStyle\">solid</property>\n <property name=\"borderTopWidth\">1pt</property>\n </style>\n <style name=\"crosstab-cell\" id=\"3\">\n <property name=\"borderBottomColor\">#CCCCCC</property>\n <property name=\"borderBottomStyle\">solid</property>\n <property name=\"borderBottomWidth\">1pt</property>\n <property name=\"borderLeftColor\">#CCCCCC</property>\n <property name=\"borderLeftStyle\">solid</property>\n <property name=\"borderLeftWidth\">1pt</property>\n <property name=\"borderRightColor\">#CCCCCC</property>\n <property name=\"borderRightStyle\">solid</property>\n <property name=\"borderRightWidth\">1pt</property>\n <property name=\"borderTopColor\">#CCCCCC</property>\n <property name=\"borderTopStyle\">solid</property>\n <property name=\"borderTopWidth\">1pt</property>\n </style>\n <style name=\"report\" id=\"6\">\n <property name=\"fontFamily\">\"Helvetica\"</property>\n <property name=\"fontSize\">15.600000000000001px</property>\n <property name=\"fontWeight\">normal</property>\n <property name=\"color\">#414042</property>\n </style>\n <style name=\"style9\" id=\"16\">\n <property name=\"paddingTop\">8px</property>\n <property name=\"paddingLeft\">8px</property>\n <property name=\"paddingBottom\">8px</property>\n <property name=\"paddingRight\">8px</property>\n <property name=\"verticalAlign\">top</property>\n <property name=\"width\">25.522%</property>\n </style>\n <style name=\"style10\" id=\"18\">\n <property name=\"paddingTop\">28px</property>\n <property name=\"paddingLeft\">8px</property>\n <property name=\"paddingBottom\">14px</property>\n <property name=\"paddingRight\">8px</property>\n <property name=\"verticalAlign\">top</property>\n <property name=\"width\">57.357%</property>\n </style>\n <style name=\"style11\" id=\"20\">\n <property name=\"paddingTop\">8px</property>\n <property name=\"paddingLeft\">8px</property>\n <property name=\"paddingBottom\">8px</property>\n <property name=\"paddingRight\">8px</property>\n <property name=\"verticalAlign\">top</property>\n <property name=\"width\">17.121%</property>\n </style>\n <style name=\"style28\" id=\"35\">\n <property name=\"verticalAlign\">top</property>\n <property name=\"width\">40%</property>\n </style>\n <style name=\"style29\" id=\"37\">\n <property name=\"verticalAlign\">top</property>\n <property name=\"width\">20%</property>\n </style>\n <style name=\"style30\" id=\"39\">\n <property name=\"verticalAlign\">top</property>\n <property name=\"width\">40%</property>\n </style>\n <style name=\"style42\" id=\"45\">\n <property name=\"paddingTop\">8px</property>\n <property name=\"paddingLeft\">6px</property>\n <property name=\"paddingBottom\">8px</property>\n <property name=\"paddingRight\">6px</property>\n <property name=\"verticalAlign\">top</property>\n <property name=\"width\">100%</property>\n </style>\n <style name=\"style48\" id=\"53\">\n <property name=\"paddingTop\">8px</property>\n <property name=\"paddingLeft\">6px</property>\n <property name=\"paddingBottom\">8px</property>\n <property name=\"paddingRight\">0px</property>\n <property name=\"verticalAlign\">top</property>\n <property name=\"width\">50%</property>\n </style>\n <style name=\"style49\" id=\"58\">\n <property name=\"paddingTop\">8px</property>\n <property name=\"paddingLeft\">0px</property>\n <property name=\"paddingBottom\">8px</property>\n <property name=\"paddingRight\">6px</property>\n <property name=\"verticalAlign\">top</property>\n <property name=\"width\">50%</property>\n </style>\n <style name=\"style64\" id=\"67\">\n <property name=\"paddingTop\">8px</property>\n <property name=\"paddingLeft\">6px</property>\n <property name=\"paddingBottom\">8px</property>\n <property name=\"paddingRight\">6px</property>\n <property name=\"verticalAlign\">top</property>\n <property name=\"width\">100%</property>\n </style>\n <style name=\"style71\" id=\"74\">\n <property name=\"paddingTop\">8px</property>\n <property name=\"paddingLeft\">6px</property>\n <property name=\"paddingBottom\">8px</property>\n <property name=\"paddingRight\">6px</property>\n <property name=\"verticalAlign\">top</property>\n <property name=\"width\">100%</property>\n </style>\n <style name=\"style77\" id=\"82\">\n <property name=\"paddingTop\">8px</property>\n <property name=\"paddingLeft\">6px</property>\n <property name=\"paddingBottom\">8px</property>\n <property name=\"paddingRight\">0px</property>\n <property name=\"verticalAlign\">top</property>\n <property name=\"width\">50%</property>\n </style>\n <style name=\"style78\" id=\"87\">\n <property name=\"paddingTop\">8px</property>\n <property name=\"paddingLeft\">0px</property>\n <property name=\"paddingBottom\">8px</property>\n <property name=\"paddingRight\">6px</property>\n <property name=\"verticalAlign\">top</property>\n <property name=\"width\">50%</property>\n </style>\n </styles>\n <page-setup>\n <simple-master-page name=\"75e0e90b-520a-424c-aa71-7658b22fc4e8\" id=\"7\">\n <property name=\"type\">us-letter</property>\n <property name=\"orientation\">portrait</property>\n <property name=\"fontFamily\">\"Helvetica\"</property>\n <property name=\"fontSize\">15.600000000000001px</property>\n <property name=\"color\">#414042</property>\n <property name=\"marginTop\">2%</property>\n <property name=\"marginLeft\">2%</property>\n <property name=\"marginBottom\">2%</property>\n <property name=\"marginRight\">2%</property>\n <property name=\"lineHeight\">143%</property>\n <property name=\"headerHeight\">1in</property>\n <property name=\"footerHeight\">25px</property>\n <page-header>\n <grid id=\"8\">\n <property name=\"marginBottom\">1px</property>\n <property name=\"width\">100%</property>\n <property name=\"dataSet\">75e0e90b-520a-424c-aa71-7658b22fc4e8</property>\n <list-property name=\"boundDataColumns\">\n <structure>\n <property name=\"name\">16d4ee9f-b632-45d6-989b-79e8c54b4e36</property>\n <expression name=\"expression\">dataSetRow[\"16d4ee9f-b632-45d6-989b-79e8c54b4e36\"]</expression>\n </structure>\n <structure>\n <property name=\"name\">bc966d19-d769-445f-b182-2305410553a4</property>\n <expression name=\"expression\">dataSetRow[\"bc966d19-d769-445f-b182-2305410553a4\"]</expression>\n </structure>\n <structure>\n <property name=\"name\">900ead6b-06d2-4e15-898e-5384983c454b</property>\n <expression name=\"expression\">dataSetRow[\"900ead6b-06d2-4e15-898e-5384983c454b\"]</expression>\n </structure>\n <structure>\n <property name=\"name\">2d5647b7-c166-4ec8-8e41-4fb8b43f8fad</property>\n <expression name=\"expression\">dataSetRow[\"2d5647b7-c166-4ec8-8e41-4fb8b43f8fad\"]</expression>\n </structure>\n </list-property>\n <column id=\"9\">\n <property name=\"style\">style9</property>\n </column>\n <column id=\"10\">\n <property name=\"style\">style10</property>\n </column>\n <column id=\"11\">\n <property name=\"style\">style11</property>\n </column>\n <row id=\"12\">\n <cell id=\"13\">\n <image name=\"c4215600-55e4-427f-8da0-1ce4610f3680\" id=\"17\">\n <property name=\"fontSize\">18.2px</property>\n <property name=\"color\">#000000</property>\n <property name=\"paddingTop\">1px</property>\n <property name=\"paddingBottom\">1px</property>\n <property name=\"width\">100%</property>\n <list-property name=\"visibility\">\n <structure>\n <property name=\"format\">all</property>\n <expression name=\"valueExpr\">\"https://demo.gocanvas.com/pdf_builder_images/41935820dc1c8516462f898adbfbcae5dcc6\" == \"null\"</expression>\n </structure>\n </list-property>\n <property name=\"source\">url</property>\n <property name=\"fitToContainer\">true</property>\n <property name=\"proportionalScale\">true</property>\n <expression name=\"uri\">\"https://demo.gocanvas.com/pdf_builder_images/41935820dc1c8516462f898adbfbcae5dcc6\"</expression>\n <expression name=\"altText\" type=\"javascript\">if(true) \"\"</expression>\n </image>\n </cell>\n <cell id=\"14\">\n <text name=\"b7d24a1d-607e-43a4-9e95-0cd2430b86c9\" id=\"19\">\n <property name=\"fontSize\">20.8px</property>\n <property name=\"fontWeight\">bold</property>\n <property name=\"color\">#414042</property>\n <property name=\"paddingTop\">1px</property>\n <property name=\"paddingBottom\">1px</property>\n <property name=\"textAlign\">center</property>\n <property name=\"lineHeight\">143%</property>\n <property name=\"contentType\">html</property>\n <text-property name=\"content\"><![CDATA[Your Business Name]]></text-property>\n </text>\n </cell>\n <cell id=\"15\">\n <label id=\"21\">\n <property name=\"fontSize\">12px</property>\n <property name=\"fontWeight\">bold</property>\n <property name=\"color\">#414042</property>\n <property name=\"paddingTop\">10px</property>\n <property name=\"paddingBottom\">10px</property>\n <property name=\"textAlign\">left</property>\n <property name=\"lineHeight\">143%</property>\n <list-property name=\"visibility\">\n <structure>\n <property name=\"format\">all</property>\n <expression name=\"valueExpr\">row[\"2d5647b7-c166-4ec8-8e41-4fb8b43f8fad\"] == \"false\" || (row[\"16d4ee9f-b632-45d6-989b-79e8c54b4e36\"] == \"true\" && row[\"900ead6b-06d2-4e15-898e-5384983c454b\"] == \"false\")</expression>\n </structure>\n </list-property>\n <text-property name=\"text\">Date</text-property>\n </label>\n <data name=\"33112a84-438e-4bd9-a392-af7335a358c4\" id=\"22\">\n <property name=\"fontSize\">15.600000000000001px</property>\n <property name=\"fontWeight\">normal</property>\n <property name=\"color\">#414042</property>\n <property name=\"paddingBottom\">10px</property>\n <property name=\"textAlign\">left</property>\n <property name=\"lineHeight\">143%</property>\n <list-property name=\"visibility\">\n <structure>\n <property name=\"format\">all</property>\n <expression name=\"valueExpr\">row[\"2d5647b7-c166-4ec8-8e41-4fb8b43f8fad\"] == \"false\" || (row[\"16d4ee9f-b632-45d6-989b-79e8c54b4e36\"] == \"true\" && row[\"900ead6b-06d2-4e15-898e-5384983c454b\"] == \"false\")</expression>\n </structure>\n </list-property>\n <property name=\"resultSetColumn\">bc966d19-d769-445f-b182-2305410553a4</property>\n </data>\n </cell>\n </row>\n </grid>\n </page-header>\n <page-footer>\n <grid id=\"23\">\n <property name=\"width\">100%</property>\n <property name=\"dataSet\">75e0e90b-520a-424c-aa71-7658b22fc4e8</property>\n <column id=\"24\"/>\n <row id=\"25\">\n <cell id=\"26\">\n <grid name=\"sectionGrid\" id=\"27\">\n <property name=\"marginTop\">5px</property>\n <property name=\"width\">100%</property>\n <property name=\"dataSet\">75e0e90b-520a-424c-aa71-7658b22fc4e8</property>\n <list-property name=\"boundDataColumns\">\n <structure>\n <property name=\"name\">6d0ab69f-16fd-4aca-b2e1-b35938d794ba</property>\n <expression name=\"expression\">dataSetRow[\"6d0ab69f-16fd-4aca-b2e1-b35938d794ba\"]</expression>\n </structure>\n <structure>\n <property name=\"name\">b6601e1a-25cd-4a06-a920-c2993757ca8a</property>\n <expression name=\"expression\">dataSetRow[\"b6601e1a-25cd-4a06-a920-c2993757ca8a\"]</expression>\n </structure>\n </list-property>\n <column id=\"28\">\n <property name=\"style\">style28</property>\n </column>\n <column id=\"29\">\n <property name=\"style\">style29</property>\n </column>\n <column id=\"30\">\n <property name=\"style\">style30</property>\n </column>\n <row id=\"31\">\n <cell id=\"32\">\n <image name=\"660ef121-f756-4076-aa6f-7468cdcbf048\" id=\"36\">\n <property name=\"marginLeft\">-15px</property>\n <property name=\"height\">20px</property>\n <property name=\"width\">120px</property>\n <list-property name=\"visibility\">\n <structure>\n <property name=\"format\">all</property>\n <expression name=\"valueExpr\">\"https://demo.gocanvas.com/images/pdfbuilder/powered_by_canvas.png\" == \"null\"</expression>\n </structure>\n </list-property>\n <property name=\"source\">url</property>\n <property name=\"fitToContainer\">true</property>\n <property name=\"proportionalScale\">true</property>\n <expression name=\"uri\">\"https://demo.gocanvas.com/images/pdfbuilder/powered_by_canvas.png\"</expression>\n <expression name=\"altText\" type=\"javascript\">if(true) \"\"</expression>\n <list-property name=\"action\">\n <structure>\n <property name=\"linkType\">hyperlink</property>\n <expression name=\"uri\" type=\"constant\">http://www.gocanvas.com/?utm_source=canvas_pdf&utm_medium=pdf_link&utm_campaign=canvas_pdf_link</expression>\n </structure>\n </list-property>\n </image>\n </cell>\n <cell id=\"33\">\n <label id=\"38\">\n <property name=\"fontSize\">12px</property>\n <property name=\"color\">#27AAE1</property>\n <property name=\"textAlign\">center</property>\n <property name=\"lineHeight\">100%</property>\n <text-property name=\"text\">www.gocanvas.com</text-property>\n <list-property name=\"action\">\n <structure>\n <property name=\"linkType\">hyperlink</property>\n <expression name=\"uri\" type=\"constant\">http://www.gocanvas.com/?utm_source=canvas_pdf&utm_medium=pdf_link&utm_campaign=canvas_pdf_link</expression>\n </structure>\n </list-property>\n </label>\n </cell>\n <cell id=\"34\">\n <data name=\"450d25ca-3851-4347-98d3-73693be9775a\" id=\"40\">\n <property name=\"fontSize\">12px</property>\n <property name=\"color\">#ADB0B3</property>\n <property name=\"textAlign\">right</property>\n <property name=\"lineHeight\">100%</property>\n <property name=\"resultSetColumn\">b6601e1a-25cd-4a06-a920-c2993757ca8a</property>\n </data>\n </cell>\n </row>\n </grid>\n </cell>\n </row>\n </grid>\n </page-footer>\n </simple-master-page>\n </page-setup>\n <body>\n <grid id=\"41\">\n <property name=\"marginBottom\">1px</property>\n <property name=\"width\">100%</property>\n <property name=\"dataSet\">75e0e90b-520a-424c-aa71-7658b22fc4e8</property>\n <list-property name=\"boundDataColumns\">\n <structure>\n <property name=\"name\">0c55f802-e5a3-4b49-970d-679e21920c56</property>\n <expression name=\"expression\">dataSetRow[\"0c55f802-e5a3-4b49-970d-679e21920c56\"]</expression>\n </structure>\n </list-property>\n <column id=\"42\">\n <property name=\"style\">style42</property>\n </column>\n <row id=\"43\">\n <cell id=\"44\">\n <text name=\"8cc8557c-9291-4912-9ce3-3a5e188a7766\" id=\"46\">\n <property name=\"backgroundColor\">#00305E</property>\n <property name=\"fontSize\">18.2px</property>\n <property name=\"fontWeight\">normal</property>\n <property name=\"color\">#FFFFFF</property>\n <property name=\"borderBottomColor\">#00305E</property>\n <property name=\"borderBottomStyle\">solid</property>\n <property name=\"borderBottomWidth\">1px</property>\n <property name=\"borderLeftColor\">#00305E</property>\n <property name=\"borderLeftStyle\">solid</property>\n <property name=\"borderLeftWidth\">1px</property>\n <property name=\"borderRightColor\">#00305E</property>\n <property name=\"borderRightStyle\">solid</property>\n <property name=\"borderRightWidth\">1px</property>\n <property name=\"borderTopColor\">#00305E</property>\n <property name=\"borderTopStyle\">solid</property>\n <property name=\"borderTopWidth\">1px</property>\n <property name=\"paddingTop\">3px</property>\n <property name=\"paddingBottom\">3px</property>\n <property name=\"textAlign\">center</property>\n <property name=\"lineHeight\">143%</property>\n <property name=\"contentType\">html</property>\n <text-property name=\"content\"><![CDATA[General Information]]></text-property>\n </text>\n </cell>\n </row>\n </grid>\n <grid id=\"47\">\n <property name=\"marginBottom\">1px</property>\n <property name=\"width\">100%</property>\n <property name=\"dataSet\">75e0e90b-520a-424c-aa71-7658b22fc4e8</property>\n <list-property name=\"boundDataColumns\">\n <structure>\n <property name=\"name\">3089bd7c-0287-4d56-86b1-e21a52e34e6c</property>\n <expression name=\"expression\">dataSetRow[\"3089bd7c-0287-4d56-86b1-e21a52e34e6c\"]</expression>\n </structure>\n <structure>\n <property name=\"name\">652bb715-39fd-4c9f-b328-1c4650ae5c90</property>\n <expression name=\"expression\">dataSetRow[\"652bb715-39fd-4c9f-b328-1c4650ae5c90\"]</expression>\n </structure>\n <structure>\n <property name=\"name\">12a83f67-6234-494b-ad66-82f7d515afcb</property>\n <expression name=\"expression\">dataSetRow[\"12a83f67-6234-494b-ad66-82f7d515afcb\"]</expression>\n </structure>\n <structure>\n <property name=\"name\">7e6a9d44-3791-49d1-8ab2-0aaec42b1394</property>\n <expression name=\"expression\">dataSetRow[\"7e6a9d44-3791-49d1-8ab2-0aaec42b1394\"]</expression>\n </structure>\n <structure>\n <property name=\"name\">18a0b3d2-f9fa-4fde-97f3-f50d3a013c99</property>\n <expression name=\"expression\">dataSetRow[\"18a0b3d2-f9fa-4fde-97f3-f50d3a013c99\"]</expression>\n </structure>\n <structure>\n <property name=\"name\">62cf2d6a-b714-41ee-97be-5a6153430d3b</property>\n <expression name=\"expression\">dataSetRow[\"62cf2d6a-b714-41ee-97be-5a6153430d3b\"]</expression>\n </structure>\n <structure>\n <property name=\"name\">4a6abda6-d3f7-4431-afec-939d270d0967</property>\n <expression name=\"expression\">dataSetRow[\"4a6abda6-d3f7-4431-afec-939d270d0967\"]</expression>\n </structure>\n <structure>\n <property name=\"name\">1e90160e-f503-4d84-999b-a36540841a8c</property>\n <expression name=\"expression\">dataSetRow[\"1e90160e-f503-4d84-999b-a36540841a8c\"]</expression>\n </structure>\n <structure>\n <property name=\"name\">52ab588a-d9d3-4613-b22f-6c989a9b3bed</property>\n <expression name=\"expression\">dataSetRow[\"52ab588a-d9d3-4613-b22f-6c989a9b3bed\"]</expression>\n </structure>\n <structure>\n <property name=\"name\">f40ff177-4d8e-4707-8fa1-1ecccd44671f</property>\n <expression name=\"expression\">dataSetRow[\"f40ff177-4d8e-4707-8fa1-1ecccd44671f\"]</expression>\n </structure>\n <structure>\n <property name=\"name\">91961290-f362-452d-b90d-8966733e7d3c</property>\n <expression name=\"expression\">dataSetRow[\"91961290-f362-452d-b90d-8966733e7d3c\"]</expression>\n </structure>\n <structure>\n <property name=\"name\">e9a3b434-9ba4-464e-ade7-a68272b34372</property>\n <expression name=\"expression\">dataSetRow[\"e9a3b434-9ba4-464e-ade7-a68272b34372\"]</expression>\n </structure>\n <structure>\n <property name=\"name\">d32e0ab9-ea60-4e1e-bb38-bb8426664e7b</property>\n <expression name=\"expression\">dataSetRow[\"d32e0ab9-ea60-4e1e-bb38-bb8426664e7b\"]</expression>\n </structure>\n </list-property>\n <column id=\"48\">\n <property name=\"style\">style48</property>\n </column>\n <column id=\"49\">\n <property name=\"style\">style49</property>\n </column>\n <row id=\"50\">\n <cell id=\"51\">\n <label id=\"54\">\n <property name=\"fontSize\">12px</property>\n <property name=\"fontWeight\">bold</property>\n <property name=\"paddingTop\">1px</property>\n <property name=\"paddingBottom\">1px</property>\n <property name=\"textAlign\">left</property>\n <property name=\"lineHeight\">143%</property>\n <list-property name=\"visibility\">\n <structure>\n <property name=\"format\">all</property>\n <expression name=\"valueExpr\">row[\"7e6a9d44-3791-49d1-8ab2-0aaec42b1394\"] == \"false\" || (row[\"3089bd7c-0287-4d56-86b1-e21a52e34e6c\"] == \"true\" && row[\"12a83f67-6234-494b-ad66-82f7d515afcb\"] == \"false\")</expression>\n </structure>\n </list-property>\n <text-property name=\"text\">Employee Name</text-property>\n </label>\n <data name=\"6f96de37-d472-45f7-880a-a9d1e9a336d6\" id=\"55\">\n <property name=\"fontWeight\">normal</property>\n <property name=\"paddingBottom\">1px</property>\n <property name=\"textAlign\">left</property>\n <property name=\"lineHeight\">143%</property>\n <list-property name=\"visibility\">\n <structure>\n <property name=\"format\">all</property>\n <expression name=\"valueExpr\">row[\"7e6a9d44-3791-49d1-8ab2-0aaec42b1394\"] == \"false\" || (row[\"3089bd7c-0287-4d56-86b1-e21a52e34e6c\"] == \"true\" && row[\"12a83f67-6234-494b-ad66-82f7d515afcb\"] == \"false\")</expression>\n </structure>\n </list-property>\n <property name=\"resultSetColumn\">652bb715-39fd-4c9f-b328-1c4650ae5c90</property>\n </data>\n <label id=\"56\">\n <property name=\"backgroundColor\">#FBFCFD</property>\n <property name=\"fontSize\">12px</property>\n <property name=\"fontWeight\">bold</property>\n <property name=\"borderLeftColor\">#FBFCFD</property>\n <property name=\"borderLeftStyle\">solid</property>\n <property name=\"borderLeftWidth\">1px</property>\n <property name=\"borderRightColor\">#FBFCFD</property>\n <property name=\"borderRightStyle\">solid</property>\n <property name=\"borderRightWidth\">1px</property>\n <property name=\"borderTopColor\">#FBFCFD</property>\n <property name=\"borderTopStyle\">solid</property>\n <property name=\"borderTopWidth\">1px</property>\n <property name=\"paddingTop\">1px</property>\n <property name=\"paddingBottom\">1px</property>\n <property name=\"textAlign\">left</property>\n <property name=\"lineHeight\">143%</property>\n <list-property name=\"visibility\">\n <structure>\n <property name=\"format\">all</property>\n <expression name=\"valueExpr\">row[\"4a6abda6-d3f7-4431-afec-939d270d0967\"] == \"false\" || (row[\"3089bd7c-0287-4d56-86b1-e21a52e34e6c\"] == \"true\" && row[\"62cf2d6a-b714-41ee-97be-5a6153430d3b\"] == \"false\")</expression>\n </structure>\n </list-property>\n <text-property name=\"text\">Employee ID</text-property>\n </label>\n <data name=\"94da1549-3dd9-4c84-844a-e55dc13a60ca\" id=\"57\">\n <property name=\"backgroundColor\">#FBFCFD</property>\n <property name=\"fontWeight\">normal</property>\n <property name=\"borderBottomColor\">#FBFCFD</property>\n <property name=\"borderBottomStyle\">solid</property>\n <property name=\"borderBottomWidth\">1px</property>\n <property name=\"borderLeftColor\">#FBFCFD</property>\n <property name=\"borderLeftStyle\">solid</property>\n <property name=\"borderLeftWidth\">1px</property>\n <property name=\"borderRightColor\">#FBFCFD</property>\n <property name=\"borderRightStyle\">solid</property>\n <property name=\"borderRightWidth\">1px</property>\n <property name=\"paddingBottom\">1px</property>\n <property name=\"textAlign\">left</property>\n <property name=\"lineHeight\">143%</property>\n <list-property name=\"visibility\">\n <structure>\n <property name=\"format\">all</property>\n <expression name=\"valueExpr\">row[\"4a6abda6-d3f7-4431-afec-939d270d0967\"] == \"false\" || (row[\"3089bd7c-0287-4d56-86b1-e21a52e34e6c\"] == \"true\" && row[\"62cf2d6a-b714-41ee-97be-5a6153430d3b\"] == \"false\")</expression>\n </structure>\n </list-property>\n <property name=\"resultSetColumn\">18a0b3d2-f9fa-4fde-97f3-f50d3a013c99</property>\n </data>\n </cell>\n <cell id=\"52\">\n <label id=\"59\">\n <property name=\"fontSize\">12px</property>\n <property name=\"fontWeight\">bold</property>\n <property name=\"paddingTop\">1px</property>\n <property name=\"paddingBottom\">1px</property>\n <property name=\"textAlign\">left</property>\n <property name=\"lineHeight\">143%</property>\n <list-property name=\"visibility\">\n <structure>\n <property name=\"format\">all</property>\n <expression name=\"valueExpr\">row[\"f40ff177-4d8e-4707-8fa1-1ecccd44671f\"] == \"false\" || (row[\"3089bd7c-0287-4d56-86b1-e21a52e34e6c\"] == \"true\" && row[\"52ab588a-d9d3-4613-b22f-6c989a9b3bed\"] == \"false\")</expression>\n </structure>\n </list-property>\n <text-property name=\"text\">Start Time</text-property>\n </label>\n <data name=\"77a55a2c-cbd3-4832-b033-6fac227d90c7\" id=\"60\">\n <property name=\"fontWeight\">normal</property>\n <property name=\"paddingBottom\">1px</property>\n <property name=\"textAlign\">left</property>\n <property name=\"lineHeight\">143%</property>\n <list-property name=\"visibility\">\n <structure>\n <property name=\"format\">all</property>\n <expression name=\"valueExpr\">row[\"f40ff177-4d8e-4707-8fa1-1ecccd44671f\"] == \"false\" || (row[\"3089bd7c-0287-4d56-86b1-e21a52e34e6c\"] == \"true\" && row[\"52ab588a-d9d3-4613-b22f-6c989a9b3bed\"] == \"false\")</expression>\n </structure>\n </list-property>\n <property name=\"resultSetColumn\">1e90160e-f503-4d84-999b-a36540841a8c</property>\n </data>\n <label id=\"61\">\n <property name=\"backgroundColor\">#FBFCFD</property>\n <property name=\"fontSize\">12px</property>\n <property name=\"fontWeight\">bold</property>\n <property name=\"borderLeftColor\">#FBFCFD</property>\n <property name=\"borderLeftStyle\">solid</property>\n <property name=\"borderLeftWidth\">1px</property>\n <property name=\"borderRightColor\">#FBFCFD</property>\n <property name=\"borderRightStyle\">solid</property>\n <property name=\"borderRightWidth\">1px</property>\n <property name=\"borderTopColor\">#FBFCFD</property>\n <property name=\"borderTopStyle\">solid</property>\n <property name=\"borderTopWidth\">1px</property>\n <property name=\"paddingTop\">1px</property>\n <property name=\"paddingBottom\">1px</property>\n <property name=\"textAlign\">left</property>\n <property name=\"lineHeight\">143%</property>\n <list-property name=\"visibility\">\n <structure>\n <property name=\"format\">all</property>\n <expression name=\"valueExpr\">row[\"d32e0ab9-ea60-4e1e-bb38-bb8426664e7b\"] == \"false\" || (row[\"3089bd7c-0287-4d56-86b1-e21a52e34e6c\"] == \"true\" && row[\"e9a3b434-9ba4-464e-ade7-a68272b34372\"] == \"false\")</expression>\n </structure>\n </list-property>\n <text-property name=\"text\">End Time</text-property>\n </label>\n <data name=\"df872395-5845-44b1-88fe-f497639ce3b4\" id=\"62\">\n <property name=\"backgroundColor\">#FBFCFD</property>\n <property name=\"fontWeight\">normal</property>\n <property name=\"borderBottomColor\">#FBFCFD</property>\n <property name=\"borderBottomStyle\">solid</property>\n <property name=\"borderBottomWidth\">1px</property>\n <property name=\"borderLeftColor\">#FBFCFD</property>\n <property name=\"borderLeftStyle\">solid</property>\n <property name=\"borderLeftWidth\">1px</property>\n <property name=\"borderRightColor\">#FBFCFD</property>\n <property name=\"borderRightStyle\">solid</property>\n <property name=\"borderRightWidth\">1px</property>\n <property name=\"paddingBottom\">1px</property>\n <property name=\"textAlign\">left</property>\n <property name=\"lineHeight\">143%</property>\n <list-property name=\"visibility\">\n <structure>\n <property name=\"format\">all</property>\n <expression name=\"valueExpr\">row[\"d32e0ab9-ea60-4e1e-bb38-bb8426664e7b\"] == \"false\" || (row[\"3089bd7c-0287-4d56-86b1-e21a52e34e6c\"] == \"true\" && row[\"e9a3b434-9ba4-464e-ade7-a68272b34372\"] == \"false\")</expression>\n </structure>\n </list-property>\n <property name=\"resultSetColumn\">91961290-f362-452d-b90d-8966733e7d3c</property>\n </data>\n </cell>\n </row>\n </grid>\n <grid id=\"63\">\n <property name=\"marginBottom\">1px</property>\n <property name=\"width\">100%</property>\n <property name=\"dataSet\">75e0e90b-520a-424c-aa71-7658b22fc4e8</property>\n <list-property name=\"boundDataColumns\">\n <structure>\n <property name=\"name\">776f80bb-0293-4d20-8ecd-7597df5e818f</property>\n <expression name=\"expression\">dataSetRow[\"776f80bb-0293-4d20-8ecd-7597df5e818f\"]</expression>\n </structure>\n <structure>\n <property name=\"name\">783c57a7-1d71-424a-b60b-516a7515993c</property>\n <expression name=\"expression\">dataSetRow[\"783c57a7-1d71-424a-b60b-516a7515993c\"]</expression>\n </structure>\n <structure>\n <property name=\"name\">1549cba6-84da-40c7-9f8e-eceb2c044dd7</property>\n <expression name=\"expression\">dataSetRow[\"1549cba6-84da-40c7-9f8e-eceb2c044dd7\"]</expression>\n </structure>\n <structure>\n <property name=\"name\">584d343d-8a33-4d9a-b069-0e2c1e4d6a2f</property>\n <expression name=\"expression\">dataSetRow[\"584d343d-8a33-4d9a-b069-0e2c1e4d6a2f\"]</expression>\n </structure>\n </list-property>\n <column id=\"64\">\n <property name=\"style\">style64</property>\n </column>\n <row id=\"65\">\n <list-property name=\"visibility\">\n <structure>\n <property name=\"format\">all</property>\n <expression name=\"valueExpr\">row[\"584d343d-8a33-4d9a-b069-0e2c1e4d6a2f\"] == \"false\" || (row[\"776f80bb-0293-4d20-8ecd-7597df5e818f\"] == \"true\" && row[\"1549cba6-84da-40c7-9f8e-eceb2c044dd7\"] == \"false\")</expression>\n </structure>\n </list-property>\n <cell id=\"66\">\n <label id=\"68\">\n <property name=\"fontSize\">12px</property>\n <property name=\"fontWeight\">bold</property>\n <property name=\"paddingTop\">1px</property>\n <property name=\"paddingBottom\">1px</property>\n <property name=\"textAlign\">left</property>\n <property name=\"lineHeight\">143%</property>\n <list-property name=\"visibility\">\n <structure>\n <property name=\"format\">all</property>\n <expression name=\"valueExpr\">row[\"584d343d-8a33-4d9a-b069-0e2c1e4d6a2f\"] == \"false\" || (row[\"776f80bb-0293-4d20-8ecd-7597df5e818f\"] == \"true\" && row[\"1549cba6-84da-40c7-9f8e-eceb2c044dd7\"] == \"false\")</expression>\n </structure>\n </list-property>\n <text-property name=\"text\">Work Performed</text-property>\n </label>\n <data name=\"d2993f6e-42c1-423d-ae67-4c0c7f01c214\" id=\"69\">\n <property name=\"fontWeight\">normal</property>\n <property name=\"paddingBottom\">1px</property>\n <property name=\"textAlign\">left</property>\n <property name=\"lineHeight\">143%</property>\n <list-property name=\"visibility\">\n <structure>\n <property name=\"format\">all</property>\n <expression name=\"valueExpr\">row[\"584d343d-8a33-4d9a-b069-0e2c1e4d6a2f\"] == \"false\" || (row[\"776f80bb-0293-4d20-8ecd-7597df5e818f\"] == \"true\" && row[\"1549cba6-84da-40c7-9f8e-eceb2c044dd7\"] == \"false\")</expression>\n </structure>\n </list-property>\n <property name=\"resultSetColumn\">783c57a7-1d71-424a-b60b-516a7515993c</property>\n </data>\n </cell>\n </row>\n </grid>\n <grid id=\"70\">\n <property name=\"marginBottom\">1px</property>\n <property name=\"width\">100%</property>\n <property name=\"dataSet\">75e0e90b-520a-424c-aa71-7658b22fc4e8</property>\n <list-property name=\"boundDataColumns\">\n <structure>\n <property name=\"name\">e261f86d-76e4-4e29-a8bd-32fd3d1282b3</property>\n <expression name=\"expression\">dataSetRow[\"e261f86d-76e4-4e29-a8bd-32fd3d1282b3\"]</expression>\n </structure>\n </list-property>\n <column id=\"71\">\n <property name=\"style\">style71</property>\n </column>\n <row id=\"72\">\n <cell id=\"73\">\n <text name=\"6e86b1fc-8b84-4da0-9abf-a91f3c24d242\" id=\"75\">\n <property name=\"backgroundColor\">#00305E</property>\n <property name=\"fontSize\">18.2px</property>\n <property name=\"fontWeight\">normal</property>\n <property name=\"fontStyle\">normal</property>\n <property name=\"color\">#FFFFFF</property>\n <property name=\"textUnderline\">none</property>\n <property name=\"borderBottomColor\">#00305E</property>\n <property name=\"borderBottomStyle\">solid</property>\n <property name=\"borderBottomWidth\">1px</property>\n <property name=\"borderLeftColor\">#00305E</property>\n <property name=\"borderLeftStyle\">solid</property>\n <property name=\"borderLeftWidth\">1px</property>\n <property name=\"borderRightColor\">#00305E</property>\n <property name=\"borderRightStyle\">solid</property>\n <property name=\"borderRightWidth\">1px</property>\n <property name=\"borderTopColor\">#00305E</property>\n <property name=\"borderTopStyle\">solid</property>\n <property name=\"borderTopWidth\">1px</property>\n <property name=\"paddingTop\">3px</property>\n <property name=\"paddingBottom\">3px</property>\n <property name=\"textAlign\">center</property>\n <property name=\"lineHeight\">143%</property>\n <property name=\"contentType\">html</property>\n <text-property name=\"content\"><![CDATA[Summary]]></text-property>\n </text>\n </cell>\n </row>\n </grid>\n <grid id=\"76\">\n <property name=\"marginBottom\">1px</property>\n <property name=\"width\">100%</property>\n <property name=\"dataSet\">75e0e90b-520a-424c-aa71-7658b22fc4e8</property>\n <list-property name=\"boundDataColumns\">\n <structure>\n <property name=\"name\">c9087be2-4986-4e06-9c35-1b0b97b91b9a</property>\n <expression name=\"expression\">dataSetRow[\"c9087be2-4986-4e06-9c35-1b0b97b91b9a\"]</expression>\n </structure>\n <structure>\n <property name=\"name\">db68f9d2-123b-4230-b520-8b68405b6e80</property>\n <expression name=\"expression\">dataSetRow[\"db68f9d2-123b-4230-b520-8b68405b6e80\"]</expression>\n </structure>\n <structure>\n <property name=\"name\">1c936da0-f467-4d43-baa1-6f1662d1fc93</property>\n <expression name=\"expression\">dataSetRow[\"1c936da0-f467-4d43-baa1-6f1662d1fc93\"]</expression>\n </structure>\n <structure>\n <property name=\"name\">d7bfd25b-f103-4c5e-a98f-1c73c26bf545</property>\n <expression name=\"expression\">dataSetRow[\"d7bfd25b-f103-4c5e-a98f-1c73c26bf545\"]</expression>\n </structure>\n <structure>\n <property name=\"name\">177f6163-aecc-47a7-9078-97e92c0208b3</property>\n <expression name=\"expression\">dataSetRow[\"177f6163-aecc-47a7-9078-97e92c0208b3\"]</expression>\n </structure>\n <structure>\n <property name=\"name\">f9fd7cb9-0897-4f6a-9931-97e9295113e7</property>\n <expression name=\"expression\">dataSetRow[\"f9fd7cb9-0897-4f6a-9931-97e9295113e7\"]</expression>\n </structure>\n <structure>\n <property name=\"name\">62df09de-1e60-4c91-a1dd-05a9ccb7a77d</property>\n <expression name=\"expression\">dataSetRow[\"62df09de-1e60-4c91-a1dd-05a9ccb7a77d\"]</expression>\n </structure>\n <structure>\n <property name=\"name\">5d51abbb-7730-4f69-8ad3-8800f266d125</property>\n <expression name=\"expression\">dataSetRow[\"5d51abbb-7730-4f69-8ad3-8800f266d125\"]</expression>\n </structure>\n <structure>\n <property name=\"name\">60afd61b-cebd-4865-b921-c086052340aa</property>\n <expression name=\"expression\">dataSetRow[\"60afd61b-cebd-4865-b921-c086052340aa\"]</expression>\n </structure>\n <structure>\n <property name=\"name\">efa95347-6369-4766-b0d0-e0d5a908f498</property>\n <expression name=\"expression\">dataSetRow[\"efa95347-6369-4766-b0d0-e0d5a908f498\"]</expression>\n </structure>\n <structure>\n <property name=\"name\">774fa8b7-4a5b-4731-b3be-8ce3e868a88e</property>\n <expression name=\"expression\">dataSetRow[\"774fa8b7-4a5b-4731-b3be-8ce3e868a88e\"]</expression>\n </structure>\n <structure>\n <property name=\"name\">4c6a3bed-da52-4ff2-a1e6-ebc731aff3cf</property>\n <expression name=\"expression\">dataSetRow[\"4c6a3bed-da52-4ff2-a1e6-ebc731aff3cf\"]</expression>\n </structure>\n <structure>\n <property name=\"name\">ffc2811f-dd15-4548-8994-81b161b6fb1e</property>\n <expression name=\"expression\">dataSetRow[\"ffc2811f-dd15-4548-8994-81b161b6fb1e\"]</expression>\n </structure>\n </list-property>\n <column id=\"77\">\n <property name=\"style\">style77</property>\n </column>\n <column id=\"78\">\n <property name=\"style\">style78</property>\n </column>\n <row id=\"79\">\n <cell id=\"80\">\n <label id=\"83\">\n <property name=\"fontSize\">12px</property>\n <property name=\"fontWeight\">bold</property>\n <property name=\"paddingTop\">1px</property>\n <property name=\"paddingBottom\">1px</property>\n <property name=\"lineHeight\">143%</property>\n <list-property name=\"visibility\">\n <structure>\n <property name=\"format\">all</property>\n <expression name=\"valueExpr\">row[\"d7bfd25b-f103-4c5e-a98f-1c73c26bf545\"] == \"false\" || (row[\"c9087be2-4986-4e06-9c35-1b0b97b91b9a\"] == \"true\" && row[\"1c936da0-f467-4d43-baa1-6f1662d1fc93\"] == \"false\")</expression>\n </structure>\n </list-property>\n <text-property name=\"text\">Hours Worked</text-property>\n </label>\n <data name=\"8e65bfdd-ae00-4e53-a0f2-ca53202a35bc\" id=\"84\">\n <property name=\"paddingBottom\">1px</property>\n <property name=\"lineHeight\">143%</property>\n <list-property name=\"visibility\">\n <structure>\n <property name=\"format\">all</property>\n <expression name=\"valueExpr\">row[\"d7bfd25b-f103-4c5e-a98f-1c73c26bf545\"] == \"false\" || (row[\"c9087be2-4986-4e06-9c35-1b0b97b91b9a\"] == \"true\" && row[\"1c936da0-f467-4d43-baa1-6f1662d1fc93\"] == \"false\")</expression>\n </structure>\n </list-property>\n <property name=\"resultSetColumn\">db68f9d2-123b-4230-b520-8b68405b6e80</property>\n </data>\n <label id=\"85\">\n <property name=\"backgroundColor\">#FBFCFD</property>\n <property name=\"fontSize\">12px</property>\n <property name=\"fontWeight\">bold</property>\n <property name=\"borderLeftColor\">#FBFCFD</property>\n <property name=\"borderLeftStyle\">solid</property>\n <property name=\"borderLeftWidth\">1px</property>\n <property name=\"borderRightColor\">#FBFCFD</property>\n <property name=\"borderRightStyle\">solid</property>\n <property name=\"borderRightWidth\">1px</property>\n <property name=\"borderTopColor\">#FBFCFD</property>\n <property name=\"borderTopStyle\">solid</property>\n <property name=\"borderTopWidth\">1px</property>\n <property name=\"paddingTop\">1px</property>\n <property name=\"paddingBottom\">1px</property>\n <property name=\"textAlign\">left</property>\n <property name=\"lineHeight\">143%</property>\n <list-property name=\"visibility\">\n <structure>\n <property name=\"format\">all</property>\n <expression name=\"valueExpr\">row[\"62df09de-1e60-4c91-a1dd-05a9ccb7a77d\"] == \"false\" || (row[\"c9087be2-4986-4e06-9c35-1b0b97b91b9a\"] == \"true\" && row[\"f9fd7cb9-0897-4f6a-9931-97e9295113e7\"] == \"false\")</expression>\n </structure>\n </list-property>\n <text-property name=\"text\">Overtime Approval Required?</text-property>\n </label>\n <data name=\"94678a87-0c76-4682-af1f-927fa499f9be\" id=\"86\">\n <property name=\"backgroundColor\">#FBFCFD</property>\n <property name=\"fontWeight\">normal</property>\n <property name=\"fontStyle\">normal</property>\n <property name=\"textUnderline\">none</property>\n <property name=\"borderBottomColor\">#FBFCFD</property>\n <property name=\"borderBottomStyle\">solid</property>\n <property name=\"borderBottomWidth\">1px</property>\n <property name=\"borderLeftColor\">#FBFCFD</property>\n <property name=\"borderLeftStyle\">solid</property>\n <property name=\"borderLeftWidth\">1px</property>\n <property name=\"borderRightColor\">#FBFCFD</property>\n <property name=\"borderRightStyle\">solid</property>\n <property name=\"borderRightWidth\">1px</property>\n <property name=\"paddingBottom\">1px</property>\n <property name=\"textAlign\">left</property>\n <property name=\"lineHeight\">143%</property>\n <list-property name=\"visibility\">\n <structure>\n <property name=\"format\">all</property>\n <expression name=\"valueExpr\">row[\"62df09de-1e60-4c91-a1dd-05a9ccb7a77d\"] == \"false\" || (row[\"c9087be2-4986-4e06-9c35-1b0b97b91b9a\"] == \"true\" && row[\"f9fd7cb9-0897-4f6a-9931-97e9295113e7\"] == \"false\")</expression>\n </structure>\n </list-property>\n <property name=\"resultSetColumn\">177f6163-aecc-47a7-9078-97e92c0208b3</property>\n </data>\n </cell>\n <cell id=\"81\">\n <label id=\"88\">\n <property name=\"fontSize\">12px</property>\n <property name=\"fontWeight\">bold</property>\n <property name=\"paddingTop\">1px</property>\n <property name=\"paddingBottom\">1px</property>\n <property name=\"lineHeight\">143%</property>\n <list-property name=\"visibility\">\n <structure>\n <property name=\"format\">all</property>\n <expression name=\"valueExpr\">row[\"efa95347-6369-4766-b0d0-e0d5a908f498\"] == \"false\" || (row[\"c9087be2-4986-4e06-9c35-1b0b97b91b9a\"] == \"true\" && row[\"60afd61b-cebd-4865-b921-c086052340aa\"] == \"false\")</expression>\n </structure>\n </list-property>\n <text-property name=\"text\">Regular Hours</text-property>\n </label>\n <data name=\"5a257a9b-82bb-4674-b307-7953f5d7181b\" id=\"89\">\n <property name=\"paddingBottom\">1px</property>\n <property name=\"lineHeight\">143%</property>\n <list-property name=\"visibility\">\n <structure>\n <property name=\"format\">all</property>\n <expression name=\"valueExpr\">row[\"efa95347-6369-4766-b0d0-e0d5a908f498\"] == \"false\" || (row[\"c9087be2-4986-4e06-9c35-1b0b97b91b9a\"] == \"true\" && row[\"60afd61b-cebd-4865-b921-c086052340aa\"] == \"false\")</expression>\n </structure>\n </list-property>\n <property name=\"resultSetColumn\">5d51abbb-7730-4f69-8ad3-8800f266d125</property>\n </data>\n <label id=\"90\">\n <property name=\"backgroundColor\">#FBFCFD</property>\n <property name=\"fontSize\">12px</property>\n <property name=\"fontWeight\">bold</property>\n <property name=\"borderLeftColor\">#FBFCFD</property>\n <property name=\"borderLeftStyle\">solid</property>\n <property name=\"borderLeftWidth\">1px</property>\n <property name=\"borderRightColor\">#FBFCFD</property>\n <property name=\"borderRightStyle\">solid</property>\n <property name=\"borderRightWidth\">1px</property>\n <property name=\"borderTopColor\">#FBFCFD</property>\n <property name=\"borderTopStyle\">solid</property>\n <property name=\"borderTopWidth\">1px</property>\n <property name=\"paddingTop\">1px</property>\n <property name=\"paddingBottom\">1px</property>\n <property name=\"textAlign\">left</property>\n <property name=\"lineHeight\">143%</property>\n <list-property name=\"visibility\">\n <structure>\n <property name=\"format\">all</property>\n <expression name=\"valueExpr\">row[\"ffc2811f-dd15-4548-8994-81b161b6fb1e\"] == \"false\" || (row[\"c9087be2-4986-4e06-9c35-1b0b97b91b9a\"] == \"true\" && row[\"4c6a3bed-da52-4ff2-a1e6-ebc731aff3cf\"] == \"false\")</expression>\n </structure>\n </list-property>\n <text-property name=\"text\">Overtime Hours</text-property>\n </label>\n <data name=\"c96bd0fe-aeca-4fc4-87cd-eb197a210bca\" id=\"91\">\n <property name=\"backgroundColor\">#FBFCFD</property>\n <property name=\"fontWeight\">normal</property>\n <property name=\"fontStyle\">normal</property>\n <property name=\"textUnderline\">none</property>\n <property name=\"borderBottomColor\">#FBFCFD</property>\n <property name=\"borderBottomStyle\">solid</property>\n <property name=\"borderBottomWidth\">1px</property>\n <property name=\"borderLeftColor\">#FBFCFD</property>\n <property name=\"borderLeftStyle\">solid</property>\n <property name=\"borderLeftWidth\">1px</property>\n <property name=\"borderRightColor\">#FBFCFD</property>\n <property name=\"borderRightStyle\">solid</property>\n <property name=\"borderRightWidth\">1px</property>\n <property name=\"paddingBottom\">1px</property>\n <property name=\"textAlign\">left</property>\n <property name=\"lineHeight\">143%</property>\n <list-property name=\"visibility\">\n <structure>\n <property name=\"format\">all</property>\n <expression name=\"valueExpr\">row[\"ffc2811f-dd15-4548-8994-81b161b6fb1e\"] == \"false\" || (row[\"c9087be2-4986-4e06-9c35-1b0b97b91b9a\"] == \"true\" && row[\"4c6a3bed-da52-4ff2-a1e6-ebc731aff3cf\"] == \"false\")</expression>\n </structure>\n </list-property>\n <property name=\"resultSetColumn\">774fa8b7-4a5b-4731-b3be-8ce3e868a88e</property>\n </data>\n </cell>\n </row>\n </grid>\n </body>\n</report>\n",
"created_at": "2021-09-22 19:34:17 UTC",
"updated_at": "2021-09-22 19:34:17 UTC",
"format": "PDF",
"default_emailed": true
}
Generate PDF with Report ID
To generate a specific Report from a Submission, use the List of Reports By Form API above to find the Report's ID, then use the Submission ID and Report ID together to request a PDF:
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
https://www.gocanvas.com/api/v3/submissions/52523/reports/32525 --output custom_pdf.pdf
require 'net/http'
username = "api.user@example.com"
password = "supersecretpassword"
endpoint = "https://www.gocanvas.com/api/v3/submissions/52523/reports/32525"
uri = URI.parse(endpoint)
req = Net::HTTP::Get.new(endpoint)
http = Net::HTTP.new(uri.host, uri.port)
http.read_timeout = 5
http.open_timeout = 5
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
const username = "api.user@example.com";
const password = "supersecretpassword";
fetch("https://www.gocanvas.com/api/v3/submissions/52523/reports/32525", {
method: "GET",
headers: {
Authorization: "Basic " + btoa(username + ":" + password)
},
})
.then(response => response.blob())
.then(report => console.log(report));
HTTP Request
GET https://www.gocanvas.com/api/v3/submissions/160504422/reports/8433
Request Parameters
| Parameter | Type | Description |
|---|---|---|
| submission_id | integer | The unique identifier of a Submission |
| report_id | integer | The unique identifier of the Report |
// response will be the pdf as a binary file
Locations
Use the Locations endpoint to retrieve the sequence of location events captured by Tracker. You can scope the results to a single mobile user or, by omitting the user_id, retrieve activity for every user in your company. Each event contains device metadata that helps you reconstruct where users were and what state the Tracker session was in.
The Location object
Example
{
"id": 456789012,
"user_id": 314159,
"site_id": null,
"event_type": "start_tracking",
"recorded_at": "2025-09-17T14:22:39Z",
"lat": 40.7128,
"lon": -74.006,
"gps_accuracy": 3.5,
"speed": -1.0,
"direction": 90.0,
"battery": 42,
"device_type": "android",
"version": "2.0.0 (789)",
"created_at": "2025-09-17T14:25:10Z",
"address": "123 Market Street",
"city": "Philadelphia",
"state": "PA",
"zip_code": "19107",
"country": "US"
}
Each entry represents a single point captured by the mobile tracker. The structure below reflects the serialized payload returned by the API.
Attributes
| Field | Type | Description |
|---|---|---|
| id | integer | Unique identifier of the location event. |
| user_id | integer | Identifier of the user associated with the event. |
| event_type | enum | Type of event. See Location Event Types for details. |
| site_id | integer | Identifier of the site associated with the event, if any. |
| recorded_at | string | Timestamp when the event was recorded on the device. |
| created_at | string | Timestamp when the event was saved to the database. |
| lat | number | Latitude in decimal degrees. |
| lon | number | Longitude in decimal degrees. |
| gps_accuracy | number | Horizontal accuracy in meters as reported by the device. |
| speed | number | Speed reported by the device in meters per second. A value of -1 indicates the device did not report speed. |
| direction | number | Bearing in degrees (0–360) reported by the device. |
| battery | integer | Device battery level percentage when the event was recorded. |
| device_type | string | Platform reported by the device (e.g. ios, android). |
| version | string | Mobile app version string reported by the device. |
| address* | string | Street address associated with the location event. |
| city* | string | City associated with the location event. |
| state* | string | State or province associated with the location event. |
| zip_code* | string | Postal code associated with the location event. |
| country* | string | Two-letter country code associated with the location event. |
* For the location event type, the denoted fields are returned with empty string values.
Location Event Types
| Value | Description |
|---|---|
location |
General location tracking event. |
start_tracking |
User taps “Start Tracking” in the app. |
stop_tracking |
User taps “Stop Tracking” in the app. |
planned_stop |
User has arrived within roughly 100 meters of a site. |
planned_stop_end |
Marks the end of a planned stop. |
planned_stop_created |
A new submission is created on mobile for a site (address). |
planned_stop_deleted |
A submission for a site is deleted from the device. |
unplanned_stop |
User has been idle (not moved beyond the configured threshold) for more than five minutes. |
unplanned_stop_end |
Marks the end of an unplanned stop. |
List all Locations
Retrieve the location events captured for a user within a limited date range. e.g a specific time during the day
Retrieve the location events captured for a user spanning multiple days
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X GET \
https://www.gocanvas.com/api/v3/tracker/locations?start_date=2025-09-17&end_date=2025-09-20
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
uri = URI("https://www.gocanvas.com/api/v3/tracker/locations?start_date=2025-09-17&end_date=2025-09-20")
req = Net::HTTP::Get.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
tracker_locations_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
fetch("https://www.gocanvas.com/api/v3/tracker/locations?start_date=2025-09-17&end_date=2025-09-20", {
method: "GET",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
}
})
.then(response => response.json())
.then(tracker_locations => console.log(tracker_locations));
HTTP Request
GET https://www.gocanvas.com/api/v3/tracker/locations
Query Parameters
| Parameter | Type | Description | Default |
|---|---|---|---|
| user_id | integer (optional) | Optional. Limit results to a specific user in your company. Omit to retrieve events for all users in your company. | |
| start_date* | string | Required. Beginning of the window to search. When only a date is provided, it is interpreted as 00:00:00 for that day. | |
| end_date* | string | Required. End of the window to search. When only a date is provided, it is interpreted as 23:59:59 for that day. | |
| page | integer (optional) | The page requested, see Pagination. | 1 |
| use_created_at | boolean (optional) | When true, filter and sort records using their created_at timestamp instead of recorded_at. Use this to pull all events that were uploaded during a window, even if they were recorded earlier. |
false |
* start_date and end_date must be in the ISO-8601 format, e.g. 2024-01-30, 2024-01-30T00:00:00, or 2024-01-30T00:00:00-04:00.
- The date range cannot exceed seven (7) days and
start_datemust not be later thanend_date. - Results are returned in chronological order by
recorded_atwhen a specificuser_idis provided. - When
user_idis omitted, results include all users in your company and are ordered byuser_id, then byrecorded_at. - If
use_created_at=true, filtering and ordering usecreated_atinstead ofrecorded_at, and the response includes both timestamps.
Site
A site represents a physical location where work is conducted. To create a site, the user must have authorization to create a site for the associated company.
The Site object
EXAMPLE
{
"id": 7,
"type": "site",
"name": "Site #1",
"address": "1234 Elm Street",
"city": "Springfield",
"state": "IL",
"zip_code": "62704",
"country": "US",
"code": "A1B2C3"
}
A Site requires a name to be created. The name is the only required field, and will be associated by default to the company of the User creating the site.
Customers and Sites
A Site can be associated with a single Customer. By passing a customer_id in the PATCH request for a site, you can assign the Site to the Customer. The Customer must be associated with the same company as the Site.
A Site can only be associated with one Customer. If the Customer doesn't have a Primary Site, the Site will be considered the Primary Site. If the Customer already has a Primary Site, the Site will be considered an Additional Site.
List all Sites
Users can view a list of all the Sites associated with their company.
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X GET \
https://www.gocanvas.com/api/v3/sites
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
uri = URI("https://www.gocanvas.com/api/v3/sites")
req = Net::HTTP::Get.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
sites_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
fetch("https://www.gocanvas.com/api/v3/sites", {
method: "GET",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
}
})
.then(response => response.json())
.then(sites => console.log(sites));
RESPONSE
[
{
"id": 7,
"type": "site",
"name": "Site #1",
"address": "1234 Elm Street",
"city": "Springfield",
"state": "IL",
"zip_code": "62704",
"country": "US",
"code": "A1B2C3"
},
{
"id": 8,
"type": "site",
"name": "Site #2",
"address": "5678 Oak Avenue",
"city": "Metropolis",
"state": "NY",
"zip_code": "10001",
"country": "US",
"code": "D4E5F6"
},
{
"id": 9,
"type": "site",
"name": "Site #3",
"address": "9101 Pine Lane",
"city": "Gotham",
"state": "NJ",
"zip_code": "07001",
"country": "US",
"code": "G7H8I9"
}
]
HTTP Request
GET https://www.gocanvas.com/api/v3/sites
Query Parameters
| Parameter | Type | Description | Default |
|---|---|---|---|
| page | integer (optional) | The page requested, see Pagination | 1 |
Retrieve a Site
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X GET \
https://www.gocanvas.com/api/v3/sites/7
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
uri = URI("https://www.gocanvas.com/api/v3/sites/7")
req = Net::HTTP::Get.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
site_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
fetch("https://www.gocanvas.com/api/v3/sites/7", {
method: "GET",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
}
})
.then(response => response.json())
.then(site => console.log(site));
Users can retrieve a Site by its ID.
HTTP Request
GET https://www.gocanvas.com/api/v3/sites/7
RESPONSE
{
"id": 7,
"type": "site",
"name": "Site #1",
"address": "1234 Elm Street",
"city": "Springfield",
"state": "IL",
"zip_code": "62704",
"country": "US",
"code": "A1B2C3"
}
Response Parameters
| Parameter | Type | Description |
|---|---|---|
| id | integer | The identifier for this exact Site |
| type | string | The type of object returned |
| name | string | A short string value for name of the Site |
| address | string | The address of the Site |
| city | string | The city of the Site |
| state | string | The state of the Site |
| zip_code | string | The zip code of the Site |
| country | string | The country abbreviation of the Site |
| code | string | An alpha numeric code to uniquely identify the Site |
Create a Site
To create a new Site, the POST body can be sent as JSON. The site name field is required.
BODY='{
name: "My new site",
address: "123 Park Place",
city: "New York",
state: "NY",
zip_code: "10001",
country: "US",
customer_id: 11
}'
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X POST \
-d $BODY \
https://www.gocanvas.com/api/v3/sites
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
request_body = {
name: "My new site",
address: "123 Park Place",
city: "New York",
state: "NY",
zip_code: "10001",
country: "US",
customer_id: 11
}
uri = URI("https://www.gocanvas.com/api/v3/sites")
json_request_body = request_body.to_json
req = Net::HTTP::Post.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
req.body = json_request_body
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
site_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
const data = {
name: "My new site",
address: "123 Park Place",
city: "New York",
state: "NY",
zip_code: "10001",
country: "US",
customer_id: 11
};
fetch("https://www.gocanvas.com/api/v3/sites", {
method: "POST",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(site => console.log(site));
RESPONSE
{
"id": 10,
"name": "My new site",
"address": "123 Park Place",
"city": "New York",
"state": "NY",
"zip_code": "10001",
"country": "US",
"code": "NEW123"
}
HTTP Request
POST https://www.gocanvas.com/api/v3/sites
Request Body Parameters
| Parameter | Type | Description |
|---|---|---|
| type | string | The type of object returned |
| name* | string | A short string value for name of the Site |
| address | string | The address of the Site |
| city | string | The city of the Site |
| state | string | The state of the Site |
| zip_code | string | The zip code of the Site |
| country** | string | The country abbreviation of the Site |
| code | string | An alpha numeric code to uniquely identify the Site |
| customer_id*** | integer | The ID of a Customer associated with the Company |
* required field
** must be 2 letter country abbreviation
*** The Customer can be associated with multiple Sites.
Update a Site
To update an existing Site, the PATCH request body can be sent as JSON.
BODY='{
"name": "Updated site name",
"customer_id": 11,
}'
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X PATCH \
-d $BODY \
https://www.gocanvas.com/api/v3/sites
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
request_body = {
"name": "Updated site name",
"customer_id": 11,
}
uri = URI("https://www.gocanvas.com/api/v3/sites")
json_request_body = request_body.to_json
req = Net::HTTP::Patch.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
req.body = json_request_body
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
site_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
const data = {
"name": "Updated site name",
"customer_id": 11,
};
fetch("https://www.gocanvas.com/api/v3/sites", {
method: "PATCH",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(site => console.log(site));
RESPONSE
{
"message": "Site updated successfully"
}
HTTP Request
PATCH https://www.gocanvas.com/api/v3/sites/14
Request Body Parameters
| Parameter | Type | Description |
|---|---|---|
| type | string | The type of object returned |
| name* | string | A short string value for name of the Site |
| address | string | The address of the Site |
| city | string | The city of the Site |
| state | string | The state of the Site |
| zip_code | string | The zip code of the Site |
| country** | string | The country abbreviation of the Site |
| code | string | An alpha numeric code to uniquely identify the Site |
| customer_id*** | integer | The ID of a Customer associated with the Company |
* required field
** must be 2 letter country abbreviation
*** The Customer can be associated with multiple Sites.
Delete a Site
A Site can be deleted with a DELETE request.
By default, the DELETE request will soft-delete the site, which preserves the Site data but hides it from the web views. To permanently delete a Site, use the hard_delete=true parameter, e.g. DELETE https://www.gocanvas.com/api/v3/sites/10?hard_delete=true.
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X DELETE \
https://www.gocanvas.com/api/v3/sites/10
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
uri = URI("https://www.gocanvas.com/api/v3/sites/10")
req = Net::HTTP::Delete.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
site_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
fetch("https://www.gocanvas.com/api/v3/sites/10", {
method: "DELETE",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
}
})
.then(response => response.json())
.then(site => console.log(site));
RESPONSE
{
"message": "Site 10 has been soft deleted successfully"
}
HTTP Request
DELETE https://www.gocanvas.com/api/v3/sites/14
Request Parameters
| Parameter | Type | Description |
|---|---|---|
| hard_delete* | boolean | Will hard delete the Site record when set to true |
* This is an optional URL parameter. If not provided, the Site will be soft deleted.
Submission
A Submission is a set of responses to a Form. Submissions are how GoCanvas clients transmit collected data.
The Submission object
EXAMPLE
{
"id": 132394,
"type": "submission",
"client_guid": "156899451178900",
"form_id": 346127,
"submission_number": "00004",
"submission_name": null,
"created_at": "2023-05-16 00:47:51 UTC",
"device_guid": "BB5E03A7-560C-4419-A99E-5388338C157C",
"form": {
"id": 346127,
"type": "form",
"name": "Basic Form",
"description": null,
"status": "published",
"version": 1,
"root_version_id": 346127
},
"department": {
"id": 19134,
"type": "department",
"name": "First Department",
"description": null
}
}
Submissions must reference a Form. Clients must also generate a globally unique identifier (GUID) to allow GoCanvas servers to identify the submission and prevent duplicates. Responses within a Submission are the answers to questions or the responses to prompts against the Form.
For retrieving a form's entries used for Creating a Submission, see the minimal Form format documentation.
List all Submissions
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X GET \
https://www.gocanvas.com/api/v3/submissions?form_id=346127
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
uri = URI("https://www.gocanvas.com/api/v3/submissions?form_id=346127")
req = Net::HTTP::Get.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
submissions_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
fetch("https://www.gocanvas.com/api/v3/submissions?form_id=346127", {
method: "GET",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
}
})
.then(response => response.json())
.then(submissions => console.log(submissions));
Users can view and filter a list of Submissions.
RESPONSE
[
{
"id": 6625009,
"type": "submission",
"client_guid": "049c1544-1ab5-41a1-a249-b8811cfa335c",
"form_id": 346127,
"submission_number": "00003",
"submission_name": null,
"created_at": "2023-10-13T14:10:34Z",
"revision": true,
"revised_at": "2025-04-09T16:43:57Z",
"department_id": 13521,
"user_id": 20079,
"status": "completed",
"device_guid": "BB5E03A7-560C-4419-A99E-5388338C157C"
},
{
"id": 6624756,
"type": "submission",
"client_guid": "19b24c19-2247-4e05-92b1-0fd7f7510336",
"form_id": 346127,
"submission_number": "00002",
"submission_name": null,
"created_at": "2023-10-09T18:00:17Z",
"revision": false,
"revised_at": null,
"department_id": 13521,
"user_id": 20079,
"status": "completed",
"device_guid": "BB5E03A7-560C-4419-A99E-5388338C157C"
},
{
"id": 6623946,
"type": "submission",
"client_guid": "d97c09ed-ce49-4a76-bcad-01508d4b6576",
"form_id": 346127,
"submission_number": "00001",
"submission_name": null,
"created_at": "2023-10-09T17:59:31Z",
"revision": false,
"revised_at": null,
"department_id": 13521,
"user_id": 20079,
"status": "completed",
"device_guid": "BB5E03A7-560C-4419-A99E-5388338C157C"
}
]
HTTP Request
GET https://www.gocanvas.com/api/v3/submissions?form_id=346127
Query Parameters
| Parameter | Type | Description | Default |
|---|---|---|---|
| page | integer (optional) | The page requested, see Pagination | 1 |
| form_id* | integer | The identifier for the Form the associated with the Submission | |
| department_id** | integer (optional) | The identifier for the Department associated with the Submission | (default department**) |
| user_id | integer (optional) | The identifier for the User who created the Submission | |
| status | enum (optional) | The status filter of the Submission. Can be all, completed, deleted, in-progress, overdue, rejected, handed-off, assigned, unassigned, custom, saved-to-cloud, or unfinished. |
completed |
| hand_off | string (optional) | The name of the workflow handoff state to filter Submissions by. Required for the handed-off status. Learn more about GoCanvas Workflows. |
|
| custom_status | string (optional) | The label of the custom status to filter Submissions by. Required for the custom status. Learn more about GoCanvas custom submission statuses. |
|
| start_date*** | datetime (optional) | A DateTime value for the beginning bounds to search the Submissions' created_at |
|
| end_date*** | datetime (optional) | A DateTime value for the ending bounds to search the Submissions' created_at |
* The provided form_id will match all versions of the Form for convenience.
** If no department_id is provided, the User's default department will be used.
*** start_date and end_date must be in the ISO-8601 format, e.g. 2024-01-30 or 2024-01-30T23:59:59 or 2024-01-30T23:59:59-04:00.
Submission Status Filters
| Status | Description |
|---|---|
all |
Includes all submissions, regardless of their status. |
completed |
Submissions that have been finalized and marked as complete. |
deleted |
Submissions that have been deleted. |
in-progress |
Submissions that are not yet completed. This is a superset of other statuses including statuses such as overdue, rejected, handed-off, assigned, and unassigned. |
overdue |
Submissions for Forms using Follow-Ups that are incomplete and past their scheduled due date. |
rejected |
Submissions for Forms using Workflow that have been rejected in a handoff. |
handed-off |
Submissions for Forms using Workflow that have been handed off in a handoff. Requires the hand_off parameter. |
assigned |
Submissions for Forms using Assignments that are assigned to a user. |
unassigned |
Submissions for Forms using Assignments that are unassigned. |
custom |
Submissions for Forms using Custom Statuses. Requires the custom_status parameter. |
saved-to-cloud |
Submissions that have been saved to the cloud. |
unfinished |
Submissions which are Unfinished in the process of uploading from the client. |
Create a basic Submission
A basic text-only submission can be sent as JSON in the Request Body with a request header of Content-Type: application/json.
Submissions with media fields (photos, videos, or attachments) must use form-data, with a request header of Content-Type: multipart/form-data, as detailed in the Create a Submission with Media heading.
BODY='{
guid: "c2703768-f672-42e9-a307-77abede123462",
department_id: 19134,
form: {
id: 346127,
version: 1
},
responses: [
{ "entry_id": 3777059, "displayed": true, "value": "Jane" },
{ "entry_id": 3777060, "displayed": true, "value": "Doe" },
{ "entry_id": 3777061, "displayed": true, "value": "Main Street" },
{ "entry_id": 3777062, "displayed": true, "value": "Boca Raton" },
{ "entry_id": 3777063, "displayed": true, "value": "FL" },
{ "entry_id": 3777064, "displayed": true, "value": "23456" },
],
recipients: ["recipient.user@example.com"]
}'
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X POST \
-d $BODY \
https://www.gocanvas.com/api/v3/submissions
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
request_body = {
guid: "c2703768-f672-42e9-a307-77abede123462",
department_id: 19134,
form: {
id: 346127,
version: 1
},
responses: [
{ "entry_id": 3777059, "displayed": true, "value": "Jane" },
{ "entry_id": 3777060, "displayed": true, "value": "Doe" },
{ "entry_id": 3777061, "displayed": true, "value": "Main Street" },
{ "entry_id": 3777062, "displayed": true, "value": "Boca Raton" },
{ "entry_id": 3777063, "displayed": true, "value": "FL" },
{ "entry_id": 3777064, "displayed": true, "value": "23456" },
],
recipients: ["recipient.user@example.com"]
}
uri = URI("https://www.gocanvas.com/api/v3/submissions")
json_request_body = request_body.to_json
req = Net::HTTP::Post.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
req.body = json_request_body
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
submission_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
const data = {
guid: "c2703768-f672-42e9-a307-77abede123462",
department_id: 19134,
form: {
id: 346127,
version: 1
},
responses: [
{ "entry_id": 3777059, "displayed": true, "value": "Jane" },
{ "entry_id": 3777060, "displayed": true, "value": "Doe" },
{ "entry_id": 3777061, "displayed": true, "value": "Main Street" },
{ "entry_id": 3777062, "displayed": true, "value": "Boca Raton" },
{ "entry_id": 3777063, "displayed": true, "value": "FL" },
{ "entry_id": 3777064, "displayed": true, "value": "23456" },
],
recipients: ["recipient.user@example.com"]
};
fetch("https://www.gocanvas.com/api/v3/submissions", {
method: "POST",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(submission => console.log(submission));
RESPONSE
{
"id": 132394,
"type": "submission",
"client_guid": "156899451178900",
"form_id": 346127,
"submission_number": "00004",
"submission_name": null,
"created_at": "2023-05-16 00:47:51 UTC",
"device_guid": "BB5E03A7-560C-4419-A99E-5388338C157C",
"form": {
"id": 346127,
"type": "form",
"name": "Basic Form",
"description": null,
"status": "published",
"version": 1,
"root_version_id": 346127
},
"department": {
"id": 19134,
"type": "department",
"name": "First Department",
"description": null
}
}
HTTP Request
POST https://www.gocanvas.com/api/v3/submissions
Request Body Parameters
| Parameter | Type | Description |
|---|---|---|
| body | hash | The JSON Submission body |
| guid | string | A globally unique identifier used to prevent duplicates |
| department_id§ | integer | The identifier to specify a Department. |
| form | hash | The Form to create the Submission to |
| form.id* | integer | The identifier to specify a Form |
| form.guid* | string | The identifier to specify a Form |
| form.version** | integer | The identifier to specify a Form |
| responses[] | array | A collection of responses against Form Entries |
| responses[].entry_id | integer | The unique identifier of an Entry |
| responses[].entry_guid | string | The unique guid of an Entry. An alternative to entry_id |
| responses[].displayed | boolean | Whether this Entry is displayed for user entry or calculated |
| responses[].value | string | The response data for the Entry |
| responses[].multi_key† | string (optional) | Reference to the looped value |
| responses[].content_guid‡ | string (optional) | A guid indicating an image or file will be uploaded |
content_guid‡ |
file (optional) | An image or file to be uploaded |
| recipients | array (optional) | An array of email addresses to send a copy of the Submission to |
* Either form.id or form.guid is required to identify the Form.
** When form.guid is specified, specifying a form.version is recommended.
† Only required for looped forms
‡ Only required for Media uploads, the attached file's guid must match with a responses[].content_guid value
§ Only required for forms that are shared across multiple departments, if one is not provided it will default to the form's original department
Create Submission with loops
Loop screens can be configured when designing a form, for information on how to configure loop screens, please refer to Loop Screens. Responses in loop screens use the multi_key field to identify the looped value.
BODY='{
guid: "f4c7a1d9-8b1e-4d7f-9d5c-2d9e6b4e5a8f",
department_id: 13521,
form: {
id: 4639578,
version: 1,
},
responses: [
{ "entry_id": 543728076, "displayed": true, "value": "api.user@example.com" },
{ "entry_id": 543728077, "displayed": true, "value": "Smith Kane" },
{ "entry_id": 543728078, "displayed": true, "value": "555-414-1234" },
{ "entry_id": 543728080, "displayed": true, "value": "Priority" },
{ "entry_id": 543728079, "displayed": true, "multi_key": "Priority", "value": "High" },
{ "entry_id": 543728080, "displayed": true, "value": "Service Requested" },
{ "entry_id": 543728079, "displayed": true, "multi_key": "Service Requested", "value": "Painting" }
],
recipients: ["recipient.user@example.com"]
}'
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X POST \
-d $BODY \
https://www.gocanvas.com/api/v3/submissions
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
request_body = {
guid: "f4c7a1d9-8b1e-4d7f-9d5c-2d9e6b4e5a8f",
department_id: 13521,
form: {
id: 4639578,
version: 1,
},
responses: [
{ "entry_id": 543728076, "displayed": true, "value": "api.user@example.com" },
{ "entry_id": 543728077, "displayed": true, "value": "Smith Kane" },
{ "entry_id": 543728078, "displayed": true, "value": "555-414-1234" },
{ "entry_id": 543728080, "displayed": true, "value": "Priority" },
{ "entry_id": 543728079, "displayed": true, "multi_key": "Priority", "value": "High" },
{ "entry_id": 543728080, "displayed": true, "value": "Service Requested" },
{ "entry_id": 543728079, "displayed": true, "multi_key": "Service Requested", "value": "Painting" }
],
recipients: ["recipient.user@example.com"]
}
uri = URI("https://www.gocanvas.com/api/v3/submissions")
json_request_body = request_body.to_json
req = Net::HTTP::Post.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
req.body = json_request_body
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
submission_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
const data = {
guid: "f4c7a1d9-8b1e-4d7f-9d5c-2d9e6b4e5a8f",
department_id: 13521,
form: {
id: 4639578,
version: 1,
},
responses: [
{ "entry_id": 543728076, "displayed": true, "value": "api.user@example.com" },
{ "entry_id": 543728077, "displayed": true, "value": "Smith Kane" },
{ "entry_id": 543728078, "displayed": true, "value": "555-414-1234" },
{ "entry_id": 543728080, "displayed": true, "value": "Priority" },
{ "entry_id": 543728079, "displayed": true, "multi_key": "Priority", "value": "High" },
{ "entry_id": 543728080, "displayed": true, "value": "Service Requested" },
{ "entry_id": 543728079, "displayed": true, "multi_key": "Service Requested", "value": "Painting" }
],
recipients: ["recipient.user@example.com"]
};
fetch("https://www.gocanvas.com/api/v3/submissions", {
method: "POST",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(submission => console.log(submission));
RESPONSE
{
"id": 145654,
"type": "submission",
"client_guid": "134278987678900",
"form_id": 4639578,
"submission_number": "00001",
"submission_name": null,
"created_at": "2023-05-16 00:47:51 UTC",
"device_guid": "BB5E03A7-560C-4419-A99E-5388338C157C",
"form": {
"id": 4639578,
"type": "form",
"name": "Looped Screen Form",
"description": null,
"status": "published",
"version": 1,
"root_version_id": 4639578
},
"department": {
"id": 13521,
"type": "department",
"name": "First Department",
"description": null
}
}
HTTP Request
POST https://www.gocanvas.com/api/v3/submissions
Request Body Parameters
| Parameter | Type | Description |
|---|---|---|
| body | hash | The JSON Submission body |
| guid | string | A globally unique identifier used to prevent duplicates |
| department_id§ | integer | The identifier to specify a Department. |
| form | hash | The Form to create the Submission to |
| form.id* | integer | The identifier to specify a Form |
| form.guid* | string | The identifier to specify a Form |
| form.version** | integer | The identifier to specify a Form |
| responses[] | array | A collection of responses against Form Entries |
| responses[].entry_id | integer | The unique identifier of an Entry |
| responses[].entry_guid | string | The unique guid of an Entry. An alternative to entry_id |
| responses[].displayed | boolean | Whether this Entry is displayed for user entry or calculated |
| responses[].value | string | The response data for the Entry |
| responses[].multi_key† | string (optional) | Reference to the looped value |
| responses[].content_guid‡ | string (optional) | A guid indicating an image or file will be uploaded |
content_guid‡ |
file (optional) | An image or file to be uploaded |
| recipients | array (optional) | An array of email addresses to send a copy of the Submission to |
* Either form.id or form.guid is required to identify the Form.
** When form.guid is specified, specifying a form.version is recommended.
† Only required for looped forms
‡ Only required for Media uploads, the attached file's guid must match with a responses[].content_guid value
§ Only required for forms that are shared across multiple departments, if one is not provided it will default to the form's original department
Create Submission with media
Submissions with media fields (photos, videos, or attachments) require a multipart/form-data content type to upload a file associated with the submission. A content_guid for the response is necessary to link the uploaded file with its associated response, see Request Body Parameters below for more information.
curl -X POST \
-u 'api.user@example.com:supersecretpassword' \
--location 'https://www.gocanvas.com/api/v3/submissions' \
--form 'guid="c2703768-f672-42e9-a307-77abede123462"' \
--form 'department_id="19134"' \
--form 'form="{\"id\": 346127, \"version\": 1}"' \
--form 'responses="[
{\"entry_id\": 3777059, \"displayed\": true, \"value\": \"Jane\"},
{\"entry_id\": 3777060, \"displayed\": true, \"value\": \"Doe\"},
{\"entry_id\": 3777061, \"displayed\": true, \"content_guid\": \"c3984328-f672-42e9-a307-77abede123462\"}
]"' \
--form '{{c3984328-f672-42e9-a307-77abede123462}}=@"/path/to/image.jpg"'
require 'net/http'
require 'uri'
require 'json'
uri = URI.parse('https://www.gocanvas.com/api/v3/submissions')
request = Net::HTTP::Post.new(uri)
request.basic_auth('api.user@example.com', 'supersecretpassword')
form_data = {
guid: 'c2703768-f672-42e9-a307-77abede123462',
department_id: 19134,
form: { id: 346127, version: 1 }.to_json,
responses: [
{ entry_id: 3777059, displayed: true, value: 'Jane' },
{ entry_id: 3777060, displayed: true, value: 'Doe' },
{ entry_id: 3777061, displayed: true, content_guid: 'c3984328-f672-42e9-a307-77abede123462' }
].to_json
}
# Note: For file uploads, you may need to handle it differently as multipart upload
# This is a simplified version
form_data["c3984328-f672-42e9-a307-77abede123462"] = File.open('/path/to/image.jpg', 'rb')
request.set_form form_data, 'multipart/form-data'
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.request(request)
end
puts response.body
const form = new FormData();
form.append('guid', 'c2703768-f672-42e9-a307-77abede123462');
form.append('department_id', '19134');
form.append('form', JSON.stringify({ id: 346127, version: 1 }));
form.append('responses', JSON.stringify([
{ entry_id: 3777059, displayed: true, value: 'Jane' },
{ entry_id: 3777060, displayed: true, value: 'Doe' },
{ entry_id: 3777061, displayed: true, content_guid: 'c3984328-f672-42e9-a307-77abede123462' }
]));
form.append('c3984328-f672-42e9-a307-77abede123462', fs.createReadStream('/path/to/image.jpg'));
fetch('https://www.gocanvas.com/api/v3/submissions', {
method: 'POST',
headers: {
'Authorization': 'Basic ' + btoa(username + ':' + password),
'Content-Type': 'application/json'
},
body: form
}).then((response) => response.json())
.then((data => console.log(data) ))
RESPONSE
{
"id": 132394,
"type": "submission",
"client_guid": "156899451178900",
"form_id": 346127,
"submission_number": "00004",
"submission_name": null,
"created_at": "2023-05-16 00:47:51 UTC",
"device_guid": "BB5E03A7-560C-4419-A99E-5388338C157C",
"form": {
"id": 346127,
"type": "form",
"name": "Basic Form",
"description": null,
"status": "published",
"version": 1,
"root_version_id": 346127
},
"department": {
"id": 19134,
"type": "department",
"name": "First Department",
"description": null
}
}
HTTP Request
POST https://www.gocanvas.com/api/v3/submissions
Request Body Parameters
| Parameter | Type | Description |
|---|---|---|
| body | hash | The JSON Submission body |
| guid | string | A globally unique identifier used to prevent duplicates |
| department_id§ | integer | The identifier to specify a Department. |
| form | hash | The Form to create the Submission to |
| form.id* | integer | The identifier to specify a Form |
| form.guid* | string | The identifier to specify a Form |
| form.version** | integer | The identifier to specify a Form |
| responses[] | array | A collection of responses against Form Entries |
| responses[].entry_id | integer | The unique identifier of an Entry |
| responses[].entry_guid | string | The unique guid of an Entry. An alternative to entry_id |
| responses[].displayed | boolean | Whether this Entry is displayed for user entry or calculated |
| responses[].value | string | The response data for the Entry |
| responses[].multi_key† | string (optional) | Reference to the looped value |
| responses[].content_guid‡ | string (optional) | A guid indicating an image or file will be uploaded |
content_guid‡ |
file (optional) | An image or file to be uploaded |
| recipients | array (optional) | An array of email addresses to send a copy of the Submission to |
* Either form.id or form.guid is required to identify the Form.
** When form.guid is specified, specifying a form.version is recommended.
† Only required for looped forms
‡ Only required for Media uploads, the attached file's guid must match with a responses[].content_guid value
§ Only required for forms that are shared across multiple departments, if one is not provided it will default to the form's original department
Retrieve a Submission
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X GET \
https://www.gocanvas.com/api/v3/submissions/691911
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
uri = URI("https://www.gocanvas.com/api/v3/submissions/691911")
req = Net::HTTP::Get.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
submission_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
fetch("https://www.gocanvas.com/api/v3/submissions/691911", {
method: "GET",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
}
})
.then(response => response.json())
.then(submission => console.log(submission));
Users can retrieve a Submission by its ID.
HTTP Request
GET https://www.gocanvas.com/api/v3/submissions/691911
RESPONSE
{
"id": 691911,
"type": "submission",
"client_guid": "02ED5FB2-9C61-4F18-AB17-543547DF899B",
"form_id": 81700,
"submission_number": "00020",
"submission_name": null,
"created_at": "2024-05-16 17:27:57 UTC",
"revision": true,
"revised_at": "2025-04-09T16:43:57Z",
"department_id": 27722,
"user_id": 20079,
"status": "completed",
"device_guid": "BB5E03A7-560C-4419-A99E-5388338C157C",
"responses": [
{
"id": 641486,
"type": "Text Box",
"entry_id": 3791371,
"value": "Example text value",
"label": "Destination",
"export_label": null,
"displayed": true
},
{
"id": 641509,
"type": "Text Box",
"entry_id": 3791565,
"value": "",
"label": "Color",
"export_label": null,
"displayed": false
},
{
"id": 641488,
"type": "Integer",
"entry_id": 3791373,
"value": "23",
"label": "Number",
"export_label": null,
"displayed": true
},
{
"id": 641489,
"type": "Signature",
"entry_id": 3791374,
"value": null,
"label": "Approval Signature",
"export_label": null,
"displayed": true
},
{
"id": 641490,
"type": "Image Capture",
"entry_id": 3791375,
"value": "Binary data is not displayed",
"label": "New Photo",
"export_label": null,
"displayed": true
},
{
"id": 641491,
"type": "Value List",
"entry_id": 3791350,
"value": "April",
"label": "Select Month",
"export_label": null,
"displayed": true
},
{
"id": 641492,
"type": "Text Box",
"entry_id": 3791348,
"value": "John",
"label": "First Name",
"export_label": null,
"multi_key": "April",
"displayed": true
},
{
"id": 641493,
"type": "Text Box",
"entry_id": 3791349,
"value": "Smith",
"label": "Last Name",
"export_label": null,
"multi_key": "April",
"displayed": true
}
]
}
Response Parameters
| Parameter | Type | Description |
|---|---|---|
| id | integer | The identifier for this exact Submission |
| client_guid | string | A globally unique identifier used to prevent duplicates |
| form_id | integer | The version number of the Form that the Submission was created with |
| submission_number * | string | A Submission number generated based on the Form's submission numbering rules |
| revision ** | boolean | true indicates that the Submission has revisions |
| revised_at ** | datetime | The date and time when the Submission was last revised; null if it has not been revised |
| department_id | integer | The identifier for the Department associated with the Submission |
| user_id | integer | The unique identifier for the user who made the Submission |
| status | string | The status of the Submission. |
| device_guid | string | The unique identifier for the device that made the Submission |
| responses[] | array | A collection values for Entries |
| responses[].id | integer | The unique identifier of a Response |
| responses[].type | string | The data type of the Entry |
| responses[].entry_id | integer | The unique identifier of an Entry |
| responses[].value *** | string | The response data for the Entry |
| responses[].label | string | The label of the Entry |
| responses[].export_label | string | The export label of the Entry. |
| responses[].displayed | boolean | true indicates that this Entry is displayed for user entry, while false indicates that it was not displayed based on a condition |
| responses[].multi_key | string (optional) | Reference to the looped value |
* More information on Submission Numbering can be found here
** When the revision field is true and revised_at is not null, additional information about the Submission Revisions can be retrieved from List of Revisions by Submission
*** Entries that are media fields (photos, videos, or attachments), return "Binary data is not displayed" if data was captured and null if it was not. Use the Retrieve a Value method to download the media field value.
Submission Statuses
| Status | Description |
|---|---|
completed |
Submission has been finalized and marked as complete. |
deleted |
Submission has been deleted. |
overdue |
Submission for Forms using Follow-Ups that is incomplete and past its scheduled due date. |
rejected |
Submission for Forms using Workflow that has been rejected in a handoff. |
handed-off |
Submission for Forms using Workflow that has been handed off in a handoff. |
assigned |
Submission for Forms using Assignments that is assigned to a user. |
unassigned |
Submission for Forms using Assignments that is unassigned. |
saved-to-cloud |
Submission that has been saved to the cloud. |
unfinished |
Submission that is Unfinished in the process of uploading from the client. |
| (User defined) | Submission status when using Forms using Custom Statuses may be user-defined values. |
Retrieve a Submission by GUID
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X GET \
https://www.gocanvas.com/api/v3/submissions/02ED5FB2-9C61-4F18-AB17-543547DF899B
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
uri = URI("https://www.gocanvas.com/api/v3/submissions/02ED5FB2-9C61-4F18-AB17-543547DF899B")
req = Net::HTTP::Get.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
submission_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
fetch("https://www.gocanvas.com/api/v3/submissions/02ED5FB2-9C61-4F18-AB17-543547DF899B", {
method: "GET",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
}
})
.then(response => response.json())
.then(submission => console.log(submission));
Users can retrieve a Submission by its GUID.
HTTP Request
GET https://www.gocanvas.com/api/v3/submissions/02ED5FB2-9C61-4F18-AB17-543547DF899B
RESPONSE
{
"id": 691911,
"type": "submission",
"client_guid": "02ED5FB2-9C61-4F18-AB17-543547DF899B",
"form_id": 81700,
"submission_number": "00020",
"submission_name": null,
"created_at": "2024-05-16 17:27:57 UTC",
"revision": true,
"revised_at": "2025-04-09T16:43:57Z",
"department_id": 27722,
"user_id": 20079,
"status": "completed",
"device_guid": "BB5E03A7-560C-4419-A99E-5388338C157C",
"responses": [
{
"id": 641486,
"type": "Text Box",
"entry_id": 3791371,
"value": "Example text value",
"label": "Destination",
"export_label": null,
"displayed": true
},
{
"id": 641509,
"type": "Text Box",
"entry_id": 3791565,
"value": "",
"label": "Color",
"export_label": null,
"displayed": false
},
{
"id": 641488,
"type": "Integer",
"entry_id": 3791373,
"value": "23",
"label": "Number",
"export_label": null,
"displayed": true
},
{
"id": 641489,
"type": "Signature",
"entry_id": 3791374,
"value": null,
"label": "Approval Signature",
"export_label": null,
"displayed": true
},
{
"id": 641490,
"type": "Image Capture",
"entry_id": 3791375,
"value": "Binary data is not displayed",
"label": "New Photo",
"export_label": null,
"displayed": true
},
{
"id": 641491,
"type": "Value List",
"entry_id": 3791350,
"value": "April",
"label": "Select Month",
"export_label": null,
"displayed": true
},
{
"id": 641492,
"type": "Text Box",
"entry_id": 3791348,
"value": "John",
"label": "First Name",
"export_label": null,
"multi_key": "April",
"displayed": true
},
{
"id": 641493,
"type": "Text Box",
"entry_id": 3791349,
"value": "Smith",
"label": "Last Name",
"export_label": null,
"multi_key": "April",
"displayed": true
}
]
}
Response Parameters
| Parameter | Type | Description |
|---|---|---|
| id | integer | The identifier for this exact Submission |
| client_guid | string | A globally unique identifier used to prevent duplicates |
| form_id | integer | The version number of the Form that the Submission was created with |
| submission_number * | string | A Submission number generated based on the Form's submission numbering rules |
| revision ** | boolean | true indicates that the Submission has revisions |
| revised_at ** | datetime | The date and time when the Submission was last revised; null if it has not been revised |
| department_id | integer | The identifier for the Department associated with the Submission |
| user_id | integer | The unique identifier for the user who made the Submission |
| status | string | The status of the Submission. |
| device_guid | string | The unique identifier for the device that made the Submission |
| responses[] | array | A collection values for Entries |
| responses[].id | integer | The unique identifier of a Response |
| responses[].type | string | The data type of the Entry |
| responses[].entry_id | integer | The unique identifier of an Entry |
| responses[].value *** | string | The response data for the Entry |
| responses[].label | string | The label of the Entry |
| responses[].export_label | string | The export label of the Entry. |
| responses[].displayed | boolean | true indicates that this Entry is displayed for user entry, while false indicates that it was not displayed based on a condition |
| responses[].multi_key | string (optional) | Reference to the looped value |
* More information on Submission Numbering can be found here
** When the revision field is true and revised_at is not null, additional information about the Submission Revisions can be retrieved from List of Revisions by Submission
*** Entries that are media fields (photos, videos, or attachments), return "Binary data is not displayed" if data was captured and null if it was not. Use the Retrieve a Value method to download the media field value.
Submission Statuses
| Status | Description |
|---|---|
completed |
Submission has been finalized and marked as complete. |
deleted |
Submission has been deleted. |
overdue |
Submission for Forms using Follow-Ups that is incomplete and past its scheduled due date. |
rejected |
Submission for Forms using Workflow that has been rejected in a handoff. |
handed-off |
Submission for Forms using Workflow that has been handed off in a handoff. |
assigned |
Submission for Forms using Assignments that is assigned to a user. |
unassigned |
Submission for Forms using Assignments that is unassigned. |
saved-to-cloud |
Submission that has been saved to the cloud. |
unfinished |
Submission that is Unfinished in the process of uploading from the client. |
| (User defined) | Submission status when using Forms using Custom Statuses may be user-defined values. |
List of Revisions by Submission
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X GET \
https://www.gocanvas.com/api/v3/submissions/691911/revisions
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
uri = URI("https://www.gocanvas.com/api/v3/submissions/691911/revisions")
req = Net::HTTP::Get.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
submission_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
fetch("https://www.gocanvas.com/api/v3/submissions/691911/revisions", {
method: "GET",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
}
})
.then(response => response.json())
.then(submission => console.log(submission));
Users can retrieve the revisions for a specific Submission by its ID. Revisions provide a history of changes made to the values within the Submission.
The oldest revision is generated at the time of the first submission edit and corresponds to the original submission. It is assigned a revision_number of 0. Submissions with no revisions will return an empty array.
Revisions are returned in reverse chronological order, with the most recent revision appearing first in the list.
HTTP Request
GET https://www.gocanvas.com/api/v3/submissions/691911/revisions
RESPONSE
[
{
"id": 1002806,
"type": "value_revision",
"revision_number": 2,
"user_id": 114,
"user_email": "johndoe@example.com",
"entry_id": 44890,
"value_id": 52089,
"previous_data": "Window repair",
"new_data": "Fence repair",
"created_at": "2025-04-09T16:43:89Z"
},
{
"id": 1002805,
"type": "value_revision",
"revision_number": 1,
"user_id": 114,
"user_email": "johndoe@example.com",
"entry_id": 44890,
"value_id": 52089,
"previous_data": "Roof repair",
"new_data": "Window repair",
"created_at": "2025-04-09T16:17:12Z"
},
{
"id": 1002800,
"type": "value_revision",
"revision_number": 0,
"user_id": 114,
"user_email": "johndoe@example.com",
"entry_id": null,
"value_id": null,
"previous_data": null,
"new_data": null,
"created_at": "2025-01-08T12:34:57Z"
}
]
Response Parameters
| Parameter | Type | Description |
|---|---|---|
| id | integer | The unique identifier for the revision |
| type | string | The type of object returned |
| revision_number | integer | The revision number, indicating the order of changes |
| user_id | integer | The unique identifier for the user who made the revision |
| user_email | string | The email of the user who made the revision |
| entry_id | integer | The unique identifier of an Entry |
| value_id | integer | The unique identifier of a Value |
| previous_data | string | The previous value before the revision |
| new_data | string | The new value after the revision |
| created_at | datetime | The timestamp when the revision was created |
Query Parameters
| Parameter | Type | Description | Default |
|---|---|---|---|
| page | integer (optional) | The page requested, see Pagination | 1 |
Update a Submission
A submission that has already been created can be updated by sending a PATCH request to the submission endpoint with the submission ID. By passing value_ids and values in the request body, the submission can be updated with new values. By passing an empty string as the value, the value can be removed. A single image or signature can be updated by passing in a content_guid and the value_id in the request within the responses array body.
curl -X PATCH 'https://www.gocanvas.com/api/v3/submissions/691911' \
-u 'api.user@example.com:supersecretpassword' \
-H 'Content-Type: multipart/form-data' \
-F 'responses="[
{\"value_id\": 641346, \"delete": true},
{\"value_id\": 641347, \"value\": \"Jane\"},
{\"value_id\": 641348, \"value\": \"Doe\"},
{\"value_id\": 641349, \"content_guid\": \"c3984328-f672-42e9-a307-77abede123462\"},
{\"value_id\": 641351, \"value\": \"Lat:50.669662,Lon:-79.957642,Acc:3.535534\"}
{ "entry_id": 3777061, "displayed": true, "value": "Main Street" }
]"' \
-F 'c3984328-f672-42e9-a307-77abede123462=@/path/to/image.jpg'
# the value 641346 is a text field that will be removed since the `delete` key is set to true
# the values with ids 641347, 641348, 641349 and 641351 will be updated with the corresponding values
# a new value is added to the entry_id 3777061, which is a text field that will be displayed with the data `Main Street`
require 'net/http'
require 'uri'
require 'json'
uri = URI.parse('https://www.gocanvas.com/api/v3/submissions/691911')
request = Net::HTTP::Patch.new(uri)
request.basic_auth('api.user@example.com', 'supersecretpassword')
request.body = {
responses: [
{ value_id: 641346, delete: true },
{ value_id: 641347, value: 'Jane' },
{ value_id: 641348, value: 'Doe' },
{ value_id: 641349, content_guid: 'c3984328-f672-42e9-a307-77abede123462' },
{ value_id: 641350 },
{ value_id: 641351, value: "Lat:50.669662,Lon:-79.957642,Acc:3.535534" },
{ entry_id: 3777061, displayed: true, value: "Main Street" }
]
}.to_json
form_data = {}
form_data["c3984328-f672-42e9-a307-77abede123462"] = File.open('/path/to/image.jpg', 'rb')
request.set_form form_data, 'multipart/form-data'
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.request(request)
end
puts response.body
# the value 641346 is a text field that will be removed since the `delete` key is set to `true`
# the values with ids 641347, 641348, 641349 and 641351 will be updated with the corresponding values
# a new value is added to the entry_id 3777061, which is a text field that will be displayed with the data `Main Street`
const form = new FormData();
form.append('responses', JSON.stringify([
{ value_id: 641346, delete: true },
{ value_id: 641347, value: 'Jane' },
{ value_id: 641348, value: 'Doe' },
{ value_id: 641349, content_guid: 'c3984328-f672-42e9-a307-77abede123462' },
{ value_id: 641351, value: "Lat:50.669662,Lon:-79.957642,Acc:3.535534" },
{ entry_id: 3777061, displayed: true, value: "Main Street" }
]));
form.append('c3984328-f672-42e9-a307-77abede123462', fs.createReadStream('/path/to/image.jpg'));
fetch('https://www.gocanvas.com/api/v3/submissions/691911', {
method: 'PATCH',
headers: {
'Authorization': 'Basic ' + btoa(username + ':' + password),
},
body: form
})
.then(response => response.json())
.then(data => console.log(data))
// the value 641346 is a text field that will be removed since the `delete` key is set to `true`
// the values with ids 641347, 641348, 641349 and 641351 will be updated with the corresponding values
// a new value is added to the entry_id 3777061, which is a text field that will be displayed with the data `Main Street`
HTTP Request
PATCH https://www.gocanvas.com/api/v3/submissions/691911
Request Body Parameters
| Parameter | Type | Description |
|---|---|---|
| body | hash | The JSON Submission body |
| submission | hash | The Submission to update |
| submission.id* | integer | The identifier to specify a Submission |
| responses[] | array | A collection of responses against Submission Values |
| responses[].value_id | integer | The unique identifier of a Value |
| responses[].value | string | The response data for the Value |
| responses[].multi_key† | string (optional) | Reference to the looped value |
| responses[].content_guid‡ | string (optional) | A guid indicating an image or file will be uploaded |
content_guid‡ |
file (optional) | An image of file to be uploaded |
* A submission.id is required to identify the Submission.
† Only required for looped forms
‡ Only required for Image uploads, the attached file's guid must match with a responses[].content_guid value
Note: To update a GPS field, the value should be a string in the format of latitude,longitude,accuracy (e.g. "Lat:50.669662,Lon:-79.957642,Acc:3.535534").
Note: In order to update your GPS values correctly, make sure you are using EPSG:3857 projection to have your location correctly update and render"
Response
200 OK
Update a Submission with loops
Updating a submission with loops requires the multi_key field to be passed in the request body. The multi_key field is used to identify the looped value. When updating a "child" looped value, the multi_key field should be the same as the multi_key field of the "parent" looped value.
BODY='{
"responses": [
{ "value_id": 641346, "value": "Priority" },
{ "value_id": 641345, "multi_key": "Priority", "value": "High" },
{ "value_id": 641348, "value": "Service Requested" },
{ "value_id": 641347, "multi_key": "Service Requested", "value": "Painting" }
]
}'
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X PATCH \
-d $BODY \
https://www.gocanvas.com/api/v3/submissions
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
request_body = {
"responses": [
{ "value_id": 641346, "value": "Priority" },
{ "value_id": 641345, "multi_key": "Priority", "value": "High" },
{ "value_id": 641348, "value": "Service Requested" },
{ "value_id": 641347, "multi_key": "Service Requested", "value": "Painting" }
]
}
uri = URI("https://www.gocanvas.com/api/v3/submissions")
json_request_body = request_body.to_json
req = Net::HTTP::Patch.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
req.body = json_request_body
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
submission_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
const data = {
"responses": [
{ "value_id": 641346, "value": "Priority" },
{ "value_id": 641345, "multi_key": "Priority", "value": "High" },
{ "value_id": 641348, "value": "Service Requested" },
{ "value_id": 641347, "multi_key": "Service Requested", "value": "Painting" }
]
};
fetch("https://www.gocanvas.com/api/v3/submissions", {
method: "PATCH",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(submission => console.log(submission));
HTTP Request
PATCH https://www.gocanvas.com/api/v3/submissions/691911
Request Body Parameters
| Parameter | Type | Description |
|---|---|---|
| body | hash | The JSON Submission body |
| submission | hash | The Submission to update |
| submission.id* | integer | The identifier to specify a Submission |
| responses[] | array | A collection of responses against Submission Values |
| responses[].value_id | integer | The unique identifier of a Value |
| responses[].value | string | The response data for the Value |
| responses[].multi_key† | string (optional) | Reference to the looped value |
| responses[].content_guid‡ | string (optional) | A guid indicating an image or file will be uploaded |
content_guid‡ |
file (optional) | An image of file to be uploaded |
* A submission.id is required to identify the Submission.
† Only required for looped forms
‡ Only required for Image uploads, the attached file's guid must match with a responses[].content_guid value
Note: To update a GPS field, the value should be a string in the format of latitude,longitude,accuracy (e.g. "Lat:50.669662,Lon:-79.957642,Acc:3.535534").
Note: In order to update your GPS values correctly, make sure you are using EPSG:3857 projection to have your location correctly update and render"
Response
200 OK
Delete a Submission
A Submission can be deleted with a DELETE request.
By default, the DELETE request will soft-delete the submission, which preserves the Submission data but hides it from the web views. To permanently delete a Submission, use the hard_delete=true parameter, e.g. DELETE https://www.gocanvas.com/api/v3/submissions/691911?hard_delete=true.
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X DELETE \
https://www.gocanvas.com/api/v3/submissions/691911
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
uri = URI("https://www.gocanvas.com/api/v3/submissions/691911")
req = Net::HTTP::Delete.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
submission_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
fetch("https://www.gocanvas.com/api/v3/submissions/691911", {
method: "DELETE",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
}
})
.then(response => response.json())
.then(submission => console.log(submission));
RESPONSE
{
"message": "Submission 691911 has been soft deleted successfully"
}
HTTP Request
DELETE https://www.gocanvas.com/api/v3/submissions/691911
Request Parameters
| Parameter | Type | Description |
|---|---|---|
| hard_delete* | boolean | Will hard delete the Submission record when set to true |
* This is an optional parameter. If not provided, the submission will be soft deleted.
Delete a Submission by GUID
A Submission can be deleted with a DELETE request by GUID.
By default, the DELETE request will soft-delete the submission, which preserves the Submission data but hides it from the web views. To permanently delete a Submission, use the hard_delete=true parameter, e.g. DELETE https://www.gocanvas.com/api/v3/submissions/02ED5FB2-9C61-4F18-AB17-543547DF899B?hard_delete=true.
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X DELETE \
https://www.gocanvas.com/api/v3/submissions/02ED5FB2-9C61-4F18-AB17-543547DF899B
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
uri = URI("https://www.gocanvas.com/api/v3/submissions/02ED5FB2-9C61-4F18-AB17-543547DF899B")
req = Net::HTTP::Delete.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
submission_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
fetch("https://www.gocanvas.com/api/v3/submissions/02ED5FB2-9C61-4F18-AB17-543547DF899B", {
method: "DELETE",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
}
})
.then(response => response.json())
.then(submission => console.log(submission));
RESPONSE
{
"message": "Submission 691911 has been soft deleted successfully"
}
HTTP Request
DELETE https://www.gocanvas.com/api/v3/submissions/02ED5FB2-9C61-4F18-AB17-543547DF899B
Request Parameters
| Parameter | Type | Description |
|---|---|---|
| hard_delete* | boolean | Will hard delete the Submission record when set to true |
* This is an optional parameter. If not provided, the submission will be soft deleted.
User
A User is a GoCanvas user who belongs to a specific Company. To ensure proper access and permissions, each User must be assigned a valid Company role.
The User object
EXAMPLE
{
"id": 114,
"type": "user",
"created_at": "2023-06-05 13:43:08 UTC",
"first_name": "New",
"last_name": "User",
"login": "new.user@gocanvas.com",
"enabled": true,
"phone": "123-456-7890"
}
| Parameter | Type | Description |
|---|---|---|
| id | integer | The unique User id |
| first_name | string | The first name of the User |
| last_name | string | The last name of the User |
| login | string | The email address of the User |
| enabled | boolean | Whether a user is allowed to login |
List all Users
Users can view a list of all the Users associated with their Company.
To view a list of all Users per Department, see List all Department Users.
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X GET \
https://www.gocanvas.com/api/v3/users
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
uri = URI("https://www.gocanvas.com/api/v3/users")
req = Net::HTTP::Get.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
users_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
fetch("https://www.gocanvas.com/api/v3/users", {
method: "GET",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
}
})
.then(response => response.json())
.then(users => console.log(users));
RESPONSE
[
{
"id": 20079,
"type": "user",
"created_at": "2023-06-16 23:09:20 UTC",
"enabled": true,
"first_name": "Sophie",
"last_name": "Olufsen",
"login": "sophie.olufsen@acmecorp.com",
"address": "456 Market St",
"address2": "Floor 3",
"city": "San Francisco",
"state": "CA",
"zip": "94105"
},
{
"id": 20122,
"type": "user",
"created_at": "2024-08-18 18:22:13 UTC",
"enabled": true,
"first_name": "Gregory",
"last_name": "Johnson",
"login": "gregory.johnson@acmecorp.com",
"address": "123 Main St",
"address2": "Suite 200",
"city": "Denver",
"state": "CO",
"zip": "80202"
}
]
HTTP Request
GET https://www.gocanvas.com/api/v3/users
Query Parameters
| Parameter | Type | Description | Default |
|---|---|---|---|
| page | integer (optional) | The page requested, see Pagination | 1 |
| enabled | boolean (optional) | Returns only users that are enabled or disabled. Returns all users if omitted. |
null |
Retrieve a User
Users can retrieve a User by its ID.
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X GET \
https://www.gocanvas.com/api/v3/users/20122
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
uri = URI("https://www.gocanvas.com/api/v3/users/20122")
req = Net::HTTP::Get.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
user_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
fetch("https://www.gocanvas.com/api/v3/users/20122", {
method: "GET",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
}
})
.then(response => response.json())
.then(user => console.log(user));
HTTP Request
GET https://www.gocanvas.com/api/v3/users/20122
RESPONSE
{
"id": 20122,
"type": "user",
"created_at": "2024-08-18 18:22:13 UTC",
"enabled": true,
"first_name": "Gregory",
"last_name": "Johnson",
"login": "gregory.johnson@acmecorp.com",
"phone": "555-123-4567",
"address": "123 Main St",
"address2": "Suite 200",
"city": "Denver",
"state": "CO",
"zip": "80202"
}
Response Parameters
| Parameter | Type | Description |
|---|---|---|
| id | integer | The identifier for this User |
| created_at | string | A DateTime value of when the User was created |
| enabled | boolean | Whether the User is allowed to login |
| first_name | string | The first name of the User |
| last_name | string | The last name of the User |
| login | string | The email address of the User |
| phone | string | The phone number of the User |
| address | string | The street address of the User |
| address2 | string | The second line of the User's street address |
| city | string | The city of the User |
| state | string | The state or province of the User |
| zip | string | The postal code of the User |
Create a User
To create a User in a Company, you'll need to pass basic information about the User: a unique email, a first_name, a last_name, and a department_role giving the User specific rights within a Department. If Departments are enabled for the Company, a valid department_id is also required to set the User's default department.
For more information on roles:
- If you do not have departments enabled see Department Roles
- If you have departments enabled see Account Roles
BODY='{
"first_name": "New",
"last_name": "User",
"email": "new.user@gocanvas.com",
"password": "SuperSecretPassword123!",
"phone": "5555555555",
"department_id": 1999,
"department_role": "department_user",
"account_role": "account_reporter"
}'
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X POST \
-d $BODY \
https://www.gocanvas.com/api/v3/users
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
request_body = {
"first_name": "New",
"last_name": "User",
"email": "new.user@gocanvas.com",
"password": "SuperSecretPassword123!",
"phone": "5555555555",
"department_id": 1999,
"department_role": "department_user",
"account_role": "account_reporter"
}
uri = URI("https://www.gocanvas.com/api/v3/users")
json_request_body = request_body.to_json
req = Net::HTTP::Post.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
req.body = json_request_body
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
user_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
const data = {
"first_name": "New",
"last_name": "User",
"email": "new.user@gocanvas.com",
"password": "SuperSecretPassword123!",
"phone": "5555555555",
"department_id": 1999,
"department_role": "department_user",
"account_role": "account_reporter"
};
fetch("https://www.gocanvas.com/api/v3/users", {
method: "POST",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(user => console.log(user));
HTTP Request
POST https://www.gocanvas.com/api/v3/users
Request Body Parameters
| Parameter | Type | Description | Options |
|---|---|---|---|
| department_role* | string | A valid department role to assign to the new User | department_admin department_reporter department_user department_designer department_dispatcher |
| first_name | string | The first name of a new User | |
| last_name | string | The last name of a new User | |
| string | The unique email address of a new User | ||
| account_role** | string (optional) | A valid account role to assign to the new User | account_admin account_reporter |
| password*** | string (optional) | The password of a new User | |
| department_id**** | integer (optional) | The unique Department id to assign a new User to a specific Department | |
| phone | string (optional) | The phone number of a new User | |
| skip_welcome_email***** | boolean (optional) | Prevents welcome email from being sent to the new User when set to true |
true false |
* All Companies have a default Department (when Departments are disabled, all Users belong to the default Department). department_role is used to set the User's role within a Department. When Departments are enabled, this role is specific to the specified department_id.
** account_role is only used when Departments are enabled for the Company. This sets the User's role for the entire Company and is not Department specific.
*** When password is specified, it must adhere to the company's password policy. When password is not specified, a secure password will be created automatically and a "Set your password" email will be sent to the email provided (not sent if skip_welcome_email is set to true).
**** department_id is required if Departments are enabled for the Company.
***** If skip_welcome_email is not specified, the default is false.
Response
RESPONSE
{
"id": 114,
"type": "user",
"created_at": "2023-06-05 13:43:08 UTC",
"first_name": "New",
"last_name": "User",
"login": "new.user@gocanvas.com",
"enabled": true,
"phone": "123-456-7890"
}
| Parameter | Type | Description |
|---|---|---|
| id | integer | The unique User id for the new User |
| type | string | The type of object |
| first_name | string | The first name of the new User |
| last_name | string | The last name of the new User |
| login | string | The email address of the new User |
Change User password
To change a User's password, you'll need to pass the id of the User and the new password. Must be an admin to change a User's password.
HTTP Request
curl -u api.user@example.com:supersecretpassword \
-X PATCH \
-H 'Content-Type: application/json' \
-d '{"password": "SuperSecretPassword123!"}' \
https://www.gocanvas.com/api/v3/users/114/change_password
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
uri = URI("https://www.gocanvas.com/api/v3/users/114/change_password")
req = Net::HTTP::Patch.new(uri)
req.basic_auth(username, password)
req.set_form_data({ password: "SuperSecretPassword123!" })
req["Content-Type"] = "application/json"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
const data = { "password": "SuperSecretPassword123!" }
fetch('https://www.gocanvas.com/api/v3/users/114/change_password', {
method: 'PATCH',
headers: {
'Authorization': 'Basic ' + btoa(username + ':' + password),
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
})
.then((response) => response.json())
.then((data => console.log(data) ))
PATCH https://www.gocanvas.com/api/v3/users/114/change_password
Request Body Parameters
| Parameter | Type | Description |
|---|---|---|
| password* | string | The new password of a User |
* Password must adhere to the company's password policy.
Response
204 No Content
Update User
To update a User, you will need to pass the id of the User and the new information. Either admin or user themself can update a User. Only fields listed in Request Body Parameters can be updated, others will be ignored.
HTTP Request
BODY='{
"first_name": "New First Name"
}'
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X PATCH \
-d $BODY \
https://www.gocanvas.com/api/v3/users
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
request_body = {
"first_name": "New First Name"
}
uri = URI("https://www.gocanvas.com/api/v3/users")
json_request_body = request_body.to_json
req = Net::HTTP::Patch.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
req.body = json_request_body
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
user_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
const data = {
"first_name": "New First Name"
};
fetch("https://www.gocanvas.com/api/v3/users", {
method: "PATCH",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(user => console.log(user));
RESPONSE
{
"message": "User updated successfully"
}
PATCH https://www.gocanvas.com/api/v3/users/114
Request Body Parameters
| Parameter | Type | Description |
|---|---|---|
| first_name | string (optional) | New first name of a User |
| last_name | string (optional) | New last name of a User |
| phone | string (optional) | New phone number of a User |
| enabled* | boolean (optional) | Whether a user is allowed to login |
* A disabled user may only be enabled if additional seats are available.
Values
Values represent the data that is collected in a submission.
Most values will be in-line within the Retrieve a Submission response. Values for media fields (photos, videos, or attachments) must be downloaded individually using this method.
Retrieve a Value
Users can download a Value's content for media fields (photos, videos, or attachments) by its ID through its submission.
HTTP Request
GET https://www.gocanvas.com/api/v3/submissions/691911/values/641490
curl -u api.user@example.com:supersecretpassword \
https://www.gocanvas.com/api/v3/submissions/691911/values/641490 > value_641490.jpg
require 'net/http'
username = "api.user@example.com"
password = "supersecretpassword"
uri = URI("https://www.gocanvas.com/api/v3/submissions/691911/values/641490")
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
req = Net::HTTP::Get.new(uri)
req.basic_auth username, password
http.request req do |response|
open 'value-641490.jpg', 'wb' do |io|
response.read_body do |chunk|
io.write chunk
end
end
end
end
let username = "api.user@example.com"
let password = "supersecretpassword"
fetch("https://www.gocanvas.com/api/v3/submissions/691911/values/641490", {
method: "GET",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
},
})
.then(response => {
if (response.ok) {
return response.blob();
}
})
.then(blob => {
let fileURL = URL.createObjectURL(blob);
let fileLink = document.createElement('a');
fileLink.href = fileURL;
fileLink.download = 'value-641490.jpg';
fileLink.click();
})
.catch((err) => {
// handle error
console.log(err);
});
Webhooks
Webhooks are a customizable Integration Option that will notify your back end services of GoCanvas events in real time when you have time-sensitive needs based on your Form events.
The Webhook Object
EXAMPLE
{
"id": 1,
"type": "CustomIntegration",
"event_type": "dispatch_create",
"format": "json",
"form_id": 346127,
"push_url": "https://example.com/webhook",
"push_tag": "webhook tag"
}
Webhooks are configured at a Form level and will persist across all versions of a Form. For example, any Webhook set up with version 2 of your Form will carry forward to versions 3 and so on.
When you add Webhook configurations to your forms, a payload containing some metadata about the event will be sent to the configured endpoint. There are five webhook event_types available:
- dispatch_create - Triggered when a dispatch is created
- submission_create - Triggered when a form submission is completed
- submission_edit - Triggered when a form submission is edited after completion
- workflow_handoff_create - Triggered when a submission is completed
- submission_custom_status_change - Triggered when a submission's custom status changes
Learn more about Webhooks here.
List all Webhooks
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X GET \
https://www.gocanvas.com/api/v3/webhooks
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
uri = URI("https://www.gocanvas.com/api/v3/webhooks")
req = Net::HTTP::Get.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
webhooks_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
fetch("https://www.gocanvas.com/api/v3/webhooks", {
method: "GET",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
}
})
.then(response => response.json())
.then(webhooks => console.log(webhooks));
User can view a list of all Webhooks associated with their Form.
RESPONSE
[
{
"id": 1,
"type": "CustomIntegration",
"event_type": "dispatch_create",
"format": "json",
"form_id": 346127,
"push_url": "https://example.com/webhook",
"push_tag": "dispatch webhook tag"
},
{
"id": 2,
"type": "CustomIntegration",
"event_type": "submission_create",
"format": "xml",
"form_id": 346127,
"push_url": "https://example.org/notify",
"push_tag": "submission webhook tag"
},
{
"id": 3,
"type": "CustomIntegration",
"event_type": "submission_edit",
"format": "json",
"form_id": 346127,
"push_url": "https://example.org/notify-edit",
"push_tag": "submission edit webhook tag"
},
{
"id": 4,
"type": "CustomIntegration",
"event_type": "workflow_handoff_create",
"format": "json",
"form_id": 346127,
"push_url": "https://example.net/user-webhook",
"push_tag": " workflow webhook tag"
},
{
"id": 5,
"type": "CustomIntegration",
"event_type": "submission_custom_status_change",
"format": "json",
"form_id": 346127,
"push_url": "https://example.net/status-webhook",
"push_tag": "submission status webhook tag"
}
]
HTTP Request
GET https://www.gocanvas.com/api/v3/forms/346127/webhooks
Query Parameters
| Parameter | Type | Description | Default |
|---|---|---|---|
| page | integer (optional) | The page requested, see Pagination | 1 |
Retrieve a Webhook
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X GET \
https://www.gocanvas.com/api/v3/forms/346127/webhooks/1
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
uri = URI("https://www.gocanvas.com/api/v3/forms/346127/webhooks/1")
req = Net::HTTP::Get.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
webhook_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
fetch("https://www.gocanvas.com/api/v3/forms/346127/webhooks/1", {
method: "GET",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
}
})
.then(response => response.json())
.then(webhook => console.log(webhook));
Users can retrieve a single Webhook associated with their Form by its ID.
RESPONSE
{
"id": 1,
"type": "CustomIntegration",
"event_type": "dispatch_create",
"format": "json",
"form_id": 346127,
"push_url": "https://example.com/webhook",
"push_tag": "webhook tag"
}
HTTP Request
GET https://www.gocanvas.com/api/v3/forms/346127/webhooks/1
Response Parameters (Summary)
| Parameter | Type | Description |
|---|---|---|
| id | integer | The unique identifier for the Webhook |
| type | string | The type of Integration Option |
| event_type | string | The event that triggers the Webhook |
| format | string | The format of the Webhook payload |
| form_id * | integer | The unique identifier for the associated Form |
| push_url | string | The URL to which the Webhook will send data |
| push_tag | string | A user-defined tag for the Webhook |
* Webhook is tied to a root version of the Form. If the Form is updated, the Webhook remains associated with the root version. Using any version of the Form in the URL will return the same Webhook configuration.
Create a Webhook
Users can create a Webhook for a specific Form. In order to create dispatch_create(event_type) Webhook, Dispatch has to be enabled on the Form. In order to createworkflow_handoff_create Webhook, Workflow has to be enabled on the Form. In order to create submission_custom_status_change Webhook, Submission Status has to be enabled on the Form. Form can have only one Webhook per event_type.
BODY='{
"event_type": "dispatch_create",
"format": "json",
"push_url": "https://example.com/webhook",
"push_tag": "webhook tag"
}'
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X POST \
-d $BODY \
https://www.gocanvas.com/api/v3/forms/346127/webhooks
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
request_body = {
"event_type": "dispatch_create",
"format": "json",
"push_url": "https://example.com/webhook",
"push_tag": "webhook tag"
}
uri = URI("https://www.gocanvas.com/api/v3/forms/346127/webhooks")
json_request_body = request_body.to_json
req = Net::HTTP::Post.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
req.body = json_request_body
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
webhook_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
const data = {
"event_type": "dispatch_create",
"format": "json",
"push_url": "https://example.com/webhook",
"push_tag": "webhook tag"
};
fetch("https://www.gocanvas.com/api/v3/forms/346127/webhooks", {
method: "POST",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(webhook => console.log(webhook));
RESPONSE
{
"id": 1,
"type": "CustomIntegration",
"event_type": "dispatch_create",
"format": "json",
"form_id": 346127,
"push_url": "https://example.com/webhook",
"push_tag": "webhook tag"
}
HTTP Request
POST https://www.gocanvas.com/api/v3/forms/346127/webhooks
Request Body Parameters
| Parameter | Type | Description |
|---|---|---|
| event_type* | string | The event that triggers the Webhook** |
| format* | string | The format of the Webhook payload*** |
| push_url* | string | The URL to which the Webhook will send data |
| push_tag | string | A user-defined tag for the Webhook |
* required field
** event_type can be dispatch_create, submission_create, submission_edit, workflow_handoff_create, or submission_custom_status_change
*** format can be json or xml for submission_create events, or json only for other event types
Test a Webhook
Users can test an existing Webhook for a specific Form to make sure integration is working before real events start triggering. This will send a test payload to the Webhook's push_url.
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X POST \
https://www.gocanvas.com/api/v3/forms/346127/webhooks/1/test
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
uri = URI("https://www.gocanvas.com/api/v3/forms/346127/webhooks/1/test")
req = Net::HTTP::Post.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
webhook_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
fetch("https://www.gocanvas.com/api/v3/forms/346127/webhooks/1/test", {
method: "POST",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
}
})
.then(response => response.json())
.then(webhook => console.log(webhook));
RESPONSE
{
"message": "Test webhook sent successfully",
"response_code": 200,
"response_body": "Webhook received and processed successfully",
"test_payload": {
"type": "dispatch_create",
"form": {
"id": 1,
"name": "FORM_NAME",
"guid": "FORM_GUID",
"tag": ""
},
"dispatch_item": {
"id": 1
}
}
}
HTTP Request
POST https://www.gocanvas.com/api/v3/forms/346127/webhooks/1/test
Response Parameters (Summary)
| Parameter | Type | Description |
|---|---|---|
| message | string | Confirmation message about the test |
| response_code | integer | HTTP response code from the webhook endpoint |
| response_body | string | Response body received from the webhook endpoint |
| test_payload | object | The test payload that was sent to the webhook endpoint |
Update a Webhook
Users can update an existing Webhook for a specific Form.
BODY='{
"push_tag": "updated webhook tag"
}'
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X PATCH \
-d $BODY \
https://www.gocanvas.com/api/v3/forms/346127/webhooks/1
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
request_body = {
"push_tag": "updated webhook tag"
}
uri = URI("https://www.gocanvas.com/api/v3/forms/346127/webhooks/1")
json_request_body = request_body.to_json
req = Net::HTTP::Patch.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
req.body = json_request_body
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
webhook_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
const data = {
"push_tag": "updated webhook tag"
};
fetch("https://www.gocanvas.com/api/v3/forms/346127/webhooks/1", {
method: "PATCH",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(webhook => console.log(webhook));
RESPONSE
{
"message": "Webhook has been updated successfully"
}
HTTP Request
PATCH https://www.gocanvas.com/api/v3/forms/346127/webhooks/1
Request Body Parameters
| Parameter | Type | Description |
|---|---|---|
| event_type | string | The event that triggers the Webhook** |
| format | string | The format of the Webhook payload*** |
| push_url | string | The URL to which the Webhook will send data |
| push_tag | string | A user-defined tag for the Webhook |
** event_type can be dispatch_create, submission_create, submission_edit, workflow_handoff_create, or submission_custom_status_change
*** format can be json or xml for submission_create events, or json only for other event types
Delete a Webhook
Users can delete an existing Webhook for a specific Form. By default, the DELETE request will only soft delete the Webhook which preserves the Webhook data and removes it from the view. To permanently delete the Webhook, include the hard_delete parameter with a value of true, e.g. DELETE https://www.gocanvas.com/api/v3/forms/346127/webhooks/1?hard_delete=true .
curl -u api.user@example.com:supersecretpassword \
-H "Content-Type: application/json" \
-X DELETE \
https://www.gocanvas.com/api/v3/forms/346127/webhooks/1
require 'net/http'
require 'json'
username = "api.user@example.com"
password = "supersecretpassword"
uri = URI("https://www.gocanvas.com/api/v3/forms/346127/webhooks/1")
req = Net::HTTP::Delete.new(uri)
req['Authorization'] = "Basic " + Base64.strict_encode64("#{username}:#{password}")
req['Content-Type'] = "application/json"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
webhook_json = JSON.parse(res.body)
const username = "api.user@example.com";
const password = "supersecretpassword";
fetch("https://www.gocanvas.com/api/v3/forms/346127/webhooks/1", {
method: "DELETE",
headers: {
Authorization: "Basic " + btoa(username + ":" + password),
"Content-Type": "application/json",
}
})
.then(response => response.json())
.then(webhook => console.log(webhook));
RESPONSE
{
"message": "Webhook 1 has been soft deleted successfully"
}
HTTP Request
DELETE https://www.gocanvas.com/api/v3/forms/346127/webhooks/1
Request Parameters
| Parameter | Type | Description |
|---|---|---|
| hard_delete* | boolean | Will hard delete the Webhook record when set to true |
* This is an optional URL parameter. If not provided, the Webhook will be soft deleted.
