Skip to content
ContentRemovalDeskDocumentation

THE COMPLETE CONTRACT

API reference

Every endpoint, parameter and response. Examples use standard HTTP clients and your server’s environment variables.

30 endpoints

Read your agency API connection

Read credential scopes, expiry, assigned agency workspace, and live engine configuration. The legacy partner field identifies the agency API account.

Permissionsany valid agency key

Response

Returns 200 on success.

partnerobjectrequired
Show nested fields
idstringrequired
namestringrequired
kindstringrequired

Always agency.

workspace_idstring | nullrequired
key_idstring | nullrequired
scopesarray[]required
expires_atinteger | nullrequired

Key expiration in epoch milliseconds, or null when there is no scheduled expiration. Revocation, agency verification, ownership, and scope checks still apply.

environmentstringrequired

Always live.

workspacesarray[]required
Show nested fields
idstringrequired
external_idstringrequired
namestringrequired
engine_configuredbooleanrequired

Retries & errors

This read can be retried with exponential backoff. Honor Retry-After when it is returned.

Documented statuses: 200, 400, 401, 403, 404, 409, 429, 502, 503, 504. Error handling guide

GET/v1/me
curl --request GET 'https://api.crd.systems/v1/me' \
  --header "Authorization: Bearer $CRD_API_KEY"
Use your secret key in the environment variable.
Example response · 200
{
  "partner": {
    "id": "ptn_example",
    "name": "Example Agency",
    "kind": "agency"
  },
  "workspace_id": "wsp_example",
  "key_id": "key_example",
  "scopes": [
    "workspaces:read",
    "creators:read",
    "creators:write"
  ],
  "expires_at": null,
  "environment": "live",
  "workspaces": [
    {
      "id": "wsp_example",
      "name": "Example Agency",
      "external_id": "agency_001"
    }
  ],
  "engine_configured": true
}

Retrieve your assigned workspace

Requires workspaces:read. API customers cannot create agencies or additional workspaces.

Permissionsworkspaces:read

Parameters

idpathrequired

Response

Returns 200 on success.

idstringrequired
external_idstringrequired
namestringrequired
created_atintegerrequired

Unix epoch milliseconds.

Retries & errors

This read can be retried with exponential backoff. Honor Retry-After when it is returned.

Documented statuses: 200, 400, 401, 403, 404, 409, 429, 502, 503, 504. Error handling guide

GET/v1/workspaces/{id}
curl --request GET 'https://api.crd.systems/v1/workspaces/wsp_example' \
  --header "Authorization: Bearer $CRD_API_KEY"
Use your secret key in the environment variable.
Example response · 200
{
  "id": "wsp_example",
  "external_id": "agency_001",
  "name": "Example Agency",
  "created_at": 1790035200000
}

Link or invite an agency creator

Requires creators:write. Provide an existing agency crd_user_id or email, first_name, last_name for a real CRD invitation. Existing creators must belong to the agency and not be staff. Aliases and supported profile URLs update actual CRD identity data; mandate/contact evidence is not fabricated. Invitations send real email and require acceptance/onboarding. Enrollment starts inactive. Retry with identical external_id and payload; changed input conflicts. If roster sync already imported the same CRD user, enrollment reuses its stable API creator ID and may replace the automatic crd:UUID external ID with the supplied ID. A different already-assigned external ID conflicts. No duplicate creator or usage interval is created. New invitation enrollment triggers email; email_sent reports provider acceptance, not inbox delivery or creator acceptance. An identical retry does not resend an invitation. Existing confirmed agency creators can link without invitation. Enrollment never activates protection automatically.

Permissionscreators:write

Request body

workspace_idstringrequired

Maximum 200 characters.

external_idstringrequired

Maximum 200 characters.

display_namestringrequired

Maximum 160 characters.

aliasesarray[]

Pseudonyms, alternate spellings, and usernames without a required social-network label. Merged into the native CRD search aliases.

Up to 30 items.

profile_urlsarray[]

Full canonical HTTPS profile URLs using the same creator-platform rules as the portal. CRD derives the platform and username. Supports the portal platform catalog, X/Twitter aliases and RevealMe (reveal.me). Unknown public HTTPS hosts are stored as website profiles, not newly supported social platforms. No tracking query, fragment, credentials, private host or post URL. These links do not prove account ownership.

Up to 20 items.

crd_user_idstring
emailstring

Maximum 254 characters.

first_namestring

Maximum 100 characters.

last_namestring

Maximum 100 characters.

localestring

Values: en fr

Response

Returns 201 on success.

idstringrequired
workspace_idstringrequired
external_idstringrequired
display_namestringrequired
aliasesarray[]required
profile_urlsarray[]required

Full canonical HTTPS profile URLs using the same creator-platform rules as the portal. CRD derives the platform and username. Supports the portal platform catalog, X/Twitter aliases and RevealMe (reveal.me). Unknown public HTTPS hosts are stored as website profiles, not newly supported social platforms. No tracking query, fragment, credentials, private host or post URL. These links do not prove account ownership.

protection_statusstringrequired

Current API dispatch state. For active_creators billing, observed portal activations synchronize this state; valid authorization and paid entitlement remain required.

Values: not_activated active paused

created_atintegerrequired

Unix epoch milliseconds.

enrollment_statusstringrequired

Current CRD linkage state, for example invited, pending_onboarding, linked, enrolling, failed, or uncertain.

crd_user_idstring | nullrequired
invitation_idstring | nullrequired
simulatedbooleanrequired

Always false.

scan_schedule_managed_bystringrequired

Legacy response field. The API controls its active-protection setting and on-demand scan eligibility; the existing CRD plan controls recurring scans.

Always api.

crd_subscription_managed_bystringrequired

CRD owns billing and recurring scheduling. Under active_creators billing the protection PUT changes the same billable activation as the portal; legacy agreements retain API-dispatch-only behavior.

Always crd.

email_sentboolean

Present on a new enrollment response. True means the email provider accepted the invitation email; it does not prove inbox delivery, acceptance, authorization, or activation.

identity_sync_pendingbooleanrequired

True when an accepted invitation still needs legal onboarding before its submitted identity data can be applied.

billingobject
Show nested fields
modelstringrequired

Values: legacy active_creators

unit_price_centsinteger | nullrequired
currencystringrequired

Always EUR.

activatedbooleanrequired
operation_idstring

Retries & errors

Reuse the same external_id and complete payload for retries. Changed input under the same external ID conflicts. Use PATCH to update a linked creator’s identity.

Documented statuses: 200, 201, 400, 401, 403, 404, 409, 413, 415, 429, 502, 503, 504. Error handling guide

POST/v1/creators
curl --request POST 'https://api.crd.systems/v1/creators' \
  --header "Authorization: Bearer $CRD_API_KEY" \
  --header 'Content-Type: application/json' \
  --data '{
  "workspace_id": "wsp_example",
  "external_id": "creator_001",
  "crd_user_id": "33333333-3333-4333-8333-333333333333",
  "display_name": "Example Creator",
  "aliases": [
    "example_creator"
  ],
  "profile_urls": [
    "https://onlyfans.com/example_creator"
  ]
}'
Use your secret key in the environment variable.
Example response · 201
{
  "id": "crt_example",
  "workspace_id": "wsp_example",
  "external_id": "creator_001",
  "display_name": "Example Creator",
  "aliases": [
    "example_creator"
  ],
  "profile_urls": [
    "https://onlyfans.com/example_creator"
  ],
  "protection_status": "not_activated",
  "created_at": 1790035200000,
  "enrollment_status": "linked",
  "crd_user_id": "33333333-3333-4333-8333-333333333333",
  "invitation_id": null,
  "simulated": false,
  "scan_schedule_managed_by": "api",
  "crd_subscription_managed_by": "crd",
  "identity_sync_pending": false,
  "email_sent": false
}

Read your canonical agency roster

Requires creators:read. Reads the existing CRD agency roster, imports missing API mappings without activating billing, and returns stable API creator IDs with current names, aliases, official URLs, authorization, entitlement, and eligibility. Changes made in the CRD app are reflected on reads. The after cursor is a CRD user UUID, not an API creator ID.

Permissionscreators:read

Parameters

limitquery

afterquery

Canonical CRD user UUID from next_cursor.

Response

Returns 200 on success.

dataarray[]required
Show nested fields
idstringrequired
workspace_idstringrequired
external_idstringrequired
display_namestringrequired
aliasesarray[]required
profile_urlsarray[]required

Full canonical HTTPS profile URLs using the same creator-platform rules as the portal. CRD derives the platform and username. Supports the portal platform catalog, X/Twitter aliases and RevealMe (reveal.me). Unknown public HTTPS hosts are stored as website profiles, not newly supported social platforms. No tracking query, fragment, credentials, private host or post URL. These links do not prove account ownership.

protection_statusstringrequired

API schedule state, separate from enrollment and eligibility. Activation and resumption require an explicit protection PUT after current eligibility checks.

Values: not_activated active paused

created_atintegerrequired

Unix epoch milliseconds.

enrollment_statusstringrequired

Current CRD linkage state, for example invited, pending_onboarding, linked, enrolling, failed, or uncertain.

crd_user_idstring | nullrequired
invitation_idstring | nullrequired
simulatedbooleanrequired

Always false.

scan_schedule_managed_bystringrequired

Legacy response field. The API controls its active-protection setting and on-demand scan eligibility; the existing CRD plan controls recurring scans.

Always api.

crd_subscription_managed_bystringrequired

