SalesDogg

API reference

SalesDogg API 0.1.0. Generated from /openapi.json, the same document the CLI and the MCP server are generated from.

SalesDogg is a subscription and in-app purchase backend. It normalizes Stripe, Braintree, App Store and Google Play into one model: customers own subscriptions and purchases of products; products unlock entitlements; offerings group products for display.

Authentication

Send Authorization: Bearer <credential>.

  • Secret key (sd_sk_...): full access to one project. Server-side only.
  • Public key (sd_pk_...): safe in client apps; read offerings, check a user's entitlements, submit App Store / Google Play receipts, attach an anonymous user to a signed-in one, set customer attributes. It never returns attributes or purchase history.
  • Session token (from salesdogg login): a human user. Project-scoped endpoints then need an X-Project-Id header. Some operations need the owner or admin role in the organization; each endpoint says so.

Try it without a store account

POST /v1/simulator/purchases with { "app_user_id": "user_1", "store_identifier": "pro_monthly" } creates a sandbox subscription with no setup. Attach its product to an entitlement, check the user's access, then drive renewals, cancellations, billing issues and refunds with POST /v1/simulator/subscriptions/{id}/advance. Events and webhooks behave as in production.

Quickstart

  1. POST /v1/apps – connect a provider.
  2. POST /v1/apps/{app_id}/import_products (or POST /v1/products).
  3. POST /v1/entitlements with product_ids.
  4. POST /v1/checkout_sessions (web) or POST /v1/receipts (mobile) to record purchases.
  5. GET /v1/customers/{app_user_id}/entitlements to check access.

Moving from RevenueCat

  • POST /v1/imports/revenuecat/catalog, then POST /v1/imports/revenuecat/customers page by page (or salesdogg import revenuecat).
  • GET /v1/subscribers/{app_user_id} and the other /v1/subscribers endpoints answer in RevenueCat's REST v1 format.
  • Webhook endpoints with format: "revenuecat" receive RevenueCat's webhook body.
  • Customer attributes, aliases, $RCAnonymousID: ids and restore behavior (GET/PATCH /v1/settings) follow RevenueCat's rules.

Conventions

  • Errors: { "error": { type, code, message, param?, hint? } }. hint says what to do next.
  • Creates keyed by lookup_key, app_user_id or store_identifier are idempotent upserts and safe to retry.
  • Lists: limit + starting_after; responses carry has_more and next_cursor.
  • Money is in minor units (cents). Timestamps are ISO 8601 UTC.
  • Rate limits: responses carry RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset (seconds). A 429 includes Retry-After.

Account

Identify the current credential

GET/v1/me
CLI
salesdogg account whoami
MCP tool
account_whoami
Credentials
Session, Secret key

Returns the user (session) or the project (API key) the credential belongs to. Useful to verify setup.

Organizations

Projects

Create a project

POST/v1/projects
CLI
salesdogg projects create
MCP tool
projects_create
Credentials
Session

A project holds all billing data for one product. If you have no organization yet, one is created. The response includes a secret and a public API key so you can start immediately.

ParameterInTypeDescription
name*bodystring
organization_idbodystringDefaults to your only organization, or creates one named after the project.

Delete a project and all of its data

DELETE/v1/projects/{project_id}
CLI
salesdogg projects delete <project_id>
MCP tool
projects_delete
Credentials
Session

Needs the owner or admin role in the organization.

ParameterInTypeDescription
project_id*pathstring

API keys

Create an API key

POST/v1/api_keys
CLI
salesdogg api-keys create
MCP tool
api_keys_create
Credentials
Session, Secret key · sessions need the owner or admin role

Secret keys (sd_sk_) have full access to the project and must stay on servers. Public keys (sd_pk_) are safe to ship in client apps: they can only read offerings, check a user's entitlements, submit App Store and Google Play receipts, attach an anonymous user to a signed-in one, and set (not read) customer attributes. Signed-in users need the owner or admin role in the organization.

ParameterInTypeDescription
kind*body"secret" | "public"
namebodystring

Revoke an API key

