v↗ValueSignal✳Request a trial ↗

Campaign service API · $149 + 1%

Current contract: USD $149 per natural month, prorated over effective service dates, plus 1% of actual media spend for registered Campaigns on those dates. One app, advertising platform and agreed IANA timezone per contract; multiple Campaigns share one base fee. No user-result allowance debit. Existing quota contracts retain their original terms and require explicit future migration.

1. Prepare an application and service scope

The platform owner creates an app with billing_mode="campaign" and its authoritative MMP billing_provider="af" or "adjust". Google Ads and other advertising platforms are separate from this MMP field. Agree source authorization, fields, history, processing capacity, cost definition, validated model and contract terms. Owner management calls use an authorized owner session and tenant_id; customer management uses a scoped web session with configure permission. Machine passwords are not API tokens.

Management route: POST /api/v2/apps/APP/ACTION. Replace APP with the real app ID; owner calls include ?tenant_id=TENANT. All requests use Content-Type: application/json; web writes must satisfy same-origin session protection. The equivalent /v2/ alias is supported. See the action fields below.

2. Register and approve a Campaign

Submit the following campaign-scope body. Keep all account and Campaign IDs as strings. The customer confirms adoption for the whole Campaign; owner verifies account ownership with campaign-approve before activation. A pending scope produces neither delivery permission nor spend obligations. Names are display-only. Observation-only scope authorizes reported actual metrics, not predictions or billing. Scope revisions are immutable; future effective_date does not alter current delivery eligibility.

{
  "id": "scope-a",
  "revision": 1,
  "platform": "google_ads",
  "ad_account_id": "90071992547409931234",
  "campaign_id": "campaign-a",
  "campaign_name": "Value test",
  "kind": "delivery",
  "signal_definition_id": "net-d90",
  "signal_version": "1",
  "optimization_setup": "Customer-managed value optimization",
  "adoption_confirmed": true,
  "result_data_from": "2026-10-01T00:00:00.000Z"
}

New activations and resumptions start at the next local midnight or later agreed date. The owner starts a company-once 30 × 24 hour trial only after usable registered data and a compatible model are ready. Trial payable is zero, including variable fees. Trial end never automatically enables paid service. Explicit acceptance and owner activation are required for postpaid service.

3. Upload the full authorized dataset and pull published results

The raw-v2 ingestion steps below remain the data transport. Each authoritative paid install intended for Campaign matching also includes ad_platform, ad_account_id and campaign_id, using the exact registered identity. Do not infer account ownership or match by Campaign name. Unknown identity remains internal and cannot be forced into a delivery scope. Authorized unregistered data may be analyzed internally; raw ingestion is not narrowed to the registered Campaign list.

"ad_platform": "google_ads",
"ad_account_id": "90071992547409931234",
"campaign_id": "campaign-a"

Owner load/daily operations perform processing. A stored internal prediction is not customer publication. GET users, user detail, results, insights, results/export and results/sync expose only independently receipted versions in the allowed scope. Follow returned cursors, then save sync_token for changes; restart on 410. No client advertising upload receipt is needed for billing, and successful reads do not prove platform adoption or ad lift.

4. Report daily actual spend by API or CSV

Use an app-bound batches:write token: POST /api/v2/apps/APP/campaign-spend with Authorization: Bearer YOUR_WRITE_TOKEN. results:read is not required for uploading. This token cannot approve scopes, review evidence, confirm invoices, finalize billing or record funds. GET result routes require a separate results:read token. Supply JSON rows or JSON {"csv":"HEADER\nROW"}; the CSV header is shown below. Each request contains 1–5000 complete daily rows and commits atomically.

{
  "rows": [
    {
      "platform": "google_ads",
      "ad_account_id": "90071992547409931234",
      "campaign_id": "campaign-a",
      "spend_date": "2026-10-19",
      "currency": "USD",
      "spend_cents": 10000,
      "revision": 1,
      "data_cutoff_at": "2026-10-20T12:00:00.000Z",
      "source_reference": "platform-export-2026-10-20"
    }
  ]
}
platform,ad_account_id,campaign_id,spend_date,currency,spend_cents,revision,data_cutoff_at,source_reference