Always 'crd': the creator's actual CRD subscription and its own automatic scan cadence are managed entirely by CRD, independent of this API's protection_status.

Always crd.

email_sentboolean

Present on a new enrollment response. True means the email provider accepted the invitation email; it does not prove inbox delivery, acceptance, authorization, or activation.

authorizationobjectrequired
Show nested fields
approvedbooleanrequired
statusstring
expires_atstring | null
entitlementobjectrequired
Show nested fields
activebooleanrequired
sourcestring
eligiblebooleanrequired
identity_sync_pendingbooleanrequired

True when an accepted invitation still needs legal onboarding before its submitted identity data can be applied.

next_cursorstring | nullrequired

Last canonical CRD user UUID for the next roster page, or null.

Retries & errors

This read can be retried with exponential backoff. Honor Retry-After when it is returned.

Documented statuses: 200, 400, 401, 403, 404, 409, 429, 502, 503, 504. Error handling guide

GET/v1/creators
curl --request GET 'https://api.crd.systems/v1/creators?limit=25' \
  --header "Authorization: Bearer $CRD_API_KEY"
Use your secret key in the environment variable.
Example response · 200
{
  "data": [
    {
      "id": "crt_example",
      "workspace_id": "wsp_example",
      "external_id": "creator_001",
      "display_name": "Example Creator",
      "aliases": [
        "example_creator"
      ],
      "profile_urls": [
        "https://onlyfans.com/example_creator"
      ],
      "protection_status": "not_activated",
      "created_at": 1790035200000,
      "enrollment_status": "linked",
      "crd_user_id": "33333333-3333-4333-8333-333333333333",
      "invitation_id": null,
      "simulated": false,
      "scan_schedule_managed_by": "api",
      "crd_subscription_managed_by": "crd",
      "identity_sync_pending": false,
      "authorization": {
        "approved": true,
        "status": "approved",
        "expires_at": null
      },
      "entitlement": {
        "active": true,
        "source": "agency_subscription"
      },
      "eligible": true
    }
  ],
  "next_cursor": null
}

Read creator linkage and eligibility

Requires creators:read. Refreshes the shared CRD identity so changes made in the agency dashboard are returned by the API. Resolves invitation onboarding and returns actual authorization, entitlement, and eligibility.

Permissionscreators:read

Parameters

idpathrequired

Response

Returns 200 on success.

idstringrequired
workspace_idstringrequired
external_idstringrequired
display_namestringrequired
aliasesarray[]required
profile_urlsarray[]required

Full canonical HTTPS profile URLs using the same creator-platform rules as the portal. CRD derives the platform and username. Supports the portal platform catalog, X/Twitter aliases and RevealMe (reveal.me). Unknown public HTTPS hosts are stored as website profiles, not newly supported social platforms. No tracking query, fragment, credentials, private host or post URL. These links do not prove account ownership.

protection_statusstringrequired

API schedule state, separate from enrollment and eligibility. Activation and resumption require an explicit protection PUT after current eligibility checks.

Values: not_activated active paused

created_atintegerrequired

Unix epoch milliseconds.

enrollment_statusstringrequired

Current CRD linkage state, for example invited, pending_onboarding, linked, enrolling, failed, or uncertain.

crd_user_idstring | nullrequired
invitation_idstring | nullrequired
simulatedbooleanrequired

Always false.

scan_schedule_managed_bystringrequired

Legacy response field. The API controls its active-protection setting and on-demand scan eligibility; the existing CRD plan controls recurring scans.

Always api.

crd_subscription_managed_bystringrequired

Always 'crd': the creator's actual CRD subscription and its own automatic scan cadence are managed entirely by CRD, independent of this API's protection_status.

Always crd.

email_sentboolean

Present on a new enrollment response. True means the email provider accepted the invitation email; it does not prove inbox delivery, acceptance, authorization, or activation.

authorizationobjectrequired
Show nested fields
approvedbooleanrequired
statusstring
expires_atstring | null
entitlementobjectrequired
Show nested fields
activebooleanrequired
sourcestring
eligiblebooleanrequired
identity_sync_pendingbooleanrequired

True when an accepted invitation still needs legal onboarding before its submitted identity data can be applied.

Retries & errors

This read can be retried with exponential backoff. Honor Retry-After when it is returned.

Documented statuses: 200, 400, 401, 403, 404, 409, 429, 502, 503, 504. Error handling guide

GET/v1/creators/{id}
curl --request GET 'https://api.crd.systems/v1/creators/crt_example' \
  --header "Authorization: Bearer $CRD_API_KEY"
Use your secret key in the environment variable.
Example response · 200
{
  "id": "crt_example",
  "workspace_id": "wsp_example",
  "external_id": "creator_001",
  "display_name": "Example Creator",
  "aliases": [
    "example_creator"
  ],
  "profile_urls": [
    "https://onlyfans.com/example_creator"
  ],
  "protection_status": "not_activated",
  "created_at": 1790035200000,
  "enrollment_status": "linked",
  "crd_user_id": "33333333-3333-4333-8333-333333333333",
  "invitation_id": null,
  "simulated": false,
  "scan_schedule_managed_by": "api",
  "crd_subscription_managed_by": "crd",
  "identity_sync_pending": false,
  "authorization": {
    "approved": true,
    "status": "approved",
    "expires_at": null
  },
  "entitlement": {
    "active": true,
    "source": "agency_subscription"
  },
  "eligible": true
}

Update the shared CRD creator identity

Requires creators:write and a linked current agency creator. Omitted fields are unchanged. display_name updates the CRD name; aliases and supported profile URLs merge into existing CRD identity data. Reads in the API and agency dashboard use the same creator state. This is not removal/replacement of the complete alias or platform collection. Identical retries are safe for these additive/set operations.

Permissionscreators:write

Parameters

idpathrequired

Request body

display_namestring

Maximum 160 characters.

aliasesarray[]

Pseudonyms, alternate spellings, and usernames without a required social-network label. Merged into the native CRD search aliases.

Up to 30 items.

profile_urlsarray[]

Full canonical HTTPS profile URLs using the same creator-platform rules as the portal. CRD derives the platform and username. Supports the portal platform catalog, X/Twitter aliases and RevealMe (reveal.me). Unknown public HTTPS hosts are stored as website profiles, not newly supported social platforms. No tracking query, fragment, credentials, private host or post URL. These links do not prove account ownership.

Up to 20 items.

Response

Returns 200 on success.

idstringrequired
workspace_idstringrequired
external_idstringrequired
display_namestringrequired
aliasesarray[]required
profile_urlsarray[]required

Full canonical HTTPS profile URLs using the same creator-platform rules as the portal. CRD derives the platform and username. Supports the portal platform catalog, X/Twitter aliases and RevealMe (reveal.me). Unknown public HTTPS hosts are stored as website profiles, not newly supported social platforms. No tracking query, fragment, credentials, private host or post URL. These links do not prove account ownership.

protection_statusstringrequired

API schedule state, separate from enrollment and eligibility. Activation and resumption require an explicit protection PUT after current eligibility checks.

Values: not_activated active paused

created_atintegerrequired

Unix epoch milliseconds.

enrollment_statusstringrequired

Current CRD linkage state, for example invited, pending_onboarding, linked, enrolling, failed, or uncertain.

crd_user_idstring | nullrequired
invitation_idstring | nullrequired
simulatedbooleanrequired

Always false.

scan_schedule_managed_bystringrequired

Legacy response field. The API controls its active-protection setting and on-demand scan eligibility; the existing CRD plan controls recurring scans.

Always api.

crd_subscription_managed_bystringrequired

Always 'crd': the creator's actual CRD subscription and its own automatic scan cadence are managed entirely by CRD, independent of this API's protection_status.

Always crd.

email_sentboolean

Present on a new enrollment response. True means the email provider accepted the invitation email; it does not prove inbox delivery, acceptance, authorization, or activation.

authorizationobjectrequired
Show nested fields
approvedbooleanrequired
statusstring
expires_atstring | null
entitlementobjectrequired
Show nested fields
activebooleanrequired
sourcestring
eligiblebooleanrequired
identity_sync_pendingbooleanrequired

True when an accepted invitation still needs legal onboarding before its submitted identity data can be applied.

Retries & errors

Omitted fields stay unchanged. Aliases and platforms merge into the existing CRD identity. Repeating the same update does not add duplicate identity entries.

Documented statuses: 200, 400, 401, 403, 404, 409, 413, 415, 429, 502, 503, 504. Error handling guide

PATCH/v1/creators/{id}
curl --request PATCH 'https://api.crd.systems/v1/creators/crt_example' \
  --header "Authorization: Bearer $CRD_API_KEY" \
  --header 'Content-Type: application/json' \
  --data '{
  "display_name": "Example Creator",
  "aliases": [
    "example_creator_official"
  ],
  "profile_urls": [
    "https://mym.fans/fr/example_mym"
  ]
}'
Use your secret key in the environment variable.
Example response · 200
{
  "id": "crt_example",
  "workspace_id": "wsp_example",
  "external_id": "creator_001",
  "display_name": "Example Creator",
  "aliases": [
    "example_creator",
    "example_creator_official"
  ],
  "profile_urls": [
    "https://onlyfans.com/example_creator",
    "https://mym.fans/example_mym"
  ],
  "protection_status": "not_activated",
  "created_at": 1790035200000,
  "enrollment_status": "linked",
  "crd_user_id": "33333333-3333-4333-8333-333333333333",
  "invitation_id": null,
  "simulated": false,
  "scan_schedule_managed_by": "api",
  "crd_subscription_managed_by": "crd",
  "identity_sync_pending": false,
  "authorization": {
    "approved": true,
    "status": "approved",
    "expires_at": null
  },
  "entitlement": {
    "active": true,
    "source": "agency_subscription"
  },
  "eligible": true
}

