GoSignHere API reference

Getting started

Integrate GoSignHere into your workflow

GoSignHere has an API, so it fits into your business and workflows and works with your other products through it.

Create an API key

  1. Sign in to GoSignHere as an owner or admin.
  2. Open Settings, then API and webhooks.
  3. Choose Create key, name it for the system that will use it, and copy the key now. It is shown once.
  4. Send it with every request as Authorization: Bearer gsh_live_....

Every route below is under /api/v1. Successful responses are {"data": ...}; errors are {"error": {"code", "message", "field"}}. The same reference is available as openapi.json.

Base URL: https://app.gosignhere.com. Send JSON with Content-Type: application/json; uploads are multipart/form-data. A first call:

curl

curl 'https://app.gosignhere.com/api/v1/auth/me' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}

r = requests.get('https://app.gosignhere.com/api/v1/auth/me', headers=headers)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/auth/me', {
    method: 'GET',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/auth/me', {
    method: 'GET',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$ch = curl_init('https://app.gosignhere.com/api/v1/auth/me');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
    ],
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Send a document for signature

  1. POST /api/v1/documents with the file. Wait until render_status is ready.
  2. Place the signing fields once in the app (or with PUT /api/v1/documents/{id}/fields); mark the document as a template if you reuse it.
  3. POST /api/v1/packages with the document_id and the signers. They get the email at once.
  4. Listen for webhooks, or poll GET /api/v1/packages/{id}. When it completes, download completed.pdf.

Errors

Every failure has a 4xx or 5xx status and one envelope. field is present when one input is at fault.

{"error": {"code": "validation_failed", "message": "Add between 1 and 8 signers.", "field": "signers"}}
CodeHTTPWhen
validation_failed422A field is missing or malformed; "field" names it.
bad_request400The request itself is malformed (for example a bad If-Match value).
invalid_api_key401The bearer key is unknown or revoked.
unauthenticated401No key and no session.
invalid_credentials401Wrong email or password.
forbidden403Your role or folder access cannot do this.
session_required403The route needs a signed-in session; API keys are refused.
plan_api_disabled403The account plan does not include API access.
email_unverified403Confirm the sender address before sending documents.
csrf_failed403A session call without a valid X-CSRF header (key calls never need it).
not_found404No such object in your account.
document_not_ready409The document is still rendering, or archived.
document_locked409A sent package uses the document, so its file cannot change.
duplicate_document409This file was already uploaded.
not_draft409Only a draft package can be edited this way.
not_editable409The package or signer can no longer be changed.
not_voidable409Only a package in progress can be voided.
not_completed409The package has not completed, so it has no signed PDF yet.
not_ready409The package has a problem; GET /validate lists it.
package_closed409The package is completed, declined, voided or expired.
slug_taken409That name is already used.
precondition_required428A fields write without If-Match: send the fields_revision you loaded.
no_fields422The document has no fields to sign.
signer_missing422A role with fields has no signer.
role_without_fields422A signer has no fields on the document.
bad_hash422A SHA-256 is 64 hexadecimal characters.
file_too_large413Uploads are limited to 25 MB.
send_cap_reached429The plan's monthly send limit is used up.
rate_limited429Too many requests; see Retry-After.
server_error500Something went wrong on our side; safe to retry reads.
render_busy503The PDF renderer is busy; retry in a few seconds.

Rate limits

Each IP address may make 600 requests per minute to the API. Sending is limited to 60 packages per hour per user, and signer resends to 20 per hour per package. Over a limit the answer is 429 with code rate_limited and a Retry-After header in seconds; wait that long, then retry. Plans also cap sends per month (send_cap_reached).

Webhooks

Set a webhook URL under Settings, API and webhooks. We POST a JSON body to it when a package changes state. Answer with any 2xx; anything else is retried 3 times, 2 then 4 minutes apart.

Events:

  • package.completed
  • package.declined
  • package.voided
  • package.test
{
    "event": "package.completed",
    "package": {
        "id": "018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f",
        "status": "completed",
        "title": "Services agreement",
        "completed_at": "2026-10-10T10:45:00Z",
        "pdf_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
        "verify_url": "https://app.gosignhere.com/verify/3f6c1c52-8b0e-4c1a-9a53-0d2f6c1b7e10"
    }
}

Headers: X-GSH-Event, X-GSH-Delivery (a unique id; use it to ignore repeats) and X-GSH-Signature: sha256=<hex>. The signature is the HMAC-SHA256 of the exact raw request body, keyed with your webhook secret (Settings, API and webhooks). Compute it over the raw bytes before parsing the JSON, compare in constant time, and reject a mismatch with 400.

curl

# Queue a package.test delivery to your webhook URL (signed like a real one)
curl -X POST 'https://app.gosignhere.com/api/v1/account/settings/webhook-test' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY'

Python

import hashlib, hmac

def is_genuine(raw_body: bytes, header: str, secret: str) -> bool:
    expected = 'sha256=' + hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, header)

# Flask: is_genuine(request.get_data(), request.headers['X-GSH-Signature'], WEBHOOK_SECRET)

JavaScript

// Runs anywhere with WebCrypto (Cloudflare Workers, Deno, browsers). Keep the secret server-side.
async function isGenuine(rawBody, header, secret) {
  const key = await crypto.subtle.importKey('raw', new TextEncoder().encode(secret), { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);
  const mac = await crypto.subtle.sign('HMAC', key, new TextEncoder().encode(rawBody));
  const hex = [...new Uint8Array(mac)].map(b => b.toString(16).padStart(2, '0')).join('');
  return header === 'sha256=' + hex;
}

Node.js

const crypto = require('node:crypto');

function isGenuine(rawBody, header, secret) {
  const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
  const a = Buffer.from(expected), b = Buffer.from(header || '');
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

// Express: app.post('/hooks/gsh', express.raw({ type: 'application/json' }), (req, res) => {
//   if (!isGenuine(req.body, req.get('X-GSH-Signature'), process.env.GSH_WEBHOOK_SECRET)) return res.sendStatus(400);
//   res.sendStatus(204); });

PHP

<?php
$raw = file_get_contents('php://input');
$expected = 'sha256=' . hash_hmac('sha256', $raw, getenv('GSH_WEBHOOK_SECRET'));
if (!hash_equals($expected, $_SERVER['HTTP_X_GSH_SIGNATURE'] ?? '')) {
    http_response_code(400);
    exit;
}
$event = json_decode($raw, true);   // $event['event'], $event['package']['verify_url'], ...
http_response_code(204);

Validate a signed PDF

Anyone can check a signed PDF without an account at https://app.gosignhere.com/verify/{id}: drop the file on the page and your browser fingerprints it (nothing is uploaded) and compares it with the sealed PDF's SHA-256.

The id is the package's GUID (the same value the package's API id carries). You get it as verify_url in every webhook payload, in the completed mail the signers and sender receive, and from the keyed route GET /api/v1/packages/{id}/verify, which also returns pdf_sha256, the SHA-256 of the sealed PDF. A copy is genuine when its own SHA-256 equals pdf_sha256. To let the server do the comparison, add ?hash=<sha256 of your copy> to that route; the answer says whether it matches.

Fetch the package's verification record and print the two values:

curl

curl 'https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/verify' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY' \
  | jq -r '.data | .verify_url, .pdf_sha256'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}

r = requests.get('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/verify', headers=headers)
r.raise_for_status()
d = r.json()['data']
print(d['verify_url'])
print(d['pdf_sha256'])

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/verify', {
    method: 'GET',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
    },
  });
  if (!res.ok) throw new Error(await res.text());
  const { data } = await res.json();
  console.log(data.verify_url);
  console.log(data.pdf_sha256);
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/verify', {
    method: 'GET',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
    },
  });
  if (!res.ok) throw new Error(await res.text());
  const { data } = await res.json();
  console.log(data.verify_url);
  console.log(data.pdf_sha256);
}

main();

PHP

<?php
$ch = curl_init('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/verify');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
    ],
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
$data = json_decode($out, true)['data'];
echo $data['verify_url'], "\n", $data['pdf_sha256'], "\n";   // HTTP $status, body {"data": ...}

Reference

Authentication notes: API key or session routes accept Authorization: Bearer gsh_live_...; Signed-in session only routes refuse keys (session_required) and need the session cookie plus an X-CSRF header on writes; No key needed routes are open. Success bodies are {"data": ...}. Placeholders such as {id} are shown as a sample GUID (018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f) in the samples; page numbers are plain integers.

Account

GET /api/v1/account #

API key or session.

The account: name, plan, usage.

No request fields.

curl

curl 'https://app.gosignhere.com/api/v1/account' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}

r = requests.get('https://app.gosignhere.com/api/v1/account', headers=headers)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/account', {
    method: 'GET',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/account', {
    method: 'GET',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$ch = curl_init('https://app.gosignhere.com/api/v1/account');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
    ],
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "account": {
            "id": "018f6c1e-7b31-7c4d-8e3f-7a8b9caebfc0",
            "name": "Analytical Engines Ltd",
            "type": "business",
            "plan": "beta"
        }
    }
}

PATCH /api/v1/account #

Signed-in session only (API keys are refused). Roles: owner, admin.

Rename the account.

NameTypeDescription
namestringrequired2 to 120 characters.

curl

curl -X PATCH 'https://app.gosignhere.com/api/v1/account' \
  -H 'Cookie: gsh_s=YOUR_SESSION' \
  -H 'X-CSRF: YOUR_CSRF_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"name":"Analytical Engines Inc"}'

Python

import requests

headers = {
    'Cookie': 'gsh_s=YOUR_SESSION',
    'X-CSRF': 'YOUR_CSRF_TOKEN',
}
payload = {
    'name': 'Analytical Engines Inc',
}

r = requests.patch('https://app.gosignhere.com/api/v1/account', headers=headers, json=payload)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/account', {
    method: 'PATCH',
    headers: {
      'Cookie': 'gsh_s=YOUR_SESSION',
      'X-CSRF': 'YOUR_CSRF_TOKEN',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "name": "Analytical Engines Inc"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/account', {
    method: 'PATCH',
    headers: {
      'Cookie': 'gsh_s=YOUR_SESSION',
      'X-CSRF': 'YOUR_CSRF_TOKEN',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "name": "Analytical Engines Inc"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$payload = [
    'name' => 'Analytical Engines Inc',
];
$ch = curl_init('https://app.gosignhere.com/api/v1/account');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'PATCH',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Cookie: gsh_s=YOUR_SESSION',
        'X-CSRF: YOUR_CSRF_TOKEN',
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "account": {
            "id": "018f6c1e-7b31-7c4d-8e3f-7a8b9caebfc0",
            "name": "Analytical Engines Inc"
        }
    }
}

DELETE /api/v1/account #

Signed-in session only (API keys are refused). Roles: owner.

Delete the account and everything in it. Owner only; needs the password.

NameTypeDescription
passwordstringrequiredThe owner's password.

curl

curl -X DELETE 'https://app.gosignhere.com/api/v1/account' \
  -H 'Cookie: gsh_s=YOUR_SESSION' \
  -H 'X-CSRF: YOUR_CSRF_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"password":"a long passphrase here"}'

Python

import requests

headers = {
    'Cookie': 'gsh_s=YOUR_SESSION',
    'X-CSRF': 'YOUR_CSRF_TOKEN',
}
payload = {
    'password': 'a long passphrase here',
}

r = requests.delete('https://app.gosignhere.com/api/v1/account', headers=headers, json=payload)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/account', {
    method: 'DELETE',
    headers: {
      'Cookie': 'gsh_s=YOUR_SESSION',
      'X-CSRF': 'YOUR_CSRF_TOKEN',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "password": "a long passphrase here"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/account', {
    method: 'DELETE',
    headers: {
      'Cookie': 'gsh_s=YOUR_SESSION',
      'X-CSRF': 'YOUR_CSRF_TOKEN',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "password": "a long passphrase here"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$payload = [
    'password' => 'a long passphrase here',
];
$ch = curl_init('https://app.gosignhere.com/api/v1/account');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'DELETE',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Cookie: gsh_s=YOUR_SESSION',
        'X-CSRF: YOUR_CSRF_TOKEN',
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "deleted": true
    }
}

GET /api/v1/account/settings #

API key or session.

Sending defaults, notification switches and the webhook URL.

No request fields.

curl

curl 'https://app.gosignhere.com/api/v1/account/settings' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}

