curl --request POST \
--url https://app.sideshift.app/api/oauth/v1/contracts/{id}/signature \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"dataUrl": "<string>",
"mimeType": "<string>",
"signerRole": "company",
"signedName": "<string>",
"setAsDefault": true,
"signedAt": "<string>"
}
'import requests
url = "https://app.sideshift.app/api/oauth/v1/contracts/{id}/signature"
payload = {
"dataUrl": "<string>",
"mimeType": "<string>",
"signerRole": "company",
"signedName": "<string>",
"setAsDefault": True,
"signedAt": "<string>"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
dataUrl: '<string>',
mimeType: '<string>',
signerRole: 'company',
signedName: '<string>',
setAsDefault: true,
signedAt: '<string>'
})
};
fetch('https://app.sideshift.app/api/oauth/v1/contracts/{id}/signature', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.sideshift.app/api/oauth/v1/contracts/{id}/signature",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'dataUrl' => '<string>',
'mimeType' => '<string>',
'signerRole' => 'company',
'signedName' => '<string>',
'setAsDefault' => true,
'signedAt' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://app.sideshift.app/api/oauth/v1/contracts/{id}/signature"
payload := strings.NewReader("{\n \"dataUrl\": \"<string>\",\n \"mimeType\": \"<string>\",\n \"signerRole\": \"company\",\n \"signedName\": \"<string>\",\n \"setAsDefault\": true,\n \"signedAt\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://app.sideshift.app/api/oauth/v1/contracts/{id}/signature")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"dataUrl\": \"<string>\",\n \"mimeType\": \"<string>\",\n \"signerRole\": \"company\",\n \"signedName\": \"<string>\",\n \"setAsDefault\": true,\n \"signedAt\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.sideshift.app/api/oauth/v1/contracts/{id}/signature")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"dataUrl\": \"<string>\",\n \"mimeType\": \"<string>\",\n \"signerRole\": \"company\",\n \"signedName\": \"<string>\",\n \"setAsDefault\": true,\n \"signedAt\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"data": {
"success": true,
"contractId": "<string>",
"signerRole": "company",
"signatureImageUrl": "<string>",
"setAsDefault": true,
"fileUrl": "<string>",
"pdfRegenerationError": "<string>",
"pendingCreatorContractUpdate": true,
"skippedRegenForUploadMode": true
}
}{
"error": {
"code": "unauthorized",
"message": "Missing bearer access token",
"requestId": "req_..."
}
}{
"error": {
"code": "insufficient_scope",
"message": "Requires scope 'campaigns:write'",
"requestId": "req_..."
}
}{
"error": {
"code": "not_found",
"message": "Resource not found",
"requestId": "req_..."
}
}{
"error": {
"code": "rate_limited",
"message": "Rate limit exceeded",
"requestId": "req_..."
}
}Save a contract signature
Save the company’s signature on a contract and rebuild the signed document. Returns the stored signatureImageUrl and the regenerated fileUrl, and reports pdfRegenerationError if the document could not be rebuilt. Sandbox tokens are rejected. Requires the contracts:sign scope.
curl --request POST \
--url https://app.sideshift.app/api/oauth/v1/contracts/{id}/signature \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"dataUrl": "<string>",
"mimeType": "<string>",
"signerRole": "company",
"signedName": "<string>",
"setAsDefault": true,
"signedAt": "<string>"
}
'import requests
url = "https://app.sideshift.app/api/oauth/v1/contracts/{id}/signature"
payload = {
"dataUrl": "<string>",
"mimeType": "<string>",
"signerRole": "company",
"signedName": "<string>",
"setAsDefault": True,
"signedAt": "<string>"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
dataUrl: '<string>',
mimeType: '<string>',
signerRole: 'company',
signedName: '<string>',
setAsDefault: true,
signedAt: '<string>'
})
};
fetch('https://app.sideshift.app/api/oauth/v1/contracts/{id}/signature', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.sideshift.app/api/oauth/v1/contracts/{id}/signature",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'dataUrl' => '<string>',
'mimeType' => '<string>',
'signerRole' => 'company',
'signedName' => '<string>',
'setAsDefault' => true,
'signedAt' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://app.sideshift.app/api/oauth/v1/contracts/{id}/signature"
payload := strings.NewReader("{\n \"dataUrl\": \"<string>\",\n \"mimeType\": \"<string>\",\n \"signerRole\": \"company\",\n \"signedName\": \"<string>\",\n \"setAsDefault\": true,\n \"signedAt\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://app.sideshift.app/api/oauth/v1/contracts/{id}/signature")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"dataUrl\": \"<string>\",\n \"mimeType\": \"<string>\",\n \"signerRole\": \"company\",\n \"signedName\": \"<string>\",\n \"setAsDefault\": true,\n \"signedAt\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.sideshift.app/api/oauth/v1/contracts/{id}/signature")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"dataUrl\": \"<string>\",\n \"mimeType\": \"<string>\",\n \"signerRole\": \"company\",\n \"signedName\": \"<string>\",\n \"setAsDefault\": true,\n \"signedAt\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"data": {
"success": true,
"contractId": "<string>",
"signerRole": "company",
"signatureImageUrl": "<string>",
"setAsDefault": true,
"fileUrl": "<string>",
"pdfRegenerationError": "<string>",
"pendingCreatorContractUpdate": true,
"skippedRegenForUploadMode": true
}
}{
"error": {
"code": "unauthorized",
"message": "Missing bearer access token",
"requestId": "req_..."
}
}{
"error": {
"code": "insufficient_scope",
"message": "Requires scope 'campaigns:write'",
"requestId": "req_..."
}
}{
"error": {
"code": "not_found",
"message": "Resource not found",
"requestId": "req_..."
}
}{
"error": {
"code": "rate_limited",
"message": "Rate limit exceeded",
"requestId": "req_..."
}
}Authorizations
OAuth 2.1 authorization code + PKCE (S256). Tokens are tenant-bound (company_id) and scoped. Discover endpoints via /.well-known/oauth-authorization-server.
Path Parameters
The id.
Body
Upload and save an e-signature for a contract (company or campaign-manager signer).
Base64 data URL of the signature image; must be data:image/png|jpeg|jpg;base64,... (max 4MB).
MIME type of the signature image.
Signer role (defaults to company).
company, campaign-manager Name to display with the signature.
Store as the signer's default signature for future contracts.
ISO date string of the signature timestamp.
Source of the signature.
drawn, typed, uploaded Response
Result of saving the e-signature, including the stored signature URL and regen status.
Show child attributes
Show child attributes