| Use case | Example |
|---|---|
| Remote customer onboarding (KYC) | A bank, microfinance or insurance company opens an account online without a branch visit. |
| Identity confirmation before a sensitive action | Confirming the account owner before a large transfer, a password reset or changing a phone number. |
| Online contract signing | Making sure the person signing a loan or rental agreement is the actual citizen. |
| Age / identity checks | Marketplaces, telecom, gaming or delivery services that must verify age or a real identity. |
| Pre-filled registration | The user only takes a selfie; your form is filled with verified name, document and birth date. |
| Term | Who it is |
|---|---|
| Client | The company integrating RS-ID (you). Registered in RS-ID and issued a client_id / client_secret. Includes the client backend (calls the RS-ID API) and the client frontend (your website that sends the user to the RS-ID page). |
| User | The end person being identified — your customer, a citizen of Uzbekistan. |
| Server | The RS-ID server: the Web SDK API and the RS-ID page (<rsid_base_url>) where the user takes the selfie. |
| Session | One identification attempt created by the client backend. Identified by session_id (UUID). Has a limited lifetime and a limited number of attempts. |
| PINFL | Personal identification number of an individual — 14 digits. |
Document number (id_number) | Passport or ID card series and number, e.g. AA1234567. |
redirect_url.<iframe> on its own page, so the user never leaves your site.allow="camera" is mandatory — without it the browser blocks the camera inside the iframe.redirect_url. Point redirect_url to a small page on your own domain that notifies the parent window, for example:| Environment | API base URL | RS-ID page |
|---|---|---|
| Stage (testing) | https://sdk.stage.rsid.uz/web/api | https://sdk.stage.rsid.uz/?session_id={session_id} |
| Production | https://sdk.rsid.uz/web/api | https://sdk.rsid.uz/?session_id={session_id} |
client_id / client_secret. A session created on stage opens only on the stage page, and vice versa.{ "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 |
Accept-Language | uz / ru / en | Optional — language of message |
Security. client_secretandaccess_tokenmust stay on the client backend. Never send them to the browser. The client frontend only needs thesession_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 | 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"
}POST {base_url}/v1/auth/refresh?token={refresh_token} with the required params. Reuse the token until it expires instead of signing in for every session.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. |
client_id | string | Yes | Non-empty | Client identifier issued by RS-ID. |
| Field | Type | Description |
|---|---|---|
data.access_token | string (JWT) | New 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. |
code | integer | 0 on success. |
message | string | Result text. |
{
"data": {
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "read write"
},
"code": 0,
"message": "Success"
}ip_address of user. It provides the session works only user's current device only once.POST{base_url}/v1/sessionsBearer {access_token}application/json| Field | Type | Required | Length / format | Description |
|---|---|---|---|---|
client_type | string (enum) | Yes | WEB | Integration channel. Always WEB for Web SDK. |
ip_address | string | Yes | IPv4 / IPv6 | The user's public IP address (take it from the user's request to your backend). The RS-ID page only works from this IP — see note below. |
user_info | object | No | — | Citizen data. Send it to create a session with user_info; omit it for a session without user_info. |
user_info.pinfl | string | Conditional | Exactly 14 digits | PINFL. Send either pinfl or id_number, not both. |
user_info.id_number | string | Conditional | 9 chars: 2 letters + 7 digits, e.g. AA1234567 | Passport / ID card number. Send either pinfl or id_number, not both. |
user_info.birth_date | string | Yes, if user_info is sent | dd.MM.yyyy | Date of birth. User must be at least 16 years old. |
external_id | string | No | — | Your own reference (order, application or customer id) to link the session to your records. Recommended random uuid |
retry_count | integer | No | > 0 | Maximum number of attempts. If omitted, 0 or above the system maximum, the system maximum is used. |
threshold | number | No | 0.0 – 1.0 | Minimum face-similarity score to pass. If omitted, the system default is used. |
locale | string (enum) | No | UZ, RU, EN | Default UZ. |
additional_params | object | No | Only the keys below | Settings for the RS-ID page. Any other key is rejected. |
additional_params.redirect_url | string | Recommended | URL | Where the user is sent after successful identification (see 7.5). |
additional_params.lang | string | No | uz, ru, en | Language of the RS-ID page. |
additional_params.theme | string | No | e.g. light, dark | RS-ID page theme. |
additional_params.primary_color | string | No | Hex color, e.g. #1A73E8 | Accent color of the RS-ID page. |
Threshold. thresholdis the minimum face-similarity score (from0.0to1.0) the selfie must reach against the passport photo for identification to pass. If you don't send it, the default0.5is used. If you do send it, we recommend a value above0.5. For high-quality (strict) identification, send a value above0.7. A higher value is stricter and lowers the risk of a wrong person passing, but genuine users may need more attempts.
IP binding. The session is locked to ip_address. When the user opens the RS-ID page, RS-ID compares the user's IP with this value. If they differ, the page shows an error (-1028). Pass the real public IP of the user, not your server's IP.
| Field | Type | Length / format | Description |
|---|---|---|---|
data | string | UUID, 36 chars | session_id. Use it to open the RS-ID page and to get the result. |
code | integer | 0 on success. | |
message | string | Result text. |
{
"data": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"code": 0,
"message": "Success"
}| Code | Reason |
|---|---|
-1000 | Invalid request — e.g. both or neither of pinfl / id_number in user_info. |
-1002 | Credentials do not belong to a Web SDK client. |
-1024 | Invalid id_number format. |
-1025 | Invalid pinfl format. |
-1026 | birth_date is missing. |
-1034 | Unknown key in additional_params. |
-1052 | threshold outside 0–1. |
-1090 | User is younger than 16. |
400 | Field validation error, e.g. ip address cannot be blank. |
session_id, the client frontend opens the RS-ID page — by redirect (3.1) or in an iFrame (3.2):| Environment | URL |
|---|---|
| Stage | https://sdk.stage.rsid.uz/?session_id={session_id} |
| Production | https://sdk.rsid.uz/?session_id={session_id} |
| Page mode | Shown when | What the user does |
|---|---|---|
| with_info | Session created without user_info (Option 2) | Enters their data, then takes a selfie |
| without_info | Session created with user_info (Option 1) | Only takes a selfie |
dd.mm.yyyy), then taps Next (Далее).redirect_url (7.6).redirect_url (7.6).retry_count). When attempts run out or the session expires, the page shows an error and the client must create a new session.additional_params.redirect_url from the create-session request.redirect_url; use it to notify the parent page (see 3.2).redirect_url (for example ?order=ORDER-123) so you know which session finished. Then the client backend fetches the result (7.6).Do not treat the redirect alone as proof of identification — anyone can open that URL. Always confirm the result from your backend with 7.6.
GET{base_url}/v1/user/{session_id}Bearer {access_token}| Field | Type | Required | Length / format | Description |
|---|---|---|---|---|
session_id | string | Yes | UUID, 36 chars | From 7.2. |
| Field | Type | Description |
|---|---|---|
data.session_id | string | Session id. |
data.comparison_value | number | Face similarity score, 0–1. |
data.note | string | Failure note, if any. |
data.profile.user_info.first_name | string | First name. |
data.profile.user_info.last_name | string | Last name. |
data.profile.user_info.middle_name | string | Patronymic. |
data.profile.user_info.pinfl | string | PINFL, 14 digits. |
data.profile.user_info.gender | string | Gender. |
data.profile.user_info.birth_date | string | yyyy-MM-dd. |
data.profile.user_info.birth_place | string | Place of birth. |
data.profile.user_info.birth_country | string | Country of birth. |
data.profile.user_info.nationality | string | Nationality. |
data.profile.user_info.citizenship | string | Citizenship. |
data.profile.document_info.document | string | Document series and number. |
data.profile.document_info.type | string | Document type. |
data.profile.document_info.issued_by | string | Issuing authority. |
data.profile.document_info.issued_at | string | Issue date, yyyy-MM-dd. |
data.profile.document_info.expiry_at | string | Expiry date, yyyy-MM-dd. |
data.profile.permanent_address | object | country, country_id, region_id, district_id, address. |
data.profile.temporary_address | object | May be null. |
{
"data": {
"session_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"comparison_value": 0.93,
"profile": {
"user_info": {
"first_name": "ALISHER",
"last_name": "KARIMOV",
"middle_name": "BAXTIYOROVICH",
"pinfl": "12345678901234",
"gender": "MALE",
"birth_date": "1990-01-01",
"birth_place": "TOSHKENT",
"birth_country": "UZBEKISTAN",
"nationality": "UZBEK",
"citizenship": "UZBEKISTAN"
},
"document_info": {
"document": "AA1234567",
"type": "PASSPORT",
"issued_by": "IIV 26283",
"issued_at": "2018-05-10",
"expiry_at": "2028-05-09"
},
"contact_info": {},
"permanent_address": {
"country": "UZBEKISTAN",
"country_id": 182,
"region_id": 26,
"district_id": 2603,
"address": "..."
},
"temporary_address": null
}
},
"code": 0,
"message": "Success"
}| Code | Reason |
|---|---|
-1005 | Identification was not successful. |
-1027 | Session expired — fetch the result right after the redirect. |
-1029 | Session not found. |
-1002 | Session belongs to another client. |
| 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 allowed for this client. |
-1005 | UNSUCCESS_JOB | Identification not successful. |
-1008 | IDENTIFICATION_FAILED | Face did not match. |
-1024 | INVALID_ID_NUMBER | Invalid document number. |
-1025 | INVALID_PINFL | Invalid PINFL. |
-1026 | BIRTH_DATE_NOT_NULL | Birth date required. |
-1027 | SESSION_EXPIRED | Session expired. |
-1028 | IP_RESTRICTED_FOR_SESSION | User's IP differs from session ip_address. |
-1029 | JOB_SESSION_NOT_FOUND | Session not found. |
-1031 | RETRY_COUNT_EXPIRED | No attempts left. |
-1032 | SUCCESS_JOB_EXISTS_FOR_SESSION | Session already identified. |
-1033 | SPOOFED_FILE_DETECTED | Liveness check failed. |
-1034 | ADDITIONAL_PARAMS_INVALID | Unknown additional_params key. |
-1052 | INVALID_THRESHOLD_LIMIT | threshold outside 0–1. |
-1090 | USER_AGE_OLDER_THAN_16 | User must be at least 16. |
-2001 | AI_ERROR | Face service error. |