|

Collectibles integrations and boundaries

Payment and shipping adapters, card data and market price sources, S3 storage, MCP, OAuth, API keys, and webhooks in the current source.

An integration record says which provider a shop has chosen. It does not prove that credentials work, that a provider accepted a request, or that money or goods moved.

Payment providers

Adapters live in features/integrations/payment and are selected by function name on each PaymentProvider record (stripe, paypal, manual). Onboarding seeds two providers:

ProviderCodeEnvironment
Stripepp_stripe_stripeNEXT_PUBLIC_STRIPE_KEY, STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET
Bank transfer (manual review)pp_system_defaultnone

A PayPal adapter also exists (NEXT_PUBLIC_PAYPAL_CLIENT_ID, PAYPAL_CLIENT_SECRET, PAYPAL_WEBHOOK_ID, NEXT_PUBLIC_PAYPAL_SANDBOX) but is not seeded. A provider must be installed and connected to the checkout region before customers can use it.

The manual provider charges nothing at checkout. completeActiveCart creates the order with a pending payment, and a manager records the payment with confirmManualPayment after funds arrive. Provider webhooks are received at /api/payment-webhooks/[providerId] and handled by handlePaymentProviderWebhook.

Shipping providers

features/integrations/shipping contains shippo, shipengine, and manual adapters behind a shared contract for rates, labels, address validation, tracking, and label cancellation (getRatesForOrder, createProviderShippingLabel, validateShippingAddress, trackShipment, cancelShippingLabel). Provider credentials are configured on ShippingProvider records in the dashboard. Onboarding seeds shipping options ("Tracked bubble mailer", "Insured, signature required", "Return shipping"), not a connected carrier account.

High-value fulfillment records declared value, signature, insurance, and shipment evidence in the database. It does not buy insurance or request a signature service from a carrier.

Card data and market prices

  • Card catalog: full set checklists are bundled as JSON in features/keystone/lib/pokemon/checklists, built from Pokémon TCG API data. importCardCatalog reads these files; it does not call the Pokémon TCG API at runtime. Card images are linked by URL on images.pokemontcg.io and images.scrydex.com.
  • Market prices: refreshMarketPrices fetches https://tcgcsv.com/tcgplayer/3/<groupId>/prices for each set with a tcgplayerGroupId. No API key is used. Readings are per card and finish, not per condition; conditions are priced as a share of the NM reading through PricingRule.
  • Grading companies: GradingCompany stores a certificate lookup URL template. receiveCollectibleItem sets templates for PSA and CGC; BGS has none. The storefront slab view shows a "Verify with" link only when a template exists and the certificate is not marked as a sample. Nothing calls a grading-company API, so the link is not a verification result.

TCGCSV and the bundled card data are third-party sources outside the shop's control. If TCGCSV is unavailable, the refresh reports the failure per set and existing readings stay in place.

File storage

Keystone file and image fields use S3-compatible storage configured by S3_BUCKET_NAME, S3_REGION, S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY, and S3_ENDPOINT, all required in production. Claim images can also use Cloudinary (CLOUDINARY_CLOUD_NAME, CLOUDINARY_KEY, CLOUDINARY_SECRET). CollectibleMedia and dispute evidence store URLs.

Email

Password reset and order emails use SMTP (SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASSWORD, SMTP_FROM, SMTP_STORE_LINK). NotificationIntent records outbound notification state; there is no restock or want-list alert delivery.

MCP and AI assistant

/api/mcp-transport/[transport] exposes an MCP server. It forwards the caller's session cookie to /api/graphql, so every tool runs with the caller's own permissions. Tools include schema discovery (listModels, searchModels, getFieldsForType, lookupInputType), generic data tools (queryData, createData, updateData, deleteData, modelSpecificSearch), and storefront commerce tools (searchProducts, getProduct, cart, address, shipping, payment, placeOrder, getOrder, getCheckoutLink).

The dashboard assistant at /api/completion uses OpenRouter and requires OPENROUTER_API_KEY and OPENROUTER_MODEL. Model choice determines where shop data is sent.

API keys, OAuth apps, and webhooks

  • API keys: bearer tokens prefixed of_, with scopes, optional expiry, and optional IP restrictions. Effective access is limited to both the key's scopes and its owner's role. Set TRUSTED_PROXY_IPS if keys are IP-restricted behind a proxy.
  • OAuth apps: /api/oauth/authorize and /api/oauth/token issue tokens for OAuthApp records, used by the order-management connection page. Token scopes are capped at the owner role.
  • Outbound webhooks: WebhookEndpoint and WebhookEvent with registerWebhookEndpoint and retryWebhookDeliveries. Retries run when that mutation is called; no worker runs them on a schedule.

Out of scope

  • No TCGplayer marketplace, eBay, or other channel listing sync.
  • No TCGplayer API, PriceCharting, or graded-price feed.
  • No grading-company, identity-verification, or risk-scoring provider adapter. ProviderConnection and RiskAssessment records exist without a connected service.
  • No store-credit ledger or payout provider for trade-ins or consignment settlements.
  • No POS or in-store hardware integration.

On this page