r = requests.get('https://app.gosignhere.com/api/v1/account/settings', headers=headers)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/account/settings', {
    method: 'GET',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/account/settings', {
    method: 'GET',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$ch = curl_init('https://app.gosignhere.com/api/v1/account/settings');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
    ],
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "settings": {
            "default_expiry_days": 30,
            "reminder_days": 3,
            "default_subject": "",
            "default_message": "",
            "notify_viewed": false,
            "notify_signed": true,
            "notify_completed": true,
            "notify_declined": true,
            "webhook_url": "https://example.com/hooks/gsh",
            "webhook_secret_set": true
        }
    }
}

PATCH /api/v1/account/settings #

Signed-in session only (API keys are refused). Roles: owner, admin.

Change any of the settings; only the keys you send change.

NameTypeDescription
webhook_urlstringoptionalHTTPS URL for webhooks; empty clears it.
default_expiry_daysintegeroptional0 (never) to 365.
reminder_daysintegeroptionalDays between reminders; 0 turns them off.
default_subjectstringoptionalEmail subject for new packages.
default_messagestringoptionalMessage for new packages.
notify_signedbooleanoptionalEmail me when someone signs.

curl

curl -X PATCH 'https://app.gosignhere.com/api/v1/account/settings' \
  -H 'Cookie: gsh_s=YOUR_SESSION' \
  -H 'X-CSRF: YOUR_CSRF_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"webhook_url":"https://example.com/hooks/gsh","default_expiry_days":14}'

Python

import requests

headers = {
    'Cookie': 'gsh_s=YOUR_SESSION',
    'X-CSRF': 'YOUR_CSRF_TOKEN',
}
payload = {
    'webhook_url': 'https://example.com/hooks/gsh',
    'default_expiry_days': 14,
}

r = requests.patch('https://app.gosignhere.com/api/v1/account/settings', headers=headers, json=payload)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/account/settings', {
    method: 'PATCH',
    headers: {
      'Cookie': 'gsh_s=YOUR_SESSION',
      'X-CSRF': 'YOUR_CSRF_TOKEN',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "webhook_url": "https://example.com/hooks/gsh",
        "default_expiry_days": 14
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/account/settings', {
    method: 'PATCH',
    headers: {
      'Cookie': 'gsh_s=YOUR_SESSION',
      'X-CSRF': 'YOUR_CSRF_TOKEN',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "webhook_url": "https://example.com/hooks/gsh",
        "default_expiry_days": 14
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$payload = [
    'webhook_url' => 'https://example.com/hooks/gsh',
    'default_expiry_days' => 14,
];
$ch = curl_init('https://app.gosignhere.com/api/v1/account/settings');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'PATCH',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Cookie: gsh_s=YOUR_SESSION',
        'X-CSRF: YOUR_CSRF_TOKEN',
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "settings": {
            "default_expiry_days": 30,
            "reminder_days": 3,
            "default_subject": "",
            "default_message": "",
            "notify_viewed": false,
            "notify_signed": true,
            "notify_completed": true,
            "notify_declined": true,
            "webhook_url": "https://example.com/hooks/gsh",
            "webhook_secret_set": true
        }
    }
}

POST /api/v1/account/settings/webhook-test #

Signed-in session only (API keys are refused). Roles: owner, admin.

Queue a package.test delivery to your webhook URL.

No request fields.

curl

curl -X POST 'https://app.gosignhere.com/api/v1/account/settings/webhook-test' \
  -H 'Cookie: gsh_s=YOUR_SESSION' \
  -H 'X-CSRF: YOUR_CSRF_TOKEN'

Python

import requests

headers = {
    'Cookie': 'gsh_s=YOUR_SESSION',
    'X-CSRF': 'YOUR_CSRF_TOKEN',
}

r = requests.post('https://app.gosignhere.com/api/v1/account/settings/webhook-test', headers=headers)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/account/settings/webhook-test', {
    method: 'POST',
    headers: {
      'Cookie': 'gsh_s=YOUR_SESSION',
      'X-CSRF': 'YOUR_CSRF_TOKEN',
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/account/settings/webhook-test', {
    method: 'POST',
    headers: {
      'Cookie': 'gsh_s=YOUR_SESSION',
      'X-CSRF': 'YOUR_CSRF_TOKEN',
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$ch = curl_init('https://app.gosignhere.com/api/v1/account/settings/webhook-test');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Cookie: gsh_s=YOUR_SESSION',
        'X-CSRF: YOUR_CSRF_TOKEN',
    ],
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 202

{
    "data": {
        "delivery": {
            "id": "018f6c1e-7b33-7c4d-8e3f-9aabbcd0d1e2",
            "event": "package.test",
            "status": "queued"
        }
    }
}

GET /api/v1/account/users #

Signed-in session only (API keys are refused).

The people on the account.

No request fields.

curl

curl 'https://app.gosignhere.com/api/v1/account/users' \
  -H 'Cookie: gsh_s=YOUR_SESSION' \
  -H 'X-CSRF: YOUR_CSRF_TOKEN'

Python

import requests

headers = {
    'Cookie': 'gsh_s=YOUR_SESSION',
    'X-CSRF': 'YOUR_CSRF_TOKEN',
}

r = requests.get('https://app.gosignhere.com/api/v1/account/users', headers=headers)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/account/users', {
    method: 'GET',
    headers: {
      'Cookie': 'gsh_s=YOUR_SESSION',
      'X-CSRF': 'YOUR_CSRF_TOKEN',
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/account/users', {
    method: 'GET',
    headers: {
      'Cookie': 'gsh_s=YOUR_SESSION',
      'X-CSRF': 'YOUR_CSRF_TOKEN',
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$ch = curl_init('https://app.gosignhere.com/api/v1/account/users');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Cookie: gsh_s=YOUR_SESSION',
        'X-CSRF: YOUR_CSRF_TOKEN',
    ],
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "users": [
            {
                "id": "018f6c1e-7b30-7c4d-8e3f-6a7b8c9daebf",
                "name": "Grace Hopper",
                "email": "grace@example.com",
                "role": "admin",
                "status": "active"
            }
        ]
    }
}

POST /api/v1/account/users/invite #

Signed-in session only (API keys are refused). Roles: owner, admin.

Invite a teammate by email.

NameTypeDescription
emailstringrequiredTheir address.
namestringoptionalTheir name.
rolestringoptionaladmin or member.

curl

curl -X POST 'https://app.gosignhere.com/api/v1/account/users/invite' \
  -H 'Cookie: gsh_s=YOUR_SESSION' \
  -H 'X-CSRF: YOUR_CSRF_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"email":"grace@example.com","name":"Grace Hopper","role":"member"}'

Python

import requests

headers = {
    'Cookie': 'gsh_s=YOUR_SESSION',
    'X-CSRF': 'YOUR_CSRF_TOKEN',
}
payload = {
    'email': 'grace@example.com',
    'name': 'Grace Hopper',
    'role': 'member',
}

r = requests.post('https://app.gosignhere.com/api/v1/account/users/invite', headers=headers, json=payload)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/account/users/invite', {
    method: 'POST',
    headers: {
      'Cookie': 'gsh_s=YOUR_SESSION',
      'X-CSRF': 'YOUR_CSRF_TOKEN',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "email": "grace@example.com",
        "name": "Grace Hopper",
        "role": "member"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/account/users/invite', {
    method: 'POST',
    headers: {
      'Cookie': 'gsh_s=YOUR_SESSION',
      'X-CSRF': 'YOUR_CSRF_TOKEN',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "email": "grace@example.com",
        "name": "Grace Hopper",
        "role": "member"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$payload = [
    'email' => 'grace@example.com',
    'name' => 'Grace Hopper',
    'role' => 'member',
];
$ch = curl_init('https://app.gosignhere.com/api/v1/account/users/invite');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Cookie: gsh_s=YOUR_SESSION',
        'X-CSRF: YOUR_CSRF_TOKEN',
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 201

{
    "data": {
        "user": {
            "id": "018f6c1e-7b30-7c4d-8e3f-6a7b8c9daebf",
            "name": "Grace Hopper",
            "email": "grace@example.com",
            "role": "admin",
            "status": "active"
        }
    }
}

POST /api/v1/account/users/{id}/resend-invite #

Signed-in session only (API keys are refused). Roles: owner, admin.

Send a pending invitation again.

No request fields.

curl

curl -X POST 'https://app.gosignhere.com/api/v1/account/users/018f6c1e-7b30-7c4d-8e3f-6a7b8c9daebf/resend-invite' \
  -H 'Cookie: gsh_s=YOUR_SESSION' \
  -H 'X-CSRF: YOUR_CSRF_TOKEN'

Python

import requests

headers = {
    'Cookie': 'gsh_s=YOUR_SESSION',
    'X-CSRF': 'YOUR_CSRF_TOKEN',
}

r = requests.post('https://app.gosignhere.com/api/v1/account/users/018f6c1e-7b30-7c4d-8e3f-6a7b8c9daebf/resend-invite', headers=headers)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/account/users/018f6c1e-7b30-7c4d-8e3f-6a7b8c9daebf/resend-invite', {
    method: 'POST',
    headers: {
      'Cookie': 'gsh_s=YOUR_SESSION',
      'X-CSRF': 'YOUR_CSRF_TOKEN',
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/account/users/018f6c1e-7b30-7c4d-8e3f-6a7b8c9daebf/resend-invite', {
    method: 'POST',
    headers: {
      'Cookie': 'gsh_s=YOUR_SESSION',
      'X-CSRF': 'YOUR_CSRF_TOKEN',
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$ch = curl_init('https://app.gosignhere.com/api/v1/account/users/018f6c1e-7b30-7c4d-8e3f-6a7b8c9daebf/resend-invite');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Cookie: gsh_s=YOUR_SESSION',
        'X-CSRF: YOUR_CSRF_TOKEN',
    ],
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "sent": true
    }
}

PATCH /api/v1/account/users/{id} #

Signed-in session only (API keys are refused). Roles: owner, admin.

Change a teammate's role or switch them off.

NameTypeDescription
rolestringoptionaladmin or member.
activebooleanoptionalfalse disables the user.

curl

curl -X PATCH 'https://app.gosignhere.com/api/v1/account/users/018f6c1e-7b30-7c4d-8e3f-6a7b8c9daebf' \
  -H 'Cookie: gsh_s=YOUR_SESSION' \
  -H 'X-CSRF: YOUR_CSRF_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"role":"admin"}'

Python

import requests

headers = {
    'Cookie': 'gsh_s=YOUR_SESSION',
    'X-CSRF': 'YOUR_CSRF_TOKEN',
}
payload = {
    'role': 'admin',
}

r = requests.patch('https://app.gosignhere.com/api/v1/account/users/018f6c1e-7b30-7c4d-8e3f-6a7b8c9daebf', headers=headers, json=payload)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/account/users/018f6c1e-7b30-7c4d-8e3f-6a7b8c9daebf', {
    method: 'PATCH',
    headers: {
      'Cookie': 'gsh_s=YOUR_SESSION',
      'X-CSRF': 'YOUR_CSRF_TOKEN',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "role": "admin"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/account/users/018f6c1e-7b30-7c4d-8e3f-6a7b8c9daebf', {
    method: 'PATCH',
    headers: {
      'Cookie': 'gsh_s=YOUR_SESSION',
      'X-CSRF': 'YOUR_CSRF_TOKEN',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "role": "admin"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$payload = [
    'role' => 'admin',
];
$ch = curl_init('https://app.gosignhere.com/api/v1/account/users/018f6c1e-7b30-7c4d-8e3f-6a7b8c9daebf');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'PATCH',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Cookie: gsh_s=YOUR_SESSION',
        'X-CSRF: YOUR_CSRF_TOKEN',
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "user": {
            "id": "018f6c1e-7b30-7c4d-8e3f-6a7b8c9daebf",
            "name": "Grace Hopper",
            "email": "grace@example.com",
            "role": "admin",
            "status": "active"
        }
    }
}

POST /api/v1/account/transfer-ownership #

Signed-in session only (API keys are refused). Roles: owner.

Hand the account to another user. Owner only; needs the password.

NameTypeDescription
user_iduuidrequiredThe new owner.
passwordstringrequiredYour password.

curl

curl -X POST 'https://app.gosignhere.com/api/v1/account/transfer-ownership' \
  -H 'Cookie: gsh_s=YOUR_SESSION' \
  -H 'X-CSRF: YOUR_CSRF_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"user_id":"018f6c1e-7b30-7c4d-8e3f-6a7b8c9daebf","password":"a long passphrase here"}'

Python

import requests

headers = {
    'Cookie': 'gsh_s=YOUR_SESSION',
    'X-CSRF': 'YOUR_CSRF_TOKEN',
}
payload = {
    'user_id': '018f6c1e-7b30-7c4d-8e3f-6a7b8c9daebf',
    'password': 'a long passphrase here',
}

r = requests.post('https://app.gosignhere.com/api/v1/account/transfer-ownership', headers=headers, json=payload)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/account/transfer-ownership', {
    method: 'POST',
    headers: {
      'Cookie': 'gsh_s=YOUR_SESSION',
      'X-CSRF': 'YOUR_CSRF_TOKEN',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "user_id": "018f6c1e-7b30-7c4d-8e3f-6a7b8c9daebf",
        "password": "a long passphrase here"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/account/transfer-ownership', {
    method: 'POST',
    headers: {
      'Cookie': 'gsh_s=YOUR_SESSION',
      'X-CSRF': 'YOUR_CSRF_TOKEN',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "user_id": "018f6c1e-7b30-7c4d-8e3f-6a7b8c9daebf",
        "password": "a long passphrase here"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$payload = [
    'user_id' => '018f6c1e-7b30-7c4d-8e3f-6a7b8c9daebf',
    'password' => 'a long passphrase here',
];
$ch = curl_init('https://app.gosignhere.com/api/v1/account/transfer-ownership');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Cookie: gsh_s=YOUR_SESSION',
        'X-CSRF: YOUR_CSRF_TOKEN',
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "transferred": true
    }
}

GET /api/v1/account/api-keys #

Signed-in session only (API keys are refused). Roles: owner, admin.

Your API keys (prefix and last use only, never the secret).

No request fields.

curl

curl 'https://app.gosignhere.com/api/v1/account/api-keys' \
  -H 'Cookie: gsh_s=YOUR_SESSION' \
  -H 'X-CSRF: YOUR_CSRF_TOKEN'

Python

import requests

headers = {
    'Cookie': 'gsh_s=YOUR_SESSION',
    'X-CSRF': 'YOUR_CSRF_TOKEN',
}

r = requests.get('https://app.gosignhere.com/api/v1/account/api-keys', headers=headers)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/account/api-keys', {
    method: 'GET',
    headers: {
      'Cookie': 'gsh_s=YOUR_SESSION',
      'X-CSRF': 'YOUR_CSRF_TOKEN',
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/account/api-keys', {
    method: 'GET',
    headers: {
      'Cookie': 'gsh_s=YOUR_SESSION',
      'X-CSRF': 'YOUR_CSRF_TOKEN',
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$ch = curl_init('https://app.gosignhere.com/api/v1/account/api-keys');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Cookie: gsh_s=YOUR_SESSION',
        'X-CSRF: YOUR_CSRF_TOKEN',
    ],
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "keys": [
            {
                "id": "018f6c1e-7b32-7c4d-8e3f-8a9babcfc0d1",
                "name": "CRM sync",
                "prefix": "gsh_live_ab12",
                "created_at": "2026-10-10T09:00:00Z",
                "last_used_at": null
            }
        ]
    }
}

