import { FirmaClient } from "@firma-dev/sdk";
const firma = new FirmaClient({ apiKey: "YOUR_API_KEY" });
const response = await firma.signingRequests.createAndSendSigningRequest({
"name": "Employment Contract - John Doe",
"description": "Full-time employment contract",
"document": "JVBERi0xLjQKJeLjz9MK...",
"expiration_hours": 168,
"recipients": [
{
"id": "temp_signer_1",
"first_name": "John",
"last_name": "Doe",
"email": "john.doe@example.com",
"designation": "Signer",
"order": 1,
"phone_number": "+1-555-0123",
"company": "Acme Corp",
"title": "Software Engineer"
}
],
"fields": [
{
"recipient_id": "temp_signer_1",
"type": "signature",
"page": 1,
"x": 100,
"y": 500,
"width": 200,
"height": 50
},
{
"recipient_id": "temp_signer_1",
"type": "text",
"page": 1,
"x": 100,
"y": 400,
"width": 150,
"height": 30,
"variable_name": "phone_number",
"required": true,
"read_only": true
}
],
"settings": {
"use_signing_order": true,
"send_signing_email": true
}
});
console.log(response);curl --request POST \
--url https://api.firma.dev/functions/v1/signing-request-api/signing-requests/create-and-send \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "Employment Contract - John Doe",
"description": "Full-time employment contract",
"document": "JVBERi0xLjQKJeLjz9MK...",
"expiration_hours": 168,
"recipients": [
{
"id": "temp_signer_1",
"first_name": "John",
"last_name": "Doe",
"email": "john.doe@example.com",
"designation": "Signer",
"order": 1,
"phone_number": "+1-555-0123",
"company": "Acme Corp",
"title": "Software Engineer"
}
],
"fields": [
{
"recipient_id": "temp_signer_1",
"type": "signature",
"page": 1,
"x": 100,
"y": 500,
"width": 200,
"height": 50
},
{
"recipient_id": "temp_signer_1",
"type": "text",
"page": 1,
"x": 100,
"y": 400,
"width": 150,
"height": 30,
"variable_name": "phone_number",
"required": true,
"read_only": true
}
],
"settings": {
"use_signing_order": true,
"send_signing_email": true
}
}
'import requests
url = "https://api.firma.dev/functions/v1/signing-request-api/signing-requests/create-and-send"
payload = {
"name": "Employment Contract - John Doe",
"description": "Full-time employment contract",
"document": "JVBERi0xLjQKJeLjz9MK...",
"expiration_hours": 168,
"recipients": [
{
"id": "temp_signer_1",
"first_name": "John",
"last_name": "Doe",
"email": "john.doe@example.com",
"designation": "Signer",
"order": 1,
"phone_number": "+1-555-0123",
"company": "Acme Corp",
"title": "Software Engineer"
}
],
"fields": [
{
"recipient_id": "temp_signer_1",
"type": "signature",
"page": 1,
"x": 100,
"y": 500,
"width": 200,
"height": 50
},
{
"recipient_id": "temp_signer_1",
"type": "text",
"page": 1,
"x": 100,
"y": 400,
"width": 150,
"height": 30,
"variable_name": "phone_number",
"required": True,
"read_only": True
}
],
"settings": {
"use_signing_order": True,
"send_signing_email": True
}
}
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: 'Employment Contract - John Doe',
description: 'Full-time employment contract',
document: 'JVBERi0xLjQKJeLjz9MK...',
expiration_hours: 168,
recipients: [
{
id: 'temp_signer_1',
first_name: 'John',
last_name: 'Doe',
email: 'john.doe@example.com',
designation: 'Signer',
order: 1,
phone_number: '+1-555-0123',
company: 'Acme Corp',
title: 'Software Engineer'
}
],
fields: [
{
recipient_id: 'temp_signer_1',
type: 'signature',
page: 1,
x: 100,
y: 500,
width: 200,
height: 50
},
{
recipient_id: 'temp_signer_1',
type: 'text',
page: 1,
x: 100,
y: 400,
width: 150,
height: 30,
variable_name: 'phone_number',
required: true,
read_only: true
}
],
settings: {use_signing_order: true, send_signing_email: true}
})
};
fetch('https://api.firma.dev/functions/v1/signing-request-api/signing-requests/create-and-send', 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/signing-requests/create-and-send",
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' => 'Employment Contract - John Doe',
'description' => 'Full-time employment contract',
'document' => 'JVBERi0xLjQKJeLjz9MK...',
'expiration_hours' => 168,
'recipients' => [
[
'id' => 'temp_signer_1',
'first_name' => 'John',
'last_name' => 'Doe',
'email' => 'john.doe@example.com',
'designation' => 'Signer',
'order' => 1,
'phone_number' => '+1-555-0123',
'company' => 'Acme Corp',
'title' => 'Software Engineer'
]
],
'fields' => [
[
'recipient_id' => 'temp_signer_1',
'type' => 'signature',
'page' => 1,
'x' => 100,
'y' => 500,
'width' => 200,
'height' => 50
],
[
'recipient_id' => 'temp_signer_1',
'type' => 'text',
'page' => 1,
'x' => 100,
'y' => 400,
'width' => 150,
'height' => 30,
'variable_name' => 'phone_number',
'required' => true,
'read_only' => true
]
],
'settings' => [
'use_signing_order' => true,
'send_signing_email' => true
]
]),
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/signing-requests/create-and-send"
payload := strings.NewReader("{\n \"name\": \"Employment Contract - John Doe\",\n \"description\": \"Full-time employment contract\",\n \"document\": \"JVBERi0xLjQKJeLjz9MK...\",\n \"expiration_hours\": 168,\n \"recipients\": [\n {\n \"id\": \"temp_signer_1\",\n \"first_name\": \"John\",\n \"last_name\": \"Doe\",\n \"email\": \"john.doe@example.com\",\n \"designation\": \"Signer\",\n \"order\": 1,\n \"phone_number\": \"+1-555-0123\",\n \"company\": \"Acme Corp\",\n \"title\": \"Software Engineer\"\n }\n ],\n \"fields\": [\n {\n \"recipient_id\": \"temp_signer_1\",\n \"type\": \"signature\",\n \"page\": 1,\n \"x\": 100,\n \"y\": 500,\n \"width\": 200,\n \"height\": 50\n },\n {\n \"recipient_id\": \"temp_signer_1\",\n \"type\": \"text\",\n \"page\": 1,\n \"x\": 100,\n \"y\": 400,\n \"width\": 150,\n \"height\": 30,\n \"variable_name\": \"phone_number\",\n \"required\": true,\n \"read_only\": true\n }\n ],\n \"settings\": {\n \"use_signing_order\": true,\n \"send_signing_email\": true\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/signing-requests/create-and-send")
.header("Authorization", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"Employment Contract - John Doe\",\n \"description\": \"Full-time employment contract\",\n \"document\": \"JVBERi0xLjQKJeLjz9MK...\",\n \"expiration_hours\": 168,\n \"recipients\": [\n {\n \"id\": \"temp_signer_1\",\n \"first_name\": \"John\",\n \"last_name\": \"Doe\",\n \"email\": \"john.doe@example.com\",\n \"designation\": \"Signer\",\n \"order\": 1,\n \"phone_number\": \"+1-555-0123\",\n \"company\": \"Acme Corp\",\n \"title\": \"Software Engineer\"\n }\n ],\n \"fields\": [\n {\n \"recipient_id\": \"temp_signer_1\",\n \"type\": \"signature\",\n \"page\": 1,\n \"x\": 100,\n \"y\": 500,\n \"width\": 200,\n \"height\": 50\n },\n {\n \"recipient_id\": \"temp_signer_1\",\n \"type\": \"text\",\n \"page\": 1,\n \"x\": 100,\n \"y\": 400,\n \"width\": 150,\n \"height\": 30,\n \"variable_name\": \"phone_number\",\n \"required\": true,\n \"read_only\": true\n }\n ],\n \"settings\": {\n \"use_signing_order\": true,\n \"send_signing_email\": true\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.firma.dev/functions/v1/signing-request-api/signing-requests/create-and-send")
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\": \"Employment Contract - John Doe\",\n \"description\": \"Full-time employment contract\",\n \"document\": \"JVBERi0xLjQKJeLjz9MK...\",\n \"expiration_hours\": 168,\n \"recipients\": [\n {\n \"id\": \"temp_signer_1\",\n \"first_name\": \"John\",\n \"last_name\": \"Doe\",\n \"email\": \"john.doe@example.com\",\n \"designation\": \"Signer\",\n \"order\": 1,\n \"phone_number\": \"+1-555-0123\",\n \"company\": \"Acme Corp\",\n \"title\": \"Software Engineer\"\n }\n ],\n \"fields\": [\n {\n \"recipient_id\": \"temp_signer_1\",\n \"type\": \"signature\",\n \"page\": 1,\n \"x\": 100,\n \"y\": 500,\n \"width\": 200,\n \"height\": 50\n },\n {\n \"recipient_id\": \"temp_signer_1\",\n \"type\": \"text\",\n \"page\": 1,\n \"x\": 100,\n \"y\": 400,\n \"width\": 150,\n \"height\": 30,\n \"variable_name\": \"phone_number\",\n \"required\": true,\n \"read_only\": true\n }\n ],\n \"settings\": {\n \"use_signing_order\": true,\n \"send_signing_email\": true\n }\n}"
response = http.request(request)
puts response.read_body{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Employment Contract - John Doe",
"description": "Full-time employment contract",
"status": "sent",
"document_url": "https://storage.supabase.co/...",
"page_count": 3,
"expiration_hours": 168,
"settings": {
"use_signing_order": true,
"allow_download": true,
"attach_pdf_on_finish": true,
"send_signing_email": true,
"send_finish_email": true,
"send_expiration_email": true,
"send_cancellation_email": true,
"hand_drawn_only": false
},
"created_date": "2026-01-12T10:30:00Z",
"sent_date": "2026-01-12T10:30:00Z",
"template_id": null,
"first_signer": {
"id": "rec456-e89b-12d3-a456-426614174000",
"name": "John Doe",
"email": "john.doe@example.com",
"signing_link": "https://app.firma.dev/signing/rec456-e89b-12d3-a456-426614174000"
},
"recipients": [
{
"id": "rec456-e89b-12d3-a456-426614174000",
"first_name": "John",
"last_name": "Doe",
"name": "John Doe",
"email": "john.doe@example.com",
"designation": "Signer",
"order": 1
}
],
"fields": [
{
"id": "field123-e89b-12d3-a456-426614174000",
"type": "signature",
"page": 1,
"x": 100,
"y": 500,
"width": 200,
"height": 50,
"required": true,
"recipient_id": "rec456-e89b-12d3-a456-426614174000"
}
],
"credits_remaining": 99
}Create and Send Signing Request (Atomic)
Create and immediately send a signing request in a single atomic operation. This endpoint combines the functionality of POST /signing-requests and POST /signing-requests//send.
Key Benefits:
- Single API call instead of two separate requests
- Validates all send requirements BEFORE creating the signing request
- Atomic credit deduction - only charges if everything succeeds
- Returns status: ‘sent’ immediately with first signer details
- More efficient (saves 1 API call + round-trip time)
Validation:
- All standard creation validations (document/template, recipients, fields)
- Additional send validations:
- All signers must have first_name and valid email
- Required read-only fields must have final_value populated
- Prefilled data fields (variable_name) must have corresponding user data
- Company must have sufficient credits (≥1)
Atomicity:
- If any validation fails, nothing is created
- Credit is only deducted after successful creation and before email send
- If email send fails after creation, signing request remains in ‘draft’ status and credit is NOT deducted
Temporary ID Pattern: For document-based creation, use temporary IDs (format: ‘temp_X’) to reference recipients before creation. The API validates all references and automatically maps temporary IDs to real UUIDs.
Rate Limit: 120 requests/minute (same as write operations)
import { FirmaClient } from "@firma-dev/sdk";
const firma = new FirmaClient({ apiKey: "YOUR_API_KEY" });
const response = await firma.signingRequests.createAndSendSigningRequest({
"name": "Employment Contract - John Doe",
"description": "Full-time employment contract",
"document": "JVBERi0xLjQKJeLjz9MK...",
"expiration_hours": 168,
"recipients": [
{
"id": "temp_signer_1",
"first_name": "John",
"last_name": "Doe",
"email": "john.doe@example.com",
"designation": "Signer",
"order": 1,
"phone_number": "+1-555-0123",
"company": "Acme Corp",
"title": "Software Engineer"
}
],
"fields": [
{
"recipient_id": "temp_signer_1",
"type": "signature",
"page": 1,
"x": 100,
"y": 500,
"width": 200,
"height": 50
},
{
"recipient_id": "temp_signer_1",
"type": "text",
"page": 1,
"x": 100,
"y": 400,
"width": 150,
"height": 30,
"variable_name": "phone_number",
"required": true,
"read_only": true
}
],
"settings": {
"use_signing_order": true,
"send_signing_email": true
}
});
console.log(response);curl --request POST \
--url https://api.firma.dev/functions/v1/signing-request-api/signing-requests/create-and-send \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "Employment Contract - John Doe",
"description": "Full-time employment contract",
"document": "JVBERi0xLjQKJeLjz9MK...",
"expiration_hours": 168,
"recipients": [
{
"id": "temp_signer_1",
"first_name": "John",
"last_name": "Doe",
"email": "john.doe@example.com",
"designation": "Signer",
"order": 1,
"phone_number": "+1-555-0123",
"company": "Acme Corp",
"title": "Software Engineer"
}
],
"fields": [
{
"recipient_id": "temp_signer_1",
"type": "signature",
"page": 1,
"x": 100,
"y": 500,
"width": 200,
"height": 50
},
{
"recipient_id": "temp_signer_1",
"type": "text",
"page": 1,
"x": 100,
"y": 400,
"width": 150,
"height": 30,
"variable_name": "phone_number",
"required": true,
"read_only": true
}
],
"settings": {
"use_signing_order": true,
"send_signing_email": true
}
}
'import requests
url = "https://api.firma.dev/functions/v1/signing-request-api/signing-requests/create-and-send"
payload = {
"name": "Employment Contract - John Doe",
"description": "Full-time employment contract",
"document": "JVBERi0xLjQKJeLjz9MK...",
"expiration_hours": 168,
"recipients": [
{
"id": "temp_signer_1",
"first_name": "John",
"last_name": "Doe",
"email": "john.doe@example.com",
"designation": "Signer",
"order": 1,
"phone_number": "+1-555-0123",
"company": "Acme Corp",
"title": "Software Engineer"
}
],
"fields": [
{
"recipient_id": "temp_signer_1",
"type": "signature",
"page": 1,
"x": 100,
"y": 500,
"width": 200,
"height": 50
},
{
"recipient_id": "temp_signer_1",
"type": "text",
"page": 1,
"x": 100,
"y": 400,
"width": 150,
"height": 30,
"variable_name": "phone_number",
"required": True,
"read_only": True
}
],
"settings": {
"use_signing_order": True,
"send_signing_email": True
}
}
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: 'Employment Contract - John Doe',
description: 'Full-time employment contract',
document: 'JVBERi0xLjQKJeLjz9MK...',
expiration_hours: 168,
recipients: [
{
id: 'temp_signer_1',
first_name: 'John',
last_name: 'Doe',
email: 'john.doe@example.com',
designation: 'Signer',
order: 1,
phone_number: '+1-555-0123',
company: 'Acme Corp',
title: 'Software Engineer'
}
],
fields: [
{
recipient_id: 'temp_signer_1',
type: 'signature',
page: 1,
x: 100,
y: 500,
width: 200,
height: 50
},
{
recipient_id: 'temp_signer_1',
type: 'text',
page: 1,
x: 100,
y: 400,
width: 150,
height: 30,
variable_name: 'phone_number',
required: true,
read_only: true
}
],
settings: {use_signing_order: true, send_signing_email: true}
})
};
fetch('https://api.firma.dev/functions/v1/signing-request-api/signing-requests/create-and-send', 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/signing-requests/create-and-send",
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' => 'Employment Contract - John Doe',
'description' => 'Full-time employment contract',
'document' => 'JVBERi0xLjQKJeLjz9MK...',
'expiration_hours' => 168,
'recipients' => [
[
'id' => 'temp_signer_1',
'first_name' => 'John',
'last_name' => 'Doe',
'email' => 'john.doe@example.com',
'designation' => 'Signer',
'order' => 1,
'phone_number' => '+1-555-0123',
'company' => 'Acme Corp',
'title' => 'Software Engineer'
]
],
'fields' => [
[
'recipient_id' => 'temp_signer_1',
'type' => 'signature',
'page' => 1,
'x' => 100,
'y' => 500,
'width' => 200,
'height' => 50
],
[
'recipient_id' => 'temp_signer_1',
'type' => 'text',
'page' => 1,
'x' => 100,
'y' => 400,
'width' => 150,
'height' => 30,
'variable_name' => 'phone_number',
'required' => true,
'read_only' => true
]
],
'settings' => [
'use_signing_order' => true,
'send_signing_email' => true
]
]),
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/signing-requests/create-and-send"
payload := strings.NewReader("{\n \"name\": \"Employment Contract - John Doe\",\n \"description\": \"Full-time employment contract\",\n \"document\": \"JVBERi0xLjQKJeLjz9MK...\",\n \"expiration_hours\": 168,\n \"recipients\": [\n {\n \"id\": \"temp_signer_1\",\n \"first_name\": \"John\",\n \"last_name\": \"Doe\",\n \"email\": \"john.doe@example.com\",\n \"designation\": \"Signer\",\n \"order\": 1,\n \"phone_number\": \"+1-555-0123\",\n \"company\": \"Acme Corp\",\n \"title\": \"Software Engineer\"\n }\n ],\n \"fields\": [\n {\n \"recipient_id\": \"temp_signer_1\",\n \"type\": \"signature\",\n \"page\": 1,\n \"x\": 100,\n \"y\": 500,\n \"width\": 200,\n \"height\": 50\n },\n {\n \"recipient_id\": \"temp_signer_1\",\n \"type\": \"text\",\n \"page\": 1,\n \"x\": 100,\n \"y\": 400,\n \"width\": 150,\n \"height\": 30,\n \"variable_name\": \"phone_number\",\n \"required\": true,\n \"read_only\": true\n }\n ],\n \"settings\": {\n \"use_signing_order\": true,\n \"send_signing_email\": true\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/signing-requests/create-and-send")
.header("Authorization", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"Employment Contract - John Doe\",\n \"description\": \"Full-time employment contract\",\n \"document\": \"JVBERi0xLjQKJeLjz9MK...\",\n \"expiration_hours\": 168,\n \"recipients\": [\n {\n \"id\": \"temp_signer_1\",\n \"first_name\": \"John\",\n \"last_name\": \"Doe\",\n \"email\": \"john.doe@example.com\",\n \"designation\": \"Signer\",\n \"order\": 1,\n \"phone_number\": \"+1-555-0123\",\n \"company\": \"Acme Corp\",\n \"title\": \"Software Engineer\"\n }\n ],\n \"fields\": [\n {\n \"recipient_id\": \"temp_signer_1\",\n \"type\": \"signature\",\n \"page\": 1,\n \"x\": 100,\n \"y\": 500,\n \"width\": 200,\n \"height\": 50\n },\n {\n \"recipient_id\": \"temp_signer_1\",\n \"type\": \"text\",\n \"page\": 1,\n \"x\": 100,\n \"y\": 400,\n \"width\": 150,\n \"height\": 30,\n \"variable_name\": \"phone_number\",\n \"required\": true,\n \"read_only\": true\n }\n ],\n \"settings\": {\n \"use_signing_order\": true,\n \"send_signing_email\": true\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.firma.dev/functions/v1/signing-request-api/signing-requests/create-and-send")
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\": \"Employment Contract - John Doe\",\n \"description\": \"Full-time employment contract\",\n \"document\": \"JVBERi0xLjQKJeLjz9MK...\",\n \"expiration_hours\": 168,\n \"recipients\": [\n {\n \"id\": \"temp_signer_1\",\n \"first_name\": \"John\",\n \"last_name\": \"Doe\",\n \"email\": \"john.doe@example.com\",\n \"designation\": \"Signer\",\n \"order\": 1,\n \"phone_number\": \"+1-555-0123\",\n \"company\": \"Acme Corp\",\n \"title\": \"Software Engineer\"\n }\n ],\n \"fields\": [\n {\n \"recipient_id\": \"temp_signer_1\",\n \"type\": \"signature\",\n \"page\": 1,\n \"x\": 100,\n \"y\": 500,\n \"width\": 200,\n \"height\": 50\n },\n {\n \"recipient_id\": \"temp_signer_1\",\n \"type\": \"text\",\n \"page\": 1,\n \"x\": 100,\n \"y\": 400,\n \"width\": 150,\n \"height\": 30,\n \"variable_name\": \"phone_number\",\n \"required\": true,\n \"read_only\": true\n }\n ],\n \"settings\": {\n \"use_signing_order\": true,\n \"send_signing_email\": true\n }\n}"
response = http.request(request)
puts response.read_body{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Employment Contract - John Doe",
"description": "Full-time employment contract",
"status": "sent",
"document_url": "https://storage.supabase.co/...",
"page_count": 3,
"expiration_hours": 168,
"settings": {
"use_signing_order": true,
"allow_download": true,
"attach_pdf_on_finish": true,
"send_signing_email": true,
"send_finish_email": true,
"send_expiration_email": true,
"send_cancellation_email": true,
"hand_drawn_only": false
},
"created_date": "2026-01-12T10:30:00Z",
"sent_date": "2026-01-12T10:30:00Z",
"template_id": null,
"first_signer": {
"id": "rec456-e89b-12d3-a456-426614174000",
"name": "John Doe",
"email": "john.doe@example.com",
"signing_link": "https://app.firma.dev/signing/rec456-e89b-12d3-a456-426614174000"
},
"recipients": [
{
"id": "rec456-e89b-12d3-a456-426614174000",
"first_name": "John",
"last_name": "Doe",
"name": "John Doe",
"email": "john.doe@example.com",
"designation": "Signer",
"order": 1
}
],
"fields": [
{
"id": "field123-e89b-12d3-a456-426614174000",
"type": "signature",
"page": 1,
"x": 100,
"y": 500,
"width": 200,
"height": 50,
"required": true,
"recipient_id": "rec456-e89b-12d3-a456-426614174000"
}
],
"credits_remaining": 99
}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
- Option 1
- Option 2
Signing request name
255"Employment Contract - John Doe"
Base64-encoded PDF or DOCX document (mutually exclusive with template_id and document_id). DOCX files are automatically converted to PDF. Maximum size: 50MB.
"JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9UeXBlIC9QYWdlCi9QYXJlbnQgMSAwIFIKL1Jlc291c..."
Signing request description
"Full-time employment contract for Software Engineer position"
Template ID to use (mutually exclusive with document and document_id)
"123e4567-e89b-12d3-a456-426614174000"
Hours until signing request expires (default: 168 = 7 days)
x >= 1168
Array of recipients. At least one must be a Signer. For document-based: required. For template-based: optional (uses template recipients if omitted). Use template_user_id (preferred) or order (fallback) to match template users.
1Show child attributes
Show child attributes
Array of fields to be filled (document-based only)
Show child attributes
Show child attributes
Anchor tags for automatic field placement. Text markers in the PDF are located and converted to positioned fields. The anchor text is removed from the PDF after processing. Fields created from anchor tags are added alongside any manually specified fields. Only available for document-based creation (not template-based).
100Show child attributes
Show child attributes
Array of reminder configurations
Show child attributes
Show child attributes
Signing request settings
Show child attributes
Show child attributes
ID of a previously uploaded document (mutually exclusive with document and template_id). Obtain by calling POST /documents first.
"123e4567-e89b-12d3-a456-426614174000"
Response
Signing request created and sent successfully
Signing request created and sent
Signing request ID
Signing request name
Always 'sent' for this endpoint
sent Signing request description
Signed URL to access document
Number of pages in document
Hours until expiration
Settings returned by the signing request list and detail endpoints. Templates use the TemplateSettings schema (no identity fields).
Show child attributes
Show child attributes
When request was sent
Details of the first signer who received the email
Show child attributes
Show child attributes
All recipients with real UUIDs
Show child attributes
Show child attributes
All fields with real recipient UUIDs
Show child attributes
Show child attributes
Company credits remaining after deduction
Was this page helpful?