Introduction
# SignNow
Access the SignNow API with managed OAuth authentication. Upload documents, send signature invites, manage templates, and automate e-signature workflows.
## Quick Start
```bash # 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`:
```bash 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
```bash 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
```bash 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
```bash 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:** ```json { "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
```bash 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:
```bash 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
```bash GET /signnow/user ```
**Response:** ```json { "id": "59cce130e93a4e9488522ca67e3a6779f3e48a72", "first_name": "Chris", "last_name": "Kim", "active": "1", "verified": true, "emails": ["[email protected]"], "primary_email": "[email protected]", "document_count": 0, "subscriptions": [...], "teams": [...], "organization": {...} } ```
#### Get User Documents
```bash GET /signnow/user/documents ```
**Response:** ```json [ { "id": "c63a7bc73f03449c987bf0feaa36e96212408352", "document_name": "Contract", "page_count": "3", "created": "1770598603", "updated": "1770598603", "original_filename": "contract.pdf", "owner": "[email protected]", "template": false, "roles": [], "field_invites": [], "signatures": [] } ] ```
### Document Operations
#### Upload Document
Documents must be uploaded as multipart form data with a PDF file:
```bash 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:** ```json { "id": "c63a7bc73f03449c987bf0feaa36e96212408352" } ```
#### Get Document
```bash GET /signnow/document/{document_id} ```
**Response:** ```json { "id": "c63a7bc73f03449c987bf0feaa36e96212408352", "document_name": "Contract", "page_count": "3", "created": "1770598603", "updated": "1770598603", "original_filename": "contract.pdf", "owner": "[email protected]", "template": false, "roles": [], "viewer_roles": [], "attachments": [], "fields": [], "signatures": [], "texts": [], "checks": [] } ```
#### Update Document
```bash PUT /signnow/document/{document_id} Content-Type: application/json
{ "document_name": "Updated Contract Name" } ```
**Response:** ```json { "id": "c63a7bc73f03449c987bf0feaa36e96212408352", "signatures": [], "texts": [], "checks": [] } ```
#### Download Document
```bash 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
```bash GET /signnow/document/{document_id}/historyfull ```
**Response:** ```json [ { "unique_id": "c4eb89d84b2b407ba8ec1cf4d25b8b435bcef69d", "user_id": "59cce130e93a4e9488522ca67e3a6779f3e48a72", "document_id": "c63a7bc73f03449c987bf0feaa36e96212408352", "email": "[email protected]", "created": 1770598603, "event": "created_document" } ] ```
#### Move Document to Folder
```bash POST /signnow/document/{document_id}/move Content-Type: application/json
{ "folder_id": "5e2798bdd3d642c3aefebe333bb5b723d6db01a4" } ```
**Response:** ```json { "result": "success" } ```
#### Merge Documents
Combines multiple documents into a single PDF:
```bash 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
```bash DELETE /signnow/document/{document_id} ```
**Response:** ```json { "status": "success" } ```
### Template Operations
#### Create Template from Document
```bash POST /signnow/template Content-Type: application/json
{ "document_id": "c63a7bc73f03449c987bf0feaa36e96212408352", "document_name": "Contract Template" } ```
**Response:** ```json { "id": "47941baee4f74784bc1d37c25e88836fc38ed501" } ```
#### Create Document from Template
```bash POST /signnow/template/{template_id}/copy Content-Type: application/json
{ "document_name": "New Contract from Template" } ```
**Response:** ```json { "id": "08f5f4a2cc1a4d6c8a986adbf90be2308807d4ae", "name": "New Contract from Template" } ```
### Signature Invite Operations
#### Send Freeform Invite
Send a document for signature:
```bash POST /signnow/document/{document_id}/invite Content-Type: application/json
{ "to": "[email protected]", "from": "[email protected]" } ```
**Response:** ```json { "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):
```bash 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
```bash GET /signnow/folder ```
**Response:** ```json { "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
```bash GET /signnow/folder/{folder_id} ```
**Response:** ```json { "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
```bash GET /signnow/event_subscription ```
**Response:** ```json { "subscriptions": [ { "id": "b1d6700dfb0444ed9196e913b2515ae8d5f731a7", "event": "document.complete", "created": "1770598678", "callback_url": "https://example.com/webhook" } ] } ```
#### Create Event Subscription
```bash POST /signnow/event_subscription Content-Type: application/json
{ "event": "document.complete", "callback_url": "https://example.com/webhook" } ```
**Response:** ```json { "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
```bash DELETE /signnow/event_subscription/{subscription_id} ```
**Response:** ```json { "id": "b1d6700dfb0444ed9196e913b2515ae8d5f731a7", "status": "deleted" } ```
## Code Examples
### JavaScript
```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
```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)
```python 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)
```python 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': '[email protected]', 'from': '[email protected]' } ) 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: ```json { "errors": [ { "code": 65578, "message": "Invalid file type." } ] } ```
### Troubleshooting: API Key Issues
1. Check that the `MATON_API_KEY` environment variable is set:
```bash echo $MATON_API_KEY ```
2. Verify the API key is valid by listing connections:
```bash 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:[email protected])