Use USD integer cents, explicitly submit 0 for known zero spend, and never leave the amount blank. Only ended local days are accepted; data_cutoff_at must be at or after that local day’s end and not in the future. Same identity/date/revision and content is idempotent; same revision with changed content or an older revision returns 409. Higher revisions replace the effective snapshot and retain the previous version. Missing reports stay unknown. No weekly total is divided by seven. All reports remain customer_reported after owner source review; manual review is not platform_verified.

5. Observe weekly revenue separately

campaign-weeks uses Monday 00:00 UTC weeks and an explicit using_solution or not_using_solution group. Campaign contracts require platform and ad_account_id in addition to campaign_id; the example below includes them. Authorize the comparison Campaign separately as observation-only if its predictions are not delivered. This weekly source is not the daily billing ledger. Group differences alone do not establish causal lift.

{
  "records": [
    {
      "platform": "google_ads",
      "ad_account_id": "90071992547409931234",
      "campaign_id": "campaign-a",
      "campaign_name": "Value test",
      "group": "using_solution",
      "week_start": "2026-10-19T00:00:00.000Z",
      "currency": "USD",
      "revenue_cents": 10000,
      "data_cutoff": "2026-10-26T00:00:00.000Z",
      "revision": 1
    }
  ]
}

6. Reconcile, confirm and finalize

GET /api/v2/campaign-service?app_id=APP returns contract, scopes, active/pause_reason, daily spend, invoices and ledger. GET /api/v2/campaign-quote?app_id=APP&month=2026-11 produces a recomputation with input_hash, days, effective_spend_cents, base_cents, variable_cents, total_cents, missing and unreviewed. Resource aliases contracts, campaign-scopes, campaign-spend-days and invoices return the same service projection.

Owner creates an ended-month invoice, the customer confirms its current input_hash, and the owner finalizes that version. Missing or unreviewed reports prevent confirmation/finalization. Input changes require regeneration and reconfirmation; a concurrent revision rejects the stale commit. Only one finalized main invoice exists per contract month. Later corrections create a separately confirmed cumulative difference adjustment; they never overwrite the main invoice. A complete month with $20,000 effective spend is $149 + $200 = $349. A 30-day month with 15 effective dates and $5,000 effective spend is $124.50. Round the base and whole-period percentage separately to cents, then add.

7. Pause, close, restore and pay

Pause or cancel stops new deliveries immediately and billing at next local midnight. Previously published exact versions remain readable within current authorization and original retention. Internal new versions cannot leak through history, export or saved pages. Resume also waits until next local midnight and enforces its explicit install/cohort watermark on first deliveries. Closed Campaigns cannot resume; a new future registration is required. Revocation overrides historical receipts.

Submit complete spend by the fifth and reconcile by the seventh of the next month; unresolved reporting stops new service from the eighth. Final invoices are due seven days after issue, with seven more days of grace. Fixed stop deadlines do not move because nobody visits the UI. Resolving evidence or funds does not automatically resume jobs; owner restores with a validated watermark and gap decision. Owner records only externally completed payments/refunds, including partial payments or overpayments. Unique references prevent duplicates; refunds cannot exceed net paid funds. The system does not debit cards or transfer money.

Action schema and errors