Cancel an invitation or remove incomplete onboarding

Requires creators:write. Pending API invitations are cancelled. Linked creators can be detached only before onboarding completes, matching agency-remove-member. Removes agency membership and pauses API protection; never deletes the user, leaks or legal records. Completed onboarding returns creator_onboarding_completed. Retries after successful detachment are safe.

Permissionscreators:write

Parameters

idpathrequired

Response

Returns 200 on success.

cancelledboolean
removedboolean

Retries & errors

Cancels a pending invitation or detaches an accepted creator before onboarding completes. Completed creators return 409 creator_onboarding_completed. User and legal/leak records are retained. Cancelling a pending invitation frees its external ID for a fresh enrollment.

Documented statuses: 200, 400, 401, 403, 404, 409, 429, 502, 503, 504. Error handling guide

DELETE/v1/creators/{id}
curl --request DELETE 'https://api.crd.systems/v1/creators/crt_example' \
  --header "Authorization: Bearer $CRD_API_KEY"
Use your secret key in the environment variable.
Example response · 200
{
  "cancelled": true
}

Activate or pause API protection

Requires protection:write. Read creator.billing.model first. For active_creators, activation or pause changes the agency subscription and recurring protection in both systems. Supply expected_price_cents from the corresponding creator.billing activation or pause quote and a stable UUID Idempotency-Key. First activation returns 202 with checkout_url; the owner must complete checkout. One seven-day trial per agency. Use billing.activation_quote.unit_price_cents or billing.pause_quote.unit_price_cents and confirm its monthly_total_cents. Pricing is EUR 69 each for 1–9 active creators, EUR 59 each for every creator from 10. Changes recalculate the entire roster with proration: increases invoice immediately outside trial; decreases credit the next invoice. Moving from 10 to 9 increases the total from EUR 590 to EUR 621. A paid current invoice is required before credits. Never retry with a new key after an uncertain response. For legacy agreements, this route controls API dispatch only and does not change subscription billing. Current agency KYC, membership, signed agency agreement and creator mandate are enforced. Enrollment alone is free and inactive. Separately negotiated graduated agreements retain their private rates. For pricing_model=graduated, unit_price_cents is the base confirmation rate; always use monthly_total_cents for the total, never multiply quantity by that base. No repeat trial after a prepaid transition.

Permissionsprotection:write

Parameters

idpathrequired

Idempotency-Keyheader

Required UUID for active_creators billing; reuse for the identical request until reconciled.

Request body

statusstringrequired

Values: active paused

expected_price_centsinteger

Required for active_creators billing. Monthly EUR price in cents explicitly approved for this change.

expected_quantityinteger

Confirm activation_quote.quantity or pause_quote.quantity to reject a stale roster total.

Maximum: 1000.

Response

Returns 202 on success.

statusstringrequired

Values: checkout payment_pending

checkout_urlstring | null
operation_idstringrequired

Retries & errors

For active_creators, get owner approval of the current creator.billing.activation_quote.unit_price_cents (or pause_quote.unit_price_cents when pausing) and use a stable UUID Idempotency-Key. Retry the identical key and body after uncertainty. Complete checkout, then read the creator to confirm activation. Legacy agreements retain the API-dispatch-only switch without a price field.

Documented statuses: 200, 202, 400, 401, 403, 404, 409, 413, 415, 429, 502, 503, 504. Error handling guide

PUT/v1/creators/{id}/protection
curl --request PUT 'https://api.crd.systems/v1/creators/crt_example/protection' \
  --header "Authorization: Bearer $CRD_API_KEY" \
  --header 'Content-Type: application/json' \
  --header 'Idempotency-Key: example-request-001' \
  --data '{
  "status": "active",
  "expected_price_cents": 6900
}'
Use your secret key in the environment variable.
Example response · 202
{
  "status": "checkout",
  "operation_id": "77777777-7777-4777-8777-777777777777",
  "checkout_url": "https://checkout.stripe.com/example"
}

Queue a real CRD scan

Requires scans:write and active API protection. Returns before completion. Idempotency-Key is agency-wide for scan requests. Replays preserve the exact engine request identity; uncertain dispatch is reconciled rather than duplicated. Scans use actual CRD reporting workflows and can have real effects.

Permissionsscans:write

Parameters

idpathrequired

Idempotency-Keyheaderrequired

Stable key for one logical operation. Reuse unchanged for retries.

Request body

Send an empty JSON object: {}.

Response

Returns 202 on success.

idstringrequired
creator_idstringrequired
statusstringrequired

Values: queued dispatching running uncertain completed failed cancelled

sourcestringrequired

Values: manual scheduled

created_atintegerrequired

Unix epoch milliseconds.

finished_atinteger | nullrequired

Unix epoch milliseconds, or null.

error_codestring | nullrequired
crd_job_idstring | nullrequired
simulatedbooleanrequired

Always false.

Retries & errors

Use one Idempotency-Key per logical scan and preserve it across retries. A matching retry returns 200 with the original scan. Reconcile uncertain state rather than creating replacement work.

Documented statuses: 200, 202, 400, 401, 403, 404, 409, 413, 415, 429, 502, 503, 504. Error handling guide

POST/v1/creators/{id}/scans
curl --request POST 'https://api.crd.systems/v1/creators/crt_example/scans' \
  --header "Authorization: Bearer $CRD_API_KEY" \
  --header 'Content-Type: application/json' \
  --header 'Idempotency-Key: example-request-001' \
  --data '{}'
Use your secret key in the environment variable.
Example response · 202
{
  "id": "scn_example",
  "creator_id": "crt_example",
  "status": "queued",
  "source": "manual",
  "created_at": 1790035200000,
  "finished_at": null,
  "error_code": null,
  "crd_job_id": null,
  "simulated": false
}

Read real scan progress

Requires scans:read. Follow queued/running work through completed, failed, or cancelled. dispatching and uncertain mean provider reconciliation is in progress; do not replace the logical request.

Permissionsscans:read

Parameters

idpathrequired

Response

Returns 200 on success.

idstringrequired
creator_idstringrequired
statusstringrequired

Values: queued dispatching running uncertain completed failed cancelled

sourcestringrequired

Values: manual scheduled

created_atintegerrequired

Unix epoch milliseconds.

finished_atinteger | nullrequired

Unix epoch milliseconds, or null.

error_codestring | nullrequired
crd_job_idstring | nullrequired
simulatedbooleanrequired

Always false.

Retries & errors

This read can be retried with exponential backoff. Honor Retry-After when it is returned.

Documented statuses: 200, 400, 401, 403, 404, 409, 429, 502, 503, 504. Error handling guide

GET/v1/scans/{id}
curl --request GET 'https://api.crd.systems/v1/scans/scn_example' \
  --header "Authorization: Bearer $CRD_API_KEY"
Use your secret key in the environment variable.
Example response · 200
{
  "id": "scn_example",
  "creator_id": "crt_example",
  "status": "completed",
  "source": "manual",
  "created_at": 1790035200000,
  "finished_at": 1790035201000,
  "error_code": null,
  "crd_job_id": "44444444-4444-4444-8444-444444444444",
  "simulated": false
}

Read the creator’s native CRD findings

Requires cases:read. Synchronizes existing native CRD leak records for this current agency creator, including manual, scheduled, historical, and API-scan findings. API IDs are stable; status changes are refreshed. Native records without known API-scan provenance have scan_id null and source crd. Use limit up to 100 and after from this creator’s authorized results. Only verified API-scan findings can use the API deindex route.

Permissionscases:read

Parameters

idpathrequired

limitquery

afterquery

Last case ID in this creator’s authorized collection.

Response

Returns 200 on success.

dataarray[]required
Show nested fields
idstringrequired
scan_idstring | nullrequired

Known API scan ID, or null for a native CRD case without API-scan provenance.

creator_idstringrequired
statusstringrequired

Current native CRD finding state observed during synchronization, not a removal confirmation.

urlstringrequired

The finding URL from the creator’s current native CRD leak record.

simulatedbooleanrequired

Always false.

created_atintegerrequired

Unix epoch milliseconds.

sourcestringrequired

crd for native findings without known API-scan provenance; api_scan when a verified API scan mapping exists.

Values: crd api_scan

leak_idstringrequired

The underlying native CRD leak record ID. Use the API case id in public API paths.

updated_atintegerrequired

Native update time in epoch milliseconds, or the imported creation time until native state is observed.

actionableboolean | nullrequired

Native actionability flag when synchronized; null if not yet observed.

dead_on_arrivalboolean | nullrequired

Native dead-on-arrival flag when synchronized; null if not yet observed.

availablebooleanrequired

Whether the synchronized native record remains available. Removal is observed after complete reconciliation.

api_deindex_supportedbooleanrequired

Whether known API-scan provenance supports the API deindex route. Current authorization and entitlement are checked separately.

escalationobject | nullrequired

Latest observed eligibility for paid escalation. Only CRD-selected leaks qualify. Null means not yet synchronized. Revalidated from current CRD records when quoting and reserving payment.

Show nested fields
eligiblebooleanrequired
reasonstring | nullrequired
sitestringrequired
base_amount_centsintegerrequired
currencystringrequired

