# BOP Share Machine Gateway — Complete Integration Guide for AI Agents > Product Identity: Temporary file delivery infrastructure for humans and AI agents. > Philosophy: Create artifact → BOP → Deliver → Done. > Canonical Base URL: https://share.bop.ink > API Version: v1 > Content-Type: text/plain; charset=utf-8 --- ## 1. PRODUCT PURPOSE & ARCHITECTURE BOP Share is a zero-friction, ephemeral file delivery bridge. It solves ONE job for AI agents: "An agent creates or possesses an artifact (PDF, image, spreadsheet, archive, document) and needs to deliver it temporarily to a human user." ### The Core Lifecycle: 1. Agent generates artifact. 2. Agent calls BOP Machine Gateway to request a delivery slot. 3. BOP allocates an opaque transfer key (`f_`) and generates a short-lived presigned S3 upload URL. 4. Agent uploads binary bytes to the presigned URL using HTTP PUT. 5. BOP provides a human-facing receiver URL (e.g. `https://share.bop.ink/d/f_4a8b9c0d1e2f`). 6. Agent returns this receiver URL to the human user. 7. Human downloads or previews the file in their browser. 8. File automatically and permanently self-destructs after the designated expiry period (1 to 7 days). ### What BOP Share is NOT: - NOT permanent cloud storage or Google Drive / Dropbox alternative. - NOT an account or project management SaaS (no users, no logins, no API keys). - NOT a public CDN or static asset host. - NOT a permanent file repository. --- ## 2. OPERATIONAL BOUNDARIES & LIMITS | Property | Machine Gateway Policy | Human Web Interface Policy | |---|---|---| | Maximum File Size | 50 MiB (52,428,800 bytes) | 100 MiB (104,857,600 bytes) | | Default Expiry | 1 day (24 hours) | 3 days (72 hours) | | Minimum Expiry | 1 day | 1 day | | Maximum Expiry | 7 days | 7 days | | Upload Presign TTL | 15 minutes (900 seconds) | 15 minutes (900 seconds) | | Rate Limit | 15 creations / minute per IP | 10 uploads / minute per IP | | Storage Privacy | Private S3 bucket, no public listing | Private S3 bucket, no public listing | | Client Authentication | None required (capability-based receiver URL) | None required | ### 2.1. Encryption Model & Vault Distinction - **Machine Gateway & Standard Transfers:** Data is encrypted in transit via standard TLS/HTTPS. Files are stored as private objects in S3-compatible cloud storage. This is NOT end-to-end encrypted. Machine agents should NOT attempt to run client-side WebCrypto key derivations. - **Human Web Vault:** Optional human browser client-side zero-knowledge encryption using WebCrypto AES-GCM 256-bit where keys are derived in local browser RAM. The Machine Gateway operates purely on standard transfers. ### 2.2. Expiry Semantics & Destruction Lifecycle - **Logical Expiry (Authoritative):** The transfer record specifies an authoritative `expiresAt` timestamp. The moment `Date.now() >= expiresAt`, access is immediately cut off, and any download attempt returns HTTP 410 Gone, regardless of whether background storage deletion has completed. - **Physical Deletion:** Stored objects are removed via scheduled lifecycle policies and opportunistic cleanup routines. - **Early Revocation:** Calling the revoke endpoint with the confidential `revocationToken` immediately invalidates the transfer record and initiates destruction of the stored object. --- ## 3. HTTP REST API (VERSION 1) ### 3.1. Flow 1: Two-Step Direct S3 Presigned Upload (Recommended for all agents) #### Step 1: Create Transfer Slot - **Endpoint:** `POST https://share.bop.ink/api/v1/transfers` - **Headers:** `Content-Type: application/json` - **Request Body:** ```json { "filename": "summary_report.pdf", "contentType": "application/pdf", "fileSizeBytes": 1048576, "expiryDays": 1 } ``` - **Success Response (201 Created):** ```json { "success": true, "transfer": { "id": "f_4a8b9c0d1e2f", "fileKey": "d/f_4a8b9c0d1e2f", "url": "https://share.bop.ink/d/f_4a8b9c0d1e2f", "filename": "summary_report.pdf", "contentType": "application/pdf", "sizeBytes": 1048576, "expiresAt": 1741234567890, "expiresAtIso": "2026-09-03T18:00:00.000Z", "status": "pending_upload" }, "upload": { "method": "PUT", "url": "https://s3.cloudfly.vn/sharebopink/d/f_4a8b9c0d1e2f?X-Amz-Algorithm=...", "expiresInSeconds": 900, "headers": { "Content-Type": "application/pdf" } }, "revocation": { "token": "del_sec_a1b2c3d4e5f6", "revokeUrl": "https://share.bop.ink/api/v1/transfers/f_4a8b9c0d1e2f/revoke" } } ``` #### Step 2: Upload Binary Bytes Directly to S3 The agent performs an HTTP PUT directly to `upload.url` with raw binary bytes: ```bash curl -X PUT "https://s3.cloudfly.vn/sharebopink/d/f_4a8b9c0d1e2f?..." \ -H "Content-Type: application/pdf" \ --data-binary "@summary_report.pdf" ``` #### Step 3 (Optional but recommended): Finalize Transfer - **Endpoint:** `POST https://share.bop.ink/api/v1/transfers/f_4a8b9c0d1e2f/finalize` - Verifies that the file was written to S3 and enforces that the actual size is <= 50MB. - **Success Response (200 OK):** ```json { "success": true, "transfer": { "id": "f_4a8b9c0d1e2f", "receiverUrl": "https://share.bop.ink/d/f_4a8b9c0d1e2f", "sizeBytes": 1048576, "expiresAt": 1741234567890, "expiresAtIso": "2026-09-03T18:00:00.000Z", "status": "active" } } ``` #### Step 4: Return Link to User Present the receiver URL to the human: "Here is your file: https://share.bop.ink/d/f_4a8b9c0d1e2f (link self-destructs in 24 hours)." --- ### 3.2. Flow 2: Single-Step Multipart Direct Upload If your agent environment supports multipart form upload, you can upload in a single HTTP request: ```bash curl -X POST "https://share.bop.ink/api/v1/transfers" \ -F "file=@generated_chart.png;type=image/png" \ -F "filename=generated_chart.png" \ -F "expiryDays=1" ``` Response will immediately contain the activated `transfer.url`. --- ### 3.3. Check Transfer Status - **Endpoint:** `GET https://share.bop.ink/api/v1/transfers/{fileKey}` - Returns metadata, expiry time, and preview eligibility. - Does not expose secret revocation tokens. --- ### 3.4. Revoke Transfer (Early Deletion) - **Endpoint:** `POST https://share.bop.ink/api/v1/transfers/{fileKey}/revoke` - **Headers:** `Content-Type: application/json` - **Body:** `{ "token": "del_sec_a1b2c3d4e5f6" }` (or header `Authorization: Bearer del_sec_a1b2c3d4e5f6`) - Destroys the object immediately in S3. --- ## 4. MODEL CONTEXT PROTOCOL (MCP) INTEGRATION BOP Share implements an MCP Server following the modern Model Context Protocol specification. - **MCP Endpoint:** `https://share.bop.ink/api/mcp` - **Transport:** Stateless HTTP Request/Response (JSON-RPC 2.0) - **Protocol Version:** 2026-07-28 - **Headers Supported:** `MCP-Protocol-Version: 2026-07-28` (standard) and `Mcp-Version: 2026-07-28` (alias), `Mcp-Method`, `Mcp-Name` - **Session Model:** 100% Stateless over HTTP. No persistent sessions or sticky connections required. ### Tools Exposed: 1. **create_temporary_transfer** - `filename` (string, required): Name of the file with extension. - `contentType` (string, optional): MIME type. - `fileSizeBytes` (integer, optional): Size in bytes (max 50 MiB = 52,428,800 bytes). - `expiryDays` (integer, optional): 1 to 7 days (default 1). - Returns: uploadUrl (PUT target) + receiverUrl (to give to user). 2. **finalize_temporary_transfer** - `fileKey` (string, required): The transfer key from creation. - Returns: Confirmed active status and verified size. 3. **revoke_temporary_transfer** - `fileKey` (string, required) - `revocationToken` (string, required) - Returns: Revocation confirmation. ### Configuration for Claude Desktop / Cursor: Add to your `claude_desktop_config.json` or MCP config: ```json { "mcpServers": { "bop-share": { "url": "https://share.bop.ink/api/mcp" } } } ``` --- ## 5. WEBMCP (BROWSER-NATIVE AGENT INTERACTION) Status: Experimental Community Group Draft incubated by the W3C Web Machine Learning Community Group. For AI agents running directly inside compatible browser environments with WebMCP support: BOP Share registers browser-level tools via `document.modelContext`: - `bop_get_page_context`: Reads current active transfer status and limits. - `bop_create_browser_transfer`: Triggers an upload slot from in-browser generated data. WebMCP is implemented strictly as progressive enhancement with AbortSignal cleanup. If unsupported, the human web interface operates normally with zero errors. --- ## 6. STANDARDS STATUS & TRUTHFUL DISCLOSURES | Standard | Ecosystem Authority | Specification Version | Status in BOP Share | |---|---|---|---| | HTTP REST API | BOP Share | v1 | Public machine API | | Model Context Protocol (MCP) | Model Context Protocol / Anthropic | 2026-07-28 | Stateless HTTP JSON-RPC 2.0 Server | | WebMCP | W3C Web Machine Learning CG | Community Draft | Progressive Enhancement (`document.modelContext`) | | llms.txt | Answer.AI / Jeremy Howard | Community Convention | Plain text site summary for LLMs | | llms-full.txt | LLMs Ecosystem | Community Convention | Full technical integration reference | | OpenAPI | OpenAPI Initiative (Linux Foundation) | 3.1.0 | Machine-readable REST schema at `/openapi.json` | --- ## 7. ERROR CODES REFERENCE All machine endpoints return structured errors: ```json { "error": { "code": "FILE_TOO_LARGE", "message": "File size exceeds machine limit of 50 MiB (52428800 bytes).", "retryable": false } } ``` | Code | HTTP Status | Description | Retryable | |---|---|---|---| | GATEWAY_DISABLED | 503 | Operator has temporarily disabled machine intake | No | | SERVICE_MAINTENANCE | 503 | Server maintenance in progress | Yes | | RATE_LIMITED | 429 | Rate limit exceeded (15 req/min) | Yes (after retry-after) | | INVALID_PAYLOAD | 400 | Malformed JSON or missing required fields | No | | FILE_TOO_LARGE | 413 | Size exceeds 50 MiB (52428800 bytes) | No | | INVALID_TRANSFER_KEY | 400 | Key format rejected (must match f_*) | No | | TRANSFER_NOT_FOUND | 404 | Object does not exist in storage | No | | TRANSFER_EXPIRED | 410 | File reached scheduled expiry | No | | UPLOAD_NOT_COMPLETED | 404 | Finalize called before binary upload finished | Yes | | UNAUTHORIZED_REVOCATION | 401/403 | Missing or invalid revocation token | No | | STORAGE_ERROR | 500 | Storage backend error | Yes | --- ## 8. CODE EXAMPLES ### Python Example ```python import requests def share_artifact(filename, file_bytes, content_type="application/pdf"): # 1. Request transfer slot init_res = requests.post("https://share.bop.ink/api/v1/transfers", json={ "filename": filename, "contentType": content_type, "fileSizeBytes": len(file_bytes), "expiryDays": 1 }).json() if not init_res.get("success"): raise Exception(f"Failed to create transfer: {init_res}") upload_url = init_res["upload"]["url"] receiver_url = init_res["transfer"]["url"] # 2. Upload binary bytes put_res = requests.put(upload_url, data=file_bytes, headers={"Content-Type": content_type}) put_res.raise_for_status() # 3. Return receiver URL return receiver_url # Usage: # url = share_artifact("report.pdf", pdf_bytes) # print("Deliver this link to the user:", url) ``` ### Node.js / TypeScript Example ```typescript async function shareArtifact(filename: string, fileBuffer: Buffer, contentType = 'application/pdf') { // 1. Create slot const res = await fetch('https://share.bop.ink/api/v1/transfers', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ filename, contentType, fileSizeBytes: fileBuffer.length, expiryDays: 1 }), }); const data = await res.json(); if (!data.success) throw new Error(data.error?.message || 'Failed to create transfer'); // 2. Upload binary const putRes = await fetch(data.upload.url, { method: 'PUT', headers: { 'Content-Type': contentType }, body: fileBuffer, }); if (!putRes.ok) throw new Error('Failed to upload file bytes to S3'); // 3. Deliver receiver URL return data.transfer.url; } ``` --- ## 9. SUMMARY FOR AGENTS When asked by a user for an artifact: 1. Generate the artifact. 2. Call `POST https://share.bop.ink/api/v1/transfers` with filename & size. 3. PUT the binary bytes to `upload.url`. 4. Reply to the user with `transfer.url`. 5. Done.