Skip to content

API reference

Every endpoint, generated from the OpenAPI document. Base URL: https://taseli.co.il/api/v1.

Workspace

The business a key opens.

The business this key opens

GET/workspace

ReturnsType
idstring
namestring
slugstringIn the app's links.
currencystring
planfree starter pro agency
accountsintegerConnected ad accounts.
curl https://taseli.co.il/api/v1/workspace \
  -H "Authorization: Bearer $TASELI_KEY"
Response 200
{
  "data": {
    "id": "0b6f3c1e-7a42-4c55-9b1d-2f6e8a1c4d90",
    "name": "Dan Plumbing",
    "slug": "dan-plumbing",
    "currency": "ILS",
    "plan": "pro",
    "accounts": 2
  }
}

Accounts

The connected Google, Meta and TikTok ad accounts, and their numbers.

List ad accounts

GET/accounts

QueryType
limitintegerHow many, from 1 to 100. Default 50.
cursorstringnextCursor from the previous page.
ReturnsType
idstring
namestring
platformgoogle meta tiktok
externalIdstringThe platform's own id.
currencystring
timezonestringThe account's time zone: its metrics' days end here.
statusactive syncing needs_reconnect suspended
readOnlybooleanNothing changes in it, even approved.
goalleads sales calls traffic
targetobject
target.kindcpa roas
target.valuenumberMoney for cpa, a ratio for roas.
target.setbooleanFalse: nobody set a target; value is the account's own cost per result standing in.
lastSyncAtstring
budgetobject
budget.monthlynumber
budget.spentMtdnumberSpent this month.
budget.forecastnumberWhere the month ends at this pace.
budget.setbooleanFalse: no monthly budget set; monthly is the pace estimate.
last28object
last28.costnumber
last28.conversionsnumber
last28.valuenumberThe conversion value the platform reports. 0 when it reports none.
last28.clicksinteger
last28.impressionsinteger
totalintegerHow many in the whole list.
nextCursorstring or null
curl https://taseli.co.il/api/v1/accounts \
  -H "Authorization: Bearer $TASELI_KEY"
Response 200
{
  "data": [
    {
      "id": "0b6f3c1e-7a42-4c55-9b1d-2f6e8a1c4d90",
      "name": "Dan Plumbing Search",
      "platform": "google",
      "externalId": "123-456-7890",
      "currency": "ILS",
      "timezone": "Asia/Jerusalem",
      "status": "active",
      "readOnly": false,
      "goal": "leads",
      "target": {
        "kind": "cpa",
        "value": 85,
        "set": true
      },
      "lastSyncAt": "2026-10-20T08:12:00.000Z",
      "budget": {
        "monthly": 6000,
        "spentMtd": 2140.5,
        "forecast": 5890,
        "set": true
      },
      "last28": {
        "cost": 5320.1,
        "conversions": 61,
        "value": 0,
        "clicks": 1840,
        "impressions": 41200
      }
    }
  ],
  "total": 1,
  "nextCursor": null
}

One ad account

GET/accounts/{id}

PathType
idstringThe account's Taseli id. Required.
ReturnsType
idstring
namestring
platformgoogle meta tiktok
externalIdstringThe platform's own id.
currencystring
timezonestringThe account's time zone: its metrics' days end here.
statusactive syncing needs_reconnect suspended
readOnlybooleanNothing changes in it, even approved.
goalleads sales calls traffic
targetobject
target.kindcpa roas
target.valuenumberMoney for cpa, a ratio for roas.
target.setbooleanFalse: nobody set a target; value is the account's own cost per result standing in.
lastSyncAtstring
budgetobject
budget.monthlynumber
budget.spentMtdnumberSpent this month.
budget.forecastnumberWhere the month ends at this pace.
budget.setbooleanFalse: no monthly budget set; monthly is the pace estimate.
last28object
last28.costnumber
last28.conversionsnumber
last28.valuenumberThe conversion value the platform reports. 0 when it reports none.
last28.clicksinteger
last28.impressionsinteger
curl "https://taseli.co.il/api/v1/accounts/$ACCOUNT_ID" \
  -H "Authorization: Bearer $TASELI_KEY"
