Request a signing code
curl --request POST \
--url https://sandbox.api.nkama.ga/api/v1/documents/{id}/sign/otp \
--header 'Authorization: Bearer <token>'import requests
url = "https://sandbox.api.nkama.ga/api/v1/documents/{id}/sign/otp"
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, headers=headers)
print(response.text)const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
fetch('https://sandbox.api.nkama.ga/api/v1/documents/{id}/sign/otp', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://sandbox.api.nkama.ga/api/v1/documents/{id}/sign/otp",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://sandbox.api.nkama.ga/api/v1/documents/{id}/sign/otp"
req, _ := http.NewRequest("POST", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://sandbox.api.nkama.ga/api/v1/documents/{id}/sign/otp")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://sandbox.api.nkama.ga/api/v1/documents/{id}/sign/otp")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"challengeId": "<string>",
"channel": "WHATSAPP",
"expiresAt": "2026-04-01T09:35:00Z",
"maskedDestination": "+241••••••00",
"purpose": "PHONE_VERIFICATION"
}{
"detail": "<string>",
"instance": "<string>",
"properties": {},
"status": 123,
"title": "<string>",
"type": "<string>"
}{
"detail": "<string>",
"instance": "<string>",
"properties": {},
"status": 123,
"title": "<string>",
"type": "<string>"
}{
"detail": "<string>",
"instance": "<string>",
"properties": {},
"status": 123,
"title": "<string>",
"type": "<string>"
}{
"detail": "<string>",
"instance": "<string>",
"properties": {},
"status": 123,
"title": "<string>",
"type": "<string>"
}{
"detail": "<string>",
"instance": "<string>",
"properties": {},
"status": 123,
"title": "<string>",
"type": "<string>"
}Documents
Request a signing code
Issues a one-time code to the caller’s on-file number, authorizing them to sign this document. The number is taken from the caller’s profile, not the request. The returned challenge id and the delivered code are presented back to the sign endpoint to finalize the signature.
POST
/
api
/
v1
/
documents
/
{id}
/
sign
/
otp
Request a signing code
curl --request POST \
--url https://sandbox.api.nkama.ga/api/v1/documents/{id}/sign/otp \
--header 'Authorization: Bearer <token>'import requests
url = "https://sandbox.api.nkama.ga/api/v1/documents/{id}/sign/otp"
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, headers=headers)
print(response.text)const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
fetch('https://sandbox.api.nkama.ga/api/v1/documents/{id}/sign/otp', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://sandbox.api.nkama.ga/api/v1/documents/{id}/sign/otp",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://sandbox.api.nkama.ga/api/v1/documents/{id}/sign/otp"
req, _ := http.NewRequest("POST", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://sandbox.api.nkama.ga/api/v1/documents/{id}/sign/otp")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://sandbox.api.nkama.ga/api/v1/documents/{id}/sign/otp")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"challengeId": "<string>",
"channel": "WHATSAPP",
"expiresAt": "2026-04-01T09:35:00Z",
"maskedDestination": "+241••••••00",
"purpose": "PHONE_VERIFICATION"
}{
"detail": "<string>",
"instance": "<string>",
"properties": {},
"status": 123,
"title": "<string>",
"type": "<string>"
}{
"detail": "<string>",
"instance": "<string>",
"properties": {},
"status": 123,
"title": "<string>",
"type": "<string>"
}{
"detail": "<string>",
"instance": "<string>",
"properties": {},
"status": 123,
"title": "<string>",
"type": "<string>"
}{
"detail": "<string>",
"instance": "<string>",
"properties": {},
"status": 123,
"title": "<string>",
"type": "<string>"
}{
"detail": "<string>",
"instance": "<string>",
"properties": {},
"status": 123,
"title": "<string>",
"type": "<string>"
}Authorizations
Bearer access token (JWT) issued by Keycloak or the sandbox token endpoint.
Path Parameters
Document id
Response
A pending signing challenge
A pending signing challenge; carries no code or full destination.
Opaque challenge id presented back to sign the document
Available options:
WHATSAPP, SMS, EMAIL When the challenge expires (UTC)
Example:
"2026-04-01T09:35:00Z"
Partially-redacted destination for display
Example:
"+241••••••00"
Available options:
PHONE_VERIFICATION, REGISTRATION, DOCUMENT_SIGNATURE, PASSWORD_RESET, PHONE_CHANGE 