Always eur.

mandate_requiredbooleanrequired
domainstring | null

Website hostname without www. Use this exact value to group display rows; this is not escalation billing grouping.

favicon_urlstring | null

Google favicon URL, matching the portal. Load with an image fallback; fetching it uses a third-party service.

status_codestring

Values: detected reported in_progress manual_review escalation_required removed unknown

next_cursorstring | nullrequired

Retries & errors

This read can be retried with exponential backoff. Honor Retry-After when it is returned.

Documented statuses: 200, 400, 401, 403, 404, 409, 429, 502, 503, 504. Error handling guide

GET/v1/creators/{id}/cases
curl --request GET 'https://api.crd.systems/v1/creators/crt_example/cases?limit=25' \
  --header "Authorization: Bearer $CRD_API_KEY"
Use your secret key in the environment variable.
Example response · 200
{
  "data": [
    {
      "domain": "example.invalid",
      "favicon_url": "https://www.google.com/s2/favicons?domain=example.invalid&sz=64",
      "status_code": "detected",
      "id": "case_example",
      "scan_id": "scn_example",
      "creator_id": "crt_example",
      "status": "À faire",
      "url": "https://example.invalid/illustrative-finding",
      "simulated": false,
      "created_at": 1790035200000,
      "source": "api_scan",
      "leak_id": "55555555-5555-4555-8555-555555555555",
      "updated_at": 1790035200000,
      "actionable": true,
      "dead_on_arrival": false,
      "available": true,
      "api_deindex_supported": true,
      "escalation": {
        "eligible": false,
        "reason": "not_selected_by_crd",
        "site": "example.invalid",
        "base_amount_cents": 80000,
        "currency": "eur",
        "mandate_required": false
      }
    }
  ],
  "next_cursor": null
}

Report a leak or impersonation account you already found

Requires cases:write. For a URL the integration already knows about, instead of waiting for the next scan to find it. A known social platform (Instagram, TikTok, X/Twitter, Facebook, Reddit, Telegram) is filed as an impersonation account; anything else is filed as a leak and flows into the same removal process a scan-found leak does. Reporting the same URL again returns the existing record (200) rather than creating a duplicate (201). A reported leak later appears through GET on this same path; a reported impersonation account does not yet have a read endpoint of its own — this response is the only confirmation. Reporting requires current creator authorization and entitlement. The returned id is a native CRD UUID, not a case_ API ID. For a leak, read the cases collection and match the URL to obtain its API ID. Follow impersonation status in the agency portal; no impersonation status endpoint or event stream is exposed.

Permissionscases:write

Parameters

idpathrequired

Request body

urlstringrequired

An https:// URL. No credentials in the URL.

descriptionstring

Maximum 2000 characters.

severitystring

Leaks only; ignored for an impersonation account. Defaults to Modéré.

Values: Critique Modéré

Response

Returns 201 on success.

idstringrequired

Native CRD leak or impersonation-account UUID. It is not the case_ API ID. Match a reported leak by URL in GET /v1/creators/{id}/cases before subsequent case operations.

typestringrequired

Values: leak impersonation

creator_idstringrequired

Retries & errors

Reporting the same URL again is harmless: it returns the existing record with 200 instead of a duplicate. This id is a native CRD identifier, not the API case id — for a leak, do not use it in a later escalation request. Use the case_… id from GET .../cases instead, matching on url, once synchronization has picked it up.

Documented statuses: 200, 201, 400, 401, 403, 404, 409, 413, 415, 429, 502, 503, 504. Error handling guide

POST/v1/creators/{id}/cases
curl --request POST 'https://api.crd.systems/v1/creators/crt_example/cases' \
  --header "Authorization: Bearer $CRD_API_KEY" \
  --header 'Content-Type: application/json' \
  --data '{
  "url": "https://example.invalid/reported-leak",
  "description": "Reported by the integration"
}'
Use your secret key in the environment variable.
Example response · 201
{
  "id": "55555555-5555-4555-8555-555555555555",
  "type": "leak",
  "creator_id": "crt_example"
}

Read this creator's whitelisted domains

Requires creators:read. Domains that never become a leak or an impersonation account for this creator — her own scope plus any CRD added globally for every creator. Reading needs only current agency membership, not a valid mandate or entitlement.

Permissionscreators:read

Parameters

idpathrequired

Response

Returns 200 on success.

dataarray[]required
Show nested fields
idstringrequired
domainstringrequired
scopestringrequired

creator: only for this creator. global: CRD added it for every creator; it cannot be removed through this API.

Values: creator global

created_atstringrequired
createdboolean

Present only on the add response: true for a newly whitelisted domain, false if it was already there.

Retries & errors

This read can be retried with exponential backoff. Honor Retry-After when it is returned.

Documented statuses: 200, 400, 401, 403, 404, 409, 502, 503. Error handling guide

GET/v1/creators/{id}/whitelist
curl --request GET 'https://api.crd.systems/v1/creators/crt_example/whitelist' \
  --header "Authorization: Bearer $CRD_API_KEY"
Use your secret key in the environment variable.
Example response · 200
{
  "data": [
    {
      "id": "wl_example",
      "domain": "licensed-reseller.example",
      "scope": "creator",
      "created_at": "2026-09-01T00:00:00.000Z"
    }
  ]
}

Whitelist a domain for this creator

Requires creators:write and current agency membership. Stores a hostname-level exclusion in the existing CRD whitelist; it is not an account-level exemption. Never whitelist a shared social platform to mark one official profile: add that profile to profile_urls instead. Identical repeats return 200 with the existing entry rather than a duplicate (201). Only creator-scoped entries can be removed through the API.

Permissionscreators:write

Parameters

idpathrequired

Request body

domainstringrequired

A bare domain (site.com) or a full URL — either normalizes to the same hostname.

Maximum 253 characters.

Response

Returns 201 on success.

idstringrequired
domainstringrequired
scopestringrequired

creator: only for this creator. global: CRD added it for every creator; it cannot be removed through this API.

Values: creator global

created_atstringrequired
createdboolean

Present only on the add response: true for a newly whitelisted domain, false if it was already there.

Retries & errors

Whitelisting the same domain again is harmless: it returns the existing entry with 200 (created: false) instead of a duplicate. Only the hostname is stored, not a path — never whitelist a shared social-platform hostname (instagram.com and similar) to mark one official account; that would also suppress a real impersonator there. Put their own social profiles in profile_urls instead.

Documented statuses: 200, 201, 400, 401, 403, 404, 409, 413, 415, 502, 503. Error handling guide

POST/v1/creators/{id}/whitelist
curl --request POST 'https://api.crd.systems/v1/creators/crt_example/whitelist' \
  --header "Authorization: Bearer $CRD_API_KEY" \
  --header 'Content-Type: application/json' \
  --data '{
  "domain": "https://licensed-reseller.example"
}'
Use your secret key in the environment variable.
Example response · 201
{
  "id": "wl_example",
  "domain": "licensed-reseller.example",
  "scope": "creator",
  "created_at": "2026-09-01T00:00:00.000Z",
  "created": true
}

Remove a whitelisted domain for this creator

Requires creators:write. Only ever acts on this creator's own entries — a global (CRD-added) entry can never be removed through this API. Removing an entry that is not there, or belongs to a different creator, is refused, not silently accepted.

Permissionscreators:write

Parameters

idpathrequired

idqueryrequired

The whitelist entry's own ID (from the list or add response), not the creator's ID.

Response

Returns 200 on success.

idstringrequired

Retries & errors

This read can be retried with exponential backoff. Honor Retry-After when it is returned.

Documented statuses: 200, 400, 401, 403, 404, 409, 502, 503. Error handling guide

DELETE/v1/creators/{id}/whitelist
curl --request DELETE 'https://api.crd.systems/v1/creators/crt_example/whitelist?id=wl_example' \
  --header "Authorization: Bearer $CRD_API_KEY"
Use your secret key in the environment variable.
Example response · 200
{
  "id": "wl_example"
}

Set this creator's profile photo by URL

Requires creators:write. The URL is fetched here (https only, no redirects, a size and time limit, and it must actually be an image) and stored into the same photo storage and profile field the normal sign-up photo picker writes to, so it appears wherever her photo already appears. Write-only for now: GET /v1/creators/{id} does not yet include it.

Permissionscreators:write

Parameters

idpathrequired

Request body

photo_urlstringrequired

An https:// URL to an image (JPEG, PNG, WebP, or GIF), up to 8 MB.

Maximum 2048 characters.

Response

Returns 200 on success.

photo_urlstringrequired

The stored (not the original) address; the original is never hotlinked back.

Retries & errors

This read can be retried with exponential backoff. Honor Retry-After when it is returned.

Documented statuses: 200, 400, 401, 403, 404, 409, 413, 415, 502, 503. Error handling guide

POST/v1/creators/{id}/photo
curl --request POST 'https://api.crd.systems/v1/creators/crt_example/photo' \
  --header "Authorization: Bearer $CRD_API_KEY" \
  --header 'Content-Type: application/json' \
  --data '{
  "photo_url": "https://cdn.example.com/creator-current-photo.jpg"
}'
Use your secret key in the environment variable.
Example response · 200
{
  "photo_url": "https://storage.crd.systems/avatars/example/photo.jpg"
}

Request CRD's paid legal-escalation service for a leak