ACTIONPermission / 权限Fields / 字段
campaign-contractownerid, revision, platform, billing_timezone, currency=USD, base_monthly_fee_cents=14900, fee_rate_bps=100, terms_accepted=true, terms_reference, processing_scope
campaign-scopeconfigureid, revision, platform, ad_account_id, campaign_id, kind, signal_definition_id, signal_version, optimization_setup, adoption_confirmed, result_data_from, result_data_to (optional), effective_date (optional)
campaign-approveownerid, account_verified=true
trialownerreference (recommended for retry / 建议重试时提供)
campaign-activateownerconfirm_paid=true, effective_date (optional)
campaign-pause / campaign-closeconfigureid
campaign-resumeconfigureid, resume_watermark (ISO timestamp)
contract-cancelconfigureconfirm_cancel=true, reason
campaign-spendbatches:write token / configure sessionrows OR csv
campaign-spend-reviewownerplatform, ad_account_id, campaign_id, spend_date, revision, evidence_checked=true
campaign-invoiceownerid, month (YYYY-MM, ended month / 已结束月份)
campaign-invoice-confirmconfigureid, input_hash
campaign-invoice-finalizeownerid, input_hash
campaign-adjustmentownerinvoice_id, reference, input_hash, customer_confirmed=true, reason
campaign-payment / campaign-refundownerinvoice_id, reference, amount_cents, external_verified=true, reason
campaign-waiverownerdate, reason, scope_id (optional)
campaign-restoreownerresume_watermark, confirm_gap_processing=true

400/422: invalid schema, amounts, date, missing confirmation or readiness. 401: invalid/expired credentials. 403: wrong tenant, app, role, token scope, revoked authorization or paused production. 409: immutable revision conflict, stale inputs, interval overlap or repeated company trial. 410: expired or changed synchronization snapshot. 413: payload too large. 503: temporary dependency failure. Retry transient failures with unchanged IDs/references; do not mark failed uploads as accepted. Use current dates in these examples and explicitly report ended days, never fabricated current/future final spend. Local software tests and synthetic demos do not establish platform verification, production cloud operation, real payment settlement or D90 lift.

Raw-v2 data transport

Current published plans start at $149/month for 5,000 delivered paid-user value results. Every plan offers a 30-day free trial using its selected allowance. First valid delivered results for new paid users consume allowance; repeat reads and updates do not. New deliveries pause at the limit, with no automatic overage charges. See all plans. Plans are confirmed through onboarding; existing accounts retain their agreed billing contract until explicitly migrated.

Send authorized raw install/event records to POST /v2/ingestion/batches?app_id=APP with an app-scoped batches:write token. Read the receipt separately; accepted means durable storage, not scoring. Query available results with a separate results:read token at GET /v2/results?app_id=APP. Organic data is stored but not billed. Models need real independent validation and manual publication; otherwise the service shows the actual waiting reason.

{"app_id":"APP","batch_id":"batch-001","source_system":"af","schema_version":"raw-v2","mode":"increment","records":[{"kind":"install","event_id":"source-record-001","provider_user_id":"original-MMP-ID","source_type":"paid","platform_install_time":"2026-10-30T00:00:00Z","occurred_at":"2026-10-30T00:00:00Z","currency":"USD","channel":"google","acquisition_cost_cents":100}]}

Original MMP identities and install times define paid acquisition. S24 contains the first 24 hours; daily processing begins at age 24 hours, with late-data recomputations versioned. Raw data expires 180 days after occurrence. Customer-specific datasets and purposes remain isolated. Customers execute advertising uploads and verify same-channel economic outcomes; this service does not store advertising credentials or place ads.

Open the authorized workspace. Full local pilot instructions: repository document docs/local-pilot.md.

Current v2 / 1. Prepare access and purpose

Ask the platform owner for an authorized account, the exact app_id and confirmed AppsFlyer (af) or Adjust (adjust) source. Confirm permission for install, event and cost data, source currency, channel scope, event mappings and the versioned cost policy. Initial validated scopes use USD. Keep original MMP user IDs; never substitute an advertising ID. Account passwords and machine credentials are independent.

Use a server-side app-bound token with batches:write to upload, a separate batches:read token to inspect receipts, and a results:read token to retrieve results and weekly revenue. The owner or an authorized technical administrator issues only granted scopes in Integration. Web-account export additionally requires export permission; tokens cannot perform owner actions. Keep tokens off browsers and out of logs. Revoke and rotate compromised tokens.

Current v2 / 2. Send installs and events

