Skip to main content

Advertiser & Invoicing Companies, Brands, and User Mapping

Advertiser & Invoicing Companies, Brands, and User Mapping

This guide explains how to create advertiser companiesinvoicing companies, and brands in Adhese through the Campaign API, and how to connect (map) users to those companies and brands.

All endpoints live under the Adhese API and are versioned with a /v1 prefix. The server base path is /api, so a full path looks like /api/v1/media-partners and /v1/user-mapping.

Key concepts & terminology

In Adhese, an advertiser company and an invoicing company are the same underlying entity — a media partner — distinguished by the roles assigned to it. A single media partner can hold one or more roles at the same time.

You want to create…What it is in the APIHow
An advertiser companyA media partner with the ADVERTISER rolePOST /v1/media-partners with "roles": ["ADVERTISER"]
An invoicing companyA media partner with the INVOICE rolePOST /v1/media-partners with "roles": ["INVOICE"]
A company that is bothA media partner with both rolesPOST /v1/media-partners with "roles": ["ADVERTISER", "INVOICE"]
brandmedia brand that belongs to a media partnerPOST /v1/media-partners/{mediaPartnerId}/brands
user ↔ company/brand linkuser mappingPOST /v1/user-mapping

Available roles: ADVERTISERINVOICEINTERMEDIARYMEDIA.

Note. The read-only endpoints GET /v1/advertiser-companies and GET /v1/brands expose the same entities from the campaign-booking perspective (used when creating or editing a campaign). Their id values are the media-partner and media-brand ids you create below.


Authentication & headers

Every request is authenticated with a Bearer JWT and must carry the Keycloak auth header.

HeaderRequiredValueNotes
AuthorizationYesBearer <jwt>JWT access token.
Use-Keycloak-AuthYestrueRequired on all /v1 endpoints.
Content-TypeFor POST/DELETE with a bodyapplication/json
api-versionOptionale.g. v1Accepted on /v1/advertiser-companies and /v1/brands.

Example request line and headers:

POST /api/v1/media-partners
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
Use-Keycloak-Auth: true
Content-Type: application/json

Data model

  • media partner is a company. Its roles decide whether it can be used as an advertiser company, an invoicing company, or both.
  • media brand always belongs to exactly one media partner.
  • user mapping connects a user identifier to a specific advertiserCompanyId and brandId (both required), optionally scoped to an invoiceCompanyId.

Create advertiser & invoicing companies

Both are created with the same endpoint; the roles array is what makes a company an advertiser, an invoicing party, or both.

Create a company

POST /v1/media-partners

Creates a media partner (advertiser company, invoicing company, or both, depending on roles).

Request body — CreateMediaPartnerRequest

FieldTypeRequiredDescription
namestringYesDisplay name of the company.
rolesarray of enumYesAny of ADVERTISERINVOICEINTERMEDIARYMEDIA.
externalKeystringNoYour own external reference key.
subsystemExternalIdsobject (string → string)NoExternal ids per subsystem.

Create an advertiser company

{
  "name": "Acme Beverages",
  "roles": ["ADVERTISER"],
  "externalKey": "acme-bev",
  "subsystemExternalIds": {
    "crm": "CRM-10432"
  }
}

Create an invoicing company

{
  "name": "Acme Beverages Billing BV",
  "roles": ["INVOICE"],
  "externalKey": "acme-bev-billing"
}

Create a company that is both advertiser and invoicing party

{
  "name": "Acme Beverages",
  "roles": ["ADVERTISER", "INVOICE"]
}

Responses

StatusMeaning
201Media partner created.
400Invalid input (e.g. empty name or unknown role).
401 / 403Not authenticated / not allowed.
500Unexpected failure.

The 201 response does not return a body. To obtain the generated id, call the list endpoint below and filter by search or externalKey.

List companies

GET /v1/media-partners?limit=50&offset=0
ParameterInRequiredTypeDescription
limitqueryYesintegerMax number of results to return.
offsetqueryYesintegerNumber of results to skip.
searchqueryNostringURL-encoded, case-insensitive match on name.
rolesqueryNoarrayFilter on the role(s) the media partner has, e.g. roles=ADVERTISER.
includeInactivequeryNobooleanInclude deactivated media partners.

Response — array of MediaPartnerDto

[
  {
    "id": 4021,
    "name": "Acme Beverages",
    "roles": ["ADVERTISER"],
    "externalKey": "acme-bev",
    "subsystemExternalIds": { "crm": "CRM-10432" },
    "active": true
  }
]

