Skip to main content
For this walkthrough, we’ll use a web application as an example, though most other services require only a subset of these steps.
1

Backend Integration

Fetching Predicate Attestations requires an API key that must be secured. Like most cases, using a passthrough proxy is best practice here.
2

Frontend Integration

Embed the Predicate Attestation into the transaction object, allowing users access to your financial application.

Mental model

  • With specific transaction information, your backend requests the PredicateAPI for an attestation.
  • The PredicateAPI returns a message detailing if the request is compliant and a corresponding attestation.
  • Your frontend includes that message when calling a predicated contract function.

Backend Integration

Store your API key on the server, call the Predicate API, and return the attestation to the client.With BasicPredicateClient, the request only needs from, to, and chain — no calldata encoding required. If using PredicateClient, include data and msg_value so the policy can validate function calls, parameters, and value-based limits.
import express from 'express';
import fetch from 'node-fetch';

const app = express();
app.use(express.json());

app.post('/api/predicate/attestation', async (req, res) => {
  const { from, to, chain = 'base' } = req.body;
  try {
    const resp = await fetch('https://api.predicate.io/v2/attestation', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'x-api-key': process.env.PREDICATE_API_KEY as string,
      },
      body: JSON.stringify({ from, to, chain }),
    });

    if (!resp.ok) {
      const err = await resp.text();
      return res.status(resp.status).send(err);
    }

    const result = await resp.json();
    if (!result.is_compliant) {
      return res.status(400).json({ error: 'Transaction not compliant', details: result });
    }

    res.json({
      attestation: result.attestation,
      policy_id: result.policy_id,
      policy_name: result.policy_name,
      verification_hash: result.verification_hash,
    });
  } catch (e) {
    res.status(500).json({ error: 'Failed to evaluate policy' });
  }
});

Frontend Integration

Fetch the attestation from your backend and pass it to your predicated function.
// 1) Fetch attestation
const resp = await fetch('/api/predicate/attestation', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    from: userAddress,
    to: vaultAddress,
    chain: 'base',
  }),
});
const { attestation } = await resp.json();

// 2) Call the predicated function with the Attestation struct
const tx = await vault.deposit(
  {
    uuid: attestation.uuid,
    expiration: attestation.expiration,
    attester: attestation.attester,
    signature: attestation.signature,
  },
  { value: depositAmount }
);