v1.0.2

SignNow

byungkyu byungkyu ← All skills

SignNow API integration with managed OAuth. E-signature platform for sending, signing, and managing documents. Use this skill when users want to upload documents, send signature invites, create templates, or manage e-signature workflows. For other third party apps, use the api-gateway skill (https://clawhub.ai/byungkyu/api-gateway). Requires network access and valid Maton API key.

Downloads
1.4k
Stars
1
Versions
3
Updated
2026-02-24

Install

npx clawhub@latest install signnow

Documentation

SignNow

Access the SignNow API with managed OAuth authentication. Upload documents, send signature invites, manage templates, and automate e-signature workflows.

Quick Start

Get current user info

python <<'EOF'

import urllib.request, os, json

req = urllib.request.Request('https://gateway.maton.ai/signnow/user')

req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')

print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))

EOF

Base URL

https://gateway.maton.ai/signnow/{resource}

The gateway proxies requests to api.signnow.com and automatically injects your OAuth token.

Authentication

All requests require the Maton API key in the Authorization header:

Authorization: Bearer $MATON_API_KEY
Environment Variable: Set your API key as MATON_API_KEY:
export MATON_API_KEY="YOUR_API_KEY"

Getting Your API Key

1. Sign in or create an account at [maton.ai](https://maton.ai)

2. Go to [maton.ai/settings](https://maton.ai/settings)

3. Copy your API key

Connection Management

Manage your SignNow OAuth connections at https://ctrl.maton.ai.

List Connections

python <<'EOF'

import urllib.request, os, json

req = urllib.request.Request('https://ctrl.maton.ai/connections?app=signnow&status=ACTIVE')

req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')

print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))

EOF

Create Connection

python <<'EOF'

import urllib.request, os, json

data = json.dumps({'app': 'signnow'}).encode()

req = urllib.request.Request('https://ctrl.maton.ai/connections', data=data, method='POST')

req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')

req.add_header('Content-Type', 'application/json')

print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))

EOF

Get Connection

python <<'EOF'

import urllib.request, os, json

req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}')

req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')

print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))

EOF

Response:
{

"connection": {

"connection_id": "5ff5474b-5f21-41ba-8bf3-afb33cce5a75",

"status": "ACTIVE",

"creation_time": "2026-02-08T20:47:23.019763Z",

"last_updated_time": "2026-02-08T20:50:32.210896Z",

"url": "https://connect.maton.ai/?session_token=...",

"app": "signnow",

"metadata": {}

}

}

Open the returned url in a browser to complete OAuth authorization.

Delete Connection

python <<'EOF'

import urllib.request, os, json

req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}', method='DELETE')

req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')

print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))

EOF

Specifying Connection

If you have multiple SignNow connections, specify which one to use with the Maton-Connection header:

python <<'EOF'

import urllib.request, os, json

req = urllib.request.Request('https://gateway.maton.ai/signnow/user')

req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')

req.add_header('Maton-Connection', '5ff5474b-5f21-41ba-8bf3-afb33cce5a75')

print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))

EOF

If omitted, the gateway uses the default (oldest) active connection.

API Reference

User Operations

#### Get Current User

GET /signnow/user
Response:
{

"id": "59cce130e93a4e9488522ca67e3a6779f3e48a72",

"first_name": "Chris",

"last_name": "Kim",

"active": "1",

"verified": true,

"emails": ["chris@example.com"],

"primary_email": "chris@example.com",

"document_count": 0,

"subscriptions": [...],

"teams": [...],

"organization": {...}

}

#### Get User Documents

GET /signnow/user/documents
Response:
[

{

"id": "c63a7bc73f03449c987bf0feaa36e96212408352",

"document_name": "Contract",

"page_count": "3",

"created": "1770598603",

"updated": "1770598603",

"original_filename": "contract.pdf",

"owner": "chris@example.com",

"template": false,

"roles": [],

"field_invites": [],

"signatures": []

}

]

Document Operations

#### Upload Document

Documents must be uploaded as multipart form data with a PDF file:

python <<'EOF'

import urllib.request, os, json

def encode_multipart_formdata(files):

boundary = '----WebKitFormBoundary7MA4YWxkTrZu0gW'

lines = []

for (key, filename, content) in files:

lines.append(f'--{boundary}'.encode())

lines.append(f'Content-Disposition: form-data; name="{key}"; filename="{filename}"'.encode())

lines.append(b'Content-Type: application/pdf')

lines.append(b'')

lines.append(content)

lines.append(f'--{boundary}--'.encode())

lines.append(b'')

body = b'\r\n'.join(lines)