Get a single company

GET /v1/media-partners/{mediaPartnerId}
ParameterInRequiredTypeDescription
mediaPartnerIdpathYesintegerThe id of the media partner.

Returns a single MediaPartnerDto (same shape as above).


Create brands

A brand is a media brand that belongs to a media partner (typically the advertiser company).

Create a brand

POST /v1/media-partners/{mediaPartnerId}/brands
ParameterInRequiredTypeDescription
mediaPartnerIdpathYesintegerThe media partner (company) the brand belongs to.

Request body — CreateMediaBrandRequest

FieldTypeRequiredDescription
namestringYesBrand name.
externalKeystringNoYour own external reference key.
subsystemExternalIdsobject (string → string)NoExternal ids per subsystem.
{
  "name": "Acme Cola",
  "externalKey": "acme-cola",
  "subsystemExternalIds": {}
}

Responses

StatusMeaning
201Media brand created.
400Invalid input.
401 / 403Not authenticated / not allowed.
404Media partner not found.

As with companies, 201 has no body — retrieve the generated brand id via the list endpoint below.

List a company's brands

GET /v1/media-partners/{mediaPartnerId}/brands?limit=50&offset=0
ParameterInRequiredTypeDescription
mediaPartnerIdpathYesintegerThe media partner.
limitqueryYesintegerMax number of results.
offsetqueryYesintegerResults to skip.
includeInactivequeryNobooleanInclude deactivated brands.
searchqueryNostringURL-encoded, case-insensitive match on name.

Response — array of MediaBrandDto

[
  {
    "id": 8801,
    "name": "Acme Cola",
    "externalKey": "acme-cola",
    "subsystemExternalIds": {},
    "active": true
  }
]

Get a single brand

GET /v1/media-partners/{mediaPartnerId}/brands/{mediaBrandId}

Returns a single MediaBrandDto.


Read companies & brands (campaign views)

These read-only endpoints return the same entities as they appear when creating or editing a campaign. Use them to resolve the ids you need for user mapping.

List advertiser / invoicing companies

GET /v1/advertiser-companies?type=ADVERTISER
ParameterInRequiredTypeDescription
typequeryYesenumADVERTISER or INVOICE.
advertiserCompanyIdqueryNointegerFilter to a single company id.
api-versionheaderNostringOptional API version.

Response — array of AdvertiserCompanyDto

[
  {
    "id": 4021,
    "name": "Acme Beverages",
    "active": true,
    "externalId": "acme-bev",
    "subsystemExternalIds": {}
  }
]

Get a single advertiser company

GET /v1/advertiser-companies/{advertiserCompanyId}

Returns a single AdvertiserCompanyDto.

List brands (for campaign creation)

GET /v1/brands?advertiserCompanyId=4021&invoiceCompanyId=4022
ParameterInRequiredTypeDescription
advertiserCompanyIdqueryYesintegerAdvertiser company to filter on.
invoiceCompanyIdqueryYesintegerInvoice company to filter on.
api-versionheaderNostringOptional API version.

Response — array of BrandDto

[
  { "id": 8801, "name": "Acme Cola" }
]

Connect users (user mapping)

user mapping grants a user access to a company/brand combination. Each mapping entry (MappingDto) requires an advertiserCompanyId and a brandIdinvoiceCompanyId is optional.

Create a user mapping

POST /v1/user-mapping

Request body — CreateUserMappingRequest

FieldTypeRequiredDescription
userstring (1–255)YesUser identifier (e.g. email or username).
mappingsarray of MappingDtoYesAt least one mapping entry.

MappingDto

FieldTypeRequiredDescription
advertiserCompanyIdinteger (≥ 1)YesThe advertiser company to grant access to.
invoiceCompanyIdintegerNoRestrict the mapping to a specific invoicing company.
brandIdinteger (≥ 1)YesThe brand to grant access to.
{
  "user": "jane.doe@partner.example",
  "mappings": [
    {
      "advertiserCompanyId": 4021,
      "invoiceCompanyId": 4022,
      "brandId": 8801
    }
  ]
}

Responses

StatusMeaning
201User mapping created.
400Invalid input (e.g. missing advertiserCompanyId or brandId).
401 / 403Not authenticated / not allowed.

List users with mappings

