# PinglyMCP developer reference Human documentation: https://pinglymcp.com/docs REST base: https://api.pinglymcp.com MCP Streamable HTTP endpoint: https://mcp.pinglymcp.com OAuth authorization server: https://auth.pinglymcp.com Authenticate with Authorization: Bearer pmcp_... or an OAuth access token. Personal keys are shown once; keep them secret. OAuth requires the correct resource audience and api:access or mcp:access scope, with billing scopes for billing. Public documentation is accessible without login; service calls require authentication. GET /services returns the shared catalog. Do not automatically repeat contact_website after an unconfirmed external submission. ## ping REST: POST /ping Check public IPv4 addresses, IPv6 addresses, and domain names for network reachability. Costs 0 credits. - target (string, required): Public IPv4 address, IPv6 address, or domain name to check. Example arguments: { "target": "example.com" } Response: Success returns ok, data.request, data.ping, and meta. Errors use stable product codes, retry guidance, and a request ID. ## describe_website REST: POST /website/describe Render a public website, capture its viewport before AI analysis, and return a description, screenshot URL, and visible navigation links. Costs 1 credits. - url (string, required): Public HTTP(S) website URL to render and describe. - instruction (string, optional): Optional focus for the visual description. Example arguments: { "url": "https://example.com", "instruction": "Focus on the navigation and primary call to action." } Response: Success returns ok, data.request, data.page (requested/resolved URLs, title, screenshot), data.analysis, data.content, data.navigation, and meta. The screenshot URL is public to anyone with the link and expires after seven days. data.page.screenshot is null if capture or storage fails. data.navigation.links contains up to 12 visible links; data.navigation is null if the scan fails. Links are reported, not visited. Errors return ok: false, error (code, message, retryable, optional details), and meta. ## contact_website REST: POST /contacts/send Contact a website owner from a public URL by email or contact form, with optional AI-assistance for difficult form workflows. Costs 1 credits when completed without AI, or 10 credits when AI assistance is used. - url (string, required): Public HTTP(S) website URL to contact. A direct contact-page URL is allowed and its path/query are preserved. - name (string, required): Sender name used for email Reply-To and contact-form fields. Tabs become spaces; other control characters are not allowed. - email (string, required): Required parameter; supply a plain ASCII email address without quoted mailbox syntax, or an empty string to select the SMTP email assigned to your API key. A matching address also sends through SMTP without Reply-To. A different address sends from hello@pinglymcp.com with this address as Reply-To. Contact forms use this address or the assigned account address. A nonempty address is required when no email account is assigned. - subject (string, required): Email or contact-form subject. Tabs become spaces; other control characters are not allowed. - message (string, required): Message to send to the website owner. - method (enum, optional): Delivery method. auto prefers contact via email. Choose your preferred contact method. Values: auto, email, contact_form. - use_ai (boolean, optional): Enable AI-assistance for automated contact-form discovery and submission. - phonetic_name (string, optional): Optional phonetic spelling for contact forms that request it. - phone_number_ext (string, optional): Optional phone country/area extension for contact forms. - phone_number (string, optional): Optional phone number for contact forms. - state (string, optional): Optional state/region for contact forms. - city (string, optional): Optional city for contact forms. Example arguments: { "url": "https://example.com/contact-us", "name": "Your Name", "email": "you@example.com", "subject": "Hello", "message": "I would like to get in touch.", "method": "auto", "use_ai": false } Response: Success returns ok, data.request (effective contact values), data.page (requested/target URLs and optional screenshot), data.contact (method, status, submission, verification, confirmation), and meta (billing and safe debug summary). Email results additionally include data.contact.email with from (effective From address), replyTo (effective Reply-To address, or null when no header was sent), and status: accepted. Accepted confirms submission to the sending service, not inbox delivery. This optional object is absent for contact forms and may be absent in older results. Errors use stable product codes and retryable flags. An unconfirmed submission is never safe to retry automatically. Owner confirmation: I understand this sends a real email or submits a contact form. ## MCP utility tools - get_account: View the account connected to this MCP client. - get_credit_balance: View current free monthly and purchased credits. Costs 0 credits. - hello: Check the MCP connection with a greeting. # PinglyMCP billing ## Authorization and agent permissions Use your personal pmcp_ key or an OAuth access token. Personal keys offer Billing access choices None, Read and Manage in Dashboard → API Keys. None grants no billing access; Read permits billing accounts, history and operation reads; Manage permits reads plus payment links, subscription previews or changes, and billing portal sessions. Manage includes Read. This same key setting applies to REST billing endpoints and MCP billing tools, and new personal keys default to None. OAuth requires api:access for REST or mcp:access for MCP, plus billing:read to read billing data or billing:manage for billing reads and changes. Personal keys have a separate MCP tool setting: All tools grants current and future tools and hides the tool list; Selected tools shows the complete non-billing tool list and allows an explicit selection. Changing a key’s Billing access choice synchronizes the matching billing tools in a selected allowlist. An existing custom allowlist remains as saved until Billing access or the tool selection changes, and calling billing tools still requires the matching billing permission. MCP tool selection does not restrict REST access. All billing calls cost zero service credits. A successful call can still create or confirm a financial action. Agents must obtain the account owner’s approval of the amount, recurring price and effective date before purchasing or confirming a change. Keep checkout, invoice and portal URLs private to the account owner. ## Plans and service credits Plans include monthly service credits. Free: 100 included credits per month; Developer: 2,500 included credits per month; Startup: 15,000 included credits per month. Credits are usage units, not a cash balance. Any plan, including Free, can buy $5–$1000 in top-ups without subscribing. Amounts are integer USD cents; each cent buys one credit. Included credits refresh at the start of each UTC calendar month and do not roll over. Purchased credits are separate and do not expire while your account remains active. Included credits are spent first. ping and get_credit_balance cost 0 credits; describe_website costs 1; contact_website costs 1, or 10 when AI is used. Requests reserve credits before execution. Invalid requests and internal failures before execution release the reservation; an executed external failure may still incur a charge. Check meta.billing and your credit history for the final charge. Credits never bypass contact rate limits. Use GET /credits or the MCP get_credit_balance tool for spendable balance, including reserved credits. GET /credits/history gives the credit ledger. Billing account credits.totalBalance sums included and purchased balances and can include reserved credits. A plan change adjusts the remaining included allowance while preserving usage already consumed in the current UTC month. ## Buy credits or start a subscription Read get_billing_account first. Call create_credit_top_up with topUpCents and operationKey, or create_subscription_checkout with developer or startup and operationKey. Save data.operation.id and hand data.operation.checkoutUrl to the account owner to complete hosted Stripe Checkout. Card details are collected by Stripe, never as REST or MCP arguments. Poll get_billing_operation with operationId after checkout. A return to the dashboard or an HTTP success does not prove payment or credit delivery. payment_pending means payment or webhook reconciliation is still underway. Wait for completed and reread get_billing_account or get_credit_balance before relying on the purchased balance. A new paid plan becomes available only after the subscription is verified as active. To manage an existing subscription, use the preview and change flow. create_billing_portal_session returns data.operation.portalUrl for the account owner’s payment methods and invoices. ## Preview and confirm subscription changes Call preview_subscription_change with action upgrade, downgrade, cancel, resume or keep_current. Supply plan only for upgrade or downgrade. keep_current removes a Pingly-managed scheduled downgrade and keeps the current plan. A pending scheduled downgrade can also be replaced by another downgrade, canceled at renewal, or removed before an immediate upgrade. Review data.preview.fromPlan, toPlan, estimatedAmountCents, effectiveAt, expiresAt and cancelAtPeriodEnd with the account owner. Previews expire after five minutes and cannot be reused for another change. After approval, call change_subscription with the previewId and a stable operationKey. Upgrades may charge the saved payment method immediately, including prorated amounts; the larger allowance is applied only after successful payment. An upgrade releases a pending scheduled downgrade first. If payment remains pending, the schedule stays removed and the subscription remains on its current plan; after resolving the pending payment, create a fresh preview to cancel or schedule another plan. If data.operation.requiresActionUrl is present, send it to the owner to finish payment authentication. Downgrades and cancellation take effect at subscription renewal. resume reverses a scheduled cancellation. completed can mean a future change was successfully scheduled; check effectiveAt and account.subscription.pendingChange. A stale or expired preview requires a fresh preview and another review of its amount and date. ## Operation status and safe retries Generate operationKey once for each intended mutation and persist it before sending the request. It must be 8–128 characters using letters, digits, underscores, periods, colons or hyphens. Reuse exactly the same key and arguments after a timeout or retryable error. Changing the key may create another purchase. Reusing a key with different arguments returns BILLING_OPERATION_CONFLICT. Operation states are processing (request underway), requires_action (owner must use checkoutUrl, portalUrl or requiresActionUrl), payment_pending (waiting for payment or reconciliation), completed (finished or scheduled), failed and expired. Poll by operation ID without repeatedly creating new purchases. Failed or expired operations need review before starting a new intent. Responses use { ok, data, meta }. Read data.account, data.history, data.operation or data.preview according to the tool. Failures use { ok: false, error: { code, message, retryable }, meta }; preserve meta.requestId for support. In MCP, inspect the returned structuredContent for the same envelope. BILLING_PERMISSION_REQUIRED (403): grant the required permission. INVALID_REQUEST (400): correct the inputs. BILLING_OPERATION_NOT_FOUND (404): check the account and operation ID. BILLING_OPERATION_IN_PROGRESS or BILLING_OPERATION_CONFLICT (409): inspect the existing operation instead of changing the key. SUBSCRIPTION_PREVIEW_EXPIRED or SUBSCRIPTION_PREVIEW_STALE (409): create and review a fresh preview. RATE_LIMITED (429): pause before another attempt. BILLING_RECONCILIATION_REQUIRED (409): stop and contact support; do not bypass it with a new key. For retryable service errors, back off and reuse the original key. ## Sandbox and live payments Read data.account.mode: test means Stripe sandbox, live means real payments, and null means billing is unavailable. Test payments move no real money. Test and live customers, subscriptions and billing operations are separate; a sandbox subscription is not a live subscription. Never infer the payment mode from the website hostname. In sandbox, PinglyMCP automatically prepares a saved test card and billing details for hosted Checkout. Review the test-mode banner and complete checkout yourself. If Stripe requests fallback card entry, use 4242 4242 4242 4242, any future expiry, any three-digit CVC and any postal code. Never use real card details in sandbox or test card details in live mode. Card fields remain on Stripe’s hosted page. Before enabling live payments, the owner should verify a sandbox top-up, subscription checkout, invoice, upgrade, downgrade and cancellation, then confirm the balance and operation status. The credit wallet is shared across payment modes: reconcile sandbox-generated credits and plan allowances before switching to live. Switching payment mode is an operator action; agents cannot enable live payments with a billing tool. ## Billing reference GET arguments use query parameters; replace :id with operationId for GET /billing/operations/:id. POST arguments use a JSON body. MCP tools use the same named arguments. ### get_billing_account REST: GET /billing Permission: billing:read Read your subscription and credits. Requires billing:read. Costs 0 credits. No arguments. ### get_billing_history REST: GET /billing/history Permission: billing:read Read purchases, invoices and refunds. Requires billing:read. Costs 0 credits. - limit (number, optional): Maximum number of records. Minimum: 1. Maximum: 100. - cursor (string, optional): Pagination cursor returned by the previous response. Maximum length: 256. ### create_credit_top_up REST: POST /billing/top-ups Permission: billing:manage Create a hosted payment link to buy credits. Payment must complete before credits are granted. Requires billing:manage. Costs 0 service credits. - topUpCents (number, required): USD cents to spend, from 500 ($5) to 100000 ($1,000). Each cent buys one credit. Minimum: 500. Maximum: 100000. - operationKey (string, required): A unique key for this operation. Reuse the same key and arguments when retrying. Minimum length: 8. Maximum length: 128. ### get_billing_operation REST: GET /billing/operations/:id Permission: billing:read Check whether a billing operation requires payment, is pending, or has completed. Requires billing:read. Costs 0 credits. - operationId (string, required): The operation ID returned when the operation was created. Minimum length: 1. Maximum length: 128. ### create_subscription_checkout REST: POST /billing/subscriptions/checkout Permission: billing:manage Create a hosted payment link for a new subscription. Requires billing:manage. Costs 0 service credits. - plan (enum, required): The paid subscription plan. Values: developer, startup. - operationKey (string, required): A unique key for this operation. Reuse the same key and arguments when retrying. Minimum length: 8. Maximum length: 128. ### preview_subscription_change REST: POST /billing/subscriptions/preview Permission: billing:manage Preview an upgrade, downgrade, cancellation at renewal, reversal of cancellation, or removal of a scheduled downgrade while keeping the current plan. Upgrades require successful payment; downgrades apply at renewal. Requires billing:manage. Costs 0 credits. - action (enum, required): The proposed subscription change. Values: upgrade, downgrade, cancel, resume, keep_current. - plan (enum, optional): Required for an upgrade or downgrade; omit for cancel, resume, or keep_current. Values: developer, startup. ### change_subscription REST: POST /billing/subscriptions/change Permission: billing:manage Confirm an unexpired preview. May charge the saved payment method for an upgrade. Review the preview before calling. Requires billing:manage. Costs 0 service credits. - previewId (string, required): The unexpired preview ID to confirm. Minimum length: 1. Maximum length: 128. - operationKey (string, required): A unique key for this operation. Reuse the same key and arguments when retrying. Minimum length: 8. Maximum length: 128. ### create_billing_portal_session REST: POST /billing/portal Permission: billing:manage Create a private hosted link for payment methods and invoices. Share it only with the account owner. Requires billing:manage. Costs 0 credits. - operationKey (string, required): A unique key for this operation. Reuse the same key and arguments when retrying. Minimum length: 8. Maximum length: 128.