curl --request GET \
--url https://app.vumasign.com/api/v1/templates/{templateId}/documents/{documentId}/field-map \
--header 'Authorization: Bearer <token>'import requests
url = "https://app.vumasign.com/api/v1/templates/{templateId}/documents/{documentId}/field-map"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://app.vumasign.com/api/v1/templates/{templateId}/documents/{documentId}/field-map', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://app.vumasign.com/api/v1/templates/{templateId}/documents/{documentId}/field-map"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}"<string>"{
"error": {
"code": "unauthenticated",
"message": "<string>"
}
}{
"error": {
"code": "unauthenticated",
"message": "<string>"
}
}{
"error": {
"code": "unauthenticated",
"message": "<string>"
}
}{
"error": {
"code": "unauthenticated",
"message": "<string>"
}
}{
"error": {
"code": "unauthenticated",
"message": "<string>"
}
}{
"error": {
"code": "unauthenticated",
"message": "<string>"
}
}{
"error": {
"code": "unauthenticated",
"message": "<string>"
}
}One document of a template with every field outlined and numbered on it, as a PDF.
THE FIELD MAP’S ANNOTATED PAGES. Every page of one document of the template, as GET /api/v1/documents/{documentId}/content serves it, with every field’s box outlined and labelled: its number — the box of its row in GET /api/v1/templates/{templateId}/field-map — and its data_key, with its subject in brackets before it when it has one. A box of a question shows the question’s key and the box’s own option value (medical_aid.plan = classic). Every box of a field split across several sets of printed boxes is outlined and carries the one number, marked (1/2), (2/2).
A box with a name somebody chose or Vumasign suggested is drawn in solid blue. A box whose name Vumasign numbered because nothing printed says what it is (name_source: fallback, such as form.text_013) is drawn in dashed red with that key: a value reaches it, but the name tells you nothing, so give it a better one. A box with no name at all is dashed red and labelled unnamed. A box no value is written to, such as a signature, is drawn in grey and labelled with its type.
⚠️ A PDF OF THE WHOLE DOCUMENT, NOT AN IMAGE. The outlines are drawn into the page as vectors, so they stay sharp at any zoom and the form’s own text stays selectable. Each document of a pack is its own map: ask once per documents[].id. It is rebuilt like every document this API serves — it draws and does nothing, and the form is not fillable. A document with more than 5,000 boxes to draw is refused with document_too_complex; its spreadsheet still lists every field.
⚠️ IT IS THE DOCUMENT’S BYTES, SO IT NEEDS documents:read, as .../content does. The names on it are what GET /api/v1/templates/{templateId} already publishes.
⚠️ THE SAME 404 for every situation in which you cannot have it: no such template, another organisation’s, an archived one, a document that is not one of this template’s, and an id that is not a uuid. Never cached, by anything: Cache-Control: private, no-store.
curl --request GET \
--url https://app.vumasign.com/api/v1/templates/{templateId}/documents/{documentId}/field-map \
--header 'Authorization: Bearer <token>'import requests
url = "https://app.vumasign.com/api/v1/templates/{templateId}/documents/{documentId}/field-map"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://app.vumasign.com/api/v1/templates/{templateId}/documents/{documentId}/field-map', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://app.vumasign.com/api/v1/templates/{templateId}/documents/{documentId}/field-map"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}"<string>"{
"error": {
"code": "unauthenticated",
"message": "<string>"
}
}{
"error": {
"code": "unauthenticated",
"message": "<string>"
}
}{
"error": {
"code": "unauthenticated",
"message": "<string>"
}
}{
"error": {
"code": "unauthenticated",
"message": "<string>"
}
}{
"error": {
"code": "unauthenticated",
"message": "<string>"
}
}{
"error": {
"code": "unauthenticated",
"message": "<string>"
}
}{
"error": {
"code": "unauthenticated",
"message": "<string>"
}
}Authorizations
Authorization: Bearer vsk_live_…. Chosen over a bespoke X-API-KEY header because every client, proxy and log-redaction rule already knows this one. What a key may DO is its scopes — see x-scopes at the root of this document and x-required-scope on each operation. The scope list is not written here because OpenAPI reserves a requirement’s scope array for oauth2 and openIdConnect and requires it to be empty for an http scheme.
Path Parameters
The template’s id, as returned by the list endpoint.
A template id.
"01960000-0000-4000-8000-0000000007e1"
A documents[].id of this template, from GET /api/v1/templates/{templateId}. ⚠️ The document’s id, not the template’s.
A document id.
"01960000-0000-4000-8000-00000000d0c5"
Response
The document, every page, with the fields drawn on it. Content-Disposition: attachment; filename="field-map-document-1-1a2b3c4d.pdf": the document’s place in the pack, and the start of the template’s ETag — nothing about the customer. A spreadsheet and pages whose names end the same way were drawn from the same version of the template, so their numbers agree.
The PDF bytes. ⚠️ NOT JSON. Its refusals still are: every non-2xx is the same Error envelope in application/json.