DELETE/v1/api_keys/{api_key_id}
CLI
salesdogg api-keys revoke <api_key_id>
MCP tool
api_keys_revoke
Credentials
Session, Secret key · sessions need the owner or admin role

Signed-in users need the owner or admin role in the organization.

ParameterInTypeDescription
api_key_id*pathstring

Apps (provider connections)

Connect a payment provider

POST/v1/apps
CLI
salesdogg apps create
MCP tool
apps_create
Credentials
Session, Secret key · sessions need the owner or admin role

Creates a connection ("app") to one provider account or store listing. Required fields per provider: - stripe: credentials { secret_key, webhook_secret? }. When the API has a public HTTPS URL the webhook endpoint is registered in Stripe automatically. - braintree: credentials { merchant_id, public_key, private_key, environment }, config { customer_id_is_app_user_id? }. - app_store: config { bundle_id, app_apple_id? }, credentials { issuer_id, key_id, private_key } (optional: an In-App Purchase key, needed to look purchases up at Apple, e.g. for the RevenueCat import). - play_store: credentials { service_account_json }, config { package_name }. The response contains `webhook_url` and `webhook_instructions` describing the one remaining manual step, if any. The Free plan is sandbox only. Live credentials (a live Stripe key, Braintree `environment: production`, an App Store `app_apple_id`) on Free answer 402 `plan_required`; show the user `error.details.upgrade_url`, a link to choose a plan and pay, then retry. Signed-in users need the owner or admin role in the organization.

ParameterInTypeDescription
provider*body"stripe" | "braintree" | "app_store" | "play_store" | "simulator"
namebodystring
credentialsbodyobjectProvider secrets. Stored encrypted; never returned.
configbodyobjectNon-secret provider settings.

Get a provider connection

GET/v1/apps/{app_id}
CLI
salesdogg apps get <app_id>
MCP tool
apps_get
Credentials
Session, Secret key
ParameterInTypeDescription
app_id*pathstring

Update a provider connection

PATCH/v1/apps/{app_id}
CLI
salesdogg apps update <app_id>
MCP tool
apps_update
Credentials
Session, Secret key · sessions need the owner or admin role

Given credential and config fields are merged into the stored ones (e.g. set a Stripe `webhook_secret` after creating the endpoint). Signed-in users need the owner or admin role in the organization.

ParameterInTypeDescription
app_id*pathstring
namebodystring
credentialsbodyobject
configbodyobject

Delete a provider connection and its products

DELETE/v1/apps/{app_id}
CLI
salesdogg apps delete <app_id>
MCP tool
apps_delete
Credentials
Session, Secret key · sessions need the owner or admin role

Signed-in users need the owner or admin role in the organization.

ParameterInTypeDescription
app_id*pathstring

Import products from the provider

POST/v1/apps/{app_id}/import_products
CLI
salesdogg apps import-products <app_id>
MCP tool
apps_import_products
Credentials
Session, Secret key

Fetches the provider's catalog (Stripe prices, Braintree plans) and creates any products that do not exist yet. Idempotent.

ParameterInTypeDescription
app_id*pathstring

Products

List products

GET/v1/products
CLI
salesdogg products list
MCP tool
products_list
Credentials
Session, Secret key
ParameterInTypeDescription
limitqueryintegerPage size (1-100).
starting_afterquerystringCursor: the `next_cursor` value from the previous page.
app_idquerystring

Create a product

POST/v1/products
CLI
salesdogg products create
MCP tool
products_create
Credentials
Session, Secret key

Registers a store product so it can be attached to entitlements and offerings. Idempotent on (app_id, store_identifier): creating an existing product updates and returns it.

ParameterInTypeDescription
app_id*bodystring
store_identifier*bodystring
typebody"subscription" | "one_time"
display_namebodystring

Delete a product

DELETE/v1/products/{product_id}
CLI
salesdogg products delete <product_id>
MCP tool
products_delete
Credentials
Session, Secret key
ParameterInTypeDescription
product_id*pathstring

Entitlements

List entitlements

GET/v1/entitlements
CLI
salesdogg entitlements list
MCP tool
entitlements_list
Credentials
Session, Secret key

Create or update an entitlement