Response 200
{
  "data": {
    "id": "0b6f3c1e-7a42-4c55-9b1d-2f6e8a1c4d90",
    "name": "Dan Plumbing Search",
    "platform": "google",
    "externalId": "123-456-7890",
    "currency": "ILS",
    "timezone": "Asia/Jerusalem",
    "status": "active",
    "readOnly": false,
    "goal": "leads",
    "target": {
      "kind": "cpa",
      "value": 85,
      "set": true
    },
    "lastSyncAt": "2026-10-20T08:12:00.000Z",
    "budget": {
      "monthly": 6000,
      "spentMtd": 2140.5,
      "forecast": 5890,
      "set": true
    },
    "last28": {
      "cost": 5320.1,
      "conversions": 61,
      "value": 0,
      "clicks": 1840,
      "impressions": 41200
    }
  }
}

Daily metrics, or totals by campaign

GET/accounts/{id}/metrics

As synced from the platform once a day, in the account's currency and time zone. A day not synced yet is missing, never zero. At most 400 days per call. by=campaign gives the 200 campaigns that spent the most in the period; for one row per campaign per day, call it once per day.

PathType
idstringThe account's Taseli id. Required.
QueryType
fromstringFirst day, YYYY-MM-DD. Default: 29 days before to.
tostringLast day, YYYY-MM-DD. Default: today (UTC).
byday campaignOne row per day, or totals per campaign. Default day.
ReturnsType
accountstring
currencystring
fromstring
tostring
daysobject[]Optional.
days[].datestring
days[].costnumber
days[].conversionsnumber
days[].valuenumber
days[].clicksinteger
days[].impressionsinteger
totalsobjectOptional.
totals.costnumber
totals.conversionsnumber
totals.valuenumber
totals.clicksinteger
totals.impressionsinteger
totals.costPerConversionnumber or null
totals.ctrnumber or null
campaignsobject[]Optional.
campaigns[].idstringThe campaign's Taseli id.
campaigns[].namestring
campaigns[].costnumber
campaigns[].conversionsnumber
campaigns[].valuenumber
campaigns[].clicksinteger
campaigns[].impressionsinteger
campaigns[].costPerConversionnumber or null
curl "https://taseli.co.il/api/v1/accounts/$ACCOUNT_ID/metrics?from=2026-10-01&to=2026-10-20&by=day" \
  -H "Authorization: Bearer $TASELI_KEY"
Response 200
{
  "data": {
    "account": "0b6f3c1e-7a42-4c55-9b1d-2f6e8a1c4d90",
    "currency": "ILS",
    "from": null,
    "to": null,
    "days": [
      {
        "date": "2026-10-19",
        "cost": 182.4,
        "conversions": 3,
        "value": 0,
        "clicks": 64,
        "impressions": 1390
      }
    ],
    "totals": {
      "cost": 182.4,
      "conversions": 3,
      "value": 0,
      "clicks": 64,
      "impressions": 1390,
      "costPerConversion": 60.8,
      "ctr": 4.6
    }
  }
}

Proposals

Changes Taseli prepared, ran, watched or undid. The owner approves them in Taseli; approvalUrl is the link. Taseli keeps the latest 200 here.

List proposals by state

GET/proposals

