# Organization API: Organizations & Members: Ads

> The 10 Organization API operations for ads.

Source: https://www.coritan.com/docs/api/reference/organizations/organizations-members/ads/

Part of [Organizations & Members](/docs/api/reference/organizations/organizations-members/).

## Operations

| Method | Path | Summary |
| --- | --- | --- |
| GET | [`/api/v1/orgs/{org_slug}/ads`](#op-get-api-v1-orgs-org-slug-ads) | Get ads |
| DELETE | [`/api/v1/orgs/{org_slug}/ads/connections/{connection_id}`](#op-delete-api-v1-orgs-org-slug-ads-connections-connection-id) | Disconnect one ad account |
| POST | [`/api/v1/orgs/{org_slug}/ads/connections/{connection_id}/sync`](#op-post-api-v1-orgs-org-slug-ads-connections-connection-id-sync) | Read one ad account now |
| GET | [`/api/v1/orgs/{org_slug}/ads/return`](#op-get-api-v1-orgs-org-slug-ads-return) | Get ad return |
| GET | [`/api/v1/orgs/{org_slug}/ads/spend`](#op-get-api-v1-orgs-org-slug-ads-spend) | What was spent, grouped by platform, campaign or day |
| GET | [`/api/v1/orgs/{org_slug}/ads/spend/manual`](#op-get-api-v1-orgs-org-slug-ads-spend-manual) | Spend entered by hand, newest first |
| POST | [`/api/v1/orgs/{org_slug}/ads/spend/manual`](#op-post-api-v1-orgs-org-slug-ads-spend-manual) | Enter spend for a channel that has no connection |
| DELETE | [`/api/v1/orgs/{org_slug}/ads/spend/manual/{entry_id}`](#op-delete-api-v1-orgs-org-slug-ads-spend-manual-entry-id) | Remove an entry of spend entered by hand |
| POST | [`/api/v1/orgs/{org_slug}/ads/{platform}/accounts`](#op-post-api-v1-orgs-org-slug-ads-platform-accounts) | Pick which of the platform's accounts to read |
| POST | [`/api/v1/orgs/{org_slug}/ads/{platform}/connect`](#op-post-api-v1-orgs-org-slug-ads-platform-connect) | Start signing in to an ad platform |

### Get ads {#op-get-api-v1-orgs-org-slug-ads}

`GET /api/v1/orgs/{org_slug}/ads`

Every ad platform with its status, every connected ad account, and the last 30 days of spend.

Needs the Admin or Owner role. ``platforms`` lists Google Ads, Meta Ads, TikTok Ads, Microsoft Ads and Reddit
Ads. A platform's ``status`` is `not_configured` (Coritan has not added its app credentials, so it cannot be
connected), `not_connected`, `pending` (signed in, no account picked yet), `connected`, `failing` (an
account has had errors and no successful read for an hour) or `reauth` (the sign-in ended, so connect
again). ``connections`` has one entry for each ad account the sign-in found, with the same status words
(an account that is found but not picked reads `pending`), when it was last read, the last error, how far
its 13 month history has been read and its spend per currency. ``summary`` is the last 30 days of spend per
currency, with entered spend included. ``warning`` is set when a sign-in ends within 14 days. Nothing here
carries a token.

#### Parameters

| Name | In | Type | Required |
| --- | --- | --- | --- |
| `org_slug` | path | string | yes |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

### Disconnect one ad account {#op-delete-api-v1-orgs-org-slug-ads-connections-connection-id}

`DELETE /api/v1/orgs/{org_slug}/ads/connections/{connection_id}`

Disconnect one ad account.

Needs the Admin or Owner role. The account's saved sign-in is deleted and nothing is read from it again. The
spend already imported stays in your reports. Connect the platform again to read the account again.

#### Parameters

| Name | In | Type | Required |
| --- | --- | --- | --- |
| `connection_id` | path | integer | yes |
| `org_slug` | path | string | yes |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

### Read one ad account now {#op-post-api-v1-orgs-org-slug-ads-connections-connection-id-sync}

`POST /api/v1/orgs/{org_slug}/ads/connections/{connection_id}/sync`

Read one ad account now.

Needs the Admin or Owner role. With no body it reads today and the two days before. With ``from`` and ``to``
it reads those days again (at most 400, none before 13 months ago), which is how to refresh a month after the
platform adjusts its numbers. The read runs in the background: check ``last_sync_at`` on the account.
Answers 409 when the account's sign-in has ended or the account is not picked, and 429 after 4 requests an
hour for one account.

#### Parameters

| Name | In | Type | Required |
| --- | --- | --- | --- |
| `connection_id` | path | integer | yes |
| `org_slug` | path | string | yes |

#### Request body

`application/json`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `from` | string (date) or null | no | The first day to read again. Send it with `to`, or send neither. |
| `to` | string (date) or null | no | The last day to read again. |

#### Responses

| Status | Meaning |
| --- | --- |
| `202` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

### Get ad return {#op-get-api-v1-orgs-org-slug-ads-return}

`GET /api/v1/orgs/{org_slug}/ads/return`

What the ad spend returned: orders, new customers, revenue, CAC and ROAS per platform, and per campaign.

Needs the Admin or Owner role. An order counts for the platform its last touch came from, when its invoice is
paid and it is not free: the touch's source and medium name the platform, and when they do not, its click ids
do. Within a platform an order counts for the campaign whose name (or id) equals its `utm_campaign`, ignoring
case. ``new_customers`` counts customers whose first paid order it was. ``roas`` is revenue without tax over
spend, ``cac_minor`` is spend over new customers, and ``platform_roas`` is the value the platform reports over
spend. Each is empty when its divisor is zero. Rows are per currency: spend and revenue meet only when they
are in the same currency, so an ad account billed in one currency and customers paying in another show as
separate rows with no CAC or ROAS. Payback is not computed, because it needs a gross margin that is not kept.
``truncated`` is true when more than 50,000 orders were in the range.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `org_slug` | path | string | yes |  |
| `from` | query | string (date) or null | no | The first day, as YYYY-MM-DD. The default is 30 days before `to`. |
| `to` | query | string (date) or null | no | The last day, as YYYY-MM-DD, included. The default is today in the organization's time zone. |
| `group` | query | string | no | `platform` or `campaign`. Default: `platform`. |
| `currency` | query | string or null | no | Only this currency. |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

### What was spent, grouped by platform, campaign or day {#op-get-api-v1-orgs-org-slug-ads-spend}

`GET /api/v1/orgs/{org_slug}/ads/spend`

What was spent, grouped by platform, campaign or day.

Needs the Admin or Owner role. Every row is in one currency, and a platform that spent in two currencies has
two rows: amounts in different currencies are never added. ``totals`` is the whole range per currency, even
when ``limit`` (rows for each currency, by campaign) cuts the rows. Spend entered by hand is included, spread evenly over its days. The range is at
most 400 days. Days follow each ad account's own time zone (Microsoft Ads and Reddit Ads follow the
organization's), so a day's spend can differ a little from the platform's own report in another zone.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `org_slug` | path | string | yes |  |
| `from` | query | string (date) or null | no | The first day, as YYYY-MM-DD. The default is 30 days before `to`. |
| `to` | query | string (date) or null | no | The last day, as YYYY-MM-DD, included. The default is today in the organization's time zone. |
| `group` | query | string | no | `platform`, `campaign` or `day`. Default: `platform`. |
| `currency` | query | string or null | no | Only this currency. |
| `limit` | query | integer | no | Rows to return for each currency when grouping by campaign. Default: `100`. |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

### Spend entered by hand, newest first {#op-get-api-v1-orgs-org-slug-ads-spend-manual}

`GET /api/v1/orgs/{org_slug}/ads/spend/manual`

Spend entered by hand, newest first.

Needs the Admin or Owner role. ``ignored`` is true for an entry whose channel has since been connected, which
reports leave out because the platform's own numbers cover it.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `org_slug` | path | string | yes |  |
| `limit` | query | integer | no | Entries to return, newest first. Default: `100`. |
| `offset` | query | integer | no | Entries to skip. Default: `0`. |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

### Enter spend for a channel that has no connection {#op-post-api-v1-orgs-org-slug-ads-spend-manual}

`POST /api/v1/orgs/{org_slug}/ads/spend/manual`

Enter spend for a channel that has no connection.

Needs the Admin or Owner role. ``amount_minor`` is the whole amount over ``starts_on`` to ``ends_on`` (at most
400 days), and reports spread it evenly over those days. A platform with a picked account, or one that was already
read for some of these days, is refused with 409 because its own numbers cover it. Answers 422 for a
channel, currency, amount or dates that do not fit.

#### Parameters

| Name | In | Type | Required |
| --- | --- | --- | --- |
| `org_slug` | path | string | yes |

#### Request body

`application/json` (required)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `channel` | string | yes | Where the money was spent: a platform key or another network such as x, linkedin, snapchat, pinterest or other. |
| `label` | string | yes | What the spend was for, in your words. |
| `currency` | string | yes | The three letter code of the currency it was paid in. |
| `amount_minor` | integer | yes | The whole amount over the days, in the currency's smallest unit (cents for USD). |
| `starts_on` | string (date) | yes | The first day the spend covers. |
| `ends_on` | string (date) | yes | The last day the spend covers. |

#### Responses

| Status | Meaning |
| --- | --- |
| `201` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

### Remove an entry of spend entered by hand {#op-delete-api-v1-orgs-org-slug-ads-spend-manual-entry-id}

`DELETE /api/v1/orgs/{org_slug}/ads/spend/manual/{entry_id}`

Remove an entry of spend entered by hand. Needs the Admin or Owner role.

#### Parameters

| Name | In | Type | Required |
| --- | --- | --- | --- |
| `entry_id` | path | integer | yes |
| `org_slug` | path | string | yes |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

### Pick which of the platform's accounts to read {#op-post-api-v1-orgs-org-slug-ads-platform-accounts}

`POST /api/v1/orgs/{org_slug}/ads/{platform}/accounts`

Pick which of the platform's accounts to read.

Needs the Admin or Owner role. ``account_ids`` is the whole list: accounts you name start being read (their
13 month history first), and accounts of this platform you leave out stop being read but keep the spend
already imported. At most 50 accounts for one platform. Answers 422 for an account that is not on the
sign-in. Pick only the accounts that belong to this organization: a sign-in to a manager account can list
accounts that are not yours.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `platform` | path | string | yes | One of google, meta, tiktok, microsoft, reddit. |
| `org_slug` | path | string | yes |  |

#### Request body

`application/json` (required)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `account_ids` | array of string | yes | The accounts to read, by the platform's own ids. Accounts of the platform that are not listed stop being read. |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |

### Start signing in to an ad platform {#op-post-api-v1-orgs-org-slug-ads-platform-connect}

`POST /api/v1/orgs/{org_slug}/ads/{platform}/connect`

Start signing in to an ad platform. Answers ``authorization_url``, the platform's own page.

Needs the Admin or Owner role. Send the person to ``authorization_url``. The platform sends the browser back
to Coritan, which finds the accounts the sign-in can read and returns the person to ``return_path`` (a page of
the console on the host of this request) with `ads=connected` or `ads=error` in the address. The link is good
for 15 minutes. Answers 409 `not_configured` when the platform's app credentials have not been added to
Coritan, and 422 when the request does not come from one of your console's hosts.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `platform` | path | string | yes | One of google, meta, tiktok, microsoft, reddit. |
| `org_slug` | path | string | yes |  |

#### Request body

`application/json`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `return_path` | string or null | no | The page of the console to come back to when the sign-in is done, such as /staff/marketing/ads. It is a path on the host the request came from. |

#### Responses

| Status | Meaning |
| --- | --- |
| `200` | Success. |
| `422` | The request is not valid. `detail` lists each problem. |
