# How to Integrate Bolt.new with Moz

- Tool: Bolt.new
- Difficulty: Intermediate
- Time required: 20 minutes
- Last updated: April 2026

## TL;DR

Integrate Moz with Bolt.new using the Moz Links API and Moz URL Metrics API through an API route that keeps your Moz API credentials server-side. Fetch domain authority scores, page authority, spam scores, and backlink data for any URL. Moz's API uses simple token-based authentication over HTTPS — all calls work from Bolt's WebContainer preview. Build SEO audit dashboards and domain analysis tools with Moz data surfaced directly in your Bolt app.

## Build SEO Authority Tools in Your Bolt.new App with Moz API

Moz is the creator of Domain Authority (DA) — the 100-point logarithmic scale that has become the industry-standard metric for measuring a website's overall ranking strength. When SEO professionals, content marketers, and digital agencies talk about a site's authority, they're usually referring to Moz's DA score. Integrating Moz into your Bolt.new app gives you access to this authoritative data programmatically — enabling you to build SEO audit tools, competitive analysis dashboards, link prospecting systems, and client reporting portals.

The Moz API provides two main data streams that power most use cases. The URL Metrics API returns a bundle of authority metrics for any URL: Domain Authority (DA), Page Authority (PA), Spam Score, linking root domains count, and total links count. These metrics are the foundation of any SEO analysis — you can analyze a single URL, bulk-process lists of prospects, or monitor a client's authority trends over time. The Links API goes deeper, returning the actual backlink profile: which domains link to a target URL, the anchor text used, and the authority of the linking pages.

Moz's free tier provides limited monthly API rows — enough for development and light usage. Paid plans unlock higher monthly limits for production tools. The API uses simple token-based HTTP Basic Auth with no OAuth flow to manage, making it one of the simpler SEO APIs to integrate. Since all calls are standard HTTPS requests, they work perfectly from Bolt's WebContainer during development — no deployment or special configuration needed for outbound data fetching.

## Before you start

- A Moz account at moz.com (free account available, paid plan for higher API limits)
- Moz API access token: Access ID and Secret Key from moz.com/products/mozscape/access
- A Bolt.new project with Next.js for API routes
- Supabase connected to the Bolt project (for caching Moz API results)
- Understanding of Moz's API row pricing model — each URL metric fetch consumes rows against your monthly limit

## Step-by-step guide

### 1. Get Your Moz API Credentials

Moz provides API access through their Mozscape API, which they also call the Moz Links API. To get credentials, you need a Moz account with API access enabled. Go to moz.com and create an account if you don't have one — the free tier includes a limited number of API rows per month (enough for development and testing). Once logged in, navigate to moz.com/products/mozscape/access or go to your Moz account settings and look for the API section. You'll find two credentials: an Access ID (a string like `mozscape-xxxxxxxxxx`) and a Secret Key (a longer token string). These two values are used together as HTTP Basic Auth credentials — the Access ID is the username and the Secret Key is the password. Unlike OAuth-based APIs, there's no token expiry or refresh flow — the credentials are permanent until you reset them. Moz's API base URL is `https://lsapi.seomoz.com/v2/`. Copy both credentials into your Bolt project's `.env` file. Since these credentials authenticate your Moz account and control your monthly API usage, they must stay server-side — never expose them in client-side JavaScript. The Moz API does not have a separate sandbox environment; all requests hit the production API, but the data returned for any URL reflects Moz's real-world index. Fetching metrics for test URLs like your own domain is a free and safe way to verify the integration works.

```
# .env — Moz API credentials
# Found at moz.com/products/mozscape/access after logging in
MOZ_ACCESS_ID=mozscape-your-access-id
MOZ_SECRET_KEY=your-secret-key

# Moz API v2 base URL
MOZ_API_BASE=https://lsapi.seomoz.com/v2

# For Next.js server-side: process.env.MOZ_ACCESS_ID
# Never use NEXT_PUBLIC_ prefix — these are server-side only credentials
```

**Expected result:** You have Moz Access ID and Secret Key stored in your .env file. Test the credentials by calling the Moz API directly from your API route with a domain you know (e.g., your own website).

### 2. Create the URL Metrics API Route