Send JSON with Content-Type: application/json and Authorization: Bearer YOUR_UPLOAD_TOKEN to POST /api/v2/ingestion/batches?app_id=app. The complete synthetic example below is exercised by the local HTTP contract test. Replace its IDs, times, currency and costs with authorized source facts. Do not send expired or future records. App scope comes from the credential and must match app_id; do not add tenant_id to records.

{
  "app_id": "app",
  "batch_id": "documented-batch-001",
  "source_system": "af",
  "schema_version": "raw-v2",
  "mode": "increment",
  "records": [
    {
      "kind": "install",
      "event_id": "documented-install-001",
      "provider_user_id": "documented-user",
      "attribution_provider": "af",
      "source_type": "paid",
      "platform_install_time": "2026-10-01T00:00:00.000Z",
      "occurred_at": "2026-10-01T00:00:00.000Z",
      "currency": "USD",
      "channel": "google",
      "acquisition_cost_cents": 100,
      "source_revision": 1
    },
    {
      "kind": "event",
      "event_id": "documented-core-001",
      "provider_user_id": "documented-user",
      "attribution_provider": "af",
      "source_type": "paid",
      "platform_install_time": "2026-10-01T00:00:00.000Z",
      "occurred_at": "2026-10-01T01:00:00.000Z",
      "currency": "USD",
      "channel": "google",
      "event_name": "core",
      "source_revision": 1
    }
  ]
}

For raw-v2, event_name core counts core actions, session counts active sessions, and trial indicates a started trial. Map source events to these agreed names before sending. source_type is explicitly paid, organic, retargeting or restricted; organic records are retained but do not consume paid-user allowance. All timestamps are ISO 8601 with an explicit offset; examples use UTC. Monetary fields ending _cents are exact integer cents (100 = USD 1.00). Predicted_value is in major currency units. Never send a predicted value as actual revenue.

HTTP 202
{"batch_id":"documented-batch-001","status":"accepted","records":2,"prediction_status":"pending","request_id":"…"}

Current v2 / 3. Reconcile the receipt and processing

202 accepted means durable staging only. Read the batch receipt with batches:read. The owner separately runs POST /api/v2/apps/app/load?tenant_id=YOUR_TENANT with an empty JSON object to normalize and load accepted batches, then POST /api/v2/apps/app/daily?tenant_id=YOUR_TENANT with an empty object or a non-future cutoff. These are owner operations, not upload-token capabilities or an automatic client API. Receipt status progresses through accepted/loading/loaded or blocked; inspect counts_json and error_code. A loaded receipt does not guarantee a scored user.

S24 uses events from install time inclusive to install + 24 hours exclusive. Daily processing starts once a user is at least 24 hours old. Compatible independently validated published models, agreed costs, confirmed purpose and active service allowance are required. Waiting reasons include waiting_s24, awaiting_daily_processing, awaiting_compatible_model and quota_exhausted. Late data can create a new current result version while preserving the first prediction.

Current v2 / 4. Pull one user, pages, changes or an export

GET /api/v2/ingestion/batches/documented-batch-001?app_id=app
Authorization: Bearer YOUR_RECEIPT_TOKEN

GET /api/v2/users/documented-user?app_id=app&provider=af
GET /api/v2/users?app_id=app&limit=100
GET /api/v2/users?app_id=app&limit=100&after=NEXT_CURSOR
GET /api/v2/results/sync?app_id=app&limit=100
GET /api/v2/results/sync?app_id=app&limit=100&cursor=NEXT_CURSOR
GET /api/v2/results/sync?app_id=app&since=SYNC_TOKEN
GET /api/v2/results/export?app_id=app
Authorization: Bearer YOUR_RESULT_TOKEN

The single-user response is {user:…}; provider=af or adjust disambiguates original IDs. The paged user list is {users:[…],next_cursor:…}; pass its opaque next_cursor as after and continue until null. This is the batch retrieval interface, not a POST list-of-IDs endpoint. Synchronization returns results, next_cursor, sync_token, publication_waterline and expires_at; pass next_cursor as cursor until null, then persist sync_token for the next since request. Incremental results can contain status:removed, reason:no_longer_visible; remove those local records. Tokens are principal-bound and snapshots expire no later than one day, sometimes earlier. On 410 or changed authorization, discard the cursor and begin a new snapshot. Exports return a JSON results array; do not leave this request in a tight polling loop.