POST /api/v1/account/api-keys #

Signed-in session only (API keys are refused). Roles: owner, admin.

Create a key. The full key is in this response only.

NameTypeDescription
namestringrequiredWhat the key is for.

curl

curl -X POST 'https://app.gosignhere.com/api/v1/account/api-keys' \
  -H 'Cookie: gsh_s=YOUR_SESSION' \
  -H 'X-CSRF: YOUR_CSRF_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"name":"CRM sync"}'

Python

import requests

headers = {
    'Cookie': 'gsh_s=YOUR_SESSION',
    'X-CSRF': 'YOUR_CSRF_TOKEN',
}
payload = {
    'name': 'CRM sync',
}

r = requests.post('https://app.gosignhere.com/api/v1/account/api-keys', headers=headers, json=payload)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/account/api-keys', {
    method: 'POST',
    headers: {
      'Cookie': 'gsh_s=YOUR_SESSION',
      'X-CSRF': 'YOUR_CSRF_TOKEN',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "name": "CRM sync"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/account/api-keys', {
    method: 'POST',
    headers: {
      'Cookie': 'gsh_s=YOUR_SESSION',
      'X-CSRF': 'YOUR_CSRF_TOKEN',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "name": "CRM sync"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$payload = [
    'name' => 'CRM sync',
];
$ch = curl_init('https://app.gosignhere.com/api/v1/account/api-keys');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Cookie: gsh_s=YOUR_SESSION',
        'X-CSRF: YOUR_CSRF_TOKEN',
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 201

{
    "data": {
        "id": "018f6c1e-7b32-7c4d-8e3f-8a9babcfc0d1",
        "name": "CRM sync",
        "prefix": "gsh_live_ab12",
        "key": "gsh_live_ab12EXAMPLEEXAMPLEEXAMPLE"
    }
}

DELETE /api/v1/account/api-keys/{id} #

Signed-in session only (API keys are refused). Roles: owner, admin.

Revoke a key. It stops working at once.

No request fields.

curl

curl -X DELETE 'https://app.gosignhere.com/api/v1/account/api-keys/018f6c1e-7b32-7c4d-8e3f-8a9babcfc0d1' \
  -H 'Cookie: gsh_s=YOUR_SESSION' \
  -H 'X-CSRF: YOUR_CSRF_TOKEN'

Python

import requests

headers = {
    'Cookie': 'gsh_s=YOUR_SESSION',
    'X-CSRF': 'YOUR_CSRF_TOKEN',
}

r = requests.delete('https://app.gosignhere.com/api/v1/account/api-keys/018f6c1e-7b32-7c4d-8e3f-8a9babcfc0d1', headers=headers)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/account/api-keys/018f6c1e-7b32-7c4d-8e3f-8a9babcfc0d1', {
    method: 'DELETE',
    headers: {
      'Cookie': 'gsh_s=YOUR_SESSION',
      'X-CSRF': 'YOUR_CSRF_TOKEN',
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/account/api-keys/018f6c1e-7b32-7c4d-8e3f-8a9babcfc0d1', {
    method: 'DELETE',
    headers: {
      'Cookie': 'gsh_s=YOUR_SESSION',
      'X-CSRF': 'YOUR_CSRF_TOKEN',
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$ch = curl_init('https://app.gosignhere.com/api/v1/account/api-keys/018f6c1e-7b32-7c4d-8e3f-8a9babcfc0d1');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'DELETE',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Cookie: gsh_s=YOUR_SESSION',
        'X-CSRF: YOUR_CSRF_TOKEN',
    ],
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "revoked": true
    }
}

Auth

POST /api/v1/auth/register #

No key needed.

Create an account and its first owner. A confirmation email follows.

NameTypeDescription
namestringrequiredYour name, up to 120 characters.
emailstringrequiredSign-in address.
passwordstringrequiredAt least 10 characters.
account_namestringrequiredCompany or workspace name.
account_typestringrequiredbusiness or personal.
invite_codestringoptionalOnly when registration is closed.

curl

curl -X POST 'https://app.gosignhere.com/api/v1/auth/register' \
  -H 'Content-Type: application/json' \
  -d '{"name":"Ada Lovelace","email":"ada@example.com","password":"a long passphrase here","account_name":"Analytical Engines Ltd","account_type":"business"}'

Python

import requests

payload = {
    'name': 'Ada Lovelace',
    'email': 'ada@example.com',
    'password': 'a long passphrase here',
    'account_name': 'Analytical Engines Ltd',
    'account_type': 'business',
}

r = requests.post('https://app.gosignhere.com/api/v1/auth/register', json=payload)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/auth/register', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "name": "Ada Lovelace",
        "email": "ada@example.com",
        "password": "a long passphrase here",
        "account_name": "Analytical Engines Ltd",
        "account_type": "business"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/auth/register', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "name": "Ada Lovelace",
        "email": "ada@example.com",
        "password": "a long passphrase here",
        "account_name": "Analytical Engines Ltd",
        "account_type": "business"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$payload = [
    'name' => 'Ada Lovelace',
    'email' => 'ada@example.com',
    'password' => 'a long passphrase here',
    'account_name' => 'Analytical Engines Ltd',
    'account_type' => 'business',
];
$ch = curl_init('https://app.gosignhere.com/api/v1/auth/register');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 201

{
    "data": {
        "user": {
            "id": "018f6c1e-7b30-7c4d-8e3f-6a7b8c9daebf",
            "name": "Ada Lovelace",
            "email": "ada@example.com",
            "role": "owner"
        },
        "verification_sent": true
    }
}

POST /api/v1/auth/verify-email #

No key needed.

Confirm an email address with the token from the email.

NameTypeDescription
tokenstringrequiredFrom the confirmation link.

curl

curl -X POST 'https://app.gosignhere.com/api/v1/auth/verify-email' \
  -H 'Content-Type: application/json' \
  -d '{"token":"tok_EXAMPLE"}'

Python

import requests

payload = {
    'token': 'tok_EXAMPLE',
}

r = requests.post('https://app.gosignhere.com/api/v1/auth/verify-email', json=payload)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/auth/verify-email', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "token": "tok_EXAMPLE"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/auth/verify-email', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "token": "tok_EXAMPLE"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$payload = [
    'token' => 'tok_EXAMPLE',
];
$ch = curl_init('https://app.gosignhere.com/api/v1/auth/verify-email');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "verified": true
    }
}

POST /api/v1/auth/verify-email/resend #

No key needed.

Send the confirmation email again.

NameTypeDescription
emailstringrequiredThe address to confirm.

curl

curl -X POST 'https://app.gosignhere.com/api/v1/auth/verify-email/resend' \
  -H 'Content-Type: application/json' \
  -d '{"email":"ada@example.com"}'

Python

import requests

payload = {
    'email': 'ada@example.com',
}

r = requests.post('https://app.gosignhere.com/api/v1/auth/verify-email/resend', json=payload)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/auth/verify-email/resend', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "email": "ada@example.com"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/auth/verify-email/resend', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "email": "ada@example.com"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$payload = [
    'email' => 'ada@example.com',
];
$ch = curl_init('https://app.gosignhere.com/api/v1/auth/verify-email/resend');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "sent": true
    }
}

POST /api/v1/auth/login #

No key needed.

Start a session. Returns the CSRF token to send as X-CSRF on later writes; the session cookie is set.

NameTypeDescription
emailstringrequiredAccount email.
passwordstringrequiredAccount password.

curl

curl -X POST 'https://app.gosignhere.com/api/v1/auth/login' \
  -H 'Content-Type: application/json' \
  -d '{"email":"ada@example.com","password":"a long passphrase here"}'

Python

import requests

payload = {
    'email': 'ada@example.com',
    'password': 'a long passphrase here',
}

r = requests.post('https://app.gosignhere.com/api/v1/auth/login', json=payload)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/auth/login', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "email": "ada@example.com",
        "password": "a long passphrase here"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/auth/login', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "email": "ada@example.com",
        "password": "a long passphrase here"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$payload = [
    'email' => 'ada@example.com',
    'password' => 'a long passphrase here',
];
$ch = curl_init('https://app.gosignhere.com/api/v1/auth/login');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "user": {
            "id": "018f6c1e-7b30-7c4d-8e3f-6a7b8c9daebf",
            "name": "Ada Lovelace",
            "role": "owner"
        },
        "csrf": "EXAMPLE_CSRF_TOKEN"
    }
}

POST /api/v1/auth/logout #

Signed-in session only (API keys are refused).

End the session.

No request fields.

curl

curl -X POST 'https://app.gosignhere.com/api/v1/auth/logout' \
  -H 'Cookie: gsh_s=YOUR_SESSION' \
  -H 'X-CSRF: YOUR_CSRF_TOKEN'

Python

import requests

headers = {
    'Cookie': 'gsh_s=YOUR_SESSION',
    'X-CSRF': 'YOUR_CSRF_TOKEN',
}

