DocSpring is a service that helps you fill out and sign PDF templates.
Bring your own key. This API needs your own API v1 key - get one from the provider, add it once below, and the proxy injects it on every call. Your OmniStream plan covers the unified SDK, key storage, and proxy - the provider's own rate limits still apply to your key.
This is a community listing. If you own this API, you can request ownership.
npm install omnistream-sdkimport { OmniClient } from "omnistream-sdk";
const omni = new OmniClient({ token: process.env.OMNI_KEY! });
// One key reaches every API on the marketplace.
const data = await omni.call("formapi/testAuthentication");One install, one key - the same client calls every API on the marketplace.
Test Authentication
Get a list of all combined submissions
Merge generated PDFs together
Check the status of a combined submission (merged PDFs)
Expire a combined submission
Merge submission PDFs, template PDFs, or custom files
/**
* APIv1 - generated by OmniStream from API v1's OpenAPI spec.
* One typed method per endpoint. A single Omni key reaches the API.
*/
const DEFAULT_BASE = "https://grid.skinvaults.online/v1/proxy/formapi";
export class APIv1Error extends Error {
status: number;
code?: string;
constructor(status: number, code: string | undefined, message?: string) {
super(message || `APIv1 error ${status}`);
this.name = "APIv1Error";
this.status = status;
this.code = code;
}
}
export interface APIv1Options {
baseUrl?: string;
fetch?: typeof fetch;
timeoutMs?: number;
}
export class APIv1 {
/** @param token Your OmniStream key (one key for every API). */
constructor(private token: string, private opts: APIv1Options = {}) {
if (!token) throw new Error("APIv1: token is required");
}
rateLimit: { remainingMinute?: number; remainingDay?: number } | null = null;
private async _request(method: string, path: string, { params, body }: { params?: Record<string, unknown>; body?: unknown } = {}): Promise<any> {
const f = this.opts.fetch ?? globalThis.fetch;
const url = new URL((this.opts.baseUrl ?? DEFAULT_BASE).replace(/\/+$/, "") + path);
if (params) for (const [k, v] of Object.entries(params)) if (v != null) url.searchParams.set(k, String(v));
const headers: Record<string, string> = { "x-omni-key": this.token };
if (body !== undefined) headers["content-type"] = "application/json";
const res = await f(url, { method, headers, body: body !== undefined ? JSON.stringify(body) : undefined });
this.rateLimit = {
remainingMinute: Number(res.headers.get("x-ratelimit-remaining-minute")) || undefined,
remainingDay: Number(res.headers.get("x-ratelimit-remaining-day")) || undefined,
};
const data = await res.json().catch(() => ({}));
if (!res.ok) throw new APIv1Error(res.status, data?.error?.code, data?.error?.message);
return data.data ?? data;
}
/** Test Authentication */
testAuthentication(): Promise<any> {
return this._request("GET", "/authentication", {});
}
/** Get a list of all combined submissions */
listCombinedSubmissions(params: { "page"?: number; "per_page"?: number }): Promise<any> {
return this._request("GET", "/combined_submissions", { params });
}
/** Merge generated PDFs together */
combineSubmissions(body: unknown): Promise<any> {
return this._request("POST", "/combined_submissions", { body });
}
/** Check the status of a combined submission (merged PDFs) */
getCombinedSubmission(params: { "combined_submission_id": string }): Promise<any> {
return this._request("GET", "/combined_submissions/{combined_submission_id}", { params });
}
/** Expire a combined submission */
expireCombinedSubmission(params: { "combined_submission_id": string }): Promise<any> {
return this._request("DELETE", "/combined_submissions/{combined_submission_id}", { params });
}
/** Merge submission PDFs, template PDFs, or custom files */
combinePdfs(body: unknown): Promise<any> {
return this._request("POST", "/combined_submissions?v=2", { body });
}
/** Create a new custom file from a cached presign upload */
createCustomFileFromUpload(body: unknown): Promise<any> {
return this._request("POST", "/custom_files", { body });
}
/** Look up a submission data request */
getDataRequest(params: { "data_request_id": string }): Promise<any> {
return this._request("GET", "/data_requests/{data_request_id}", { params });
}
/** Update a submission data request */
updateDataRequest(body: unknown, params: { "data_request_id": string }): Promise<any> {
return this._request("PUT", "/data_requests/{data_request_id}", { body, params });
}
/** Creates a new data request token for form authentication */
createDataRequestToken(params: { "data_request_id": string }): Promise<any> {
return this._request("POST", "/data_requests/{data_request_id}/tokens", { params });
}
/** Get a list of all folders */
listFolders(params: { "parent_folder_id"?: string }): Promise<any> {
return this._request("GET", "/folders/", { params });
}
/** Create a folder */
createFolder(body: unknown): Promise<any> {
return this._request("POST", "/folders/", { body });
}
/** Delete a folder */
deleteFolder(params: { "folder_id": string }): Promise<any> {
return this._request("DELETE", "/folders/{folder_id}", { params });
}
/** Move a folder */
moveFolderToFolder(body: unknown, params: { "folder_id": string }): Promise<any> {
return this._request("POST", "/folders/{folder_id}/move", { body, params });
}
/** Rename a folder */
renameFolder(body: unknown, params: { "folder_id": string }): Promise<any> {
return this._request("POST", "/folders/{folder_id}/rename", { body, params });
}
/** List all submissions */
listSubmissions(params: { "cursor"?: string; "limit"?: number; "created_after"?: string; "created_before"?: string; "type"?: string; "include_data"?: boolean }): Promise<any> {
return this._request("GET", "/submissions", { params });
}
/** Generates multiple PDFs */
batchGeneratePdfs(body: unknown): Promise<any> {
return this._request("POST", "/submissions/batches", { body });
}
/** Check the status of a submission batch job */
getSubmissionBatch(params: { "submission_batch_id": string; "include_submissions"?: boolean }): Promise<any> {
return this._request("GET", "/submissions/batches/{submission_batch_id}", { params });
}
/** Check the status of a PDF */
getSubmission(params: { "submission_id": string; "include_data"?: boolean }): Promise<any> {
return this._request("GET", "/submissions/{submission_id}", { params });
}
/** Expire a PDF submission */
expireSubmission(params: { "submission_id": string }): Promise<any> {
return this._request("DELETE", "/submissions/{submission_id}", { params });
}
/** Get a list of all templates */
listTemplates(params: { "query"?: string; "parent_folder_id"?: string; "page"?: number; "per_page"?: number }): Promise<any> {
return this._request("GET", "/templates", { params });
}
/** Create a new PDF template with a form POST file upload */
createPDFTemplate(): Promise<any> {
return this._request("POST", "/templates", { });
}
/** Check the status of an uploaded template */
getTemplate(params: { "template_id": string }): Promise<any> {
return this._request("GET", "/templates/{template_id}", { params });
}
/** Update a Template */
updateTemplate(body: unknown, params: { "template_id": string }): Promise<any> {
return this._request("PUT", "/templates/{template_id}", { body, params });
}
/** Add new fields to a Template */
addFieldsToTemplate(body: unknown, params: { "template_id": string }): Promise<any> {
return this._request("PUT", "/templates/{template_id}/add_fields", { body, params });
}
/** Copy a Template */
copyTemplate(body: unknown, params: { "template_id": string }): Promise<any> {
return this._request("POST", "/templates/{template_id}/copy", { body, params });
}
/** Move Template to folder */
moveTemplateToFolder(body: unknown, params: { "template_id": string }): Promise<any> {
return this._request("POST", "/templates/{template_id}/move", { body, params });
}
/** Fetch the JSON schema for a template */
getTemplateSchema(params: { "template_id": string }): Promise<any> {
return this._request("GET", "/templates/{template_id}/schema", { params });
}
/** List all submissions for a given template */
gettemplatesTemplateIdSubmissions(params: { "template_id": string; "cursor"?: string; "limit"?: number; "created_after"?: string; "created_before"?: string; "type"?: string; "include_data"?: boolean }): Promise<any> {
return this._request("GET", "/templates/{template_id}/submissions", { params });
}
/** Generates a new PDF */
generatePDF(body: unknown, params: { "template_id": string }): Promise<any> {
return this._request("POST", "/templates/{template_id}/submissions", { body, params });
}
/** Generates multiple PDFs */
batchGeneratePdfV1(body: unknown, params: { "template_id": string }): Promise<any> {
return this._request("POST", "/templates/{template_id}/submissions/batch", { body, params });
}
/** Fetch the full template attributes */
getFullTemplate(params: { "template_id": string }): Promise<any> {
return this._request("GET", "/templates/{template_id}?full=true", { params });
}
/** Create a new PDF template from a cached presign upload */
createPDFTemplateFromUpload(body: unknown): Promise<any> {
return this._request("POST", "/templates?desc=cached_upload", { body });
}
/** Create a new HTML template */
createHTMLTemplate(body: unknown): Promise<any> {
return this._request("POST", "/templates?desc=html", { body });
}
/** Get a presigned URL so that you can upload a file to our AWS S3 bucket */
getPresignUrl(): Promise<any> {
return this._request("GET", "/uploads/presign", {});
}
}
export default APIv1;
No reviews yet. Be the first to rate this API.
Yes. API v1 uses basic authentication, so you bring your own key from the provider. You store it once on OmniStream and the proxy injects it into every call, so your code only ever sends your Omni key.
DocSpring is a service that helps you fill out and sign PDF templates. It exposes 35 endpoints over GET, POST, DELETE, PUT, including GET /authentication, GET /combined_submissions, POST /combined_submissions.
Install the OmniStream SDK for your language and call API v1 through it. The client is generated from this API's OpenAPI spec, so parameters and responses are fully typed, and the same client also calls every other API in the marketplace.
You can start on the free plan. OmniStream charges for the unified SDK, key storage and proxy rather than for API v1 itself, and API v1's own rate limits still apply to your provider key.
GraphHopper Directions: Routing, geocoding, isochrones, matrix, and route optimization from the GraphHopper Directions API.
Create a new custom file from a cached presign upload
Look up a submission data request
Update a submission data request
Creates a new data request token for form authentication
Get a list of all folders
Create a folder
Delete a folder
Move a folder
Rename a folder
List all submissions
Generates multiple PDFs
Check the status of a submission batch job
Check the status of a PDF
Expire a PDF submission
Get a list of all templates
Create a new PDF template with a form POST file upload
Check the status of an uploaded template
Update a Template
Add new fields to a Template
Copy a Template
Move Template to folder
Fetch the JSON schema for a template
List all submissions for a given template
Generates a new PDF
Generates multiple PDFs
Fetch the full template attributes
Create a new PDF template from a cached presign upload
Create a new HTML template
Get a presigned URL so that you can upload a file to our AWS S3 bucket