POST/v1/entitlements
CLI
salesdogg entitlements create
MCP tool
entitlements_create
Credentials
Session, Secret key

An entitlement is a level of access (e.g. "pro") unlocked by any of its products. Idempotent on lookup_key. When product_ids is given it replaces the attached products.

ParameterInTypeDescription
lookup_key*bodystring
display_namebodystring
product_idsbodystring[]

Attach products to an entitlement

POST/v1/entitlements/{entitlement}/products
CLI
salesdogg entitlements attach-products <entitlement>
MCP tool
entitlements_attach_products
Credentials
Session, Secret key
ParameterInTypeDescription
entitlement*pathstringEntitlement id or lookup_key.
product_ids*bodystring[]

Detach a product from an entitlement

DELETE/v1/entitlements/{entitlement}/products/{product_id}
CLI
salesdogg entitlements detach-product <entitlement> <product_id>
MCP tool
entitlements_detach_product
Credentials
Session, Secret key
ParameterInTypeDescription
entitlement*pathstringEntitlement id or lookup_key.
product_id*pathstring

Delete an entitlement

DELETE/v1/entitlements/{entitlement}
CLI
salesdogg entitlements delete <entitlement>
MCP tool
entitlements_delete
Credentials
Session, Secret key
ParameterInTypeDescription
entitlement*pathstringEntitlement id or lookup_key.

Offerings

List offerings

GET/v1/offerings
CLI
salesdogg offerings list
MCP tool
offerings_list
Credentials
Session, Secret key, Public key

Offerings are the sets of products you present to customers. Client apps fetch this with a public key and display the one with `is_current: true`.

Create or update an offering

POST/v1/offerings
CLI
salesdogg offerings create
MCP tool
offerings_create
Credentials
Session, Secret key

Idempotent on lookup_key. When `packages` is given it replaces the offering's packages. The first offering of a project becomes current automatically.

ParameterInTypeDescription
lookup_key*bodystring
display_namebodystring
is_currentbodyboolean
metadatabodyobject
packagesbodyobject[]

Get an offering

GET/v1/offerings/{offering}
CLI
salesdogg offerings get <offering>
MCP tool
offerings_get
Credentials
Session, Secret key, Public key
ParameterInTypeDescription
offering*pathstringOffering id or lookup_key.

Delete an offering

DELETE/v1/offerings/{offering}
CLI
salesdogg offerings delete <offering>
MCP tool
offerings_delete
Credentials
Session, Secret key
ParameterInTypeDescription
offering*pathstringOffering id or lookup_key.

Customers

List and search customers

GET/v1/customers
CLI
salesdogg customers list
MCP tool
customers_list
Credentials
Session, Secret key

Newest first. Filters combine with AND. Each customer comes with attributes, aliases and last-seen device details.

ParameterInTypeDescription
limitqueryintegerPage size (1-100).
starting_afterquerystringCursor: the `next_cursor` value from the previous page.
searchquerystringAn app user id or alias (exact, or the start of one), or an exact $email address (case-insensitive).
entitlementquerystringOnly customers with this entitlement (lookup_key) active right now.
activequery"true" | "false"true: customers with any active entitlement; false: customers with none.
platformquerystringLast seen platform, e.g. ios or android.
countryquerystringLast seen country, ISO 3166-1 alpha-2.
app_versionquerystringLast seen app version.
storequery"stripe" | "braintree" | "app_store" | "play_store" | "simulator"Customers with a subscription or purchase from this store.
attribute_keyquerystringWith attribute_value: customers whose attribute equals the value (case-insensitive). Alone: customers that have the attribute.
attribute_valuequerystring
first_seen_afterquerystring
first_seen_beforequerystring
last_seen_afterquerystring
last_seen_beforequerystring

Create or update a customer

POST/v1/customers
CLI
salesdogg customers upsert
MCP tool
customers_upsert
Credentials
Session, Secret key

Idempotent on app_user_id (an alias finds its customer). Given attributes are merged into existing ones; set a key to null to remove it.

ParameterInTypeDescription
app_user_id*bodystring
attributesbodyobjectKey -> value. A value may also be `{ value, updated_at_ms }` (RevenueCat format). null or "" deletes the attribute.