r = requests.post('https://app.gosignhere.com/api/v1/auth/logout', headers=headers)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/auth/logout', {
    method: 'POST',
    headers: {
      'Cookie': 'gsh_s=YOUR_SESSION',
      'X-CSRF': 'YOUR_CSRF_TOKEN',
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/auth/logout', {
    method: 'POST',
    headers: {
      'Cookie': 'gsh_s=YOUR_SESSION',
      'X-CSRF': 'YOUR_CSRF_TOKEN',
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$ch = curl_init('https://app.gosignhere.com/api/v1/auth/logout');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Cookie: gsh_s=YOUR_SESSION',
        'X-CSRF: YOUR_CSRF_TOKEN',
    ],
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "logged_out": true
    }
}

GET /api/v1/auth/me #

API key or session.

The signed-in user and account (works with a key too).

No request fields.

curl

curl 'https://app.gosignhere.com/api/v1/auth/me' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}

r = requests.get('https://app.gosignhere.com/api/v1/auth/me', headers=headers)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/auth/me', {
    method: 'GET',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/auth/me', {
    method: 'GET',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$ch = curl_init('https://app.gosignhere.com/api/v1/auth/me');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
    ],
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "user": {
            "id": "018f6c1e-7b30-7c4d-8e3f-6a7b8c9daebf",
            "name": "Grace Hopper",
            "email": "grace@example.com",
            "role": "admin",
            "status": "active"
        },
        "account": {
            "id": "018f6c1e-7b31-7c4d-8e3f-7a8b9caebfc0",
            "name": "Analytical Engines Ltd",
            "plan": "beta"
        }
    }
}

POST /api/v1/auth/password/forgot #

No key needed.

Email a password reset link. Always answers the same, whether or not the address exists.

NameTypeDescription
emailstringrequiredAccount email.

curl

curl -X POST 'https://app.gosignhere.com/api/v1/auth/password/forgot' \
  -H 'Content-Type: application/json' \
  -d '{"email":"ada@example.com"}'

Python

import requests

payload = {
    'email': 'ada@example.com',
}

r = requests.post('https://app.gosignhere.com/api/v1/auth/password/forgot', json=payload)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/auth/password/forgot', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "email": "ada@example.com"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/auth/password/forgot', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "email": "ada@example.com"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$payload = [
    'email' => 'ada@example.com',
];
$ch = curl_init('https://app.gosignhere.com/api/v1/auth/password/forgot');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "sent": true
    }
}

POST /api/v1/auth/password/reset #

No key needed.

Set a new password with the token from the reset email.

NameTypeDescription
tokenstringrequiredFrom the reset link.
passwordstringrequiredThe new password.

curl

curl -X POST 'https://app.gosignhere.com/api/v1/auth/password/reset' \
  -H 'Content-Type: application/json' \
  -d '{"token":"tok_EXAMPLE","password":"a new long passphrase"}'

Python

import requests

payload = {
    'token': 'tok_EXAMPLE',
    'password': 'a new long passphrase',
}

r = requests.post('https://app.gosignhere.com/api/v1/auth/password/reset', json=payload)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/auth/password/reset', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "token": "tok_EXAMPLE",
        "password": "a new long passphrase"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/auth/password/reset', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "token": "tok_EXAMPLE",
        "password": "a new long passphrase"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$payload = [
    'token' => 'tok_EXAMPLE',
    'password' => 'a new long passphrase',
];
$ch = curl_init('https://app.gosignhere.com/api/v1/auth/password/reset');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "reset": true
    }
}

POST /api/v1/auth/password/change #

Signed-in session only (API keys are refused).

Change your password. Other sessions end.

NameTypeDescription
current_passwordstringrequiredThe password now.
new_passwordstringrequiredThe new password.

curl

curl -X POST 'https://app.gosignhere.com/api/v1/auth/password/change' \
  -H 'Cookie: gsh_s=YOUR_SESSION' \
  -H 'X-CSRF: YOUR_CSRF_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"current_password":"old passphrase","new_password":"a new long passphrase"}'

Python

import requests

headers = {
    'Cookie': 'gsh_s=YOUR_SESSION',
    'X-CSRF': 'YOUR_CSRF_TOKEN',
}
payload = {
    'current_password': 'old passphrase',
    'new_password': 'a new long passphrase',
}

r = requests.post('https://app.gosignhere.com/api/v1/auth/password/change', headers=headers, json=payload)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/auth/password/change', {
    method: 'POST',
    headers: {
      'Cookie': 'gsh_s=YOUR_SESSION',
      'X-CSRF': 'YOUR_CSRF_TOKEN',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "current_password": "old passphrase",
        "new_password": "a new long passphrase"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/auth/password/change', {
    method: 'POST',
    headers: {
      'Cookie': 'gsh_s=YOUR_SESSION',
      'X-CSRF': 'YOUR_CSRF_TOKEN',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "current_password": "old passphrase",
        "new_password": "a new long passphrase"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$payload = [
    'current_password' => 'old passphrase',
    'new_password' => 'a new long passphrase',
];
$ch = curl_init('https://app.gosignhere.com/api/v1/auth/password/change');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Cookie: gsh_s=YOUR_SESSION',
        'X-CSRF: YOUR_CSRF_TOKEN',
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "changed": true
    }
}

POST /api/v1/auth/email/change #

Signed-in session only (API keys are refused).

Start an email change; the new address must confirm.

NameTypeDescription
new_emailstringrequiredThe new address.
passwordstringrequiredYour password.

curl

curl -X POST 'https://app.gosignhere.com/api/v1/auth/email/change' \
  -H 'Cookie: gsh_s=YOUR_SESSION' \
  -H 'X-CSRF: YOUR_CSRF_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"new_email":"ada@new.example.com","password":"a long passphrase here"}'

Python

import requests

headers = {
    'Cookie': 'gsh_s=YOUR_SESSION',
    'X-CSRF': 'YOUR_CSRF_TOKEN',
}
payload = {
    'new_email': 'ada@new.example.com',
    'password': 'a long passphrase here',
}

r = requests.post('https://app.gosignhere.com/api/v1/auth/email/change', headers=headers, json=payload)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/auth/email/change', {
    method: 'POST',
    headers: {
      'Cookie': 'gsh_s=YOUR_SESSION',
      'X-CSRF': 'YOUR_CSRF_TOKEN',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "new_email": "ada@new.example.com",
        "password": "a long passphrase here"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/auth/email/change', {
    method: 'POST',
    headers: {
      'Cookie': 'gsh_s=YOUR_SESSION',
      'X-CSRF': 'YOUR_CSRF_TOKEN',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "new_email": "ada@new.example.com",
        "password": "a long passphrase here"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$payload = [
    'new_email' => 'ada@new.example.com',
    'password' => 'a long passphrase here',
];
$ch = curl_init('https://app.gosignhere.com/api/v1/auth/email/change');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Cookie: gsh_s=YOUR_SESSION',
        'X-CSRF: YOUR_CSRF_TOKEN',
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "sent": true
    }
}

POST /api/v1/auth/invite/accept #

No key needed.

Accept a team invitation: set your name and password.

NameTypeDescription
tokenstringrequiredFrom the invitation email.
namestringrequiredYour name.
passwordstringrequiredYour password.

curl

curl -X POST 'https://app.gosignhere.com/api/v1/auth/invite/accept' \
  -H 'Content-Type: application/json' \
  -d '{"token":"tok_EXAMPLE","name":"Grace Hopper","password":"a long passphrase here"}'

Python

import requests

payload = {
    'token': 'tok_EXAMPLE',
    'name': 'Grace Hopper',
    'password': 'a long passphrase here',
}

r = requests.post('https://app.gosignhere.com/api/v1/auth/invite/accept', json=payload)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/auth/invite/accept', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "token": "tok_EXAMPLE",
        "name": "Grace Hopper",
        "password": "a long passphrase here"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/auth/invite/accept', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "token": "tok_EXAMPLE",
        "name": "Grace Hopper",
        "password": "a long passphrase here"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$payload = [
    'token' => 'tok_EXAMPLE',
    'name' => 'Grace Hopper',
    'password' => 'a long passphrase here',
];
$ch = curl_init('https://app.gosignhere.com/api/v1/auth/invite/accept');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "accepted": true
    }
}

Documents

GET /api/v1/documents #

API key or session.

List documents. Filter with the query parameters.

NameTypeDescription
folder_id queryuuidoptionalOnly this folder.
q querystringoptionalSearch the title.
status querystringoptionaldraft, ready or archived.

curl

curl 'https://app.gosignhere.com/api/v1/documents?folder_id=018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}

r = requests.get('https://app.gosignhere.com/api/v1/documents?folder_id=018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f', headers=headers)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/documents?folder_id=018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f', {
    method: 'GET',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/documents?folder_id=018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f', {
    method: 'GET',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$ch = curl_init('https://app.gosignhere.com/api/v1/documents?folder_id=018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
    ],
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "documents": [
            {
                "id": "018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f",
                "title": "Services agreement",
                "folder_id": "018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f",
                "folder_name": "Contracts",
                "status": "ready",
                "kind": "upload",
                "created_by": "018f6c1e-7b30-7c4d-8e3f-6a7b8c9daebf",
                "created_by_name": "Grace Hopper",
                "created_at": "2026-10-10T09:30:00Z",
                "updated_at": "2026-10-10T09:31:00Z",
                "tags": [],
                "render_status": "ready",
                "render_error": null,
                "page_count": 3,
                "source_name": "agreement.pdf",
                "source_bytes": 184320
            }
        ]
    }
}

GET /api/v1/documents/{id} #

API key or session.

One document and its processing state.

No request fields.

curl

curl 'https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}

r = requests.get('https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f', headers=headers)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f', {
    method: 'GET',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f', {
    method: 'GET',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$ch = curl_init('https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
    ],
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "document": {
            "id": "018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f",
            "title": "Services agreement",
            "folder_id": "018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f",
            "folder_name": "Contracts",
            "status": "ready",
            "kind": "upload",
            "created_by": "018f6c1e-7b30-7c4d-8e3f-6a7b8c9daebf",
            "created_by_name": "Grace Hopper",
            "created_at": "2026-10-10T09:30:00Z",
            "updated_at": "2026-10-10T09:31:00Z",
            "tags": [],
            "render_status": "ready",
            "render_error": null,
            "page_count": 3,
            "source_name": "agreement.pdf",
            "source_bytes": 184320
        }
    }
}

PATCH /api/v1/documents/{id} #

API key or session.

Rename or move a document.

NameTypeDescription
titlestringoptionalNew title.
folder_iduuidoptionalNew folder.

curl

curl -X PATCH 'https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"title":"Services agreement v2"}'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}
payload = {
    'title': 'Services agreement v2',
}

r = requests.patch('https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f', headers=headers, json=payload)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f', {
    method: 'PATCH',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "title": "Services agreement v2"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f', {
    method: 'PATCH',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "title": "Services agreement v2"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$payload = [
    'title' => 'Services agreement v2',
];
$ch = curl_init('https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'PATCH',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "document": {
            "id": "018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f",
            "title": "Services agreement",
            "folder_id": "018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f",
            "folder_name": "Contracts",
            "status": "ready",
            "kind": "upload",
            "created_by": "018f6c1e-7b30-7c4d-8e3f-6a7b8c9daebf",
            "created_by_name": "Grace Hopper",
            "created_at": "2026-10-10T09:30:00Z",
            "updated_at": "2026-10-10T09:31:00Z",
            "tags": [],
            "render_status": "ready",
            "render_error": null,
            "page_count": 3,
            "source_name": "agreement.pdf",
            "source_bytes": 184320
        }
    }
}

POST /api/v1/documents/{id}/archive #

API key or session.

Archive a document (it leaves the library; sent packages keep their copy).

No request fields.

curl

curl -X POST 'https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/archive' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}

r = requests.post('https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/archive', headers=headers)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/archive', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/archive', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$ch = curl_init('https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/archive');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
    ],
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "document": {
            "status": "archived",
            "id": "018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f",
            "title": "Services agreement",
            "folder_id": "018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f",
            "folder_name": "Contracts",
            "kind": "upload",
            "created_by": "018f6c1e-7b30-7c4d-8e3f-6a7b8c9daebf",
            "created_by_name": "Grace Hopper",
            "created_at": "2026-10-10T09:30:00Z",
            "updated_at": "2026-10-10T09:31:00Z",
            "tags": [],
            "render_status": "ready",
            "render_error": null,
            "page_count": 3,
            "source_name": "agreement.pdf",
            "source_bytes": 184320
        }
    }
}

PUT /api/v1/documents/{id}/tags #