The URL Metrics endpoint is the core of most Moz integrations. It accepts an array of URLs and returns authority metrics for each one: Domain Authority (DA, 1-100 scale measuring overall link authority), Page Authority (PA, 1-100 scale for individual page authority), Spam Score (0-17 scale measuring how likely the domain is penalized), and link counts (linking root domains and total links). Build a Next.js API route that accepts a URL (or array of URLs) from your frontend, authenticates with Moz using Basic Auth, and returns the formatted metrics. The Moz API v2 uses a POST request to `/url_metrics` with a JSON body containing a `targets` array of URL strings. Moz recommends normalizing URLs before sending them — including the protocol (`https://`) and removing trailing slashes for consistent results. The Basic Auth header is computed by base64-encoding `AccessID:SecretKey`. Store the Basic Auth string at module level so it's computed once rather than on every request. Moz's API returns results as an array matching the order of your input targets — this allows batch processing of multiple URLs in a single API call, which is more efficient than individual calls. For production tools analyzing many URLs, batch requests reduce both latency and API row consumption.

```
// app/api/moz/url-metrics/route.ts
import { NextResponse } from 'next/server';
import { createClient } from '@supabase/supabase-js';

const MOZ_AUTH = Buffer.from(
  `${process.env.MOZ_ACCESS_ID}:${process.env.MOZ_SECRET_KEY}`
).toString('base64');

function normalizeUrl(url: string): string {
  const trimmed = url.trim();
  if (!trimmed.startsWith('http')) return `https://${trimmed}`;
  return trimmed.replace(/\/$/, '');
}

