Skip to main content

Create & Send Agreement

Create and send an agreement using the Propper Sign API. This API uses a simpler, flat tab structure compared to the DocuSign-compatible API.

Overview

This example demonstrates:

  1. Creating an agreement with a basic request (no tabs)
  2. Creating an agreement with XY-positioned tabs
  3. Creating an agreement with anchor text-positioned tabs
  4. Handling draft vs. sent status
  5. Using the separate send endpoint for drafts

Prerequisites

  • Propper API credentials (client ID and secret)
  • A PDF document to send for signing
  • Scope: sign:write

Endpoint

POST /v1/sign/agreements

Set status to "SENT" to create AND send immediately, or "CREATED" for a draft.

Example 1: Basic Agreement (No Tabs)

The simplest case - recipients sign wherever they choose on the document.

curl -X POST https://api.propper.ai/v1/sign/agreements \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Employment Contract - John Smith",
"status": "SENT",
"emailSubject": "Please sign: Employment Contract",
"emailMessage": "Please review and sign the attached employment contract.",
"type": "SEQUENTIAL",
"recipients": [
{
"email": "john.smith@example.com",
"name": "John Smith",
"role": "Employee",
"order": 1
},
{
"email": "jane.doe@company.com",
"name": "Jane Doe",
"role": "Manager",
"order": 2
}
],
"documents": [
{
"name": "Employment_Contract.pdf",
"documentBase64": "<base64-encoded-pdf-content>",
"mimeType": "application/pdf",
"order": 1
}
]
}'

Response (Sent)

{
"agreement": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Employment Contract - John Smith",
"status": "SENT",
"type": "SEQUENTIAL",
"emailSubject": "Please sign: Employment Contract",
"emailMessage": "Please review and sign the attached employment contract.",
"expiresAt": null,
"createdAt": "2026-02-04T10:30:00.000Z",
"updatedAt": "2026-02-04T10:30:00.000Z",
"completedAt": null,
"recipients": [
{
"id": "recipient-uuid-1",
"email": "john.smith@example.com",
"name": "John Smith",
"role": "Employee",
"order": 1,
"status": "PENDING",
"signedAt": null
}
],
"sourceDocuments": [
{
"id": "document-uuid-1",
"filename": "Employment_Contract.pdf",
"mimeType": "application/pdf",
"pageCount": 3,
"order": 1
}
]
},
"emailsSent": 1,
"signingUrls": [
{
"recipientId": "recipient-uuid-1",
"url": "https://sign.propper.ai/sign/abc123..."
}
]
}

Response (Draft)

When status is "CREATED":

{
"agreement": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Employment Contract - John Smith",
"status": "CREATED",
"type": "SEQUENTIAL",
"emailSubject": "Please sign: Employment Contract",
"emailMessage": "Please review and sign the attached employment contract.",
"expiresAt": null,
"createdAt": "2026-02-04T10:30:00.000Z",
"updatedAt": "2026-02-04T10:30:00.000Z",
"completedAt": null
}
}
tip

Send a draft agreement later using POST /v1/sign/agreements/{agreementId}/send (requires sign:send scope).


Example 2: Agreement with XY-Positioned Tabs

Position tabs using absolute x,y coordinates in PDF points (1/72 inch). Note that page indices are 0-based in the native API.

curl -X POST https://api.propper.ai/v1/sign/agreements \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Employment Contract with Tabs",
"status": "SENT",
"emailSubject": "Please sign: Employment Contract",
"emailMessage": "Please review and sign the attached contract.",
"type": "SEQUENTIAL",
"recipients": [
{
"email": "john.smith@example.com",
"name": "John Smith",
"role": "Employee",
"order": 1,
"tabs": [
{
"type": "SIGNATURE",
"pageIndex": 2,
"rect": { "x": 100, "y": 500, "width": 150, "height": 40 },
"isRequired": true,
"label": "EmployeeSignature"
},
{
"type": "DATE_SIGNED",
"pageIndex": 2,
"rect": { "x": 350, "y": 500, "width": 100, "height": 20 },
"label": "EmployeeSignDate"
},
{
"type": "TEXT",
"pageIndex": 0,
"rect": { "x": 200, "y": 300, "width": 150, "height": 20 },
"isRequired": true,
"label": "EmployeeTitle",
"placeholder": "Enter your job title"
},
{
"type": "FULL_NAME",
"pageIndex": 0,
"rect": { "x": 200, "y": 250, "width": 200, "height": 20 },
"label": "EmployeeFullName"
}
]
},
{
"email": "jane.doe@company.com",
"name": "Jane Doe",
"role": "Manager",
"order": 2,
"tabs": [
{
"type": "SIGNATURE",
"pageIndex": 2,
"rect": { "x": 100, "y": 600, "width": 150, "height": 40 },
"isRequired": true,
"label": "ManagerSignature"
},
{
"type": "DATE_SIGNED",
"pageIndex": 2,
"rect": { "x": 350, "y": 600, "width": 100, "height": 20 },
"label": "ManagerSignDate"
}
]
}
],
"documents": [
{
"name": "Employment_Contract.pdf",
"documentBase64": "<base64-encoded-pdf-content>",
"mimeType": "application/pdf",
"order": 1
}
]
}'