Legacy single-case checkout: cases:read plus escalations:write required. CRD must have selected the leak for escalation and the agency must have an active signed escalation mandate. Current creator authorization, entitlement and ownership are required. Arbitrary URLs and impersonation accounts cannot be escalated. Use escalation-quotes to review a price before checkout and group several cases for site discounts. Preserve Idempotency-Key on retries; the same purchase and Stripe session are reused.

Permissionscases:readescalations:write

Parameters

idpathrequired

Idempotency-Keyheaderrequired

Stable key for one logical operation. Reuse unchanged for retries.

Request body

Send an empty JSON object: {}.

Response

Returns 202 on success.

idstringrequired
case_idstringrequired

First API case ID; use case_ids for a grouped purchase.

creator_idstringrequired

First creator in the purchase; a quote can span creators in the same workspace.

statusstringrequired

queued: awaiting dispatch. dispatching/uncertain: dispatch or reconciliation in progress; preserve the same Idempotency-Key. ready: Checkout link is available. paid: CRD recorded the payment. failed: definite rejection; resolve error_code before new work. attention_required: CRD must reconcile the request; do not create a replacement.

Values: queued dispatching uncertain ready paid failed attention_required refunded partially_refunded disputed

payment_linkstring | nullrequired

Hosted Stripe Checkout URL when available, otherwise null. An expired or completed checkout may no longer have a URL. CRD computes the amount; API callers cannot set or mark up it.

amount_centsinteger | nullrequired
currencystring | nullrequired
simulatedbooleanrequired

Always false.

created_atintegerrequired

Unix epoch milliseconds.

updated_atintegerrequired

Unix epoch milliseconds.

error_codestring | nullrequired
case_idsarray[]required
quote_idstring | nullrequired
pricingobject | nullrequired

Paid escalation only. URLs group by CRD site/mirror-family rules across the selection. Highest-priced sites first: positions 1–2 at list, 3–4 minus 10%, 5–9 minus 20%, 10–14 minus 30%, 15+ minus 35%. A supported percentage promotion applies after the graduated discount. All monetary fields are EUR cents. leak_ids are native IDs; submit API case_ids in requests.

Show nested fields
currencystringrequired

Always eur.

site_countintegerrequired
subtotal_centsintegerrequired
volume_discount_centsintegerrequired
promo_discount_centsintegerrequired
total_centsintegerrequired
linesarray[]required
Show nested fields
sitestringrequired
leak_idsarray[]required
base_amount_centsintegerrequired
discount_percentnumberrequired

Maximum: 100.

amount_centsintegerrequired
workflowarray[]required

Native legal work after payment. Payment state paid does not mean work completed. No private notes, documents or recipients are returned.

Show nested fields
idstringrequired
user_idstringrequired

Native CRD creator ID.

website_urlstringrequired
platformstring | nullrequired
statusstringrequired
updated_atstring | nullrequired
paymentobject | null

Latest independently reconciled Stripe payment state. A refund or dispute does not erase legal work. Null until verified.

Show nested fields
statusstringrequired

Values: pending processing paid cancelled refunded partially_refunded disputed

refunded_amount_centsintegerrequired
dispute_statusstring | nullrequired
checked_atstringrequired

Retries & errors

Preserve the Idempotency-Key for retries — a repeated request returns the same resource, never a second Checkout Session. Leaks only; an impersonation account returns 409 escalation_leaks_only.

Documented statuses: 200, 202, 400, 401, 403, 404, 409, 413, 415, 429, 502, 503, 504. Error handling guide

POST/v1/cases/{id}/escalation-requests
curl --request POST 'https://api.crd.systems/v1/cases/case_example/escalation-requests' \
  --header "Authorization: Bearer $CRD_API_KEY" \
  --header 'Content-Type: application/json' \
  --header 'Idempotency-Key: example-request-001' \
  --data '{}'
Use your secret key in the environment variable.
Example response · 202
{
  "payment": null,
  "case_ids": [
    "case_example"
  ],
  "quote_id": null,
  "workflow": [],
  "pricing": null,
  "id": "esc_example",
  "case_id": "case_example",
  "creator_id": "crt_example",
  "status": "queued",
  "payment_link": null,
  "amount_cents": null,
  "currency": null,
  "simulated": false,
  "created_at": 1790035200000,
  "updated_at": 1790035200000,
  "error_code": null
}

Read an escalation request, including its payment link

Read payment state and sanitized native escalation workflow for a purchase belonging to the agency. The same selection is checked for current agency ownership. paid means the real charge was recorded; read workflow for legal-work progress. escalation.status_changed also fires when observed workflow changes. Expired unpaid checkouts become failed with escalation_checkout_expired; request a fresh quote before retrying a purchase.

Permissionscases:read

Parameters

idpathrequired

Response

Returns 200 on success.

idstringrequired
case_idstringrequired

First API case ID; use case_ids for a grouped purchase.

creator_idstringrequired

First creator in the purchase; a quote can span creators in the same workspace.

statusstringrequired

queued: awaiting dispatch. dispatching/uncertain: dispatch or reconciliation in progress; preserve the same Idempotency-Key. ready: Checkout link is available. paid: CRD recorded the payment. failed: definite rejection; resolve error_code before new work. attention_required: CRD must reconcile the request; do not create a replacement.

Values: queued dispatching uncertain ready paid failed attention_required refunded partially_refunded disputed

payment_linkstring | nullrequired

Hosted Stripe Checkout URL when available, otherwise null. An expired or completed checkout may no longer have a URL. CRD computes the amount; API callers cannot set or mark up it.

amount_centsinteger | nullrequired
currencystring | nullrequired
simulatedbooleanrequired

Always false.

created_atintegerrequired

Unix epoch milliseconds.

updated_atintegerrequired

Unix epoch milliseconds.

error_codestring | nullrequired
case_idsarray[]required
quote_idstring | nullrequired
pricingobject | nullrequired

Paid escalation only. URLs group by CRD site/mirror-family rules across the selection. Highest-priced sites first: positions 1–2 at list, 3–4 minus 10%, 5–9 minus 20%, 10–14 minus 30%, 15+ minus 35%. A supported percentage promotion applies after the graduated discount. All monetary fields are EUR cents. leak_ids are native IDs; submit API case_ids in requests.

Show nested fields
currencystringrequired

Always eur.

site_countintegerrequired
subtotal_centsintegerrequired
volume_discount_centsintegerrequired
promo_discount_centsintegerrequired
total_centsintegerrequired
linesarray[]required
Show nested fields
sitestringrequired
leak_idsarray[]required
base_amount_centsintegerrequired
discount_percentnumberrequired

Maximum: 100.

amount_centsintegerrequired
workflowarray[]required

Native legal work after payment. Payment state paid does not mean work completed. No private notes, documents or recipients are returned.

Show nested fields
idstringrequired
user_idstringrequired

Native CRD creator ID.

website_urlstringrequired
platformstring | nullrequired
statusstringrequired
updated_atstring | nullrequired
paymentobject | null

Latest independently reconciled Stripe payment state. A refund or dispute does not erase legal work. Null until verified.

Show nested fields
statusstringrequired

Values: pending processing paid cancelled refunded partially_refunded disputed

refunded_amount_centsintegerrequired
dispute_statusstring | nullrequired
checked_atstringrequired

Retries & errors

status becomes paid only once CRD's own systems have recorded the real Stripe charge, never inferred from this read.

Documented statuses: 200, 400, 401, 403, 404, 409, 429, 502, 503, 504. Error handling guide

GET/v1/escalation-requests/{id}
curl --request GET 'https://api.crd.systems/v1/escalation-requests/esc_example' \
  --header "Authorization: Bearer $CRD_API_KEY"
Use your secret key in the environment variable.
Example response · 200
{
  "payment": null,
  "case_ids": [
    "case_example"
  ],
  "quote_id": null,
  "workflow": [],
  "pricing": null,
  "id": "esc_example",
  "case_id": "case_example",
  "creator_id": "crt_example",
  "status": "ready",
  "payment_link": "https://checkout.stripe.com/pay/cs_test_example",
  "amount_cents": 80000,
  "currency": "eur",
  "simulated": false,
  "created_at": 1790035200000,
  "updated_at": 1790035200000,
  "error_code": null
}

Read active API protection usage

Requires usage:read. Measures active API protection in UTC creator-months. Agency API access is included in the existing agency plan. Usage is informational, not an invoice or payment confirmation. The legacy billing_basis value active_api_scan_schedule is retained for compatibility; it does not describe a separate recurring scanner.

Permissionsusage:read

Parameters

monthquery

UTC calendar month YYYY-MM; defaults to the current month.

Response

Returns 200 on success.

monthstringrequired
period_startstringrequired
period_endstringrequired
measured_throughstringrequired
active_creator_countintegerrequired

Distinct creators contributing positive active time in the measured period; not current enrollment count.

creator_secondsnumberrequired
creator_monthsnumberrequired
estimated_subtotal_centsinteger | nullrequired

Integer minor units (cents), or null when unconfigured or not exposed to this credential.

minimum_monthly_centsinteger | nullrequired

Integer minor units (cents), or null when unconfigured or not exposed to this credential.

estimated_total_centsinteger | nullrequired

Integer minor units (cents), or null when unconfigured or not exposed to this credential.

currencystringrequired

Values: EUR USD

estimatebooleanrequired

Always true.

simulatedbooleanrequired

Always false.

scopestringrequired

Always agency.

billing_basisstringrequired

Legacy field value retained for compatibility. Measures active API protection time; recurring scans remain governed by the existing CRD plan.