GET /v1/user-mapping?limit=50&offset=0
ParameterInRequiredTypeDescription
limitqueryNointegerMax results (≤ 100).
offsetqueryNointegerResults to skip.
searchqueryNostringLoose match on user identifier.
advertiserCompanyIdqueryNointegerOnly users mapped to this advertiser company.
invoiceCompanyIdqueryNointegerOnly users mapped to this invoice company.
brandIdqueryNointegerOnly users mapped to this brand.

The response includes a Record-Count header with the total number of matches.

Response — array of UserMappingDto

[
  { "user": "jane.doe@partner.example", "mappingCount": 3 }
]

List a single user's mappings

GET /v1/user-mapping/{user}
ParameterInRequiredTypeDescription
userpathYesstringThe user identifier.
limit / offsetqueryNointegerPagination.
advertiserCompanyIdqueryNointegerFilter by advertiser company.
invoiceCompanyIdqueryNointegerFilter by invoice company.
brandIdqueryNointegerFilter by brand.

Response — array of MappingDto

[
  {
    "advertiserCompanyId": 4021,
    "invoiceCompanyId": 4022,
    "brandId": 8801
  }
]

Delete a user mapping

DELETE /v1/user-mapping

Request body — DeleteUserMappingRequest

FieldTypeRequiredDescription
userstring (1–255)YesThe user identifier.
advertiserCompanyIdinteger (≥ 1)Advertiser company of the mapping to remove.
invoiceCompanyIdintegerInvoice company of the mapping to remove.
brandIdinteger (≥ 1)Brand of the mapping to remove.
{
  "user": "jane.doe@partner.example",
  "advertiserCompanyId": 4021,
  "invoiceCompanyId": 4022,
  "brandId": 8801
}

Responds 200 when the mapping is deleted.


End-to-end walkthrough

Create an advertiser company, an invoicing company, and a brand, then give a user access to them.

1. Create the advertiser company

POST /v1/media-partners

{
  "name": "Acme Beverages",
  "roles": ["ADVERTISER"],
  "externalKey": "acme-bev"
}

Look it up to get its id → assume 4021.

2. Create the invoicing company

POST /v1/media-partners

{
  "name": "Acme Beverages Billing BV",
  "roles": ["INVOICE"],
  "externalKey": "acme-bev-billing"
}

Look it up to get its id → assume 4022.

3. Create a brand under the advertiser company

POST /v1/media-partners/4021/brands

{
  "name": "Acme Cola",
  "externalKey": "acme-cola"
}

Look it up to get its id → assume 8801.

4. Map the user to the company + brand

POST /v1/user-mapping

{
  "user": "jane.doe@partner.example",
  "mappings": [
    { "advertiserCompanyId": 4021, "invoiceCompanyId": 4022, "brandId": 8801 }
  ]
}

5. Verify the mapping

GET /v1/user-mapping/jane.doe@partner.example
[
  { "advertiserCompanyId": 4021, "invoiceCompanyId": 4022, "brandId": 8801 }
]

Error handling

Errors are returned as an RFC 7807 ProblemDetail object.

{
  "type": "about:blank",
  "title": "Bad Request",
  "status": 400,
  "detail": "roles must not be empty",
  "instance": "/api/v1/media-partners"
}
StatusMeaning
400Bad Request — invalid input or parameters.
401Unauthorized — authentication required or invalid token.
403Forbidden — authenticated but not allowed to access this resource.
404Not Found — resource not found.
422Unprocessable Entity — the request was understood but could not be processed.
500Internal Server Error — unexpected failure.

Schema reference

CreateMediaPartnerRequest · MediaPartnerDto

{
  "id": 4021,
  "name": "string",
  "roles": ["ADVERTISER", "INVOICE", "INTERMEDIARY", "MEDIA"],
  "externalKey": "string",
  "subsystemExternalIds": { "subsystem": "externalId" },
  "active": true
}

CreateMediaBrandRequest · MediaBrandDto

{
  "id": 8801,
  "name": "string",
  "externalKey": "string",
  "subsystemExternalIds": { "subsystem": "externalId" },
  "active": true
}

AdvertiserCompanyDto

{
  "id": 4021,
  "name": "string",
  "active": true,
  "externalId": "string",
  "subsystemExternalIds": { "subsystem": "externalId" }
}

BrandDto

{ "id": 8801, "name": "string" }

CreateUserMappingRequest

{
  "user": "string",
  "mappings": [
    { "advertiserCompanyId": 4021, "invoiceCompanyId": 4022, "brandId": 8801 }
  ]
}

UserMappingDto

{ "user": "string", "mappingCount": 3 }