Example 3: Agreement with Anchor-Positioned Tabs

Position tabs relative to text found in the document. More resilient to layout changes than XY coordinates.

tip

Use unique anchor markers like /sig1/, /date1/, /init1/ in your document templates for reliable positioning.

curl -X POST https://api.propper.ai/v1/sign/agreements \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Employment Contract with Anchor Tabs",
"status": "SENT",
"emailSubject": "Please sign: Employment Contract",
"emailMessage": "Please review and sign the attached contract.",
"type": "SEQUENTIAL",
"recipients": [
{
"email": "john.smith@example.com",
"name": "John Smith",
"role": "Employee",
"order": 1,
"tabs": [
{
"type": "SIGNATURE",
"pageIndex": 0,
"anchorString": "/sig1/",
"anchorXOffset": 0,
"anchorYOffset": -10,
"isRequired": true,
"label": "EmployeeSignature"
},
{
"type": "DATE_SIGNED",
"pageIndex": 0,
"anchorString": "/date1/",
"anchorXOffset": 0,
"anchorYOffset": 0,
"label": "EmployeeSignDate"
},
{
"type": "TEXT",
"pageIndex": 0,
"anchorString": "Job Title:",
"anchorXOffset": 100,
"anchorYOffset": 0,
"isRequired": true,
"label": "EmployeeTitle"
},
{
"type": "INITIAL",
"pageIndex": 0,
"anchorString": "/init1/",
"anchorXOffset": 0,
"anchorYOffset": 0,
"label": "EmployeeInitials"
},
{
"type": "CHECKBOX",
"pageIndex": 0,
"anchorString": "I agree to the terms",
"anchorXOffset": -25,
"anchorYOffset": 0,
"isRequired": true,
"label": "AgreeToTerms"
}
]
},
{
"email": "jane.doe@company.com",
"name": "Jane Doe",
"role": "Manager",
"order": 2,
"tabs": [
{
"type": "SIGNATURE",
"pageIndex": 0,
"anchorString": "/sig2/",
"anchorXOffset": 0,
"anchorYOffset": -10,
"isRequired": true,
"label": "ManagerSignature"
},
{
"type": "DATE_SIGNED",
"pageIndex": 0,
"anchorString": "/date2/",
"anchorXOffset": 0,
"anchorYOffset": 0,
"label": "ManagerSignDate"
}
]
}
],
"documents": [
{
"name": "Employment_Contract.pdf",
"documentBase64": "<base64-encoded-pdf-content>",
"mimeType": "application/pdf",
"order": 1
}
]
}'

Tab Types Reference

TypeDescription
SIGNATURESignature field - recipient draws or types signature
INITIALInitials field - recipient adds initials
DATE_SIGNEDAuto-populated date when recipient signs
TEXTText input field for free-form text
NUMBERNumeric input field
CHECKBOXCheckbox field
RADIORadio button (use with groupName for radio groups)
DROPDOWNDropdown list selection (use with options)
EMAILEmail input field
FULL_NAMEAuto-populated from recipient name
ATTACHMENTFile attachment field
FORMULACalculated field based on other tab values

Positioning Options

XY Coordinates

FieldDescription
pageIndex0-based page index
rect.xHorizontal position in PDF points from left edge
rect.yVertical position in PDF points from top edge
rect.widthWidth in PDF points
rect.heightHeight in PDF points

Anchor Text

FieldDescription
pageIndex0-based page index (first page where anchor is found)
anchorStringText to search for in the document
anchorXOffsetHorizontal offset from anchor in PDF points
anchorYOffsetVertical offset from anchor in PDF points
anchorIgnoreIfNotPresentIf true, tab is skipped if anchor not found
anchorCaseSensitiveIf true, anchor search is case-sensitive
anchorMatchWholeWordIf true, anchor must match whole word

Common Tab Properties

PropertyDescription
typeTab type (required) - see table above
pageIndex0-based page index (required)
isRequiredWhether tab must be completed (default: true)
labelUnique identifier for the tab
placeholderPlaceholder text for input fields
valuePre-filled value
fontFamilyFont family name
fontSizeFont size in points
fontColorFont color (hex or named)
bold / italic / underlineText styling (true/false)
optionsArray of {label, value} for dropdown/radio fields
groupNameGroup name for radio buttons

Status Options

StatusDescription
CREATEDCreates a draft agreement (default)
SENTCreates and immediately sends to recipients

Error Responses

ScenarioResponse
Missing requirements{"error": "Agreement created but failed to send. Check that all required fields are present (recipients, documents)."}
Invalid document{"error": "Failed to upload document: Contract.pdf"}
Unauthorized{"error": "Unauthorized"}

Limits

LimitValue
Max documents10
Max document size25 MB
Max name length255 characters
Max subject length255 characters
Max message length2,000 characters
Max tabs per recipient100

Next Steps