Document Signing V1
Last Updated: 2 June 2025
Last updated
Was this helpful?
Last Updated: 2 June 2025
Last updated
Was this helpful?
We are no longer accepting requests to onboard Sign V1. Please refer to the instead.
30 Sep 2024
Deprecation of Basic Authentication
11 Nov 2024
Added IP addresses for whitelisting
5 Mar 2025
27 May 2025
2 June 2025
The guide provide a clear illustration of the web-based application programming interfaces (API) for the use of Document Signing Application Providers (DSAP). Described here are the necessary APIs that DSAPs must invoke to facilitate a document signing process for a Singpass user.
An overview of the document signing flow and the interactions between DSAP, Singpass and other dependencies.
Disclaimer: The domains used in the sample requests in the API specs below may not be accurate for your environment. Please choose the correct one from the table below that suits your testing needs.
Staging
SSL
Basic Authentication (Deprecated)
Production
SSL
Basic Authentication (Deprecated)
You must not do "cert pinning" or create any form of dependency to the leaf TLS certificates of the above domains. Singpass reserves the right to rotate its TLS leaf certificate without prior notice to partners.
mTLS is no longer required. We will ignore all incoming mTLS client authentication.
Staging
SSL
Production
SSL
Please note that there may be more than one key appearing in the JWKS, and DSAPs must use the kid
value to identify the right key.
Additionally, server certificates presented must minimally conform to the following requirements:
Required Public Key dimensions
>= 2048 bits
>= 3072 bits (recommended)
>= 256-bit based on curves P-256
, P-384
or P-521
(NIST curves, aka secp256r1
, secp384r1
, secp521r1
respectively)
X.509 v3 extension KeyUsage
digitalSignature, keyEncipherment
digitalSignature
X509 v3 extension ExtendedKeyUsage
serverAuth
serverAuth
DSS APIs are RESTful in design and communicate classes of errors based on the Http Status code. The status code should be used to determine if the error is caused by consumer or provider. Consumers should log the HTTP status code along with the id
and/or trace_id
of the error.
4XX
Errors caused by API consumer. You can expect codes such as 400, 401, 403, 404 etc if incorrect requests are made to APIs.
Example: 400: Invalid/missing request arguments
5XX
Errors caused by DSS or its dependencies. You can expect codes such as 500, 502, 503 etc if there is an issue on DSS or its dependencies.
Example: 500: Internal Server Error due to some kind of programming error.
id
String
The unique identifier for this error/request. Please log this identifier for support and debugging purposes.
trace_id
String
(Optional) An auxiliary id for request correlation across services. Please also log this identifier for operational support and debugging purposes.
error
String
Error code representing broad class of error. See Error Codes for the list of possible error codes that can be returned and what they represent.
error_description
String
Returns human readable general information about the reason for the error. Note that due to security reasons; detailed information is unlikely to be available in this message.
CLIENT_SIDE_ERROR
Generic error code for an invalid request.
SERVER_SIDE_ERROR
Generic error code for an error that occurred in Singpass.
UNAUTHORIZED
Authorization header value is invalid.
MISSING_AUTHORIZATION
Authorization header was required but not found.
ARGUMENTS_NOT_VALID
Some request parameters are invalid.
SIGN_REF_NOT_FOUND
Requested sign ref is invalid or has already expired.
MULTIPLE_ASSERTION_HEADER
Multiple DSS assertion headers.
ASSERTION_NOT_VALID
DSS assertion header is invalid.
JWKS_URL_NOT_FOUND
DSAP JWKS URL is not found.
CLIENT_JWKS_ERROR
Unable to fetch DSAP JWKS or DSAP JWKS is invalid.
The API in this sections are endpoints invoked by DSAPs at various part of the DSS flow.
/doc-signing-sessions
/doc-signing-sessions/<sign_ref>/hash
/.well-known/keys.json
DSAPs are to use JSON Web Token (JWT) assertion for authentication when calling the DSS APIs.
Decoded JWT Header
alg
String
Algorithm used in the JWT. Acceptable values are: ES256
, ES384
, ES512
typ
String
Acceptable value: JWT
kid
String
The Key ID used for the JWT. This value must correspond to a key in the DSAP JWKS endpoint.
iss
String
Use the ClientID provided by Singpass
sub
String
Use the ClientID provided by Singpass
aud
String
The DSS domain that will be accepting the JWT.
iat
Number
A Unix timestamp in seconds indicating the date and time when the JWT was issued.
exp
Number
A Unix timestamp in seconds indicating the date and time when the JWT will expire. Max expiry allowed is600
seconds from iat
jti
String
A random string that must be regenerated for each JWT to prevent replay attacks. Singpass will cache and reject all duplicate jti
that is sent within a preset period. As such, DSAPs are advised to use a UUID-v4 value when populating this value.
DSAP JWKS Endpoint
Singpass will attempt to retrieve the public key from the DSAP JWKS endpoint in order to verify the JWT. This endpoint is provided during onboarding and is tied to the DSAP Client ID.
Singpass will only accept JWT signed by EC key. DSAP JWKS should have at least 1 EC key.
kty
String
Key Type Acceptable value: EC
x
String
X-Coordinate This is the X-coordinate of the elliptic curve point, which is a component of the public key. It is base64url-encoded.
y
String
Y-Coordinate This is the Y-coordinate of the elliptic curve point, which is a component of the public key. It is base64url-encoded.
crv
Number
Curve Name
use
Number
Public Key Use. Acceptable value: sig
kid
String
Key ID. Singpass will search for the kid
that was specified in the JWT for verification.
alg
String
[Optional] Algorithm
DSAPs are to put the JWT in the request header with the key X-Dss-Assertion
when calling all DSS APIs.
POST /doc-signing-sessions
DSAPs can call this endpoint to start a document signing session. On success, a unique signing reference value - sign_ref
- is included in the response object. The sign_ref
is the primary identifier of a signing session used in all exchanges between Singpass and DSAP.
DSAPs have to specify a client notification token when initialising a session. Singpass will specify this token in an Authorization
header for subsequent calls to the DSAP notification webhook endpoints.
Sample Curl Request (Deprecated)
Sample Curl Request (New)
Sample Response
Request Body
client_notification_token
String
A token provided by the DSAP to be used by Singpass when invoking the DSAP’s webhook endpoint.
Allowed Characters: Alphanumeric, underscore ( _ ), dash ( - ), and whitespace
Max length: 255 characters
tenant_id
String
The identifier of the tenant of the DSAP client using the doc signing service.
Allowed Characters: Alphanumeric, underscore ( _ ), dash ( - ), and whitespace
Max length: 255 characters
Authorization
(Deprecated)
The DSAP’s client id and client secret in http basic authentication scheme format.
Not required if DSAP is using JWT to authenticate
X-Dss-Assertion
(New)
JWT issued by the DSAP for authentication.
Authorization
(Deprecated)
The DSAP’s client id and client secret in http basic authentication scheme format.
Not required if DSAP is using JWT to authenticate.
X-Dss-Assertion
(New)
JWT issued by the DSAP for authentication.
sign_ref
String
The primary identifier of a signing session used in all exchanges between Singpass and DSAP.
qr_code.payload
String
The QR payload containing the sign ref in a format understood by SingPass Mobile (SPM). DSAPs are expected to encode and display this as a QR code for SPM users to scan. Refer to the UX Guide provided in the developer package for the QR code display specifications.
expires_at
Number
A Unix timestamp in seconds indicating the date and time when the sign_ref
will expire.
The host of the URL in qr_code.payload
in staging environment will change to stg-app.singpass.gov.sg after 18 Mar 2025.
POST /doc-signing-sessions/<sign-ref>/hash
DSAPs must use this endpoint to send the document hash, document name, and challenge code to Singpass. Singpass will then forward the document information and challenge code to the user for verification and signing.
Sample HTTP Request (Deprecated)
sign_ref
The primary identifier of a signing session used in all exchanges between Singpass and DSAP
doc_name
String
The name of the document to be signed by the user. Do note that this value will be displayed to the user, so it is recommended to use a human-readable name.
Length must be between 1 and 255
doc_hash
String
Length must be 64
challenge_code
String
A set of characters used by the user to visually verify the signing session between the Singpass App and the DSAP website.
Length must be 4. Numerical values are recommended.
nonce
String
Singpass-generated random string sent to the DSAP's webhook endpoint during user certificate notification.
challenge_fqdn
String
The domain name of the webpage displaying the QR code. This will be displayed to the user on the Singpass app.
Length must be between 1-255
app_launch_url
String
(Optional) This adds the possibility for the user to be redirected back to the provided App Link after they successfully authorize themselves on the Singpass App. The value passed here should be the App Link registered with Apple’s App Store and/or Google’s Play Store.
Max length allowed is 255 characters.
Authorization
(Deprecated)
The DSAP’s client id and client secret in http basic authentication scheme format. Not required if DSAP is using JWT to authenticate
X-Dss-Assertion
(New)
JWT issued by the DSAP for authentication.
Response Body
There is no body in the response for successful API call.
If Singpass fails to find the requested sign_ref
(e.g. due to expiry), this API will return a HTTP 400
error, and an accompanying SIGN_REF_NOT_FOUND
error code in the response body.
GET /.well-known/keys.json
There is no request body for this API call.
Responses from this endpoint, or individual keys from inside the JWKS can and should be cached for at least 1 hour, and NOT retrieved for each JWT validation. Cache-Control headers on the response indicate a possible policy.
For varying reasons, keys used for signing can and will be rotated/changed with no defined schedule, and at the full discretion of Singpass. When a key rotation happens, the new key will be available from the JWKS endpoint and will have a different kid
value. The new kid
value will be reflected in all the new JWTs signed by Singpass. In such cases, cached copies of Singpass public keys must be refreshed by re-invoking the JWKS endpoint.
If the validation of the Singpass signature fails, re-fetch from the JWKS endpoint once for that validation.
Please read through the list of DON’Ts below:
Do not assume the position of a signing key among the list of the returned keys.
Do not validate Singpass signatures using a hardcoded public key OR kid
. Always determine the correct key (for signature verification) by inspecting the kid
from the JWS header, and use it to retrieve the public key from our JWKS endpoint.
Do not cache only 1 key. Caching should be done for the entire JWKS.
Singpass will inform DSAP of various events that happen during the document signing process. To facilitate this, DSAPs must implement and expose a webhook endpoint to accept information from Singpass.
Singpass will call the webhook endpoint to inform of the following events:
User certificate notification - To send the user’s certificate (See Step 6 of flow diagram).
Document hash signature notification - To send the user’s document hash signature (See Step 14 of flow diagram).
Webhook error notification - To inform DSAP of any errors encountered during the webhook calls above.
Please note that for all calls to the webhook endpoint, DSAPs are expected to respond HTTP 200
to the webhook calls immediately, before any significant processing is performed on the request. This is to keep low latencies on the user-facing APIs that are dependent on the webhook calls and give a better overall experience to Singpass users.
The webhook must accept the POST
HTTP method.
Singpass will perform automated retries of webhook requests if it encounters timeouts and on certain errors. See the webhook Retry Settings for more details.
It is sufficient for DSAPs to respond with an HTTP status code without any response body for this endpoint.
Singpass will call your webhook endpoints from these IP addresses, which you may choose to whitelist.
54.169.20.186
18.143.229.39
54.179.76.90
3.0.39.45
token
String
The signed JWT containing standard and custom claims that describe a user or error event of a digital signing session.
Authorization
Bearer token authentication credentials. The token value is equal to the client_notification_token
provided by the DSAP during session initialization.
There is no body in the response for this API call.
token
structureAs mentioned previously, the request body token
field is a JWT signed by Singpass, which can be verified by DSAPs.
sign_ref
String
The primary identifier of a signing session used in all exchanges between Singpass and DSAP.
user_cert
String
The user's digital signing certificate in base64-encoded DER format.
iat
Number
A Unix timestamp in seconds indicating the date and time when the JWT was issued.
exp
Number
A Unix timestamp in seconds indicating the date and time when the JWT will expire.
nonce
String
A randomly generated string used to associate this user certificate notification to a document hash callback . This nonce must be included in the subsequent document hash callback request from DSAP.
request_type
String
Value to indicate the type of the request, value is user_cert
.
sign_ref
String
The primary identifier of a signing session used in all exchanges between Singpass and DSAP.
doc_hash
String
iat
Number
A Unix timestamp in seconds indicating the date and time when the JWT was issued.
exp
Number
A Unix timestamp in seconds indicating the date and time when the JWT will expire.
doc_hash_signature
String
request_type
String
Value to indicate the type of the request, value is signed_doc_hash
.
sign_ref
String
The primary identifier of a signing session used in all exchanges between Singpass and DSAP.
error
String
Error code representing an error, e.g. CLIENT_NOTIFICATION_FAILED
iat
Number
A Unix timestamp in seconds indicating the date and time when the JWT was issued.
exp
Number
A Unix timestamp in seconds indicating the date and time when the JWT will expire.
error_description
String
Returns human readable general information about the reason for the error.
request_type
String
Value to indicate the type of the request, value is error
.
ndi_request_id
String
A randomly generated ID that can be used to correlate requests between Singpass and DSAP. This ID is unique per user request.
Singpass will retry on any connection errors, client timeout and the following http response codes returned from the DSAP webhook endpoint:
502 - BAD_GATEWAY
503 - SERVICE_UNAVAILABLE
504 - GATEWAY_TIMEOUT
Singpass is using the following configuration for retry strategy:
The DSAP webhook API must follow RESTful conventions and communicate errors by returning a proper error response and with a corresponding HTTP status code, following the structure indicated below. All fields are mandatory.
id
String
A randomly generated ID that can be used to correlate requests between Singpass and DSAP. This ID is unique per user request.
error
String
error_description
String
Returns human readable general information about the reason for the error.
SIGN_REF_NOT_FOUND
400
To be returned if the sign ref in the request is unknown or expired.
INVALID_REQUEST
400
A catch all indicating an invalid request parameter from DSS. Eg. invalid client notification token, invalid user cert, invalid doc hash signature, etc.
SERVER_ERROR
5XX
A catch all for any other errors that occurred in the DSAP.
DSAPs are expected to verify the validity of the user’s certificate status against National Certificate Authority (NCA).
DSAPs shall not send unknown OCSP requests (e.g. unknown OCSP certificate serial number or unknown CA Hash name).
Cryptographic algorithms: DSAP shall ensure that the default cryptographic algorithms used in its systems and during the Digital Signing Process are as follows:
Digital Signature Algorithms: ECDSA (key size with 256 bits or more);
ECC Curves: NIST P-256, P-384, P-521;
Hash Algorithms: SHA-2 (256/384/512).
The document hash should be SHA256 hashed and hex-encoded before sending to Singpass.
The document hash is locally signed by the user’s digital identity, verified by Singpass and then sent to the DSAP.
DSAPs should follow the UX Guide provided in the developer package given during onboarding when displaying the QR code and/or challenge code to the users on their webpage.
To support mobile users, DSAPs are also required to render the QR code with the mobile app links (deep links) following the format below.
For production:
Android
intent://app.singpass.gov.sg/docsign?sign_ref=<sign-ref>#Intent;scheme=https;package=sg.ndi.sp;S.browser_fallback_url=https://app.singpass.gov.sg/docsign;end
iOS
https://app.singpass.gov.sg/docsign?sign_ref=<sign-ref>
For staging:
Android
intent://stg-app.singpass.gov.sg/docsign?sign_ref=<sign-ref>#Intent;scheme=https;package=sg.ndi.sp.dev;S.browser_fallback_url=https://stg-app.singpass.gov.sg/docsign;end
iOS
https://stg-app.singpass.gov.sg/docsign?sign_ref=<sign-ref>
The new staging domain stg-app.singpass.gov.sg
will only take effect from 18 Mar 2025. In the meantime, RP must use app.singpass.gov.sg
for both staging and production.
Question: Are DSAPs allowed to cache an end-user’s public X.509 Certificate beyond the TTL of a signing-session (sign_ref
) to cater for better user experience?
Introduction of anism
Update to to support new staging app
Update to
Updated to indicate that ; onboarding for v1 no longer supported
JWT
JWT
The webhook server must be configured to present the full certificate chain to Singpass when Singpass invokes the notification webhook endpoints. This can be verified using a tool like . Please note that your cert should not be a self-signed certificate.
This is deprecated in favour of
For all DSS APIs, DSAPs will need to authenticate themselves using their base64-encoded client_id
and client_secret
via the scheme in the following format:
A document signing session is only valid for a short amount of time. The expiry of a signing session can be found via the expires_at
response field. When a sign session expires, Singpass will delete it from storage and calls to will result in a SIGN_REF_NOT_FOUND
error. Also, any attempts to scan a doc signing QR code or sign a doc hash will fail.
Please refer to
The DSAP must invoke this API only after it has received the user’s digital signing certificate through its notification webhook endpoint. See Steps 6, 7 and 8 of the for more details about what DSAPs need to do before invoking this endpoint.
The hash of the document to be signed by the user. Refer to for more details.
For other errors, please refer to
Integrating parties can verify the signature of a JWT from Singpass by acquiring the signing public key from this endpoint. More information about a JSON Web Key (JWK) endpoint can be found .
Public keys returned from this endpoint could be in random sequence or rotated for security enhancement. For more information, please refer to
It should expect a in the request body.
It should authenticate incoming calls using the , accepting only the client_notification_token
given to Singpass during session initialisation.
For non-repudiation purposes, Singpass will sign all JWTs sent to DSAPs webhook with its signing key. DSAPs can retrieve the corresponding public keys for verification from
The hash of the document to be signed by the user. Refer to for more details.
The signature of the document hash, signed by the user. Refer to for more details.
Error code representing an error. Must be one of the values from the list of
Singpass will retry on 502, 503 and 504. Refer to
DSAPs must use to do the status verification against NCA. The OCSP response must be embedded in the signed document.
The size is large so we do not recommend using to verify the cert status to avoid large signed document file sizes.
DSAPs are expected to use the received user cert and generate a document hash that can later be digitally signed (locally) to form a compliant signature.
The signature follows the and will be hex-encoded.
DSAPs are expected to then generate a compliant signature using this.
Question: Since the webhook is defined as asynchronous and non-blocking, are there any constraints on when a DSAP should invoke the ?
Answer: Yes. The agreed average response time between the start of the webhook and the invocation of the hash endpoint must be 8 seconds. This 8-second interval correlates to the period that an end-user has to wait after scanning the QR (till he/she receives a "Signing Challenge"). While waiting for the "Signing Challenge" (which is provided by a DSAP), the end-user will encounter a loading/ spinner screen.
Answer: Although it is technically possible for DSAPs to cache an end-user’s public certificate beyond the TTL of a signing-session (sign_ref
), Singpass does not condone such a practice as it infringes Data Protection Policies. i.e. Lack of end-user’s consent in providing his/her personal information to a third-party site/application ().
The will proceed to reject any requests of such nature if an invalid signing-reference ID (sign_ref
) is provided. Repeated attempts to guess a signing-reference ID (sign_ref) will be logged and recognised by Singpass as a malicious security event.