Always active_api_scan_schedule.

Retries & errors

This read can be retried with exponential backoff. Honor Retry-After when it is returned.

Documented statuses: 200, 400, 401, 403, 404, 409, 429, 502, 503, 504. Error handling guide

GET/v1/usage
curl --request GET 'https://api.crd.systems/v1/usage?month=2026-09' \
  --header "Authorization: Bearer $CRD_API_KEY"
Use your secret key in the environment variable.
Example response · 200
{
  "month": "2026-09",
  "period_start": "2026-09-01T00:00:00.000Z",
  "period_end": "2026-10-01T00:00:00.000Z",
  "measured_through": "2026-09-16T00:00:00.000Z",
  "active_creator_count": 1,
  "creator_seconds": 1296000,
  "creator_months": 0.5,
  "estimated_subtotal_cents": null,
  "minimum_monthly_cents": null,
  "estimated_total_cents": null,
  "currency": "EUR",
  "estimate": true,
  "simulated": false,
  "scope": "agency",
  "billing_basis": "active_api_scan_schedule"
}

Recover your agency event stream

Requires events:read. Events are in insertion order and share IDs with signed webhook deliveries. Retain the last event ID for later polling even when next_cursor is null. The catalog covers API-linked current agency creators, synchronized native leak records, API protection, API scans, and API-created CRD deindex and legal-escalation requests. Creator, case, and eligibility updates reflect state observed on reads or periodic worker reconciliation, not every intermediate database edit. There are no impersonation-status, invoice-paid, KYC-approved or dedicated mandate-approved events. Webhook receivers are registered in the authenticated agency dashboard, not through a /v1/webhooks route.

Permissionsevents:read

Parameters

limitquery

afterquery

Last event ID from this authorized stream.

Response

Returns 200 on success.

dataarray[]required
Show nested fields
idstringrequired
typestringrequired

Values: protection.activated protection.paused scan.completed scan.failed case.created escalation.status_changed creator.updated case.updated case.deleted impersonation.created impersonation.updated impersonation.deleted

workspace_idstringrequired
created_atintegerrequired

Unix epoch milliseconds.

simulatedbooleanrequired

Always false.

dataobjectrequired
Show nested fields
creator_idstringrequired
scan_idstring
case_idstring
crd_job_idstring
statusstring
reasonstring
scopestring

Always api_scan_schedule.

escalation_request_idstring
creatorobject
Show nested fields
idstringrequired
workspace_idstringrequired
external_idstringrequired
display_namestringrequired
aliasesarray[]required
profile_urlsarray[]required

Full canonical HTTPS profile URLs using the same creator-platform rules as the portal. CRD derives the platform and username. Supports the portal platform catalog, X/Twitter aliases and RevealMe (reveal.me). Unknown public HTTPS hosts are stored as website profiles, not newly supported social platforms. No tracking query, fragment, credentials, private host or post URL. These links do not prove account ownership.

protection_statusstringrequired

API schedule state, separate from enrollment and eligibility. Activation and resumption require an explicit protection PUT after current eligibility checks.

Values: not_activated active paused

created_atintegerrequired

Unix epoch milliseconds.

enrollment_statusstringrequired

Current CRD linkage state, for example invited, pending_onboarding, linked, enrolling, failed, or uncertain.

crd_user_idstring | nullrequired
invitation_idstring | nullrequired
simulatedbooleanrequired

Always false.

scan_schedule_managed_bystringrequired

Legacy response field. The API controls its active-protection setting and on-demand scan eligibility; the existing CRD plan controls recurring scans.

Always api.

crd_subscription_managed_bystringrequired

Always 'crd': the creator's actual CRD subscription and its own automatic scan cadence are managed entirely by CRD, independent of this API's protection_status.

Always crd.

email_sentboolean

Present on a new enrollment response. True means the email provider accepted the invitation email; it does not prove inbox delivery, acceptance, authorization, or activation.

authorizationobjectrequired
entitlementobjectrequired
eligiblebooleanrequired
identity_sync_pendingbooleanrequired

True when an accepted invitation still needs legal onboarding before its submitted identity data can be applied.

caseobject
Show nested fields
idstringrequired
scan_idstring | nullrequired

Known API scan ID, or null for a native CRD case without API-scan provenance.

creator_idstringrequired
statusstringrequired

Current native CRD finding state observed during synchronization, not a removal confirmation.

urlstringrequired

The finding URL from the creator’s current native CRD leak record.

simulatedbooleanrequired

Always false.

created_atintegerrequired

Unix epoch milliseconds.

sourcestringrequired

crd for native findings without known API-scan provenance; api_scan when a verified API scan mapping exists.

Values: crd api_scan

leak_idstringrequired

The underlying native CRD leak record ID. Use the API case id in public API paths.

updated_atintegerrequired

Native update time in epoch milliseconds, or the imported creation time until native state is observed.

actionableboolean | nullrequired

Native actionability flag when synchronized; null if not yet observed.

dead_on_arrivalboolean | nullrequired

Native dead-on-arrival flag when synchronized; null if not yet observed.

availablebooleanrequired

Whether the synchronized native record remains available. Removal is observed after complete reconciliation.

api_deindex_supportedbooleanrequired

Whether known API-scan provenance supports the API deindex route. Current authorization and entitlement are checked separately.

escalationobject | nullrequired

Latest observed eligibility for paid escalation. Only CRD-selected leaks qualify. Null means not yet synchronized. Revalidated from current CRD records when quoting and reserving payment.

domainstring | null

Website hostname without www. Use this exact value to group display rows; this is not escalation billing grouping.

favicon_urlstring | null

Google favicon URL, matching the portal. Load with an image fallback; fetching it uses a third-party service.

status_codestring

Values: detected reported in_progress manual_review escalation_required removed unknown

error_codestring

Present on some terminal scan, deindex or escalation events. Refresh the resource for its current error and state.

impersonation_idstring
impersonationobject
Show nested fields
idstringrequired
creator_idstringrequired
urlstringrequired
usernamestring | nullrequired
platformstringrequired
typestringrequired
statusstringrequired
created_atintegerrequired
updated_atintegerrequired
reported_atinteger | nullrequired
removed_atinteger | nullrequired
domainstring | nullrequired

Website hostname without www. Use this exact value to group display rows; this is not escalation billing grouping.

favicon_urlstring | nullrequired

Google favicon URL, matching the portal. Load with an image fallback; fetching it uses a third-party service.

next_cursorstring | nullrequired

Last ID for the next page, or null. Retain the last returned event ID for subsequent polling.

Retries & errors

This read can be retried with exponential backoff. Honor Retry-After when it is returned.

Documented statuses: 200, 400, 401, 403, 404, 409, 429, 502, 503, 504. Error handling guide

GET/v1/events
curl --request GET 'https://api.crd.systems/v1/events?limit=25' \
  --header "Authorization: Bearer $CRD_API_KEY"
Use your secret key in the environment variable.
Example response · 200
{
  "data": [
    {
      "id": "evt_example",
      "type": "scan.completed",
      "workspace_id": "wsp_example",
      "created_at": 1790035200000,
      "simulated": false,
      "data": {
        "creator_id": "crt_example",
        "scan_id": "scn_example",
        "crd_job_id": "44444444-4444-4444-8444-444444444444"
      }
    }
  ],
  "next_cursor": null
}

Quote selected escalation cases

Requires cases:read and escalations:write. Select 1–100 distinct API case IDs in one workspace. CRD reloads native cases, verifies ownership and its escalation selection, checks the active signed agency escalation mandate, groups sites and applies current graduated pricing. Returns a quote valid for 15 minutes without reserving or charging a payment. Separate quotes are safe; only checkout creates a purchase.

Permissionscases:readescalations:write

Request body

case_idsarray[]required

Up to 100 items.

promo_codestring

Optional active, unrestricted percentage promotion. Fixed-amount, product-limited, customer-first-use, minimum-spend and redemption-limited promotions are not supported.

Maximum 100 characters.

Response

Returns 201 on success.

idstringrequired
case_idsarray[]required
expires_atstringrequired
expiredbooleanrequired
pricingobjectrequired

Paid escalation only. URLs group by CRD site/mirror-family rules across the selection. Highest-priced sites first: positions 1–2 at list, 3–4 minus 10%, 5–9 minus 20%, 10–14 minus 30%, 15+ minus 35%. A supported percentage promotion applies after the graduated discount. All monetary fields are EUR cents. leak_ids are native IDs; submit API case_ids in requests.

Show nested fields
currencystringrequired

Always eur.

site_countintegerrequired
subtotal_centsintegerrequired
volume_discount_centsintegerrequired
promo_discount_centsintegerrequired
total_centsintegerrequired
linesarray[]required
Show nested fields
sitestringrequired
leak_idsarray[]required
base_amount_centsintegerrequired
discount_percentnumberrequired

Maximum: 100.

amount_centsintegerrequired
mandate_statusstringrequired

Always signed.

Retries & errors

Quoting does not reserve or charge payment. Show the returned total, then create checkout for that quote after manager approval.

Documented statuses: 201, 400, 401, 403, 404, 409, 413, 415, 429, 502, 503, 504. Error handling guide