content_type = f'multipart/form-data; boundary={boundary}'

return content_type, body

with open('document.pdf', 'rb') as f:

file_content = f.read()

content_type, body = encode_multipart_formdata([('file', 'document.pdf', file_content)])

req = urllib.request.Request('https://gateway.maton.ai/signnow/document', data=body, method='POST')

req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')

req.add_header('Content-Type', content_type)

print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))

EOF

Response:
{

"id": "c63a7bc73f03449c987bf0feaa36e96212408352"

}

#### Get Document

GET /signnow/document/{document_id}
Response:
{

"id": "c63a7bc73f03449c987bf0feaa36e96212408352",

"document_name": "Contract",

"page_count": "3",

"created": "1770598603",

"updated": "1770598603",

"original_filename": "contract.pdf",

"owner": "chris@example.com",

"template": false,

"roles": [],

"viewer_roles": [],

"attachments": [],

"fields": [],

"signatures": [],

"texts": [],

"checks": []

}

#### Update Document

PUT /signnow/document/{document_id}

Content-Type: application/json

{

"document_name": "Updated Contract Name"

}

Response:
{

"id": "c63a7bc73f03449c987bf0feaa36e96212408352",

"signatures": [],

"texts": [],

"checks": []

}

#### Download Document

GET /signnow/document/{document_id}/download?type=collapsed

Returns the PDF file as binary data.

Query parameters:

  • -type - Download type: collapsed (flattened PDF), zip (all pages as images)

#### Get Document History

GET /signnow/document/{document_id}/historyfull
Response:
[

{

"unique_id": "c4eb89d84b2b407ba8ec1cf4d25b8b435bcef69d",

"user_id": "59cce130e93a4e9488522ca67e3a6779f3e48a72",

"document_id": "c63a7bc73f03449c987bf0feaa36e96212408352",

"email": "chris@example.com",

"created": 1770598603,

"event": "created_document"

}

]

#### Move Document to Folder

POST /signnow/document/{document_id}/move

Content-Type: application/json

{

"folder_id": "5e2798bdd3d642c3aefebe333bb5b723d6db01a4"

}

Response:
{

"result": "success"

}

#### Merge Documents

Combines multiple documents into a single PDF:

POST /signnow/document/merge

Content-Type: application/json

{

"name": "Merged Document",

"document_ids": ["doc_id_1", "doc_id_2"]

}

Returns the merged PDF as binary data.

#### Delete Document

DELETE /signnow/document/{document_id}
Response:
{

"status": "success"

}

Template Operations

#### Create Template from Document

POST /signnow/template

Content-Type: application/json

{

"document_id": "c63a7bc73f03449c987bf0feaa36e96212408352",

"document_name": "Contract Template"

}

Response:
{

"id": "47941baee4f74784bc1d37c25e88836fc38ed501"

}

#### Create Document from Template

POST /signnow/template/{template_id}/copy

Content-Type: application/json

{

"document_name": "New Contract from Template"

}

Response:
{

"id": "08f5f4a2cc1a4d6c8a986adbf90be2308807d4ae",

"name": "New Contract from Template"

}

Signature Invite Operations

#### Send Freeform Invite

Send a document for signature:

POST /signnow/document/{document_id}/invite

Content-Type: application/json

{

"to": "signer@example.com",

"from": "sender@example.com"

}

Response:
{

"result": "success",

"id": "c38a57f08f2e48d98b5de52f75f7b1dd0a074c00",

"callback_url": "none"

}

Note: Custom subject and message require a paid subscription plan.

#### Create Signing Link

Create an embeddable signing link (requires document fields):

POST /signnow/link

Content-Type: application/json

{

"document_id": "c63a7bc73f03449c987bf0feaa36e96212408352"

}

Note: Document must have signature fields added before creating a signing link.

Folder Operations

#### Get All Folders

GET /signnow/folder
Response:
{

"id": "2ea71a3a9d06470d8e5ec0df6122971f47db7706",

"name": "Root",

"system_folder": true,

"folders": [

{

"id": "5e2798bdd3d642c3aefebe333bb5b723d6db01a4",

"name": "Documents",

"document_count": "5",

"template_count": "2"

},

{

"id": "fafdef6de6d947fc84627e4ddeed6987bfeee02d",

"name": "Templates",

"document_count": "0",

"template_count": "3"

},

{

"id": "6063688b1e724a25aa98befcc3f2cb7795be7da1",

"name": "Trash Bin",

"document_count": "0"

}

],

"total_documents": 0,

"documents": []

}

#### Get Folder by ID