API key or session.

Replace the document's tags.

NameTypeDescription
tagsarrayrequiredTag ids.

curl

curl -X PUT 'https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/tags' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"tags":["018f6c1e-7b2f-7c4d-8e3f-5a6b7c8d9eaf"]}'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}
payload = {
    'tags': [
        '018f6c1e-7b2f-7c4d-8e3f-5a6b7c8d9eaf',
    ],
}

r = requests.put('https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/tags', headers=headers, json=payload)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/tags', {
    method: 'PUT',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "tags": [
            "018f6c1e-7b2f-7c4d-8e3f-5a6b7c8d9eaf"
        ]
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/tags', {
    method: 'PUT',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "tags": [
            "018f6c1e-7b2f-7c4d-8e3f-5a6b7c8d9eaf"
        ]
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$payload = [
    'tags' => [
        '018f6c1e-7b2f-7c4d-8e3f-5a6b7c8d9eaf',
    ],
];
$ch = curl_init('https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/tags');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'PUT',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "document": {
            "tags": [
                {
                    "id": "018f6c1e-7b2f-7c4d-8e3f-5a6b7c8d9eaf",
                    "name": "Legal"
                }
            ],
            "id": "018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f",
            "title": "Services agreement",
            "folder_id": "018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f",
            "folder_name": "Contracts",
            "status": "ready",
            "kind": "upload",
            "created_by": "018f6c1e-7b30-7c4d-8e3f-6a7b8c9daebf",
            "created_by_name": "Grace Hopper",
            "created_at": "2026-10-10T09:30:00Z",
            "updated_at": "2026-10-10T09:31:00Z",
            "render_status": "ready",
            "render_error": null,
            "page_count": 3,
            "source_name": "agreement.pdf",
            "source_bytes": 184320
        }
    }
}

POST /api/v1/documents #

API key or session.

Upload a document (PDF, Word, Excel, PowerPoint, OpenDocument, RTF, text, PNG or JPG; 25 MB) as multipart, or create one from HTML as JSON. Rendering is asynchronous: poll GET /documents/{id} until render_status is ready.

NameTypeDescription
filefilerequiredMultipart form field.
folder_iduuidoptionalTarget folder; defaults to your home folder.
titlestringoptionalDefaults to the file name. Required with html.
htmlstringoptionalJSON alternative to file: the document body as HTML.

curl

curl -X POST 'https://app.gosignhere.com/api/v1/documents' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY' \
  -F 'file=@agreement.pdf' \
  -F 'folder_id=018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}

r = requests.post('https://app.gosignhere.com/api/v1/documents', headers=headers, files={'file': open('agreement.pdf', 'rb')}, data={'folder_id': '018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f'})
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const form = new FormData();
  form.append('file', fileInput.files[0]);   // an <input type="file">
  form.append('folder_id', '018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f');
  const res = await fetch('https://app.gosignhere.com/api/v1/documents', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
    },
    body: form,
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

const fs = require('node:fs');

async function main() {
  const form = new FormData();
  form.append('file', new Blob([fs.readFileSync('agreement.pdf')]), 'agreement.pdf');
  form.append('folder_id', '018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f');
  const res = await fetch('https://app.gosignhere.com/api/v1/documents', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
    },
    body: form,
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$form = [
    'file' => new CURLFile('agreement.pdf'),
    'folder_id' => '018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f',
];
$ch = curl_init('https://app.gosignhere.com/api/v1/documents');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
    ],
    CURLOPT_POSTFIELDS => $form,
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 201

{
    "data": {
        "document": {
            "render_status": "queued",
            "page_count": null,
            "id": "018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f",
            "title": "Services agreement",
            "folder_id": "018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f",
            "folder_name": "Contracts",
            "status": "ready",
            "kind": "upload",
            "created_by": "018f6c1e-7b30-7c4d-8e3f-6a7b8c9daebf",
            "created_by_name": "Grace Hopper",
            "created_at": "2026-10-10T09:30:00Z",
            "updated_at": "2026-10-10T09:31:00Z",
            "tags": [],
            "render_error": null,
            "source_name": "agreement.pdf",
            "source_bytes": 184320
        }
    }
}

POST /api/v1/documents/{id}/file #

API key or session.

Replace the file. Refused when a sent package already uses the document.

NameTypeDescription
filefilerequiredMultipart form field.

curl

curl -X POST 'https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/file' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY' \
  -F 'file=@agreement-v2.pdf'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}

r = requests.post('https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/file', headers=headers, files={'file': open('agreement-v2.pdf', 'rb')})
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const form = new FormData();
  form.append('file', fileInput.files[0]);   // an <input type="file">
  const res = await fetch('https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/file', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
    },
    body: form,
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

const fs = require('node:fs');

async function main() {
  const form = new FormData();
  form.append('file', new Blob([fs.readFileSync('agreement-v2.pdf')]), 'agreement-v2.pdf');
  const res = await fetch('https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/file', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
    },
    body: form,
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$form = [
    'file' => new CURLFile('agreement-v2.pdf'),
];
$ch = curl_init('https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/file');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
    ],
    CURLOPT_POSTFIELDS => $form,
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "document": {
            "id": "018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f",
            "title": "Services agreement",
            "folder_id": "018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f",
            "folder_name": "Contracts",
            "status": "ready",
            "kind": "upload",
            "created_by": "018f6c1e-7b30-7c4d-8e3f-6a7b8c9daebf",
            "created_by_name": "Grace Hopper",
            "created_at": "2026-10-10T09:30:00Z",
            "updated_at": "2026-10-10T09:31:00Z",
            "tags": [],
            "render_status": "ready",
            "render_error": null,
            "page_count": 3,
            "source_name": "agreement.pdf",
            "source_bytes": 184320
        }
    }
}

GET /api/v1/documents/{id}/pages/{p} #

API key or session.

A rendered page image (PNG).

No request fields.

curl

curl -o out.png 'https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/pages/1' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}

r = requests.get('https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/pages/1', headers=headers)
r.raise_for_status()
open('out.png', 'wb').write(r.content)

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/pages/1', {
    method: 'GET',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
    },
  });
  if (!res.ok) throw new Error(await res.text());
  const file = await res.blob();   // save or display it
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/pages/1', {
    method: 'GET',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
    },
  });
  if (!res.ok) throw new Error(await res.text());
  require('node:fs').writeFileSync('out.png', Buffer.from(await res.arrayBuffer()));
}

main();

PHP

<?php
$ch = curl_init('https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/pages/1');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
    ],
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
file_put_contents('out.png', $out);

Response 200

The file itself (image/png), not JSON.

GET /api/v1/documents/{id}/fields #

API key or session.

The signing fields and the fields_revision to send back as If-Match.

No request fields.

curl

curl 'https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/fields' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}

r = requests.get('https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/fields', headers=headers)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/fields', {
    method: 'GET',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/fields', {
    method: 'GET',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$ch = curl_init('https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/fields');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
    ],
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "fields_revision": 4,
        "roles": [
            {
                "role": "R1",
                "label": "Client"
            }
        ],
        "fields": [
            {
                "id": "018f6c1e-7b34-7c4d-8e3f-0abbcdd1e2f3",
                "field_key": "client_signature",
                "field_type": "signature",
                "label": "Client signature",
                "recipient_role": "R1",
                "page": 1,
                "x_bp": 1000,
                "y_bp": 8000,
                "w_bp": 3000,
                "h_bp": 700,
                "required": true
            }
        ]
    }
}

PUT /api/v1/documents/{id}/fields #

API key or session.

Replace the document's fields. Positions are basis points (0 to 10000) of the page. Send If-Match: the fields_revision you loaded.

NameTypeDescription
fieldsarrayrequiredfield_key, field_type (signature, initials, date, text, checkbox), recipient_role, page, x_bp, y_bp, w_bp, h_bp, required, label.

curl

curl -X PUT 'https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/fields' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY' \
  -H 'If-Match: 4' \
  -H 'Content-Type: application/json' \
  -d '{"fields":[{"field_key":"client_signature","field_type":"signature","label":"Client signature","recipient_role":"R1","page":1,"x_bp":1000,"y_bp":8000,"w_bp":3000,"h_bp":700,"required":true}]}'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
    'If-Match': '4',
}
payload = {
    'fields': [
        {
            'field_key': 'client_signature',
            'field_type': 'signature',
            'label': 'Client signature',
            'recipient_role': 'R1',
            'page': 1,
            'x_bp': 1000,
            'y_bp': 8000,
            'w_bp': 3000,
            'h_bp': 700,
            'required': True,
        },
    ],
}

r = requests.put('https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/fields', headers=headers, json=payload)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/fields', {
    method: 'PUT',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
      'If-Match': '4',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "fields": [
            {
                "field_key": "client_signature",
                "field_type": "signature",
                "label": "Client signature",
                "recipient_role": "R1",
                "page": 1,
                "x_bp": 1000,
                "y_bp": 8000,
                "w_bp": 3000,
                "h_bp": 700,
                "required": true
            }
        ]
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/fields', {
    method: 'PUT',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
      'If-Match': '4',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "fields": [
            {
                "field_key": "client_signature",
                "field_type": "signature",
                "label": "Client signature",
                "recipient_role": "R1",
                "page": 1,
                "x_bp": 1000,
                "y_bp": 8000,
                "w_bp": 3000,
                "h_bp": 700,
                "required": true
            }
        ]
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$payload = [
    'fields' => [
        [
            'field_key' => 'client_signature',
            'field_type' => 'signature',
            'label' => 'Client signature',
            'recipient_role' => 'R1',
            'page' => 1,
            'x_bp' => 1000,
            'y_bp' => 8000,
            'w_bp' => 3000,
            'h_bp' => 700,
            'required' => true,
        ],
    ],
];
$ch = curl_init('https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/fields');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'PUT',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
        'If-Match: 4',
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "fields_revision": 5,
        "fields": [
            {
                "id": "018f6c1e-7b34-7c4d-8e3f-0abbcdd1e2f3",
                "field_key": "client_signature"
            }
        ]
    }
}

PUT /api/v1/documents/{id}/roles #

API key or session.

Name the signing roles (R1, R2, ...) of the document.

NameTypeDescription
rolesarrayrequiredObjects with role and label.

curl

curl -X PUT 'https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/roles' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"roles":[{"role":"R1","label":"Client"}]}'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}
payload = {
    'roles': [
        {
            'role': 'R1',
            'label': 'Client',
        },
    ],
}

r = requests.put('https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/roles', headers=headers, json=payload)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/roles', {
    method: 'PUT',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "roles": [
            {
                "role": "R1",
                "label": "Client"
            }
        ]
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/roles', {
    method: 'PUT',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "roles": [
            {
                "role": "R1",
                "label": "Client"
            }
        ]
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$payload = [
    'roles' => [
        [
            'role' => 'R1',
            'label' => 'Client',
        ],
    ],
];
$ch = curl_init('https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/roles');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'PUT',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "roles": [
            {
                "role": "R1",
                "label": "Client"
            }
        ]
    }
}

GET /api/v1/documents/{id}/preview.pdf #

API key or session.

The document with its fields drawn on, as a PDF.

No request fields.

curl

curl -o out.pdf 'https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/preview.pdf' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}

r = requests.get('https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/preview.pdf', headers=headers)
r.raise_for_status()
open('out.pdf', 'wb').write(r.content)

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/preview.pdf', {
    method: 'GET',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
    },
  });
  if (!res.ok) throw new Error(await res.text());
  const file = await res.blob();   // save or display it
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/preview.pdf', {
    method: 'GET',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
    },
  });
  if (!res.ok) throw new Error(await res.text());
  require('node:fs').writeFileSync('out.pdf', Buffer.from(await res.arrayBuffer()));
}

main();

PHP

<?php
$ch = curl_init('https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/preview.pdf');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
    ],
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
file_put_contents('out.pdf', $out);

Response 200

The file itself (application/pdf), not JSON.

PUT /api/v1/documents/{id}/template #

API key or session.

Mark or unmark the document as a reusable template.

NameTypeDescription
is_templatebooleanrequiredtrue or false.

curl

curl -X PUT 'https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/template' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"is_template":true}'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}
payload = {
    'is_template': True,
}

