Skip to main content
Use Refiner through Corsair: one client, typed API calls. Create an API key under Environment Settings, API Keys in the Refiner dashboard. It goes in Authorization: Bearer, the method Refiner recommends; the api_key= parameter and HTTP Basic both still work but are never used here, because a credential in a URL is logged by every proxy on the way. Things to know before you wire it up:
  • Two operations can create a contact. users.identify creates the contact on first sight, and users.track and segments.sync also create one when no match exists. All three are marked write for that reason, even though a track sounds like an append.
  • users.identify forwards every unrecognised key as a trait. Refiner infers a trait’s type from the value: a key ending in _at is parsed as a date, an unquoted integer is a number, an unquoted true/false a boolean, and anything else a string. Nothing is coerced here, so send the type you mean — {"a_number": 42} rather than {"a_number": "42"}. Pass account: { id: … } to group contacts under one account.
  • responses.store needs a survey that already exists. form_uuid is required, but the survey may be empty and unpublished, so a dummy survey works as a container for imported history. Put answers at the top level keyed by question identifier, and set date on a historical import or everything lands on the import day. Refiner de-duplicates by default; prevent_duplicates: false turns that off, which is why the operation is never retried.
  • responses.list includes survey views, not only answers. With the default include: completed only answers come back; all adds dismissed views, whose data values and completed_at are null. Reading a null score as a zero would quietly corrupt an average.
  • Timestamps in a response are YYYY-MM-DD HH:MM:SS, not ISO 8601. That is what Refiner sends, so parse them accordingly; the report endpoints use ISO 8601 with microseconds instead.
  • forms.archive is an archive, not a delete. The route is DELETE /forms, but the docs say “archive” and the survey still appears under list: 'all_with_archived'. forms.duplicate makes a new draft, and forms.publish takes one live.
  • contacts.delete also removes the contact’s survey responses. When an erasure request must leave the responses intact, the docs suggest overwriting the sensitive traits with users.identify instead.
  • segments.sync distinguishes adding from removing by HTTP method, not by a body field. The plugin sends POST to add and DELETE to remove, via remove: true. Only manual segments can be changed this way; a computed one will not accept it.
  • Two lists page by cursor. responses.list and contacts.list answer pagination.next_page_cursor; pass it back as page_cursor. Refiner recommends the cursor over numeric pages above 10,000 entries. forms.list, forms.history and segments.list take page and page_length only. page_length caps at 1,000.
  • Filters are bracketed keys. response_data[nps]=9, contact_data[country]=France and account_data[plan]=pro are built explicitly; when several keys are given, all must match.
  • Rate limits and errors. 4,000 requests a minute and 1,000 per 15 seconds per key, plus 100 a minute per user for the endpoints that take an identifier. A 429 carries Retry-After, which the plugin honours. A 409 on identify-user means another request for that user is in flight and clears on its own, so the plugin waits it out.
What you get:
  • 17 typed API operations

Setup

1

Install

2

Add the plugin

corsair.ts
With multiTenancy: true, scope calls with corsair.withTenant(id). See Quick start for KEK + Hub keys, and Multi-tenancy for account isolation.
3

Choose authentication

4

Connect a tenant

Mint a connect link and send the tenant to it. Hub hosts the page and delivers the result to your app — see Connect / OAuth.

Example API calls

Read the account usage
Identify a user
See the full list on the API page.

What’s next

API reference

Every refiner.api.* operation with input and output types.

Connect / OAuth

createLink, Hub delivery, and tenant connect flows.

Use with agents

Expose this plugin’s operations as MCP tools.