Validation Findings

Read channel validation findings, mute acceptable ones, and export the full affected-product list as CSV.

When a feed is connected to a channel (Google, Commission Junction), the feed is validated against that channel’s requirements. Findings tell you what’s wrong and why — the issues that would cause products to be rejected or warned. Use them to drive feed optimization: read the findings, fix them with rules or product overrides, then re-read until clean.

All endpoints are scoped to a feed and a channel, addressed by the channel’s slug (e.g. google, commission_junction). Fetch the connectable channels and their slugs from GET /v1/channels.


List findings

GET /v1/feeds/:feed_id/channels/:channel_slug/findings

Returns the channel’s validation findings as a flat array of issue categories. Each entry is an issue type with the number of affected products and up to ~5 sample rows. The complete row-level list is available via Export findings.

Reading this triggers (re)validation when the channel has never been validated or its configuration changed since the last run — watch meta.revalidating and poll until it is false for up-to-date findings. Channels without a validator return meta.status: "unsupported" and an empty array.

Required scope: read_feeds

Severity sub-collections

PathReturns
/findingsAll findings.
/findings/errorsOnly error-severity findings.
/findings/warningsOnly warning-severity findings.

Parameters

ParameterTypeDescription
categorystringNarrow to a single finding category.
pageintegerPage number (default 1).
per_pageintegerResults per page (default 25, max 100).

Request

curl https://app.simpleproductfeeds.com/v1/feeds/feed_1/channels/google/findings/errors \
  -H "Authorization: Bearer spf_live_sk_your_key_here"

Response

{
  "data": [
    {
      "object": "finding",
      "category": "Invalid Link URL",
      "severity": "error",
      "field": "link",
      "affected_count": 634,
      "samples": [
        {
          "row_id": "shopify_US_8012345678901_44012345678901",
          "message": "Link URL is not a valid absolute URL.",
          "field_value": "/products/blue-t-shirt",
          "shopify_admin_url": "https://admin.shopify.com/store/my-store/products/8012345678901"
        }
      ]
    }
  ],
  "meta": {
    "page": 1,
    "per_page": 25,
    "total": 1,
    "total_pages": 1,
    "has_more": false,
    "status": "errors",
    "errors_count": 634,
    "warnings_count": 1902,
    "validated_at": "2026-03-09T14:30:00Z",
    "revalidating": false
  }
}

Finding fields

FieldTypeDescription
category string The issue type, e.g. "Invalid Link URL".
severity string "error" or "warning".
field string | null The feed field the issue applies to.
affected_count integer Total number of products affected by this issue.
samples array Up to ~5 example rows (row_id, message, field_value, shopify_admin_url). Use the export for the complete list.

Meta fields

FieldTypeDescription
status string Overall channel status: "clean", "errors", "warnings", "unvalidated", or "unsupported".
errors_count integer Total error-affected products across all categories.
warnings_count integer Total warning-affected products across all categories.
validated_at string | null ISO 8601 timestamp of the last validation run.
revalidating boolean True when a (re)validation was triggered by this read; poll until false for fresh findings.

Errors

StatusCodeDescription
404resource_not_foundThe feed does not exist, or the channel is not connected to it.

Mute a finding

POST /v1/feeds/:feed_id/channels/:channel_slug/finding_mutes

Suppresses a specific finding (by category + field + row_id) from the active report — useful for known-acceptable issues so the error signal stays actionable. Idempotent on that triple.

Expiry is expressed as muted_until (an absolute timestamp; null means permanent) in the response. On input you can provide muted_until directly, or a convenience duration / days; precedence is muted_until > duration > days, defaulting to permanent.

Required scope: write_feeds

Parameters

ParameterTypeRequiredDescription
categorystringYesThe finding category to mute.
fieldstringNoThe field the finding applies to.
row_idstringNoA specific product row to mute.
muted_untilstringNoAbsolute expiry (ISO 8601).
durationstringNoRelative expiry: 30d, 90d, or permanent.
daysintegerNoRelative expiry in days.

Request

curl -X POST https://app.simpleproductfeeds.com/v1/feeds/feed_1/channels/google/finding_mutes \
  -H "Authorization: Bearer spf_live_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"category": "Missing Units", "field": "shipping_weight", "row_id": "shopify_US_801...", "duration": "30d"}'

Response

{
  "data": {
    "id": 14,
    "object": "finding_mute",
    "category": "Missing Units",
    "field": "shipping_weight",
    "row_id": "shopify_US_801...",
    "muted_until": "2026-04-08T14:30:00Z",
    "created_at": "2026-03-09T14:30:00Z"
  }
}

Remove a mute

DELETE /v1/feeds/:feed_id/channels/:channel_slug/finding_mutes/:id

Deletes a mute, un-suppressing its finding. Returns 204 No Content.

Required scope: write_feeds

curl -X DELETE https://app.simpleproductfeeds.com/v1/feeds/feed_1/channels/google/finding_mutes/14 \
  -H "Authorization: Bearer spf_live_sk_your_key_here"

Export findings

POST /v1/feeds/:feed_id/channels/:channel_slug/findings_exports

Triggers an asynchronous CSV export of the full row-level findings for a channel (the list endpoint only returns aggregated categories with a few samples). Optionally narrow the export to specific categories; omit categories to export all. Repeat requests with the same filter reuse the in-flight export.

Poll Get export status until status is ready, then download from download_url.

Required scope: write_feeds

Parameters

ParameterTypeDescription
categoriesarrayOptional list of { "category": "...", "field": "..." } objects to narrow the export. Omit for all.

Request

curl -X POST https://app.simpleproductfeeds.com/v1/feeds/feed_1/channels/google/findings_exports \
  -H "Authorization: Bearer spf_live_sk_your_key_here"

Response

{
  "data": {
    "id": 8,
    "object": "findings_export",
    "status": "pending",
    "row_count": null,
    "download_url": null,
    "error": null
  }
}

Get export status

GET /v1/feeds/:feed_id/channels/:channel_slug/findings_exports/:id

Polls an export. Once status is ready, download_url is a time-limited link to the CSV.

Required scope: read_feeds

Response

{
  "data": {
    "id": 8,
    "object": "findings_export",
    "status": "ready",
    "row_count": 2560,
    "download_url": "https://files.simpleproductfeeds.com/findings/...csv?signature=...",
    "error": null
  }
}

Export status values

StatusDescription
pendingQueued, not started.
processingThe export is being generated.
readyComplete; download_url is available.
failedGeneration failed; see error.