curl --request POST \
--url https://api.firma.dev/functions/v1/signing-request-api/documents \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "Sales Agreement 2024",
"recipients": [
{
"name": "John Doe",
"email": "john@example.com"
}
]
}
'import requests
url = "https://api.firma.dev/functions/v1/signing-request-api/documents"
payload = {
"name": "Sales Agreement 2024",
"recipients": [
{
"name": "John Doe",
"email": "john@example.com"
}
]
}
headers = {
"Authorization": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: 'Sales Agreement 2024',
recipients: [{name: 'John Doe', email: 'john@example.com'}]
})
};
fetch('https://api.firma.dev/functions/v1/signing-request-api/documents', 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://api.firma.dev/functions/v1/signing-request-api/documents",
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([
'name' => 'Sales Agreement 2024',
'recipients' => [
[
'name' => 'John Doe',
'email' => 'john@example.com'
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: <api-key>",
"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://api.firma.dev/functions/v1/signing-request-api/documents"
payload := strings.NewReader("{\n \"name\": \"Sales Agreement 2024\",\n \"recipients\": [\n {\n \"name\": \"John Doe\",\n \"email\": \"john@example.com\"\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<api-key>")
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://api.firma.dev/functions/v1/signing-request-api/documents")
.header("Authorization", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"Sales Agreement 2024\",\n \"recipients\": [\n {\n \"name\": \"John Doe\",\n \"email\": \"john@example.com\"\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.firma.dev/functions/v1/signing-request-api/documents")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"Sales Agreement 2024\",\n \"recipients\": [\n {\n \"name\": \"John Doe\",\n \"email\": \"john@example.com\"\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"description": "<string>",
"status": "draft",
"document_url": "<string>",
"page_count": 2,
"expiration_hours": 168,
"template_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"settings": {
"allow_download": true,
"attach_pdf_on_finish": true,
"allow_editing_before_sending": false,
"use_signing_order": true,
"hand_drawn_only": false,
"send_signing_email": true,
"send_finish_email": true,
"send_expiration_email": true,
"send_cancellation_email": true,
"require_otp_verification": null,
"disable_guided_navigation": true
},
"created_date": "2023-11-07T05:31:56Z",
"updated_date": "2023-11-07T05:31:56Z",
"sent_date": "2023-11-07T05:31:56Z",
"finished_date": "2023-11-07T05:31:56Z",
"cancelled_date": "2023-11-07T05:31:56Z",
"recipients": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"first_name": "<string>",
"last_name": "<string>",
"name": "<string>",
"email": "jsmith@example.com",
"order": 2,
"phone_number": "<string>",
"street_address": "<string>",
"city": "<string>",
"state_province": "<string>",
"postal_code": "<string>",
"country": "<string>",
"title": "<string>",
"company": "<string>",
"custom_fields": {},
"finished_date": "2023-11-07T05:31:56Z"
}
],
"fields": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"recipient_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"page_number": 2,
"x_position": 123,
"y_position": 123,
"width": 123,
"height": 123,
"required": true,
"read_only": true,
"read_only_value": "<string>",
"variable_name": "<string>",
"variable_defined_name": "<string>",
"dropdown_options": [
"<string>"
],
"format_rules": {},
"validation_rules": {},
"date_signing_default": true,
"final_value": "<string>"
}
],
"warnings": [
"<string>"
]
}{
"error": "Validation Error",
"message": "Invalid input data",
"details": {
"name": "Name is required",
"email": "Invalid email format"
}
}{
"error": "Unauthorized",
"message": "Invalid API key"
}{
"error": "Rate Limit Exceeded",
"message": "Too many requests. Please wait before retrying.",
"details": {
"retry_after": 45
}
}Create document (Legacy)
DEPRECATED: Use /signing-requests instead. Legacy endpoint for creating a new signing request.
curl --request POST \
--url https://api.firma.dev/functions/v1/signing-request-api/documents \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "Sales Agreement 2024",
"recipients": [
{
"name": "John Doe",
"email": "john@example.com"
}
]
}
'import requests
url = "https://api.firma.dev/functions/v1/signing-request-api/documents"
payload = {
"name": "Sales Agreement 2024",
"recipients": [
{
"name": "John Doe",
"email": "john@example.com"
}
]
}
headers = {
"Authorization": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: 'Sales Agreement 2024',
recipients: [{name: 'John Doe', email: 'john@example.com'}]
})
};
fetch('https://api.firma.dev/functions/v1/signing-request-api/documents', 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://api.firma.dev/functions/v1/signing-request-api/documents",
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([
'name' => 'Sales Agreement 2024',
'recipients' => [
[
'name' => 'John Doe',
'email' => 'john@example.com'
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: <api-key>",
"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://api.firma.dev/functions/v1/signing-request-api/documents"
payload := strings.NewReader("{\n \"name\": \"Sales Agreement 2024\",\n \"recipients\": [\n {\n \"name\": \"John Doe\",\n \"email\": \"john@example.com\"\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<api-key>")
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://api.firma.dev/functions/v1/signing-request-api/documents")
.header("Authorization", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"Sales Agreement 2024\",\n \"recipients\": [\n {\n \"name\": \"John Doe\",\n \"email\": \"john@example.com\"\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.firma.dev/functions/v1/signing-request-api/documents")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"Sales Agreement 2024\",\n \"recipients\": [\n {\n \"name\": \"John Doe\",\n \"email\": \"john@example.com\"\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"description": "<string>",
"status": "draft",
"document_url": "<string>",
"page_count": 2,
"expiration_hours": 168,
"template_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"settings": {
"allow_download": true,
"attach_pdf_on_finish": true,
"allow_editing_before_sending": false,
"use_signing_order": true,
"hand_drawn_only": false,
"send_signing_email": true,
"send_finish_email": true,
"send_expiration_email": true,
"send_cancellation_email": true,
"require_otp_verification": null,
"disable_guided_navigation": true
},
"created_date": "2023-11-07T05:31:56Z",
"updated_date": "2023-11-07T05:31:56Z",
"sent_date": "2023-11-07T05:31:56Z",
"finished_date": "2023-11-07T05:31:56Z",
"cancelled_date": "2023-11-07T05:31:56Z",
"recipients": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"first_name": "<string>",
"last_name": "<string>",
"name": "<string>",
"email": "jsmith@example.com",
"order": 2,
"phone_number": "<string>",
"street_address": "<string>",
"city": "<string>",
"state_province": "<string>",
"postal_code": "<string>",
"country": "<string>",
"title": "<string>",
"company": "<string>",
"custom_fields": {},
"finished_date": "2023-11-07T05:31:56Z"
}
],
"fields": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"recipient_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"page_number": 2,
"x_position": 123,
"y_position": 123,
"width": 123,
"height": 123,
"required": true,
"read_only": true,
"read_only_value": "<string>",
"variable_name": "<string>",
"variable_defined_name": "<string>",
"dropdown_options": [
"<string>"
],
"format_rules": {},
"validation_rules": {},
"date_signing_default": true,
"final_value": "<string>"
}
],
"warnings": [
"<string>"
]
}{
"error": "Validation Error",
"message": "Invalid input data",
"details": {
"name": "Name is required",
"email": "Invalid email format"
}
}{
"error": "Unauthorized",
"message": "Invalid API key"
}{
"error": "Rate Limit Exceeded",
"message": "Too many requests. Please wait before retrying.",
"details": {
"retry_after": 45
}
}Authorizations
API key for authentication. Use your API key directly without any prefix (e.g., 'your-api-key'). Bearer prefix is optional but not required.
Body
Response
Document created successfully
Signing request as returned by CREATE endpoints (POST /signing-requests, POST /documents)
Unique identifier for the signing request
Signing request name
255Signing request description
Status is always 'draft' for newly created signing requests
draft Pre-signed URL to the PDF document
Number of pages in the document
x >= 1Hours until signing request expires (default: 168 = 7 days)
x >= 1Template ID if created from a template
Signing request and template settings. All 9 fields are returned by every endpoint that includes settings.
Show child attributes
Show child attributes
Creation timestamp
Last update timestamp
When the signing request was sent
When all signatures were completed
When the signing request was cancelled
Signing request recipients
Show child attributes
Show child attributes
Signing request fields with flat position values
Show child attributes
Show child attributes
Optional email format validation warnings. Only present when recipient emails have unusual formats.
Was this page helpful?