Integration Guide - Certificate Registration
This guide walks you through every step required to submit a Certificate Registration request using the Esign APIs. Follow the steps in order; each step depends on the output of the previous one.
Prerequisites
Before you begin, ensure you have:
client-idandpass-keycredentials from the GoTo OneKYC team- Your assigned
x-esign-onboarding-partneridentifier (e.g.CLIENT_X-BE-CERT_REG) - HTTPS-capable server that can reach the Esign API base URLs
- A callback endpoint that can receive
POSTrequests from the Esign platform (see Handling Submission Results)
Common Request Headers
The following headers are required on every Esign API call (except authentication):
| Header | Description | Example |
|---|---|---|
x-onekyc-token | Partner token from Get Partner Token API | eyJraWQiOiJlY... |
x-esign-onboarding-partner | Identifies your integration (provided by OneKYC team) | CLIENT_X-BE-CERT_REG |
x-partner-user-id | Your internal user identifier for the current user | user-12345 |
x-partner-user-id-type | The type/label of your user ID | CLIENT_X_USER_ID |
x-partner-session-id | A unique ID for this specific invocation (use a new UUID per call) | session-abc-001 |
Step 1 — Get an Authentication Token
Generate a partner token that will authenticate all subsequent API calls.
For detailed instructions, request/response examples, and token caching strategies, see Getting Authentication Token.
You will pass this token as x-onekyc-token in all subsequent steps.
Step 2 — Get Presigned Upload URLs
API Reference: Get Presigned URLs
Initiate a new Certificate Registration submission and receive pre-signed URLs for uploading the user's KTP and selfie images.
Endpoint
GET /esign-partner/v1/submissions/urls?submissionType=CERT_REG
Base URL: https://onekyc.ky.id.staging.gopayapi.com (staging)
Request
curl -X GET \
"https://onekyc.ky.id.staging.gopayapi.com/esign-partner/v1/submissions/urls?submissionType=CERT_REG" \
-H "x-onekyc-token: <TOKEN>" \
-H "x-esign-onboarding-partner: CLIENT_X-BE-CERT_REG" \
-H "x-partner-user-id: user-12345" \
-H "x-partner-user-id-type: CLIENT_X_USER_ID" \
-H "x-partner-session-id: session-abc-001"Query Parameters
| Parameter | Type | Required | Value |
|---|---|---|---|
submissionType | string | ✅ | Must be CERT_REG for Certificate Registration |
Success Response — 200 OK
200 OK{
"success": true,
"data": {
"submissionId": "8a0aef3d-0e27-4a7e-a4ba-2e1b97bcb00c",
"status": "INITIATED",
"documents": {
"KTP": {
"documentUrl": "https://al-ky-id-s-esign-service.oss-ap-southeast-5.aliyuncs.com/CERT_REG/93134121-bc15-4796-a911-9257913f0020_KTP?...",
"documentReference": "93134121-bc15-4796-a911-9257913f0020_KTP",
"expiryInSeconds": "432000"
},
"SELFIE": {
"documentUrl": "https://al-ky-id-s-esign-service.oss-ap-southeast-5.aliyuncs.com/CERT_REG/5e021eb4-d875-47bb-817b-8b1782f0c3bb_SELFIE?...",
"documentReference": "5e021eb4-d875-47bb-817b-8b1782f0c3bb_SELFIE",
"expiryInSeconds": "432000"
}
}
}
}| Field | Description |
|---|---|
submissionId | Unique ID for this submission — save this, you'll need it in Steps 4 and 6 |
status | Will be INITIATED at this stage |
documents.KTP.documentUrl | Presigned URL to upload the KTP image |
documents.SELFIE.documentUrl | Presigned URL to upload the selfie image |
expiryInSeconds | Time (in seconds) before the presigned URL expires — 432000 = 5 days |
Important: Save the
submissionIdand bothdocumentUrlvalues before proceeding.
Step 3 — Upload KTP and Selfie Images
Upload the user's images directly to the pre-signed URLs received in Step 2. These are direct object storage uploads — do not call a platform API here, just PUT the file bytes to the URL.
Upload KTP
curl -X PUT "<KTP_DOCUMENT_URL>" \
-H "Content-Type: image/jpeg" \
--data-binary @/path/to/ktp-image.jpgUpload Selfie
curl -X PUT "<SELFIE_DOCUMENT_URL>" \
-H "Content-Type: image/jpeg" \
--data-binary @/path/to/selfie-image.jpgImage Requirements
| Document | Format | Notes |
|---|---|---|
| KTP | JPEG / PNG | Must be a clear photo of the user's physical eKTP card |
| Selfie | JPEG / PNG | Clear frontal photo of the user's face |
Both uploads must succeed before proceeding to Step 4. A
200or204HTTP response from the presigned URL indicates a successful upload.
Step 4 — Confirm Upload
API Reference: Confirm Upload
Once both images are uploaded, call the Confirm Upload API to provide the user's personal details and trigger asynchronous processing.
At least one of user's addressable contact is required to issue a certificate, it can be either email, phoneNumber or both.
And in the case of Partial RA integration, whichever addressable contact provided to us has to already be verified by you.
Endpoint
PUT /esign-partner/v1/submissions/urls
Request
curl -X PUT \
"https://onekyc.ky.id.staging.gopayapi.com/esign-partner/v1/submissions/urls" \
-H "x-onekyc-token: <TOKEN>" \
-H "x-esign-onboarding-partner: CLIENT_X-BE-CERT_REG" \
-H "x-partner-user-id: user-12345" \
-H "x-partner-user-id-type: CLIENT_X_USER_ID" \
-H "x-partner-session-id: session-abc-002" \
-H "Content-Type: application/json" \
-d '{
"submissionId": "8a0aef3d-0e27-4a7e-a4ba-2e1b97bcb00c",
"metadata": {
"userDetails": {
"name": "John Doe",
"nik": 3187888902845410,
"dateOfBirth": "07-03-1980",
"email": "[email protected]",
"dataVerification": {
"email": {
"isVerified": true,
"verificationReferenceId": "5fb51cca-6d64-49bb-a67a-f3ceaad1a913"
}
}
},
"userLocale": "en_ID",
"consentData": [
{
"entity": "Digi",
"consentType": "termsAndConditions",
"consentGiven": true,
"details": {
"en_ID": {
"url": "https://www.digi.com/termsAndConditions?version=v1.0.0",
"text": "terms and conditions"
},
"id_ID": {
"url": "https://www.digi.com/termsAndConditions?version=v1.0.0",
"text": "terms and conditions"
}
},
"timeStamp": 1725603017,
"additionalDetails": {
"userAgent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36",
"userIp": "172.217.22.14",
"deviceDetails": {
"os": "R",
"make": "google",
"model": "KB2001",
"uniqueId": "AF7KI0bly3aPIsYJ4+O+2QE",
"networkProvider": "XL Axiata",
"appId": "gojek",
"appVersion": "4.96.0"
}
}
}
],
"additionalData": {}
}
}'curl -X PUT \
"https://onekyc.ky.id.staging.gopayapi.com/esign-partner/v1/submissions/urls" \
-H "x-onekyc-token: <TOKEN>" \
-H "x-esign-onboarding-partner: CLIENT_X-BE-CERT_REG" \
-H "x-partner-user-id: user-12345" \
-H "x-partner-user-id-type: CLIENT_X_USER_ID" \
-H "x-partner-session-id: session-abc-002" \
-H "Content-Type: application/json" \
-d '{
"submissionId": "8a0aef3d-0e27-4a7e-a4ba-2e1b97bcb00c",
"metadata": {
"userDetails": {
"name": "John Doe",
"nik": 3187888902845410,
"dateOfBirth": "07-03-1980",
"phoneNumber": "62888675678910",
"dataVerification": {
"phoneNumber": {
"isVerified": true,
"verificationReferenceId": "5fb51cca-6d64-49bb-a67a-f3ceaad1a913"
}
}
},
"userLocale": "en_ID",
"consentData": [
{
"entity": "Digi",
"consentType": "termsAndConditions",
"consentGiven": true,
"details": {
"en_ID": {
"url": "https://www.digi.com/termsAndConditions?version=v1.0.0",
"text": "terms and conditions"
},
"id_ID": {
"url": "https://www.digi.com/termsAndConditions?version=v1.0.0",
"text": "terms and conditions"
}
},
"timeStamp": 1725603017,
"additionalDetails": {
"userAgent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36",
"userIp": "172.217.22.14",
"deviceDetails": {
"os": "R",
"make": "google",
"model": "KB2001",
"uniqueId": "AF7KI0bly3aPIsYJ4+O+2QE",
"networkProvider": "XL Axiata",
"appId": "gojek",
"appVersion": "4.96.0"
}
}
}
],
"additionalData": {}
}
}'Key Request Fields
Required fields in the request body:
submissionId— The submission ID from Step 2metadata.userDetails.name— Full name (must match KTP)metadata.userDetails.nik— 16-digit National ID numbermetadata.userDetails.dateOfBirth— Format:DD-MM-YYYYmetadata.userDetails.email— User's email address (required ifphoneNumberis not available)metadata.userDetails.phoneNumber— Phone in international format e.g.,628xxx(required ifemailis not available)metadata.userDetails.dataVerification— Email and phone verification status with your reference IDsmetadata.consentData— User's consent to terms and conditions with timestamp and device details
For a complete list of all available fields and their descriptions, refer to the Confirm Upload API documentation.
Success Response — 200 OK
200 OK{
"success": true,
"data": {
"submissionId": "8a0aef3d-0e27-4a7e-a4ba-2e1b97bcb00c"
}
}After receiving this response, the submission enters asynchronous processing. You do not need to poll immediately — wait for a callback (Step 5).
Step 5 — Receive the Callback
Once the Esign platform finishes processing the submission, it sends a POST request to your registered callback endpoint with the result.
You do not need to do anything to trigger this — it happens automatically after Step 4.
See Handling Submission Results for the full callback body structure and how to interpret every outcome.
Step 6 — Poll Submission Status (Fallback)
API Reference: Get Submission Details
If a callback is not received within the expected window (e.g. due to network issues on your endpoint), you can query the submission status directly.
Endpoint
GET /esign-partner/v1/submissions
Request
curl -X GET \
"https://onekyc.ky.id.staging.gopayapi.com/esign-partner/v1/submissions" \
-H "x-onekyc-token: <TOKEN>" \
-H "x-partner-user-id: user-12345" \
-H "x-partner-user-id-type: CLIENT_X_USER_ID" \
-H "x-partner-session-id: session-abc-003"Note:
x-esign-onboarding-partneris not required for this endpoint.
Success Response — 200 OK
200 OK{
"success": true,
"data": {
"submissionId": "d208917d-84a1-4edc-98b0-af2c2f4fcf5e",
"userId": "user-12345",
"userIdType": "CLIENT_X_USER_ID",
"partnerSessionId": "session-abc-001",
"status": "COMPLETED",
"result": "VALID",
"submissionDetails": {
"verificationResult": {
"nik": "PASS",
"name": "PASS",
"dateOfBirth": "PASS",
"selfie": "PASS"
},
"registrationId": "6dab7f08-0dcb-4852-8459-59cb7c25f4dc",
"eligibleToActivate": false,
"onboardingCode": "NEW_USER",
"shouldSkipActivation": true
}
}
}For a full explanation of
status,result, andreasonCodevalues, see Handling Submission Results.
Full Integration Flow Summary
Step 1 → GET /v1/esign/partner/authentication → obtain token
Step 2 → GET /esign-partner/v1/submissions/urls → obtain submissionId + presigned URLs
Step 3 → PUT <presigned KTP URL> → upload KTP image
Step 3 → PUT <presigned Selfie URL> → upload Selfie image
Step 4 → PUT /esign-partner/v1/submissions/urls → confirm upload + provide user details
Step 5 ← POST <your callback endpoint> ← receive async result
Step 6 → GET /esign-partner/v1/submissions → (fallback) poll for resultUpdated 20 days ago