export async function POST(request: Request) {
  const body = await request.json();
  const inputUrls: string[] = Array.isArray(body.urls)
    ? body.urls
    : body.url
    ? [body.url]
    : [];

  if (inputUrls.length === 0) {
    return NextResponse.json({ error: 'url or urls is required' }, { status: 400 });
  }

  const targets = inputUrls.map(normalizeUrl);

  const supabase = createClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.SUPABASE_SERVICE_ROLE_KEY!
  );

  // Check cache for all targets
  const yesterday = new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString();
  const { data: cached } = await supabase
    .from('moz_metrics_cache')
    .select('*')
    .in('url', targets)
    .gt('cached_at', yesterday);

  const cachedUrls = new Set(cached?.map((c) => c.url) ?? []);
  const uncachedTargets = targets.filter((t) => !cachedUrls.has(t));

  let freshResults: Array<Record<string, number | string>> = [];

  if (uncachedTargets.length > 0) {
    const mozResponse = await fetch(`${process.env.MOZ_API_BASE}/url_metrics`, {
      method: 'POST',
      headers: {
        'Authorization': `Basic ${MOZ_AUTH}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ targets: uncachedTargets }),
    });

    if (!mozResponse.ok) {
      const errorText = await mozResponse.text();
      return NextResponse.json(
        { error: `Moz API error: ${errorText}` },
        { status: mozResponse.status }
      );
    }

    const mozData = await mozResponse.json();
    freshResults = mozData.results ?? [];

    // Cache fresh results
    const toCache = freshResults.map((result, i) => ({
      url: uncachedTargets[i],
      domain_authority: result.domain_authority,
      page_authority: result.page_authority,
      spam_score: result.spam_score,
      linking_root_domains: result.root_domains_to_root_domain,
      total_links: result.links_to_root_domain,
      cached_at: new Date().toISOString(),
    }));

    await supabase
      .from('moz_metrics_cache')
      .upsert(toCache, { onConflict: 'url' });
  }

  // Merge cached + fresh, preserving input order
  const allResults = targets.map((url) => {
    const fromCache = cached?.find((c) => c.url === url);
    if (fromCache) return fromCache;
    const freshIdx = uncachedTargets.indexOf(url);
    return freshResults[freshIdx] ? { url, ...freshResults[freshIdx] } : { url, error: 'not found' };
  });

  return NextResponse.json({ results: allResults });
}
```

**Expected result:** POST to /api/moz/url-metrics with { url: 'https://example.com' } returns domain authority, page authority, spam score, and link counts. Results are cached in Supabase for 24 hours.

### 3. Build the SEO Audit Dashboard UI

With the URL metrics API route in place, build the frontend dashboard that makes this data useful. The dashboard needs a URL input field, a way to show loading state during the API call, and a clear visual display of the returned metrics. Domain Authority is the headline metric — display it prominently with color coding based on the score range. SEO professionals use these rough benchmarks: DA 1-29 is low authority (new or weak sites), DA 30-49 is moderate authority (established sites with some link equity), DA 50-69 is high authority (well-established, significant link profiles), and DA 70+ is very high authority (major publications, authority brands). Spam Score deserves attention too — a score of 10+ indicates potential quality issues with the domain's link profile. Display metrics as visual cards with icons rather than raw numbers to make the dashboard accessible to non-technical users like marketing teams and clients. For the bulk URL feature, add a textarea for pasting multiple domains (one per line), parse them client-side, and send the array to your API route in a single batch request. The Moz API supports up to 50 URLs per request in the v2 endpoint — process larger lists in batches of 50 with a small delay between requests to respect rate limits.

```
// components/MozMetricsCards.tsx
'use client';

interface MozMetrics {
  url: string;
  domain_authority: number;
  page_authority: number;
  spam_score: number;
  linking_root_domains: number;
  total_links: number;
}

function getDAColor(da: number): string {
  if (da >= 50) return 'bg-green-100 text-green-800 border-green-200';
  if (da >= 30) return 'bg-yellow-100 text-yellow-800 border-yellow-200';
  return 'bg-red-100 text-red-800 border-red-200';
}

function getSpamColor(spam: number): string {
  if (spam <= 3) return 'text-green-600';
  if (spam <= 7) return 'text-yellow-600';
  return 'text-red-600';
}

export function MozMetricsCards({ metrics }: { metrics: MozMetrics }) {
  const daColor = getDAColor(metrics.domain_authority);

  return (
    <div className="space-y-4">
      <p className="text-sm text-gray-500 break-all">{metrics.url}</p>
      <div className="grid grid-cols-2 md:grid-cols-4 gap-4">
        <div className={`p-4 rounded-xl border-2 ${daColor}`}>
          <p className="text-xs font-medium uppercase tracking-wide opacity-70">Domain Authority</p>
          <p className="text-4xl font-bold mt-1">{metrics.domain_authority}</p>
          <p className="text-xs mt-1">out of 100</p>
        </div>
        <div className="p-4 rounded-xl border-2 bg-blue-50 text-blue-800 border-blue-200">
          <p className="text-xs font-medium uppercase tracking-wide opacity-70">Page Authority</p>
          <p className="text-4xl font-bold mt-1">{metrics.page_authority}</p>
          <p className="text-xs mt-1">out of 100</p>
        </div>
        <div className="p-4 rounded-xl border-2 bg-gray-50 border-gray-200">
          <p className="text-xs font-medium uppercase tracking-wide text-gray-500">Spam Score</p>
          <p className={`text-4xl font-bold mt-1 ${getSpamColor(metrics.spam_score)}`}>
            {metrics.spam_score}
          </p>
          <p className="text-xs mt-1 text-gray-500">out of 17</p>
        </div>
        <div className="p-4 rounded-xl border-2 bg-purple-50 text-purple-800 border-purple-200">
          <p className="text-xs font-medium uppercase tracking-wide opacity-70">Linking Domains</p>
          <p className="text-3xl font-bold mt-1">
            {metrics.linking_root_domains.toLocaleString()}
          </p>
          <p className="text-xs mt-1">root domains</p>
        </div>
      </div>
    </div>
  );
}
```

**Expected result:** The SEO audit dashboard displays Moz authority metrics as color-coded cards. Entering any URL returns its Domain Authority, Page Authority, Spam Score, and linking domain count.

### 4. Add Backlink Analysis with the Moz Links API

The Moz Links API provides access to the actual backlink data behind DA and PA scores — showing which specific URLs and domains link to a target, the anchor text, and whether each link is followed or nofollowed. This is valuable for competitive research (analyzing what links your competitors have built), link prospecting (finding sites that link to one competitor to target for your own link building), and link auditing (identifying potentially spammy links pointing to your site). The Links API endpoint accepts a target URL and returns an array of linking page objects, each with the source URL, target URL, anchor text, source page authority, source domain authority, and link attributes (nofollow, sponsored, etc.). The API supports filtering by link type, link status (active vs deleted), and sorting by page authority or anchor text. For most use cases, requesting the top 25-50 links by Page Authority gives the best picture of high-quality backlinks. Like all Moz API calls, this is a standard HTTPS request that works from the WebContainer — build and test the backlink analysis feature in the preview before deploying. Rate limits apply to the Links API separately from URL Metrics, so cache backlink results aggressively (they change slowly) to avoid hitting limits.

```
// app/api/moz/links/route.ts
import { NextResponse } from 'next/server';

const MOZ_AUTH = Buffer.from(
  `${process.env.MOZ_ACCESS_ID}:${process.env.MOZ_SECRET_KEY}`
).toString('base64');

export async function POST(request: Request) {
  const { url, limit = 25, minDA = 0 } = await request.json();

  if (!url) {
    return NextResponse.json({ error: 'url is required' }, { status: 400 });
  }

  const target = url.startsWith('http') ? url : `https://${url}`;

  const mozResponse = await fetch(`${process.env.MOZ_API_BASE}/links`, {
    method: 'POST',
    headers: {
      'Authorization': `Basic ${MOZ_AUTH}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      target,
      target_scope: 'root_domain',
      source_scope: 'page',
      limit,
      sort: 'page_authority',
    }),
  });

  if (!mozResponse.ok) {
    const errorText = await mozResponse.text();
    return NextResponse.json(
      { error: `Moz API error: ${errorText}` },
      { status: mozResponse.status }
    );
  }

  const data = await mozResponse.json();
  const links = (data.results ?? []).filter(
    (link: { source_domain_authority: number }) => link.source_domain_authority >= minDA
  );

  return NextResponse.json({
    target,
    total_links: data.total_links,
    results: links.map((link: {
      source_url: string;
      target_url: string;
      anchor_text: string;
      source_domain_authority: number;
      source_page_authority: number;
      flags: number;
    }) => ({
      source_url: link.source_url,
      target_url: link.target_url,
      anchor_text: link.anchor_text ?? '',
      source_domain_authority: link.source_domain_authority,
      source_page_authority: link.source_page_authority,
      is_nofollow: Boolean(link.flags & 32),
    })),
  });
}
```

**Expected result:** The links API route returns a list of backlinks for any target URL, each with source domain authority, page authority, anchor text, and nofollow status. The dashboard displays these in a sortable table.

## Best practices

- Cache Moz API results in Supabase with a 24-hour TTL to reduce row consumption and improve response times for repeated URL lookups
- Always normalize URLs before sending to Moz — include the https:// protocol and remove trailing slashes for consistent results
- Never expose MOZ_ACCESS_ID or MOZ_SECRET_KEY in client-side code — all Moz API calls must go through server-side API routes where they access process.env variables
- Batch multiple URL requests in a single Moz API call (up to 50 URLs per request in v2) rather than making individual calls to save your monthly row budget
- Add context to DA and PA scores for non-technical users — a DA of 45 means little without labels like 'Moderate Authority' or comparisons to known reference points
- Monitor your monthly row usage in the Moz account dashboard and set up alerts before you hit the limit to avoid unexpected API failures in production tools
- Use the Links API with source_scope: 'root_domain' to get unique linking domains rather than individual pages — this gives a cleaner competitive overview

## Use cases

### SEO Authority Audit Dashboard

Build an internal dashboard where your team can paste any URL and instantly see its Domain Authority, Page Authority, Spam Score, and link counts. Useful for pre-qualifying guest post targets, evaluating acquisition targets, and benchmarking against competitors.

Prompt example:

```
Create an SEO audit dashboard at /seo-audit. Add a URL input field where users can paste any website URL. On submit, call /api/moz/url-metrics with the URL to fetch Domain Authority, Page Authority, Spam Score, and number of linking root domains from the Moz API. Display the results as metric cards with color coding (green for DA 50+, yellow for 30-50, red for under 30). Cache results in Supabase for 24 hours to avoid redundant API calls.
```

### Bulk URL Analyzer for Link Prospecting

Analyze a list of URLs in bulk to quickly score prospects for link building outreach. Paste a list of domains, get authority scores for all of them, and sort by DA to prioritize high-authority targets.

Prompt example:

```
Build a bulk SEO analyzer page. Accept up to 20 URLs pasted in a textarea (one per line). On submit, call the Moz URL Metrics API for each URL via my API route and display results in a sortable table with columns: URL, Domain Authority, Page Authority, Spam Score, and Linking Root Domains. Sort by Domain Authority descending by default. Show a loading skeleton while fetching. Export to CSV button using client-side CSV generation.
```

### Competitor Backlink Research Tool

Analyze the backlink profile of any competitor URL using the Moz Links API. See which high-authority domains link to them, what anchor text they use, and identify link building opportunities to replicate.

Prompt example:

```
Create a competitor backlink analysis page. Accept a target URL. Call /api/moz/links with the URL to fetch the top 25 backlinks from Moz's Links API. Display each backlink as a card showing: source domain, Domain Authority of the source, anchor text, and whether the link is follow or nofollow. Show total backlink count at the top. Add a filter to show only links from domains with DA 30 or higher.
```

## Troubleshooting

### Moz API returns 401 Unauthorized

Cause: The Basic Auth header is incorrect — either the Access ID or Secret Key is wrong, or they've been transposed (Secret Key used as username, Access ID as password).

Solution: Verify MOZ_ACCESS_ID and MOZ_SECRET_KEY in your .env match exactly what's shown in your Moz account API settings. The Access ID is the username and the Secret Key is the password: Buffer.from('AccessID:SecretKey').toString('base64'). Check there are no leading/trailing spaces in the credential values.

```
// Correct Basic Auth construction for Moz
const MOZ_AUTH = Buffer.from(
  `${process.env.MOZ_ACCESS_ID}:${process.env.MOZ_SECRET_KEY}`
).toString('base64');
// Header: 'Authorization': `Basic ${MOZ_AUTH}`
```

### Moz API returns 429 Too Many Requests or row limit exceeded error

Cause: Your account's monthly API row budget has been exhausted, or you're making too many requests too quickly. Moz's free tier has a low monthly row limit.

Solution: Implement caching in Supabase — store URL metrics results with a cached_at timestamp and only call the Moz API again if the cache is older than 24 hours. For bulk analysis, batch URLs into groups of 10-20 and add a 1-second delay between batches. Consider upgrading to a Moz paid plan for production tools with higher volume needs.

```
// Add rate limiting delay between batch requests
for (let i = 0; i < batches.length; i++) {
  const results = await fetchBatch(batches[i]);
  allResults.push(...results);
  if (i < batches.length - 1) {
    await new Promise(resolve => setTimeout(resolve, 1000)); // 1s delay
  }
}
```

### Moz returns DA of 0 or null for a known popular website

Cause: The URL format is incorrect — Moz requires the full URL with protocol (https://). Domain-only strings without a protocol may not match Moz's index.

Solution: Normalize all URLs before sending to the Moz API: ensure they include the https:// protocol and remove trailing slashes. Use the normalizeUrl() helper function to standardize inputs before sending to Moz.

```
function normalizeUrl(url: string): string {
  const trimmed = url.trim();
  if (!trimmed.startsWith('http')) return `https://${trimmed}`;
  return trimmed.replace(/\/$/, '');
}
```

## Frequently asked questions

### How do I get a Moz API access token?

Log into your Moz account at moz.com and navigate to moz.com/products/mozscape/access (or your account's API section). You'll find your Access ID and Secret Key listed there. Free Moz accounts include a limited number of monthly API rows. Create a paid Moz subscription for higher monthly limits needed by production SEO tools.

### Can I call the Moz API from Bolt's WebContainer preview?

Yes. Moz's API is a standard HTTPS REST API with no special connection requirements — all calls are outbound from your API route to Moz's servers. Since Bolt's WebContainer supports standard outbound HTTPS requests, you can develop and test the full Moz integration in the preview without deploying. Moz has no webhooks or incoming connection requirements.

### What is Moz Domain Authority and how does it differ from Page Authority?

Domain Authority (DA) is a score from 1 to 100 predicting how well a website's entire domain will rank in search engines, based on its overall link profile strength. Page Authority (PA) is the same scale but for a specific individual page rather than the whole domain. A site's homepage typically has a lower PA than its DA, while a popular blog post on a high-DA site might have a PA close to or exceeding the domain's DA.

### How many URLs can I analyze per month with Moz's free tier?

Moz's free tier includes a limited number of API rows per month — each URL in a URL Metrics request consumes one row, and each link returned from the Links API also consumes rows. The exact free limit is shown in your Moz account dashboard. For development and testing, the free tier is sufficient. Production tools with high query volume need a Moz paid API subscription.

### Is Moz's npm package available for Bolt.new?

Moz does not have an official Node.js SDK npm package — the API uses direct HTTP calls with Basic Auth. This is actually simpler: use the built-in fetch() API in your Next.js API routes with the Authorization: Basic header. No npm install needed beyond what Bolt already provides.

---

Source: https://www.rapidevelopers.com/bolt-ai-integrations/moz
© RapidDev — https://www.rapidevelopers.com/bolt-ai-integrations/moz
