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

# Handle Requests

> Learn how AI Builders can process AI Tasks and validate paid requests

Once a Payment Plan is purchased, User(s) can query all the AI Agents linked to that plan.

To ensure AI agents only authorize valid requests (users with credits), we provide a simple API (via the Payments Libraries) that makes validation simple and secure.

## Users: Sending Requests to AI Agents

When a user wants to query an AI Agent, they need to send a request with the access token received when purchasing the Payment Plan. This token is used to validate that the user has access to the AI Agent and that they have enough credits.

<Note>
  The access token is minted against a **delegation** — create it once with `createDelegation` / `create_delegation`, then reuse its `delegationId`. The direct call defaults to crypto (`nvm:erc4337`); for **fiat** (card) plans pass `scheme: 'nvm:card-delegation'`. See [Query Agents](/docs/development-guide/query-agents) for the full buyer flow and [Order Plans](/docs/development-guide/order-plans#which-payment-type-does-this-plan-need) for detecting a plan's payment type.
</Note>

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}

    // After purchasing a Payment Plan, create a delegation once, then mint the access token against it
    const { delegationId } = await payments.delegation.createDelegation({
      provider: 'erc4337',       // 'stripe' | 'braintree' | 'visa' for fiat plans
      spendingLimitCents: 10000, // $100 budget
      durationSecs: 604800,      // 7 days
      currency: 'usdc',          // 'usd' for fiat plans
    })
    const { accessToken } = await payments.x402.getX402AccessToken(planId, agentId, {
      scheme: 'nvm:erc4337',       // 'nvm:card-delegation' for fiat plans
      delegationConfig: { delegationId },
    })

    //// OUTPUT: accessToken is a JWT string containing X402 v2 payment credentials

    // Now we can use this access token to send requests to the AI agent
    const agentHTTPOptions = {
      method: 'POST',
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json',
        'payment-signature': accessToken,
      }
    }

    // Example request to the AI agent
    const response = await fetch(new URL('https://my.agent.io/prompt'), agentHTTPOptions)

    if (response.ok) {
      const data = await response.json()
      console.log('AI agent response:', data)
    } else {
      console.error('Error accessing AI agent:', response.status, await response.text())
    }
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    import requests
    from payments_py.x402 import X402TokenOptions, DelegationConfig, CreateDelegationPayload

    # Create a delegation once, then mint the X402 access token against it
    delegation = payments.delegation.create_delegation(
        CreateDelegationPayload(
            provider="erc4337",          # 'stripe' | 'braintree' | 'visa' for fiat plans
            spending_limit_cents=10000,  # $100 budget
            duration_secs=604800,        # 7 days
            currency="usdc",             # 'usd' for fiat plans
        )
    )
    token_response = payments.x402.get_x402_access_token(
        plan_id,
        agent_id,
        token_options=X402TokenOptions(
            scheme="nvm:erc4337",  # "nvm:card-delegation" for fiat plans
            delegation_config=DelegationConfig(delegation_id=delegation.delegation_id)
        ),
    )
    access_token = token_response['accessToken']
    # OUTPUT: access_token is a JWT string containing X402 v2 payment credentials

    # Now we can use this access token to send requests to the AI agent
    headers = {
        "Accept": "application/json",
        "Content-Type": "application/json",
        "payment-signature": access_token,
    }

    response = requests.post("https://my.agent.io/prompt", headers=headers)
    if response.status_code == 200:
        data = response.json()
        print('AI agent response:', data)
    else:
        print('Error accessing AI agent:', response.status_code, response.text)
    ```
  </Tab>
</Tabs>

## AI Agents: Authorizing Only Valid Requests from Users

All the authorization can be done by calling the `requests.startProcessingRequest` method. This method will receive the access token sent by the user and will validate:

1. The user is a subscriber of any payment plans linked to the AI agent.
2. The requested endpoint and that the HTTP method is permitted (as included as part of the AI agent registration).
3. The user has sufficient credits to pay for the request (in the case of a credits-based Payment Plan) or the payment plan hasn't expired (in the case of a time-based subscription).

In the example below, we will start a simple HTTP server that will first validate the request using the `startProcessingRequest` method. If the request is valid, it will return a 200 OK response; otherwise, it will return a 402 Payment Required response.

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    import http from 'http'

    const agentHost = 'https://example.com' // The AI agent is running on this host

    const server = http.createServer(async (req, res) => {
      const x402Token = req.headers['payment-signature'] as string
      const requestedUrl = `${agentHost}${req.url}`
      const httpVerb = req.method
      console.log('Received request:', { endpoint: requestedUrl, httpVerb, x402Token })

      try {
        const isValidReq = await payments.requests.startProcessingRequest(
          agentId,
          x402Token,
          requestedUrl,
          httpVerb!,
        )
        console.log('isValidReq', isValidReq)
        if (isValidReq.balance.isSubscriber) {
          res.writeHead(200, { 'Content-Type': 'application/json' })
          res.end(JSON.stringify({ message: 'Hello from the agent!' }))
          return
        }
      } catch (error) {
        console.log('Unauthorized access attempt:', x402Token)
        console.log('Error details:', error)
      }

      res.writeHead(402, { 'Content-Type': 'application/json' })
      res.end(JSON.stringify({ error: 'Payment Required' }))
    })

    server.listen(8889, () => {
      console.log('AI agent server running on port 8889')
    })
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    from http.server import HTTPServer, BaseHTTPRequestHandler
    import json
    from payments_py.x402.helpers import build_payment_required

    agent_host = "https://example.com"  # The AI agent is running on this host

    class AgentRequestHandler(BaseHTTPRequestHandler):
        def do_POST(self):
            self._handle_request()

        def do_GET(self):
            self._handle_request()

        def _handle_request(self):
            x402_token = self.headers.get("payment-signature", "")
            requested_url = f"{agent_host}{self.path}"
            http_verb = self.command
            print("Received request:", {"endpoint": requested_url, "httpVerb": http_verb, "x402Token": x402_token})

            try:
                # Build payment requirements
                payment_required = build_payment_required(
                    plan_id=plan_id,
                    endpoint=requested_url,
                    agent_id=agent_id,
                    http_verb=http_verb
                )

                # Verify permissions with x402 access token
                verification = payments.facilitator.verify_permissions(
                    payment_required=payment_required,
                    x402_access_token=x402_token,
                    max_amount="1"
                )

                print("Verification result:", verification)
                if verification.get("is_valid"):
                    self.send_response(200)
                    self.send_header("Content-Type", "application/json")
                    self.end_headers()
                    self.wfile.write(json.dumps({"message": "Hello from the agent!"}).encode())
                    return
            except Exception as error:
                print("Unauthorized access attempt:", x402_token)
                print("Error details:", error)

            self.send_response(402)
            self.send_header("Content-Type", "application/json")
            self.end_headers()
            self.wfile.write(json.dumps({"error": "Payment Required"}).encode())

    # To start the server:
    server = HTTPServer(("localhost", 8889), AgentRequestHandler)
    print("AI agent server running on port 8889")
    server.serve_forever()
    ```
  </Tab>
</Tabs>

## Integration with Popular Frameworks

As you can see, the Payments libraries are framework-agnostic, so you can integrate them with any web framework in TypeScript/JavaScript (Express, Next.js, etc.) or Python (FastAPI, Flask, etc.).

## Best Practices for Request Processing

<CardGroup cols={2}>
  <Card title="Validation First" icon="shield">
    Always validate payments before processing expensive AI operations to avoid wasting resources.
  </Card>

  <Card title="Error Handling" icon="exclamation-triangle">
    Provide clear error messages and appropriate HTTP status codes for different failure scenarios.
  </Card>

  <Card title="Resource Management" icon="gauge">
    Implement timeouts and resource limits to prevent abuse and ensure fair usage.
  </Card>

  <Card title="Monitoring" icon="chart-line">
    Log all requests, validation results, and processing times for analytics and debugging.
  </Card>
</CardGroup>
