Agent integration guide

How an AI agent buys a gift card

Connect once over MCP or REST, then buy in three tool calls: list_brandsbuy_giftcardget_code. Amounts are always integer minor units (cents).

Connect & authenticate

Endpoints

MCP (Streamable HTTP): https://mcp.agentrefills.com/mcp
REST base: https://api.agentrefills.com

Auth

Programmatic: Authorization: Bearer <key>. Host apps (Claude/ChatGPT connectors): OAuth 2.1 via /.well-known/oauth-protected-resource.

The purchase flow

1
Resolve a brand

Call list_brands (for example query:"amazon") to get a brand_id and its denominations.

2
Buy

Call buy_giftcard with brand_id, amount_minor, currency, and a client_ref idempotency key. Under the spend cap it settles; at or above the approval threshold ($25 default) it returns APPROVAL_REQUIRED and a human approves in Slack.

3
Release the code

When status is completed, call get_code once to receive the code, link, or PIN. A second call returns ALREADY_RELEASED.

REST example
curl -X POST https://api.agentrefills.com/v1/purchases \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{"brand_id":"amazon_com-usa","amount_minor":2500,"currency":"USD","client_ref":"reward-9f3a"}'
# -> 202 {"task_id":"...","status":"accepted"}

curl -X POST https://api.agentrefills.com/v1/purchases/<task_id>/code \
  -H "Authorization: Bearer sk_live_..."
# -> 200 {"code":"GIFT-XXXX-9F2A","face_minor":2500,"remaining_minor":2500}

Tool reference

Five tools, identical over MCP and REST. Amounts in integer minor units (cents).

ToolInputReturns
list_brands
read-only
query?, country="US", category?, limit=20brands[] with brand_id, denominations_minor, min/max_minor, in_stock
buy_giftcard
idempotent
brand_id, amount_minor, currency, client_ref?task_id, status:"accepted", estimated_seconds
get_code
single release
task_idcode?, link?, pin?, face_minor, remaining_minor
check_balance
read-only
budget_remaining_minor, daily/monthly_limit_minor, kill_switch
request_approvaltask_id, reasonapproval_id, status

Per-SDK connection

Every one points at the same URL and token. Verified mid-2026; transport strings differ per library.

Claude (Code CLI)
claude mcp add agentrefills --transport http \
  https://mcp.agentrefills.com/mcp \
  --header "Authorization: Bearer sk_live_..."
OpenAI Responses API (hosted MCP tool)
tools=[{ "type":"mcp", "server_label":"agentrefills",
  "server_url":"https://mcp.agentrefills.com/mcp",
  "headers":{"Authorization":"Bearer sk_live_..."},
  "require_approval":"never" }]
OpenAI Agents SDK (Python)
from agents import Agent, Runner
from agents.mcp import MCPServerStreamableHttp

async with MCPServerStreamableHttp(name="agentrefills", params={
    "url":"https://mcp.agentrefills.com/mcp",
    "headers":{"Authorization":"Bearer sk_live_..."}}) as server:
    agent = Agent(name="Shopper", mcp_servers=[server])
    await Runner.run(agent, "Buy a $25 Amazon gift card")
LangChain / LangGraph
from langchain_mcp_adapters.client \
  import MultiServerMCPClient
client = MultiServerMCPClient({"agentrefills":{
  "transport":"streamable_http",
  "url":"https://mcp.agentrefills.com/mcp",
  "headers":{"Authorization":"Bearer sk_live_..."}}})
tools = await client.get_tools()
CrewAI
from crewai_tools import MCPServerAdapter
cfg = {"url":"https://mcp.agentrefills.com/mcp",
  "transport":"streamable-http",
  "headers":{"Authorization":"Bearer sk_live_..."}}
with MCPServerAdapter(cfg) as tools:
    Agent(role="Shopper", tools=tools)
Vercel AI SDK (TypeScript)
import { experimental_createMCPClient as mcpClient } from "ai";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp";

const mcp = await mcpClient({ transport:
  new StreamableHTTPClientTransport(new URL("https://mcp.agentrefills.com/mcp"),
    { requestInit:{ headers:{ Authorization:"Bearer sk_live_..." } } }) });
const tools = await mcp.tools();

Note: LangChain uses streamable_http (underscore); CrewAI and the MCP spec use streamable-http (hyphen). Check each SDK's current MCP docs before shipping.

Error taxonomy

Closed set. Every error is { code, message, hint, task_id?, retry_after? }. Branch on code; the hint is an actionable next step.

CodeMeaning & next step
POLICY_DENIEDNot allowed by policy. Do not retry as-is.
BUDGET_EXCEEDEDOver the agent's cap. Lower the amount or wait.
APPROVAL_REQUIREDParked for a human. Call request_approval or await the webhook.
APPROVAL_REJECTEDHuman declined. Do not retry the same purchase.
OUT_OF_STOCKBrand/denomination unavailable. Try another.
ALREADY_RELEASEDget_code already called. Code returned once only.
RETRYABLETransient. Wait retry_after seconds, retry the same call.
othersPAYMENT_FAILED, INVOICE_EXPIRED, PROVIDER_HOLD, NOT_FOUND, UNAUTHORIZED