GET /signnow/folder/{folder_id}
Response:
{

"id": "5e2798bdd3d642c3aefebe333bb5b723d6db01a4",

"name": "Documents",

"user_id": "59cce130e93a4e9488522ca67e3a6779f3e48a72",

"parent_id": "2ea71a3a9d06470d8e5ec0df6122971f47db7706",

"system_folder": true,

"folders": [],

"total_documents": 5,

"documents": [...]

}

Webhook (Event Subscription) Operations

#### List Event Subscriptions

GET /signnow/event_subscription
Response:
{

"subscriptions": [

{

"id": "b1d6700dfb0444ed9196e913b2515ae8d5f731a7",

"event": "document.complete",

"created": "1770598678",

"callback_url": "https://example.com/webhook"

}

]

}

#### Create Event Subscription

POST /signnow/event_subscription

Content-Type: application/json

{

"event": "document.complete",

"callback_url": "https://example.com/webhook"

}

Response:
{

"id": "b1d6700dfb0444ed9196e913b2515ae8d5f731a7",

"created": 1770598678

}

Available Events:
  • -document.create - Document created
  • -document.update - Document updated
  • -document.delete - Document deleted
  • -document.complete - Document signed by all parties
  • -invite.create - Invite sent
  • -invite.update - Invite updated

#### Delete Event Subscription

DELETE /signnow/event_subscription/{subscription_id}
Response:
{

"id": "b1d6700dfb0444ed9196e913b2515ae8d5f731a7",

"status": "deleted"

}

Code Examples

JavaScript

const response = await fetch(

'https://gateway.maton.ai/signnow/user',

{

headers: {

'Authorization': Bearer ${process.env.MATON_API_KEY}

}

}

);

const data = await response.json();

Python

import os

import requests

response = requests.get(

'https://gateway.maton.ai/signnow/user',

headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'}

)

data = response.json()

Python (Upload Document)

import os

import requests

with open('document.pdf', 'rb') as f:

response = requests.post(

'https://gateway.maton.ai/signnow/document',

headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'},

files={'file': ('document.pdf', f, 'application/pdf')}

)

doc = response.json()

print(f"Uploaded document: {doc['id']}")

Python (Send Invite)

import os

import requests

doc_id = "c63a7bc73f03449c987bf0feaa36e96212408352"

response = requests.post(

f'https://gateway.maton.ai/signnow/document/{doc_id}/invite',

headers={

'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}',

'Content-Type': 'application/json'

},

json={

'to': 'signer@example.com',

'from': 'sender@example.com'

}

)

result = response.json()

print(f"Invite sent: {result['id']}")

Notes

  • -Documents must be in PDF format for upload
  • -Supported file types: PDF, DOC, DOCX, ODT, RTF, PNG, JPG
  • -System folders (Documents, Templates, Archive, Trash Bin) cannot be renamed or deleted
  • -Creating signing links requires documents to have signature fields
  • -Custom invite subject/message requires a paid subscription
  • -Rate limit in development mode: 500 requests/hour per application
  • -IMPORTANT: When piping curl output to jq or other commands, environment variables like $MATON_API_KEY may not expand correctly in some shell environments

Error Handling

| Status | Meaning |

|--------|---------|

| 400 | Missing SignNow connection or bad request |

| 401 | Invalid or missing Maton API key |

| 403 | Insufficient permissions or subscription required |

| 404 | Resource not found |

| 405 | Method not allowed |

| 429 | Rate limited |

| 4xx/5xx | Passthrough error from SignNow API |

SignNow errors include detailed messages:

{

"errors": [

{

"code": 65578,

"message": "Invalid file type."

}

]

}

Troubleshooting: API Key Issues

1. Check that the MATON_API_KEY environment variable is set:

echo $MATON_API_KEY

2. Verify the API key is valid by listing connections:

python <<'EOF'

import urllib.request, os, json

req = urllib.request.Request('https://ctrl.maton.ai/connections')

req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')

print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))

EOF

Troubleshooting: Invalid App Name

1. Ensure your URL path starts with signnow. For example:

  • -Correct: https://gateway.maton.ai/signnow/user
  • -Incorrect: https://gateway.maton.ai/user

Resources

  • -[SignNow API Reference](https://docs.signnow.com/docs/signnow/reference)
  • -[SignNow Developer Portal](https://www.signnow.com/developers)
  • -[SignNow Postman Collection](https://github.com/signnow/postman-collection)
  • -[SignNow SDKs](https://github.com/signnow)
  • -[Maton Community](https://discord.com/invite/dBfFAcefs2)
  • -[Maton Support](mailto:support@maton.ai)

Launch an agent with SignNow on Termo.