r = requests.put('https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/template', headers=headers, json=payload)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/template', {
    method: 'PUT',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "is_template": true
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/template', {
    method: 'PUT',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "is_template": true
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$payload = [
    'is_template' => true,
];
$ch = curl_init('https://app.gosignhere.com/api/v1/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f/template');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'PUT',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "document": {
            "is_template": true,
            "id": "018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f",
            "title": "Services agreement",
            "folder_id": "018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f",
            "folder_name": "Contracts",
            "status": "ready",
            "kind": "upload",
            "created_by": "018f6c1e-7b30-7c4d-8e3f-6a7b8c9daebf",
            "created_by_name": "Grace Hopper",
            "created_at": "2026-10-10T09:30:00Z",
            "updated_at": "2026-10-10T09:31:00Z",
            "tags": [],
            "render_status": "ready",
            "render_error": null,
            "page_count": 3,
            "source_name": "agreement.pdf",
            "source_bytes": 184320
        }
    }
}

Folders

GET /api/v1/folders #

API key or session.

The folders you can see.

No request fields.

curl

curl 'https://app.gosignhere.com/api/v1/folders' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}

r = requests.get('https://app.gosignhere.com/api/v1/folders', headers=headers)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/folders', {
    method: 'GET',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/folders', {
    method: 'GET',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$ch = curl_init('https://app.gosignhere.com/api/v1/folders');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
    ],
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "folders": [
            {
                "id": "018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f",
                "name": "Contracts",
                "parent_id": null,
                "is_default": false
            }
        ]
    }
}

POST /api/v1/folders #

API key or session.

Create a folder.

NameTypeDescription
namestringrequiredUp to 120 characters.
parent_iduuidoptionalNest it inside another folder.

curl

curl -X POST 'https://app.gosignhere.com/api/v1/folders' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"name":"Contracts"}'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}
payload = {
    'name': 'Contracts',
}

r = requests.post('https://app.gosignhere.com/api/v1/folders', headers=headers, json=payload)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/folders', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "name": "Contracts"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/folders', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "name": "Contracts"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$payload = [
    'name' => 'Contracts',
];
$ch = curl_init('https://app.gosignhere.com/api/v1/folders');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 201

{
    "data": {
        "folder": {
            "id": "018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f",
            "name": "Contracts",
            "parent_id": null,
            "is_default": false
        }
    }
}

GET /api/v1/folders/{id} #

API key or session.

One folder.

No request fields.

curl

curl 'https://app.gosignhere.com/api/v1/folders/018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}

r = requests.get('https://app.gosignhere.com/api/v1/folders/018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f', headers=headers)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/folders/018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f', {
    method: 'GET',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/folders/018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f', {
    method: 'GET',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$ch = curl_init('https://app.gosignhere.com/api/v1/folders/018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
    ],
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "folder": {
            "id": "018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f",
            "name": "Contracts",
            "parent_id": null,
            "is_default": false
        }
    }
}

PATCH /api/v1/folders/{id} #

API key or session.

Rename or move a folder.

NameTypeDescription
namestringoptionalNew name.
parent_iduuidoptionalNew parent.

curl

curl -X PATCH 'https://app.gosignhere.com/api/v1/folders/018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"name":"Signed contracts"}'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}
payload = {
    'name': 'Signed contracts',
}

r = requests.patch('https://app.gosignhere.com/api/v1/folders/018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f', headers=headers, json=payload)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/folders/018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f', {
    method: 'PATCH',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "name": "Signed contracts"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/folders/018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f', {
    method: 'PATCH',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "name": "Signed contracts"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$payload = [
    'name' => 'Signed contracts',
];
$ch = curl_init('https://app.gosignhere.com/api/v1/folders/018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'PATCH',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "folder": {
            "id": "018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f",
            "name": "Contracts",
            "parent_id": null,
            "is_default": false
        }
    }
}

DELETE /api/v1/folders/{id} #

API key or session.

Delete an empty folder.

No request fields.

curl

curl -X DELETE 'https://app.gosignhere.com/api/v1/folders/018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}

r = requests.delete('https://app.gosignhere.com/api/v1/folders/018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f', headers=headers)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/folders/018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f', {
    method: 'DELETE',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/folders/018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f', {
    method: 'DELETE',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$ch = curl_init('https://app.gosignhere.com/api/v1/folders/018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'DELETE',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
    ],
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "deleted": true
    }
}

GET /api/v1/folders/{id}/shares #

API key or session.

Who else can see or edit the folder.

No request fields.

curl

curl 'https://app.gosignhere.com/api/v1/folders/018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f/shares' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}

r = requests.get('https://app.gosignhere.com/api/v1/folders/018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f/shares', headers=headers)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/folders/018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f/shares', {
    method: 'GET',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/folders/018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f/shares', {
    method: 'GET',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$ch = curl_init('https://app.gosignhere.com/api/v1/folders/018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f/shares');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
    ],
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "shares": [
            {
                "user_id": "018f6c1e-7b30-7c4d-8e3f-6a7b8c9daebf",
                "access": "edit"
            }
        ]
    }
}

PUT /api/v1/folders/{id}/shares #

API key or session.

Replace the folder's share list.

NameTypeDescription
sharesarrayrequiredObjects with user_id and access (view or edit).

curl

curl -X PUT 'https://app.gosignhere.com/api/v1/folders/018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f/shares' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"shares":[{"user_id":"018f6c1e-7b30-7c4d-8e3f-6a7b8c9daebf","access":"edit"}]}'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}
payload = {
    'shares': [
        {
            'user_id': '018f6c1e-7b30-7c4d-8e3f-6a7b8c9daebf',
            'access': 'edit',
        },
    ],
}

r = requests.put('https://app.gosignhere.com/api/v1/folders/018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f/shares', headers=headers, json=payload)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/folders/018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f/shares', {
    method: 'PUT',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "shares": [
            {
                "user_id": "018f6c1e-7b30-7c4d-8e3f-6a7b8c9daebf",
                "access": "edit"
            }
        ]
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/folders/018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f/shares', {
    method: 'PUT',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "shares": [
            {
                "user_id": "018f6c1e-7b30-7c4d-8e3f-6a7b8c9daebf",
                "access": "edit"
            }
        ]
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$payload = [
    'shares' => [
        [
            'user_id' => '018f6c1e-7b30-7c4d-8e3f-6a7b8c9daebf',
            'access' => 'edit',
        ],
    ],
];
$ch = curl_init('https://app.gosignhere.com/api/v1/folders/018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f/shares');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'PUT',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "shares": [
            {
                "user_id": "018f6c1e-7b30-7c4d-8e3f-6a7b8c9daebf",
                "access": "edit"
            }
        ]
    }
}

Packages

POST /api/v1/packages #

API key or session.

Send a document for signature in one call: pass document_id and signers. For several documents, a draft, or per-signer kinds, pass documents (a list of ids) and optionally send:true.

NameTypeDescription
document_iduuidrequiredA ready document with fields placed.
signersarrayrequired1 to 8 objects: role (R1...), name, email.
titlestringoptionalDefaults to the document title.
messagestringoptionalUp to 2,000 characters.
expires_in_daysintegeroptional0 (never) to 365.
documentsarrayoptionalAssembly form: document ids; with signers (kind signer, approver or cc) and send.
draftbooleanoptionalCreate a draft, do not send.

curl

curl -X POST 'https://app.gosignhere.com/api/v1/packages' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"document_id":"018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f","title":"Services agreement","message":"Please sign by Friday.","signers":[{"role":"R1","name":"Ada Lovelace","email":"ada@example.com"}]}'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}
payload = {
    'document_id': '018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f',
    'title': 'Services agreement',
    'message': 'Please sign by Friday.',
    'signers': [
        {
            'role': 'R1',
            'name': 'Ada Lovelace',
            'email': 'ada@example.com',
        },
    ],
}

r = requests.post('https://app.gosignhere.com/api/v1/packages', headers=headers, json=payload)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/packages', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "document_id": "018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f",
        "title": "Services agreement",
        "message": "Please sign by Friday.",
        "signers": [
            {
                "role": "R1",
                "name": "Ada Lovelace",
                "email": "ada@example.com"
            }
        ]
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/packages', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "document_id": "018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f",
        "title": "Services agreement",
        "message": "Please sign by Friday.",
        "signers": [
            {
                "role": "R1",
                "name": "Ada Lovelace",
                "email": "ada@example.com"
            }
        ]
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$payload = [
    'document_id' => '018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f',
    'title' => 'Services agreement',
    'message' => 'Please sign by Friday.',
    'signers' => [
        [
            'role' => 'R1',
            'name' => 'Ada Lovelace',
            'email' => 'ada@example.com',
        ],
    ],
];
$ch = curl_init('https://app.gosignhere.com/api/v1/packages');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 201

{
    "data": {
        "package": {
            "id": "018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f",
            "status": "sent",
            "title": "Services agreement",
            "message": "Please sign by Friday.",
            "expires_in_days": 30,
            "expires_at": "2026-11-09T10:00:00Z",
            "signing_mode": "sequential",
            "created_at": "2026-10-10T10:00:00Z",
            "document_count": 1,
            "page_count": 3,
            "documents": [
                {
                    "document_id": "018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f",
                    "title": "Services agreement",
                    "page_count": 3
                }
            ],
            "signers": [
                {
                    "id": "018f6c1e-7b2d-7c4d-8e3f-3a4b5c6d7e8f",
                    "slot": 1,
                    "role": "R1",
                    "kind": "signer",
                    "name": "Ada Lovelace",
                    "email": "ada@example.com",
                    "sequence": 1,
                    "status": "pending",
                    "approval": false
                }
            ],
            "validation": {
                "ok": true,
                "messages": []
            }
        }
    }
}

GET /api/v1/packages #

API key or session.

List packages, newest first.

NameTypeDescription
status querystringoptionaldraft, sent, in_progress, completed, declined, expired, voided.
q querystringoptionalSearch title or signer.

curl

curl 'https://app.gosignhere.com/api/v1/packages?status=completed' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}

r = requests.get('https://app.gosignhere.com/api/v1/packages?status=completed', headers=headers)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/packages?status=completed', {
    method: 'GET',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/packages?status=completed', {
    method: 'GET',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$ch = curl_init('https://app.gosignhere.com/api/v1/packages?status=completed');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
    ],
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "packages": [
            {
                "id": "018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f",
                "status": "sent",
                "title": "Services agreement",
                "message": "Please sign by Friday.",
                "expires_in_days": 30,
                "expires_at": "2026-11-09T10:00:00Z",
                "signing_mode": "sequential",
                "created_at": "2026-10-10T10:00:00Z",
                "document_count": 1,
                "page_count": 3,
                "documents": [
                    {
                        "document_id": "018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f",
                        "title": "Services agreement",
                        "page_count": 3
                    }
                ],
                "signers": [
                    {
                        "id": "018f6c1e-7b2d-7c4d-8e3f-3a4b5c6d7e8f",
                        "slot": 1,
                        "role": "R1",
                        "kind": "signer",
                        "name": "Ada Lovelace",
                        "email": "ada@example.com",
                        "sequence": 1,
                        "status": "pending",
                        "approval": false
                    }
                ],
                "validation": {
                    "ok": true,
                    "messages": []
                }
            }
        ]
    }
}

GET /api/v1/packages/{id} #

API key or session.

One package: signers, documents, timeline and webhook deliveries.

No request fields.

curl

curl 'https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}

r = requests.get('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f', headers=headers)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f', {
    method: 'GET',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f', {
    method: 'GET',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$ch = curl_init('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
    ],
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "package": {
            "id": "018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f",
            "status": "sent",
            "title": "Services agreement",
            "message": "Please sign by Friday.",
            "expires_in_days": 30,
            "expires_at": "2026-11-09T10:00:00Z",
            "signing_mode": "sequential",
            "created_at": "2026-10-10T10:00:00Z",
            "document_count": 1,
            "page_count": 3,
            "documents": [
                {
                    "document_id": "018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f",
                    "title": "Services agreement",
                    "page_count": 3
                }
            ],
            "signers": [
                {
                    "id": "018f6c1e-7b2d-7c4d-8e3f-3a4b5c6d7e8f",
                    "slot": 1,
                    "role": "R1",
                    "kind": "signer",
                    "name": "Ada Lovelace",
                    "email": "ada@example.com",
                    "sequence": 1,
                    "status": "pending",
                    "approval": false
                }
            ],
            "validation": {
                "ok": true,
                "messages": []
            },
            "events": [
                {
                    "type": "package.sent",
                    "at": "2026-10-10T10:00:00Z"
                }
            ],
            "deliveries": []
        }
    }
}

