VC Service Developer Guide
This guide shows you how to implement a complete verifiable credential payment flow using the VC service endpoints.
Quick Start
Want to get up and running fast? Follow this 5-minute setup:
- Enroll a user → Get their DID and keys
- Issue a credential → Authorize payments
- Sign a presentation → User consents to payment
- Make payment → Submit signed presentation
- Verify → Bank validates everything
Prerequisites
- Base URL:
https://localhost:4901/vc/v1 - Content-Type:
application/json - Authentication: Required for all endpoints (partner API key)
VC Enrollment
Enroll a User
Purpose: Create a user account with cryptographic keys for signing payments.
Endpoint: POST /enroll
Request:
curl -X POST https://localhost:4901/vc/v1/enroll \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"entityType": "user",
"name": "John Doe",
"email": "john@example.com",
"metadata": {
"department": "engineering"
}
}'
Response:
{
"success": true,
"data": {
"userDid": "did:key:z6Mk2b84e6986130ed411d0e386722b0ebb5",
"publicKey": "base64_encoded_32_byte_public_key",
"verificationMethod": "did:key:z6Mk2b84e6986130ed411d0e386722b0ebb5#key-1"
}
}
Save these values - you'll need them for the next steps:
userDid→ Use in credential issuancepublicKey→ Used by system to verify signatures (you don't need to handle this)verificationMethod→ Reference for signature verification
Issue a Credential
Purpose: Create a payment authorization credential for the user.
Endpoint: POST /issue-credential
Request:
curl -X POST https://localhost:4901/vc/v1/issue-credential \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"userDid": "did:key:z6Mk2b84e6986130ed411d0e386722b0ebb5",
"agentDid": "did:key:z6Mk7b4bcd19d9dee0182ae9e9ef05c9779c",
"amount": 250,
"scope": "restaurant",
"purpose": "Dinner payment",
"expirationMinutes": 30
}'
Response:
{
"success": true,
"data": {
"credential": {
"id": "https://localhost:4901/vc/v1/credentials/uuid-here",
"type": ["VerifiableCredential", "PaymentConsentCredential"],
"issuer": "did:key:platform-issuer-did",
"credentialSubject": {
"id": "did:key:z6Mk2b84e6986130ed411d0e386722b0ebb5",
"authorizedAgent": "did:key:z6Mk7b4bcd19d9dee0182ae9e9ef05c9779c",
"paymentLimit": 250,
"currency": "USD",
"scope": "restaurant",
"purpose": "Dinner payment"
}
}
}
}
What happened: The platform created and signed a credential authorizing the user to make payments up to $250 at restaurants.
Sign a Presentation
Purpose: Get the user's cryptographic consent for the payment.
Endpoint: POST /sign-presentation
Request:
curl -X POST https://localhost:4901/vc/v1/sign-presentation \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"userDid": "did:key:z6Mk2b84e6986130ed411d0e386722b0ebb5",
"presentation": {
"context": ["https://www.w3.org/2018/credentials/v1"],
"type": ["VerifiablePresentation"],
"verifiableCredential": [
{
"id": "https://localhost:4901/vc/v1/credentials/uuid-here",
"type": ["VerifiableCredential", "PaymentConsentCredential"],
"issuer": "did:key:platform-issuer-did",
"credentialSubject": {
"id": "did:key:z6Mk2b84e6986130ed411d0e386722b0ebb5",
"authorizedAgent": "did:key:z6Mk7b4bcd19d9dee0182ae9e9ef05c9779c",
"paymentLimit": 250,
"currency": "USD",
"scope": "restaurant",
"purpose": "Dinner payment"
}
}
]
}
}'
Response:
{
"success": true,
"data": {
"signedPresentation": {
"context": ["https://www.w3.org/2018/credentials/v1"],
"type": ["VerifiablePresentation"],
"verifiableCredential": [...],
"proof": {
"type": "Ed25519Signature2020",
"verificationMethod": "did:key:z6Mk2b84e6986130ed411d0e386722b0ebb5#key-1",
"proofValue": "user_signature_using_enrollment_private_key"
}
}
}
}
What happened: The system signed the presentation using the user's enrollment private key (stored securely on the server).
Make Payment
Purpose: Process the payment using the signed presentation.
Endpoint: POST /pay
Request:
curl -X POST https://localhost:4901/vc/v1/pay \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"amount": 250,
"recipient": "did:key:restaurant-recipient-did",
"currency": "USD",
"description": "Dinner payment",
"presentation": {
"context": ["https://www.w3.org/2018/credentials/v1"],
"type": ["VerifiablePresentation"],
"verifiableCredential": [...],
"proof": {
"type": "Ed25519Signature2020",
"verificationMethod": "did:key:z6Mk2b84e6986130ed411d0e386722b0ebb5#key-1",
"proofValue": "user_signature_using_enrollment_private_key"
}
}
}'
Response:
{
"success": true,
"data": {
"paymentId": "payment-uuid",
"transactionId": "bank-transaction-id",
"amount": 250,
"status": "completed",
"message": "Payment processed successfully"
}
}
What happened: The system automatically verified the user's signature using their enrollment public key, then processed the payment.
Complete Working Example
Here's a complete flow you can copy-paste and run:
1. Enroll User
curl -X POST https://localhost:4901/vc/v1/enroll \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"entityType": "user",
"name": "Test User",
"email": "test@example.com"
}'
2. Issue Credential
curl -X POST https://localhost:4901/vc/v1/issue-credential \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"userDid": "PASTE_USER_DID_FROM_STEP_1",
"agentDid": "did:key:z6Mk7b4bcd19d9dee0182ae9e9ef05c9779c",
"amount": 100,
"scope": "test",
"purpose": "Test payment",
"expirationMinutes": 60
}'
3. Sign Presentation
curl -X POST https://localhost:4901/vc/v1/sign-presentation \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"userDid": "PASTE_USER_DID_FROM_STEP_1",
"presentation": {
"context": ["https://www.w3.org/2018/credentials/v1"],
"type": ["VerifiablePresentation"],
"verifiableCredential": [
{
"id": "PASTE_CREDENTIAL_ID_FROM_STEP_2",
"type": ["VerifiableCredential", "PaymentConsentCredential"],
"issuer": "PASTE_ISSUER_DID_FROM_STEP_2",
"credentialSubject": {
"id": "PASTE_USER_DID_FROM_STEP_1",
"authorizedAgent": "did:key:z6Mk7b4bcd19d9dee0182ae9e9ef05c9779c",
"paymentLimit": 100,
"currency": "USD",
"scope": "test",
"purpose": "Test payment"
}
}
]
}
}'
4. Make Payment
curl -X POST https://localhost:4901/vc/v1/pay \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"amount": 100,
"recipient": "did:key:recipient-did",
"currency": "USD",
"description": "Test payment",
"presentation": "PASTE_SIGNED_PRESENTATION_FROM_STEP_3"
}'
Common Errors & Solutions
401 Unauthorized
Problem: Invalid signature
Solution: Make sure you're using the signed presentation from /sign-presentation
404 Not Found
Problem: User DID not enrolled
Solution: Call /enroll first to create the user
400 Bad Request
Problem: Invalid request format
Solution: Check JSON syntax and required fields
That's it! You now have a complete, working verifiable credential payment system. The cryptographic complexity is handled automatically - you just make HTTPs requests and get secure payments!