RapidCents Developer Documentation
Contracts Integration Guide
v1.0 · REST API

Contracts

Create & send digital contracts · E-signatures · Linked payments & subscriptions

Summary

Contracts enable merchants to create digital agreements that customers must sign before a payment can proceed. A contract can be linked to a Payment Link (one-time payment), a Subscription (recurring payment), or an Installment plan. The customer receives the contract via email, signs it electronically (with optional document upload), and is then directed to complete payment.

📝

Contracts support HTML-based templates with {{ signature }} and {{ input::placeholder }} placeholders, allowing merchants to build reusable contract templates. The system automatically generates a contract number in CT-YYYYMMDD#### format.

Contract Lifecycle

  1. Create — Merchant creates a contract with HTML content, customer, amount, and payment type. A Payment Link or Subscription is automatically created and linked.
  2. Notify — Customer receives an email with a link to view and sign the contract. The email includes a “Pay Now” button directing them to the signing page.
  3. View — Customer opens the contract and sees the agreement with signature fields and input fields. If a document upload is required, a file upload area is displayed.
  4. Sign — Customer fills in all signature and input fields, optionally uploads a supporting document, and submits. The contract status changes to SIGNED.
  5. Pay — After signing, the customer is directed to the linked Payment Link or Subscription page to complete payment. The payment page will not allow access until the contract is signed.

Contract Statuses

UNSIGNED

Initial state. Contract has been created and sent to the customer but has not yet been signed.

SIGNED

Customer has signed the contract. The linked payment page is now accessible.

If a Payment Link has an UNSIGNED contract, the payment page will throw a PaymentLinkContractUnsignedException and prevent the customer from paying.

Processing Flow

MerchantCreates Contract
RapidCentsSends Email Notification
CustomerViews & Signs
CustomerCompletes Payment
RapidCentsProcesses Payment
Visa · Mastercard · Discover · Amex

Authentication

Merchant API (Private)

All merchant-facing endpoints require a valid Bearer token and are scoped to a business:

Authorization: Bearer {access_token}
Content-Type: application/json

Base URL pattern: /api/{business_id}/contracts

Customer API (Public)

Public endpoints for viewing and signing contracts do not require authentication:

GET  /api/contracts/{contract_id}/show
POST /api/contracts/{contract_id}/sign

Create Contract

POST /api/{business}/contracts

Request Body

FieldTypeRequiredDescription
contractstringYesHTML content of the contract. Supports {{ signature }} and {{ input::Label }} placeholders.
customerIdstring (UUID)YesCustomer who will receive and sign the contract
amountnumberYesPayment amount linked to the contract
includeDocumentbooleanYesWhether to require the customer to upload a document when signing
paymentTypestringYes1 = Payment Link, 2 = Subscription, 3 = Installment
sequencenumberIf type 2 or 3Payment frequency (see Payment Types)
startDatedateIf type 2 or 3First charge date for recurring payments
numberOfBillsnumberIf type 3Total number of installments
descriptionstringNoContract description
paymentMethodstringNoDefault: rapidcents_direct_manual_card_entry
customInvoiceNumberstringNoCustom invoice number for the linked Payment Link
Request
POST /api/{business}/contracts
Content-Type: application/json
Authorization: Bearer {token}

{
  "contract": "<h1>Service Agreement</h1><p>I, {{ input::Full Name }}, agree to...</p><p>Signature: {{ signature }}</p>",
  "customerId": "customer-uuid",
  "amount": 500.00,
  "includeDocument": true,
  "paymentType": "1",
  "description": "Monthly service agreement"
}
Response — 200 OK
{
  "ok": true,
  "contract": {
    "id": "contract-uuid",
    "contract_number": "CT-202602190001",
    "status": "UNSIGNED",
    "payment_link_id": "payment-link-uuid",
    "has_file": true,
    "created_at": "2026-02-19T12:00:00.000000Z"
  },
  "message": "Contract created successfully"
}

List Contracts

GET /api/{business}/contracts

Returns a paginated list of contracts. Includes permission flags for the current user.

Response — 200 OK
{
  "ok": true,
  "contracts": { /* paginated collection */ },
  "business": { /* business object */ },
  "isRoleAdmin": true,
  "canUpdateContract": true,
  "canDeleteContract": true,
  "filters": { "fromDate": null, "toDate": null }
}

Edit Contract (Form Data)

GET /api/{business}/contracts/{contract}/edit

Returns the contract data in a format suitable for populating an edit form.

Update Contract

PUT /api/{business}/contracts/{contract}

Updates an existing contract. Only editable if the contract has not been signed and its linked payment has not been completed.

Delete Contract

DELETE /api/{business}/contracts/{contract}

Deletes a contract and its linked Payment Link or Subscription. Only deletable if the linked payment has not been completed.

Response — 200 OK
{
  "ok": true,
  "message": "Contract deleted successfully"
}

Contract Details

GET /api/{business}/contracts/{contract}/details

Returns full details of a contract, including its signed content and linked payment information.

Export Contracts

GET /api/{business}/contracts/export

