REST API
The REST API does what the panel on the page does, from another system: a contract tool, a workflow engine, an HR system or a script. It is about signing only, and it is not a general Confluence API.
The global settings carry the same reference under API access, beside the one thing no website can tell you: your site’s own address.
Before you start
You need three things:
- SignPlus installed on your Confluence site.
- The API address. API access, then API address. Atlassian creates it for each
installation, so it is different on every site and cannot be guessed. Every endpoint below is
a path added to it, such as
/v1/signings. - An Atlassian service account with an OAuth 2.0 credential. SignPlus issues no API keys of
its own. An organisation administrator creates the service account and its credential in
Atlassian Administration, copies the
client_idandclient_secret, which are shown once, grants the credential one scope,read:confluence-user, and gives the service account the Confluence permissions it should have. Atlassian’s instructions.
What the service account’s permissions decide
SignPlus spends the token once against your site to find out whose it is, checks that account’s Confluence permissions on the page on every request, and reads the page as that account. More scopes on the credential grant nothing extra.
| To | The account needs |
|---|---|
| Read a page’s status, its signings, their people, a PDF or a signed document | View the page |
| Start a signing, cancel one, or export a PDF | Edit the page |
| Delete a finished signing | What the site’s deleting signings setting allows |
Because the page is read as the service account, a signing holds what that account sees: a Jira work items table lists what it may see, and an excerpt from a page it cannot open is left out. Give it the access the document should reflect. A token from another Atlassian organisation is refused by Atlassian itself.
Your first signing
Fetch a token. The client id and secret travel in the body of a POST, read from the environment so the secret is never written on a command line.
export SIGNPLUS_URL="https://513c7988-....hello.atlassian.net/x1/G7gth8r-Vw5-wMfGB7FGgW6AQ9A"export CLIENT_ID=... CLIENT_SECRET=...
export SIGNPLUS_TOKEN=$(jq -n '{grant_type: "client_credentials", client_id: env.CLIENT_ID, client_secret: env.CLIENT_SECRET}' \ | curl -s -X POST 'https://auth.atlassian.com/oauth/token' \ -H 'Content-Type: application/json' --data @- \ | jq -r .access_token)The token lasts 60 minutes. A page id is in the page’s address, or under Page information.
1. Ask where the page stands
curl -s "$SIGNPLUS_URL/v1/pages/123456/status" -H "Authorization: Bearer $SIGNPLUS_TOKEN"{ "pageId": "123456", "spaceId": "98765", "pageVersion": 4, "state": "ready-to-sign", "signings": [] }A 401 means the token is wrong or has expired. A 403 means the service account cannot see that
page.
2. Start a signing
curl -s -X POST "$SIGNPLUS_URL/v1/signings" \ -H "Authorization: Bearer $SIGNPLUS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "pageId": "123456", "signers": [ { "email": "anna@example.com", "name": "Anna Tamm" }, { "group": "finance-team" } ] }'{ "jobId": "7c1e9a0f3b2d4c5e6f7a8b9c", "status": "queued", "pageId": "123456", "statusUrl": "/v1/pages/123456/signing-jobs/7c1e9a0f3b2d4c5e6f7a8b9c" }The answer is 202 Accepted. The request has been checked against the space’s settings, and the
signing is prepared in the background: the page is rendered, every member of the group is looked
up, and everybody is sent to Dokobit. That takes seconds for a few people and minutes for a group
of thousands.
3. Follow the job
curl -s "$SIGNPLUS_URL/v1/pages/123456/signing-jobs/7c1e9a0f3b2d4c5e6f7a8b9c" \ -H "Authorization: Bearer $SIGNPLUS_TOKEN"{ "id": "7c1e9a0f3b2d4c5e6f7a8b9c", "status": "started", "reference": "a3f9c2d1...", "documentName": "Expense policy" }queued and running mean it is being prepared. started means Dokobit has it and the
invitations are out; keep the reference, which is the signing’s public id and what the other
endpoints take. failed carries the reason in message.
4. See who has not signed
curl -s "$SIGNPLUS_URL/v1/signings/a3f9c2d1.../signers?pageId=123456&status=pending" \ -H "Authorization: Bearer $SIGNPLUS_TOKEN" | jq -r '.signers[] | [.name, .email] | @tsv'Do not poll for completion
A signing takes minutes or days. Configure the completion webhook instead, and SignPlus posts you the signed document when it exists.
Authentication and limits
Authorization: Bearer <the access token>That is the only credential. Every authentication failure answers the same 401 with the same
sentence, so the API cannot be used to find out which tokens are live. Basic authentication is
not supported. Revoke the credential in Atlassian Administration, and SignPlus stops accepting its
tokens within two minutes.
| Limit | |
|---|---|
| Rate | 60 requests per minute per account, answered with 429 |
| Request body | 2MB, answered with 413 |
| People on one signing | 25,000, after groups are expanded |
| People named one by one in a view restriction | 200. A group counts as one |
| People on one reply | 100 by default, any number with limit, and nextCursor reaches the rest |
| Document returned inline | 4MB, above which contentBase64 is null rather than truncated |
| Time | 55 seconds per request. A signing is queued, so it is not bound by this |
Every request, a refused one included, is recorded under Logs in the global settings: what was called, the outcome and the account it acted as. Never the token.
Endpoints
Every reply is JSON, errors included. pageId is required on every endpoint that takes a
reference, so a reference from one page cannot address a signing on another.
| Endpoint | Does | Needs |
|---|---|---|
POST /v1/signings |
Queues a signing. 202 and a job |
Edit |
GET /v1/pages/{pageId}/signing-jobs/{jobId} |
How a queued signing went. Kept for 7 days | The account that queued it |
GET /v1/pages/{pageId}/status |
Where a page stands, and its signings, newest first | View |
GET /v1/signings/{reference}?pageId= |
One signing, with counts rather than its people | View |
GET /v1/signings/{reference}/signers?pageId= |
The people on a signing, a page at a time | View |
GET /v1/signings |
Signings on a page with ?pageId=, or every signing the account started |
View |
DELETE /v1/signings/{reference}?pageId= |
Cancels a running signing, or deletes a finished one | See above |
POST /v1/pages/{pageId}/pdf |
Exports the page as PDF and attaches it | Edit |
GET /v1/pages/{pageId}/pdf/{attachmentId} |
A document SignPlus attached to the page | View |
GET /v1/signings/{reference}/document?pageId= |
The signed document, once everyone has signed | View |
POST /v1/signings
| Field | Required | Notes |
|---|---|---|
pageId |
yes | The page to sign |
signers |
yes | At least one, below |
name |
no | What the document is called. The page title when left out, numbered when that name is already attached |
type |
no | pdf, asice, bdoc, edoc or adoc. The space decides which are allowed |
message |
no | Sent to signers. The space may require it or forbid it |
deadline |
no | ISO 8601 date and time with an offset, in the future |
hardDeadline |
no | Refuse signatures after the deadline. The space may overrule |
lockPage |
no | Make the page read-only while it is signed. The space may overrule |
restrictViewers |
no | Restrict viewing to the participants. The space may overrule |
includeAttachments |
no | Append the page’s attachments |
A signer is a person or a group, with role signer (the default) or viewer:
{ "email": "anna@example.com", "name": "Anna Tamm", "role": "signer" }{ "group": "finance-team", "role": "signer" }{ "groupId": "0f6a1b2c-...", "role": "viewer" }- A person is named by email address. When the address belongs to a Confluence user who can
view the page, they are added as that user. Anybody else signs as an external signer.
Confluence cannot be searched by address, so the match is made by
nameand confirmed against the account’s own address. - A group is named by its name or its id, and every member is invited with the group’s role.
A member Confluence gives no address for cannot be invited, and the job’s
messagesays how many. Unlike the panel on the page, a service account is not limited to groups it belongs to: its Confluence permissions decide. spaceIdis not a field. SignPlus asks Confluence which space the page is in, so a caller cannot choose which space’s rules apply.
GET /v1/pages/{pageId}/status
state |
Means |
|---|---|
ready-to-sign |
Nothing has been started on this page |
pending-unmodified |
A signing is out and the page has not changed |
pending-modified |
A signing is out and the page has changed since it was sent |
signed-valid |
Signed, and the page is exactly what was signed |
signed-modified |
Signed, and the page has been edited since |
declined |
A signer refused |
unknown |
The stored status is not one of the above |
The newest signing decides the state, by the same hash the byline uses.
GET /v1/signings/{reference}/signers
| Query | Notes |
|---|---|
limit |
People per reply, 100 by default |
cursor |
The nextCursor of the previous reply |
status |
pending, signed or declined |
email, accountId |
Repeat either to ask about specific people. notFound lists anyone never asked |
A reply can come back shorter than limit when reading more would outrun the request’s time.
Only an absent nextCursor means you have everybody. This is the one place SignPlus returns a
signer’s email address, to an account that can view the page, because chasing the people who
have not signed needs it. The panel on the page never sends one to a browser.
DELETE /v1/signings/{reference}
A running signing is cancelled: removed from Dokobit for every signer, with its page restrictions
lifted. A finished one is deleted: its record goes, and the signed file stays attached to the page.
The same permissions apply as in the panel: see
cancelling or deleting a signing. A 502
means Dokobit could not be reached or the page restrictions could not be put back; nothing was
removed, and sending it again is safe.
The PDF endpoints
POST /v1/pages/{pageId}/pdf takes name, which the {documentName} placeholder prints, and
includeAttachments. Add ?inline=true to have the bytes back as base64 beside the attachment’s
full Confluence address. Without Confluence credentials, keep the attachmentId and fetch the file
with GET /v1/pages/{pageId}/pdf/{attachmentId}.
GET /v1/signings/{reference}/document answers 409 with the signing’s state until every signer
has signed and Dokobit has handed the file over.
Errors
| Status | Means |
|---|---|
400 |
Something is missing, or the space’s rules refuse it. error says which |
401 |
The token is not valid here. All reasons answer the same way |
402 |
The site has no active SignPlus licence |
403 |
The service account cannot reach that page, or may not do that to it |
404 |
No such page, signing, job, document or path |
409 |
The signing has no signed document yet |
413 |
The body is over 2MB |
429 |
Over 60 requests in a minute for this account |
500 |
Something failed inside SignPlus. The detail is in the app’s logs, never in the reply |
502 |
Dokobit refused, or could not be reached |
503 |
Signing is not configured on this site, for example no Dokobit token |
{ "error": "At least one signer is required in \"signers\"." }What the API never returns
- The Dokobit document token, which downloads the signed file and is what a signer signs with.
The
referenceis its SHA-256 and cannot be reversed. - A signer’s Dokobit token, for the same reason.
- A stored copy of the document. None is stored: a document comes back only from the PDF endpoints, which read it from the page.
Things that will catch you out
- The address is per installation. A script that works on your sandbox has the wrong address for production.
- The service account needs Confluence permissions, not only a credential. A new one can
authenticate and then be refused
403by every page. - A signing is queued. The
POSTanswers before the signing exists. Follow the job, or the completion webhook, for the reference. - The space’s settings win. A refusal that mentions a format or a message points at the space’s SignPlus settings.
- Test mode is watermarked. In Test signing mode, documents can only be signed with Dokobit’s test identities and have no legal effect.
- Tokens expire after an hour. A script that caches one forever starts answering
401exactly once, in production.
When you ask for help with a signing, quote its reference: it identifies the signing and reveals
nothing about its contents.
Related
A problem or a question? Write to support@oktul.com or open a request in the Help Center. Both reach the same service desk, so either way the request gets a reference and an SLA measuring the response.