Recoup

Get started with Recoup.

API REFERENCE

Get comments

On this page
GET/api/comments

Read existing stored comments on posts linked to a creator the caller can access. Authenticate with exactly one x-api-key or Authorization: Bearer credential. Caller identity comes from authentication; artist_account_id is the required target creator UUID (the retained wire name), not a caller override. account_id and other unknown or repeated query parameters return 400.

Access uses direct roster, shared-organization and Recoup-administrator checks, plus endpoint-local self-creator and owning-organization-key reads. These read rules do not grant artist mutation permission. Missing and denied targets both return 403. Access is checked on each request; this is not an atomic guarantee against revocation during an executing request. Ownership follows the creator’s linked socials through the post, not the commenter’s social_id. Optional post_id is a stored posts.id UUID, never a URL, and only narrows the authorized linked-post set. An unrelated post or no linked socials returns an empty page; neither permits an unscoped read.

page defaults to 1 and limit to 10; omitted or empty values use these defaults. Both otherwise require positive integers. Larger positive limits are accepted and clamped to 100; pagination.limit reports the effective value. Requests must satisfy page × effective_limit <= 2147483647 or return 400. Comments are ordered by commented_at descending, then id descending. Counts use the same ownership/post filter. Offset pages are deterministic for a fixed dataset, not a frozen snapshot during concurrent changes. A page beyond the results can be empty while retaining a nonzero exact total; no results means total_pages=0. A missing exact count is a 500, not an invented zero.

Each result has only id, post_id, social_id, comment and commented_at. Saved nulls are preserved in the nullable fields; a missing comment author/text is not invented. The stored post join determines inclusion; nullable post_id describes the retained row projection, not permission to read unlinked rows. No joined profile, account or grant metadata is returned. GET success and errors use Cache-Control: private, no-store. Authentication failures are 401; lookup failures are a masked 500 with no unscoped/provider fallback.

This reads saved evidence and does not start scraping, enrichment, billing or comment-writing work. The existing link lookup reads at most 10,000 social links; stored reads do not establish complete ingestion/history, a live report, or the original customer weekly-report journey. The implementation is merged in API #1062; hosted/customer verification remains separate in Mono #327/app #2023.

Authentication

x-api-key in header

bearerAuth bearer

Request

cURL
curl --request GET \
  --url 'https://api.recoupable.dev/api/comments?artist_account_id=11111111-1111-4111-8111-111111111111' \
  --header 'x-api-key: YOUR_API_KEY'

Replace the YOUR_ placeholders with your values. Required query parameters are included; optional parameters are listed below.

Try it

Fill in the fields, send the request from your browser, and read the live response. The curl below updates as you type.

Kept in this browser tab only and cleared when it closes.

cURL for this request
curl --request GET \
  --url 'https://api.recoupable.dev/api/comments'

Parameters

Query parameters

artist_account_idstringrequired

Required target creator account UUID, using the retained artist wire name. It never overrides the authenticated caller.

post_idstring

Optional stored posts.id UUID. Narrows the authorized linked-post set; an unrelated stored post returns an empty page. This is not a post URL.

pageinteger

Positive integer page, default 1 for omitted or empty values. page × effective_limit must not exceed 2147483647.

Default: 1

limitinteger

Positive requested page size, default 10 for omitted or empty values. Values above 100 are accepted and clamped to 100; the response reports the effective size.

Default: 10

Responses

200Stored comments and exact scoped pagination
Cache-Controlresponse header

All GET success and error responses disable shared caching.

application/json

statusstring · enumrequired

Status of the request

Values: "success"

commentsarray<Comment>required

Saved comments within the authorized creator’s linked-post set and optional post UUID filter.

Item properties for comments
idstringrequired

UUID of the comment

format: uuid

post_idstring | nullrequired

Stored post UUID when present. Saved nullable row shape is retained; ownership is still enforced through the linked post join.

