Start building in minutes
Integrate signed document verification into your app with just a few lines of code. No complex setup required.
Secure Verification
Verify cryptographic signatures and document status in real-time.
Fast Response
Optimized API with millisecond response times.
All Types
Supports single PDF, multi-signature, and wallet certificates.
Documentation
Single endpoint to verify any type of certificate.
/api/v1/verifyParameters
idCertificate ID (e.g., PDF-MS-xxx, PDF-xxx, or wallet ID)
Headers
x-api-keyYour ProofLayer API key
Examples
curl -X GET "https://prooflayer.ink/api/v1/verify?id=PDF-MS-1779027938314-COpJ33AX" \
-H "x-api-key: pl_test_your_api_key"Example Response
{
"success": true,
"data": {
"valid": true,
"type": "multisig_pdf",
"certificate": {
"id": "PDF-MS-1779027938314-COpJ33AX",
"filename": "contract.pdf",
"fileHash": "a03d1e666a2a9a1e4ab68e8f...",
"status": "completed",
"requiredSignatures": 2,
"completedSignatures": 2,
"isComplete": true,
"signers": [...]
},
"verifyUrl": "https://prooflayer.ink/verificar/PDF-MS-1779027938314-COpJ33AX"
},
"meta": {
"environment": "test",
"timestamp": "2026-05-17T14:30:00Z"
}
}PDF documents signed by multiple wallets
PDF documents signed by a single wallet
Text documents signed by one or more wallets
Creation Endpoints
Create documents programmatically. Users sign in the ProofLayer UI.
/api/v1/pdf/multisig/createCreate multi-signature PDF document
Body (multipart/form-data)
filerequired- PDF filesignersrequired- JSON array: [{wallet, name?, organization?, role?}]requiredSignaturesoptional- Number (defaults to signers.length)curl -X POST "https://prooflayer.ink/api/v1/pdf/multisig/create" \
-H "x-api-key: pl_test_xxx" \
-F "file=@contract.pdf" \
-F 'signers=[{"wallet":"0x123...","name":"Alice","role":"CEO"},{"wallet":"0x456...","name":"Bob"}]'/api/v1/pdf/createCreate single-signature PDF document
Body (multipart/form-data)
filerequired- PDF filesignerrequired- Wallet address (0x...)nameoptional - Signer nameorganizationoptional - Organizationroleoptional - Role/titlecurl -X POST "https://prooflayer.ink/api/v1/pdf/create" \ -H "x-api-key: pl_test_xxx" \ -F "file=@contract.pdf" \ -F "signer=0x7dA443837Bb1df22EE5e2BC5892843401659515D" \ -F "name=John Doe" \ -F "organization=Acme Inc"
/api/v1/document/createCreate text document for multi-signature
Body (JSON)
{
"title": "Service Agreement",
"content": "Terms and conditions...",
"signers": [
{"wallet": "0x123...", "name": "Alice", "organization": "Acme Inc", "role": "CEO"},
{"wallet": "0x456...", "name": "Bob"}
]
}Response
{
"success": true,
"data": {
"id": "DOC-1234567890-AbCdEf",
"signUrl": "https://prooflayer.ink/firmar/DOC-1234567890-AbCdEf",
"verifyUrl": "https://prooflayer.ink/verificar/DOC-1234567890-AbCdEf",
"signers": [...]
}
}Transaction Certificate API
Generate verifiable certificates for blockchain transactions. Send a txHash and receive a certificate with PDF and verification URL.
/api/v1/transaction-certificate/createRequest body
txHashrequired- Transaction hash (required)chainId- Chain ID (1=Ethereum, 137=Polygon, etc.)networkKey- Alternative to chainId: ethereum, polygon, bsc, arbitrum, base, optimismcertificateType- Certificate type: transfer, payment, loan, customcustomMessageoptional - Optional custom messagelanguageoptional - Language: en or escurl -X POST "https://prooflayer.ink/api/v1/transaction-certificate/create" \
-H "x-api-key: pl_test_xxx" \
-H "Content-Type: application/json" \
-d '{
"txHash": "0x123abc...",
"networkKey": "ethereum",
"certificateType": "transfer"
}'Response example
{
"success": true,
"data": {
"certificateId": "TX-CERT-1234567890-AbCd",
"status": "created",
"txHash": "0x123abc...",
"network": "Ethereum",
"from": "0x...",
"to": "0x...",
"amount": "1.5",
"token": "ETH",
"usdValue": "3500.00",
"timestamp": "2026-05-19T12:00:00Z",
"printableUrl": "https://prooflayer.ink/api/v1/transaction-certificate/TX-CERT.../pdf",
"verifyUrl": "https://prooflayer.ink/verificar/TX-CERT..."
}
}Payment Receipt API
Generate verifiable payment receipts. Ideal for platforms with their own checkout that accept crypto.
/api/v1/receipts/paymentRequest body
txHashrequired- Transaction hash (required)chainId / networkKeyrequired- Chain ID (1=Ethereum, 137=Polygon, etc.)orderIdrequired- Order ID in your system (required)productNamerequired- Product name (required)merchantNamerequired- Merchant name (required)merchantWalletrecommended- Merchant wallet (recommended for validation)expectedAmountoptional - Expected amount (for validation)Server-Side Validation
The API validates the transaction directly on the blockchain. Never trust client-provided data.
Replay protection
Duplicate txHash + orderId combinations are detected and return the existing receipt.
curl -X POST "https://prooflayer.ink/api/v1/receipts/payment" \
-H "x-api-key: pl_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"txHash": "0x456def...",
"networkKey": "polygon",
"orderId": "ORDER-12345",
"productName": "Premium Subscription",
"merchantName": "Acme Inc",
"merchantWallet": "0x7dA443837Bb1df22EE5e2BC5892843401659515D",
"expectedAmount": 50
}'Response example
{
"success": true,
"data": {
"receiptId": "RCPT-1234567890-XyZw",
"status": "created",
"txHash": "0x456def...",
"network": "Polygon",
"payerWallet": "0xcustomer...",
"merchantWallet": "0x7dA443...",
"amount": "50.0",
"token": "USDC",
"usdValue": "50.00",
"transferType": "erc20",
"timestamp": "2026-05-19T12:00:00Z",
"orderId": "ORDER-12345",
"productName": "Premium Subscription",
"merchantName": "Acme Inc",
"printableReceiptUrl": "https://prooflayer.ink/api/v1/receipts/RCPT.../pdf",
"verifyUrl": "https://prooflayer.ink/verificar/RCPT..."
}
}Invisible Checkout Receipt
Generate verifiable receipts automatically after each crypto payment - no widgets or visible integration.
Integration flow
Receipt Status
ERC20 Validation
For token payments (USDC, USDT, DAI), the API parses Transfer event logs to validate that merchantWallet received the payment.
Error: merchantWallet is not receiver
If the transaction does not send funds to merchantWallet, the API returns error 400 with validationError.
{
"success": false,
"data": {
"status": "failed",
"error": "Transaction receiver (0xcontract...) does not match merchantWallet (0xmerchant...)",
"txHash": "0x...",
"webhookEvent": "receipt.failed"
},
"error": "Transaction receiver (0xcontract...) does not match merchantWallet..."
}JavaScript Example
// After payment is confirmed in your checkout
async function generateReceipt(txHash, orderData) {
const response = await fetch('https://prooflayer.ink/api/v1/receipts/payment', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': process.env.PROOFLAYER_API_KEY,
},
body: JSON.stringify({
txHash,
networkKey: 'polygon', // or chainId: 137
orderId: orderData.id,
productName: orderData.productName,
merchantName: 'Your Company',
merchantWallet: process.env.MERCHANT_WALLET,
expectedAmount: orderData.amount, // optional validation
expectedToken: 'USDC', // optional validation
}),
});
const { data, error } = await response.json();
if (data.status === 'verified') {
// Success! Save receipt URL
await saveReceiptToOrder(orderData.id, {
receiptId: data.receiptId,
printableReceiptUrl: data.printableReceiptUrl,
verifyUrl: data.verifyUrl,
});
} else if (data.status === 'pending') {
// Transaction not confirmed yet - retry later
scheduleRetry(txHash, orderData);
} else if (data.status === 'duplicate') {
// Receipt already exists - use existing
return data;
}
return data;
}Idempotency Note
Repeated calls with the same txHash + orderId return the existing receipt with status: duplicate.
Internal ProofLayer Use Case
This same API is used internally to generate receipts for PRO/Enterprise payments.
After-Payment Widget
Display verifiable receipts automatically after each crypto payment.
When to use
After the user completes a payment in your existing checkout and you have the txHash.
How it works
Embed code
<!-- Include the widget script --> <script src="https://prooflayer.ink/embed/receipt-widget.js"></script> <!-- Widget container --> <div data-prooflayer-widget="receipt" data-public-key="pk_widget_test_your_public_key" data-tx-hash="0x..." data-network-key="polygon" data-order-id="ORDER-123" data-product-name="Annual Subscription" data-merchant-name="Your Company" data-merchant-wallet="0x..." data-customer-name="John Doe" data-theme="light" data-language="en" ></div>
Supported attributes
data-public-keyrequired- Your widget public key pk_widget_... (required)data-tx-hashrequired- Transaction hash (required)data-network-key- Network: ethereum, polygon, base, etc.data-order-id- Order ID in your systemdata-product-name- Product namedata-merchant-name- Merchant namedata-merchant-walletrecommended- Merchant wallet (for validation)data-customer-name- Customer name (optional)data-theme- Theme: light or darkdata-language- Language: en or esWidget states
Security model
- • Widget uses public keys (pk_widget_*), NOT secret keys
- • Domain restrictions configurable per key
- • All tx validation is done server-side
- • Secret keys (pl_*) for backend-to-backend only
API Key Types
For backend-to-backend use only. NEVER expose in frontend.
pl_live_abc123... (backend only)Safe to use in embedded widgets. Configure allowed domains.
pk_widget_live_xyz789... (frontend safe)Domain restrictions
Widget public keys can be restricted to specific domains. In test mode, localhost is allowed by default.
Need help? Contact support@prooflayer.ink