Guides
Payments
Give an agent a Ramp identity, controlled spending power, and a complete purchase record.
Standalone agents are in limited early access. Reach out to the team to get started.
Use business credentials to create roles, agents, and funds. Switch to the agent's credentials only after connecting its runtime; those credentials are what identify the agent when it requests payment credentials and completes the purchase record.
Python examples use the official Ramp SDK. Preview businesses receive a supported version that includes the provisioning resources shown below.
Optional: Create a role
Use one of Ramp's default agent roles: Purchasing, Bill approvals, Data analysis, Expense Completion, or Full Access. Create a custom role only when none of the defaults matches the agent's job.
The API and SDK accept custom roles only; built-in role IDs are not available
through those surfaces. The business integration needs users:read and
users:write, the person authorizing it must be a role admin, and custom roles
must be enabled for the business.
Open Company → Agents, select New agent, and enter the agent's name. On the Role step, choose Purchasing agent, Bill approvals, Data analysis, or Expense completion. Ramp creates or reuses the matching role as part of setup.
from ramp import Ramp
business_client = Ramp.from_env(environment="production")
# Reuse a matching custom role when one exists.
roles = business_client.roles.list()["data"]
role = next(
(item for item in roles if item["name"] == "Purchasing Agent Role"),
None,
)
if role is None:
# Otherwise create a role with the approved capability map.
role = business_client.roles.create(
name="Purchasing Agent Role",
description="Purchases approved goods and services",
product_capabilities={
"<capability-name>": "<access-level>",
},
)# List existing custom roles.
curl --request GET \
--url https://api.ramp.com/developer/v1/roles \
--header "Authorization: Bearer $RAMP_BUSINESS_ACCESS_TOKEN"
# Create a role when none matches the agent's job.
curl --request POST \
--url https://api.ramp.com/developer/v1/roles \
--header "Authorization: Bearer $RAMP_BUSINESS_ACCESS_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"name": "<role-name>",
"description": "<role-description>",
"product_capabilities": {
"<capability-name>": "<access-level>"
}
}'# List existing custom roles.
ramp --profile human roles list
# Create a role when none matches the agent's job.
ramp --profile human roles create --json '{
"name": "Purchasing Agent Role",
"description": "Purchases approved goods and services",
"product_capabilities": {
"<capability-name>": "<access-level>"
}
}'1. Create an agent
Create a company-owned identity for the software.
The business integration needs agents:write, the person authorizing it must
be a role admin, and standalone agents must be enabled for the business.
When supplied, the owner must be an active human with Ramp access in the same
business.
Open Company → Agents and select New agent. Enter the agent's name, continue to Role, and choose the role that matches its job. The UI stages the agent until you finish the Wallet step.
from uuid import UUID
# Create the standalone agent and capture its show-once credentials.
agent = business_client.agents.create(
name="Purchasing Agent",
description="Purchases approved goods and services",
owner_id=UUID("<owner-user-id>"),
role_ids=[UUID(str(role["id"]))],
)
agent_id = str(agent["id"])
agent_client_id = str(agent["client_id"])
agent_client_secret = str(agent["client_secret"])# Create the standalone agent.
curl --request POST \
--url https://api.ramp.com/developer/v1/agents \
--header "Authorization: Bearer $RAMP_BUSINESS_ACCESS_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"name": "Purchasing Agent",
"description": "Purchases approved goods and services",
"owner_id": "<owner-user-id>",
"role_ids": ["<custom-role-id>"]
}'
# Store client_id and the show-once client_secret from the response.# Create the standalone agent.
ramp --profile human agent create \
--name "Purchasing Agent" \
--description "Purchases approved goods and services" \
--owner_id "<owner-user-id>" \
--role-id "<custom-role-id>"
# Store the returned Client ID and show-once Client secret.2. Assign a fund
Give the agent a budget, merchant rules, approvals, and accounting defaults.
The SDK, API, and CLI examples below show every control supported for a
standalone fund. Amounts in fund controls use the currency's smallest unit—for
example, 10000 means $100.00 USD. Configure approval chains in Ramp.
On the Wallet step, search for an existing fund and select Add. You can preview its limits, eligibility, policies, and recent activity before assigning it.
To make a new fund, select Create funds and set its name, spend limit, cadence, optional per-transaction limit, and merchant or category rules. The new fund is selected automatically.
Select Create agent when the wallet is ready. Ramp creates the agent, assigns the selected funds, and opens the Credential step. Save the Client ID and show-once Client secret in a secret manager.
from uuid import UUID
# Create a standalone, shareable fund for the agent.
fund = business_client.funds.create(
idempotency_key="<unique-fund-request-id>",
user_id=UUID("<human-owner-id>"),
display_name="Agent purchases",
is_shareable=True,
is_exempt_from_policy_agent=False,
accounting_rules=[
{
"field_id": "<accounting-field-id>",
"field_option_id": "<accounting-option-id>",
},
],
spending_restrictions={
"limit": {
"amount": 10000,
"currency_code": "USD",
},
"interval": "MONTHLY",
"transaction_amount_limit": {
"amount": 5000,
"currency_code": "USD",
},
"lock_date": "<iso-8601-expiration>",
"blocked_mcc_codes": ["<mcc-code>"],
"allowed_vendor_ids": ["<vendor-id>"],
"allowed_category_codes": [14],
},
permitted_spend_types={
"reimbursements": False,
"virtual_card": True,
"physical_card": False,
},
)
# Assign the agent to the fund.
membership = business_client.funds.add_members(
fund_id=str(fund["id"]),
user_ids=[agent_id],
)# Create a standalone, shareable fund.
curl --request POST \
--url https://api.ramp.com/developer/v1/funds \
--header "Authorization: Bearer $RAMP_BUSINESS_ACCESS_TOKEN" \
--header "Content-Type: application/json" \
--header "X-Idempotency-Key: <unique-fund-request-id>" \
--data '{
"user_id": "<human-owner-id>",
"display_name": "Agent purchases",
"is_shareable": true,
"is_exempt_from_policy_agent": false,
"accounting_rules": [
{
"field_id": "<accounting-field-id>",
"field_option_id": "<accounting-option-id>"
}
],
"spending_restrictions": {
"limit": {
"amount": 10000,
"currency_code": "USD"
},
"interval": "MONTHLY",
"transaction_amount_limit": {
"amount": 5000,
"currency_code": "USD"
},
"lock_date": "<iso-8601-expiration>",
"blocked_mcc_codes": ["<mcc-code>"],
"allowed_vendor_ids": ["<vendor-id>"],
"allowed_category_codes": [14]
},
"permitted_spend_types": {
"reimbursements": false,
"virtual_card": true,
"physical_card": false
}
}'# Assign the agent to the fund.
curl --request POST \
--url https://api.ramp.com/developer/v1/funds/{fund_id}/members \
--header "Authorization: Bearer $RAMP_BUSINESS_ACCESS_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"user_ids": ["<agent-id>"]
}'# Create a standalone, shareable fund.
ramp --profile human funds create-fund "<human-owner-id>" \
--idempotency_key "<unique-fund-request-id>" \
--display_name "Agent purchases" \
--is_shareable \
--json '{
"is_exempt_from_policy_agent": false,
"accounting_rules": [
{
"field_id": "<accounting-field-id>",
"field_option_id": "<accounting-option-id>"
}
],
"spending_restrictions": {
"limit": {
"amount": 10000,
"currency_code": "USD"
},
"interval": "MONTHLY",
"transaction_amount_limit": {
"amount": 5000,
"currency_code": "USD"
},
"lock_date": "<iso-8601-expiration>",
"blocked_mcc_codes": ["<mcc-code>"],
"allowed_vendor_ids": ["<vendor-id>"],
"allowed_category_codes": [14]
},
"permitted_spend_types": {
"reimbursements": false,
"virtual_card": true,
"physical_card": false
}
}'
# Assign the agent to the fund.
ramp --profile human funds add-members "<fund-id>" \
--user_ids '["<agent-id>"]'3. Connect a runtime
Store the agent's credentials in the system that will operate it.
Add Ramp through the hosted agent's secure connection or secret-storage flow. Store the Client ID and Client secret as credentials, not in the agent's instructions.
Hosted standalone-agent connections are part of the limited preview.
from ramp import Ramp
# Authenticate future purchase actions as the agent.
agent_client = Ramp(
client_id=agent_client_id,
client_secret=agent_client_secret,
environment="production",
)# Exchange the agent's credentials for an access token.
token_response="$(
curl --fail-with-body --silent --show-error --request POST \
--url https://api.ramp.com/developer/v1/token \
--user "$RAMP_AGENT_CLIENT_ID:$RAMP_AGENT_CLIENT_SECRET" \
--header "Content-Type: application/x-www-form-urlencoded" \
--data "grant_type=client_credentials"
)"
RAMP_AGENT_ACCESS_TOKEN="$(jq -er '.access_token' <<<"$token_response")"
export RAMP_AGENT_ACCESS_TOKEN
unset RAMP_AGENT_CLIENT_ID RAMP_AGENT_CLIENT_SECRET token_response# Refresh commands after Ramp enables the preview.
ramp --env production tools refresh
# Save the agent credentials in a dedicated CLI profile.
export RAMP_CLIENT_ID="$RAMP_AGENT_CLIENT_ID"
export RAMP_CLIENT_SECRET="$RAMP_AGENT_CLIENT_SECRET"
ramp --env production agent login
unset RAMP_CLIENT_ID RAMP_CLIENT_SECRET
# Confirm that future commands will run as the agent.
ramp --env production --profile agent auth status4. Generate card credentials
Request a fresh credential after the fund, merchant, amount, and purpose are approved.
The agent integration needs cards:read_agentic for fund discovery and
credential generation.
Ask the connected agent to use a specific fund for a named merchant and maximum amount. Have it confirm the fund and final total before checkout.
The agent should send the credential directly to checkout, not display the PAN or CVV in chat.
# Confirm the fund is assigned to the agent.
eligible_funds = agent_client.agent_tools.agent_cards.list_funds(
rationale="Find funds assigned to this agent",
)
# Generate credentials for one approved checkout attempt.
credentials = agent_client.agent_tools.agent_cards.create_payment_token(
fund_id="<fund-id>",
amount="100.00",
currency_code="USD",
merchant_name="<merchant-name>",
merchant_url="https://<merchant-domain>",
merchant_country_code="US",
rationale="Complete the approved purchase",
idempotency_key="<unique-checkout-attempt-id>",
)# Confirm the fund is assigned to the agent.
curl --request POST \
--url https://api.ramp.com/developer/v1/agent-tools/get-agent-card-funds \
--header "Authorization: Bearer $RAMP_AGENT_ACCESS_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"rationale": "Find funds assigned to this agent"
}'# Generate credentials for one approved checkout attempt.
credential_response="$(
curl --fail-with-body --silent --show-error --request POST \
--url https://api.ramp.com/developer/v1/agent-tools/get-agent-card-creds \
--header "Authorization: Bearer $RAMP_AGENT_ACCESS_TOKEN" \
--header "Content-Type: application/json" \
--header "X-Idempotency-Key: <unique-checkout-attempt-id>" \
--data '{
"fund_id": "<fund-id>",
"amount": "100.00",
"currency_code": "USD",
"merchant_name": "<merchant-name>",
"merchant_url": "https://<merchant-domain>",
"merchant_country_code": "US",
"rationale": "Complete the approved purchase"
}'
)"
# Pass credential_response directly to checkout here without logging it.
# Then clear it from the shell.
unset credential_response# Confirm the fund is assigned to the agent.
ramp --profile agent --agent funds get-agent-card-funds \
--rationale "Find funds assigned to this agent"
# Generate credentials without printing the PAN or CVV.
set +x
agent_card_credentials="$(
ramp --profile agent --agent funds creds "<fund-id>" \
--amount "100.00" \
--currency_code "USD" \
--merchant_name "<merchant-name>" \
--merchant_url "https://<merchant-domain>" \
--merchant_country_code "US" \
--rationale "Complete the approved purchase" \
--idempotency_key "<unique-checkout-attempt-id>" |
jq -cer '.data[0]'
)"
# Pass agent_card_credentials directly to checkout here without logging it.
# Then clear it from the shell.
unset agent_card_credentialsThe credential is limited to the merchant and requested amount. It expires after the first authorization or 12 hours, whichever comes first.
Agent Card amounts use decimal strings: 100.00 means $100.00 USD. Fund limits
above use the currency's smallest unit, where 10000 means $100.00 USD.
5. Complete the purchase record
After the charge posts, add the receipt, memo, and required accounting fields.
Credential generation does not return the posted transaction ID. Find the matching transaction after it posts. If Ramp requires accounting fields, list the available categories and options before editing.
The agent integration needs transactions:read, transactions:write,
accounting:read, and receipts:write to finish this step. The examples treat
the memo and accounting choices as agent-selected. If the user supplied either
value directly, include its field name in user_submitted_fields instead.
Open the transaction in Ramp. Upload the receipt, add a specific memo, confirm the fund, and complete any required accounting or tracking fields.
Finish when Ramp shows no missing items.
import base64
from pathlib import Path
from uuid import UUID
next_page_cursor = None
matching_transactions = []
# Find exactly one posted transaction for this purchase.
while True:
transactions = agent_client.agent_tools.transactions.list(
transactions_to_retrieve="my_transactions",
next_page_cursor=next_page_cursor,
page_size=50,
rationale="Find the posted purchase",
)
matching_transactions.extend(
transaction
for transaction in transactions["transactions"]
if transaction["merchant_name"] == "<merchant-name>"
and transaction["amount"] == "100.00"
and transaction["spend_allocation_id"] == "<fund-id>"
and transaction["transaction_time"].startswith("<purchase-date>")
and transaction["transaction_uuid"] is not None
)
next_page_cursor = transactions.get("next_page_cursor")
if next_page_cursor is None:
break
if len(matching_transactions) != 1:
raise RuntimeError("Expected exactly one matching transaction")
transaction_id = UUID(matching_transactions[0]["transaction_uuid"])
# Find valid accounting values before editing the transaction.
categories = agent_client.agent_tools.accounting.categories(
transaction_uuid=str(transaction_id),
rationale="List required accounting categories",
)
options = agent_client.agent_tools.accounting.category_options(
tracking_category_uuid="<category-id-from-categories>",
transaction_uuid=str(transaction_id),
query_string="<option-name-or-code>",
page_size=10,
rationale="List accounting options",
)
# Add the memo and accounting selections.
agent_client.agent_tools.transactions.edit(
transaction_uuid=str(transaction_id),
memo="<purchase-purpose>",
tracking_category_selections=[
{
"category_uuid": "<category-id>",
"option_selection": "<option-id>",
},
],
user_submitted_fields=[],
rationale="Complete the approved purchase record",
)
# Attach the receipt and verify that nothing is missing.
receipt_bytes = Path("<receipt-file>").read_bytes()
agent_client.agent_tools.receipts.upload(
filename="<receipt-filename>",
content_type="<mime-type>",
file_content_base64=base64.b64encode(receipt_bytes).decode("ascii"),
transaction_uuid=str(transaction_id),
rationale="Attach the purchase receipt",
)
missing_items = agent_client.agent_tools.transactions.missing(
id=transaction_id,
rationale="Verify the purchase record is complete",
)
agent_client.close()
business_client.close()# Find the first page of posted transactions.
curl --request POST \
--url https://api.ramp.com/developer/v1/agent-tools/get-transactions \
--header "Authorization: Bearer $RAMP_AGENT_ACCESS_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"transactions_to_retrieve": "my_transactions",
"page_size": 50,
"rationale": "Find the posted purchase"
}'
# Continue with the cursor returned by the previous page.
curl --request POST \
--url https://api.ramp.com/developer/v1/agent-tools/get-transactions \
--header "Authorization: Bearer $RAMP_AGENT_ACCESS_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"transactions_to_retrieve": "my_transactions",
"next_page_cursor": "<next-page-cursor>",
"page_size": 50,
"rationale": "Find the next page of posted purchases"
}'
# Find valid accounting categories and options.
curl --request POST \
--url https://api.ramp.com/developer/v1/agent-tools/get-tracking-categories \
--header "Authorization: Bearer $RAMP_AGENT_ACCESS_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"transaction_uuid": "<transaction-id>",
"rationale": "List required accounting categories"
}'
curl --request POST \
--url https://api.ramp.com/developer/v1/agent-tools/get-tracking-category-options \
--header "Authorization: Bearer $RAMP_AGENT_ACCESS_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"tracking_category_uuid": "<category-id>",
"transaction_uuid": "<transaction-id>",
"query_string": "<option-name-or-code>",
"page_size": 10,
"rationale": "List accounting options"
}'# Add the memo and accounting selections.
curl --request POST \
--url https://api.ramp.com/developer/v1/agent-tools/edit-transaction \
--header "Authorization: Bearer $RAMP_AGENT_ACCESS_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"transaction_uuid": "<transaction-id>",
"memo": "<purchase-purpose>",
"tracking_category_selections": [
{
"category_uuid": "<category-id>",
"option_selection": "<option-id>"
}
],
"user_submitted_fields": [],
"rationale": "Complete the approved purchase record"
}'# Attach the receipt.
curl --request POST \
--url https://api.ramp.com/developer/v1/agent-tools/upload-receipt-file \
--header "Authorization: Bearer $RAMP_AGENT_ACCESS_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"filename": "<receipt-filename>",
"content_type": "<mime-type>",
"file_content_base64": "<base64-receipt-content>",
"transaction_uuid": "<transaction-id>",
"rationale": "Attach the purchase receipt"
}'# Verify that no required items remain.
curl --request POST \
--url https://api.ramp.com/developer/v1/agent-tools/get-transaction-missing-items \
--header "Authorization: Bearer $RAMP_AGENT_ACCESS_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"id": "<transaction-id>",
"rationale": "Verify the purchase record is complete"
}'
unset RAMP_AGENT_ACCESS_TOKEN# Find every page of posted transactions.
ramp --profile agent --agent transactions list \
--transactions_to_retrieve my_transactions \
--page_size 50 \
--rationale "Find the posted transaction"
# Repeat with each cursor returned in pagination.next_cursor.
ramp --profile agent --agent transactions list \
--transactions_to_retrieve my_transactions \
--next_page_cursor "<next-page-cursor>" \
--page_size 50 \
--rationale "Find the next page of posted transactions"
# Add the memo and find valid accounting values.
ramp --profile agent --agent transactions edit "<transaction-id>" \
--memo "<purchase-purpose>" \
--rationale "Add the purchase memo"
ramp --profile agent --agent accounting categories \
--transaction_uuid "<transaction-id>" \
--rationale "List required accounting categories"
ramp --profile agent --agent accounting category-options "<category-id>" \
--transaction_uuid "<transaction-id>" \
--query_string "<option-name-or-code>" \
--page_size 10 \
--rationale "List accounting options"
# Add the accounting selections.
ramp --profile agent --agent transactions edit --json '{
"transaction_uuid": "<transaction-id>",
"tracking_category_selections": [
{
"category_uuid": "<category-id>",
"option_selection": "<option-id>"
}
],
"user_submitted_fields": [],
"rationale": "Complete transaction accounting"
}'
# Attach the receipt and verify that nothing is missing.
receipt_path="/path/to/receipt.pdf"
receipt_base64="$(base64 < "$receipt_path" | tr -d '\r\n')"
ramp --profile agent --agent receipts upload \
--filename "${receipt_path##*/}" \
--content_type "application/pdf" \
--file_content_base64 "$receipt_base64" \
--transaction_uuid "<transaction-id>" \
--rationale "Attach the purchase receipt"
unset receipt_base64
ramp --profile agent --agent transactions missing "<transaction-id>" \
--rationale "Verify the purchase record is complete"More payment methods
ACH, checks, wires, and crypto-native payment methods are in private preview.
Talk to the team to enable the standalone-agent payment flow for your business.