Current v2 / 5. Use labels without changing their meaning

Store provider_user_id, attribution_provider, result_version, first_result_version, model_version, tag_rule_version and cost_policy_version. predicted_value can be negative. label is high_value or below_threshold only when scored. signal_eligible is true for a delivered result at or above the frozen channel threshold, false for a delivered result below it, and null when unavailable, unscored or allowance-blocked. null is unknown, not false. Unauthorized requests return an HTTP error. The threshold may be negative; percentile is a position in the reference distribution, not payment probability. Respect expires_at and withdrawn results. Your team confirms an allowed advertising event/value mapping and executes uploads from its own accounts. There is no automatic advertising-upload endpoint here; predicted revenue is not an actual purchase and model validation is not causal lift.

Current v2 / 6. Retry, retention and capacity

Production raw JSON batches support at most 2 MB uncompressed and 1–1,000 records. Each app uses a bounded snapshot of at most 50,000 analytical rows / 16 MB. Over-capacity requests are rejected without truncation. Confirm capacity before onboarding. Stable source event_id and batch_id are required. Retry a lost receipt with the exact same batch content and identifier: an identical replay is idempotent; changed content with the same batch_id is 409 batch_conflict. Use a new batch_id and higher source_revision for supported corrections; immutable user/install identity changes are quarantined. Batches are not inherently interchangeable with source-event revisions.

For HTTP 409, inspect error.code first: configuration_busy and configuration_lock_lost mean temporary control-lock contention or loss, rather than a content conflict. Retry batch, configuration and contract requests with the same IDs, revision and original payload, using bounded exponential backoff with jitter. Preserve the original batch_id and source event_id; never change batch_id to bypass a lock error. Some steps may have committed before lock loss: check the original receipt or current configuration, then retry with the same identifiers and original content. In contrast, batch_conflict means that content actually differs for the same batch ID; do not blindly retry it as a temporary lock error. Create a new batch only for a genuine data correction under the correction rules above.

Handle 400/422 by correcting input; 401 by checking token validity; 403 by checking app, scope, purpose and service status. Do not retry permission failures indefinitely. For transient 5xx, use bounded exponential backoff and the same idempotency identifiers; preserve request_id when asking support. For other 409 codes, check the current immutable revision or authorization fence rather than blindly overwriting it. Missing warehouse service is 503, never successful delivery.

Raw events expire 180 days after occurrence; result visibility is bounded by install + 180 days and current authorization. Staging is at most seven days and can expire sooner. After service stops, receiving/computation stops and export visibility is at most 30 days, still subject to earlier retention. Renewal never restores expired data. Read 1–500 results per user/sync page; weekly revenue reads at most 100 records per page. At allowance exhaustion, new valid paid-user deliveries pause: no overage charge, no automatic upgrade or renewal. The first delivery consumes one user once, including negative/low values; recalculation and reads do not. The next period requires the selected plan, owner invoice and verified external payment after the full current period. Follow the weekly protocol below for its separate record/revision limits.

Legacy quota contracts and allowances

Each plan applies to one confirmed app. The first paid period starts after the trial ends and paid activation is confirmed. Monthly periods follow the activation anniversary in UTC. Higher plans start only in the next period, after the full current trial or paid period, an owner-frozen invoice and verified external payment. Current-period allowance never increases when a request is registered. Unused allowance does not roll over. Users awaiting results when allowance is exhausted are not automatically charged next month: only still-retained, eligible users explicitly included in the renewed/upgraded scope may resume processing; expired data cannot be restored by renewing.

Legacy v1 reference below

The v1 snapshots, 399/5000 allowance and synthetic demo below describe the previous implementation, not the current quote or raw v2 API. Keep existing v1 integrations unchanged while planning migration.

DATA IN. USER VALUE OUT.

API integration guide