format: uuid

social_idstring | nullrequired

Stored commenter social UUID, or null when absent. This is not the creator ownership filter.

format: uuid

commentstring | nullrequired

Saved comment text, or null when unavailable; no text is synthesized.

commented_atstringrequired

Timestamp with timezone of when the comment was made

format: date-time

paginationobjectrequired

Pagination metadata for the response

Properties for pagination
total_countintegerrequired

Exact total within the same authorized linked-post and optional post filter.

minimum: 0

pageintegerrequired

Current page number

minimum: 1

limitintegerrequired

Effective page size after clamping to 100.

minimum: 1 · maximum: 100

total_pagesintegerrequired

Ceiling of total_count/effective limit; zero when total_count is zero.

minimum: 0

400Invalid, repeated, unknown or unsupported-offset query parameters
Cache-Controlresponse header

All GET success and error responses disable shared caching.

application/json

statusstring · enumrequired

Values: "error"

errorstringrequired
missing_fieldsarray<string>required

Validation path, possibly empty for unknown query keys.

Item properties for missing_fields

string

401Missing/conflicting credentials or rejected authentication; existing error or message envelope
Cache-Controlresponse header

All GET success and error responses disable shared caching.

application/json

anyOf · object 1
statusstring · enumrequired

Always error.

Values: "error"

errorstringrequired

Human-readable error message or documented error code.

Additional properties

any

anyOf · object 2
statusstring · enumrequired

Always error.

Values: "error"

messagestringrequired

Human-readable authentication error message.

Additional properties

any

403Target is missing or not accessible; both use the same denial
Cache-Controlresponse header

All GET success and error responses disable shared caching.

application/json

statusstring · enumrequired

Always error.

Values: "error"

errorstringrequired

Human-readable error message or documented error code.

Additional properties

any

500Masked lookup/count failure; no unscoped or provider fallback
Cache-Controlresponse header

All GET success and error responses disable shared caching.

application/json

statusstring · enumrequired

Always error.

Values: "error"

errorstringrequired

Human-readable error message or documented error code.

Additional properties

any

Full specification

Download the OpenAPI file for complete schemas, constraints, and examples.