POST /api/v1/packages/{id}/void #

API key or session.

Cancel a package in progress. Signers' links stop working.

NameTypeDescription
reasonstringoptionalUp to 500 characters; shown to signers.

curl

curl -X POST 'https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/void' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"reason":"Terms changed"}'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}
payload = {
    'reason': 'Terms changed',
}

r = requests.post('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/void', headers=headers, json=payload)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/void', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "reason": "Terms changed"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/void', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "reason": "Terms changed"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$payload = [
    'reason' => 'Terms changed',
];
$ch = curl_init('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/void');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "package": {
            "status": "voided",
            "id": "018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f",
            "title": "Services agreement",
            "message": "Please sign by Friday.",
            "expires_in_days": 30,
            "expires_at": "2026-11-09T10:00:00Z",
            "signing_mode": "sequential",
            "created_at": "2026-10-10T10:00:00Z",
            "document_count": 1,
            "page_count": 3,
            "documents": [
                {
                    "document_id": "018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f",
                    "title": "Services agreement",
                    "page_count": 3
                }
            ],
            "signers": [
                {
                    "id": "018f6c1e-7b2d-7c4d-8e3f-3a4b5c6d7e8f",
                    "slot": 1,
                    "role": "R1",
                    "kind": "signer",
                    "name": "Ada Lovelace",
                    "email": "ada@example.com",
                    "sequence": 1,
                    "status": "pending",
                    "approval": false
                }
            ],
            "validation": {
                "ok": true,
                "messages": []
            }
        }
    }
}

POST /api/v1/packages/{id}/signers/{sid}/resend #

API key or session.

Email a signer a fresh link (the old link stops working). Pass a new email to redirect it.

NameTypeDescription
emailstringoptionalA corrected address.

curl

curl -X POST 'https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/signers/018f6c1e-7b2d-7c4d-8e3f-3a4b5c6d7e8f/resend' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"email":"ada@new.example.com"}'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}
payload = {
    'email': 'ada@new.example.com',
}

r = requests.post('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/signers/018f6c1e-7b2d-7c4d-8e3f-3a4b5c6d7e8f/resend', headers=headers, json=payload)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/signers/018f6c1e-7b2d-7c4d-8e3f-3a4b5c6d7e8f/resend', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "email": "ada@new.example.com"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/signers/018f6c1e-7b2d-7c4d-8e3f-3a4b5c6d7e8f/resend', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "email": "ada@new.example.com"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$payload = [
    'email' => 'ada@new.example.com',
];
$ch = curl_init('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/signers/018f6c1e-7b2d-7c4d-8e3f-3a4b5c6d7e8f/resend');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "package": {
            "id": "018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f",
            "status": "sent",
            "title": "Services agreement",
            "message": "Please sign by Friday.",
            "expires_in_days": 30,
            "expires_at": "2026-11-09T10:00:00Z",
            "signing_mode": "sequential",
            "created_at": "2026-10-10T10:00:00Z",
            "document_count": 1,
            "page_count": 3,
            "documents": [
                {
                    "document_id": "018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f",
                    "title": "Services agreement",
                    "page_count": 3
                }
            ],
            "signers": [
                {
                    "id": "018f6c1e-7b2d-7c4d-8e3f-3a4b5c6d7e8f",
                    "slot": 1,
                    "role": "R1",
                    "kind": "signer",
                    "name": "Ada Lovelace",
                    "email": "ada@example.com",
                    "sequence": 1,
                    "status": "pending",
                    "approval": false
                }
            ],
            "validation": {
                "ok": true,
                "messages": []
            }
        }
    }
}

PATCH /api/v1/packages/{id}/signers/{sid} #

API key or session.

Correct an unsigned signer's name or email.

NameTypeDescription
namestringoptionalNew name.
emailstringoptionalNew address.

curl

curl -X PATCH 'https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/signers/018f6c1e-7b2d-7c4d-8e3f-3a4b5c6d7e8f' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"name":"Ada King"}'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}
payload = {
    'name': 'Ada King',
}

r = requests.patch('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/signers/018f6c1e-7b2d-7c4d-8e3f-3a4b5c6d7e8f', headers=headers, json=payload)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/signers/018f6c1e-7b2d-7c4d-8e3f-3a4b5c6d7e8f', {
    method: 'PATCH',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "name": "Ada King"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/signers/018f6c1e-7b2d-7c4d-8e3f-3a4b5c6d7e8f', {
    method: 'PATCH',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "name": "Ada King"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$payload = [
    'name' => 'Ada King',
];
$ch = curl_init('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/signers/018f6c1e-7b2d-7c4d-8e3f-3a4b5c6d7e8f');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'PATCH',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "package": {
            "id": "018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f",
            "status": "sent",
            "title": "Services agreement",
            "message": "Please sign by Friday.",
            "expires_in_days": 30,
            "expires_at": "2026-11-09T10:00:00Z",
            "signing_mode": "sequential",
            "created_at": "2026-10-10T10:00:00Z",
            "document_count": 1,
            "page_count": 3,
            "documents": [
                {
                    "document_id": "018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f",
                    "title": "Services agreement",
                    "page_count": 3
                }
            ],
            "signers": [
                {
                    "id": "018f6c1e-7b2d-7c4d-8e3f-3a4b5c6d7e8f",
                    "slot": 1,
                    "role": "R1",
                    "kind": "signer",
                    "name": "Ada Lovelace",
                    "email": "ada@example.com",
                    "sequence": 1,
                    "status": "pending",
                    "approval": false
                }
            ],
            "validation": {
                "ok": true,
                "messages": []
            }
        }
    }
}

POST /api/v1/packages/{id}/signers/{sid}/edit #

API key or session.

Same as PATCH on the signer, for clients that cannot send PATCH.

NameTypeDescription
namestringoptionalNew name.
emailstringoptionalNew address.

curl

curl -X POST 'https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/signers/018f6c1e-7b2d-7c4d-8e3f-3a4b5c6d7e8f/edit' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"name":"Ada King"}'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}
payload = {
    'name': 'Ada King',
}

r = requests.post('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/signers/018f6c1e-7b2d-7c4d-8e3f-3a4b5c6d7e8f/edit', headers=headers, json=payload)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/signers/018f6c1e-7b2d-7c4d-8e3f-3a4b5c6d7e8f/edit', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "name": "Ada King"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/signers/018f6c1e-7b2d-7c4d-8e3f-3a4b5c6d7e8f/edit', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "name": "Ada King"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$payload = [
    'name' => 'Ada King',
];
$ch = curl_init('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/signers/018f6c1e-7b2d-7c4d-8e3f-3a4b5c6d7e8f/edit');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "package": {
            "id": "018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f",
            "status": "sent",
            "title": "Services agreement",
            "message": "Please sign by Friday.",
            "expires_in_days": 30,
            "expires_at": "2026-11-09T10:00:00Z",
            "signing_mode": "sequential",
            "created_at": "2026-10-10T10:00:00Z",
            "document_count": 1,
            "page_count": 3,
            "documents": [
                {
                    "document_id": "018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f",
                    "title": "Services agreement",
                    "page_count": 3
                }
            ],
            "signers": [
                {
                    "id": "018f6c1e-7b2d-7c4d-8e3f-3a4b5c6d7e8f",
                    "slot": 1,
                    "role": "R1",
                    "kind": "signer",
                    "name": "Ada Lovelace",
                    "email": "ada@example.com",
                    "sequence": 1,
                    "status": "pending",
                    "approval": false
                }
            ],
            "validation": {
                "ok": true,
                "messages": []
            }
        }
    }
}

GET /api/v1/packages/{id}/verify #

API key or session.

Check the package's hash chain. Pass hash= (the SHA-256 of a PDF you hold) to learn whether that exact file is the signed one.

NameTypeDescription
hash querystringoptionalSHA-256 of your copy, 64 hex characters.

curl

curl 'https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/verify?hash=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}

r = requests.get('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/verify?hash=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', headers=headers)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/verify?hash=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', {
    method: 'GET',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/verify?hash=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', {
    method: 'GET',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$ch = curl_init('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/verify?hash=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
    ],
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "ok": true,
        "found": true,
        "state": "consistent",
        "status": "completed",
        "pre_match": true,
        "post_match": true,
        "pdf_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
        "given_matches": true,
        "verify_url": "https://app.gosignhere.com/verify/3f6c1c52-8b0e-4c1a-9a53-0d2f6c1b7e10"
    }
}

GET /api/v1/packages/{id}/completed.pdf #

API key or session.

The signed PDF with its certificate page. Only after completion.

No request fields.

curl

curl -o out.pdf 'https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/completed.pdf' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}

r = requests.get('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/completed.pdf', headers=headers)
r.raise_for_status()
open('out.pdf', 'wb').write(r.content)

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/completed.pdf', {
    method: 'GET',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
    },
  });
  if (!res.ok) throw new Error(await res.text());
  const file = await res.blob();   // save or display it
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/completed.pdf', {
    method: 'GET',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
    },
  });
  if (!res.ok) throw new Error(await res.text());
  require('node:fs').writeFileSync('out.pdf', Buffer.from(await res.arrayBuffer()));
}

main();

PHP

<?php
$ch = curl_init('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/completed.pdf');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
    ],
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
file_put_contents('out.pdf', $out);

Response 200

The file itself (application/pdf), not JSON.

PATCH /api/v1/packages/{id} #

API key or session.

Edit a draft: title, message, expiry, signing_mode, documents or signers.

NameTypeDescription
titlestringoptionalNew title.
messagestringoptionalNew message.
expires_in_daysintegeroptional0 to 365.
signing_modestringoptionalsequential or parallel.
signersarrayoptionalThe full signer list.

curl

curl -X PATCH 'https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"title":"Services agreement v2"}'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}
payload = {
    'title': 'Services agreement v2',
}

r = requests.patch('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f', headers=headers, json=payload)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f', {
    method: 'PATCH',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "title": "Services agreement v2"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f', {
    method: 'PATCH',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "title": "Services agreement v2"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$payload = [
    'title' => 'Services agreement v2',
];
$ch = curl_init('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'PATCH',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "package": {
            "id": "018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f",
            "status": "sent",
            "title": "Services agreement",
            "message": "Please sign by Friday.",
            "expires_in_days": 30,
            "expires_at": "2026-11-09T10:00:00Z",
            "signing_mode": "sequential",
            "created_at": "2026-10-10T10:00:00Z",
            "document_count": 1,
            "page_count": 3,
            "documents": [
                {
                    "document_id": "018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f",
                    "title": "Services agreement",
                    "page_count": 3
                }
            ],
            "signers": [
                {
                    "id": "018f6c1e-7b2d-7c4d-8e3f-3a4b5c6d7e8f",
                    "slot": 1,
                    "role": "R1",
                    "kind": "signer",
                    "name": "Ada Lovelace",
                    "email": "ada@example.com",
                    "sequence": 1,
                    "status": "pending",
                    "approval": false
                }
            ],
            "validation": {
                "ok": true,
                "messages": []
            }
        }
    }
}

DELETE /api/v1/packages/{id} #

API key or session.

Delete a draft package.

No request fields.

curl

curl -X DELETE 'https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}

r = requests.delete('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f', headers=headers)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f', {
    method: 'DELETE',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f', {
    method: 'DELETE',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$ch = curl_init('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'DELETE',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
    ],
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "deleted": true
    }
}

POST /api/v1/packages/{id}/documents #

API key or session.

Add a document to a draft.

NameTypeDescription
document_iduuidrequiredA ready document.

curl

curl -X POST 'https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/documents' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"document_id":"018f6c1e-7b2c-7c4d-8e3f-2a3b4c5d6e7f"}'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}
payload = {
    'document_id': '018f6c1e-7b2c-7c4d-8e3f-2a3b4c5d6e7f',
}

