Install
openclaw skills install signnowSignNow 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.
openclaw skills install signnowAccess the SignNow API with managed OAuth authentication. Upload documents, send signature invites, manage templates, and automate e-signature workflows.
# Get current user info
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.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
https://api.maton.ai/signnow/{resource}
Maton proxies requests to api.signnow.com and automatically injects your OAuth token.
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"
Manage your SignNow OAuth connections at https://api.maton.ai.
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.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
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'app': 'signnow'}).encode()
req = urllib.request.Request('https://api.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
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.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": "{connection_id}",
"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.
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.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
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://api.maton.ai/signnow/user')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Maton-Connection', '{connection_id}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
If you have multiple connections, always include this header to ensure requests go to the intended account.
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 /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": []
}
]
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://api.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 /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": []
}
PUT /signnow/document/{document_id}
Content-Type: application/json
{
"document_name": "Updated Contract Name"
}
Response:
{
"id": "c63a7bc73f03449c987bf0feaa36e96212408352",
"signatures": [],
"texts": [],
"checks": []
}
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 /signnow/document/{document_id}/historyfull
Response:
[
{
"unique_id": "c4eb89d84b2b407ba8ec1cf4d25b8b435bcef69d",
"user_id": "59cce130e93a4e9488522ca67e3a6779f3e48a72",
"document_id": "c63a7bc73f03449c987bf0feaa36e96212408352",
"email": "chris@example.com",
"created": 1770598603,
"event": "created_document"
}
]
POST /signnow/document/{document_id}/move
Content-Type: application/json
{
"folder_id": "5e2798bdd3d642c3aefebe333bb5b723d6db01a4"
}
Response:
{
"result": "success"
}
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 /signnow/document/{document_id}
Response:
{
"status": "success"
}
POST /signnow/template
Content-Type: application/json
{
"document_id": "c63a7bc73f03449c987bf0feaa36e96212408352",
"document_name": "Contract Template"
}
Response:
{
"id": "47941baee4f74784bc1d37c25e88836fc38ed501"
}
POST /signnow/template/{template_id}/copy
Content-Type: application/json
{
"document_name": "New Contract from Template"
}
Response:
{
"id": "08f5f4a2cc1a4d6c8a986adbf90be2308807d4ae",
"name": "New Contract from Template"
}
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 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.
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 /signnow/folder/{folder_id}
Response:
{
"id": "5e2798bdd3d642c3aefebe333bb5b723d6db01a4",
"name": "Documents",
"user_id": "59cce130e93a4e9488522ca67e3a6779f3e48a72",
"parent_id": "2ea71a3a9d06470d8e5ec0df6122971f47db7706",
"system_folder": true,
"folders": [],
"total_documents": 5,
"documents": [...]
}
GET /signnow/event_subscription
Response:
{
"subscriptions": [
{
"id": "b1d6700dfb0444ed9196e913b2515ae8d5f731a7",
"event": "document.complete",
"created": "1770598678",
"callback_url": "https://example.com/webhook"
}
]
}
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 createddocument.update - Document updateddocument.delete - Document deleteddocument.complete - Document signed by all partiesinvite.create - Invite sentinvite.update - Invite updatedDELETE /signnow/event_subscription/{subscription_id}
Response:
{
"id": "b1d6700dfb0444ed9196e913b2515ae8d5f731a7",
"status": "deleted"
}
const response = await fetch(
'https://api.maton.ai/signnow/user',
{
headers: {
'Authorization': `Bearer ${process.env.MATON_API_KEY}`
}
}
);
const data = await response.json();
import os
import requests
response = requests.get(
'https://api.maton.ai/signnow/user',
headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'}
)
data = response.json()
import os
import requests
with open('document.pdf', 'rb') as f:
response = requests.post(
'https://api.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']}")
import os
import requests
doc_id = "c63a7bc73f03449c987bf0feaa36e96212408352"
response = requests.post(
f'https://api.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']}")
jq or other commands, environment variables like $MATON_API_KEY may not expand correctly in some shell environments| 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."
}
]
}
MATON_API_KEY environment variable is set:echo $MATON_API_KEY
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.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
signnow. For example:https://api.maton.ai/signnow/userhttps://api.maton.ai/user