Returns all contracts matching the filter criteria in a JSON format suitable for CSV or spreadsheet export.

Contract Templates

List Templates

GET /api/{business}/contracts/templates

Returns all saved contract templates for the business.

Save Template

POST /api/{business}/contracts/storeTemplate

Saves the current contract content as a reusable template. The placeholder [Your business name] is automatically replaced with the business legal name when used.

View Contract (Public)

GET /api/contracts/{contract}/show

Loads the contract for the customer to view and sign. Returns the contract HTML, business branding (logo), customer email, and 3D Secure configuration.

If the contract has been deleted, or if its linked Payment Link has already been paid, the endpoint will return an error.

Response — 200 OK
{
  "ok": true,
  "contract": {
    "id": "contract-uuid",
    "content": "<h1>Service Agreement</h1>...",
    "status": "UNSIGNED",
    "has_file": true
  },
  "business": { "legal_name": "Acme Corp" },
  "logo": "https://s3.amazonaws.com/...",
  "dddSecure": true,
  "customerEmail": "[email protected]"
}

Sign Contract (Public)

POST /api/contracts/{contract}/sign

Submits the customer's signatures, input values, and optional document. Uses multipart/form-data when a file is included.

Request Body

FieldTypeRequiredDescription
signature-1, signature-2, ...stringYesOne field per {{ signature }} placeholder in the contract (base64 image)
input-1, input-2, ...stringYesOne field per {{ input::Label }} placeholder
filefileIf requiredSupporting document. Max 100 MB. Accepted: PDF, JPEG, PNG, GIF, BMP, WebP, TIFF, SVG, ICO

Placeholders are matched in order of appearance. The first {{ signature }} maps to signature-1, the second to signature-2, and so on. Similarly for {{ input::... }} fields.

Response — 200 OK
{
  "ok": true,
  "signed_content": "<h1>Service Agreement</h1><p>I, John Doe, agree to...</p>...",
  "message": "Contract signed successfully"
}

Payment Types

TypeValueDescriptionAdditional Fields
Payment Link1One-time payment via Payment LinkNone
Subscription2Recurring payment with a frequencysequence, startDate
Installment3Fixed number of recurring paymentssequence, startDate, numberOfBills

Frequency Options (Sequence)

ValueFrequency
1Weekly
2Bi-Weekly
3Monthly
4Quarterly
5Twice a Year
6Annual

Template Placeholders

PlaceholderPurposeCustomer Action
{{ signature }}E-signature fieldCustomer draws or uploads a signature
{{ input::Full Name }}Text input with label “Full Name”Customer types a value
{{ input::Date }}Text input with label “Date”Customer types a value
[Your business name]Auto-replaced with business legal nameAutomatic — no customer action
Example Template
<h1>Service Agreement</h1>
<p>This agreement is entered into between
   <strong>[Your business name]</strong> and
   <strong>{{ input::Full Name }}</strong>.</p>

<p>The customer agrees to the terms outlined herein
   on <strong>{{ input::Date }}</strong>.</p>

<p>Customer Signature:</p>
<p>{{ signature }}</p>

File Upload

When includeDocument is set to true during contract creation, the customer is required to upload a supporting document at signing time.

PropertyValue
Max file size100 MB
Accepted formatsPDF, JPEG, PNG, JPG, GIF, BMP, WebP, TIFF, TIF, SVG, ICO
StorageAmazon S3 (s3-contract disk)
File path{business_id}/contracts/{contract_id}/{filename}
AccessPre-signed URL (30-minute expiry)

All Endpoints

Merchant Endpoints (Authenticated)

MethodEndpointDescription
GET/api/{business}/contractsList contracts
POST/api/{business}/contractsCreate contract
GET/api/{business}/contracts/{id}/editEdit form data
PUT/api/{business}/contracts/{id}Update contract
DELETE/api/{business}/contracts/{id}Delete contract
GET/api/{business}/contracts/{id}/detailsFull details
GET/api/{business}/contracts/exportExport contracts
GET/api/{business}/contracts/templatesList templates
POST/api/{business}/contracts/storeTemplateSave template

Public Endpoints (No Authentication)

MethodEndpointDescription
GET/api/contracts/{contract}/showView contract for signing
POST/api/contracts/{contract}/signSign contract

Error Handling

HTTP CodeScenarioDescription
422Validation errorMissing required fields or invalid data
403Contract unsignedAttempting to pay via a linked Payment Link before signing the contract
404Not foundContract does not exist or has been deleted
409Already paidLinked Payment Link has already been paid
500Server errorUnexpected processing error

Notifications

EventNotificationRecipientContent
Contract created (type 1)PaymentLinkCreatedCustomerEmail with subject “Your Payment Link is Ready”, amount, and a “Pay Now” link
Contract created (type 2 or 3)ReoccurringPaymentCreatedCustomerEmail with subject “Your Recurring payment is Ready”, amount, and a “Pay Now” link

The “Pay Now” link in the notification directs the customer to the contract signing page first. After signing, they are redirected to the payment page.