Send user data from your server, receive value labels through an API, and review historical submissions in a private dashboard. The initial contract predicts 90-day net value from a 24-hour behavior snapshot in USD.

01 / Get started

Leave your contact details on the website. We confirm your product, data readiness, trial start and value definition, then provide scoped server API Tokens, a separately authorized login account and your dashboard URL.

  1. Keep the write key on your server; never embed it in a public app or webpage.
  2. Upload stable anonymous user IDs, observation timestamps, attribution and early behavior snapshots.
  3. Receive scored results directly, or query results later.
  4. Sign in with your separately authorized account to open the private dashboard. View a public, synthetic example at the live demo.
A production customer needs a validated customer-specific model. Until it is configured, valid submissions are stored and return awaiting_model. Synthetic models are restricted to demo tenants. We handle model fitting and maintenance; customers do not need to run the algorithm.

02 / One value definition

actual_value_D90 = D90 net income − D90 non-ad service costs − acquisition cost

Net income must already account for the agreed refunds, platform/payment fees and taxes. Do not deduct those costs twice. Acquisition cost is known at scoring time or allocated under an agreed rule and then frozen for that prediction.

Results include predicted value, reference percentile, high-value threshold, label, tree leaf, decision path and model versions. Negative values are preserved. High value is not a purchase guarantee. Model reference percentiles are frozen to a chronological calibration cohort.

The current schema supports core_count_24h, active_sessions_24h, trial_started_24h, known acquisition cost and the channels google/meta/tiktok. Additional factor schemas require an agreed, validated model version. Values outside a model’s validated domain are stored with out_of_distribution, rather than silently extrapolated.

03 / Send paid-user snapshots

Explicit source_type=paid is required. Organic users return ignored_organic and are not stored, scored or billed. was_paid is payer state, not an attribution source. The dated example below uses mode=historical and requires history:write plus users:write scopes; historical imports do not consume live acquisition allowance. Use mode=live for current user snapshots.

POST https://getvaluesignal.com/v1/users/batch
Authorization: Bearer YOUR_SCOPED_API_TOKEN
Content-Type: application/json

Send 1–20 users per request, up to 250KB, one snapshot per user in each batch. The complete batch is validated before an atomic database write. Dates must include a timezone. Use the same event ID and unchanged body when retrying.

{
  "mode": "historical",
  "users": [{
    "event_id": "snapshot_example_001",
    "user_id": "anonymous_001",
    "source_type": "paid",
    "cohort_at": "2026-06-01T00:00:00Z",
    "snapshot_at": "2026-06-02T00:00:00Z",
    "features_available_at": "2026-06-02T00:00:00Z",
    "attributed_at": "2026-06-01T00:00:00Z",
    "currency": "USD",
    "features": {
      "core_count_24h": 8,
      "active_sessions_24h": 3,
      "trial_started_24h": 1,
      "acquisition_cost": 7.50,
      "channel": "google"
    }
  }]
}
FieldRequirement
event_id / user_idStable IDs, 1–128 letters, digits or _.:@-; do not send direct personal identifiers.
source_typepaid / organic; organic is ignored and never billed.
cohort_atFixed user entry time; immutable for that user.
snapshot_atExactly 24 hours after entry for the current model. Earlier snapshots return waiting_observation.
features_available_atNo later than snapshot_at. The source must ensure that features were genuinely available then.
attributed_atRequired for paid acquisition, with a timezone. The first attribution is immutable.
core_count_24hNonnegative integer, count of agreed core task completions in the observation window.
active_sessions_24h / trial_started_24hRequired nonnegative integer sessions and trial state 0/1.
acquisition_costNonnegative cost in USD, using the agreed allocation.
channelgoogle, meta or tiktok for the initial factor schema.

The response includes accepted and duplicate counts, user status and result fields. Historical replay is explicitly marked and does not prove that the prediction existed at the historical snapshot time.

04 / Read results