r = requests.post('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/documents', headers=headers, json=payload)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/documents', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "document_id": "018f6c1e-7b2c-7c4d-8e3f-2a3b4c5d6e7f"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/documents', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "document_id": "018f6c1e-7b2c-7c4d-8e3f-2a3b4c5d6e7f"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$payload = [
    'document_id' => '018f6c1e-7b2c-7c4d-8e3f-2a3b4c5d6e7f',
];
$ch = curl_init('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/documents');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "package": {
            "id": "018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f",
            "status": "sent",
            "title": "Services agreement",
            "message": "Please sign by Friday.",
            "expires_in_days": 30,
            "expires_at": "2026-11-09T10:00:00Z",
            "signing_mode": "sequential",
            "created_at": "2026-10-10T10:00:00Z",
            "document_count": 1,
            "page_count": 3,
            "documents": [
                {
                    "document_id": "018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f",
                    "title": "Services agreement",
                    "page_count": 3
                }
            ],
            "signers": [
                {
                    "id": "018f6c1e-7b2d-7c4d-8e3f-3a4b5c6d7e8f",
                    "slot": 1,
                    "role": "R1",
                    "kind": "signer",
                    "name": "Ada Lovelace",
                    "email": "ada@example.com",
                    "sequence": 1,
                    "status": "pending",
                    "approval": false
                }
            ],
            "validation": {
                "ok": true,
                "messages": []
            }
        }
    }
}

DELETE /api/v1/packages/{id}/documents/{docId} #

API key or session.

Remove a document from a draft.

No request fields.

curl

curl -X DELETE 'https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}

r = requests.delete('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f', headers=headers)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f', {
    method: 'DELETE',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f', {
    method: 'DELETE',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$ch = curl_init('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/documents/018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'DELETE',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
    ],
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "package": {
            "id": "018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f",
            "status": "sent",
            "title": "Services agreement",
            "message": "Please sign by Friday.",
            "expires_in_days": 30,
            "expires_at": "2026-11-09T10:00:00Z",
            "signing_mode": "sequential",
            "created_at": "2026-10-10T10:00:00Z",
            "document_count": 1,
            "page_count": 3,
            "documents": [
                {
                    "document_id": "018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f",
                    "title": "Services agreement",
                    "page_count": 3
                }
            ],
            "signers": [
                {
                    "id": "018f6c1e-7b2d-7c4d-8e3f-3a4b5c6d7e8f",
                    "slot": 1,
                    "role": "R1",
                    "kind": "signer",
                    "name": "Ada Lovelace",
                    "email": "ada@example.com",
                    "sequence": 1,
                    "status": "pending",
                    "approval": false
                }
            ],
            "validation": {
                "ok": true,
                "messages": []
            }
        }
    }
}

POST /api/v1/packages/{id}/reorder #

API key or session.

Set the document order of a draft.

NameTypeDescription
orderarrayrequiredEvery document id once.

curl

curl -X POST 'https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/reorder' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"order":["018f6c1e-7b2c-7c4d-8e3f-2a3b4c5d6e7f","018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f"]}'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}
payload = {
    'order': [
        '018f6c1e-7b2c-7c4d-8e3f-2a3b4c5d6e7f',
        '018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f',
    ],
}

r = requests.post('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/reorder', headers=headers, json=payload)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/reorder', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "order": [
            "018f6c1e-7b2c-7c4d-8e3f-2a3b4c5d6e7f",
            "018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f"
        ]
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/reorder', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "order": [
            "018f6c1e-7b2c-7c4d-8e3f-2a3b4c5d6e7f",
            "018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f"
        ]
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$payload = [
    'order' => [
        '018f6c1e-7b2c-7c4d-8e3f-2a3b4c5d6e7f',
        '018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f',
    ],
];
$ch = curl_init('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/reorder');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "package": {
            "id": "018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f",
            "status": "sent",
            "title": "Services agreement",
            "message": "Please sign by Friday.",
            "expires_in_days": 30,
            "expires_at": "2026-11-09T10:00:00Z",
            "signing_mode": "sequential",
            "created_at": "2026-10-10T10:00:00Z",
            "document_count": 1,
            "page_count": 3,
            "documents": [
                {
                    "document_id": "018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f",
                    "title": "Services agreement",
                    "page_count": 3
                }
            ],
            "signers": [
                {
                    "id": "018f6c1e-7b2d-7c4d-8e3f-3a4b5c6d7e8f",
                    "slot": 1,
                    "role": "R1",
                    "kind": "signer",
                    "name": "Ada Lovelace",
                    "email": "ada@example.com",
                    "sequence": 1,
                    "status": "pending",
                    "approval": false
                }
            ],
            "validation": {
                "ok": true,
                "messages": []
            }
        }
    }
}

GET /api/v1/packages/{id}/validate #

API key or session.

Check a draft is ready to send; lists what is missing.

No request fields.

curl

curl 'https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/validate' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}

r = requests.get('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/validate', headers=headers)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/validate', {
    method: 'GET',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/validate', {
    method: 'GET',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$ch = curl_init('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/validate');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
    ],
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "ok": true,
        "messages": []
    }
}

GET /api/v1/packages/{id}/flow-preview #

API key or session.

Who receives the package, in which order.

No request fields.

curl

curl 'https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/flow-preview' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}

r = requests.get('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/flow-preview', headers=headers)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/flow-preview', {
    method: 'GET',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/flow-preview', {
    method: 'GET',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$ch = curl_init('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/flow-preview');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
    ],
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "steps": [
            {
                "sequence": 1,
                "signers": [
                    {
                        "name": "Ada Lovelace",
                        "kind": "signer"
                    }
                ]
            }
        ]
    }
}

POST /api/v1/packages/{id}/send #

API key or session.

Send a draft. Emails go to the first signer(s).

NameTypeDescription
prefillobjectoptionalValues for prefilled fields, keyed by field_key.

curl

curl -X POST 'https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/send' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"prefill":{}}'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}
payload = {
    'prefill': {},
}

r = requests.post('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/send', headers=headers, json=payload)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/send', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "prefill": {}
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/send', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "prefill": {}
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$payload = [
    'prefill' => (object) [],
];
$ch = curl_init('https://app.gosignhere.com/api/v1/packages/018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f/send');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "package": {
            "id": "018f6c1e-7b2a-7c4d-9e3f-0a1b2c3d4e5f",
            "status": "sent",
            "title": "Services agreement",
            "message": "Please sign by Friday.",
            "expires_in_days": 30,
            "expires_at": "2026-11-09T10:00:00Z",
            "signing_mode": "sequential",
            "created_at": "2026-10-10T10:00:00Z",
            "document_count": 1,
            "page_count": 3,
            "documents": [
                {
                    "document_id": "018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f",
                    "title": "Services agreement",
                    "page_count": 3
                }
            ],
            "signers": [
                {
                    "id": "018f6c1e-7b2d-7c4d-8e3f-3a4b5c6d7e8f",
                    "slot": 1,
                    "role": "R1",
                    "kind": "signer",
                    "name": "Ada Lovelace",
                    "email": "ada@example.com",
                    "sequence": 1,
                    "status": "pending",
                    "approval": false
                }
            ],
            "validation": {
                "ok": true,
                "messages": []
            }
        }
    }
}

Tags

GET /api/v1/tags #

API key or session.

Your tags.

No request fields.

curl

curl 'https://app.gosignhere.com/api/v1/tags' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}

r = requests.get('https://app.gosignhere.com/api/v1/tags', headers=headers)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/tags', {
    method: 'GET',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/tags', {
    method: 'GET',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$ch = curl_init('https://app.gosignhere.com/api/v1/tags');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
    ],
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "tags": [
            {
                "id": "018f6c1e-7b2f-7c4d-8e3f-5a6b7c8d9eaf",
                "name": "Legal"
            }
        ]
    }
}

POST /api/v1/tags #

API key or session.

Create a tag.

NameTypeDescription
namestringrequiredUp to 60 characters.

curl

curl -X POST 'https://app.gosignhere.com/api/v1/tags' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"name":"Legal"}'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}
payload = {
    'name': 'Legal',
}

r = requests.post('https://app.gosignhere.com/api/v1/tags', headers=headers, json=payload)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/tags', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "name": "Legal"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/tags', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "name": "Legal"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$payload = [
    'name' => 'Legal',
];
$ch = curl_init('https://app.gosignhere.com/api/v1/tags');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 201

{
    "data": {
        "tag": {
            "id": "018f6c1e-7b2f-7c4d-8e3f-5a6b7c8d9eaf",
            "name": "Legal"
        }
    }
}

PATCH /api/v1/tags/{id} #

API key or session.

Rename a tag.

NameTypeDescription
namestringrequiredNew name.

curl

curl -X PATCH 'https://app.gosignhere.com/api/v1/tags/018f6c1e-7b2f-7c4d-8e3f-5a6b7c8d9eaf' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"name":"Contracts"}'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}
payload = {
    'name': 'Contracts',
}

r = requests.patch('https://app.gosignhere.com/api/v1/tags/018f6c1e-7b2f-7c4d-8e3f-5a6b7c8d9eaf', headers=headers, json=payload)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/tags/018f6c1e-7b2f-7c4d-8e3f-5a6b7c8d9eaf', {
    method: 'PATCH',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "name": "Contracts"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/tags/018f6c1e-7b2f-7c4d-8e3f-5a6b7c8d9eaf', {
    method: 'PATCH',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        "name": "Contracts"
    }),
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$payload = [
    'name' => 'Contracts',
];
$ch = curl_init('https://app.gosignhere.com/api/v1/tags/018f6c1e-7b2f-7c4d-8e3f-5a6b7c8d9eaf');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'PATCH',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "tag": {
            "id": "018f6c1e-7b2f-7c4d-8e3f-5a6b7c8d9eaf",
            "name": "Legal"
        }
    }
}

DELETE /api/v1/tags/{id} #

API key or session.

Delete a tag; documents keep existing.

No request fields.

curl

curl -X DELETE 'https://app.gosignhere.com/api/v1/tags/018f6c1e-7b2f-7c4d-8e3f-5a6b7c8d9eaf' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}

r = requests.delete('https://app.gosignhere.com/api/v1/tags/018f6c1e-7b2f-7c4d-8e3f-5a6b7c8d9eaf', headers=headers)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/tags/018f6c1e-7b2f-7c4d-8e3f-5a6b7c8d9eaf', {
    method: 'DELETE',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/tags/018f6c1e-7b2f-7c4d-8e3f-5a6b7c8d9eaf', {
    method: 'DELETE',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$ch = curl_init('https://app.gosignhere.com/api/v1/tags/018f6c1e-7b2f-7c4d-8e3f-5a6b7c8d9eaf');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'DELETE',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
    ],
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "deleted": true
    }
}

Templates

GET /api/v1/templates #

API key or session.

Your templates.

NameTypeDescription
q querystringoptionalSearch the title.

curl

curl 'https://app.gosignhere.com/api/v1/templates' \
  -H 'Authorization: Bearer gsh_live_YOUR_KEY'

Python

import requests

headers = {
    'Authorization': 'Bearer gsh_live_YOUR_KEY',
}

r = requests.get('https://app.gosignhere.com/api/v1/templates', headers=headers)
r.raise_for_status()
print(r.json())

JavaScript

// Call this from your server. A live key in browser code is a leaked key.
async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/templates', {
    method: 'GET',
    headers: {
      'Authorization': 'Bearer gsh_live_YOUR_KEY',
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

Node.js

async function main() {
  const res = await fetch('https://app.gosignhere.com/api/v1/templates', {
    method: 'GET',
    headers: {
      'Authorization': `Bearer ${process.env.GSH_API_KEY}`,
    },
  });
  if (!res.ok) throw new Error(await res.text());
  console.log(await res.json());
}

main();

PHP

<?php
$ch = curl_init('https://app.gosignhere.com/api/v1/templates');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: ' . 'Bearer ' . getenv('GSH_API_KEY'),
    ],
]);
$out = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $out;   // HTTP $status, body {"data": ...}

Response 200

{
    "data": {
        "documents": [
            {
                "is_template": true,
                "id": "018f6c1e-7b2b-7c4d-8e3f-1a2b3c4d5e6f",
                "title": "Services agreement",
                "folder_id": "018f6c1e-7b2e-7c4d-8e3f-4a5b6c7d8e9f",
                "folder_name": "Contracts",
                "status": "ready",
                "kind": "upload",
                "created_by": "018f6c1e-7b30-7c4d-8e3f-6a7b8c9daebf",
                "created_by_name": "Grace Hopper",
                "created_at": "2026-10-10T09:30:00Z",
                "updated_at": "2026-10-10T09:31:00Z",
                "tags": [],
                "render_status": "ready",
                "render_error": null,
                "page_count": 3,
                "source_name": "agreement.pdf",
                "source_bytes": 184320
            }
        ]
    }
}