callback_url, and marks the QR token as completed.| Use case | Example |
|---|---|
| Document signing | A user signs a loan, rental or service contract shown on your site. |
| Approval by several signers | A document must be signed by specific people or companies (by PINFL or TIN); the QR is completed when all of them have signed. |
| Sign-in with digital signature | Your site puts a one-time random challenge into sign_content; the user signs it, and you sign the user in after verifying the signature. |
| Confirming an operation | Signing a payment order or an application before it is processed. |
| Term | Who / what it is |
|---|---|
| Client | The company integrating RS-ID (you). Registered in RS-ID as a Web SDK client and issued a client_id / client_secret. Includes the client backend and the client frontend. |
| User | The person who signs — has the RS-ID mobile app with a digital signature added. |
| RS-ID mobile app | The RS-ID app on the user's phone. Stores the user's digital signatures and signs content. |
| Server | The RS-ID server: creates QR tokens, validates signatures and sends callbacks. |
| QR token | One signing request, identified by qr_id. Has a lifetime (expire_time) and a status. |
| RS-IMZO / E-IMZO | Types of digital signature (sign_method). |
| Signer | A person or company allowed to sign, identified by PINFL (14 digits, individual) or TIN (9 digits, company). |
| PKCS#7 | The standard format of the signed data (CMS) that RS-ID sends to your callback_url. |
callback_url (7.5).COMPLETED or EXPIRED.| Environment | API base URL | QR link (inside the QR code) |
|---|---|---|
| Stage (testing) | https://sdk.stage.rsid.uz/web/api | https://auth.stage.rsid.uz/{qr_id} |
| Production | https://sdk.rsid.uz/web/api | https://auth.rsid.uz/{qr_id} |
client_id / client_secret. A QR code created on stage can be scanned only with the stage RS-ID app.{ "data": { }, "code": 0, "message": "Success" }| Field | Type | Description |
|---|---|---|
code | integer | 0 — success. Any other value is an error (see the error tables). Always check code, not only the HTTP status. |
message | string | Human-readable text in the request language (uz / ru / en). Do not parse it. |
data | any | Response payload. Absent on errors. |
| Header | Value | Used in |
|---|---|---|
Content-Type | application/json | All POST requests |
Authorization | Bearer {access_token} | All requests except sign-in and refresh |
Accept-Language | uz / ru / en | Optional — language of message |
client_secret and access_token stay on your backend. The frontend only needs the QR image or link.sign_content, and that the certificate belongs to the expected person (PINFL / TIN).callback_url and match the callback to your record by external_id.POST{base_url}/v1/auth/sign-in — no Authorization headerapplication/json| Field | Type | Required | Length / format | Description |
|---|---|---|---|---|
client_id | string | Yes | Non-empty; must not start with a digit | Web SDK client identifier issued by RS-ID. |
client_secret | string | Yes | Non-empty | Client secret issued by RS-ID. |
{
"client_id": "web-sdk-client",
"client_secret": "s3cr3t-value"
}| Field | Type | Description |
|---|---|---|
data.access_token | string (JWT) | Token for the Authorization: Bearer header. |
data.token_type | string | Always Bearer. |
data.expires_in | integer | Token lifetime in seconds. |
data.scope | string | Granted scopes, space-separated. |
data.refresh_token | string (JWT) | Token to get a new access_token without sending credentials again. |
code | integer | 0 on success. |
message | string | Result text. |
{
"data": {
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "read write",
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
},
"code": 0,
"message": "Success"
}access_token until it expires instead of signing in for every request.access_token with the refresh_token, without sending a new sign-in. Call it when the access_token has expired (after expires_in seconds).POST{base_url}/v1/auth/refresh?token={refresh_token} — no Authorization header.application/json| Field | Type | Required | Length / format | Description |
|---|---|---|---|---|
token | string | Yes | JWT | refresh_token from the sign-in (7.1) or a previous refresh response. |
| Field | Type | Required | Length / format | Description |
|---|---|---|---|---|
client_id | string | Yes | Non-empty; must not start with a digit | Web SDK client identifier issued by RS-ID. |
client_secret | string | Yes | Non-empty | Client secret issued by RS-ID. |
{
"client_id": "web-sdk-client",
"client_secret": "s3cr3t-value"
}POST{base_url}/v1/qrBearer {access_token}application/json| Field | Type | Required | Length / format | Description |
|---|---|---|---|---|
sign_content | string | Yes | Non-empty | The content the user signs. It is shown to the user in the RS-ID app. |
expire_time | integer | Yes | > 0, seconds | QR token lifetime in seconds, e.g. 300 (5 minutes). |
sign_method | string (enum) | No | RS_IMZO, E_IMZO | Allowed signature type. If omitted, the user can sign with any of their signatures. |
signers | array | No | — | Who is allowed to sign. If omitted, any user can sign once. If set, each listed signer signs once, and the QR is completed when all have signed. |
signers[].signer | string | Yes, if signers is sent | PINFL (14 digits) or TIN (9 digits) | The person or company allowed to sign. |
signers[].allow_id | string | No | — | Additional identifier of the signer, stored with the signature. |
external_id | string | No | Unique per client | Your own reference (document or order id). Lets you check the status by your id (7.7). Must be unique — a repeat returns -1080. |
callback_event | object | No | — | Callback settings. |
callback_event.callback_url | string | Recommended | HTTPS URL | Where RS-ID sends the signed data after each signature (7.5). |
redirect_url | string | No | URL | Link returned to the RS-ID app after signing. |
document_provider_type | string (enum) | No | HUJJAT_UZ, DIDOX | Document provider, if the document comes from one. |
qr_response_type | string (enum) | No | BASE64, DATA, ALL | What to return. Default BASE64. BASE64 — PNG image; DATA — the link inside the QR; ALL — both. |
width | integer | No | px | QR image width. Default 100. |
height | integer | No | px | QR image height. Default 100. |
| Field | Type | Description |
|---|---|---|
data.qr_id | string | QR token id. Use it in 7.6. |
data.qr_base64 | string | QR code as a PNG image in base64. Returned for BASE64 and ALL. |
data.qr_data | string | The link inside the QR code (https://auth.rsid.uz/{qr_id}). Returned for DATA and ALL. |
data.expire_at | string | Expiry time, yyyy-MM-dd HH:mm:ss. |
data.qr_status | string | ACTIVE for a new token. |
code | integer | 0 on success. |
message | string | Result text. |
{
"data": {
"qr_id": "9b2e6c1a-4f7d-4a3b-8e5c-1d2f3a4b5c6d",
"qr_data": "https://auth.rsid.uz/9b2e6c1a-4f7d-4a3b-8e5c-1d2f3a4b5c6d",
"qr_base64": "iVBORw0KGgoAAAANSUhEUgAAAQAAAAEAAQMAAABmvDolAAAABlBMVEX///8AAABVwtN+...",
"expire_at": "2026-11-09 17:35:00",
"qr_status": "ACTIVE"
},
"code": 0,
"message": "Success"
}<img src="data:image/png;base64,{qr_base64}">, or draw your own QR from qr_data.| Code | Reason |
|---|---|
-1002 | Credentials do not belong to a Web SDK client. |
-1080 | A QR token with this external_id already exists. |
-5 | Token user not found. |
400 | Validation error, e.g. sign content cannot be blank or expire_time missing / not positive. |
sign_content).sign_method keys are shown, if set). If signers are set, only signatures with an allowed PINFL / TIN can be used.| Situation | Result |
|---|---|
| The QR token expired | QR token expired — create a new QR token. |
| The QR token is already completed | QR token completed. |
The signature's PINFL / TIN is not in signers | The user is not allowed to sign. |
| This signer has already signed | The document is already signed with this signature. |
| All signers have already signed | The document is fully signed. |
POST request to callback_event.callback_url.POSTcallback_urlapplication/json| Field | Type | Description |
|---|---|---|
sign_request_data | string | The JSON of your original create request (7.3), as a string. Use its external_id to find your record. |
pkcs7 | string | The signed data, PKCS#7 (CMS) in base64. Contains the signed content, the signature and the signer's certificate. |
{
"sign_request_data": "{\"signers\":null,\"expire_time\":300,\"sign_method\":\"RS_IMZO\",\"sign_content\":\"Contract No. A-7781 dated 09.11.2026. I agree to the terms of the service agreement.\",\"redirect_url\":null,\"external_id\":\"CONTRACT-A-7781\",\"document_provider_type\":null,\"callback_event\":{\"callback_url\":\"https://shop.example.uz/webhooks/rsid/sign\"},\"qr_response_type\":\"ALL\",\"width\":256,\"height\":256}",
"pkcs7": "MIIKvgYJKoZIhvcNAQcCoIIKrzCCCqsCAQExDjAMBggqhlADAgIBAQUAMIIBDgYJKoZIhvcNAQcBoIIA..."
}200. The callback is sent once and is not retried, so also check the status with 7.6 / 7.7.With several signers, a callback is sent for each signature.
qr_idGET{base_url}/v1/qr/{qr_id}Bearer {access_token}| Field | Type | Required | Length / format | Description |
|---|---|---|---|---|
qr_id | string | Yes | UUID | From 7.3. |
| Field | Type | Description |
|---|---|---|
data.qr_id | string | QR token id. |
data.qr_status | string | ACTIVE — waiting for signature; COMPLETED — signed (by all signers, if set); EXPIRED — lifetime passed; DELETED — removed. |
data.expire_at | string | Expiry time, yyyy-MM-dd HH:mm:ss. |
data.qr_data | string | Link inside the QR code. |
data.qr_base64 | string | QR image (100×100 PNG, base64) — to show it again. |
{
"data": {
"qr_id": "9b2e6c1a-4f7d-4a3b-8e5c-1d2f3a4b5c6d",
"qr_data": "https://auth.rsid.uz/9b2e6c1a-4f7d-4a3b-8e5c-1d2f3a4b5c6d",
"qr_base64": "iVBORw0KGgoAAAANSUhEUgAAAGQAAABkAQMAAABKLAcXAAAABlBMVEX///8AAABVwtN+...",
"expire_at": "2026-11-09 17:35:00",
"qr_status": "COMPLETED"
},
"code": 0,
"message": "Success"
}qr_status is ACTIVE.| Code | Reason |
|---|---|
-1035 | QR token not found, or it belongs to another client. |
-1002 | Credentials do not belong to a Web SDK client. |
external_idexternal_id from 7.3.GET{base_url}/v1/qr/status/by-external/{external_id}Bearer {access_token}| Field | Type | Required | Length / format | Description |
|---|---|---|---|---|
external_id | string | Yes | — | external_id from 7.3. |
| Code | Name | Meaning |
|---|---|---|
0 | SUCCESS | Success. |
-5 | BAD_CREDENTIALS | Invalid credentials or token user not found. |
-9 | SYSTEM_ERROR | Unexpected server error. |
-1000 | BAD_REQUEST | Invalid request. |
-1002 | CLIENT_NOT_PERMITTED | Not a Web SDK client. |
-1035 | INVALID_QR_TOKEN | QR token not found or belongs to another client. |
-1080 | QR_TOKEN_EXISTS_BY_EXTERNAL_ID | A QR token with this external_id already exists. |