GET https://getvaluesignal.com/v1/users?limit=30
GET https://getvaluesignal.com/v1/users?limit=30&after=LAST_USER_ID
GET https://getvaluesignal.com/v1/users/anonymous_001
GET https://getvaluesignal.com/v1/summary?month=2026-10
Authorization: Bearer YOUR_READ_API_TOKEN

The list supports limit (1–100), after, channel and status. Use next_cursor from a response as after for the next page. A single-user response includes immutable first_prediction and latest_prediction. Results are delivered through HTTP responses and queries; outbound webhooks and ad-platform upload connectors are not enabled in this version.

{
  "user_id": "anonymous_001",
  "status": "scored",
  "predicted_value": 12.34,
  "currency": "USD", "horizon_days": 90,
  "percentile": 68.5,
  "is_high_value": false,
  "threshold": 18.50,
  "leaf_id": "rootLR",
  "model_version": "YOUR_MODEL_VERSION",
  "historical_replay": true
}

The numbers above are structural examples. Actual results depend on the installed model. Other statuses include awaiting_model, waiting_observation, unsupported_snapshot and out_of_distribution; inspect reason before using a result.

05 / Send complete mature outcomes

POST https://getvaluesignal.com/v1/outcomes/batch
Authorization: Bearer YOUR_SCOPED_API_TOKEN
Content-Type: application/json
{
  "outcomes": [{
    "components_complete": true,
    "event_id": "outcome_example_001",
    "user_id": "anonymous_001",
    "currency": "USD", "horizon_days": 90,
    "window_end": "2026-08-30T00:00:00Z",
    "label_available_at": "2026-09-03T00:00:00Z",
    "net_income": 26.50,
    "non_ad_cost": 4.60,
    "acquisition_cost": 7.50
  }]
}

Upload the user first. The target window must be exactly 90 days after cohort_at and complete before label_available_at. Costs must be complete, and acquisition cost must match the frozen scoring input. The system calculates actual_value and compares it with the first prediction. Repeating an identical outcome is idempotent; conflicting corrections require a versioned support process.

06 / Authorized accounts and scoped API tokens

There is no public registration. A platform owner creates and grants an enabled account first. Tenant administrators manage only their own members and tokens; viewers read only their own customer data. Login uses a username and a system-generated high-entropy login secret, delivered privately. Login credentials are separate from API tokens. Tokens have scopes, expiry and immediate revocation. Send tokens in the Authorization header, never in URLs.

Supported scopes: users:write, outcomes:write, users:read, metrics:read and history:write. Account/tenant disable and token expiry/revocation are checked on every request. GET /v1/groups returns unequal regression-tree groups, their rules, counts and predicted/actual values.

Legacy v1 only / historical usage and trial

This section describes the previous contract, not current public plans. View current terms.

USD/month = 399 + max(new attributed users − 5,000, 0) × 0.02

Only paid users accepted in live mode are counted once under the tenant’s stable user ID; historical imports and organic users are excluded. The billing month is the UTC month of first server acceptance into attributed service. Repeated events, retries and rescoring do not count again. Anonymous/unattributed users do not consume attributed-user allowance until attributed.

The 30-day trial begins after data readiness and mutual confirmation. The trial includes 5,000 new attributed users with no base fee. Any extra trial usage is confirmed in advance. Continuation and the final statement are agreed privately; payment is by bank transfer, without automatic charges. Dashboard amounts are estimates, not invoices. Taxes and settlement currency are agreed separately.

08 / Information use

The inquiry form stores your name, contact email, product information and any optional contact details or request you provide. We use them to reply, assess readiness and arrange the trial. Inquiry records are held in cloud storage and protected by an administrator key; they are not public.

Customer business data is isolated by tenant. Send stable anonymous IDs, not personal contact details or payment card data, in the data APIs. Access scope, storage region, retention, deletion and contractual data processing are confirmed before real customer onboarding. Ask for corrections or deletion through your service contact.

Ready to connect? Leave your email and product details.
Request a trial ↗

Weekly campaign observations / 每周 Campaign 观测

