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:
| Provider | Code | Environment |
|---|---|---|
| Stripe | pp_stripe_stripe | NEXT_PUBLIC_STRIPE_KEY, STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET |
| Bank transfer (manual review) | pp_system_default | none |
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.importCardCatalogreads these files; it does not call the Pokémon TCG API at runtime. Card images are linked by URL onimages.pokemontcg.ioandimages.scrydex.com. - Market prices:
refreshMarketPricesfetcheshttps://tcgcsv.com/tcgplayer/3/<groupId>/pricesfor each set with atcgplayerGroupId. No API key is used. Readings are per card and finish, not per condition; conditions are priced as a share of the NM reading throughPricingRule. - Grading companies:
GradingCompanystores a certificate lookup URL template.receiveCollectibleItemsets 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.
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. SetTRUSTED_PROXY_IPSif keys are IP-restricted behind a proxy. - OAuth apps:
/api/oauth/authorizeand/api/oauth/tokenissue tokens forOAuthApprecords, used by the order-management connection page. Token scopes are capped at the owner role. - Outbound webhooks:
WebhookEndpointandWebhookEventwithregisterWebhookEndpointandretryWebhookDeliveries. 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.
ProviderConnectionandRiskAssessmentrecords 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.