Download social.json
View operation source
json
{
  "operationId": "getComments",
  "description": "Read existing stored comments on posts linked to a creator the caller can access. Authenticate with exactly one x-api-key or Authorization: Bearer credential. Caller identity comes from authentication; artist_account_id is the required target creator UUID (the retained wire name), not a caller override. account_id and other unknown or repeated query parameters return 400.\n\nAccess uses direct roster, shared-organization and Recoup-administrator checks, plus endpoint-local self-creator and owning-organization-key reads. These read rules do not grant artist mutation permission. Missing and denied targets both return 403. Access is checked on each request; this is not an atomic guarantee against revocation during an executing request. Ownership follows the creator’s linked socials through the post, not the commenter’s social_id. Optional post_id is a stored posts.id UUID, never a URL, and only narrows the authorized linked-post set. An unrelated post or no linked socials returns an empty page; neither permits an unscoped read.\n\npage defaults to 1 and limit to 10; omitted or empty values use these defaults. Both otherwise require positive integers. Larger positive limits are accepted and clamped to 100; pagination.limit reports the effective value. Requests must satisfy page × effective_limit <= 2147483647 or return 400. Comments are ordered by commented_at descending, then id descending. Counts use the same ownership/post filter. Offset pages are deterministic for a fixed dataset, not a frozen snapshot during concurrent changes. A page beyond the results can be empty while retaining a nonzero exact total; no results means total_pages=0. A missing exact count is a 500, not an invented zero.\n\nEach result has only id, post_id, social_id, comment and commented_at. Saved nulls are preserved in the nullable fields; a missing comment author/text is not invented. The stored post join determines inclusion; nullable post_id describes the retained row projection, not permission to read unlinked rows. No joined profile, account or grant metadata is returned. GET success and errors use Cache-Control: private, no-store. Authentication failures are 401; lookup failures are a masked 500 with no unscoped/provider fallback.\n\nThis reads saved evidence and does not start scraping, enrichment, billing or comment-writing work. The existing link lookup reads at most 10,000 social links; stored reads do not establish complete ingestion/history, a live report, or the original customer weekly-report journey. The implementation is merged in API #1062; hosted/customer verification remains separate in Mono #327/app #2023.",
  "parameters": [
    {
      "name": "artist_account_id",
      "in": "query",
      "description": "Required target creator account UUID, using the retained artist wire name. It never overrides the authenticated caller.",
      "required": true,
      "schema": {
        "type": "string",
        "format": "uuid"
      },
      "example": "11111111-1111-4111-8111-111111111111"
    },
    {
      "name": "post_id",
      "in": "query",
      "description": "Optional stored posts.id UUID. Narrows the authorized linked-post set; an unrelated stored post returns an empty page. This is not a post URL.",
      "required": false,
      "schema": {
        "type": "string",
        "format": "uuid"
      },
      "example": "22222222-2222-4222-8222-222222222222"
    },
    {
      "name": "page",
      "in": "query",
      "description": "Positive integer page, default 1 for omitted or empty values. page × effective_limit must not exceed 2147483647.",
      "required": false,
      "schema": {
        "type": "integer",
        "minimum": 1,
        "default": 1
      },
      "example": 1
    },
    {
      "name": "limit",
      "in": "query",
      "description": "Positive requested page size, default 10 for omitted or empty values. Values above 100 are accepted and clamped to 100; the response reports the effective size.",
      "required": false,
      "schema": {
        "type": "integer",
        "minimum": 1,
        "default": 10
      },
      "example": 10
    }
  ],
  "responses": {
    "200": {
      "description": "Stored comments and exact scoped pagination",
      "headers": {
        "Cache-Control": {
          "description": "All GET success and error responses disable shared caching.",
          "schema": {
            "type": "string",
            "const": "private, no-store"
          },
          "example": "private, no-store"
        }
      },
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/CommentsResponse"
          }
        }
      }
    },
    "400": {
      "description": "Invalid, repeated, unknown or unsupported-offset query parameters",
      "headers": {
        "Cache-Control": {
          "description": "All GET success and error responses disable shared caching.",
          "schema": {
            "type": "string",
            "const": "private, no-store"
          },
          "example": "private, no-store"
        }
      },
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/CommentsValidationErrorResponse"
          }
        }
      }
    },
    "401": {
      "description": "Missing/conflicting credentials or rejected authentication; existing error or message envelope",
      "headers": {
        "Cache-Control": {
          "description": "All GET success and error responses disable shared caching.",
          "schema": {
            "type": "string",
            "const": "private, no-store"
          },
          "example": "private, no-store"
        }
      },
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/CommentsAuthenticationErrorResponse"
          }
        }
      }
    },
    "403": {
      "description": "Target is missing or not accessible; both use the same denial",
      "headers": {
        "Cache-Control": {
          "description": "All GET success and error responses disable shared caching.",
          "schema": {
            "type": "string",
            "const": "private, no-store"
          },
          "example": "private, no-store"
        }
      },
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/CommentsErrorResponse"
          }
        }
      }
    },
    "500": {
      "description": "Masked lookup/count failure; no unscoped or provider fallback",
      "headers": {
        "Cache-Control": {
          "description": "All GET success and error responses disable shared caching.",
          "schema": {
            "type": "string",
            "const": "private, no-store"
          },
          "example": "private, no-store"
        }
      },
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/CommentsErrorResponse"
          }
        }
      }
    }
  },
  "summary": "Read saved comments on an authorized creator’s linked posts",
  "security": [
    {
      "apiKeyAuth": []
    },
    {
      "bearerAuth": []
    }
  ]
}