Skip to main content
Search

API 2: Submit Address Proof

Where should I integrate

Description

After receiving the challengeMsg from API 1, your VASP must build the proofPayload, sign it with the corresponding private key, and submit both the payload and signature to GTR.

GTR will verify:

  1. the request is authenticated
  2. the address is not already ownership-proved
  3. the challengeMsg matches the expected value
  4. the signature is valid for the submitted payload

If the verification succeeds, GTR records the address as an ownership-proved address.

For further details of this API, use the following endpoint:

POST $BASE_URL/ext/api/cosmos/v1/address/proof/submit

Step 1: Build the Proof Payload

Your proofPayload must use the following exact format:

PublicKey:{publicKey};PublicKeyType:{publicKeyType};WalletAddress:{walletAddress};Vendor:gtr;ChallengeMsg:{challengeMsg};ProofAlgo:{proofAlgo};UserNonce:{userNonce};PublicKeyFormat:{publicKeyFormat};

Field Rules

FieldDescription
PublicKeyThe same Base64 public key you used in the Generate Challenge request
PublicKeyTypeThe same publicKeyType you used in the Generate Challenge request
WalletAddressThe target wallet address
VendorMust be the fixed value gtr
ChallengeMsgThe challengeMsg returned from API 1
ProofAlgoThe same proofAlgo you used in API 1
UserNonceThe same userNonce you used in API 1
PublicKeyFormatThe same publicKeyFormat you used in API 1. If omitted in API 1, use PEM

⚠️ The field order and separators should remain unchanged.

GTR parses this string by field name and semicolon separators.

Step 2: Sign the Proof Payload

Use the private key corresponding to PublicKey to sign the full proofPayload string.

Then Base64-encode the resulting signature and send it as base64SignedMessage.

Step 3: Submit Request

curl --silent --location --request POST "$BASE_URL/ext/api/cosmos/v1/address/proof/submit" \
--header 'Content-Type: application/json' \
--header 'X-Authorization: [YOUR_ADDRESS_PROVING_TOKEN]' \
--data-raw '{
"proofPayload": "PublicKey:[BASE64_PUBLIC_KEY];PublicKeyType:[PUBLIC_KEY_TYPE];WalletAddress:[WALLET_ADDRESS];Vendor:gtr;ChallengeMsg:[CHALLENGE_MSG];ProofAlgo:[PROOF_ALGORITHM];UserNonce:[YOUR_RANDOM_NONCE];PublicKeyFormat:[PEM_OR_DER];",
"base64SignedMessage": "[BASE64_SIGNATURE]"
}'

Request Fields

FieldRequiredDescription
proofPayloadYesThe exact payload string that contains the proving metadata
base64SignedMessageYesBase64-encoded signature of the full proofPayload

Success Response

You can expect to receive the following response on success:

{
"verifyStatus": 100000,
"verifyMessage": "proved, thank you!",
"data": null
}

Verification Logic

Internally, GTR performs the following checks:

  1. Resolve your VASP identity from X-Authorization
  2. Parse the submitted proofPayload
  3. Check whether the wallet address already exists with ownership proof level 3 or above
  4. Recompute the expected challengeMsg from the authenticated VASP and payload fields
  5. Verify the cryptographic signature using publicKeyType, proofAlgo, publicKey, base64SignedMessage, and publicKeyFormat
  6. If verification succeeds, insert or update the address record as OWNERSHIP_PROVING

Error Handling

Authentication Errors

verifyStatusHTTP StatusverifyMessageCauseAction
100001200unauthorizedMissing or invalid X-Authorization headerCheck the token in your request

Business Errors

verifyStatusHTTP StatusverifyMessageCauseAction
100001200address already exists with proof type >= 3The address has already been ownership-provedUse another address, or contact GTR support if you believe the existing record is incorrect
100001200challenge message is not matchThe submitted ChallengeMsg does not match the expected challengeMake sure the payload fields are exactly the same as those used in API 1
100001200invalid public key: the provided base64 public key does not match the expected format for key type '[TYPE]'The public key content does not match the declared publicKeyType or publicKeyFormatVerify your key type, key bytes, and key encoding
100001200invalid base64 encoding in public key or signatureThe submitted public key or signature is not valid Base64Re-encode your public key and signature using standard Base64

Client Errors

verifyStatusHTTP StatusverifyMessageCauseAction
100004400Validation error textRequired request field is missing or invalidCheck your request body
100001200missing request body, have to check all the required parameters?Request body is missingSend a valid JSON body
100001200wrong json request body format, please check if theres any additional , in the tail of key:value, the last key-value should not have , concat at the tailJSON syntax is invalidFix the JSON formatting

Server Errors

verifyStatusHTTP StatusverifyMessageCauseAction
100006500Internal Server Error, Please contact to GTR official service, Support Id: [SUPPORT_ID]Unsupported publicKeyType, unsupported proofAlgo, invalid format combination, or another unexpected internal exceptionVerify your request values are within the supported list. If the problem continues, contact GTR support with the supportId

Important Notes

  • If your request uses unsupported publicKeyType or proofAlgo values, the current server implementation may return a server-side error instead of a business validation error.
  • If publicKeyFormat is omitted in the Generate Challenge step, you should use PEM when building the final proofPayload.
  • The same address cannot be repeatedly registered once its proof level is already 3 or above.
  • The values used in API 1 and API 2 should remain consistent.