# RedirX — MCP agent reference > RedirX maps a site's old URLs to new destinations with AI matching through a remote MCP server. Proposals stay in review until the owner confirms them, and only approved mappings are exported as redirect files. This file is the complete agent reference: connection, workflow, limits and exact tool schemas. ## Links - [MCP endpoint](https://redirx-mcp-server.onrender.com/mcp): Streamable HTTP; sign in through the RedirX OAuth broker - [Protected-resource metadata](https://redirx-mcp-server.onrender.com/.well-known/oauth-protected-resource): OAuth discovery for the endpoint - [Agent skill](https://redirx.dev/skill.md): the workflow as an installable Agent Skill; install with `npx skills add https://redirx.dev` - [Benchmark methodology](https://redirx.dev/benchmark.md): how match quality was measured - [RedirX](https://redirx.dev/): product overview and pricing RedirX maps old URLs to new destinations with AI matching. One separate free trial is available without a card. Paid runs and monthly URL allowances use the current billing catalog; only a human completes checkout or explicitly approves extra usage. Existing legacy agreements and historical access remain separate. ## Connect Streamable HTTP: https://redirx-mcp-server.onrender.com/mcp Protected-resource metadata: https://redirx-mcp-server.onrender.com/.well-known/oauth-protected-resource Follow the resource_metadata URL in the 401 WWW-Authenticate challenge, then the advertised authorization server. Use the RedirX OAuth broker, PKCE S256, scope mcp:tools, exact registered redirect URI and advertised resource. Let your MCP client handle sign-in and refresh rotation. A browser session, Google token or raw rdx_ REST key is not an MCP access token. Never ask for passwords or raw credentials. The client opens browser sign-in. Choose Continue to RedirX on the broker screen. If you need an account, choose Sign up on the RedirX login screen; that link preserves the pending consent return. Complete sign-up and any email confirmation, then return to the client sign-in flow and review the requested access. Do not ask the user to give the agent their account password. Call tools/list before acting. If it differs from the schemas below, report the deployment mismatch and stop using these examples. Keep migration_id, run_id, operation_id, revisions and idempotency keys from server responses; never substitute legacy session IDs. ## URL-first workflow 1. plan_migration creates the owned migration. import_inventory saves the supplied URL lists; save one old and one new inventory. Use data.inventory.id only when data.inventory.status is complete. A partial import requires correcting the input. Confirm both inventories are complete before starting. 2. run_migration starts the bounded matching job. Optional confirmed_pairs may contain up to 100 explicitly known old_url/new_url pairs, each present exactly in the corresponding inventory; never fill these from guesses. Save the operation_id; poll get_migration for progress and terminal state. Reuse the same idempotency key after a timeout; do not accidentally start a second job. 3. Page list_matches. Every new proposal starts needs_review. Inspect each row’s proposed target (the jev_proposal field), alternatives, confidence, pass and seed revision. Proposed is not approved. Do not interpret a low score or missing destination as a deletion instruction. 4. Explicitly confirm a destination with resolve_matches set_target and the expected current revision. An approve action does not bypass needs_review. Ask the owner when intent is unclear; preserve confirmed choices separately from model guesses. 5. refine_matches takes migration_id, run_id, expected_seed_revision and idempotency_key. It uses confirmed examples to revisit unresolved rows within the pass limit. A stale revision requires a fresh read, not an automatic retry with invented state. Confirmed mappings stay unchanged. Do not train on unreviewed proposals. 6. export_redirects produces an immutable approved map. A partial export must be explicit; unresolved rows stay out. To download, use the successful export envelope’s migration_id and data.artifact_id to fill the registered URI template redirx://migrations/{migration_id}/artifacts/{artifact_id}, then call MCP resources/read with that uri. Save the returned contents[].text using its mimeType; this is a resource read, not another tools/call or an HTTP fetch of an arbitrary URL. Download and installation are separate actions. Ask for approval before changing a site; do not report redirects live merely because an artifact exists. 7. After installing the artifact in the user's project, verify_redirects checks it: supply either an existing deployment_id, or explicit deployment_confirmation=true with live_origin and origin_rewrites ({} explicitly preserves the artifact's own destinations). Read the returned coverage and destination results; do not report an installation as verified merely because a page opens. This is an HTTP check, not evidence of Google indexing, page canonicals, robots permissions, or sitemap correctness. Incomplete and unchecked URLs still need attention. Export formats name specific integrations: wordpress is CSV for the Redirection plugin; cloudflare is a Cloudflare Pages _redirects file, not Bulk Redirects CSV. Generic csv/json exports are review mappings that need adaptation before installation. A format rejected for an unsupported raw URL must not be replaced by silently normalizing that URL. Read the JSON operation envelope in text content or its equivalent structuredContent. Inspect status, next_action, data, error and any per-row outcomes even when the tool call itself succeeds. A timeout or interrupted connection may leave a mutation committed: read saved state and reuse the same idempotency key for an identical intent. Do not invent a new key to work around an unknown outcome. The harness uses URL text and confirmed examples; it does not fetch page bodies. URL paths are embedded for candidate retrieval and an AI model proposes decisions. RedirX may change the model provider; the workflow and review rules stay the same. Examples and caches stay scoped to the customer's run. There is no automatic 410 decision. Companion/history access remains available. ## Pricing Prices are in US dollars, before tax. Quote from the authenticated billing page or checkout, which are authoritative, and never complete a purchase for the user. - Free trial: one per account, for a first migration of up to 500 old URLs and 2,000 new URLs. No card required. - Pay as you go: $0.02 per old URL, rounded up to the next whole dollar for each purchase, with a $10 minimum. New destination URLs cost nothing extra. - Monthly plans: Studio is $79 per month for 5,000 old URLs; Agency is $199 per month for 15,000 old URLs. Allowances are pooled across migrations and do not roll over. Extra usage costs $0.02 per additional old URL and runs only after explicit approval. - Pricing page: https://redirx.dev/#pricing ## Operating limits The separate trial allows 500 old URLs, 2000 new URLs and 2097152 combined URL bytes, once per account. Paid capacity is 15000 old / 20000 new URLs and 16777216 combined URL bytes, with up to 3 passes within 30 days. Capacity is an admission ceiling, not a throughput promise. Global provider budget and worker concurrency limits still apply; payment does not bypass them. When run_migration returns payment_required, open its server-returned billing_url for the human. Use the verified checkout_id for the exact inventories or an authorized subscription_id. Never set approve_extra_urls without explicit consent to max_extra_amount_cents: this is the TOTAL extra-usage charge for the month after the run, not an incremental charge. Read current prices and remaining allowances from the authenticated billing page. Reuse identical idempotency keys after timeouts. Included retries and refinements do not buy the same URLs again. ## Compatibility The registered schemas below are exactly the nine tools this deployment serves. The legacy Search Console and ongoing-monitoring tools (connect_search_console, manage_monitoring, get_monitoring_status, get_monitoring_fixes) have been withdrawn from this surface, not merely deprioritized — do not call them or describe them as available. verify_redirects checks one installed deployment; it is a required step in the workflow above, not an included recurring monitoring subscription. Preserve existing records and rights; do not start subscriptions or activate monitoring as part of this workflow. Native OAuth compatibility does not certify every named desktop/editor client. An export format does not certify installation on that platform. The landing replay is illustrative; benchmark methodology is at https://redirx.dev/benchmark.md. ## Every call requires a context argument This gateway's analytics instrumentation injects a required `context` string argument into every tool below; it carries no migration state and is not part of any REST body. Its exact requirement, verbatim from the live schema: > Explain why you are calling this tool and how it fits into the user's overall goal. This parameter is used for analytics and user intent tracking. YOU MUST provide 15-25 words (count carefully). NEVER use first person ('I', 'we', 'you') - maintain third-person perspective. NEVER include sensitive information such as credentials, passwords, or personal data. Example (20 words): "Searching across the organization's repositories to find all open issues related to performance complaints and latency issues for team prioritization." ## Without an MCP client Use the REST mappings below only with a separately authorized RedirX API key already configured in the environment. The v2 API verifies that key for its owning account; do not extract a browser session or the gateway’s internal delegation to make this fallback work. The broker's MCP access token is resource-bound and is not a REST credential. Do not paste credentials into chat or commit them. Base origin: https://redirx-api.onrender.com. Send JSON with Authorization: Bearer $REDIRX_REST_TOKEN and Content-Type: application/json. Replace every path parameter with the owned identifier returned by the previous operation. The schemas below describe MCP tool arguments, not REST request bodies. Substitute path parameters into the path and omit them from the body. For GET requests put the remaining supported fields in the query string. For this workflow, plan_migration sends its arguments as JSON; resolve_matches and refine_matches send their non-path arguments; export_redirects keeps run_id in the body because only migration_id is in its path. Two body shapes change: - import_inventory: POST /api/v2/migrations/{migration_id}/inventories with {"side":"old","rows":["https://old.example/page"],"idempotency_key":"import-old-1"}. MCP calls use urls; this REST body uses rows. Import the new side separately with its own key. - run_migration: POST /api/v2/migrations/{migration_id}/runs with {"inventory_ids":{"old":"","new":""},"idempotency_key":"run-1"}. Replace both placeholders with completed inventory IDs. Optional confirmed_pairs has the same array shape as MCP; omit payment fields for the trial; paid runs may pass the verified checkout_id or authorized subscription_id and explicitly approved extra-usage fields. Do not send old_inventory_id or new_inventory_id as top-level REST fields. A 401 requires REST reauthorization; it is not a reason to retry the MCP token. Read the envelope's status, next_action, operation_id, progress, data and error. A queued response is not completion. Follow get_migration's method/path to poll the saved operation. Preserve idempotency keys across interrupted requests and current revisions across explicit review decisions. All applicable limits and approval rules above apply identically. The injected context argument above is an MCP-only analytics field; never add it to a REST body. ## Tool schemas These schemas were captured through native MCP tools/list from the registered gateway source, instrumented exactly as production serves it. ### plan_migration Create an owned old-site/new-site plan. Next call import_inventory for the old and new URL lists; planning does not crawl or run the model. REST: POST /api/v2/migrations ```json { "type": "object", "properties": { "old_site": { "type": "string", "minLength": 1, "maxLength": 8192, "description": "Origin of existing source pages, e.g. https://old.example; no page path, query, fragment or credentials." }, "new_site": { "type": "string", "minLength": 1, "maxLength": 8192, "description": "Origin of available destination pages, e.g. https://new.example; no page path, query, fragment or credentials." }, "name": { "type": "string", "maxLength": 200 }, "site_aliases": { "description": "Additional explicitly allowed origins per side. Declare www or staging origins here before importing; aliases are not inferred.", "type": "object", "properties": { "old": { "maxItems": 100, "type": "array", "items": { "type": "string", "maxLength": 8192 } }, "new": { "maxItems": 100, "type": "array", "items": { "type": "string", "maxLength": 8192 } } } }, "idempotency_key": { "type": "string", "minLength": 1, "maxLength": 200, "pattern": "^[^\\x00-\\x1f\\x7f]+$" }, "context": { "type": "string", "description": "Explain why you are calling this tool and how it fits into the user's overall goal. This parameter is used for analytics and user intent tracking. YOU MUST provide 15-25 words (count carefully). NEVER use first person ('I', 'we', 'you') - maintain third-person perspective. NEVER include sensitive information such as credentials, passwords, or personal data. Example (20 words): \"Searching across the organization's repositories to find all open issues related to performance complaints and latency issues for team prioritization.\"" } }, "required": [ "old_site", "new_site", "idempotency_key", "context" ], "$schema": "http://json-schema.org/draft-07/schema#" } ``` ### import_inventory Import explicit HTTP(S) URL strings into an owned immutable old or new inventory. No crawl or page scraping. Use data.inventory.id only when data.inventory.status is complete for run_migration; partial imports need corrected input and a new key. The free trial allows 500 old / 2000 new URLs and 2 MiB total URL text. When paid billing is enabled, paid runs allow 15000 old / 20000 new URLs and 16 MiB total. Importing never authorizes a charge. REST: POST /api/v2/migrations/{migration_id}/inventories ```json { "type": "object", "properties": { "migration_id": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, "side": { "type": "string", "enum": [ "old", "new" ], "description": "old = existing source pages; new = available destination pages." }, "urls": { "minItems": 1, "maxItems": 20000, "type": "array", "items": { "type": "string", "maxLength": 8192, "pattern": "^https?:\\/\\/" }, "description": "Actual absolute page URLs, not a sitemap file URL. Preserve path case, escapes and query strings. Complete validates this supplied list, not full site coverage or reachability." }, "idempotency_key": { "type": "string", "minLength": 1, "maxLength": 200, "pattern": "^[^\\x00-\\x1f\\x7f]+$" }, "context": { "type": "string", "description": "Explain why you are calling this tool and how it fits into the user's overall goal. This parameter is used for analytics and user intent tracking. YOU MUST provide 15-25 words (count carefully). NEVER use first person ('I', 'we', 'you') - maintain third-person perspective. NEVER include sensitive information such as credentials, passwords, or personal data. Example (20 words): \"Searching across the organization's repositories to find all open issues related to performance complaints and latency issues for team prioritization.\"" } }, "required": [ "migration_id", "side", "urls", "idempotency_key", "context" ], "$schema": "http://json-schema.org/draft-07/schema#" } ``` ### run_migration Run URL matching from immutable inventories. When current billing is enabled, the separate free trial allows 500 old URLs; paid purchases or monthly allowances support 15000 old / 20000 new URLs. Payment-required responses provide a browser billing link. Only a human completes checkout. Pass its verified checkout_id for a one-time purchase or select a subscription_id. Never approve extra URLs without explicit user consent to max_extra_amount_cents, the TOTAL extra-usage charge for this month after this run, not an incremental charge. Included retries and refinements do not buy URLs again. confirmed_pairs must be explicitly verified examples, never guesses. REST: POST /api/v2/migrations/{migration_id}/runs ```json { "type": "object", "properties": { "migration_id": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, "old_inventory_id": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, "new_inventory_id": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, "quote_id": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, "checkout_id": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, "subscription_id": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, "approve_extra_urls": { "type": "boolean" }, "max_extra_amount_cents": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "confirmed_pairs": { "maxItems": 100, "type": "array", "items": { "type": "object", "properties": { "old_url": { "type": "string", "maxLength": 8192, "format": "uri" }, "new_url": { "type": "string", "maxLength": 8192, "format": "uri" } }, "required": [ "old_url", "new_url" ] } }, "idempotency_key": { "type": "string", "minLength": 1, "maxLength": 200, "pattern": "^[^\\x00-\\x1f\\x7f]+$" }, "context": { "type": "string", "description": "Explain why you are calling this tool and how it fits into the user's overall goal. This parameter is used for analytics and user intent tracking. YOU MUST provide 15-25 words (count carefully). NEVER use first person ('I', 'we', 'you') - maintain third-person perspective. NEVER include sensitive information such as credentials, passwords, or personal data. Example (20 words): \"Searching across the organization's repositories to find all open issues related to performance complaints and latency issues for team prioritization.\"" } }, "required": [ "migration_id", "old_inventory_id", "new_inventory_id", "idempotency_key", "context" ], "$schema": "http://json-schema.org/draft-07/schema#" } ``` ### refine_matches Resume a paused matching pass, or improve unresolved URL mappings with explicitly confirmed examples. Up to three total passes; does not consume another free migration. Read data.jev.seed_revision from get_migration first. If paused, honor retry_after_seconds and resolve the reported pause reason before resuming. REST: POST /api/v2/migrations/{migration_id}/runs/{run_id}/refine ```json { "type": "object", "properties": { "migration_id": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, "run_id": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, "expected_seed_revision": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "idempotency_key": { "type": "string", "minLength": 1, "maxLength": 200, "pattern": "^[^\\x00-\\x1f\\x7f]+$" }, "context": { "type": "string", "description": "Explain why you are calling this tool and how it fits into the user's overall goal. This parameter is used for analytics and user intent tracking. YOU MUST provide 15-25 words (count carefully). NEVER use first person ('I', 'we', 'you') - maintain third-person perspective. NEVER include sensitive information such as credentials, passwords, or personal data. Example (20 words): \"Searching across the organization's repositories to find all open issues related to performance complaints and latency issues for team prioritization.\"" } }, "required": [ "migration_id", "run_id", "expected_seed_revision", "idempotency_key", "context" ], "$schema": "http://json-schema.org/draft-07/schema#" } ``` ### get_migration Read an owned migration summary and its next recoverable action. Retain migration_id and run_id across reconnects. Poll only after retry_after_seconds; a completed run still requires explicit review before export. REST: GET /api/v2/migrations/{migration_id} ```json { "type": "object", "properties": { "migration_id": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, "run_id": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, "operation_id": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, "context": { "type": "string", "description": "Explain why you are calling this tool and how it fits into the user's overall goal. This parameter is used for analytics and user intent tracking. YOU MUST provide 15-25 words (count carefully). NEVER use first person ('I', 'we', 'you') - maintain third-person perspective. NEVER include sensitive information such as credentials, passwords, or personal data. Example (20 words): \"Searching across the organization's repositories to find all open issues related to performance complaints and latency issues for team prioritization.\"" } }, "required": [ "migration_id", "context" ], "$schema": "http://json-schema.org/draft-07/schema#" } ``` ### list_matches Read owned match exceptions in stable traffic order. Follow data.next_cursor until null using the same run and filter; one page is not the whole run. Retain each mapping revision and data.selection_revision for review/export. Traffic absence is distinct from observed zero. Confidence is an uncalibrated model estimate, never approval. REST: GET /api/v2/migrations/{migration_id}/runs/{run_id}/matches ```json { "type": "object", "properties": { "migration_id": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, "run_id": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, "filter": { "default": "all", "type": "string", "enum": [ "all", "needs_review", "unmatched", "approved", "rejected" ] }, "cursor": { "type": "string", "maxLength": 4096 }, "limit": { "default": 100, "type": "integer", "minimum": 1, "maximum": 500 }, "context": { "type": "string", "description": "Explain why you are calling this tool and how it fits into the user's overall goal. This parameter is used for analytics and user intent tracking. YOU MUST provide 15-25 words (count carefully). NEVER use first person ('I', 'we', 'you') - maintain third-person perspective. NEVER include sensitive information such as credentials, passwords, or personal data. Example (20 words): \"Searching across the organization's repositories to find all open issues related to performance complaints and latency issues for team prioritization.\"" } }, "required": [ "migration_id", "run_id", "context" ], "$schema": "http://json-schema.org/draft-07/schema#" } ``` ### resolve_matches Apply audited, optimistic-concurrency decisions. To confirm a model-proposed target, use set_target with target_url, mapping_id and expected_revision after explicit user approval. Inspect every returned outcome: a batch can partially fail. On revision conflicts, reread matches and reassess the decision. Model predictions are never automatically verified examples. REST: PATCH /api/v2/migrations/{migration_id}/runs/{run_id}/matches ```json { "type": "object", "properties": { "migration_id": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, "run_id": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, "idempotency_key": { "type": "string", "minLength": 1, "maxLength": 200, "pattern": "^[^\\x00-\\x1f\\x7f]+$" }, "decisions": { "minItems": 1, "maxItems": 100, "type": "array", "items": { "type": "object", "properties": { "mapping_id": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, "expected_revision": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "action": { "type": "string", "enum": [ "accept_repair", "set_target", "approve", "reject", "defer", "intentional_removal" ] }, "target_url": { "type": "string", "minLength": 1, "maxLength": 8192 }, "rationale": { "type": "string", "maxLength": 2000 } }, "required": [ "mapping_id", "expected_revision", "action" ] } }, "context": { "type": "string", "description": "Explain why you are calling this tool and how it fits into the user's overall goal. This parameter is used for analytics and user intent tracking. YOU MUST provide 15-25 words (count carefully). NEVER use first person ('I', 'we', 'you') - maintain third-person perspective. NEVER include sensitive information such as credentials, passwords, or personal data. Example (20 words): \"Searching across the organization's repositories to find all open issues related to performance complaints and latency issues for team prioritization.\"" } }, "required": [ "migration_id", "run_id", "idempotency_key", "decisions", "context" ], "$schema": "http://json-schema.org/draft-07/schema#" } ``` ### export_redirects Create an immutable artifact from explicitly approved decisions. Use data.selection_revision from the latest review response as revision. allow_partial requires explicit agreement to exclusions. Export does not install redirects. Large downloads are returned only as backend-authorized artifact resources; this gateway never follows arbitrary URLs. REST: POST /api/v2/migrations/{migration_id}/artifacts ```json { "type": "object", "properties": { "migration_id": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, "run_id": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, "format": { "type": "string", "enum": [ "apache", "nginx", "wordpress", "vercel", "cloudflare", "shopify", "csv", "json" ], "description": "wordpress is Redirection plugin CSV; cloudflare is Pages _redirects, not Bulk Redirects CSV. csv and json are generic review mappings that need adaptation before installation." }, "revision": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "allow_partial": { "default": false, "type": "boolean" }, "idempotency_key": { "type": "string", "minLength": 1, "maxLength": 200, "pattern": "^[^\\x00-\\x1f\\x7f]+$" }, "context": { "type": "string", "description": "Explain why you are calling this tool and how it fits into the user's overall goal. This parameter is used for analytics and user intent tracking. YOU MUST provide 15-25 words (count carefully). NEVER use first person ('I', 'we', 'you') - maintain third-person perspective. NEVER include sensitive information such as credentials, passwords, or personal data. Example (20 words): \"Searching across the organization's repositories to find all open issues related to performance complaints and latency issues for team prioritization.\"" } }, "required": [ "migration_id", "run_id", "format", "revision", "idempotency_key", "context" ], "$schema": "http://json-schema.org/draft-07/schema#" } ``` ### verify_redirects Start or resume an owned artifact HTTP check. Supply an existing deployment_id, or explicitly confirm installation with live_origin and origin_rewrites ({} preserves artifact destinations). This does not install rules or establish Google indexing, page canonicals, robots permissions, or sitemap correctness. Inspect incomplete and unchecked results before claiming success. REST: POST /api/v2/migrations/{migration_id}/verifications ```json { "type": "object", "properties": { "migration_id": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, "artifact_id": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, "deployment_id": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, "deployment_confirmation": { "type": "boolean", "const": true }, "live_origin": { "type": "string", "minLength": 1, "maxLength": 2048 }, "origin_rewrites": { "type": "object", "propertyNames": { "type": "string", "minLength": 1, "maxLength": 2048 }, "additionalProperties": { "type": "string", "minLength": 1, "maxLength": 2048 } }, "idempotency_key": { "type": "string", "minLength": 1, "maxLength": 200, "pattern": "^[^\\x00-\\x1f\\x7f]+$" }, "context": { "type": "string", "description": "Explain why you are calling this tool and how it fits into the user's overall goal. This parameter is used for analytics and user intent tracking. YOU MUST provide 15-25 words (count carefully). NEVER use first person ('I', 'we', 'you') - maintain third-person perspective. NEVER include sensitive information such as credentials, passwords, or personal data. Example (20 words): \"Searching across the organization's repositories to find all open issues related to performance complaints and latency issues for team prioritization.\"" } }, "required": [ "migration_id", "artifact_id", "idempotency_key", "context" ], "$schema": "http://json-schema.org/draft-07/schema#" } ``` ## Optional - [Privacy policy](https://redirx.dev/privacy) - [Terms of service](https://redirx.dev/terms)