> ## Documentation Index
> Fetch the complete documentation index at: https://docs.predicate.io/llms.txt
> Use this file to discover all available pages before exploring further.

# 2. Offchain Integration

> Integrate the Predicate API to evaluate compliance in your application

Integrate the Predicate API into your backend to evaluate users against your configured policy. The API returns a compliance result and a signed attestation.

<Steps>
  <Step title="Backend Integration">
    Call the Predicate API from your server using your API key.
  </Step>

  <Step title="Handle the Response">
    Use `is_compliant` to gate access in your application.
  </Step>
</Steps>

***

## Backend Integration

Store your API key on the server and call the Predicate API. Use the `verification_hash` from your project and the user's wallet address.

```typescript theme={null}
import express from 'express';

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

app.post('/api/compliance/check', async (req, res) => {
  const { userAddress } = req.body;

  const response = await fetch('https://api.predicate.io/v2/attestation', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-api-key': process.env.PREDICATE_API_KEY,
    },
    body: JSON.stringify({
      verification_hash: process.env.PREDICATE_VERIFICATION_HASH,
      from: userAddress,
      chain: 'ethereum',
    }),
  });

  const result = await response.json();

  if (!result.is_compliant) {
    return res.status(403).json({
      error: 'User not compliant',
      policy: result.policy_name,
      reason: result.reason, // may include code and message from the policy
    });
  }

  // User is compliant — proceed with your business logic
  res.json({ compliant: true });
});
```

***

## Request Parameters

| Field               | Required | Description                                       |
| ------------------- | -------- | ------------------------------------------------- |
| `verification_hash` | Yes      | Your project identifier from the dashboard        |
| `from`              | Yes      | The user's wallet address to evaluate             |
| `chain`             | Yes      | Chain name (e.g., `ethereum`, `base`, `arbitrum`) |

***

## Response

#### Compliant

```json theme={null}
{
  "policy_id": "policy_abc123",
  "policy_name": "Standard AML Policy",
  "verification_hash": "x-abc123def456",
  "is_compliant": true,
  "attestation": {
    "uuid": "550e8400-e29b-41d4-a716-446655440000",
    "expiration": 1696640400,
    "attester": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
    "signature": "0x1b2c3d4e5f..."
  }
}
```

#### Non-Compliant

Some policies include a `reason` object on non-compliant responses with details about why the evaluation failed. Both the `code` and `message` values are fully customizable when authoring a policy.

```json theme={null}
{
  "policy_id": "x-dev-trm-risk-abc123",
  "policy_name": "TRM Risk Score",
  "verification_hash": "x-abc123def456",
  "is_compliant": false,
  "attestation": {
    "uuid": "550e8400-e29b-41d4-a716-446655440000",
    "expiration": 0,
    "attester": "",
    "signature": ""
  },
  "reason": {
    "code": "trm_high_risk",
    "message": "TRM risk score for this wallet is 10 which exceeds the maximum allowed of 7"
  }
}
```

| Field          | Description                                                                                                                                 |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `is_compliant` | Whether the user passed the policy evaluation                                                                                               |
| `policy_name`  | Name of the policy that was evaluated                                                                                                       |
| `attestation`  | Signed attestation (used for onchain enforcement in Phase 2)                                                                                |
| `reason`       | Optional object on non-compliant responses. Contains `code` (machine-readable) and `message` (human-readable) fields defined by the policy. |

***

## Supported Chains

| Chain           | Value             |
| --------------- | ----------------- |
| Ethereum        | `ethereum`        |
| Base            | `base`            |
| Arbitrum        | `arbitrum`        |
| Hyperliquid     | `hyperliquid`     |
| Plume           | `plume`           |
| BSC             | `bsc`             |
| Plasma          | `plasma`          |
| World           | `worldchain`      |
| Sepolia         | `sepolia`         |
| Base Sepolia    | `base_sepolia`    |
| Solana          | `solana`          |
| MegaETH         | `megaeth`         |
| MegaETH Testnet | `megaeth_testnet` |

***

## Next Steps

Your offchain integration is complete. Your application can now evaluate compliance for any user.

When you're ready to enforce compliance at the smart contract level, continue to [Onchain Enforcement](/v2/applications/onchain-enforcement).