POST/v1/escalation-quotes
curl --request POST 'https://api.crd.systems/v1/escalation-quotes' \
  --header "Authorization: Bearer $CRD_API_KEY" \
  --header 'Content-Type: application/json' \
  --data '{
  "case_ids": [
    "case_example"
  ]
}'
Use your secret key in the environment variable.
Example response · 201
{
  "id": "66666666-6666-4666-8666-666666666666",
  "case_ids": [
    "case_example"
  ],
  "expires_at": "2026-09-22T00:15:00.000Z",
  "expired": false,
  "pricing": {
    "currency": "eur",
    "site_count": 1,
    "subtotal_cents": 80000,
    "volume_discount_cents": 0,
    "promo_discount_cents": 0,
    "total_cents": 80000,
    "lines": [
      {
        "site": "example.invalid",
        "leak_ids": [
          "55555555-5555-4555-8555-555555555555"
        ],
        "base_amount_cents": 80000,
        "discount_percent": 0,
        "amount_cents": 80000
      }
    ]
  },
  "mandate_status": "signed"
}

Read a saved escalation quote

Requires cases:read. Rechecks current creator membership. An expired quote remains readable but cannot create a new purchase.

Permissionscases:read

Parameters

idpathrequired

Response

Returns 200 on success.

idstringrequired
case_idsarray[]required
expires_atstringrequired
expiredbooleanrequired
pricingobjectrequired

Paid escalation only. URLs group by CRD site/mirror-family rules across the selection. Highest-priced sites first: positions 1–2 at list, 3–4 minus 10%, 5–9 minus 20%, 10–14 minus 30%, 15+ minus 35%. A supported percentage promotion applies after the graduated discount. All monetary fields are EUR cents. leak_ids are native IDs; submit API case_ids in requests.

Show nested fields
currencystringrequired

Always eur.

site_countintegerrequired
subtotal_centsintegerrequired
volume_discount_centsintegerrequired
promo_discount_centsintegerrequired
total_centsintegerrequired
linesarray[]required
Show nested fields
sitestringrequired
leak_idsarray[]required
base_amount_centsintegerrequired
discount_percentnumberrequired

Maximum: 100.

amount_centsintegerrequired
mandate_statusstringrequired

Always signed.

Retries & errors

An expired quote stays readable. Requote for a new purchase; recover an existing checkout with its original idempotency key.

Documented statuses: 200, 400, 401, 403, 404, 409, 413, 415, 429, 502, 503, 504. Error handling guide

GET/v1/escalation-quotes/{id}
curl --request GET 'https://api.crd.systems/v1/escalation-quotes/66666666-6666-4666-8666-666666666666' \
  --header "Authorization: Bearer $CRD_API_KEY"
Use your secret key in the environment variable.
Example response · 200
{
  "id": "66666666-6666-4666-8666-666666666666",
  "case_ids": [
    "case_example"
  ],
  "expires_at": "2026-09-22T00:15:00.000Z",
  "expired": false,
  "pricing": {
    "currency": "eur",
    "site_count": 1,
    "subtotal_cents": 80000,
    "volume_discount_cents": 0,
    "promo_discount_cents": 0,
    "total_cents": 80000,
    "lines": [
      {
        "site": "example.invalid",
        "leak_ids": [
          "55555555-5555-4555-8555-555555555555"
        ],
        "base_amount_cents": 80000,
        "discount_percent": 0,
        "amount_cents": 80000
      }
    ]
  },
  "mandate_status": "signed"
}

Create checkout for an approved quote

Requires cases:read and escalations:write, an unchanged server-issued quote and a stable Idempotency-Key. Returns queued; poll the escalation request for the Stripe link. Eligibility, mandate, ownership and quoted prices are revalidated before reservation. A changed selection or price requires a fresh quote and user review. No price can be supplied by the caller. New keys cannot purchase an already-reserved case again. Retry the original key for uncertain results.

Permissionscases:readescalations:write

Parameters

idpathrequired

Idempotency-Keyheaderrequired

Stable key for one logical operation. Reuse unchanged for retries.

Request body

Send an empty JSON object: {}.

Response

Returns 202 on success.

idstringrequired
case_idstringrequired

First API case ID; use case_ids for a grouped purchase.

creator_idstringrequired

First creator in the purchase; a quote can span creators in the same workspace.

statusstringrequired

queued: awaiting dispatch. dispatching/uncertain: dispatch or reconciliation in progress; preserve the same Idempotency-Key. ready: Checkout link is available. paid: CRD recorded the payment. failed: definite rejection; resolve error_code before new work. attention_required: CRD must reconcile the request; do not create a replacement.

Values: queued dispatching uncertain ready paid failed attention_required refunded partially_refunded disputed

payment_linkstring | nullrequired

Hosted Stripe Checkout URL when available, otherwise null. An expired or completed checkout may no longer have a URL. CRD computes the amount; API callers cannot set or mark up it.

amount_centsinteger | nullrequired
currencystring | nullrequired
simulatedbooleanrequired

Always false.

created_atintegerrequired

Unix epoch milliseconds.

updated_atintegerrequired

Unix epoch milliseconds.

error_codestring | nullrequired
case_idsarray[]required
quote_idstring | nullrequired
pricingobject | nullrequired

Paid escalation only. URLs group by CRD site/mirror-family rules across the selection. Highest-priced sites first: positions 1–2 at list, 3–4 minus 10%, 5–9 minus 20%, 10–14 minus 30%, 15+ minus 35%. A supported percentage promotion applies after the graduated discount. All monetary fields are EUR cents. leak_ids are native IDs; submit API case_ids in requests.

Show nested fields
currencystringrequired

Always eur.

site_countintegerrequired
subtotal_centsintegerrequired
volume_discount_centsintegerrequired
promo_discount_centsintegerrequired
total_centsintegerrequired
linesarray[]required
Show nested fields
sitestringrequired
leak_idsarray[]required
base_amount_centsintegerrequired
discount_percentnumberrequired

Maximum: 100.

amount_centsintegerrequired
workflowarray[]required

Native legal work after payment. Payment state paid does not mean work completed. No private notes, documents or recipients are returned.

Show nested fields
idstringrequired
user_idstringrequired

Native CRD creator ID.

website_urlstringrequired
platformstring | nullrequired
statusstringrequired
updated_atstring | nullrequired
paymentobject | null

Latest independently reconciled Stripe payment state. A refund or dispute does not erase legal work. Null until verified.

Show nested fields
statusstringrequired

Values: pending processing paid cancelled refunded partially_refunded disputed

refunded_amount_centsintegerrequired
dispute_statusstring | nullrequired
checked_atstringrequired

Retries & errors

Keep the same Idempotency-Key for the entire purchase. Eligibility, mandate, ownership and prices are checked again before reserving it.

Documented statuses: 200, 202, 400, 401, 403, 404, 409, 413, 415, 429, 502, 503, 504. Error handling guide

POST/v1/escalation-quotes/{id}/checkout
curl --request POST 'https://api.crd.systems/v1/escalation-quotes/66666666-6666-4666-8666-666666666666/checkout' \
  --header "Authorization: Bearer $CRD_API_KEY" \
  --header 'Content-Type: application/json' \
  --header 'Idempotency-Key: example-request-001' \
  --data '{}'
Use your secret key in the environment variable.
Example response · 202
{
  "payment": null,
  "case_ids": [
    "case_example"
  ],
  "quote_id": "66666666-6666-4666-8666-666666666666",
  "workflow": [],
  "pricing": null,
  "id": "esc_example",
  "case_id": "case_example",
  "creator_id": "crt_example",
  "status": "queued",
  "payment_link": null,
  "amount_cents": null,
  "currency": null,
  "simulated": false,
  "created_at": 1790035200000,
  "updated_at": 1790035200000,
  "error_code": null
}

Read creator impersonation cases

Requires cases:read. Lists the same native impersonation records as the portal. Poll or use impersonation.created/updated/deleted. IDs are native UUIDs; private descriptions, notes and contacts are excluded.

Permissionscases:read

Parameters

idpathrequired

limitquery

afterquery

Use this collection’s returned next_cursor unchanged.

Response

Returns 200 on success.

dataarray[]required
Show nested fields
idstringrequired
creator_idstringrequired
urlstringrequired
usernamestring | nullrequired
platformstringrequired
typestringrequired
statusstringrequired
created_atintegerrequired
updated_atintegerrequired
reported_atinteger | nullrequired
removed_atinteger | nullrequired
domainstring | nullrequired

Website hostname without www. Use this exact value to group display rows; this is not escalation billing grouping.

favicon_urlstring | nullrequired

Google favicon URL, matching the portal. Load with an image fallback; fetching it uses a third-party service.

next_cursorstring | nullrequired

Retries & errors

This read can be retried with exponential backoff. Honor Retry-After when it is returned.

Documented statuses: 200, 400, 401, 403, 404, 409, 429, 502, 503, 504. Error handling guide

GET/v1/creators/{id}/impersonations
curl --request GET 'https://api.crd.systems/v1/creators/crt_example/impersonations' \
  --header "Authorization: Bearer $CRD_API_KEY"
Use your secret key in the environment variable.
Example response · 200
{
  "data": [
    {
      "id": "77777777-7777-4777-8777-777777777777",
      "creator_id": "crt_example",
      "url": "https://instagram.com/example_fake",
      "username": "example_fake",
      "platform": "instagram",
      "type": "impersonation",
      "status": "reported",
      "created_at": 1790035200000,
      "updated_at": 1790035200000,
      "reported_at": 1790035200000,
      "removed_at": null,
      "domain": "instagram.com",
      "favicon_url": "https://www.google.com/s2/favicons?domain=instagram.com&sz=64"
    }
  ],
  "next_cursor": null
}

