curl --request POST \
--url https://app.vumasign.com/api/v1/standing-authorisations/{authorisationId}/renew \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: <idempotency-key>' \
--data '
{
"valid_until": "2028-04-13T22:00:00.000Z"
}
'import requests
url = "https://app.vumasign.com/api/v1/standing-authorisations/{authorisationId}/renew"
payload = { "valid_until": "2028-04-13T22:00:00.000Z" }
headers = {
"Idempotency-Key": "<idempotency-key>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'Idempotency-Key': '<idempotency-key>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({valid_until: '2028-04-13T22:00:00.000Z'})
};
fetch('https://app.vumasign.com/api/v1/standing-authorisations/{authorisationId}/renew', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://app.vumasign.com/api/v1/standing-authorisations/{authorisationId}/renew"
payload := strings.NewReader("{\n \"valid_until\": \"2028-04-13T22:00:00.000Z\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Idempotency-Key", "<idempotency-key>")
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}{
"id": "5e1d7c2a-8b34-4f6e-9a12-3c4d5e6f7a8b",
"number": "SA-0031",
"status": "invited",
"sandbox": false,
"brand": {
"id": "9d4f2a6b-1c3e-4d5f-8a7b-6c5d4e3f2a1b",
"name": "NTT DATA"
},
"legal_entity": {
"name": "NTT DATA South Africa (Pty) Ltd",
"registration_number": "1990/001234/07"
},
"grantor": {
"name": "Naledi Mokoena",
"email": "naledi@example.test",
"job_title": "HR Director"
},
"intended_use": "Salary adjustment letters and employment confirmations",
"valid_from": "2027-10-13T22:00:00.000Z",
"valid_until": "2028-04-13T22:00:00.000Z",
"invite_expires_at": "2027-10-01T22:00:00.000Z",
"granted_at": null,
"cancellation": null,
"revocation": null,
"invalidation": null,
"reference": "ntt-signatory-2026",
"renews": "0b9a5c1e-7d42-4f8a-9e13-5c6d7e8f9a0b",
"renewal_requested_at": null,
"applied_count": 0,
"created_at": "2027-09-17T06:00:00.000Z"
}{
"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>"
}
}{
"error": {
"code": "unauthenticated",
"message": "<string>"
}
}{
"error": {
"code": "unauthenticated",
"message": "<string>"
}
}{
"error": {
"code": "unauthenticated",
"message": "<string>"
}
}Renew a standing authorisation: send its grantor a new mandate that starts when it ends.
Creates a new authorisation, invited, for the same grantor, brand and legal entity, and sends the grantor a renewal mandate naming the one it renews. ⚠️ IT GRANTS NOTHING until that mandate is signed and sealed, exactly as a new request. The old authorisation stays in force until its own valid_until, unchanged, so there is no gap: while it is in force the renewal’s valid_from is its valid_until; once it has expired, the renewal runs from its own grant.
The renewal records renews, and every authorisation.* webhook about it carries renews, so on authorisation.granted you can start naming the new id. Vumasign never chooses an authorisation for you on a send.
Only an active or expired authorisation can be renewed (409 authorisation_not_renewable), and only within 90 days of its end (422 authorisation_validity_invalid). One renewal at a time: a pending or granted renewal is 409 authorisation_already_renewed. A test key renews only sandbox authorisations; a live key renewing a sandbox one is 422 authorisation_environment_mismatch. The refusals of the invitation apply too, and so does its answer when the mandate cannot be sent or delivered.
curl --request POST \
--url https://app.vumasign.com/api/v1/standing-authorisations/{authorisationId}/renew \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: <idempotency-key>' \
--data '
{
"valid_until": "2028-04-13T22:00:00.000Z"
}
'import requests
url = "https://app.vumasign.com/api/v1/standing-authorisations/{authorisationId}/renew"
payload = { "valid_until": "2028-04-13T22:00:00.000Z" }
headers = {
"Idempotency-Key": "<idempotency-key>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'Idempotency-Key': '<idempotency-key>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({valid_until: '2028-04-13T22:00:00.000Z'})
};
fetch('https://app.vumasign.com/api/v1/standing-authorisations/{authorisationId}/renew', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://app.vumasign.com/api/v1/standing-authorisations/{authorisationId}/renew"
payload := strings.NewReader("{\n \"valid_until\": \"2028-04-13T22:00:00.000Z\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Idempotency-Key", "<idempotency-key>")
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}{
"id": "5e1d7c2a-8b34-4f6e-9a12-3c4d5e6f7a8b",
"number": "SA-0031",
"status": "invited",
"sandbox": false,
"brand": {
"id": "9d4f2a6b-1c3e-4d5f-8a7b-6c5d4e3f2a1b",
"name": "NTT DATA"
},
"legal_entity": {
"name": "NTT DATA South Africa (Pty) Ltd",
"registration_number": "1990/001234/07"
},
"grantor": {
"name": "Naledi Mokoena",
"email": "naledi@example.test",
"job_title": "HR Director"
},
"intended_use": "Salary adjustment letters and employment confirmations",
"valid_from": "2027-10-13T22:00:00.000Z",
"valid_until": "2028-04-13T22:00:00.000Z",
"invite_expires_at": "2027-10-01T22:00:00.000Z",
"granted_at": null,
"cancellation": null,
"revocation": null,
"invalidation": null,
"reference": "ntt-signatory-2026",
"renews": "0b9a5c1e-7d42-4f8a-9e13-5c6d7e8f9a0b",
"renewal_requested_at": null,
"applied_count": 0,
"created_at": "2027-09-17T06:00:00.000Z"
}{
"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>"
}
}{
"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.
Headers
Any string that identifies this request, at most 255 characters. ⚠️ REQUIRED: a retry with the same key returns the same renewal instead of sending a second mandate. The caller’s own request identifier.
"01960000-0000-4000-8000-00000000ffff"
Path Parameters
The id of the authorisation to renew. A live authorisation’s id answers not_found to a test key.
An authorisation id.
"0b9a5c1e-7d42-4f8a-9e13-5c6d7e8f9a0b"
Body
Optional. Send no body to renew for the longest span allowed.
Response
The renewal, invited, with renews naming the authorisation it renews.
The renewal.
The authorisation’s id.
Its number in your organisation, as printed on the mandate.
"SA-0012"
invited until the signed mandate is sealed, then active. An invite ends declined, expired_unsigned or cancelled; an active one ends revoked, expired or invalidated.
invited, active, declined, expired_unsigned, cancelled, revoked, expired, invalidated Requested with a test key: it binds nobody, and applies only to sandbox envelopes.
The brand it covers, as granted.
Show child attributes
Show child attributes
The legal entity the grantor signs for.
Show child attributes
Show child attributes
The person who signs the mandate.
Show child attributes
Show child attributes
Your description, printed on the mandate as yours. Not enforced.
The start, or null for "from the grant".
The end.
When the mandate lapses unsigned.
When the signed mandate was sealed and the authorisation took effect.
Set when the request ended without a grant.
Show child attributes
Show child attributes
Set when an active authorisation was revoked.
Show child attributes
Show child attributes
Set when the brand changed under it.
Show child attributes
Show child attributes
Your own reference, as you set it.
The authorisation this one renews (POST /standing-authorisations/{id}/renew), or null. The old one stays in force until its own valid_until; name the new one on sends from then. Vumasign never chooses an authorisation for you.
When the grantor asked, through the renew link in their own email, to be asked again. Null if they have not. It grants nothing; renewing is your call.
How many documents it pre-signed.
When it was requested.