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.
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]",
"phoneNumber": "62888675678910",
"dataVerification": {
"email": {
"isVerified": true,
"verificationReferenceId": "5fb51cca-6d64-49bb-a67a-f3ceaad1a913"
},
"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 addressmetadata.userDetails.phoneNumber— Phone in international format (e.g.,628xxx)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 about 4 hours ago