brily
API reference

NPS responses.

Trigger surveys from release events or on a schedule, fetch individual responses, and build cohort reports programmatically. Everything the dashboard does is available via the API.

The Survey object

{
  "id": "srv_3aH2",
  "name": "post-release-v1.24",
  "question": "How likely are you to recommend ship-os to a colleague?",
  "follow_up": {
    "promoter": "What's the one thing that made you rate us this high?",
    "passive": "What's the one thing that would have made this a 9 or 10?",
    "detractor": "What's the biggest reason we're not working for you?"
  },
  "trigger": {
    "type": "release",
    "release_id": "rel_9f3K",
    "delay_hours": 168
  },
  "audience": {
    "plan_tier": ["pro", "team"],
    "min_account_age_days": 30
  },
  "response_count": 142,
  "project_id": "proj_7KfD1",
  "created_at": "2026-04-18T09:12:14Z"
}

The Response object

{
  "id": "rsp_8392",
  "survey_id": "srv_3aH2",
  "external_user_id": "user_1245",
  "score": 9,
  "cohort": "promoter",
  "follow_up_text": "The new search finally returns useful results.",
  "release_exposure": {
    "release_id": "rel_9f3K",
    "release_name": "release-1.24",
    "exposed_at": "2026-04-15T08:22:00Z"
  },
  "metadata": {
    "plan_tier": "pro",
    "account_age_days": 421
  },
  "consent_to_contact": true,
  "submitted_at": "2026-04-22T14:12:48Z"
}

Create a survey

POST/v0/surveys
curl -X POST https://api.brily.app/v0/surveys \
  -H "Authorization: Bearer $BRILY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "post-release-v1.24",
    "trigger": {
      "type": "release",
      "release_id": "rel_9f3K",
      "delay_hours": 24
    },
    "audience": {
      "plan_tier": ["pro", "team"],
      "min_account_age_days": 7
    }
  }'

List responses

GET/v0/responses

Query params: survey_id, cohort (promoter / passive / detractor), release_id, from, to, min_score, max_score, pagination.

Cohort report

GET/v0/reports/cohortBefore/after cohort comparison for a release

Query params: release_id (required), window_days (default 30).

{
  "release_id": "rel_9f3K",
  "exposed": {
    "n": 120,
    "nps": 54,
    "distribution": { "promoters": 53, "passives": 42, "detractors": 25 }
  },
  "control": {
    "n": 98,
    "nps": 42,
    "distribution": { "promoters": 41, "passives": 44, "detractors": 13 }
  },
  "delta": 12,
  "confidence": 0.87,
  "method": "bootstrap, n=10000"
}

Widget events (JavaScript)

If you use the in-app widget, you supply the user identifier once at load time; responses are attributed automatically.

<script>
  window.Brily = window.Brily || {};
  window.Brily.init({
    project: "proj_7KfD1",
    user: {
      external_id: "user_1245",
      metadata: {
        plan_tier: "pro",
        account_age_days: 421
      }
    }
  });
</script>
<script src="https://cdn.brily.app/nps.js" defer></script>

Webhooks

Subscribe to the response.created event in Settings → Webhooksand you'll receive the full Response object in real time. Useful for piping into your BI warehouse or triggering follow-up workflows on low-score responses.

POST https://your-app/hooks/brily
Content-Type: application/json
X-Brily-Signature: sha256=7f2a...

{
  "event": "response.created",
  "data": { /* Response object */ }
}

Export

GET/v0/responses/exportCSV or JSONL stream of every response

Same filters as list. Streams directly; no per-export fees.