QueryType
statuswaiting active done allwaiting: awaiting approval, most valuable first. active: approved, executing or monitoring. done: kept, rolled_back, rejected, expired or failed. all. The last three are newest first. Default waiting.
accountstringAn account's id, name or platform id.
limitintegerHow many, from 1 to 100. Default 20.
cursorstringnextCursor from the previous page.
languagehe ar enLanguage of titles and texts. Default he.
ReturnsType
idstring
numberintegerThe # the owner sees.
statusawaiting_approval approved executing monitoring kept rolled_back rejected expired failed
kindstringWhat it changes, for example budget_change, negative_keywords_add, entity_pause, bid_target_change, campaign_create.
sourcestringWho prepared it: audit, anomaly, rule, playbook, agent (Taseli's chat), mcp (an outside AI) or user.
accountstringThe account's name.
campaignstring or null
titlestring
whystring
monthlyValuenumberWhat Taseli expects it to be worth a month, in the account's currency.
risklow medium high
confidencehigh medium low
changesobject[]
changes[].whatstringThe campaign, keyword or ad.
changes[].fieldstring
changes[].beforestring
changes[].afterstring
createdAtstring
decidedAtstring or null
decidedViastring or null
executedAtstring or null
watchobject or null
watch.dayintegerDay of the watch.
watch.daysintegerLength of the watch.
rolledBackAtstring or null
approvalUrlstringWhere the owner approves it, in Taseli.
totalintegerHow many in the whole list.
nextCursorstring or null
curl "https://taseli.co.il/api/v1/proposals?status=waiting&language=en" \
  -H "Authorization: Bearer $TASELI_KEY"
Response 200
{
  "data": [
    {
      "id": "0b6f3c1e-7a42-4c55-9b1d-2f6e8a1c4d90",
      "number": 214,
      "status": "awaiting_approval",
      "kind": "negative_keywords_add",
      "source": "audit",
      "account": "Dan Plumbing Search",
      "campaign": "Emergency plumber",
      "title": "Block 12 searches that spend without leads",
      "why": "They took ₪640 in 28 days with no lead.",
      "monthlyValue": 680,
      "risk": "low",
      "confidence": "high",
      "changes": [
        {
          "what": "Emergency plumber",
          "field": "Blocked searches",
          "before": "48",
          "after": "60"
        }
      ],
      "createdAt": "2026-10-20T08:12:00.000Z",
      "decidedAt": null,
      "decidedVia": null,
      "executedAt": null,
      "watch": null,
      "rolledBackAt": null,
      "approvalUrl": "https://taseli.co.il/en/app/dan-plumbing/proposals/0b6f3c1e-7a42-4c55-9b1d-2f6e8a1c4d90"
    }
  ],
  "total": 1,
  "nextCursor": null
}

One proposal in full

GET/proposals/{id}

Up to 50 changes; the list shows 5 per proposal. Among the workspace's latest 200.

PathType
idstringThe proposal's id. Required.
QueryType
languagehe ar enLanguage of titles and texts. Default he.
ReturnsType
idstring
numberintegerThe # the owner sees.
statusawaiting_approval approved executing monitoring kept rolled_back rejected expired failed
kindstringWhat it changes, for example budget_change, negative_keywords_add, entity_pause, bid_target_change, campaign_create.
sourcestringWho prepared it: audit, anomaly, rule, playbook, agent (Taseli's chat), mcp (an outside AI) or user.
accountstringThe account's name.
campaignstring or null
titlestring
whystring
monthlyValuenumberWhat Taseli expects it to be worth a month, in the account's currency.
risklow medium high
confidencehigh medium low
changesobject[]
changes[].whatstringThe campaign, keyword or ad.
changes[].fieldstring
changes[].beforestring
changes[].afterstring
createdAtstring
decidedAtstring or null
decidedViastring or null
executedAtstring or null
watchobject or null
watch.dayintegerDay of the watch.
watch.daysintegerLength of the watch.
rolledBackAtstring or null
approvalUrlstringWhere the owner approves it, in Taseli.
curl "https://taseli.co.il/api/v1/proposals/$PROPOSAL_ID?language=en" \
  -H "Authorization: Bearer $TASELI_KEY"
Response 200
{
  "data": {
    "id": "0b6f3c1e-7a42-4c55-9b1d-2f6e8a1c4d90",
    "number": 214,
    "status": "awaiting_approval",
    "kind": "negative_keywords_add",
    "source": "audit",
    "account": "Dan Plumbing Search",
    "campaign": "Emergency plumber",
    "title": "Block 12 searches that spend without leads",
    "why": "They took ₪640 in 28 days with no lead.",
    "monthlyValue": 680,
    "risk": "low",
    "confidence": "high",
    "changes": [
      {
        "what": "Emergency plumber",
        "field": "Blocked searches",
        "before": "48",
        "after": "60"
      }
    ],
    "createdAt": "2026-10-20T08:12:00.000Z",
    "decidedAt": null,
    "decidedVia": null,
    "executedAt": null,
    "watch": null,
    "rolledBackAt": null,
    "approvalUrl": "https://taseli.co.il/en/app/dan-plumbing/proposals/0b6f3c1e-7a42-4c55-9b1d-2f6e8a1c4d90"
  }
}

Activity

The latest 200 things that happened in the accounts.

What happened in the accounts, newest first

GET/activity

QueryType
limitintegerHow many, from 1 to 100. Default 50.
cursorstringnextCursor from the previous page.
languagehe ar enLanguage of titles and texts. Default he.
ReturnsType
idstring
atstring
accountstringThe account's name.
actortaseli user external google
kindexecuted kept rolled_back approved rejected external_change sync alert access_changed
textstring
detailstring or null
entitystring or null
viastring or null
proposalIdstring or null
totalintegerHow many in the whole list.
nextCursorstring or null
curl "https://taseli.co.il/api/v1/activity?limit=20&language=en" \
  -H "Authorization: Bearer $TASELI_KEY"
Response 200
{
  "data": [
    {
      "id": "a-48213",
      "at": "2026-10-20T08:12:00.000Z",
      "account": "Dan Plumbing Search",
      "actor": "taseli",
      "kind": "executed",
      "text": "Blocked 12 searches.",
      "detail": null,
      "entity": "Emergency plumber",
      "via": null,
      "proposalId": null
    }
  ],
  "total": 1,
  "nextCursor": null
}

Creatives

Each picture and video with its own last-30-day results.

Pictures and videos with their results and verdict

GET/creatives

Highest spend first, from the 300 highest. No cursor: shown and of say how much of the list came back. An account filter leaves out creatives that belong to no account (uploads, generated pictures). With nothing to show, the answer is only a note.

QueryType
accountstringAn account's id, name or platform id.
verdictgood ok weak untested unused newOnly this verdict.
kindimage videoOnly pictures or videos.
limitintegerHow many, from 1 to 100. Default 15.
languagehe ar enLanguage of titles and texts. Default he.
ReturnsType
windowstringOptional.
verdictsobjectHow many of each verdict. Optional.
notestringA caveat on the numbers, or the only field when there is nothing to show.
shownintegerOptional.
ofintegerOptional.
creativesobject[]Optional.
creatives[].idstring
creatives[].titlestring
creatives[].kindimage video
creatives[].showsstringWhat's in it. Optional.
creatives[].secondsintegerA video's length. Optional.
creatives[].accountstringThe account's name, or the source of a creative with no account. Optional.
creatives[].verdictgood ok weak untested unused newAmong the account's own creatives. Optional.
creatives[].whystringWhy it's weak. Optional.
creatives[].livebooleanSeen in the last 3 days.
creatives[].runsOnstring[]The placements it runs on. Optional.
creatives[].spendstringFormatted with its currency. Optional.
creatives[].resultsnumberOptional.
creatives[].impressionsnumberOptional.
creatives[].ctrnumberPercent. Optional.
creatives[].perResultstringFormatted with its currency. Optional.
creatives[].offerstringWhether it matches the current offer. Optional.
creatives[].offerWhystringOptional.
creatives[].watchedobjectFor videos: the hook, the offer, voice, music, on-screen words and the start of the transcript. Optional.
curl "https://taseli.co.il/api/v1/creatives?verdict=weak&limit=50&language=en" \
  -H "Authorization: Bearer $TASELI_KEY"
Response 200
{
  "data": {
    "window": "last 30 days",
    "verdicts": {
      "good": 2,
      "weak": 1
    },
    "note": "Per-creative results on Meta are a lower bound; spend, impressions and clicks are exact.",
    "shown": 1,
    "of": 3,
    "creatives": [
      {
        "id": "0b6f3c1e-7a42-4c55-9b1d-2f6e8a1c4d90",
        "title": "Plumber at the door, 24/7",
        "kind": "image",
        "account": "Dan Plumbing Meta",
        "verdict": "good",
        "live": true,
        "spend": "₪412.00",
        "results": 9,
        "impressions": 15210,
        "ctr": 1.8,
        "perResult": "₪45.78"
      }
    ]
  }
}

Competitors

Where the feature is on for the business. Otherwise 404 not_enabled.

Competitors Taseli watches

GET/competitors

QueryType
languagehe ar enLanguage of titles and texts. Default he.
ReturnsType
statusnew discovering suggested collecting ready pausedThe feature's state for this business.
followingstringOptional.
headlinestringThe week in one line. Optional.
analyzedstringLast read, YYYY-MM-DD. Optional.
nextCheckstringNext weekly check, YYYY-MM-DD. Optional.
checkNowstringWhether a manual check is available. Optional.
competitorsobject[]Optional.
competitors[].idstring
competitors[].namestring
competitors[].platformsstring[]Optional.
competitors[].liveAdsinteger
competitors[].newThisWeekintegerOptional.
competitors[].stoppedThisWeekintegerOptional.
competitors[].longestDaysintegerIts longest-running ad, in days. Optional.
competitors[].summarystringWhat it runs, in one line. Optional.
competitors[].checkedstringYYYY-MM-DD. Optional.
competitors[].fetchstringSet when the last check failed or is still collecting. Optional.
competitors[].urlstringThe competitor in Taseli. Optional.
suggestedobject[]Competitors Taseli found and suggests. Optional.
suggested[].idstring
suggested[].namestring
suggested[].whystringOptional.
suggested[].scorenumberOptional.
suggested[].platformsstring[]Optional.
suggested[].liveAdsintegerOptional.
notestringWhen none is watched yet. Optional.
urlstringThe competitors page in Taseli. Optional.
curl https://taseli.co.il/api/v1/competitors \
  -H "Authorization: Bearer $TASELI_KEY"
Response 200
{
  "data": {
    "status": "ready",
    "following": "2 of 3",
    "competitors": [
      {
        "id": "0b6f3c1e-7a42-4c55-9b1d-2f6e8a1c4d90",
        "name": "Rami Plumbing",
        "liveAds": 14,
        "longestDays": 96
      }
    ],
    "suggested": [
      {
        "id": "0b6f3c1e-7a42-4c55-9b1d-2f6e8a1c4d90",
        "name": ""
      }
    ]
  }
}

Competitors' ads from Taseli's archive

GET/competitors/ads

Longest running first. No cursor: shown and of say how much of the list came back. Ad texts are third-party content. likely is inferred from how long an ad ran; nobody sees a competitor's results. With no ads to show, the answer is only a note.

QueryType
competitorstringA competitor's id or name.
platformmeta googleMeta or Google only.
statusactive stopped allRunning now, stopped, or both. Default active.
labelnew running long likely stoppednew: under 7 days. long: 30 days or more. likely: probably working.
min_daysintegerRunning at least this many days.
limitintegerHow many, from 1 to 30. Default 30.
languagehe ar enLanguage of titles and texts. Default he.
ReturnsType
dataNotestringHow to read the data. Optional.
shownintegerOptional.
ofintegerOptional.
adsobject[]Optional.
ads[].idstring
ads[].competitorstringOptional.
ads[].platformmeta google
ads[].formatstringimage, video, carousel, text or dynamic. Optional.
ads[].statusstringOptional.
ads[].daysintegerDays running. Optional.
ads[].labelnew running long likely stopped
ads[].likelyWhystring[]Why it counts as likely working. Optional.
ads[].adTextobject
ads[].adText.bodystring
ads[].adText.headlinestring
ads[].adText.descriptionstringOptional.
ads[].ctastringOptional.
ads[].landingstringThe landing domain. Optional.
ads[].placementsstring[]Optional.
ads[].startedOnstringYYYY-MM-DD. Optional.
ads[].firstSeenstringYYYY-MM-DD. Optional.
ads[].stoppedOnstringYYYY-MM-DD. Optional.
ads[].factsobjectWhat Taseli read from the ad: offer, price, discount, hook, angles. Optional.
ads[].thumbstringA thumbnail link, valid for about an hour. Optional.
ads[].sourcestringThe public ad library's link. Optional.
ads[].urlstringThe ad in Taseli. Optional.
notestringWhen there are no ads to show. Optional.
curl "https://taseli.co.il/api/v1/competitors/ads?label=likely&language=en" \
  -H "Authorization: Bearer $TASELI_KEY"
Response 200
{
  "data": {
    "shown": 1,
    "of": 14,
    "ads": [
      {
        "id": "0b6f3c1e-7a42-4c55-9b1d-2f6e8a1c4d90",
        "competitor": "Rami Plumbing",
        "platform": "meta",
        "format": "image",
        "status": "active",
        "days": 96,
        "label": "likely",
        "adText": {
          "body": "A plumber at your door in 30 minutes.",
          "headline": "24/7 plumber"
        },
        "landing": "rami-plumbing.example"
      }
    ]
  }
}

Webhooks

Owners and admins only, with a personal key that isn't read-only (a connected app's token can't manage webhooks).

List webhooks

GET/webhooks

ReturnsType
idstring
urlstring
eventsstring[]
languagehe ar en
activebooleanFalse: it sends nothing. See pausedReason.
pausedReasonkey member or null
failuresintegerFailed attempts in a row. At 25 it switches off.
lastStatusinteger or null
lastErrorstring or null
lastDeliveryAtstring or null
createdAtstring
curl https://taseli.co.il/api/v1/webhooks \
  -H "Authorization: Bearer $TASELI_KEY"
Response 200
{
  "data": [
    {
      "id": "0b6f3c1e-7a42-4c55-9b1d-2f6e8a1c4d90",
      "url": "https://crm.example.com/hooks/taseli",
      "events": [
        ""
      ],
      "language": "en",
      "active": true,
      "pausedReason": null,
      "failures": 0,
      "lastStatus": 200,
      "lastError": null,
      "lastDeliveryAt": null,
      "createdAt": "2026-10-20T08:12:00.000Z"
    }
  ]
}

Create a webhook

POST/webhooks

Up to 5 per workspace. The response carries the signing secret once; it isn't shown again (delete and recreate to replace it). Not idempotent: after a timeout, list webhooks before retrying. Deliveries are signed with HMAC-SHA256; reject signatures older than 300 seconds. See /developers/webhooks.

BodyType
urlstringA public https address on the default port.
eventsproposal.created change.applied change.undone verdict.recorded[]Default: all of them. Optional.
languagehe ar enLanguage of titles and texts in the events. Optional.
ReturnsType
idstring
urlstring
eventsstring[]
languagehe ar en
activebooleanFalse: it sends nothing. See pausedReason.
pausedReasonkey member or null
failuresintegerFailed attempts in a row. At 25 it switches off.
lastStatusinteger or null
lastErrorstring or null
lastDeliveryAtstring or null
createdAtstring
secretstringShown once.
curl -X POST https://taseli.co.il/api/v1/webhooks \
  -H "Authorization: Bearer $TASELI_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://crm.example.com/hooks/taseli","language":"en"}'
Response 201
{
  "data": {
    "id": "0b6f3c1e-7a42-4c55-9b1d-2f6e8a1c4d90",
    "url": "https://crm.example.com/hooks/taseli",
    "events": [
      ""
    ],
    "language": "en",
    "active": true,
    "pausedReason": null,
    "failures": 0,
    "lastStatus": 200,
    "lastError": null,
    "lastDeliveryAt": null,
    "createdAt": "2026-10-20T08:12:00.000Z",
    "secret": "whsec_G7pQ0mYcVx2u4Tn8Zk1Rb6Ld3Ha9Ws5Je0Fy7Ci2Mo4"
  }
}

Delete a webhook

DELETE/webhooks/{id}

PathType
idstringThe webhook's id. Required.

Returns 204 with no body.

curl -X DELETE "https://taseli.co.il/api/v1/webhooks/$WEBHOOK_ID" \
  -H "Authorization: Bearer $TASELI_KEY"

Send one signed webhook.test now

POST/webhooks/{id}/test

Answers what the receiver answered. A test that lands switches back on a webhook that failures switched off. One paused for its key or its maker stays paused.

PathType
idstringThe webhook's id. Required.
ReturnsType
deliveredbooleanA 2xx came back.
statusintegerThe receiver's status. 0: none.
errorstring or null
curl -X POST "https://taseli.co.il/api/v1/webhooks/$WEBHOOK_ID/test" \
  -H "Authorization: Bearer $TASELI_KEY"
Response 200
{
  "data": {
    "delivered": true,
    "status": 200,
    "error": null
  }
}