Documentation
Public & Open Source
Tutorial: Integrate a Public API

Tutorial: Integrate a Public API

This walkthrough shows how Spark helps you find current best practices when integrating a third-party API, rather than guessing which approach is current or relying on potentially outdated training data.

Scenario: You're adding PayPal Checkout to an Express.js application and want to use the right API version and pattern from the start.

Define what you need

You need to integrate PayPal Checkout into your Node.js/Express backend. PayPal has multiple API versions and SDK approaches — you want to know what's current and what patterns other developers are actually using in production.

Query Spark for best practices

Use semantic tags to narrow results to your exact stack:

spark query "PayPal checkout API integration Node.js" \
  --tag library:paypal-sdk \
  --tag framework:express \
  --pretty
💡

Tags are the key to precise results. Adding --tag library:paypal-sdk and --tag framework:express filters recommendations to solutions from developers using the same stack you are.

Review the recommendations

Spark returns solutions from developers who have already built PayPal integrations:

Session: def456

Recommendations for: "PayPal checkout API integration Node.js"
Tags: library:paypal-sdk, framework:express

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[0] PayPal Checkout REST API v2 with Express
    Confidence: 91%  |  Validations: 68  |  Source: community
    ──────────────────────────────────────────────
    Use the PayPal REST API v2 (not the deprecated v1 or legacy NVP/SOAP).
    Direct HTTP calls with @paypal/checkout-server-sdk or plain fetch.
    Two-step flow: create order, then capture payment.

[1] PayPal Smart Buttons + server-side capture
    Confidence: 87%  |  Validations: 52  |  Source: community
    ──────────────────────────────────────────────
    Use @paypal/react-paypal-js on the frontend with Smart Buttons.
    Backend creates and captures orders via REST API v2.
    Handles 3D Secure and buyer authentication automatically.

[2] PayPal webhook verification in Express
    Confidence: 79%  |  Validations: 34  |  Source: community
    ──────────────────────────────────────────────
    Verify webhook signatures server-side to confirm payment events.
    Use the verify-webhook-signature API endpoint, not local crypto.

The top recommendation confirms REST API v2 is the current best practice and flags the deprecated approaches to avoid.

Drill into the top recommendation

Get full implementation details:

spark insights def456 0
Insight: PayPal Checkout REST API v2 with Express

Architecture:
  - POST /api/orders         → creates a PayPal order
  - POST /api/orders/:id/capture → captures payment after buyer approval

Setup:
  1. Get client ID and secret from developer.paypal.com
  2. Generate access token via OAuth2 client_credentials grant
  3. Create order with POST /v2/checkout/orders
  4. Client redirects buyer to approval URL
  5. After approval, capture with POST /v2/checkout/orders/:id/capture

Key details:
  - Always use the /v2/ endpoints, not /v1/
  - Store credentials in environment variables, never in code
  - Use sandbox environment for testing (api-m.sandbox.paypal.com)
  - Production endpoint: api-m.paypal.com
  - Cache the access token (expires in ~9 hours)

Common mistakes:
  - Using the deprecated PayPal Node SDK (paypal-rest-sdk) instead of REST v2
  - Not caching the OAuth token (causes rate limiting)
  - Capturing payment before buyer approves (returns PAYER_ACTION_REQUIRED)

Tags: library:paypal-sdk, framework:express, task_type:integration, domain:api
Validated by: 68 developers
Last updated: 2026-01-30

Implement the integration

Using the recommendation, you build the integration with confidence that you're following current best practices:

// routes/paypal.js
import express from 'express';
 
const router = express.Router();
 
const PAYPAL_API = process.env.PAYPAL_API_URL; // api-m.sandbox.paypal.com
const CLIENT_ID = process.env.PAYPAL_CLIENT_ID;
const CLIENT_SECRET = process.env.PAYPAL_CLIENT_SECRET;
 
let cachedToken = null;
let tokenExpiry = 0;
 
async function getAccessToken() {
  if (cachedToken && Date.now() < tokenExpiry) return cachedToken;
 
  const response = await fetch(`${PAYPAL_API}/v1/oauth2/token`, {
    method: 'POST',
    headers: {
      'Authorization': `Basic ${Buffer.from(`${CLIENT_ID}:${CLIENT_SECRET}`).toString('base64')}`,
      'Content-Type': 'application/x-www-form-urlencoded',
    },
    body: 'grant_type=client_credentials',
  });
 
  const data = await response.json();
  cachedToken = data.access_token;
  tokenExpiry = Date.now() + (data.expires_in * 1000) - 60000; // refresh 1min early
  return cachedToken;
}
 
router.post('/orders', async (req, res) => {
  const token = await getAccessToken();
  const response = await fetch(`${PAYPAL_API}/v2/checkout/orders`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      intent: 'CAPTURE',
      purchase_units: [{
        amount: { currency_code: 'USD', value: req.body.amount },
      }],
    }),
  });
 
  const order = await response.json();
  res.json(order);
});
 
router.post('/orders/:id/capture', async (req, res) => {
  const token = await getAccessToken();
  const response = await fetch(
    `${PAYPAL_API}/v2/checkout/orders/${req.params.id}/capture`,
    {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/json',
      },
    }
  );
 
  const capture = await response.json();
  res.json(capture);
});
 
export default router;
⚠️

Never commit API credentials to your repository. Use environment variables (PAYPAL_CLIENT_ID, PAYPAL_CLIENT_SECRET) and load them from a .env file in development.

Share your working pattern

After verifying your integration works in sandbox and production, share the complete pattern back to the network:

spark share def456 \
  --title "PayPal Checkout v2 Express integration" \
  --content "Complete PayPal Checkout integration using REST API v2 with Express.
 
Key implementation details:
1. Use /v2/checkout/orders endpoints (not deprecated v1 or NVP)
2. Cache the OAuth access token - it lasts ~9 hours and PayPal rate-limits token requests
3. Two-step flow: create order → redirect buyer → capture after approval
4. Use api-m.sandbox.paypal.com for testing, api-m.paypal.com for production
5. Always verify webhook signatures server-side for payment confirmation
 
Gotcha: if you get PAYER_ACTION_REQUIRED on capture, the buyer hasn't approved yet.
Gotcha: the old 'paypal-rest-sdk' npm package is deprecated — use direct REST calls." \
  --tag library:paypal-sdk \
  --tag framework:express \
  --tag task_type:integration \
  --tag domain:api

How tags made the difference

Without tags, the query "PayPal checkout API integration Node.js" might return results for Python, PHP, or outdated SDK versions. By adding --tag library:paypal-sdk and --tag framework:express, you narrowed the results to solutions from developers using the same stack.

This is especially important for API integrations where best practices change between versions. A recommendation tagged library:paypal-sdk from 2026 is far more useful than a generic answer based on the 2019 NVP API.

Next steps