---
title: "Send a tip via JSON body (recommended for bots/integrations)"
method: POST
path: "/v1/tip"
tags: ["tipping"]
---

# Send a tip via JSON body (recommended for bots/integrations)

`POST /v1/tip`

Send a tip using a JSON request body. **Recommended for programmatic access**, bots, and integrations that need to track social graph context.

## Social Graph Context

The optional `context` field allows you to attach attribution metadata to tips:

| Field | Description | Example |
|-------|-------------|--------|
| `source_post_url` | URL where the tip was triggered | `https://x.com/user/status/123` |
| `sender_username` | Tipper's username | `olshansky` |
| `sender_profile_url` | Tipper's profile URL | `https://x.com/olshansky` |
| `sender_platform` | Platform enum | `x`, `discord`, `telegram`, etc. |
| `recipient_username` | Recipient's username | `vitalik` |
| `campaign` | Campaign/bot identifier | `grove-twitter-bot-v1` |
| `referrer` | Referrer identifier | `twitter-bot` |
| `custom_metadata` | Free-form string (max 250 chars) | `{"note": "great work!"}` |

## Supported Platforms

`x`, `reddit`, `github`, `tiktok`, `substack`, `youtube`, `discord`,
`telegram`, `farcaster`, `lens`, `other`

## Metadata Storage

Context is stored in the tip's `metadata_json` under a nested `context` key with `ctx_` prefixed fields, preserving separation from auto-resolved metadata (like `x_username` from destination resolution).

## Headers

- `authorization` string, nullable — Bearer JWT that identifies the sending account. - **Required** for all tipping calls - Format: `Bearer <jwt_token>` - Obtain JWT from `/v1/fund` after funding your account

## Request body

- TipRequest — Request body for JSON-based tipping via POST /v1/tip. Supports optional social graph context for attribution tracking.
  - `destination` string, required — Who to tip. Accepts multiple formats: - **Grove handle**: `@olshansky` or `olshansky` (resolves via Grove account) - **EVM address**: `0x9ab39B84aC4DE6D705C5f051c07db8fE72890953` - **Solana address**: `9kucRUCUiYwJLDBBi5GXb4KeqgiRZ6uJeMdLwAuV6pUC` - **ENS name**: `vitalik.eth` (resolved via Ethereum mainnet) - **Domain**: `olshansky.info` (looks up address from llms.txt) - **Twitter/X**: `x.com/olshansky` (looks up address from bio)
  - `amount` string, required — Amount to tip. Supports multiple formats: - **Plain number**: `0.01` (uses token from query or DEFAULT_TOKEN) - **With currency**: `100USDC`, `0.5ETH` - **Dollar prefix**: `$1` (interpreted as 1 USDC)
  - `network` string, nullable — Target blockchain network. Examples: `base`, `base-sepolia`, `solana-devnet`. Defaults to DEFAULT_NETWORK (base) if not specified.
  - `token` string, nullable — Token symbol to tip. Examples: `USDC`, `ETH`. Defaults to DEFAULT_TOKEN (USDC) if not specified. **Note**: If amount includes a token (e.g., `100USDC`) and this field specifies a different token, the request fails with 400.
  - `context` TipContext — Optional social graph context for tip attribution (API request model). Used in TipRequest.context and as query params in the tip endpoint. Lives in models/api.py because it defines API schema, not business logic. Captures: - Where the tip originated (source post URL) - Who sent the tip (sender's social identity) - Additional recipient context - Campaign/attribution tracking
    - `source_post_url` string, nullable — URL of the post/tweet where this tip was triggered
    - `sender_username` string, nullable — Sender's username on the social platform
    - `sender_platform` 'x' | 'twitter' | 'reddit' | 'github' | 'tiktok' | 'discord' | 'telegram' | 'farcaster' | 'lens' | 'substack' | 'youtube' | 'website' | 'instagram' | 'linkedin' | 'medium' | 'soundcloud' | 'twitch' | 'bluesky' | 'facebook' | 'spotify' | 'pinterest' | 'patreon' | 'grove' | 'other' | 'custom' — Social platforms for context attribution in tips. This enum defines WHERE a tip originated from (the sender's platform context), not where the tip is going. For destination types, see DestinationKind. Used in TipContext to track: - sender_platform: Which platform the tipper used (Twitter bot, Discord bot, etc.) - Attribution/analytics for understanding tip sources Note: "x" is the canonical name for Twitter/X. Both "x" and "twitter" are accepted on input, but "x" is used for storage and output. Use normalize_platform() to convert "twitter" → "x". Inherits from str so values serialize naturally to JSON.
    - `sender_profile_url` string, nullable — URL to the sender's profile
    - `recipient_username` string, nullable — Recipient's username on the social platform
    - `recipient_profile_url` string, nullable — URL to the recipient's profile
    - `campaign` string, nullable — Campaign or initiative identifier
    - `referrer` string, nullable — Referrer or source identifier
    - `custom_metadata` string, nullable — Custom metadata string (max 250 characters)
    - `discrete_giveaway_id` string, nullable — Giveaway UUID when this tip is an explicit, user-driven entry via the /giveaways page or a profile's giveaway card. Server-validated. Omit for regular tips (incidental giveaway enrollment still happens automatically for eligible tips — this flag is only about user intent).

## Response `200`

Successful Response

- TipResponse — Response model for successful tip
  - `tip_id` string, required
  - `status` string, required
  - `destination` string, required
  - `from_address` string, required
  - `receiver_address` string, required
  - `amount_sent` string, required
  - `amount_received` string, required
  - `fee_amount` string, required
  - `tx_hash` string, required
  - `new_balance` string, required
  - `network` string, required

## Other responses

- `422` — Validation Error

---

[API](https://skmtc.net/grove/apis/grove-api.md) · [All operations](https://skmtc.net/grove/apis/grove-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/grove/grove-api/revisions/f286b48a8105/schema)
