Audience: OttoKit engineering / App Builder team
Purpose: Native Trigv connector configuration (authentication + send-notification action)
API spec:public/openapi.yaml·trigv-api-reference.md
Production base URL:https://api.trigv.com/api
Last updated: 2026-07-09
Trigv is a developer push-notification service. Workspaces send JSON events to Trigv; Trigv queues mobile push delivery to iOS and Android devices. Notification title and body are not stored server-side — only metadata (channel, level, event type, timestamps).
The OttoKit connector is action-only for v1:
| Step | HTTP | Endpoint | Side effects |
|---|---|---|---|
| Verify credentials (connection test) | GET |
/v1/connection |
None — no event, no push, no billing |
| Send notification (action) | POST |
/v1/events |
Creates one billable event and queues push |
Do not use POST /v1/events for the connection test — that sends a real push and counts against the customer’s usage quota.
| Field | Value |
|---|---|
| App name | Trigv |
| Tagline | Send push alerts to iOS and Android from your automations |
| Description | Trigv sends instant mobile push notifications when something happens in your stack. Connect OttoKit workflows to Trigv to alert your team on deploys, form submissions, cron jobs, and more. Use your workspace API key and a channel slug — notification content is delivered to devices and not stored on Trigv servers. |
| App URL | https://trigv.com |
| Category | Developer Tools (or closest: Notifications / Automation / API) |
| Icon | Square PNG/JPG, mark only (no wordmark). App icon mark works at 256×256+. |
Bearer Token (HTTP Authorization header).
Trigv does not accept the API key in:
- JSON request body (
api_keyfield is prohibited →422) - URL query string (
?api_key=…is prohibited →422)
The customer’s plaintext workspace key must be sent only as:
Authorization: Bearer trgv_xxxxxxxx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx| Property | Value |
|---|---|
| Prefix | trgv_ |
| Pattern | trgv_{8 alphanumeric}_{32 alphanumeric} |
| Example shape | trgv_a1b2c3d4_0123456789abcdef0123456789abcdef |
| Where customers create keys | https://app.trigv.com/dashboard/api-keys |
| Shown to customer | Once at create/rotate — copy into OttoKit connection |
Not valid for ingest: login password, Sanctum session tokens ({id}|{secret} format).
OttoKit stores the customer’s plaintext key in the connection. Trigv never receives a pre-hashed key from the client.
- Parse
Authorization: Bearer {token}. - Validate token matches
^trgv_([a-zA-Z0-9]{8})_([a-zA-Z0-9]{32})$. - Look up
api_keysrow byprefix(trgv_{first_8_chars}). - Verify full token with bcrypt against stored
key_hash(Hash::check). - Require scope
events:write, key not revoked/expired, workspacestatus === active.
OttoKit should send the full plaintext key in the Bearer header on every authenticated request. Trigv hashes only at storage time.
Add one auth field:
| Setting | Value |
|---|---|
| Label | API Key |
| Field key / name | trigv_api_key |
| Type | Password / Secret |
| Required | Yes |
| Help text | Get your workspace API key from the [Trigv dashboard](https://app.trigv.com/dashboard/api-keys). It starts with trgv_ — not your login password. |
Use trigv_api_key, not api_key. If OttoKit mirrors Zapier-style behaviour and appends auth field names to the query string, the literal name api_key causes Trigv to return 422 The api key field is prohibited.
| Setting | Value |
|---|---|
| Bearer prefix | Leave empty (OttoKit default Bearer is correct) |
Resulting header: Authorization: Bearer {customer_plaintext_key}.
If OttoKit supports a second auth-only field for UI labelling (not sent to Trigv in JSON body), a connection_name string is fine — Trigv ignores unknown query parameters.
Use this for Verify Credentials / Test Connection. Read-only.
GET https://api.trigv.com/api/v1/connection
Accept: application/json
Authorization: Bearer {trigv_api_key}| Item | Value |
|---|---|
| Method | GET |
| URL | https://api.trigv.com/api/v1/connection |
| Request body | None |
| Query params | None required (do not add api_key) |
| Success HTTP status | 200 |
{
"workspace": {
"public_id": "ws_abc123",
"name": "My Workspace"
},
"api_key": {
"public_id": "key_xyz789",
"name": "Production",
"prefix": "trgv_a1b2c3d4"
}
}Suggested connection label (if OttoKit supports mapping from test response): {{workspace.name}} or {{api_key.name}}.
Never expose in UI: full plaintext key, key_hash, numeric database IDs, scopes, rate limits.
| HTTP | Meaning |
|---|---|
401 |
Missing Bearer token, malformed key, or wrong credential type (e.g. Sanctum token) |
403 |
Key revoked/expired, missing events:write, or workspace not active |
429 |
Connection-test rate limit (120/min per key or IP) — separate from event ingest limits |
curl -sS "https://api.trigv.com/api/v1/connection" \
-H "Accept: application/json" \
-H "Authorization: Bearer trgv_YOUR_KEY"Use this for the Send Notification action.
POST https://api.trigv.com/api/v1/events
Content-Type: application/json
Accept: application/json
Authorization: Bearer {trigv_api_key}| Item | Value |
|---|---|
| Method | POST |
| URL | https://api.trigv.com/api/v1/events |
| Content-Type | application/json |
| Success — new event | 202 Accepted |
| Success — duplicate idempotency key | 200 OK (returns existing event, no extra usage) |
Matches OpenAPI schema IngestEventRequest (public/openapi.yaml). additionalProperties: false — unknown keys are rejected.
| JSON field | Required | OttoKit input type | Max length | Default if omitted | Notes |
|---|---|---|---|---|---|
channel |
Yes | String (text) | 120 | — | Channel slug (e.g. general). Not a numeric ID or public_id. Must exist and be active in the customer’s workspace. |
title |
Yes | String (text) | 255 | — | Notification title shown on the push banner. |
description |
No | Text (multiline) | 1000 | — | Body text. If empty/omitted, push body falls back to title. |
level |
No | Dropdown | — | info |
Choices: info, success, warning, error. Mobile UI styling only — not delivery urgency. |
delivery_urgency |
No | Dropdown | — | standard |
Choices: standard, time_sensitive. iOS Focus / interruption level. Does not bypass mute switch. Separate from level. |
event_type |
No | String (text) | 120 | null |
Free-form label, e.g. deploy.completed, form.submitted. |
image_url |
No | String (URL) | 2048 | null |
HTTPS recommended. Passed through to FCM; not stored on Trigv servers. |
url |
No | String (URL) | 2048 | null |
Optional deep link (PR, deployment, issue). Passed in FCM data; not stored server-side. |
idempotency_key |
No | String (text) | 190 | null |
Per-workspace dedup. Same key → 200 + existing event, no extra billing. |
| Field | Error |
|---|---|
api_key |
The api key field is prohibited. |
icon |
Not supported on ingest |
| # | OttoKit label | Maps to JSON key | Required | UI control |
|---|---|---|---|---|
| 1 | Channel | channel |
Yes | Text — help: Channel slug, e.g. general |
| 2 | Title | title |
Yes | Text |
| 3 | Message | description |
No | Text (multiline) |
| 4 | Level | level |
No | Dropdown: info, success, warning, error — default info |
| 5 | Delivery urgency | delivery_urgency |
No | Dropdown: standard, time_sensitive — default standard |
| 6 | Event type | event_type |
No | Text — help: e.g. deploy.completed |
| 7 | Image URL | image_url |
No | URL string — help: HTTPS image URL |
| 8 | Link URL | url |
No | URL string — help: Optional link opened from the notification |
| 9 | Idempotency key | idempotency_key |
No | Text — help: Optional dedup key per workspace |
Level vs delivery urgency (show in help text):
- Level — how the notification looks in the Trigv app (
info/success/warning/error). - Delivery urgency — how iOS delivers the push (
standardvstime_sensitivefor Focus). Not the same as level.
Omit empty optional fields from the JSON body when possible.
{
"event": {
"public_id": "evt_01KWM1ZXDWGT563S5TN3SFQ13C",
"event_uuid": "5c528fc0-e7c1-4c6e-81b3-91baf570240b",
"status": "queued",
"level": "info",
"event_type": null,
"target_device_count": 1,
"received_at": "2026-07-03T13:16:51+00:00"
}
}title and description are not returned — they are not stored server-side.
target_device_count: 0 means the event was accepted but no devices are eligible for push on that channel (app not logged in, notifications off, or channel not subscribed).
| HTTP | Common cause |
|---|---|
401 |
Invalid/missing Bearer key |
403 |
Revoked/expired key or inactive workspace |
404 |
Channel slug not found or inactive |
422 |
Validation (missing channel/title, bad level, prohibited api_key, unknown fields) |
429 |
Per-key ingest rate limit (~60/min default) or monthly workspace event cap |
curl -sS -X POST "https://api.trigv.com/api/v1/events" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "Authorization: Bearer trgv_YOUR_KEY" \
-d '{
"channel": "general",
"title": "OttoKit test",
"description": "Sent from OttoKit App Builder",
"level": "success",
"delivery_urgency": "standard",
"event_type": "ottokit.test"
}'- Auth type: Bearer Token
- Auth field key:
trigv_api_key(notapi_key) - Bearer prefix: empty (default
Bearer) - Help text links to app.trigv.com/dashboard/api-keys
- Verify credentials:
GET https://api.trigv.com/api/v1/connection - Verify header:
Authorization: Bearer {{trigv_api_key}} - Verify body: empty
- Verify success:
200(notPOST /events)
- Method:
POST - URL:
https://api.trigv.com/api/v1/events - Headers:
Content-Type: application/json,Accept: application/json - Auth:
Authorization: Bearer {{trigv_api_key}} - Required inputs:
channel,title - Dropdowns:
level(defaultinfo),delivery_urgency(defaultstandard) - No
api_keyin body or query string - Test success:
202,status: "queued", push received on device
| Symptom | Cause | Fix |
|---|---|---|
422 + api key field is prohibited |
api_key in JSON body or query string |
Auth field must be named trigv_api_key; key only in Authorization: Bearer |
401 Unauthorized |
Wrong key or Sanctum token used | Use workspace key from dashboard; must start with trgv_ |
403 Forbidden |
Revoked/expired key or inactive workspace | Customer creates a new key or reactivates workspace |
404 Channel not found |
Invalid channel slug | Default slug is general (created at signup) |
| Connection test sends unwanted push | Using POST /events for verify |
Switch verify to GET /connection |
202 but no push |
target_device_count: 0 |
Customer must install Trigv app, log in, allow notifications, subscribe to channel |
| Resource | URL |
|---|---|
| Trigv marketing site | https://trigv.com |
| Customer dashboard | https://app.trigv.com |
| API key management | https://app.trigv.com/dashboard/api-keys |
| OpenAPI spec | https://api.trigv.com/openapi.yaml |
| Public API docs | https://trigv.com/docs/api |
| OttoKit generic API Action runbook (no native app) | ottokit.md |
| Connection endpoint implementation notes | ingest-connection-endpoint.md |
For integration questions during App Builder setup: privacy@trigv.com (or the Trigv account owner who submitted the connector).