Set customer attributes

POST/v1/customers/{app_user_id}/attributes
CLI
salesdogg customers set-attributes <app_user_id>
MCP tool
customers_set_attributes
Credentials
Session, Secret key, Public key

Same rules as RevenueCat: string values up to 500 characters; null or "" deletes; custom keys start with a letter, use letters, digits, "_" and "-", up to 40 characters, at most 50 per customer; keys starting with "$" are reserved ($email, $displayName, $phoneNumber, $mediaSource, $campaign, $adGroup, $ad, $keyword, $creative, integration ids). Send `{ value, updated_at_ms }` to say when the change was made; an older write never replaces a newer one. Client apps may call this with the public key (creating the customer if needed), but cannot read attributes back: the response then carries entitlements only. From an app, campaign attribution keys can only be set once.

ParameterInTypeDescription
app_user_id*pathstringYour own identifier for the user (URL-encoded). An alias works too.
attributes*bodyobjectKey -> value. A value may also be `{ value, updated_at_ms }` (RevenueCat format). null or "" deletes the attribute.

Attach an anonymous customer to a known user

POST/v1/customers/identify
CLI
salesdogg customers identify
MCP tool
customers_identify
Credentials
Session, Secret key, Public key

Client SDKs start with an anonymous id (`$anon:<uuid>`; RevenueCat's `$RCAnonymousID:<32 hex>` is accepted too). When the person signs in, call this to move everything the anonymous customer bought, and its attributes, to `app_user_id`. The anonymous id keeps working as an alias. Safe to repeat; if the anonymous customer does not exist it only makes sure the user exists. With a public key the response contains the user's entitlements only.

ParameterInTypeDescription
anonymous_id*bodystring
app_user_id*bodystring

Get a customer with entitlements, subscriptions, purchases and attributes

GET/v1/customers/{app_user_id}
CLI
salesdogg customers get <app_user_id>
MCP tool
customers_get
Credentials
Session, Secret key

Server-side only. Client apps check access with GET /v1/customers/{app_user_id}/entitlements. An alias finds its customer.

ParameterInTypeDescription
app_user_id*pathstringYour own identifier for the user (URL-encoded). An alias works too.

Delete a customer, their aliases, attributes and purchase history

DELETE/v1/customers/{app_user_id}
CLI
salesdogg customers delete <app_user_id>
MCP tool
customers_delete
Credentials
Session, Secret key · sessions need the owner or admin role

Signed-in users need the owner or admin role in the organization.

ParameterInTypeDescription
app_user_id*pathstringYour own identifier for the user (URL-encoded). An alias works too.

Check what a user has access to

GET/v1/customers/{app_user_id}/entitlements
CLI
salesdogg customers entitlements <app_user_id>
MCP tool
customers_entitlements
Credentials
Session, Secret key, Public key

The access check. Returns the entitlements that are active right now. Unknown users return an empty list rather than an error, so it is safe to call for any user. Calls from an app (public key, or any key with an X-Platform header) update the customer's last-seen details.

ParameterInTypeDescription
app_user_id*pathstringYour own identifier for the user (URL-encoded). An alias works too.

Grant an entitlement without a purchase

POST/v1/customers/{app_user_id}/grants
CLI
salesdogg customers grant <app_user_id>
MCP tool
customers_grant
Credentials
Session, Secret key

Gives the user an entitlement directly (promotions, support, testing). Creates the customer if needed.

ParameterInTypeDescription
app_user_id*pathstringYour own identifier for the user (URL-encoded). An alias works too.
entitlement*bodystringEntitlement lookup_key or id.
expires_atbodystringOmit for a grant that never expires.

Revoke granted entitlements

DELETE/v1/customers/{app_user_id}/grants/{entitlement}
CLI
salesdogg customers revoke-grant <app_user_id> <entitlement>
MCP tool
customers_revoke_grant
Credentials
Session, Secret key

Revokes all active grants of the entitlement for this user. Access from purchases is unaffected.

ParameterInTypeDescription
app_user_id*pathstringYour own identifier for the user (URL-encoded). An alias works too.
entitlement*pathstringEntitlement lookup_key or id.

Subscriptions

List subscriptions

GET/v1/subscriptions
CLI
salesdogg subscriptions list
MCP tool
subscriptions_list
Credentials
Session, Secret key
ParameterInTypeDescription
limitqueryintegerPage size (1-100).
starting_afterquerystringCursor: the `next_cursor` value from the previous page.
app_user_idquerystring
statusquery"trialing" | "active" | "in_grace_period" | "past_due" | "paused" | "expired"
environmentquery"production" | "sandbox"

Get a subscription

GET/v1/subscriptions/{subscription_id}
CLI
salesdogg subscriptions get <subscription_id>
MCP tool
subscriptions_get
Credentials
Session, Secret key
ParameterInTypeDescription
subscription_id*pathstring

Purchases

List one-time purchases

GET/v1/purchases
CLI
salesdogg purchases list
MCP tool
purchases_list
Credentials
Session, Secret key
ParameterInTypeDescription
limitqueryintegerPage size (1-100).
starting_afterquerystringCursor: the `next_cursor` value from the previous page.
app_user_idquerystring

Receipts

Report a purchase made in a client app

POST/v1/receipts
CLI
salesdogg receipts submit
MCP tool
receipts_submit
Credentials
Session, Secret key, Public key

Validates the purchase with the store, records it for the user and returns their updated customer record. Call it right after a purchase or restore. `token` per provider: - app_store: the StoreKit 2 transaction `jwsRepresentation`. - play_store: the purchase token (also pass `store_product_identifier` for one-time products). - stripe / braintree: the subscription id (links an existing subscription to the user). Secret key only: unlike a store receipt, the id does not prove who bought it. If the purchase already belongs to another identified user, the project's restore behavior decides (GET/PATCH /v1/settings): `transfer` moves it to this user (a `transfer` event is recorded); `keep_with_original` refuses with 409 `receipt_already_in_use`. Purchases of anonymous users always move. With a public key the response contains the user's entitlements only: `attributes`, `subscriptions` and `purchases` are empty.

ParameterInTypeDescription
app_user_id*bodystring
app_idbodystringThe app (provider connection) the purchase was made through.
providerbody"stripe" | "braintree" | "app_store" | "play_store" | "simulator"Alternative to app_id when the project has exactly one app for this provider. Client SDKs send this.
token*bodystring
store_product_identifierbodystring

Checkout

Create a hosted checkout page for a user

POST/v1/checkout_sessions
CLI
salesdogg checkout create
MCP tool
checkout_create
Credentials
Session, Secret key

Returns a URL to send the user to. The resulting purchase is attributed to `app_user_id` automatically. Currently supported for Stripe products.

ParameterInTypeDescription
app_user_id*bodystring
product_id*bodystringProduct to sell (a Stripe product).
success_url*bodystring
cancel_urlbodystring
customer_emailbodystring
trial_daysbodyinteger

Events

List lifecycle events, newest first

GET/v1/events
CLI
salesdogg events list
MCP tool
events_list
Credentials
Session, Secret key

Every change to a subscription or purchase is recorded as an event, regardless of which store it came from. The same payloads are sent to webhook endpoints.

ParameterInTypeDescription
limitqueryintegerPage size (1-100).
starting_afterquerystringCursor: the `next_cursor` value from the previous page.
app_user_idquerystring
typequery"initial_purchase" | "trial_started" | "trial_converted" | "renewal" | "cancellation" | "uncancellation" | "billing_issue" | "billing_recovered" | "paused" | "resumed" | "product_change" | "expiration" | "refund" | "non_renewing_purchase" | "transfer" | "grant_created" | "grant_revoked" | "test"

Webhooks

List webhook endpoints

GET/v1/webhook_endpoints
CLI
salesdogg webhooks list
MCP tool
webhooks_list
Credentials
Session, Secret key

Register a webhook endpoint

POST/v1/webhook_endpoints
CLI
salesdogg webhooks create
MCP tool
webhooks_create
Credentials
Session, Secret key · sessions need the owner or admin role

Events are POSTed as JSON and retried with exponential backoff (8 attempts over about 2 days) until your endpoint returns 2xx. The signing secret is only returned here. Moving from RevenueCat: set `format: "revenuecat"` to receive RevenueCat's webhook body, and `authorization_header` to the value your receiver already checks. Events RevenueCat has no counterpart for (billing_recovered, which RevenueCat reports as the RENEWAL that follows, and grants) are not sent to such endpoints. Signed-in users need the owner or admin role in the organization.

ParameterInTypeDescription
url*bodystring
event_typesbody"initial_purchase" | "trial_started" | "trial_converted" | "renewal" | "cancellation" | "uncancellation" | "billing_issue" | "billing_recovered" | "paused" | "resumed" | "product_change" | "expiration" | "refund" | "non_renewing_purchase" | "transfer" | "grant_created" | "grant_revoked" | "test"[]Omit to receive all events.
formatbody"salesdogg" | "revenuecat"
authorization_headerbodystringSent verbatim as the Authorization header of every delivery, as RevenueCat does.

Delete a webhook endpoint

DELETE/v1/webhook_endpoints/{endpoint_id}
CLI
salesdogg webhooks delete <endpoint_id>
MCP tool
webhooks_delete
Credentials
Session, Secret key · sessions need the owner or admin role

Signed-in users need the owner or admin role in the organization.

ParameterInTypeDescription
endpoint_id*pathstring

Send a test event to all enabled endpoints

POST/v1/webhook_endpoints/{endpoint_id}/test
CLI
salesdogg webhooks test <endpoint_id>
MCP tool
webhooks_test
Credentials
Session, Secret key

Emits an event of type "test". Check the outcome with GET /v1/webhook_deliveries.

ParameterInTypeDescription
endpoint_id*pathstring

List webhook delivery attempts, newest first

GET/v1/webhook_deliveries
CLI
salesdogg webhooks deliveries
MCP tool
webhooks_deliveries
Credentials
Session, Secret key
ParameterInTypeDescription
limitqueryintegerPage size (1-100).
starting_afterquerystringCursor: the `next_cursor` value from the previous page.
endpoint_idquerystring
statusquery"pending" | "succeeded" | "failed"

Metrics

Headline numbers for the project

GET/v1/metrics/overview
CLI
salesdogg metrics overview
MCP tool
metrics_overview
Credentials
Session, Secret key
ParameterInTypeDescription
environmentquery"production" | "sandbox"

Daily subscription metrics over a date range

GET/v1/metrics/timeseries
CLI
salesdogg metrics timeseries
MCP tool
metrics_timeseries
Credentials
Session, Secret key

One point per UTC day: active subscriptions, trials and MRR at the end of the day, plus the day's new subscriptions, trial conversions, churn, cancellations, refunds and revenue. At most 366 days per request. MRR is based on each subscription's current price.

ParameterInTypeDescription
fromquerystringFirst day (YYYY-MM-DD, UTC). Defaults to 29 days before `to`.
toquerystringLast day (YYYY-MM-DD, UTC). Defaults to today.
environmentquery"production" | "sandbox"

Simulator

Simulate a purchase

POST/v1/simulator/purchases
CLI
salesdogg simulator purchase
MCP tool
simulator_purchase
Credentials
Session, Secret key

Creates a purchase without any store, so you can build and test against SalesDogg before connecting a provider. It goes through the same path as a real purchase: entitlements update, events are recorded and your webhook endpoints are called. Simulated data is always in the sandbox environment. Name the product either way: - `store_identifier`: any name you like (e.g. "pro_monthly"). The simulator app and the product are created if they do not exist. Zero setup. - `product_id`: an existing product, including one imported from a real provider, to test your real catalog and entitlements without paying. Subscriptions start active, or trialing when `trial_days` is set. Move them on with POST /v1/simulator/subscriptions/{subscription_id}/advance.

ParameterInTypeDescription
app_user_id*bodystring
store_identifierbodystring
product_idbodystring
typebody"subscription" | "one_time"Only with store_identifier, when the product does not exist yet. Default subscription.
trial_daysbodyintegerStart a subscription with a free trial of this length.
billing_periodbodystringISO 8601 duration of one billing cycle, e.g. P1M, P1Y, P1W.
price_amountbodyintegerPrice per billing period in minor units (cents).
currencybodystring

Move a simulated subscription through its lifecycle

POST/v1/simulator/subscriptions/{subscription_id}/advance
CLI
salesdogg simulator advance <subscription_id>
MCP tool
simulator_advance
Credentials
Session, Secret key

Applies one change to a subscription created by the simulator and returns the events it produced: - `renew`: start the next billing period (converts a trial, recovers a billing issue, resubscribes an expired subscription). - `cancel` / `uncancel`: turn auto-renew off or back on. Access continues until `expire`. - `fail_payment` / `recover`: enter and leave the billing-issue grace period. - `pause` / `resume`. - `expire`: end the subscription now; access is removed. - `refund`: refund the last charge and end the subscription. Only simulated subscriptions can be changed this way; real ones are driven by their store.

ParameterInTypeDescription
subscription_id*pathstring
action*body"renew" | "cancel" | "uncancel" | "fail_payment" | "recover" | "pause" | "resume" | "expire" | "refund"

Refund a simulated one-time purchase

POST/v1/simulator/purchases/{purchase_id}/refund
CLI
salesdogg simulator refund-purchase <purchase_id>
MCP tool
simulator_refund_purchase
Credentials
Session, Secret key

Marks the purchase refunded, which removes the access it granted.

ParameterInTypeDescription
purchase_id*pathstring

Settings

Change the project's settings

PATCH/v1/settings
CLI
salesdogg settings update
MCP tool
settings_update
Credentials
Session, Secret key · sessions need the owner or admin role

Signed-in users need the owner or admin role in the organization.

ParameterInTypeDescription
restore_behaviorbody"transfer" | "keep_with_original"

RevenueCat-compatible subscribers

Get (or create) a customer in RevenueCat's format

GET/v1/subscribers/{app_user_id}
CLI
salesdogg subscribers get <app_user_id>
MCP tool
subscribers_get
Credentials
Session, Secret key

RevenueCat REST API v1 compatible: same path, request and response shape. Creates the customer if it does not exist, as RevenueCat does. Send X-Platform only when the request is on behalf of the app; it updates last seen. grace_period_expires_date is always null; GET /v1/customers/{app_user_id}/entitlements is the authoritative access check.

ParameterInTypeDescription
app_user_id*pathstringThe app user id (or any alias).

Delete a customer (RevenueCat format)

DELETE/v1/subscribers/{app_user_id}
CLI
salesdogg subscribers delete <app_user_id>
MCP tool
subscribers_delete
Credentials
Session, Secret key · sessions need the owner or admin role

RevenueCat REST API v1 compatible: same path, request and response shape. Deletes the customer, their aliases, attributes and purchase history. Signed-in users need the owner or admin role in the organization.

ParameterInTypeDescription
app_user_id*pathstringThe app user id (or any alias).

Update customer attributes in RevenueCat's format

POST/v1/subscribers/{app_user_id}/attributes
CLI
salesdogg subscribers set-attributes <app_user_id>
MCP tool
subscribers_set_attributes
Credentials
Session, Secret key

RevenueCat REST API v1 compatible: same path, request and response shape. Body: { "attributes": { "<key>": { "value": "...", "updated_at_ms": 1709195668093 } } }. A null or empty value deletes the attribute; an older updated_at_ms never replaces a newer value.

ParameterInTypeDescription
app_user_id*pathstringThe app user id (or any alias).
attributes*bodyobject

Grant a promotional entitlement (RevenueCat format)

POST/v1/subscribers/{app_user_id}/entitlements/{entitlement_identifier}/promotional
CLI
salesdogg subscribers grant-promotional <app_user_id> <entitlement_identifier>
MCP tool
subscribers_grant_promotional
Credentials
Session, Secret key

RevenueCat REST API v1 compatible: same path, request and response shape. Pass duration (daily, three_day, weekly, two_week, monthly, two_month, three_month, six_month, yearly, lifetime) or end_time_ms. start_time_ms only moves the end of a duration; the grant is active from now. Same as POST /v1/customers/{app_user_id}/grants.

ParameterInTypeDescription
app_user_id*pathstringThe app user id (or any alias).
entitlement_identifier*pathstringEntitlement lookup_key.
durationbody"daily" | "three_day" | "weekly" | "two_week" | "monthly" | "two_month" | "three_month" | "six_month" | "yearly" | "lifetime"
start_time_msbodyinteger
end_time_msbodyinteger

Revoke promotional entitlements (RevenueCat format)

POST/v1/subscribers/{app_user_id}/entitlements/{entitlement_identifier}/revoke_promotionals
CLI
salesdogg subscribers revoke-promotionals <app_user_id> <entitlement_identifier>
MCP tool
subscribers_revoke_promotionals
Credentials
Session, Secret key

RevenueCat REST API v1 compatible: same path, request and response shape. Revokes every active grant of the entitlement. Access from purchases is unaffected.

ParameterInTypeDescription
app_user_id*pathstringThe app user id (or any alias).
entitlement_identifier*pathstringEntitlement lookup_key.

Imports

Import products, entitlements and offerings from RevenueCat

POST/v1/imports/revenuecat/catalog
CLI
salesdogg imports revenuecat-catalog
MCP tool
imports_revenuecat_catalog
Credentials
Session, Secret key · sessions need the owner or admin role

Step 1 of moving from RevenueCat. Connect your stores first (POST /v1/apps); RevenueCat apps are matched to them by bundle id / package name, or by store when there is one app per store. Products are created under the matching app (a Stripe product becomes one product per active price), entitlements and offerings by lookup_key. Safe to run again. Signed-in users need the owner or admin role in the organization.

ParameterInTypeDescription
api_key*bodystringA RevenueCat REST API v2 secret key with read access (project configuration and customer information). Used for this request only; never stored.
project_id*bodystringThe RevenueCat project id (proj...).
app_mapbodyobjectRevenueCat app id -> SalesDogg app id, only needed when a store has several SalesDogg apps that cannot be told apart by bundle id / package name.

Import one page of customers from RevenueCat

POST/v1/imports/revenuecat/customers
CLI
salesdogg imports revenuecat-customers
MCP tool
imports_revenuecat_customers
Credentials
Session, Secret key · sessions need the owner or admin role

Step 2, after the catalog. Call repeatedly with `starting_after: next_cursor` until `has_more` is false (`salesdogg import revenuecat` does this for you). Safe to re-run any page. Brings over app user ids and aliases, attributes, first/last seen and device details, and promotional entitlements (as grants). Store purchases are looked up at the store and recorded exactly as a store notification would be: Stripe through its API, Google Play through the Orders API, the App Store when the app has App Store Server API credentials. The rest count as `awaiting_app_sync`: the SalesDogg SDK records them on the app's next launch. Expired subscriptions are skipped unless include_expired is true. Nothing imported sends webhooks. Point the stores' notifications at SalesDogg before importing so no change is missed in between. Signed-in users need the owner or admin role in the organization.

ParameterInTypeDescription
api_key*bodystringA RevenueCat REST API v2 secret key with read access (project configuration and customer information). Used for this request only; never stored.
project_id*bodystringThe RevenueCat project id (proj...).
app_mapbodyobjectRevenueCat app id -> SalesDogg app id, only needed when a store has several SalesDogg apps that cannot be told apart by bundle id / package name.
starting_afterbodystringThe next_cursor of the previous page.
limitbodyintegerCustomers per call. Each takes about 4 RevenueCat requests plus one store lookup per purchase.
include_expiredbodybooleanAlso look up subscriptions that have expired, for history.

billing

Get the organization's SalesDogg plan, with an upgrade link on Free

GET/v1/billing
CLI
salesdogg billing get
MCP tool
billing_get
Credentials
Session, Secret key

Free is sandbox only. On Free, `upgrade_url` is a link a person can open to choose a plan and pay without signing in; show it to the user when they want to go live. Connecting live credentials on Free answers 402 `plan_required` with the same link in `error.details.upgrade_url`.