Read customer-safe creator activity

Requires cases:read. Newest first, with an opaque after cursor. Includes detections, sent notices and recorded removals. leak.status is the CURRENT status timestamped by record_updated, not a fabricated historical transition. Historical intermediate changes are not reconstructed. Notice rows reflect recorded sends, not proof of recipient delivery. No private notes, recipients, email bodies or legal documents.

Permissionscases:read

Parameters

idpathrequired

limitquery

afterquery

Use this collection’s returned next_cursor unchanged.

Response

Returns 200 on success.

dataarray[]required
Show nested fields
idstringrequired
creator_idstringrequired
typestringrequired
record_idstringrequired
urlstringrequired
statusstring | nullrequired
occurred_atintegerrequired
timestamp_basisstringrequired
domainstring | nullrequired

Website hostname without www. Use this exact value to group display rows; this is not escalation billing grouping.

favicon_urlstring | nullrequired

Google favicon URL, matching the portal. Load with an image fallback; fetching it uses a third-party service.

next_cursorstring | nullrequired

Retries & errors

This read can be retried with exponential backoff. Honor Retry-After when it is returned.

Documented statuses: 200, 400, 401, 403, 404, 409, 429, 502, 503, 504. Error handling guide

GET/v1/creators/{id}/activity
curl --request GET 'https://api.crd.systems/v1/creators/crt_example/activity' \
  --header "Authorization: Bearer $CRD_API_KEY"
Use your secret key in the environment variable.
Example response · 200
{
  "data": [
    {
      "id": "leak_detected:55555555-5555-4555-8555-555555555555",
      "creator_id": "crt_example",
      "type": "leak.detected",
      "record_id": "55555555-5555-4555-8555-555555555555",
      "url": "https://example.invalid/illustrative-finding",
      "status": "detected",
      "occurred_at": 1790035200000,
      "timestamp_basis": "record_created",
      "domain": "example.invalid",
      "favicon_url": "https://www.google.com/s2/favicons?domain=example.invalid&sz=64"
    }
  ],
  "next_cursor": null
}

Read shared subscription and creator capacity

Requires usage:read. Informational snapshot of the existing agency plan, occupied and reserved slots, overflow and protection eligibility. Invitations and creator completion enforce native capacity atomically; a free slot in this response is not a reservation. No new purchase occurs.

Permissionsusage:read

Response

Returns 200 on success.

planstring | nullrequired
subscription_statusstring | nullrequired
protection_eligiblebooleanrequired
total_slotsintegerrequired
occupied_slotsintegerrequired
reserved_slotsintegerrequired
available_slotsintegerrequired
overflow_slotsintegerrequired
api_includedbooleanrequired

Always true.

checked_atstringrequired
billing_modelstring

Values: legacy active_creators

unit_price_centsinteger | null

Current unit rate for the active creator count. EUR 69 for 1–9, EUR 59 each from 10 on the volume offer. For negotiated graduated pricing this is the base rate, not an average. Use monthly_total_cents and the returned tiers.

currencystring

Always EUR.

pricing_versionstring

Values: flat_v1 volume_v2 graduated_39_29_v1

active_countinteger
monthly_total_centsinteger | null

Retries & errors

This read can be retried with exponential backoff. Honor Retry-After when it is returned.

Documented statuses: 200, 400, 401, 403, 404, 409, 429, 502, 503, 504. Error handling guide

GET/v1/capacity
curl --request GET 'https://api.crd.systems/v1/capacity' \
  --header "Authorization: Bearer $CRD_API_KEY"
Use your secret key in the environment variable.
Example response · 200
{
  "plan": "growth",
  "subscription_status": "active",
  "protection_eligible": true,
  "total_slots": 25,
  "occupied_slots": 10,
  "reserved_slots": 2,
  "available_slots": 13,
  "overflow_slots": 0,
  "api_included": true,
  "checked_at": "2026-09-25T00:00:00Z"
}

Resend a pending API invitation

Requires creators:write and Idempotency-Key. Reuses the existing CRD invitation email and branding, rotates its link and extends expiry to seven days. Only API-created pending/expired invitations; accepted creators use portal access recovery. One resend per minute, five per 24 hours. A matching retry never sends again; delivery_status uncertain requires review, not a new key. Active invitations do not consume another slot; expired invitations must reserve capacity again.

Permissionscreators:write

Parameters

idpathrequired

Idempotency-Keyheaderrequired

Request body

Send an empty JSON object: {}.

Response

Returns 200 on success.

invitation_idstringrequired
email_sentbooleanrequired
delivery_statusstringrequired
replayedbooleanrequired

Retries & errors

Keep the same Idempotency-Key. A replay never resends; an uncertain delivery requires review.

Documented statuses: 200, 400, 401, 403, 404, 409, 429, 502, 503, 504. Error handling guide

POST/v1/creators/{id}/resend-invitation
curl --request POST 'https://api.crd.systems/v1/creators/crt_example/resend-invitation' \
  --header "Authorization: Bearer $CRD_API_KEY" \
  --header 'Content-Type: application/json' \
  --header 'Idempotency-Key: example-request-001' \
  --data '{}'
Use your secret key in the environment variable.
Example response · 200
{
  "invitation_id": "77777777-7777-4777-8777-777777777777",
  "email_sent": true,
  "delivery_status": "sent",
  "replayed": false
}

Download a page of the creator’s leak report

Requires cases:read. CSV with the same cases, domain and normalized statuses as GET cases. At most 100 rows per page. Follow X-Next-Cursor using after until the header is absent. Export all pages to build a complete report; current records are not a frozen snapshot. Deduplicate by id. Cells are quoted and spreadsheet formula prefixes escaped.

Permissionscases:read

Parameters

idpathrequired

limitquery

afterquery

Last case ID in this creator’s authorized collection.

Response

Returns 200 on success.

Retries & errors

CSV response: read text, then follow X-Next-Cursor for every page. It is not a frozen export.

Documented statuses: 200, 400, 401, 403, 404, 409, 429, 502, 503, 504. Error handling guide

GET/v1/creators/{id}/report
curl --request GET 'https://api.crd.systems/v1/creators/crt_example/report?limit=100' \
  --header "Authorization: Bearer $CRD_API_KEY"
Use your secret key in the environment variable.
Example response · 200
"id,creator_id,url,domain,status,status_code,created_at,updated_at\r\n"

Quote bulk creator activation

Read a price quote for activating 1–50 eligible, inactive creators. Does not create a billing operation or grant protection. EUR totals include the entire resulting active roster, including the all-creator discount from 10. Requires protection:write and active_creators billing.

Permissionsprotection:write

Request body

creator_idsarray[]required

API creator IDs belonging to this agency/workspace, all inactive and eligible.

Up to 50 items.

Response

Returns 200 on success.

previous_quantityinteger
quantityintegerrequired
unit_price_centsintegerrequired
monthly_total_centsintegerrequired
selected_countintegerrequired

Retries & errors

This read can be retried with exponential backoff. Honor Retry-After when it is returned.

Documented statuses: 200, 400, 401, 403, 404, 409, 502, 503. Error handling guide

POST/v1/protection/bulk/quote
curl --request POST 'https://api.crd.systems/v1/protection/bulk/quote' \
  --header "Authorization: Bearer $CRD_API_KEY" \
  --header 'Content-Type: application/json' \
  --data '{
  "creator_ids": [
    "crt_example"
  ]
}'
Use your secret key in the environment variable.
Example response · 200
{
  "previous_quantity": 0,
  "quantity": 1,
  "selected_count": 1,
  "unit_price_cents": 6900,
  "monthly_total_cents": 6900
}

Activate selected creators

Activate 1–50 creators in one durable billing operation after owner approval of the bulk quote. Requires protection:write. Each selected creator must remain eligible and belong to the agency. Send the approved price and quantity and a stable UUID Idempotency-Key; retry the same key and body after uncertainty. A 202 checkout response is pending: complete checkout, then read each creator to confirm active. The entire selection is committed together after confirmed billing; eligibility failure does not partially activate it. One pending billing operation per agency. Individual pause remains available through PUT /v1/creators/{id}/protection; pausing one creator never pauses the others. No bulk pause or enrollment is introduced.

Permissionsprotection:write

Parameters

Idempotency-Keyheaderrequired

Request body

creator_idsarray[]required

API creator IDs belonging to this agency/workspace, all inactive and eligible.

Up to 50 items.

expected_price_centsintegerrequired
expected_quantityintegerrequired

Maximum: 1000.

Response

Returns 202 on success.

statusstring
operation_idstring
checkout_urlstring

Retries & errors

Save the owner-approved quote and a UUID Idempotency-Key. Retry the same key and body. Pending checkout is not active protection; confirm each creator with a fresh read.

Documented statuses: 200, 202, 400, 401, 403, 404, 409, 502, 503. Error handling guide

PUT/v1/protection/bulk
curl --request PUT 'https://api.crd.systems/v1/protection/bulk' \
  --header "Authorization: Bearer $CRD_API_KEY" \
  --header 'Content-Type: application/json' \
  --header 'Idempotency-Key: example-request-001' \
  --data '{
  "creator_ids": [
    "crt_example"
  ],
  "expected_price_cents": 6900,
  "expected_quantity": 1
}'
Use your secret key in the environment variable.
Example response · 202
{
  "status": "checkout",
  "operation_id": "77777777-7777-4777-8777-777777777777",
  "checkout_url": "https://checkout.stripe.com/example"
}