POST /api/v2/campaign-weeks?app_id=APP requires batches:write; GET requires results:read. Web sessions require the same app upload/read permissions. /v2 is an equivalent alias. Source authorization, tenant/app isolation, token validity and stop/retention rules apply. No ad accounts are pulled. Observational group revenue differences do not establish causation.

{"records":[{"campaign_id":"campaign-a","campaign_name":"Campaign A","group":"using_solution","week_start":"2026-10-19T00:00:00.000Z","currency":"USD","revenue_cents":10000,"spend_cents":3000,"users":40,"data_cutoff":"2026-10-26T00:00:00.000Z","revision":1}]}

Each POST contains 1–100 records. campaign_id is a stable identifier, campaign_name is 1–200 characters. Explicit group is using_solution or not_using_solution; a campaign’s group cannot silently change, including across weeks. week_start is Monday 00:00 UTC; only fully ended seven-day weeks are accepted. data_cutoff must be at or after week end and no later than receipt time. Currency must match the app. revenue_cents is required; spend_cents and users are optional. All amounts and users are nonnegative safe integers; amounts are integer cents. revision is a positive safe integer. Unknown fields are rejected. Identical campaign/week/revision replays are idempotent; changed content at the same revision, old revisions or group changes return 409. Higher revisions correct the same campaign/week.

GET accepts from/to ISO UTC timestamps (inclusive week starts), spanning at most 56 days and ending no later than the latest complete week. Default: latest eight complete weeks. limit is 1–100, default 100. Response contains records, from/to, next_cursor, groups (each group’s range record count, latest_week, latest_received_at and stale), and comparison_complete. Missing or stale groups make the comparison incomplete. Revenue charts represent current-page subtotals, never full-range totals. To inspect another bounded page, send cursor with the same from/to; do not assume absent page records are zero. Stop when next_cursor is null. No server polling task is implied.

GET /api/v2/campaign-weeks?app_id=APP&from=2026-10-05T00%3A00%3A00.000Z&to=2026-10-26T00%3A00%3A00.000Z&limit=100
Authorization: Bearer YOUR_SERVER_TOKEN

Weekly data expires 180 days after week end. Stopped service rejects uploads; authorized read/export remains available only within the existing 30-day stop grace and row retention. Purge removes expired data. 401: invalid/expired/revoked credentials. 403: scope/app/tenant/purpose or stopped-write denial. 405: use GET or POST. 422: campaign_batch, campaign_contract, campaign_amount, campaign_duplicate, campaign_expired, campaign_range or campaign_cursor validation errors. 409: campaign_group_conflict, campaign_revision_old or campaign_revision_conflict. 413: JSON body exceeds 2 MB. 503: temporary failure; retry unchanged records. A successful POST returns accepted and duplicate counts.

下期升级意向只登记购买确认,不改变当前额度,也不自动付款。负责人冻结账单时须将申请编号作为 customer_confirmation_reference,且匹配套餐、价格、开始时间和类型;核款并登记对应周期后,意向状态变为 fulfilled。历史意向也可能为 expired 或 superseded。

Authorized accounts and result synchronization

The customer console matches the browser language on first access and supports seven languages with a persistent manual choice. Your platform owner creates your email account and app permissions. First login requires a password change; applications do not register accounts automatically. The operations console manages company contacts, accounts and app grants.

Use /api/v2/ingestion/batches for reliable raw-v2 reports, /api/v2/users/:id?app_id=...&provider=af for a user, and /api/v2/results/sync?app_id=... for a fixed snapshot. Follow next_cursor until null, save sync_token, then request since=SYNC_TOKEN for incremental changes. Scope and expiry are rechecked on every page. A 410 means start a fresh snapshot; cursors never extend retention.

Each result includes nullable predicted_value, status/reason, label/tags and rule version, model/result/cost-policy versions, cutoff/expiry, first prediction and independent actual D90. /api/v2/insights separates backtests from actual experiment results; /api/v2/results/export requires export permission for web accounts. Machine tokens are independent of creator account disable; revoke them explicitly. Advertising uploads are executed by the customer.