Attestation Service
The Attestation Service verifies fiat payments off-chain and returns a signed EIP-712 PaymentAttestation that UnifiedPaymentVerifierV4 accepts on-chain. It also signs identity attestations for seller registration and dispute attestations for Stake to Take.
Production URL: https://attestation-service.zkp2p.xyz (Base mainnet). @zkp2p/zkp2p-attestation targets it with createNitroAttestationClient({ environment: "production" }).
Trust model
- Enclave. The service runs inside an AWS Nitro Enclave. Payment evidence, seller credentials and identity evidence are decrypted, checked and signed only inside the enclave.
- Signing key. The EIP-712 signing key is stored encrypted under AWS KMS. KMS releases it only to an enclave whose Nitro attestation document carries the expected PCR8, the measurement of the certificate Peer signs enclave images with. The plaintext key exists only in enclave memory.
- Client checks. Clients call
GET /attestation?nonce=...and verify the AWS-signed attestation document and its PCR8 against the pin in@zkp2p/zkp2p-attestationbefore they encrypt session material to the enclave or trust a signature. - On-chain checks.
UnifiedPaymentVerifierV4accepts only signatures from the witness set onMultiAttestationVerifier. - What you trust. AWS Nitro, and the enclave images Peer signs. Peer controls the signing certificate, so a malicious image signed by Peer could produce false attestations. See Risks.
Endpoints
| Endpoint | Purpose |
|---|---|
GET /attestation?nonce=... | Nitro attestation document bound to your nonce, with the enclave's upload public key |
POST /buyer/verify/:platform/:actionType | Buyer TEE Verification: verify a buyer's payment |
GET /buyer/supported | Registered buyer verifiers and the typed-data spec |
POST /seller/credentials/:platform | Seller Autopilot: validate seller credentials, return an encrypted bundle |
POST /identity | Prove a live payment-platform account and return an IdentityAttestation |
POST /dispute/verify/:platform/:actionType | Verify a Venmo or PayPal dispute email and return a DisputeAttestation |
GET /dispute/supported | Registered dispute verifiers and their typed-data specs |
GET /health | Service health |
GET /docs | OpenAPI reference |
For Seller Autopilot, Peer's API stores the encrypted credential bundle and asks the enclave to verify seller-side payments. It cannot decrypt the bundle.
Payment attestations
Buyer TEE Verification and Seller Autopilot both normalize the observed payment, check it against the intent, and return the same output: the signer, the signature, the typed PaymentAttestation values, the encoded payload and unsigned metadata naming the source path (buyer-tee or seller-tee). The client passes abi.encode(PaymentAttestation) as paymentProof to OrchestratorV4.fulfillIntent.
Before signing, the service checks the payment method, currency, payee, payment time, intent hash, conversion rate and amount. The release amount is:
min(paymentAmount * 10^18 * 10^4 / conversionRate, intentAmount)
paymentAmount is the verified amount in cents of the intent's currency, after any cross-currency adjustment; 10^4 converts cents to 6-decimal USDC units. The signed payload also carries the payment's dispute window. See Unified Payment Verifier for the on-chain format.
Requests carry chainId. The service resolves the UnifiedPaymentVerifierV4 address for that chain itself (0x7bE50E6206a9b3AdF36dbEAFac0e45Cc03A72048 on Base); requests do not include verifyingContract.
Identity registration
POST /identity proves a live platform account and returns a signed EIP-712 IdentityAttestation. The request includes platform, actionType, callerAddress, encryptedSessionMaterial (a compact JWE to the enclave's upload key that binds the same platform, action and callerAddress) and public params:
| Platform | Action type | Encrypted session material | Public params |
|---|---|---|---|
venmo | register_venmo | Cookie | SENDER_ID |
paypal | register_paypal | Cookie | none |
paypal | register_business_paypal | Cookie | none |
wise | register_wise | Cookie, X-Access-Token | PROFILE_ID |
cashapp | register_cashapp | sessionCookie, requestPayload, optional requestHeaders | none |
alipay | register_alipay | Cookie | none |
The response contains the normalized identity (platform, actionType, method, payeeId, payeeIdHash, username, metadata), the signed values (method, actionType, callerAddress, payeeIdHash, dataHash, issuedAt, validUntil), signature and signer. Registration APIs consume identity attestations; they are not payment proofs.
A Seller Autopilot credential upload can also return an IdentityAttestation when the encrypted upload includes callerAddress.
Dispute verification
POST /dispute/verify/venmo/dispute_venmo and POST /dispute/verify/paypal/dispute_paypal accept { encryptedSessionMaterial, params: {}, chainId, intentHash }. Encrypt the complete RFC 5322 dispute email as sessionMaterial: { rawEmail }. The enclave verifies the platform's DKIM signature and extracts the original payment ID, the case ID and the disputed amount.
The response contains a witness signature under the EIP-712 domain { name: "ZKP2P DisputeVerifier", version: "1", chainId, verifyingContract: DisputeVerifier } with type DisputeAttestation(bytes32 intentHash,bytes32 dataHash), plus the encoded dispute details. Build DisputeAttestation { intentHash, dataHash, signatures, data } and submit it to DisputeProtectionPolicyV2.submitDispute (DisputeProtectionPolicy.submitDispute for OrchestratorV3 intents). It is not a payment proof.
@zkp2p/zkp2p-attestation provides createNitroAttestationClient(...).verifyDispute() to encrypt and submit the email, and verifyDisputeAttestation() to check the returned signature and typed data.