Home

TrueLoyal Advocacy API

v2
Base URL
https://api.tintup.com

The reference for every endpoint of the TrueLoyal Advocacy API. Start with the guides for authentication, pagination, versioning and the JSON:API conventions the API follows.

Authentication

access_tokenoauth2

OAuth 2.0 authorization code flow.

authorizationCode
Authorization URL
https://id.tintup.com/oauth/authorize
Token URL
https://id.tintup.com/oauth/token
Scopes
  • accounts:read- Read access to accounts
  • accounts:write- Write access to accounts
  • activities:read- Read access to activities
  • assets:read- Read access to assets
  • assets:write- Write access to assets
  • authentication_factors:read- Read access to authentication factors
  • authentication_factors:write- Write access to authentication factors
  • campaigns:read- Read access to campaigns
  • campaigns:write- Write access to campaigns
  • collections:read- Read access to collections
  • collections:write- Write access to collections
  • ctas:read- Read access to CTAs
  • ctas:write- Write access to CTAs
  • domains:read- Read access to domains
  • domains:write- Write access to domains
  • ecommerce:read- Read access to e-commerce engagement metrics
  • experiences:read- Read access to experiences
  • experiences:write- Write access to experiences
  • fonts:read- Read access to fonts
  • fonts:write- Write access to fonts
  • form_submissions:read- Read access to form submissions
  • form_submissions:write- Write access to form submissions
  • forms:read- Read access to forms
  • forms:write- Write access to forms
  • identity- Read access to my user
  • identity:write- Write access to my user
  • instint_updates:read- Read access to InsTINT updates
  • instint_updates:write- Write access to InsTINT updates
  • marketing_integrations:read- Read access to marketing integrations
  • marketing_integrations:write- Write access to marketing integrations
  • marketing_integrations_requests:read- Read access to marketing integration publishing requests
  • marketing_integrations_requests:write- Publish access to marketing integrations
  • mixes:read- Read access to mixes
  • mixes:write- Write access to mixes
  • oauth_applications:read- Read access to OAuth 2.0 applications
  • oauth_applications:write- Write access to OAuth 2.0 applications
  • personalizations:read- Read access to personalizations
  • personalizations:write- Write access to personalizations
  • posts:read- Read access to posts
  • posts:write- Write access to posts
  • privacy_requests:read- Read access to privacy requests
  • privacy_requests:write- Write access to privacy requests
  • product_accounts:read- Read access to product accounts
  • product_accounts:write- Write access to product accounts
  • product_feeds:read- Read access to product feeds
  • product_feeds:write- Write access to product feeds
  • products:read- Read access to products
  • products:write- Write access to products
  • rewards:read- Read access to rewards
  • right_request_templates:read- Read access to right request templates
  • right_request_templates:write- Write access to right request templates
  • right_request_terms:read- Read access to right request terms
  • right_request_terms:write- Write access to right request terms
  • right_requests:read- Read access to right requests
  • right_requests:write- Write access to right requests
  • roles:read- Read access to roles
  • roles:write- Write access to roles
  • saved_filters:read- Read access to saved filters
  • saved_filters:write- Write access to saved filters
  • schemas:read- Read access to schemas
  • schemas:write- Write access to schemas
  • social_feeds:read- Read access to social feeds
  • social_feeds:write- Write access to social feeds
  • subaccount_metrics:read- Read access to account and subaccount metrics
  • teams:read- Read access to teams
  • teams:write- Write access to teams
  • tints:read- Read access to boards
  • tints:write- Write access to boards
  • transactions:read- Read access to transactions
  • transactions:write- Write access to transactions
  • users:read- Read access to team users
  • users:write- Write access to team users
  • webhooks:read- Read access to webhooks
  • webhooks:write- Write access to webhooks
id_tokenapiKey

A short-lived token required, in addition to an access token, to change sensitive data. See Changes to Sensitive Data.

API Key: id_token in query

OAuth

authentication

The OAuth 2.0 endpoints. How to create an OAuth application and get an access token is covered in the Authentication guide.

Authorize an application using the authorization code flow

GET
https://api.tintup.com/oauth/authorize

Redirect the user to this URL to request authorization. The user signs in (if needed) and approves the requested scopes, after which they are redirected to redirect_uri with a code query parameter (and the state you provided). The code expires after 5 minutes; exchange it for an access token with Create an access token. PKCE is required for public (non-confidential) applications and recommended for all: send a code_challenge here and the matching code_verifier when exchanging the code. Applications created with the API are confidential.

Parameters

scopeArray<string>accounts:readaccounts:writeactivities:readassets:readassets:writeauthentication_factors:readauthentication_factors:writecampaigns:readcampaigns:writecollections:readcollections:writectas:readctas:writedomains:readdomains:writeecommerce:readexperiences:readexperiences:writefonts:readfonts:writeform_submissions:readform_submissions:writeforms:readforms:writeidentityidentity:writeinstint_updates:readinstint_updates:writemarketing_integrations:readmarketing_integrations:writemarketing_integrations_requests:readmarketing_integrations_requests:writemixes:readmixes:writeoauth_applications:readoauth_applications:writepersonalizations:readpersonalizations:writeposts:readposts:writeprivacy_requests:readprivacy_requests:writeproduct_accounts:readproduct_accounts:writeproduct_feeds:readproduct_feeds:writeproducts:readproducts:writerewards:readright_request_templates:readright_request_templates:writeright_request_terms:readright_request_terms:writeright_requests:readright_requests:writeroles:readroles:writesaved_filters:readsaved_filters:writeschemas:readschemas:writesocial_feeds:readsocial_feeds:writesubaccount_metrics:readteams:readteams:writetints:readtints:writetransactions:readtransactions:writeusers:readusers:writewebhooks:readwebhooks:writeidentityquery

A space-delimited list of the scopes to request. Defaults to identity when omitted.

response_typestringcoderequiredquery

Must be code to request an authorization code.

client_idstringrequiredquery

The application's client_id.

redirect_uristring<uri>requiredquery

One of the redirect URIs registered for the application, matched exactly.

statestringquery

An opaque value that is returned unchanged to redirect_uri. Use it to prevent CSRF attacks.

code_challengestringquery

The PKCE code challenge derived from your code_verifier. Required for public (non-confidential) applications.

code_challenge_methodstringS256plainquery

How code_challenge was derived from the code_verifier. Required when code_challenge is sent. Use S256 (the Base64URL-encoded SHA-256 hash of the verifier); plain sends the verifier itself.

Response

200OKstring

The sign-in and consent page, rendered as HTML for the user.

302Found

The user approved the request and is redirected to redirect_uri with code and state query parameters (or error and error_description if the request was denied or invalid).

Authorize an application using the authorization code flow
curl -X GET 'https://api.tintup.com/oauth/authorize'
const response = await fetch('https://api.tintup.com/oauth/authorize', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/oauth/authorize')
data = response.json()
200
string

Create an access token

POST
https://api.tintup.com/oauth/token

Exchanges an authorization code for an access token (grant_type=authorization_code), or uses a refresh token to obtain a new access token (grant_type=refresh_token). Access tokens expire after one hour; use the refresh token to get a new one.

Body

application/x-www-form-urlencoded

The grant to exchange for an access token. Confidential applications authenticate with client_id and client_secret, either in the body or with HTTP Basic authentication (Authorization: Basic base64(client_id:client_secret)).

grant_typestringauthorization_coderefresh_tokenrequired

The kind of grant being exchanged.

client_idstring

The application's client_id. Required unless sent with HTTP Basic authentication.

client_secretstring

The application's client_secret. Required for confidential applications unless sent with HTTP Basic authentication.

codestring

The authorization code received on redirect_uri. Required when grant_type is authorization_code. Codes expire after 5 minutes and can only be used once.

code_verifierstring

The PKCE code verifier matching the code_challenge sent to the authorization endpoint. Required when grant_type is authorization_code and a code_challenge was sent.

redirect_uristring<uri>

The same redirect_uri that was sent to the authorization endpoint. Required when grant_type is authorization_code.

refresh_tokenstring

The refresh token returned with a previous access token. Required when grant_type is refresh_token. The response contains a new refresh token that replaces this one.

scopestring

A space-delimited list of scopes. With refresh_token, it can narrow down the originally granted scopes.

Response

200OKobject

The access token.

400Bad Requestobject

Bad Request. The request is invalid, for example the code is invalid, expired or already used, the PKCE verifier doesn't match, or a requested scope isn't allowed.

401Unauthorizedobject

Unauthorized. The client authentication failed (unknown client_id or wrong client_secret).

Create an access token
curl -X POST 'https://api.tintup.com/oauth/token' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d '{
    "grant_type": "authorization_code",
    "client_id": "3a7c1e0b9d8f4e6a2b5c7d9e1f3a5b7c",
    "client_secret": "9f8e7d6c5b4a39281706f5e4d3c2b1a0",
    "code": "1b7e4c9a2d5f8e0c3a6b9d2e5f8a1c4b",
    "code_verifier": "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk",
    "redirect_uri": "https://reports.example.com/auth/callback"
  }'
const response = await fetch('https://api.tintup.com/oauth/token', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
  },
  body: JSON.stringify({
      "grant_type": "authorization_code",
      "client_id": "3a7c1e0b9d8f4e6a2b5c7d9e1f3a5b7c",
      "client_secret": "9f8e7d6c5b4a39281706f5e4d3c2b1a0",
      "code": "1b7e4c9a2d5f8e0c3a6b9d2e5f8a1c4b",
      "code_verifier": "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk",
      "redirect_uri": "https://reports.example.com/auth/callback"
    }),
});

const data = await response.json();
import requests

payload = {
  "grant_type": "authorization_code",
  "client_id": "3a7c1e0b9d8f4e6a2b5c7d9e1f3a5b7c",
  "client_secret": "9f8e7d6c5b4a39281706f5e4d3c2b1a0",
  "code": "1b7e4c9a2d5f8e0c3a6b9d2e5f8a1c4b",
  "code_verifier": "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk",
  "redirect_uri": "https://reports.example.com/auth/callback"
}

response = requests.post('https://api.tintup.com/oauth/token', json=payload)
data = response.json()
Request Body
{
  "grant_type": "authorization_code",
  "client_id": "3a7c1e0b9d8f4e6a2b5c7d9e1f3a5b7c",
  "client_secret": "9f8e7d6c5b4a39281706f5e4d3c2b1a0",
  "code": "1b7e4c9a2d5f8e0c3a6b9d2e5f8a1c4b",
  "code_verifier": "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk",
  "redirect_uri": "https://reports.example.com/auth/callback"
}
{
  "access_token": "4e8a1c6f3b9d2e7a0c5f8b1d4e7a9c2f",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "7d2f9b4e1a6c8e3f0b5d7a9c2e4f6a8b",
  "scope": "tints:read posts:read",
  "created_at": 1741970527
}
{
  "error": "invalid_grant",
  "error_description": "The provided authorization grant is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client."
}
{
  "error": "invalid_client",
  "error_description": "Client authentication failed due to unknown client, no client authentication included, or unsupported authentication method."
}

Common

group_common
Common

Accounts

accounts

Retrieve a list of accounts

GET
https://api.tintup.com/v2/teams/{team_id}/accounts

Returns the accounts the user has access to.

Parameters

team_idintegerrequiredpath

The ID of the team.

includeArray<string>social_feedssubaccountsquery

A comma-separated list of related resources to include in the response.

filterobjectquery

Filters the list of accounts. All filters are combined with AND.

sortstring-idquery

A comma-separated list of attributes to sort by. Prefix an attribute with - to sort in descending order.

pageobjectquery

Offset pagination. Use page[size] to set the number of items per page and page[number] to select a page. The response's links object contains ready-to-use URLs for the next and previous pages.

Response

200OKobject

A list of accounts.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: accounts:read

Retrieve a list of accounts
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/accounts'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/accounts', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/accounts')
data = response.json()
{
  "data": [
    {
      "id": "4821",
      "type": "account",
      "attributes": {
        "external_id": "17841401839964064",
        "name": "Acme Inc.",
        "username": "acme",
        "image_url": "https://cdn.example.com/avatars/acme.jpg",
        "site": null,
        "expires_at": "2025-05-13T16:42:07.000Z",
        "capabilities": [
          "ingest",
          "compose"
        ],
        "meta": {},
        "followers_count": 12840,
        "follows_count": 312,
        "media_count": 587,
        "likes_count": null,
        "created_at": "2025-03-14T16:42:07.000Z",
        "updated_at": "2025-03-14T16:42:07.000Z"
      },
      "relationships": {
        "social_feeds": {
          "data": [
            {
              "id": "90211",
              "type": "social_feed"
            }
          ],
          "meta": {
            "count": 2
          }
        },
        "subaccounts": {
          "data": [
            {
              "id": "17841401839964064",
              "type": "subaccount"
            }
          ],
          "meta": {
            "included": false
          }
        }
      }
    }
  ],
  "links": {
    "self": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=2",
    "first": "https://api.tintup.com/v2/teams/1/tints",
    "next": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=3",
    "prev": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=1"
  }
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}

Create an account

POST
https://api.tintup.com/v2/teams/{team_id}/accounts

Connects an account that uses credentials (API keys, passwords, etc.) rather than OAuth, such as an SFTP product feed or a reCAPTCHA site key. The credentials are never returned. An account with the same type and external ID can only be connected once per team.

Body

application/vnd.api+json

The account to connect. Only account types that use credentials (API keys, passwords, etc.) can be created this way; OAuth-based accounts are connected with Authenticate an account.

dataNewAccountrequired

Connects an account using credentials instead of OAuth. Which attributes are required, or must be omitted, depends on type; see each attribute.

Show child attributes
typestringaccountrequired

The resource type.

attributesobjectrequired
Show child attributes
typeaccountTypesForCreatebazaarvoicebigcommercecreator_iqftphttpmagentopower_reviewsre_captchas3salesforce_commerce_cloudsftpwoocommercerequired

The type of account to connect with credentials. Other account types can only be connected using the OAuth flow (see Authenticate an account).

access_tokenstring | nullwrite only

The credential used to connect to the service. Required for every type except s3. For creator_iq and bazaarvoice this is the API key (it must be unique within the team); for salesforce_commerce_cloud it is client_id|client_secret|short_code|organization_id; for ftp, http, and sftp it is the username (stored as part of the URL).

secretstring | nullwrite only

The password or API secret. Required for bazaarvoice, woocommerce, ftp, and http; optional for sftp; must be omitted (or empty) for every other type.

external_idstring | nullwrite only

The ID of the account at the source. Required for power_reviews (merchant ID), re_captcha (site key), bigcommerce (store hash), and s3 (bucket name); must be omitted (or empty) for every other type.

sitestring | nullwrite only

Required for magento, woocommerce, ftp, http, sftp, and s3. For s3 it's an AWS region (e.g. us-east-1). Otherwise it's the server URL: ftp must start with ftp:// or ftps://, sftp with sftp://, and http, magento, and woocommerce with http:// or https://. Ignored for other types.

Parameters

team_idintegerrequiredpath

The ID of the team.

Response

201Createdobject

The account.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: accounts:write

Create an account
curl -X POST 'https://api.tintup.com/v2/teams/{team_id}/accounts' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "account",
      "attributes": {
        "type": "sftp",
        "access_token": "acme-feeds",
        "secret": "s3cr3t-Pa55word",
        "site": "sftp://files.example.com/feeds/products.csv"
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/accounts', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "account",
        "attributes": {
          "type": "sftp",
          "access_token": "acme-feeds",
          "secret": "s3cr3t-Pa55word",
          "site": "sftp://files.example.com/feeds/products.csv"
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "account",
    "attributes": {
      "type": "sftp",
      "access_token": "acme-feeds",
      "secret": "s3cr3t-Pa55word",
      "site": "sftp://files.example.com/feeds/products.csv"
    }
  }
}

response = requests.post('https://api.tintup.com/v2/teams/{team_id}/accounts', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "account",
    "attributes": {
      "type": "sftp",
      "access_token": "acme-feeds",
      "secret": "s3cr3t-Pa55word",
      "site": "sftp://files.example.com/feeds/products.csv"
    }
  }
}
{
  "data": {
    "id": "4821",
    "type": "account",
    "attributes": {
      "external_id": "17841401839964064",
      "name": "Acme Inc.",
      "username": "acme",
      "image_url": "https://cdn.example.com/avatars/acme.jpg",
      "site": null,
      "expires_at": "2025-05-13T16:42:07.000Z",
      "capabilities": [
        "ingest",
        "compose"
      ],
      "meta": {},
      "followers_count": 12840,
      "follows_count": 312,
      "media_count": 587,
      "likes_count": null,
      "created_at": "2025-03-14T16:42:07.000Z",
      "updated_at": "2025-03-14T16:42:07.000Z"
    },
    "relationships": {
      "social_feeds": {
        "data": [
          {
            "id": "90211",
            "type": "social_feed"
          }
        ],
        "meta": {
          "count": 2
        }
      },
      "subaccounts": {
        "data": [
          {
            "id": "17841401839964064",
            "type": "subaccount"
          }
        ],
        "meta": {
          "included": false
        }
      }
    }
  }
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Retrieve an account

GET
https://api.tintup.com/v2/teams/{team_id}/accounts/{account_id}

Parameters

team_idintegerrequiredpath

The ID of the team.

account_idintegerrequiredpath

The ID of the account.

includeArray<string>social_feedssubaccountsquery

A comma-separated list of related resources to include in the response.

Response

200OKobject

The account.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: accounts:read

Retrieve an account
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/accounts/{account_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/accounts/{account_id}', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/accounts/{account_id}')
data = response.json()
{
  "data": {
    "id": "4821",
    "type": "account",
    "attributes": {
      "external_id": "17841401839964064",
      "name": "Acme Inc.",
      "username": "acme",
      "image_url": "https://cdn.example.com/avatars/acme.jpg",
      "site": null,
      "expires_at": "2025-05-13T16:42:07.000Z",
      "capabilities": [
        "ingest",
        "compose"
      ],
      "meta": {},
      "followers_count": 12840,
      "follows_count": 312,
      "media_count": 587,
      "likes_count": null,
      "created_at": "2025-03-14T16:42:07.000Z",
      "updated_at": "2025-03-14T16:42:07.000Z"
    },
    "relationships": {
      "social_feeds": {
        "data": [
          {
            "id": "90211",
            "type": "social_feed"
          }
        ],
        "meta": {
          "count": 2
        }
      },
      "subaccounts": {
        "data": [
          {
            "id": "17841401839964064",
            "type": "subaccount"
          }
        ],
        "meta": {
          "included": false
        }
      }
    }
  }
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Delete an account

DELETE
https://api.tintup.com/v2/teams/{team_id}/accounts/{account_id}

Only accounts that are not in use by any social feed can be deleted; otherwise a 403 error is returned.

Parameters

team_idintegerrequiredpath

The ID of the team.

account_idintegerrequiredpath

The ID of the account.

Response

204No Content

No Content. The request succeeded and there is no response body.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: accounts:write

Delete an account
curl -X DELETE 'https://api.tintup.com/v2/teams/{team_id}/accounts/{account_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/accounts/{account_id}', {
  method: 'DELETE',
});

const data = await response.json();
import requests

response = requests.delete('https://api.tintup.com/v2/teams/{team_id}/accounts/{account_id}')
data = response.json()
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Reauthenticate an account

GET
https://api.tintup.com/v2/teams/{team_id}/accounts/{account_id}/edit

Returns the URL of the third-party authorization page for the account. Open this URL (usually in a popup window) so the user can grant access again. Once the user completes the authorization flow, the account's credentials are updated and the result is delivered using the origin or redirect_uri options. The user must authorize the same external account; otherwise the callback fails with a 422 error. Accounts connected with credentials (see Create an account) can't be reauthenticated and return a 422 error.

Parameters

team_idintegerrequiredpath

The ID of the team.

account_idintegerrequiredpath

The ID of the account.

originstring<uri>query

When specified, once the user completes the authorization flow, the callback page posts a message to window.opener using window.postMessage with this value as the target origin. The message is a JSON string of the form {"type": "account_new", "data": <response body>, "status": <HTTP status>} (account_edit when reauthenticating), where the response body is the account (or errors).

redirect_uristring<uri>query

When specified, once the user completes the authorization flow, the user is redirected to this URI with a data query parameter containing the same JSON message as for origin, encoded using Base64. Takes precedence over origin.

Response

200OKobject

The URL of the third-party authorization page. Open it (usually in a popup window) so the user can grant access.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: accounts:write

Reauthenticate an account
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/accounts/{account_id}/edit'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/accounts/{account_id}/edit', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/accounts/{account_id}/edit')
data = response.json()
{
  "data": {
    "id": "9e107d9d372bb6826bd81d3542a419d6",
    "type": "redirect",
    "attributes": {
      "url": "https://auth.example.com/oauth/authorize?client_id=8f14e45f&response_type=code&state=eyJhbGciOiJIUzI1NiJ9"
    }
  }
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Authenticate an account

GET
https://api.tintup.com/v2/teams/{team_id}/accounts/new

Returns the URL of the third-party authorization page for the requested account type. Open this URL (usually in a popup window) so the user can grant access. Once the user completes the authorization flow, the account is created (and its subaccounts are fetched) and the result is delivered using the origin or redirect_uri options. If the same external account is already connected to the team, the callback fails with a 422 error.

Parameters

team_idintegerrequiredpath

The ID of the team.

typeaccountTypesrequiredquery

The type of account to authenticate.

sitestringquery

The store URL, for account types that are tied to a specific site. Required for shopify, where it must be a *.myshopify.com domain (shop is accepted as an alias); otherwise a 422 error is returned.

originstring<uri>query

When specified, once the user completes the authorization flow, the callback page posts a message to window.opener using window.postMessage with this value as the target origin. The message is a JSON string of the form {"type": "account_new", "data": <response body>, "status": <HTTP status>} (account_edit when reauthenticating), where the response body is the account (or errors).

redirect_uristring<uri>query

When specified, once the user completes the authorization flow, the user is redirected to this URI with a data query parameter containing the same JSON message as for origin, encoded using Base64. Takes precedence over origin.

Response

200OKobject

The URL of the third-party authorization page. Open it (usually in a popup window) so the user can grant access.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: accounts:write

Authenticate an account
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/accounts/new'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/accounts/new', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/accounts/new')
data = response.json()
{
  "data": {
    "id": "9e107d9d372bb6826bd81d3542a419d6",
    "type": "redirect",
    "attributes": {
      "url": "https://auth.example.com/oauth/authorize?client_id=8f14e45f&response_type=code&state=eyJhbGciOiJIUzI1NiJ9"
    }
  }
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}
Common

Authentication Factors

authentication_factors

Retrieve a list of authentication factors

GET
https://api.tintup.com/v2/authentication_factors

Returns all the authentication factors (pending and active) of the current user.

Response

200OKobject

All the authentication factors of the current user. This list isn't paginated.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: authentication_factors:read

Retrieve a list of authentication factors
curl -X GET 'https://api.tintup.com/v2/authentication_factors'
const response = await fetch('https://api.tintup.com/v2/authentication_factors', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/authentication_factors')
data = response.json()
{
  "data": [
    {
      "id": "42",
      "type": "authentication_factor",
      "attributes": {
        "status": "pending",
        "type": "one_time_password",
        "channel": null,
        "external_id": null,
        "provisioning_url": "otpauth://totp/TrueLoyal:jane.doe%40example.com?secret=JBSWY3DPEHPK3PXPJBSWY3DPEHPK3PXP&issuer=TrueLoyal",
        "created_at": "2025-03-14T16:42:07.000Z"
      }
    }
  ]
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}

Create an authentication factor

POST
https://api.tintup.com/v2/authentication_factors

Adds an authentication factor to the current user. What happens next depends on the kind of authentication factor:

  • recovery_code, and out_of_band with the email channel, are active right away.
  • out_of_band with the sms, voice or fax channel is pending, and a code is sent to external_id immediately. Verify it with Verify an authentication factor. A new code can be requested after 30 seconds with Create an authentication factor challenge.
  • one_time_password is pending and has a provisioning_url to add to an authenticator app. Verify it with a code generated by the app.

A user can only have one authentication factor per type and channel combination.

Body

application/vnd.api+json

The authentication factor to add to the current user.

dataNewAuthenticationFactorrequired

The authentication factor to add. Which attributes are allowed depends on type and channel: channel is required for (and only allowed with) out_of_band, and external_id is required for (and only allowed with) the sms, voice and fax channels.

Show child attributes
typeAuthenticationFactorTypeauthentication_factorrequired

The resource type.

attributesobjectrequired
Show child attributes
typeauthenticationFactorTypesrequired

The kind of authentication factor. A user can have only one authentication factor per type and channel combination.

channelauthenticationFactorOutOfBandChannels

How the code is delivered. Required when type is out_of_band and must be omitted otherwise.

external_idstring

The phone or fax number to send codes to, in E.164 format (a + followed by up to 15 digits). Required when channel is sms, voice or fax and must be omitted otherwise.

Response

201Createdobject

The authentication factor.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: authentication_factors:write

id_tokenapiKey in query

A short-lived token required, in addition to an access token, to change sensitive data. See Changes to Sensitive Data.

Create an authentication factor
curl -X POST 'https://api.tintup.com/v2/authentication_factors' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "authentication_factor",
      "attributes": {
        "type": "out_of_band",
        "channel": "sms",
        "external_id": "+16045550123"
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/authentication_factors', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "authentication_factor",
        "attributes": {
          "type": "out_of_band",
          "channel": "sms",
          "external_id": "+16045550123"
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "authentication_factor",
    "attributes": {
      "type": "out_of_band",
      "channel": "sms",
      "external_id": "+16045550123"
    }
  }
}

response = requests.post('https://api.tintup.com/v2/authentication_factors', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "authentication_factor",
    "attributes": {
      "type": "out_of_band",
      "channel": "sms",
      "external_id": "+16045550123"
    }
  }
}
{
  "data": {
    "id": "42",
    "type": "authentication_factor",
    "attributes": {
      "status": "pending",
      "type": "one_time_password",
      "channel": null,
      "external_id": null,
      "provisioning_url": "otpauth://totp/TrueLoyal:jane.doe%40example.com?secret=JBSWY3DPEHPK3PXPJBSWY3DPEHPK3PXP&issuer=TrueLoyal",
      "created_at": "2025-03-14T16:42:07.000Z"
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Delete an authentication factor

DELETE
https://api.tintup.com/v2/authentication_factors/{authentication_factor_id}

Removes an authentication factor from the current user and emails them about it. If it was the user's default authentication factor, another active authentication factor (other than a recovery code) becomes the default.

Parameters

authentication_factor_idintegerrequiredpath

The ID of an authentication factor of the current user.

Response

204No Content

No Content. The request succeeded and there is no response body.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: authentication_factors:write

id_tokenapiKey in query

A short-lived token required, in addition to an access token, to change sensitive data. See Changes to Sensitive Data.

Delete an authentication factor
curl -X DELETE 'https://api.tintup.com/v2/authentication_factors/{authentication_factor_id}'
const response = await fetch('https://api.tintup.com/v2/authentication_factors/{authentication_factor_id}', {
  method: 'DELETE',
});

const data = await response.json();
import requests

response = requests.delete('https://api.tintup.com/v2/authentication_factors/{authentication_factor_id}')
data = response.json()
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Verify an authentication factor

PATCH
https://api.tintup.com/v2/authentication_factors/{authentication_factor_id}

Verifies a pending authentication factor with a code it received or generated, and marks it active. If the user doesn't have a default authentication factor yet, this one becomes the default. An email is sent to the user to let them know an authentication factor was added. Only pending authentication factors can be verified; others return 404.

Body

application/vnd.api+json

The code used to verify the pending authentication factor.

dataAuthenticationFactorForVerifyrequired

The code used to verify a pending authentication factor.

Show child attributes
idstring

The unique identifier of the authentication factor. Ignored; the path parameter is used instead.

typeAuthenticationFactorTypeauthentication_factorrequired

The resource type.

attributesobjectrequired
Show child attributes
challengestringrequiredwrite only

The code received by SMS, voice call or fax, or generated by the authenticator app.

otp_attemptstringwrite onlydeprecated

Deprecated. Use challenge instead. Only used when challenge is omitted.

Parameters

authentication_factor_idintegerrequiredpath

The ID of an authentication factor of the current user.

Response

200OKobject

The authentication factor.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

422Unprocessable Entityx-errors

Unprocessable Entity. The code is missing, invalid or expired.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: authentication_factors:write

id_tokenapiKey in query

A short-lived token required, in addition to an access token, to change sensitive data. See Changes to Sensitive Data.

Verify an authentication factor
curl -X PATCH 'https://api.tintup.com/v2/authentication_factors/{authentication_factor_id}' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "id": "42",
      "type": "authentication_factor",
      "attributes": {
        "challenge": "492817",
        "otp_attempt": "492817"
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/authentication_factors/{authentication_factor_id}', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "id": "42",
        "type": "authentication_factor",
        "attributes": {
          "challenge": "492817",
          "otp_attempt": "492817"
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "id": "42",
    "type": "authentication_factor",
    "attributes": {
      "challenge": "492817",
      "otp_attempt": "492817"
    }
  }
}

response = requests.patch('https://api.tintup.com/v2/authentication_factors/{authentication_factor_id}', json=payload)
data = response.json()
Request Body
{
  "data": {
    "id": "42",
    "type": "authentication_factor",
    "attributes": {
      "challenge": "492817",
      "otp_attempt": "492817"
    }
  }
}
{
  "data": {
    "id": "42",
    "type": "authentication_factor",
    "attributes": {
      "status": "pending",
      "type": "one_time_password",
      "channel": null,
      "external_id": null,
      "provisioning_url": "otpauth://totp/TrueLoyal:jane.doe%40example.com?secret=JBSWY3DPEHPK3PXPJBSWY3DPEHPK3PXP&issuer=TrueLoyal",
      "created_at": "2025-03-14T16:42:07.000Z"
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid challenge",
      "detail": "Challenge is invalid",
      "source": {
        "pointer": "/data/attributes/challenge"
      }
    },
    {
      "title": "Invalid otp_attempt",
      "detail": "Otp attempt is invalid",
      "source": {
        "pointer": "/data/attributes/otp_attempt"
      }
    }
  ]
}

Create an authentication factor challenge

POST
https://api.tintup.com/v2/authentication_factors/{authentication_factor_id}/challenges

Sends a new code for a pending out_of_band authentication factor, for example when the user didn't receive the first one. A code is already sent when the authentication factor is created, and a new one can only be requested every 30 seconds; earlier requests return 429 with a Retry-After header. Authentication factors that are active or aren't out_of_band return 404.

Body

application/vnd.api+json

Optional. The authentication factor to challenge is taken from the path, so the body can be omitted.

dataNewAuthenticationFactorChallengerequired

The challenge to create. The authentication factor is taken from the path.

Show child attributes
typeAuthenticationFactorChallengeTypeauthentication_factor_challengerequired

The resource type.

attributesobject
Show child attributes
authentication_factor_idintegerwrite only

The ID of the authentication factor to challenge. Ignored; the authentication_factor_id path parameter is used instead.

Parameters

authentication_factor_idintegerrequiredpath

The ID of an authentication factor of the current user.

Response

201Createdobject

The authentication factor challenge. A new code was sent.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

429Too Many Requestsx-errors

Too Many Requests. Retry after the time given in the Retry-After header.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: authentication_factors:write

id_tokenapiKey in query

A short-lived token required, in addition to an access token, to change sensitive data. See Changes to Sensitive Data.

Create an authentication factor challenge
curl -X POST 'https://api.tintup.com/v2/authentication_factors/{authentication_factor_id}/challenges' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "authentication_factor_challenge",
      "attributes": {
        "authentication_factor_id": 42
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/authentication_factors/{authentication_factor_id}/challenges', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "authentication_factor_challenge",
        "attributes": {
          "authentication_factor_id": 42
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "authentication_factor_challenge",
    "attributes": {
      "authentication_factor_id": 42
    }
  }
}

response = requests.post('https://api.tintup.com/v2/authentication_factors/{authentication_factor_id}/challenges', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "authentication_factor_challenge",
    "attributes": {
      "authentication_factor_id": 42
    }
  }
}
{
  "data": {
    "id": "SM5e0c7a1f9b3d4e2a8c6f0b1d3e5a7c9f",
    "type": "authentication_factor_challenge",
    "attributes": {
      "retry_at": "2025-03-14T16:42:37.000Z"
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}
{
  "errors": [
    {
      "code": "429",
      "title": "Too many requests",
      "status": "429"
    }
  ]
}
Common

Domains

domains

Retrieve a list of domains

GET
https://api.tintup.com/v2/teams/{team_id}/domains

Retrieves the team's domains that the user has access to.

Parameters

team_idintegerrequiredpath

The ID of the team.

includeArray<string>default_experiencequery

A comma-separated list of related resources to include in the response.

Response

200OKobject

The domains the user has access to. The list isn't paginated.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: domains:read

Retrieve a list of domains
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/domains'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/domains', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/domains')
data = response.json()
{
  "data": [
    {
      "id": "42",
      "type": "domain",
      "attributes": {
        "name": "stories.example.com",
        "status": "valid",
        "created_at": "2025-03-14T16:42:07.000Z",
        "updated_at": "2025-03-18T09:15:32.000Z"
      },
      "relationships": {
        "default_experience": {
          "data": {
            "type": "experience",
            "id": "318"
          }
        }
      },
      "links": {
        "self": "https://api.tintup.com/v2/teams/1/domains/42"
      }
    }
  ],
  "included": [
    {
      "id": "42",
      "type": "experience",
      "attributes": {
        "type": "sweepstakes",
        "title": "Win a trip to Hawaii",
        "description": "Enter our summer sweepstakes for a chance to win a trip for two.",
        "analytics_id": "GTM-5XK7Q2P",
        "analytics_type": "google_tag_manager",
        "captcha_type": null,
        "captcha_public_key": null,
        "cookie_consent": true,
        "noindex": false,
        "favicon_url": "https://cdn.example.com/favicons/acme.png",
        "maximum_image_size": 104857600,
        "maximum_video_size": 1048576000,
        "bypass_mime_type_validation": false,
        "name": "Summer Sweepstakes 2025",
        "status": "active",
        "slug": "summer-sweepstakes",
        "data": {
          "draft": [
            {
              "sectionType": "banner",
              "data": {
                "content": {
                  "title": "Win a trip to Hawaii"
                }
              }
            },
            {
              "sectionType": "form",
              "data": {
                "content": {
                  "fields": [
                    {
                      "key": "email",
                      "type": "email"
                    }
                  ]
                }
              }
            }
          ],
          "published": [
            {
              "sectionType": "banner",
              "data": {
                "content": {
                  "title": "Win a trip to Hawaii"
                }
              }
            },
            {
              "sectionType": "form",
              "data": {
                "content": {
                  "fields": [
                    {
                      "key": "email",
                      "type": "email"
                    }
                  ]
                }
              }
            }
          ],
          "locales": {
            "draft": [
              {
                "value": "en",
                "isDefault": true
              }
            ],
            "published": [
              {
                "value": "en",
                "isDefault": true
              }
            ]
          },
          "translations": {
            "draft": {
              "en": {}
            },
            "published": {
              "en": {}
            }
          },
          "customFonts": {
            "draft": {},
            "published": {}
          }
        },
        "created_at": "2025-03-14T16:42:07.000Z",
        "updated_at": "2025-03-18T09:12:44.000Z"
      },
      "relationships": {
        "domain": {
          "data": {
            "type": "domain",
            "id": "3"
          }
        },
        "form_submission_keys": {
          "data": [
            {
              "type": "form_submission_key",
              "id": "email"
            }
          ],
          "meta": {
            "included": false
          }
        },
        "user": {
          "data": {
            "type": "team",
            "id": "1"
          },
          "meta": {
            "included": false
          }
        },
        "submissions": {
          "data": [
            {
              "type": "form_submission",
              "id": "88213"
            }
          ],
          "links": {
            "related": "https://api.tintup.com/v2/teams/1/experiences/42/form_submissions",
            "first": "https://api.tintup.com/v2/teams/1/experiences/42/form_submissions",
            "next": "https://api.tintup.com/v2/teams/1/experiences/42/form_submissions?page%5Bnumber%5D=2"
          },
          "meta": {
            "total": 1289,
            "count": 1289
          }
        }
      },
      "links": {
        "public": "https://contests.example.com/summer-sweepstakes"
      }
    }
  ]
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}

Create a domain

POST
https://api.tintup.com/v2/teams/{team_id}/domains

Adds a custom domain to the team and starts issuing its SSL certificate; the domain's status is pending until the certificate has been issued. The new domain is automatically shared with the user's role and with every role that has access to new domains.

Body

application/vnd.api+json

The domain to create.

dataNewDomainrequired
Show child attributes
typestringdomainrequired

The resource type.

attributesobjectrequired
Show child attributes
namestring<hostname>required

The fully qualified domain name, without scheme or path. It must not already be in use by any team (case-insensitive). Point the domain's DNS at the experience hosting servers before creating it so the SSL certificate can be issued. The name can't be changed after creation.

Parameters

team_idintegerrequiredpath

The ID of the team.

Response

201Createdobject

The domain.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope or the user doesn't have access to the domain.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: domains:write

Create a domain
curl -X POST 'https://api.tintup.com/v2/teams/{team_id}/domains' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "domain",
      "attributes": {
        "name": "stories.example.com"
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/domains', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "domain",
        "attributes": {
          "name": "stories.example.com"
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "domain",
    "attributes": {
      "name": "stories.example.com"
    }
  }
}

response = requests.post('https://api.tintup.com/v2/teams/{team_id}/domains', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "domain",
    "attributes": {
      "name": "stories.example.com"
    }
  }
}
{
  "data": {
    "id": "42",
    "type": "domain",
    "attributes": {
      "name": "stories.example.com",
      "status": "valid",
      "created_at": "2025-03-14T16:42:07.000Z",
      "updated_at": "2025-03-18T09:15:32.000Z"
    },
    "relationships": {
      "default_experience": {
        "data": {
          "type": "experience",
          "id": "318"
        }
      }
    },
    "links": {
      "self": "https://api.tintup.com/v2/teams/1/domains/42"
    }
  },
  "included": [
    {
      "id": "42",
      "type": "experience",
      "attributes": {
        "type": "sweepstakes",
        "title": "Win a trip to Hawaii",
        "description": "Enter our summer sweepstakes for a chance to win a trip for two.",
        "analytics_id": "GTM-5XK7Q2P",
        "analytics_type": "google_tag_manager",
        "captcha_type": null,
        "captcha_public_key": null,
        "cookie_consent": true,
        "noindex": false,
        "favicon_url": "https://cdn.example.com/favicons/acme.png",
        "maximum_image_size": 104857600,
        "maximum_video_size": 1048576000,
        "bypass_mime_type_validation": false,
        "name": "Summer Sweepstakes 2025",
        "status": "active",
        "slug": "summer-sweepstakes",
        "data": {
          "draft": [
            {
              "sectionType": "banner",
              "data": {
                "content": {
                  "title": "Win a trip to Hawaii"
                }
              }
            },
            {
              "sectionType": "form",
              "data": {
                "content": {
                  "fields": [
                    {
                      "key": "email",
                      "type": "email"
                    }
                  ]
                }
              }
            }
          ],
          "published": [
            {
              "sectionType": "banner",
              "data": {
                "content": {
                  "title": "Win a trip to Hawaii"
                }
              }
            },
            {
              "sectionType": "form",
              "data": {
                "content": {
                  "fields": [
                    {
                      "key": "email",
                      "type": "email"
                    }
                  ]
                }
              }
            }
          ],
          "locales": {
            "draft": [
              {
                "value": "en",
                "isDefault": true
              }
            ],
            "published": [
              {
                "value": "en",
                "isDefault": true
              }
            ]
          },
          "translations": {
            "draft": {
              "en": {}
            },
            "published": {
              "en": {}
            }
          },
          "customFonts": {
            "draft": {},
            "published": {}
          }
        },
        "created_at": "2025-03-14T16:42:07.000Z",
        "updated_at": "2025-03-18T09:12:44.000Z"
      },
      "relationships": {
        "domain": {
          "data": {
            "type": "domain",
            "id": "3"
          }
        },
        "form_submission_keys": {
          "data": [
            {
              "type": "form_submission_key",
              "id": "email"
            }
          ],
          "meta": {
            "included": false
          }
        },
        "user": {
          "data": {
            "type": "team",
            "id": "1"
          },
          "meta": {
            "included": false
          }
        },
        "submissions": {
          "data": [
            {
              "type": "form_submission",
              "id": "88213"
            }
          ],
          "links": {
            "related": "https://api.tintup.com/v2/teams/1/experiences/42/form_submissions",
            "first": "https://api.tintup.com/v2/teams/1/experiences/42/form_submissions",
            "next": "https://api.tintup.com/v2/teams/1/experiences/42/form_submissions?page%5Bnumber%5D=2"
          },
          "meta": {
            "total": 1289,
            "count": 1289
          }
        }
      },
      "links": {
        "public": "https://contests.example.com/summer-sweepstakes"
      }
    }
  ]
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "403",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Retrieve a domain

GET
https://api.tintup.com/v2/teams/{team_id}/domains/{domain_id}

Retrieves one of the team's domains.

Parameters

team_idintegerrequiredpath

The ID of the team.

domain_idintegerrequiredpath

The ID of the domain.

includeArray<string>default_experiencequery

A comma-separated list of related resources to include in the response.

Response

200OKobject

The domain.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: domains:read

Retrieve a domain
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/domains/{domain_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/domains/{domain_id}', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/domains/{domain_id}')
data = response.json()
{
  "data": {
    "id": "42",
    "type": "domain",
    "attributes": {
      "name": "stories.example.com",
      "status": "valid",
      "created_at": "2025-03-14T16:42:07.000Z",
      "updated_at": "2025-03-18T09:15:32.000Z"
    },
    "relationships": {
      "default_experience": {
        "data": {
          "type": "experience",
          "id": "318"
        }
      }
    },
    "links": {
      "self": "https://api.tintup.com/v2/teams/1/domains/42"
    }
  },
  "included": [
    {
      "id": "42",
      "type": "experience",
      "attributes": {
        "type": "sweepstakes",
        "title": "Win a trip to Hawaii",
        "description": "Enter our summer sweepstakes for a chance to win a trip for two.",
        "analytics_id": "GTM-5XK7Q2P",
        "analytics_type": "google_tag_manager",
        "captcha_type": null,
        "captcha_public_key": null,
        "cookie_consent": true,
        "noindex": false,
        "favicon_url": "https://cdn.example.com/favicons/acme.png",
        "maximum_image_size": 104857600,
        "maximum_video_size": 1048576000,
        "bypass_mime_type_validation": false,
        "name": "Summer Sweepstakes 2025",
        "status": "active",
        "slug": "summer-sweepstakes",
        "data": {
          "draft": [
            {
              "sectionType": "banner",
              "data": {
                "content": {
                  "title": "Win a trip to Hawaii"
                }
              }
            },
            {
              "sectionType": "form",
              "data": {
                "content": {
                  "fields": [
                    {
                      "key": "email",
                      "type": "email"
                    }
                  ]
                }
              }
            }
          ],
          "published": [
            {
              "sectionType": "banner",
              "data": {
                "content": {
                  "title": "Win a trip to Hawaii"
                }
              }
            },
            {
              "sectionType": "form",
              "data": {
                "content": {
                  "fields": [
                    {
                      "key": "email",
                      "type": "email"
                    }
                  ]
                }
              }
            }
          ],
          "locales": {
            "draft": [
              {
                "value": "en",
                "isDefault": true
              }
            ],
            "published": [
              {
                "value": "en",
                "isDefault": true
              }
            ]
          },
          "translations": {
            "draft": {
              "en": {}
            },
            "published": {
              "en": {}
            }
          },
          "customFonts": {
            "draft": {},
            "published": {}
          }
        },
        "created_at": "2025-03-14T16:42:07.000Z",
        "updated_at": "2025-03-18T09:12:44.000Z"
      },
      "relationships": {
        "domain": {
          "data": {
            "type": "domain",
            "id": "3"
          }
        },
        "form_submission_keys": {
          "data": [
            {
              "type": "form_submission_key",
              "id": "email"
            }
          ],
          "meta": {
            "included": false
          }
        },
        "user": {
          "data": {
            "type": "team",
            "id": "1"
          },
          "meta": {
            "included": false
          }
        },
        "submissions": {
          "data": [
            {
              "type": "form_submission",
              "id": "88213"
            }
          ],
          "links": {
            "related": "https://api.tintup.com/v2/teams/1/experiences/42/form_submissions",
            "first": "https://api.tintup.com/v2/teams/1/experiences/42/form_submissions",
            "next": "https://api.tintup.com/v2/teams/1/experiences/42/form_submissions?page%5Bnumber%5D=2"
          },
          "meta": {
            "total": 1289,
            "count": 1289
          }
        }
      },
      "links": {
        "public": "https://contests.example.com/summer-sweepstakes"
      }
    }
  ]
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Delete a domain

DELETE
https://api.tintup.com/v2/teams/{team_id}/domains/{domain_id}

Deletes the domain. Experiences published on it are detached from the domain.

Parameters

team_idintegerrequiredpath

The ID of the team.

domain_idintegerrequiredpath

The ID of the domain.

Response

204No Content

No Content. The request succeeded and there is no response body.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: domains:write

Delete a domain
curl -X DELETE 'https://api.tintup.com/v2/teams/{team_id}/domains/{domain_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/domains/{domain_id}', {
  method: 'DELETE',
});

const data = await response.json();
import requests

response = requests.delete('https://api.tintup.com/v2/teams/{team_id}/domains/{domain_id}')
data = response.json()
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Update a domain

PATCH
https://api.tintup.com/v2/teams/{team_id}/domains/{domain_id}

Sets or clears the experience shown at the root of the domain. The domain's name can't be changed.

Body

application/vnd.api+json

The attributes to update.

dataDomainUpdaterequired
Show child attributes
typestringdomainrequired

The resource type.

idstring

The ID of the domain. Optional; the domain is identified by the URL.

attributesobjectrequired

Only default_experience_id can be updated; any other attribute is ignored.

Show child attributes
default_experience_idinteger | null

The ID of the experience to show at the root of the domain, or null to remove it. The experience must be accessible to the user and already be published on this domain.

Parameters

team_idintegerrequiredpath

The ID of the team.

domain_idintegerrequiredpath

The ID of the domain.

Response

200OKobject

The domain.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: domains:write

Update a domain
curl -X PATCH 'https://api.tintup.com/v2/teams/{team_id}/domains/{domain_id}' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "domain",
      "id": "42",
      "attributes": {
        "default_experience_id": 318
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/domains/{domain_id}', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "domain",
        "id": "42",
        "attributes": {
          "default_experience_id": 318
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "domain",
    "id": "42",
    "attributes": {
      "default_experience_id": 318
    }
  }
}

response = requests.patch('https://api.tintup.com/v2/teams/{team_id}/domains/{domain_id}', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "domain",
    "id": "42",
    "attributes": {
      "default_experience_id": 318
    }
  }
}
{
  "data": {
    "id": "42",
    "type": "domain",
    "attributes": {
      "name": "stories.example.com",
      "status": "valid",
      "created_at": "2025-03-14T16:42:07.000Z",
      "updated_at": "2025-03-18T09:15:32.000Z"
    },
    "relationships": {
      "default_experience": {
        "data": {
          "type": "experience",
          "id": "318"
        }
      }
    },
    "links": {
      "self": "https://api.tintup.com/v2/teams/1/domains/42"
    }
  },
  "included": [
    {
      "id": "42",
      "type": "experience",
      "attributes": {
        "type": "sweepstakes",
        "title": "Win a trip to Hawaii",
        "description": "Enter our summer sweepstakes for a chance to win a trip for two.",
        "analytics_id": "GTM-5XK7Q2P",
        "analytics_type": "google_tag_manager",
        "captcha_type": null,
        "captcha_public_key": null,
        "cookie_consent": true,
        "noindex": false,
        "favicon_url": "https://cdn.example.com/favicons/acme.png",
        "maximum_image_size": 104857600,
        "maximum_video_size": 1048576000,
        "bypass_mime_type_validation": false,
        "name": "Summer Sweepstakes 2025",
        "status": "active",
        "slug": "summer-sweepstakes",
        "data": {
          "draft": [
            {
              "sectionType": "banner",
              "data": {
                "content": {
                  "title": "Win a trip to Hawaii"
                }
              }
            },
            {
              "sectionType": "form",
              "data": {
                "content": {
                  "fields": [
                    {
                      "key": "email",
                      "type": "email"
                    }
                  ]
                }
              }
            }
          ],
          "published": [
            {
              "sectionType": "banner",
              "data": {
                "content": {
                  "title": "Win a trip to Hawaii"
                }
              }
            },
            {
              "sectionType": "form",
              "data": {
                "content": {
                  "fields": [
                    {
                      "key": "email",
                      "type": "email"
                    }
                  ]
                }
              }
            }
          ],
          "locales": {
            "draft": [
              {
                "value": "en",
                "isDefault": true
              }
            ],
            "published": [
              {
                "value": "en",
                "isDefault": true
              }
            ]
          },
          "translations": {
            "draft": {
              "en": {}
            },
            "published": {
              "en": {}
            }
          },
          "customFonts": {
            "draft": {},
            "published": {}
          }
        },
        "created_at": "2025-03-14T16:42:07.000Z",
        "updated_at": "2025-03-18T09:12:44.000Z"
      },
      "relationships": {
        "domain": {
          "data": {
            "type": "domain",
            "id": "3"
          }
        },
        "form_submission_keys": {
          "data": [
            {
              "type": "form_submission_key",
              "id": "email"
            }
          ],
          "meta": {
            "included": false
          }
        },
        "user": {
          "data": {
            "type": "team",
            "id": "1"
          },
          "meta": {
            "included": false
          }
        },
        "submissions": {
          "data": [
            {
              "type": "form_submission",
              "id": "88213"
            }
          ],
          "links": {
            "related": "https://api.tintup.com/v2/teams/1/experiences/42/form_submissions",
            "first": "https://api.tintup.com/v2/teams/1/experiences/42/form_submissions",
            "next": "https://api.tintup.com/v2/teams/1/experiences/42/form_submissions?page%5Bnumber%5D=2"
          },
          "meta": {
            "total": 1289,
            "count": 1289
          }
        }
      },
      "links": {
        "public": "https://contests.example.com/summer-sweepstakes"
      }
    }
  ]
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}
Common

Email Templates

email_templates

Retrieve a list of email templates

GET
https://api.tintup.com/v2/teams/{team_id}/email_templates

Retrieves the team's email templates. Any member of the team can list them.

Parameters

team_idintegerrequiredpath

The ID of the team.

pageobjectquery

Offset pagination. Use page[size] to set the number of items per page and page[number] to select a page. The response's links object contains ready-to-use URLs for the next and previous pages.

filterobjectquery

Filters the email templates.

sortArray<string>id-idname-nametype-typecreated_at-created_atupdated_at-updated_at-idquery

A comma-separated list of fields to sort by. Prefix a field with - to sort in descending order. Defaults to -id (newest first).

includeArray<string>teamquery

A comma-separated list of related resources to include in the response.

Response

200OKobject

A page of the team's email templates.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: email_templates:read

Retrieve a list of email templates
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/email_templates'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/email_templates', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/email_templates')
data = response.json()
{
  "data": [
    {
      "id": "15",
      "type": "email_templates",
      "attributes": {
        "name": "Post-purchase review request",
        "type": "review_solicitation",
        "locales": {
          "en": {
            "from": {
              "name": "Acme Inc.",
              "email": "reviews@example.com"
            },
            "subject": "Thanks for your review, {{ post.author.name }}",
            "body": "<p>Hi {{ post.author.name }},</p>\n<p>Thanks for reviewing us. Here's our reply:</p>\n<blockquote>{{ reply.text }}</blockquote>\n<p>The {{ team.name }} team</p>"
          },
          "fr": {
            "from": {
              "name": "Acme Inc.",
              "email": "reviews@example.com"
            },
            "subject": "Merci pour votre avis, {{ post.author.name }}",
            "body": "<p>Bonjour {{ post.author.name }},</p>\n<p>Merci pour votre avis. Voici notre réponse :</p>\n<blockquote>{{ reply.text }}</blockquote>\n<p>L'équipe {{ team.name }}</p>"
          }
        },
        "created_at": "2025-03-14T16:42:07.000Z",
        "updated_at": "2025-03-18T09:15:32.000Z"
      },
      "relationships": {
        "team": {
          "data": {
            "type": "team",
            "id": "1"
          },
          "meta": {
            "included": false
          }
        }
      }
    }
  ],
  "included": [
    {
      "id": "1",
      "type": "team",
      "attributes": {
        "name": "Acme Inc.",
        "image_url": "https://cdn.example.com/logos/acme.png",
        "url_shortener_type": "tintly",
        "onboarding": "completed",
        "shared_tags": [
          "summer",
          "ugc"
        ],
        "saml_enabled": true,
        "idp_entity_id": "https://idp.example.com/metadata",
        "idp_sso_target_url": "https://idp.example.com/sso/saml",
        "idp_cert": "-----BEGIN CERTIFICATE-----\nMIIDdzCCAl+gAwIBAgIEbGx0ZTANBgkqhkiG9w0BAQsFADBsMRAwDgYDVQQGEwdV\n-----END CERTIFICATE-----",
        "force_authn": false,
        "authn_requests_signed": false,
        "want_assertions_signed": true,
        "want_assertions_encrypted": false,
        "saml_jit_provisioning": true,
        "oidc_enabled": false,
        "oidc_identifier": "0oa1b2c3d4e5f6g7h8i9",
        "oidc_secret": "9f8e7d6c5b4a39281706f5e4d3c2b1a0",
        "oidc_scope": "openid email profile",
        "oidc_issuer": "https://login.example.com",
        "oidc_authorization_endpoint": "https://login.example.com/oauth2/v1/authorize",
        "oidc_token_endpoint": "https://login.example.com/oauth2/v1/token",
        "oidc_userinfo_endpoint": "https://login.example.com/oauth2/v1/userinfo",
        "oidc_jwks_uri": "https://login.example.com/oauth2/v1/keys",
        "plan": "tint_professional",
        "plan_expires_at": "2026-03-14T00:00:00.000Z",
        "plan_changed_at": "2025-03-14T16:42:07.000Z",
        "self_service": false,
        "rewards_platform_id": "mrc_4f7a2b9c",
        "rewards_platform_key": "7d1e3c5a9b2f4e6d8c0a1b3d5f7e9c2a",
        "permissions": [
          "moderate_tint",
          "modify_tint",
          "assets_read"
        ],
        "created_at": "2024-11-02T10:05:44.000Z",
        "updated_at": "2025-03-14T16:42:07.000Z"
      },
      "relationships": {
        "role": {
          "data": {
            "type": "role",
            "id": "3"
          }
        },
        "plan": {
          "data": {
            "type": "plan",
            "id": "1"
          }
        },
        "agent": {
          "data": {
            "type": "agent",
            "id": "7"
          }
        },
        "tints": {
          "data": [
            {
              "type": "tint",
              "id": "1"
            }
          ],
          "meta": {
            "active_tints_count": 4,
            "count": 6
          }
        },
        "social_feeds": {
          "data": [
            {
              "type": "social_feed",
              "id": "1"
            }
          ],
          "meta": {
            "active_count": 12,
            "inactive_count": 3,
            "access_error_count": 1,
            "active_social_feeds_count": 12,
            "inactive_social_feeds_count": 3
          }
        },
        "posts": {
          "data": [
            {
              "type": "post",
              "id": "1"
            }
          ],
          "meta": {
            "posts_ingested_from_beginning_of_month": 18250
          }
        },
        "assets": {
          "data": [
            {
              "type": "asset",
              "id": "1"
            }
          ],
          "meta": {
            "count": 320,
            "uploaded_count": 45,
            "total": 320,
            "uploaded_total": 45
          }
        },
        "mixes": {
          "data": [
            {
              "type": "mix",
              "id": "1"
            }
          ],
          "meta": {
            "count": 2
          }
        },
        "forms": {
          "data": [
            {
              "type": "form",
              "id": "1"
            }
          ],
          "meta": {
            "count": 5,
            "published_count": 3
          }
        },
        "personalizations": {
          "data": [
            {
              "type": "personalization",
              "id": "1"
            }
          ],
          "meta": {
            "count": 8
          }
        }
      }
    }
  ],
  "links": {
    "self": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=2",
    "first": "https://api.tintup.com/v2/teams/1/tints",
    "next": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=3",
    "prev": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=1"
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}

Create an email template

POST
https://api.tintup.com/v2/teams/{team_id}/email_templates

Creates an email template for the team. Any member of the team can create one.

Body

application/vnd.api+json

The email template to create.

dataNewEmailTemplaterequired
Show child attributes
typestringemail_templatesrequired

The resource type.

attributesobjectrequired
Show child attributes
nameEmailTemplateNamerequired

The name of the template, shown in the dashboard.

typeEmailTemplateTypereview_solicitationreview_solicitation_reminderform_submissioninfluencerreview_replyrequired

What the template is used for: review_solicitation (asking a customer for a review), review_solicitation_reminder (a follow-up to a review request), form_submission (sent after a form is submitted), influencer (outreach to influencers), or review_reply (a reply to a review).

localesEmailTemplateLocalesrequired

The content of the email for each locale, keyed by locale code (for example en or fr-CA). At least one locale is required, and each locale requires a non-blank from.name, from.email, subject, and body. Unknown keys are ignored.

Parameters

team_idintegerrequiredpath

The ID of the team.

Response

201Createdobject

The email template.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: email_templates:write

Create an email template
curl -X POST 'https://api.tintup.com/v2/teams/{team_id}/email_templates' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "email_templates",
      "attributes": {
        "name": "Review reply",
        "type": "review_reply",
        "locales": {
          "en": {
            "from": {
              "name": "Acme Inc.",
              "email": "reviews@example.com"
            },
            "subject": "Thanks for your review, {{ post.author.name }}",
            "body": "<p>Hi {{ post.author.name }},</p>\n<p>Thanks for reviewing us. Here'\''s our reply:</p>\n<blockquote>{{ reply.text }}</blockquote>\n<p>The {{ team.name }} team</p>"
          }
        }
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/email_templates', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "email_templates",
        "attributes": {
          "name": "Review reply",
          "type": "review_reply",
          "locales": {
            "en": {
              "from": {
                "name": "Acme Inc.",
                "email": "reviews@example.com"
              },
              "subject": "Thanks for your review, {{ post.author.name }}",
              "body": "<p>Hi {{ post.author.name }},</p>\n<p>Thanks for reviewing us. Here's our reply:</p>\n<blockquote>{{ reply.text }}</blockquote>\n<p>The {{ team.name }} team</p>"
            }
          }
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "email_templates",
    "attributes": {
      "name": "Review reply",
      "type": "review_reply",
      "locales": {
        "en": {
          "from": {
            "name": "Acme Inc.",
            "email": "reviews@example.com"
          },
          "subject": "Thanks for your review, {{ post.author.name }}",
          "body": "<p>Hi {{ post.author.name }},</p>\n<p>Thanks for reviewing us. Here's our reply:</p>\n<blockquote>{{ reply.text }}</blockquote>\n<p>The {{ team.name }} team</p>"
        }
      }
    }
  }
}

response = requests.post('https://api.tintup.com/v2/teams/{team_id}/email_templates', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "email_templates",
    "attributes": {
      "name": "Review reply",
      "type": "review_reply",
      "locales": {
        "en": {
          "from": {
            "name": "Acme Inc.",
            "email": "reviews@example.com"
          },
          "subject": "Thanks for your review, {{ post.author.name }}",
          "body": "<p>Hi {{ post.author.name }},</p>\n<p>Thanks for reviewing us. Here's our reply:</p>\n<blockquote>{{ reply.text }}</blockquote>\n<p>The {{ team.name }} team</p>"
        }
      }
    }
  }
}
{
  "data": {
    "id": "15",
    "type": "email_templates",
    "attributes": {
      "name": "Post-purchase review request",
      "type": "review_solicitation",
      "locales": {
        "en": {
          "from": {
            "name": "Acme Inc.",
            "email": "reviews@example.com"
          },
          "subject": "Thanks for your review, {{ post.author.name }}",
          "body": "<p>Hi {{ post.author.name }},</p>\n<p>Thanks for reviewing us. Here's our reply:</p>\n<blockquote>{{ reply.text }}</blockquote>\n<p>The {{ team.name }} team</p>"
        },
        "fr": {
          "from": {
            "name": "Acme Inc.",
            "email": "reviews@example.com"
          },
          "subject": "Merci pour votre avis, {{ post.author.name }}",
          "body": "<p>Bonjour {{ post.author.name }},</p>\n<p>Merci pour votre avis. Voici notre réponse :</p>\n<blockquote>{{ reply.text }}</blockquote>\n<p>L'équipe {{ team.name }}</p>"
        }
      },
      "created_at": "2025-03-14T16:42:07.000Z",
      "updated_at": "2025-03-18T09:15:32.000Z"
    },
    "relationships": {
      "team": {
        "data": {
          "type": "team",
          "id": "1"
        },
        "meta": {
          "included": false
        }
      }
    }
  },
  "included": [
    {
      "id": "1",
      "type": "team",
      "attributes": {
        "name": "Acme Inc.",
        "image_url": "https://cdn.example.com/logos/acme.png",
        "url_shortener_type": "tintly",
        "onboarding": "completed",
        "shared_tags": [
          "summer",
          "ugc"
        ],
        "saml_enabled": true,
        "idp_entity_id": "https://idp.example.com/metadata",
        "idp_sso_target_url": "https://idp.example.com/sso/saml",
        "idp_cert": "-----BEGIN CERTIFICATE-----\nMIIDdzCCAl+gAwIBAgIEbGx0ZTANBgkqhkiG9w0BAQsFADBsMRAwDgYDVQQGEwdV\n-----END CERTIFICATE-----",
        "force_authn": false,
        "authn_requests_signed": false,
        "want_assertions_signed": true,
        "want_assertions_encrypted": false,
        "saml_jit_provisioning": true,
        "oidc_enabled": false,
        "oidc_identifier": "0oa1b2c3d4e5f6g7h8i9",
        "oidc_secret": "9f8e7d6c5b4a39281706f5e4d3c2b1a0",
        "oidc_scope": "openid email profile",
        "oidc_issuer": "https://login.example.com",
        "oidc_authorization_endpoint": "https://login.example.com/oauth2/v1/authorize",
        "oidc_token_endpoint": "https://login.example.com/oauth2/v1/token",
        "oidc_userinfo_endpoint": "https://login.example.com/oauth2/v1/userinfo",
        "oidc_jwks_uri": "https://login.example.com/oauth2/v1/keys",
        "plan": "tint_professional",
        "plan_expires_at": "2026-03-14T00:00:00.000Z",
        "plan_changed_at": "2025-03-14T16:42:07.000Z",
        "self_service": false,
        "rewards_platform_id": "mrc_4f7a2b9c",
        "rewards_platform_key": "7d1e3c5a9b2f4e6d8c0a1b3d5f7e9c2a",
        "permissions": [
          "moderate_tint",
          "modify_tint",
          "assets_read"
        ],
        "created_at": "2024-11-02T10:05:44.000Z",
        "updated_at": "2025-03-14T16:42:07.000Z"
      },
      "relationships": {
        "role": {
          "data": {
            "type": "role",
            "id": "3"
          }
        },
        "plan": {
          "data": {
            "type": "plan",
            "id": "1"
          }
        },
        "agent": {
          "data": {
            "type": "agent",
            "id": "7"
          }
        },
        "tints": {
          "data": [
            {
              "type": "tint",
              "id": "1"
            }
          ],
          "meta": {
            "active_tints_count": 4,
            "count": 6
          }
        },
        "social_feeds": {
          "data": [
            {
              "type": "social_feed",
              "id": "1"
            }
          ],
          "meta": {
            "active_count": 12,
            "inactive_count": 3,
            "access_error_count": 1,
            "active_social_feeds_count": 12,
            "inactive_social_feeds_count": 3
          }
        },
        "posts": {
          "data": [
            {
              "type": "post",
              "id": "1"
            }
          ],
          "meta": {
            "posts_ingested_from_beginning_of_month": 18250
          }
        },
        "assets": {
          "data": [
            {
              "type": "asset",
              "id": "1"
            }
          ],
          "meta": {
            "count": 320,
            "uploaded_count": 45,
            "total": 320,
            "uploaded_total": 45
          }
        },
        "mixes": {
          "data": [
            {
              "type": "mix",
              "id": "1"
            }
          ],
          "meta": {
            "count": 2
          }
        },
        "forms": {
          "data": [
            {
              "type": "form",
              "id": "1"
            }
          ],
          "meta": {
            "count": 5,
            "published_count": 3
          }
        },
        "personalizations": {
          "data": [
            {
              "type": "personalization",
              "id": "1"
            }
          ],
          "meta": {
            "count": 8
          }
        }
      }
    }
  ]
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Delete multiple email templates

DELETE
https://api.tintup.com/v2/teams/{team_id}/email_templates

Deletes several of the team's email templates at once. IDs that don't match one of the team's templates are ignored.

Body

application/vnd.api+json; ext=bulk

The email templates to delete.

dataArray<EmailTemplateBulkDelete>required
Show child attributes
typestringemail_templatesrequired

The resource type.

idstringrequired

The ID of an email template to delete. IDs that don't belong to the team are ignored.

Parameters

team_idintegerrequiredpath

The ID of the team.

Response

204No Content

No Content. The request succeeded and there is no response body.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: email_templates:write

Delete multiple email templates
curl -X DELETE 'https://api.tintup.com/v2/teams/{team_id}/email_templates' \
  -H 'Content-Type: application/vnd.api+json; ext=bulk' \
  -d '{
    "data": [
      {
        "type": "email_templates",
        "id": "15"
      },
      {
        "type": "email_templates",
        "id": "16"
      }
    ]
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/email_templates', {
  method: 'DELETE',
  headers: {
    'Content-Type': 'application/vnd.api+json; ext=bulk',
  },
  body: JSON.stringify({
      "data": [
        {
          "type": "email_templates",
          "id": "15"
        },
        {
          "type": "email_templates",
          "id": "16"
        }
      ]
    }),
});

const data = await response.json();
import requests

payload = {
  "data": [
    {
      "type": "email_templates",
      "id": "15"
    },
    {
      "type": "email_templates",
      "id": "16"
    }
  ]
}

response = requests.delete('https://api.tintup.com/v2/teams/{team_id}/email_templates', json=payload)
data = response.json()
Request Body
{
  "data": [
    {
      "type": "email_templates",
      "id": "15"
    },
    {
      "type": "email_templates",
      "id": "16"
    }
  ]
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Retrieve an email template

GET
https://api.tintup.com/v2/teams/{team_id}/email_templates/{email_template_id}

Retrieves one of the team's email templates.

Parameters

team_idintegerrequiredpath

The ID of the team.

email_template_idintegerrequiredpath

The ID of the email template.

includeArray<string>teamquery

A comma-separated list of related resources to include in the response.

Response

200OKobject

The email template.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: email_templates:read

Retrieve an email template
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/email_templates/{email_template_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/email_templates/{email_template_id}', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/email_templates/{email_template_id}')
data = response.json()
{
  "data": {
    "id": "15",
    "type": "email_templates",
    "attributes": {
      "name": "Post-purchase review request",
      "type": "review_solicitation",
      "locales": {
        "en": {
          "from": {
            "name": "Acme Inc.",
            "email": "reviews@example.com"
          },
          "subject": "Thanks for your review, {{ post.author.name }}",
          "body": "<p>Hi {{ post.author.name }},</p>\n<p>Thanks for reviewing us. Here's our reply:</p>\n<blockquote>{{ reply.text }}</blockquote>\n<p>The {{ team.name }} team</p>"
        },
        "fr": {
          "from": {
            "name": "Acme Inc.",
            "email": "reviews@example.com"
          },
          "subject": "Merci pour votre avis, {{ post.author.name }}",
          "body": "<p>Bonjour {{ post.author.name }},</p>\n<p>Merci pour votre avis. Voici notre réponse :</p>\n<blockquote>{{ reply.text }}</blockquote>\n<p>L'équipe {{ team.name }}</p>"
        }
      },
      "created_at": "2025-03-14T16:42:07.000Z",
      "updated_at": "2025-03-18T09:15:32.000Z"
    },
    "relationships": {
      "team": {
        "data": {
          "type": "team",
          "id": "1"
        },
        "meta": {
          "included": false
        }
      }
    }
  },
  "included": [
    {
      "id": "1",
      "type": "team",
      "attributes": {
        "name": "Acme Inc.",
        "image_url": "https://cdn.example.com/logos/acme.png",
        "url_shortener_type": "tintly",
        "onboarding": "completed",
        "shared_tags": [
          "summer",
          "ugc"
        ],
        "saml_enabled": true,
        "idp_entity_id": "https://idp.example.com/metadata",
        "idp_sso_target_url": "https://idp.example.com/sso/saml",
        "idp_cert": "-----BEGIN CERTIFICATE-----\nMIIDdzCCAl+gAwIBAgIEbGx0ZTANBgkqhkiG9w0BAQsFADBsMRAwDgYDVQQGEwdV\n-----END CERTIFICATE-----",
        "force_authn": false,
        "authn_requests_signed": false,
        "want_assertions_signed": true,
        "want_assertions_encrypted": false,
        "saml_jit_provisioning": true,
        "oidc_enabled": false,
        "oidc_identifier": "0oa1b2c3d4e5f6g7h8i9",
        "oidc_secret": "9f8e7d6c5b4a39281706f5e4d3c2b1a0",
        "oidc_scope": "openid email profile",
        "oidc_issuer": "https://login.example.com",
        "oidc_authorization_endpoint": "https://login.example.com/oauth2/v1/authorize",
        "oidc_token_endpoint": "https://login.example.com/oauth2/v1/token",
        "oidc_userinfo_endpoint": "https://login.example.com/oauth2/v1/userinfo",
        "oidc_jwks_uri": "https://login.example.com/oauth2/v1/keys",
        "plan": "tint_professional",
        "plan_expires_at": "2026-03-14T00:00:00.000Z",
        "plan_changed_at": "2025-03-14T16:42:07.000Z",
        "self_service": false,
        "rewards_platform_id": "mrc_4f7a2b9c",
        "rewards_platform_key": "7d1e3c5a9b2f4e6d8c0a1b3d5f7e9c2a",
        "permissions": [
          "moderate_tint",
          "modify_tint",
          "assets_read"
        ],
        "created_at": "2024-11-02T10:05:44.000Z",
        "updated_at": "2025-03-14T16:42:07.000Z"
      },
      "relationships": {
        "role": {
          "data": {
            "type": "role",
            "id": "3"
          }
        },
        "plan": {
          "data": {
            "type": "plan",
            "id": "1"
          }
        },
        "agent": {
          "data": {
            "type": "agent",
            "id": "7"
          }
        },
        "tints": {
          "data": [
            {
              "type": "tint",
              "id": "1"
            }
          ],
          "meta": {
            "active_tints_count": 4,
            "count": 6
          }
        },
        "social_feeds": {
          "data": [
            {
              "type": "social_feed",
              "id": "1"
            }
          ],
          "meta": {
            "active_count": 12,
            "inactive_count": 3,
            "access_error_count": 1,
            "active_social_feeds_count": 12,
            "inactive_social_feeds_count": 3
          }
        },
        "posts": {
          "data": [
            {
              "type": "post",
              "id": "1"
            }
          ],
          "meta": {
            "posts_ingested_from_beginning_of_month": 18250
          }
        },
        "assets": {
          "data": [
            {
              "type": "asset",
              "id": "1"
            }
          ],
          "meta": {
            "count": 320,
            "uploaded_count": 45,
            "total": 320,
            "uploaded_total": 45
          }
        },
        "mixes": {
          "data": [
            {
              "type": "mix",
              "id": "1"
            }
          ],
          "meta": {
            "count": 2
          }
        },
        "forms": {
          "data": [
            {
              "type": "form",
              "id": "1"
            }
          ],
          "meta": {
            "count": 5,
            "published_count": 3
          }
        },
        "personalizations": {
          "data": [
            {
              "type": "personalization",
              "id": "1"
            }
          ],
          "meta": {
            "count": 8
          }
        }
      }
    }
  ]
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Delete an email template

DELETE
https://api.tintup.com/v2/teams/{team_id}/email_templates/{email_template_id}

Deletes the email template.

Parameters

team_idintegerrequiredpath

The ID of the team.

email_template_idintegerrequiredpath

The ID of the email template.

Response

204No Content

No Content. The request succeeded and there is no response body.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: email_templates:write

Delete an email template
curl -X DELETE 'https://api.tintup.com/v2/teams/{team_id}/email_templates/{email_template_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/email_templates/{email_template_id}', {
  method: 'DELETE',
});

const data = await response.json();
import requests

response = requests.delete('https://api.tintup.com/v2/teams/{team_id}/email_templates/{email_template_id}')
data = response.json()
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Update an email template

PATCH
https://api.tintup.com/v2/teams/{team_id}/email_templates/{email_template_id}

Updates the template's name or content. The template's type can't be changed.

Body

application/vnd.api+json

The attributes to update.

dataEmailTemplateUpdaterequired
Show child attributes
typestringemail_templatesrequired

The resource type.

idstring

The ID of the email template. Optional; the template is identified by the URL.

attributesobjectrequired

The attributes to change. Omitted attributes keep their current value. The template's type can't be changed and is ignored.

Show child attributes
nameEmailTemplateName

The name of the template, shown in the dashboard.

localesEmailTemplateLocales

The content of the email for each locale. Replaces all existing locales, so include every locale to keep.

Parameters

team_idintegerrequiredpath

The ID of the team.

email_template_idintegerrequiredpath

The ID of the email template.

Response

200OKobject

The email template.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: email_templates:write

Update an email template
curl -X PATCH 'https://api.tintup.com/v2/teams/{team_id}/email_templates/{email_template_id}' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "email_templates",
      "id": "15",
      "attributes": {
        "name": "Post-purchase review request (v2)"
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/email_templates/{email_template_id}', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "email_templates",
        "id": "15",
        "attributes": {
          "name": "Post-purchase review request (v2)"
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "email_templates",
    "id": "15",
    "attributes": {
      "name": "Post-purchase review request (v2)"
    }
  }
}

response = requests.patch('https://api.tintup.com/v2/teams/{team_id}/email_templates/{email_template_id}', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "email_templates",
    "id": "15",
    "attributes": {
      "name": "Post-purchase review request (v2)"
    }
  }
}
{
  "data": {
    "id": "15",
    "type": "email_templates",
    "attributes": {
      "name": "Post-purchase review request",
      "type": "review_solicitation",
      "locales": {
        "en": {
          "from": {
            "name": "Acme Inc.",
            "email": "reviews@example.com"
          },
          "subject": "Thanks for your review, {{ post.author.name }}",
          "body": "<p>Hi {{ post.author.name }},</p>\n<p>Thanks for reviewing us. Here's our reply:</p>\n<blockquote>{{ reply.text }}</blockquote>\n<p>The {{ team.name }} team</p>"
        },
        "fr": {
          "from": {
            "name": "Acme Inc.",
            "email": "reviews@example.com"
          },
          "subject": "Merci pour votre avis, {{ post.author.name }}",
          "body": "<p>Bonjour {{ post.author.name }},</p>\n<p>Merci pour votre avis. Voici notre réponse :</p>\n<blockquote>{{ reply.text }}</blockquote>\n<p>L'équipe {{ team.name }}</p>"
        }
      },
      "created_at": "2025-03-14T16:42:07.000Z",
      "updated_at": "2025-03-18T09:15:32.000Z"
    },
    "relationships": {
      "team": {
        "data": {
          "type": "team",
          "id": "1"
        },
        "meta": {
          "included": false
        }
      }
    }
  },
  "included": [
    {
      "id": "1",
      "type": "team",
      "attributes": {
        "name": "Acme Inc.",
        "image_url": "https://cdn.example.com/logos/acme.png",
        "url_shortener_type": "tintly",
        "onboarding": "completed",
        "shared_tags": [
          "summer",
          "ugc"
        ],
        "saml_enabled": true,
        "idp_entity_id": "https://idp.example.com/metadata",
        "idp_sso_target_url": "https://idp.example.com/sso/saml",
        "idp_cert": "-----BEGIN CERTIFICATE-----\nMIIDdzCCAl+gAwIBAgIEbGx0ZTANBgkqhkiG9w0BAQsFADBsMRAwDgYDVQQGEwdV\n-----END CERTIFICATE-----",
        "force_authn": false,
        "authn_requests_signed": false,
        "want_assertions_signed": true,
        "want_assertions_encrypted": false,
        "saml_jit_provisioning": true,
        "oidc_enabled": false,
        "oidc_identifier": "0oa1b2c3d4e5f6g7h8i9",
        "oidc_secret": "9f8e7d6c5b4a39281706f5e4d3c2b1a0",
        "oidc_scope": "openid email profile",
        "oidc_issuer": "https://login.example.com",
        "oidc_authorization_endpoint": "https://login.example.com/oauth2/v1/authorize",
        "oidc_token_endpoint": "https://login.example.com/oauth2/v1/token",
        "oidc_userinfo_endpoint": "https://login.example.com/oauth2/v1/userinfo",
        "oidc_jwks_uri": "https://login.example.com/oauth2/v1/keys",
        "plan": "tint_professional",
        "plan_expires_at": "2026-03-14T00:00:00.000Z",
        "plan_changed_at": "2025-03-14T16:42:07.000Z",
        "self_service": false,
        "rewards_platform_id": "mrc_4f7a2b9c",
        "rewards_platform_key": "7d1e3c5a9b2f4e6d8c0a1b3d5f7e9c2a",
        "permissions": [
          "moderate_tint",
          "modify_tint",
          "assets_read"
        ],
        "created_at": "2024-11-02T10:05:44.000Z",
        "updated_at": "2025-03-14T16:42:07.000Z"
      },
      "relationships": {
        "role": {
          "data": {
            "type": "role",
            "id": "3"
          }
        },
        "plan": {
          "data": {
            "type": "plan",
            "id": "1"
          }
        },
        "agent": {
          "data": {
            "type": "agent",
            "id": "7"
          }
        },
        "tints": {
          "data": [
            {
              "type": "tint",
              "id": "1"
            }
          ],
          "meta": {
            "active_tints_count": 4,
            "count": 6
          }
        },
        "social_feeds": {
          "data": [
            {
              "type": "social_feed",
              "id": "1"
            }
          ],
          "meta": {
            "active_count": 12,
            "inactive_count": 3,
            "access_error_count": 1,
            "active_social_feeds_count": 12,
            "inactive_social_feeds_count": 3
          }
        },
        "posts": {
          "data": [
            {
              "type": "post",
              "id": "1"
            }
          ],
          "meta": {
            "posts_ingested_from_beginning_of_month": 18250
          }
        },
        "assets": {
          "data": [
            {
              "type": "asset",
              "id": "1"
            }
          ],
          "meta": {
            "count": 320,
            "uploaded_count": 45,
            "total": 320,
            "uploaded_total": 45
          }
        },
        "mixes": {
          "data": [
            {
              "type": "mix",
              "id": "1"
            }
          ],
          "meta": {
            "count": 2
          }
        },
        "forms": {
          "data": [
            {
              "type": "form",
              "id": "1"
            }
          ],
          "meta": {
            "count": 5,
            "published_count": 3
          }
        },
        "personalizations": {
          "data": [
            {
              "type": "personalization",
              "id": "1"
            }
          ],
          "meta": {
            "count": 8
          }
        }
      }
    }
  ]
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}
Common

Fonts

fonts

Retrieve a list of fonts

GET
https://api.tintup.com/v2/teams/{team_id}/fonts

Retrieves the team's fonts that the user has access to.

Parameters

team_idintegerrequiredpath

The ID of the team.

pageobjectquery

Offset pagination. Use page[size] to set the number of items per page and page[number] to select a page. The response's links object contains ready-to-use URLs for the next and previous pages.

sortArray<string>id-idname-namecreated_at-created_atupdated_at-updated_at-idquery

A comma-separated list of fields to sort by. Prefix a field with - to sort in descending order. Defaults to -id (newest first).

Response

200OKobject

A page of the fonts the user has access to.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: fonts:read

Retrieve a list of fonts
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/fonts'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/fonts', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/fonts')
data = response.json()
{
  "data": [
    {
      "id": "7",
      "type": "font",
      "attributes": {
        "name": "Quicksand",
        "url": "https://storage.example.com/fonts/quicksand-regular.woff2?X-Amz-Expires=604800&X-Amz-Signature=3f9a1c0b7d",
        "format": "woff2",
        "metrics": {
          "ascent": 1000,
          "descent": -250,
          "units_per_em": 1000
        },
        "created_at": "2025-03-14T16:42:07.000Z",
        "updated_at": "2025-03-14T16:42:07.000Z"
      },
      "links": {
        "css": "https://api.tintup.com/v2/teams/1/fonts/7.css"
      }
    }
  ],
  "links": {
    "self": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=2",
    "first": "https://api.tintup.com/v2/teams/1/tints",
    "next": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=3",
    "prev": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=1"
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}

Create a font

POST
https://api.tintup.com/v2/teams/{team_id}/fonts

Creates a font from a file uploaded with the font upload endpoint. Creating a font takes three steps: create an upload, send the file to the upload's url with its headers, then call this endpoint with the upload's id as upload_id. The format and metrics are detected from the file. The new font is automatically shared with the user's role and with every role that has access to new fonts.

Body

application/vnd.api+json

The font to create.

dataNewFontrequired
Show child attributes
typestringfontrequired

The resource type.

attributesobjectrequired
Show child attributes
upload_idstringrequiredwrite only

The id of an upload created with the font upload endpoint, once the file has been uploaded to the upload's url. The upload must belong to the same team.

namestring

The font family name. Defaults to the name stored in the font file or, if it can't be read, to the uploaded file name.

Parameters

team_idintegerrequiredpath

The ID of the team.

Response

201Createdobject

The font.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: fonts:write

Create a font
curl -X POST 'https://api.tintup.com/v2/teams/{team_id}/fonts' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "font",
      "attributes": {
        "name": "Quicksand",
        "upload_id": "eyJfcmFpbHMiOnsiZGF0YSI6ODgyMTUsInB1ciI6ImJsb2JfaWQifX0=--6b1f0e3c2d9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c"
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/fonts', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "font",
        "attributes": {
          "name": "Quicksand",
          "upload_id": "eyJfcmFpbHMiOnsiZGF0YSI6ODgyMTUsInB1ciI6ImJsb2JfaWQifX0=--6b1f0e3c2d9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c"
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "font",
    "attributes": {
      "name": "Quicksand",
      "upload_id": "eyJfcmFpbHMiOnsiZGF0YSI6ODgyMTUsInB1ciI6ImJsb2JfaWQifX0=--6b1f0e3c2d9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c"
    }
  }
}

response = requests.post('https://api.tintup.com/v2/teams/{team_id}/fonts', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "font",
    "attributes": {
      "name": "Quicksand",
      "upload_id": "eyJfcmFpbHMiOnsiZGF0YSI6ODgyMTUsInB1ciI6ImJsb2JfaWQifX0=--6b1f0e3c2d9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c"
    }
  }
}
{
  "data": {
    "id": "7",
    "type": "font",
    "attributes": {
      "name": "Quicksand",
      "url": "https://storage.example.com/fonts/quicksand-regular.woff2?X-Amz-Expires=604800&X-Amz-Signature=3f9a1c0b7d",
      "format": "woff2",
      "metrics": {
        "ascent": 1000,
        "descent": -250,
        "units_per_em": 1000
      },
      "created_at": "2025-03-14T16:42:07.000Z",
      "updated_at": "2025-03-14T16:42:07.000Z"
    },
    "links": {
      "css": "https://api.tintup.com/v2/teams/1/fonts/7.css"
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Create a font upload

POST
https://api.tintup.com/v2/teams/{team_id}/fonts/upload

Starts a direct upload for a font file. Send the file's bytes to the returned url with an HTTP PUT request and the returned headers, then create the font with the upload's id as upload_id. Accepted formats are WOFF, WOFF2, TrueType, OpenType, Embedded OpenType, and SVG, up to 5 MB. Any valid access token for a member of the team can create an upload; no specific scope is checked. A missing or invalid token results in a 403.

Body

application/vnd.api+json

The file to upload.

dataNewUploadrequired
Show child attributes
typestringuploadrequired

The resource type.

attributesobjectrequired
Show child attributes
filenamestringrequired

The name of the file being uploaded.

content_typestringfont/wofffont/woff2font/ttffont/otfapplication/font-woffapplication/x-font-ttfapplication/vnd.ms-fontobjectimage/svg+xmlrequired

The MIME type of the file.

byte_sizeinteger[1, 5242880]required

The size of the file in bytes. Fonts are limited to 5 MB.

checksumstringrequired

The Base64-encoded MD5 digest of the file.

Parameters

team_idintegerrequiredpath

The ID of the team.

Response

201Createdobject

The upload. Send the file to its url, then create the font with its id as upload_id.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Create a font upload
curl -X POST 'https://api.tintup.com/v2/teams/{team_id}/fonts/upload' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "upload",
      "attributes": {
        "filename": "quicksand-regular.woff2",
        "content_type": "font/woff2",
        "byte_size": 38416,
        "checksum": "1B2M2Y8AsgTpgAmY7PhCfg=="
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/fonts/upload', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "upload",
        "attributes": {
          "filename": "quicksand-regular.woff2",
          "content_type": "font/woff2",
          "byte_size": 38416,
          "checksum": "1B2M2Y8AsgTpgAmY7PhCfg=="
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "upload",
    "attributes": {
      "filename": "quicksand-regular.woff2",
      "content_type": "font/woff2",
      "byte_size": 38416,
      "checksum": "1B2M2Y8AsgTpgAmY7PhCfg=="
    }
  }
}

response = requests.post('https://api.tintup.com/v2/teams/{team_id}/fonts/upload', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "upload",
    "attributes": {
      "filename": "quicksand-regular.woff2",
      "content_type": "font/woff2",
      "byte_size": 38416,
      "checksum": "1B2M2Y8AsgTpgAmY7PhCfg=="
    }
  }
}
{
  "data": {
    "id": "eyJfcmFpbHMiOnsiZGF0YSI6ODgyMTUsInB1ciI6ImJsb2JfaWQifX0=--6b1f0e3c2d9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c",
    "type": "upload",
    "attributes": {
      "url": "https://uploads.example.com/9f8e7d6c5b4a3f2e1d0c?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Expires=300&X-Amz-Signature=8c1d2e3f4a",
      "headers": {
        "Content-Type": "font/woff2",
        "Content-MD5": "1B2M2Y8AsgTpgAmY7PhCfg=="
      }
    }
  }
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Delete a font

DELETE
https://api.tintup.com/v2/teams/{team_id}/fonts/{font_id}

Deletes one of the team's fonts.

Parameters

team_idintegerrequiredpath

The ID of the team.

font_idintegerrequiredpath

The ID of the font.

Response

204No Content

No Content. The request succeeded and there is no response body.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: fonts:write

Delete a font
curl -X DELETE 'https://api.tintup.com/v2/teams/{team_id}/fonts/{font_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/fonts/{font_id}', {
  method: 'DELETE',
});

const data = await response.json();
import requests

response = requests.delete('https://api.tintup.com/v2/teams/{team_id}/fonts/{font_id}')
data = response.json()
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Retrieve fonts as a CSS stylesheet

GET
https://api.tintup.com/v2/teams/{team_id}/fonts/{font_ids}.css

Returns a stylesheet containing one @font-face rule per requested font, for use in a <link rel="stylesheet"> tag. This is the URL returned in each font's links.css.

Without an Authorization header the endpoint is public: team_id can be the team's ID or one of its domain names, and any of the team's fonts can be requested. With an access token, team_id must be a team ID, and the token needs the fonts:read scope.

Parameters

team_idinteger | stringrequiredpath

The ID of the team. Without an access token, it can also be the name of one of the team's custom domains, so experiences can load fonts from their own domain.

font_idsArray<integer>requiredpath

A comma-separated list of font IDs, followed by the .css extension in the path (for example 7,9.css).

Response

200OKstring

A stylesheet with one @font-face rule per requested font that was found. Requested IDs that don't match one of the team's fonts are skipped.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found. None of the requested fonts exist for the team, or the domain name doesn't match a domain.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: fonts:read

Retrieve fonts as a CSS stylesheet
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/fonts/{font_ids}.css'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/fonts/{font_ids}.css', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/fonts/{font_ids}.css')
data = response.json()
@font-face { font-family: "Quicksand"; font-style: normal; font-weight: 400; src: local("Quicksand"), url("https://storage.example.com/fonts/quicksand-regular.woff2?X-Amz-Expires=604800&X-Amz-Signature=3f9a1c0b7d"); font-display: block; }
@font-face { font-family: "Merriweather"; font-style: normal; font-weight: 400; src: local("Merriweather"), url("https://storage.example.com/fonts/merriweather-regular.ttf?X-Amz-Expires=604800&X-Amz-Signature=a41e9d27c5"); font-display: block; }
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}
Common

OAuth 2.0 Applications

oauth_applications

Retrieve a list of OAuth applications

GET
https://api.tintup.com/v2/teams/{team_id}/oauth/applications

Returns the team's OAuth applications that the current user has access to through their role. Send a valid id_token as well to get the client_secret of each application.

Parameters

team_idintegerrequiredpath

The ID of the team.

pageobjectquery

Offset pagination. Use page[size] to set the number of items per page and page[number] to select a page. The response's links object contains ready-to-use URLs for the next and previous pages.

sortstring-idquery

A comma-separated list of attributes to sort by, such as id, name, created_at or updated_at. Prefix an attribute with - to sort in descending order.

Response

200OKobject

A list of OAuth applications.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

access_tokenoauth2

OAuth 2.0 authorization code flow.

id_tokenapiKey in query

A short-lived token required, in addition to an access token, to change sensitive data. See Changes to Sensitive Data.

Retrieve a list of OAuth applications
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/oauth/applications'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/oauth/applications', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/oauth/applications')
data = response.json()
{
  "data": [
    {
      "id": "17",
      "type": "oauth_application",
      "attributes": {
        "name": "Acme Reporting",
        "redirect_uri": "https://reports.example.com/auth/callback",
        "version": 20190326,
        "client_id": "3a7c1e0b9d8f4e6a2b5c7d9e1f3a5b7c",
        "client_secret": "9f8e7d6c5b4a39281706f5e4d3c2b1a0",
        "created_at": "2025-03-14T16:42:07.000Z",
        "updated_at": "2025-03-14T16:42:07.000Z"
      }
    }
  ],
  "links": {
    "self": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=2",
    "first": "https://api.tintup.com/v2/teams/1/tints",
    "next": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=3",
    "prev": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=1"
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}

Create an OAuth application

POST
https://api.tintup.com/v2/teams/{team_id}/oauth/applications

Creates an OAuth application owned by the team. The current user's role, and every role that has access to new OAuth applications, get access to it. Send a valid id_token as well to get the client_secret in the response.

Body

application/vnd.api+json

The OAuth application to create.

dataNewOAuthApplicationrequired

The OAuth application to create.

Show child attributes
typeOAuthApplicationTypeoauth_applicationrequired

The resource type.

attributesOAuthApplicationWritableAttributes & anyrequired

Parameters

team_idintegerrequiredpath

The ID of the team.

Response

201Createdobject

The OAuth application.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

access_tokenoauth2

OAuth 2.0 authorization code flow.

id_tokenapiKey in query

A short-lived token required, in addition to an access token, to change sensitive data. See Changes to Sensitive Data.

Create an OAuth application
curl -X POST 'https://api.tintup.com/v2/teams/{team_id}/oauth/applications' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "oauth_application",
      "attributes": {
        "name": "Acme Reporting",
        "redirect_uri": "https://reports.example.com/auth/callback"
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/oauth/applications', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "oauth_application",
        "attributes": {
          "name": "Acme Reporting",
          "redirect_uri": "https://reports.example.com/auth/callback"
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "oauth_application",
    "attributes": {
      "name": "Acme Reporting",
      "redirect_uri": "https://reports.example.com/auth/callback"
    }
  }
}

response = requests.post('https://api.tintup.com/v2/teams/{team_id}/oauth/applications', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "oauth_application",
    "attributes": {
      "name": "Acme Reporting",
      "redirect_uri": "https://reports.example.com/auth/callback"
    }
  }
}
{
  "data": {
    "id": "17",
    "type": "oauth_application",
    "attributes": {
      "name": "Acme Reporting",
      "redirect_uri": "https://reports.example.com/auth/callback",
      "version": 20190326,
      "client_id": "3a7c1e0b9d8f4e6a2b5c7d9e1f3a5b7c",
      "client_secret": "9f8e7d6c5b4a39281706f5e4d3c2b1a0",
      "created_at": "2025-03-14T16:42:07.000Z",
      "updated_at": "2025-03-14T16:42:07.000Z"
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Retrieve an OAuth application

GET
https://api.tintup.com/v2/teams/{team_id}/oauth/applications/{oauth_application_id}

Retrieves one of the team's OAuth applications. Send a valid id_token as well to get the client_secret in the response.

Parameters

team_idintegerrequiredpath

The ID of the team.

oauth_application_idintegerrequiredpath

The ID of the OAuth application.

Response

200OKobject

The OAuth application.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

access_tokenoauth2

OAuth 2.0 authorization code flow.

id_tokenapiKey in query

A short-lived token required, in addition to an access token, to change sensitive data. See Changes to Sensitive Data.

Retrieve an OAuth application
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/oauth/applications/{oauth_application_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/oauth/applications/{oauth_application_id}', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/oauth/applications/{oauth_application_id}')
data = response.json()
{
  "data": {
    "id": "17",
    "type": "oauth_application",
    "attributes": {
      "name": "Acme Reporting",
      "redirect_uri": "https://reports.example.com/auth/callback",
      "version": 20190326,
      "client_id": "3a7c1e0b9d8f4e6a2b5c7d9e1f3a5b7c",
      "client_secret": "9f8e7d6c5b4a39281706f5e4d3c2b1a0",
      "created_at": "2025-03-14T16:42:07.000Z",
      "updated_at": "2025-03-14T16:42:07.000Z"
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Delete an OAuth application

DELETE
https://api.tintup.com/v2/teams/{team_id}/oauth/applications/{oauth_application_id}

Deletes the OAuth application.

Parameters

team_idintegerrequiredpath

The ID of the team.

oauth_application_idintegerrequiredpath

The ID of the OAuth application.

Response

204No Content

No Content. The request succeeded and there is no response body.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Delete an OAuth application
curl -X DELETE 'https://api.tintup.com/v2/teams/{team_id}/oauth/applications/{oauth_application_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/oauth/applications/{oauth_application_id}', {
  method: 'DELETE',
});

const data = await response.json();
import requests

response = requests.delete('https://api.tintup.com/v2/teams/{team_id}/oauth/applications/{oauth_application_id}')
data = response.json()
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Update an OAuth application

PATCH
https://api.tintup.com/v2/teams/{team_id}/oauth/applications/{oauth_application_id}

Updates the OAuth application. Send a valid id_token as well to get the client_secret in the response.

Body

application/vnd.api+json

The OAuth application attributes to change.

dataOAuthApplicationUpdaterequired

The attributes to change. Omitted attributes are left unchanged.

Show child attributes
idstring

The unique identifier of the OAuth application. Ignored; the path parameter is used instead.

typeOAuthApplicationTypeoauth_applicationrequired

The resource type.

attributesOAuthApplicationWritableAttributesrequired
Show child attributes
namestring

The name of the application, shown to users when they authorize it.

redirect_uristring

One or more redirect URIs, separated by spaces or new lines. Each must be an absolute https:// URI without a fragment.

versionoauthApplicationVersions

The API version used for requests made with this application's access tokens that don't send an API-Version header. Defaults to the API's default version when omitted on creation.

Parameters

team_idintegerrequiredpath

The ID of the team.

oauth_application_idintegerrequiredpath

The ID of the OAuth application.

Response

200OKobject

The OAuth application.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

access_tokenoauth2

OAuth 2.0 authorization code flow.

id_tokenapiKey in query

A short-lived token required, in addition to an access token, to change sensitive data. See Changes to Sensitive Data.

Update an OAuth application
curl -X PATCH 'https://api.tintup.com/v2/teams/{team_id}/oauth/applications/{oauth_application_id}' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "id": "17",
      "type": "oauth_application",
      "attributes": {
        "name": "Acme Reporting",
        "redirect_uri": "https://reports.example.com/auth/callback"
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/oauth/applications/{oauth_application_id}', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "id": "17",
        "type": "oauth_application",
        "attributes": {
          "name": "Acme Reporting",
          "redirect_uri": "https://reports.example.com/auth/callback"
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "id": "17",
    "type": "oauth_application",
    "attributes": {
      "name": "Acme Reporting",
      "redirect_uri": "https://reports.example.com/auth/callback"
    }
  }
}

response = requests.patch('https://api.tintup.com/v2/teams/{team_id}/oauth/applications/{oauth_application_id}', json=payload)
data = response.json()
Request Body
{
  "data": {
    "id": "17",
    "type": "oauth_application",
    "attributes": {
      "name": "Acme Reporting",
      "redirect_uri": "https://reports.example.com/auth/callback"
    }
  }
}
{
  "data": {
    "id": "17",
    "type": "oauth_application",
    "attributes": {
      "name": "Acme Reporting",
      "redirect_uri": "https://reports.example.com/auth/callback",
      "version": 20190326,
      "client_id": "3a7c1e0b9d8f4e6a2b5c7d9e1f3a5b7c",
      "client_secret": "9f8e7d6c5b4a39281706f5e4d3c2b1a0",
      "created_at": "2025-03-14T16:42:07.000Z",
      "updated_at": "2025-03-14T16:42:07.000Z"
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}
Common

Privacy Requests

privacy_requests

Retrieve a list of privacy requests

GET
https://api.tintup.com/v2/teams/{team_id}/privacy/requests

Parameters

team_idintegerrequiredpath

The ID of the team.

sortstring-idquery

A comma-separated list of attributes to sort by. Prefix an attribute with - to sort in descending order.

includeArray<string>teamquery

A comma-separated list of related resources to include in the response.

pageobjectquery

Offset pagination. Use page[size] to set the number of items per page and page[number] to select a page. The response's links object contains ready-to-use URLs for the next and previous pages.

Response

200OKobject

A list of privacy requests.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: privacy_requests:read

Retrieve a list of privacy requests
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/privacy/requests'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/privacy/requests', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/privacy/requests')
data = response.json()
{
  "data": [
    {
      "id": "37",
      "type": "privacy_request",
      "attributes": {
        "type": "erasure",
        "status": "pending",
        "identifier_type": "id",
        "identifier_hash": "3c1bd5494bbc5e832580d202fa3adbee31b038baebe334ab2436a3933ce468d0",
        "created_at": "2025-03-14T16:42:07.000Z",
        "updated_at": "2025-03-14T16:43:12.000Z"
      },
      "relationships": {
        "team": {
          "data": {
            "type": "team",
            "id": "1"
          },
          "meta": {
            "included": false
          }
        }
      }
    }
  ],
  "links": {
    "self": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=2",
    "first": "https://api.tintup.com/v2/teams/1/tints",
    "next": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=3",
    "prev": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=1"
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}

Create a privacy request

POST
https://api.tintup.com/v2/teams/{team_id}/privacy/requests

Creates a privacy request and processes it asynchronously. For an erasure request, the loyalty member's form submissions and assets are deleted and their community member profile is anonymized and deactivated. Poll the request until its status is success or failure.

Body

application/vnd.api+json

The privacy request to create.

dataNewPrivacyRequestrequired
Show child attributes
typestringprivacy_requestrequired
attributesobjectrequired
Show child attributes
typeprivacyRequestTypeserasurerequired

The type of privacy request. Currently, only erasure is supported.

identifier_typeprivacyRequestIdentifierTypesidrequired

The type of identifier provided. Currently, only a loyalty member id is supported.

identifierstringrequiredwrite only

The value for the chosen identifier type. Currently, this is always the ID of a loyalty member. It isn't stored; only its hash is (see identifier_hash).

Parameters

team_idintegerrequiredpath

The ID of the team.

Response

201Createdobject

The privacy request.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: privacy_requests:write

Create a privacy request
curl -X POST 'https://api.tintup.com/v2/teams/{team_id}/privacy/requests' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "privacy_request",
      "attributes": {
        "type": "erasure",
        "identifier_type": "id",
        "identifier": "65f3a1c2e4b0a91d2c7e8f10"
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/privacy/requests', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "privacy_request",
        "attributes": {
          "type": "erasure",
          "identifier_type": "id",
          "identifier": "65f3a1c2e4b0a91d2c7e8f10"
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "privacy_request",
    "attributes": {
      "type": "erasure",
      "identifier_type": "id",
      "identifier": "65f3a1c2e4b0a91d2c7e8f10"
    }
  }
}

response = requests.post('https://api.tintup.com/v2/teams/{team_id}/privacy/requests', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "privacy_request",
    "attributes": {
      "type": "erasure",
      "identifier_type": "id",
      "identifier": "65f3a1c2e4b0a91d2c7e8f10"
    }
  }
}
{
  "data": {
    "id": "37",
    "type": "privacy_request",
    "attributes": {
      "type": "erasure",
      "status": "pending",
      "identifier_type": "id",
      "identifier_hash": "3c1bd5494bbc5e832580d202fa3adbee31b038baebe334ab2436a3933ce468d0",
      "created_at": "2025-03-14T16:42:07.000Z",
      "updated_at": "2025-03-14T16:43:12.000Z"
    },
    "relationships": {
      "team": {
        "data": {
          "type": "team",
          "id": "1"
        },
        "meta": {
          "included": false
        }
      }
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Retrieve a privacy request

GET
https://api.tintup.com/v2/teams/{team_id}/privacy/requests/{privacy_request_id}

Parameters

team_idintegerrequiredpath

The ID of the team.

privacy_request_idintegerrequiredpath

The ID of the privacy request.

includeArray<string>teamquery

A comma-separated list of related resources to include in the response.

Response

200OKobject

The privacy request.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: privacy_requests:read

Retrieve a privacy request
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/privacy/requests/{privacy_request_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/privacy/requests/{privacy_request_id}', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/privacy/requests/{privacy_request_id}')
data = response.json()
{
  "data": {
    "id": "37",
    "type": "privacy_request",
    "attributes": {
      "type": "erasure",
      "status": "pending",
      "identifier_type": "id",
      "identifier_hash": "3c1bd5494bbc5e832580d202fa3adbee31b038baebe334ab2436a3933ce468d0",
      "created_at": "2025-03-14T16:42:07.000Z",
      "updated_at": "2025-03-14T16:43:12.000Z"
    },
    "relationships": {
      "team": {
        "data": {
          "type": "team",
          "id": "1"
        },
        "meta": {
          "included": false
        }
      }
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}
Common

Roles

roles

Retrieve a list of roles

GET
https://api.tintup.com/v2/teams/{team_id}/roles

Returns the team's roles.

Parameters

team_idintegerrequiredpath

The ID of the team.

includeArray<string>userstintsaccountscollectionsdomainsfontsexperiencesproduct_accountsproduct_feedspersonalizationsoauth_applicationswebhooksformsmixesquery

A comma-separated list of related resources to include in the response. Included resources are limited to those you have access to.

filterobjectquery

Filters the roles.

sortArray<string>id-idname-namecreated_at-created_atupdated_at-updated_at-idquery

A comma-separated list of attributes to sort by. Prefix an attribute with - to sort in descending order.

pageobjectquery

Offset pagination. Use page[size] to set the number of items per page and page[number] to select a page. The response's links object contains ready-to-use URLs for the next and previous pages.

Response

200OKobject

A list of roles.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: roles:read

Retrieve a list of roles
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/roles'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/roles', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/roles')
data = response.json()
{
  "data": [
    {
      "id": "3",
      "type": "role",
      "attributes": {
        "name": "Content Moderator",
        "description": "Moderates posts and manages rights requests for the brand boards.",
        "permissions": [
          "moderate_tint",
          "modify_tint",
          "assets_read",
          "replies_r",
          "replies_cu"
        ],
        "created_at": "2025-03-14T16:42:07.000Z",
        "updated_at": "2025-03-20T09:15:31.000Z"
      },
      "relationships": {
        "users": {
          "data": [
            {
              "type": "user",
              "id": "42"
            }
          ],
          "meta": {
            "count": 3
          }
        },
        "tints": {
          "data": [
            {
              "type": "tint",
              "id": "12"
            }
          ],
          "links": {
            "related": "https://api.tintup.com/v2/teams/1/roles/3/tints",
            "first": "https://api.tintup.com/v2/teams/1/roles/3/tints",
            "next": "https://api.tintup.com/v2/teams/1/roles/3/tints?page%5Bnumber%5D=2"
          },
          "meta": {
            "count": 2
          }
        },
        "accounts": {
          "data": [
            {
              "type": "account",
              "id": "3"
            }
          ],
          "links": {
            "related": "https://api.tintup.com/v2/teams/1/roles/3/accounts",
            "first": "https://api.tintup.com/v2/teams/1/roles/3/accounts",
            "next": "https://api.tintup.com/v2/teams/1/roles/3/accounts?page%5Bnumber%5D=2"
          },
          "meta": {
            "count": 1
          }
        },
        "collections": {
          "data": [
            {
              "type": "collection",
              "id": "8"
            }
          ],
          "links": {
            "related": "https://api.tintup.com/v2/teams/1/roles/3/collections",
            "first": "https://api.tintup.com/v2/teams/1/roles/3/collections",
            "next": "https://api.tintup.com/v2/teams/1/roles/3/collections?page%5Bnumber%5D=2"
          },
          "meta": {
            "count": 1
          }
        },
        "domains": {
          "data": [
            {
              "type": "domain",
              "id": "2"
            }
          ],
          "links": {
            "related": "https://api.tintup.com/v2/teams/1/roles/3/domains",
            "first": "https://api.tintup.com/v2/teams/1/roles/3/domains",
            "next": "https://api.tintup.com/v2/teams/1/roles/3/domains?page%5Bnumber%5D=2"
          },
          "meta": {
            "count": 1
          }
        },
        "fonts": {
          "data": [
            {
              "type": "font",
              "id": "5"
            }
          ],
          "links": {
            "related": "https://api.tintup.com/v2/teams/1/roles/3/fonts",
            "first": "https://api.tintup.com/v2/teams/1/roles/3/fonts",
            "next": "https://api.tintup.com/v2/teams/1/roles/3/fonts?page%5Bnumber%5D=2"
          },
          "meta": {
            "count": 1
          }
        },
        "experiences": {
          "data": [
            {
              "type": "experience",
              "id": "21"
            }
          ],
          "links": {
            "related": "https://api.tintup.com/v2/teams/1/roles/3/experiences",
            "first": "https://api.tintup.com/v2/teams/1/roles/3/experiences",
            "next": "https://api.tintup.com/v2/teams/1/roles/3/experiences?page%5Bnumber%5D=2"
          },
          "meta": {
            "count": 2
          }
        },
        "product_accounts": {
          "data": [
            {
              "type": "product_account",
              "id": "4"
            }
          ],
          "links": {
            "related": "https://api.tintup.com/v2/teams/1/roles/3/product_accounts",
            "first": "https://api.tintup.com/v2/teams/1/roles/3/product_accounts",
            "next": "https://api.tintup.com/v2/teams/1/roles/3/product_accounts?page%5Bnumber%5D=2"
          },
          "meta": {
            "count": 1
          }
        },
        "product_feeds": {
          "data": [
            {
              "type": "product_feed",
              "id": "6"
            }
          ],
          "links": {
            "related": "https://api.tintup.com/v2/teams/1/roles/3/product_feeds",
            "first": "https://api.tintup.com/v2/teams/1/roles/3/product_feeds",
            "next": "https://api.tintup.com/v2/teams/1/roles/3/product_feeds?page%5Bnumber%5D=2"
          },
          "meta": {
            "count": 1
          }
        },
        "personalizations": {
          "data": [
            {
              "type": "personalization",
              "id": "9"
            }
          ],
          "links": {
            "related": "https://api.tintup.com/v2/teams/1/roles/3/personalizations",
            "first": "https://api.tintup.com/v2/teams/1/roles/3/personalizations",
            "next": "https://api.tintup.com/v2/teams/1/roles/3/personalizations?page%5Bnumber%5D=2"
          },
          "meta": {
            "count": 1
          }
        },
        "oauth_applications": {
          "data": [
            {
              "type": "oauth_application",
              "id": "7"
            }
          ],
          "links": {
            "related": "https://api.tintup.com/v2/teams/1/roles/3/oauth_applications",
            "first": "https://api.tintup.com/v2/teams/1/roles/3/oauth_applications",
            "next": "https://api.tintup.com/v2/teams/1/roles/3/oauth_applications?page%5Bnumber%5D=2"
          },
          "meta": {
            "count": 1
          }
        },
        "webhooks": {
          "data": [
            {
              "type": "webhook",
              "id": "11"
            }
          ],
          "links": {
            "related": "https://api.tintup.com/v2/teams/1/roles/3/webhooks",
            "first": "https://api.tintup.com/v2/teams/1/roles/3/webhooks",
            "next": "https://api.tintup.com/v2/teams/1/roles/3/webhooks?page%5Bnumber%5D=2"
          },
          "meta": {
            "count": 1
          }
        },
        "forms": {
          "data": [
            {
              "type": "form",
              "id": "14"
            }
          ],
          "links": {
            "related": "https://api.tintup.com/v2/teams/1/roles/3/forms",
            "first": "https://api.tintup.com/v2/teams/1/roles/3/forms",
            "next": "https://api.tintup.com/v2/teams/1/roles/3/forms?page%5Bnumber%5D=2"
          },
          "meta": {
            "count": 1
          }
        },
        "mixes": {
          "data": [
            {
              "type": "mix",
              "id": "10"
            }
          ],
          "links": {
            "related": "https://api.tintup.com/v2/teams/1/roles/3/mixes",
            "first": "https://api.tintup.com/v2/teams/1/roles/3/mixes",
            "next": "https://api.tintup.com/v2/teams/1/roles/3/mixes?page%5Bnumber%5D=2"
          },
          "meta": {
            "count": 1
          }
        }
      }
    }
  ],
  "included": [
    {}
  ],
  "links": {
    "self": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=2",
    "first": "https://api.tintup.com/v2/teams/1/tints",
    "next": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=3",
    "prev": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=1"
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}

Create a role

POST
https://api.tintup.com/v2/teams/{team_id}/roles

Creates a role for the team.

Body

application/vnd.api+json

The role to create.

dataNewRolerequired
Show child attributes
typestringrolerequired
attributesRoleAttributes & RoleResourceAccessAttributes & objectrequired

Parameters

team_idintegerrequiredpath

The ID of the team.

Response

201Createdobject

The role.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: roles:write

Create a role
curl -X POST 'https://api.tintup.com/v2/teams/{team_id}/roles' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "role",
      "attributes": {
        "name": "Content Moderator",
        "description": "Moderates posts and manages rights requests for the brand boards.",
        "permissions": [
          "moderate_tint",
          "modify_tint",
          "assets_read"
        ],
        "tint_ids": [
          12,
          15
        ]
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/roles', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "role",
        "attributes": {
          "name": "Content Moderator",
          "description": "Moderates posts and manages rights requests for the brand boards.",
          "permissions": [
            "moderate_tint",
            "modify_tint",
            "assets_read"
          ],
          "tint_ids": [
            12,
            15
          ]
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "role",
    "attributes": {
      "name": "Content Moderator",
      "description": "Moderates posts and manages rights requests for the brand boards.",
      "permissions": [
        "moderate_tint",
        "modify_tint",
        "assets_read"
      ],
      "tint_ids": [
        12,
        15
      ]
    }
  }
}

response = requests.post('https://api.tintup.com/v2/teams/{team_id}/roles', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "role",
    "attributes": {
      "name": "Content Moderator",
      "description": "Moderates posts and manages rights requests for the brand boards.",
      "permissions": [
        "moderate_tint",
        "modify_tint",
        "assets_read"
      ],
      "tint_ids": [
        12,
        15
      ]
    }
  }
}
{
  "data": {
    "id": "3",
    "type": "role",
    "attributes": {
      "name": "Content Moderator",
      "description": "Moderates posts and manages rights requests for the brand boards.",
      "permissions": [
        "moderate_tint",
        "modify_tint",
        "assets_read",
        "replies_r",
        "replies_cu"
      ],
      "created_at": "2025-03-14T16:42:07.000Z",
      "updated_at": "2025-03-20T09:15:31.000Z"
    },
    "relationships": {
      "users": {
        "data": [
          {
            "type": "user",
            "id": "42"
          }
        ],
        "meta": {
          "count": 3
        }
      },
      "tints": {
        "data": [
          {
            "type": "tint",
            "id": "12"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/teams/1/roles/3/tints",
          "first": "https://api.tintup.com/v2/teams/1/roles/3/tints",
          "next": "https://api.tintup.com/v2/teams/1/roles/3/tints?page%5Bnumber%5D=2"
        },
        "meta": {
          "count": 2
        }
      },
      "accounts": {
        "data": [
          {
            "type": "account",
            "id": "3"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/teams/1/roles/3/accounts",
          "first": "https://api.tintup.com/v2/teams/1/roles/3/accounts",
          "next": "https://api.tintup.com/v2/teams/1/roles/3/accounts?page%5Bnumber%5D=2"
        },
        "meta": {
          "count": 1
        }
      },
      "collections": {
        "data": [
          {
            "type": "collection",
            "id": "8"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/teams/1/roles/3/collections",
          "first": "https://api.tintup.com/v2/teams/1/roles/3/collections",
          "next": "https://api.tintup.com/v2/teams/1/roles/3/collections?page%5Bnumber%5D=2"
        },
        "meta": {
          "count": 1
        }
      },
      "domains": {
        "data": [
          {
            "type": "domain",
            "id": "2"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/teams/1/roles/3/domains",
          "first": "https://api.tintup.com/v2/teams/1/roles/3/domains",
          "next": "https://api.tintup.com/v2/teams/1/roles/3/domains?page%5Bnumber%5D=2"
        },
        "meta": {
          "count": 1
        }
      },
      "fonts": {
        "data": [
          {
            "type": "font",
            "id": "5"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/teams/1/roles/3/fonts",
          "first": "https://api.tintup.com/v2/teams/1/roles/3/fonts",
          "next": "https://api.tintup.com/v2/teams/1/roles/3/fonts?page%5Bnumber%5D=2"
        },
        "meta": {
          "count": 1
        }
      },
      "experiences": {
        "data": [
          {
            "type": "experience",
            "id": "21"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/teams/1/roles/3/experiences",
          "first": "https://api.tintup.com/v2/teams/1/roles/3/experiences",
          "next": "https://api.tintup.com/v2/teams/1/roles/3/experiences?page%5Bnumber%5D=2"
        },
        "meta": {
          "count": 2
        }
      },
      "product_accounts": {
        "data": [
          {
            "type": "product_account",
            "id": "4"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/teams/1/roles/3/product_accounts",
          "first": "https://api.tintup.com/v2/teams/1/roles/3/product_accounts",
          "next": "https://api.tintup.com/v2/teams/1/roles/3/product_accounts?page%5Bnumber%5D=2"
        },
        "meta": {
          "count": 1
        }
      },
      "product_feeds": {
        "data": [
          {
            "type": "product_feed",
            "id": "6"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/teams/1/roles/3/product_feeds",
          "first": "https://api.tintup.com/v2/teams/1/roles/3/product_feeds",
          "next": "https://api.tintup.com/v2/teams/1/roles/3/product_feeds?page%5Bnumber%5D=2"
        },
        "meta": {
          "count": 1
        }
      },
      "personalizations": {
        "data": [
          {
            "type": "personalization",
            "id": "9"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/teams/1/roles/3/personalizations",
          "first": "https://api.tintup.com/v2/teams/1/roles/3/personalizations",
          "next": "https://api.tintup.com/v2/teams/1/roles/3/personalizations?page%5Bnumber%5D=2"
        },
        "meta": {
          "count": 1
        }
      },
      "oauth_applications": {
        "data": [
          {
            "type": "oauth_application",
            "id": "7"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/teams/1/roles/3/oauth_applications",
          "first": "https://api.tintup.com/v2/teams/1/roles/3/oauth_applications",
          "next": "https://api.tintup.com/v2/teams/1/roles/3/oauth_applications?page%5Bnumber%5D=2"
        },
        "meta": {
          "count": 1
        }
      },
      "webhooks": {
        "data": [
          {
            "type": "webhook",
            "id": "11"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/teams/1/roles/3/webhooks",
          "first": "https://api.tintup.com/v2/teams/1/roles/3/webhooks",
          "next": "https://api.tintup.com/v2/teams/1/roles/3/webhooks?page%5Bnumber%5D=2"
        },
        "meta": {
          "count": 1
        }
      },
      "forms": {
        "data": [
          {
            "type": "form",
            "id": "14"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/teams/1/roles/3/forms",
          "first": "https://api.tintup.com/v2/teams/1/roles/3/forms",
          "next": "https://api.tintup.com/v2/teams/1/roles/3/forms?page%5Bnumber%5D=2"
        },
        "meta": {
          "count": 1
        }
      },
      "mixes": {
        "data": [
          {
            "type": "mix",
            "id": "10"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/teams/1/roles/3/mixes",
          "first": "https://api.tintup.com/v2/teams/1/roles/3/mixes",
          "next": "https://api.tintup.com/v2/teams/1/roles/3/mixes?page%5Bnumber%5D=2"
        },
        "meta": {
          "count": 1
        }
      }
    }
  },
  "included": [
    {}
  ]
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Retrieve a role

GET
https://api.tintup.com/v2/teams/{team_id}/roles/{role_id}

Retrieves one of the team's roles.

Parameters

team_idintegerrequiredpath

The ID of the team.

role_idintegerrequiredpath

The ID of the role.

includeArray<string>userstintsaccountscollectionsdomainsfontsexperiencesproduct_accountsproduct_feedspersonalizationsoauth_applicationswebhooksformsmixesquery

A comma-separated list of related resources to include in the response. Included resources are limited to those you have access to.

Response

200OKobject

The role.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: roles:read

Retrieve a role
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/roles/{role_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/roles/{role_id}', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/roles/{role_id}')
data = response.json()
{
  "data": {
    "id": "3",
    "type": "role",
    "attributes": {
      "name": "Content Moderator",
      "description": "Moderates posts and manages rights requests for the brand boards.",
      "permissions": [
        "moderate_tint",
        "modify_tint",
        "assets_read",
        "replies_r",
        "replies_cu"
      ],
      "created_at": "2025-03-14T16:42:07.000Z",
      "updated_at": "2025-03-20T09:15:31.000Z"
    },
    "relationships": {
      "users": {
        "data": [
          {
            "type": "user",
            "id": "42"
          }
        ],
        "meta": {
          "count": 3
        }
      },
      "tints": {
        "data": [
          {
            "type": "tint",
            "id": "12"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/teams/1/roles/3/tints",
          "first": "https://api.tintup.com/v2/teams/1/roles/3/tints",
          "next": "https://api.tintup.com/v2/teams/1/roles/3/tints?page%5Bnumber%5D=2"
        },
        "meta": {
          "count": 2
        }
      },
      "accounts": {
        "data": [
          {
            "type": "account",
            "id": "3"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/teams/1/roles/3/accounts",
          "first": "https://api.tintup.com/v2/teams/1/roles/3/accounts",
          "next": "https://api.tintup.com/v2/teams/1/roles/3/accounts?page%5Bnumber%5D=2"
        },
        "meta": {
          "count": 1
        }
      },
      "collections": {
        "data": [
          {
            "type": "collection",
            "id": "8"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/teams/1/roles/3/collections",
          "first": "https://api.tintup.com/v2/teams/1/roles/3/collections",
          "next": "https://api.tintup.com/v2/teams/1/roles/3/collections?page%5Bnumber%5D=2"
        },
        "meta": {
          "count": 1
        }
      },
      "domains": {
        "data": [
          {
            "type": "domain",
            "id": "2"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/teams/1/roles/3/domains",
          "first": "https://api.tintup.com/v2/teams/1/roles/3/domains",
          "next": "https://api.tintup.com/v2/teams/1/roles/3/domains?page%5Bnumber%5D=2"
        },
        "meta": {
          "count": 1
        }
      },
      "fonts": {
        "data": [
          {
            "type": "font",
            "id": "5"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/teams/1/roles/3/fonts",
          "first": "https://api.tintup.com/v2/teams/1/roles/3/fonts",
          "next": "https://api.tintup.com/v2/teams/1/roles/3/fonts?page%5Bnumber%5D=2"
        },
        "meta": {
          "count": 1
        }
      },
      "experiences": {
        "data": [
          {
            "type": "experience",
            "id": "21"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/teams/1/roles/3/experiences",
          "first": "https://api.tintup.com/v2/teams/1/roles/3/experiences",
          "next": "https://api.tintup.com/v2/teams/1/roles/3/experiences?page%5Bnumber%5D=2"
        },
        "meta": {
          "count": 2
        }
      },
      "product_accounts": {
        "data": [
          {
            "type": "product_account",
            "id": "4"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/teams/1/roles/3/product_accounts",
          "first": "https://api.tintup.com/v2/teams/1/roles/3/product_accounts",
          "next": "https://api.tintup.com/v2/teams/1/roles/3/product_accounts?page%5Bnumber%5D=2"
        },
        "meta": {
          "count": 1
        }
      },
      "product_feeds": {
        "data": [
          {
            "type": "product_feed",
            "id": "6"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/teams/1/roles/3/product_feeds",
          "first": "https://api.tintup.com/v2/teams/1/roles/3/product_feeds",
          "next": "https://api.tintup.com/v2/teams/1/roles/3/product_feeds?page%5Bnumber%5D=2"
        },
        "meta": {
          "count": 1
        }
      },
      "personalizations": {
        "data": [
          {
            "type": "personalization",
            "id": "9"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/teams/1/roles/3/personalizations",
          "first": "https://api.tintup.com/v2/teams/1/roles/3/personalizations",
          "next": "https://api.tintup.com/v2/teams/1/roles/3/personalizations?page%5Bnumber%5D=2"
        },
        "meta": {
          "count": 1
        }
      },
      "oauth_applications": {
        "data": [
          {
            "type": "oauth_application",
            "id": "7"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/teams/1/roles/3/oauth_applications",
          "first": "https://api.tintup.com/v2/teams/1/roles/3/oauth_applications",
          "next": "https://api.tintup.com/v2/teams/1/roles/3/oauth_applications?page%5Bnumber%5D=2"
        },
        "meta": {
          "count": 1
        }
      },
      "webhooks": {
        "data": [
          {
            "type": "webhook",
            "id": "11"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/teams/1/roles/3/webhooks",
          "first": "https://api.tintup.com/v2/teams/1/roles/3/webhooks",
          "next": "https://api.tintup.com/v2/teams/1/roles/3/webhooks?page%5Bnumber%5D=2"
        },
        "meta": {
          "count": 1
        }
      },
      "forms": {
        "data": [
          {
            "type": "form",
            "id": "14"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/teams/1/roles/3/forms",
          "first": "https://api.tintup.com/v2/teams/1/roles/3/forms",
          "next": "https://api.tintup.com/v2/teams/1/roles/3/forms?page%5Bnumber%5D=2"
        },
        "meta": {
          "count": 1
        }
      },
      "mixes": {
        "data": [
          {
            "type": "mix",
            "id": "10"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/teams/1/roles/3/mixes",
          "first": "https://api.tintup.com/v2/teams/1/roles/3/mixes",
          "next": "https://api.tintup.com/v2/teams/1/roles/3/mixes?page%5Bnumber%5D=2"
        },
        "meta": {
          "count": 1
        }
      }
    }
  },
  "included": [
    {}
  ]
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Delete a role

DELETE
https://api.tintup.com/v2/teams/{team_id}/roles/{role_id}

Deletes the role. Team members who are assigned the role are removed from the team along with it.

Parameters

team_idintegerrequiredpath

The ID of the team.

role_idintegerrequiredpath

The ID of the role.

Response

204No Content

No Content. The request succeeded and there is no response body.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: roles:write

Delete a role
curl -X DELETE 'https://api.tintup.com/v2/teams/{team_id}/roles/{role_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/roles/{role_id}', {
  method: 'DELETE',
});

const data = await response.json();
import requests

response = requests.delete('https://api.tintup.com/v2/teams/{team_id}/roles/{role_id}')
data = response.json()
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Update a role

PATCH
https://api.tintup.com/v2/teams/{team_id}/roles/{role_id}

Updates the role.

Body

application/vnd.api+json

The attributes of the role to change.

dataRoleUpdaterequired
Show child attributes
idstring

The ID of the role. Optional; the role is identified by the URL.

typestringrolerequired
attributesRoleAttributes & RoleResourceAccessAttributesrequired

The attributes to change. Attributes that are omitted are left unchanged.

Parameters

team_idintegerrequiredpath

The ID of the team.

role_idintegerrequiredpath

The ID of the role.

Response

200OKobject

The role.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: roles:write

Update a role
curl -X PATCH 'https://api.tintup.com/v2/teams/{team_id}/roles/{role_id}' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "id": "3",
      "type": "role",
      "attributes": {
        "permissions": [
          "moderate_tint",
          "modify_tint",
          "assets_read",
          "replies_r"
        ],
        "tint_ids": {
          "+": [
            18
          ],
          "-": [
            12
          ]
        }
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/roles/{role_id}', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "id": "3",
        "type": "role",
        "attributes": {
          "permissions": [
            "moderate_tint",
            "modify_tint",
            "assets_read",
            "replies_r"
          ],
          "tint_ids": {
            "+": [
              18
            ],
            "-": [
              12
            ]
          }
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "id": "3",
    "type": "role",
    "attributes": {
      "permissions": [
        "moderate_tint",
        "modify_tint",
        "assets_read",
        "replies_r"
      ],
      "tint_ids": {
        "+": [
          18
        ],
        "-": [
          12
        ]
      }
    }
  }
}

response = requests.patch('https://api.tintup.com/v2/teams/{team_id}/roles/{role_id}', json=payload)
data = response.json()
Request Body
{
  "data": {
    "id": "3",
    "type": "role",
    "attributes": {
      "permissions": [
        "moderate_tint",
        "modify_tint",
        "assets_read",
        "replies_r"
      ],
      "tint_ids": {
        "+": [
          18
        ],
        "-": [
          12
        ]
      }
    }
  }
}
{
  "data": {
    "id": "3",
    "type": "role",
    "attributes": {
      "name": "Content Moderator",
      "description": "Moderates posts and manages rights requests for the brand boards.",
      "permissions": [
        "moderate_tint",
        "modify_tint",
        "assets_read",
        "replies_r",
        "replies_cu"
      ],
      "created_at": "2025-03-14T16:42:07.000Z",
      "updated_at": "2025-03-20T09:15:31.000Z"
    },
    "relationships": {
      "users": {
        "data": [
          {
            "type": "user",
            "id": "42"
          }
        ],
        "meta": {
          "count": 3
        }
      },
      "tints": {
        "data": [
          {
            "type": "tint",
            "id": "12"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/teams/1/roles/3/tints",
          "first": "https://api.tintup.com/v2/teams/1/roles/3/tints",
          "next": "https://api.tintup.com/v2/teams/1/roles/3/tints?page%5Bnumber%5D=2"
        },
        "meta": {
          "count": 2
        }
      },
      "accounts": {
        "data": [
          {
            "type": "account",
            "id": "3"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/teams/1/roles/3/accounts",
          "first": "https://api.tintup.com/v2/teams/1/roles/3/accounts",
          "next": "https://api.tintup.com/v2/teams/1/roles/3/accounts?page%5Bnumber%5D=2"
        },
        "meta": {
          "count": 1
        }
      },
      "collections": {
        "data": [
          {
            "type": "collection",
            "id": "8"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/teams/1/roles/3/collections",
          "first": "https://api.tintup.com/v2/teams/1/roles/3/collections",
          "next": "https://api.tintup.com/v2/teams/1/roles/3/collections?page%5Bnumber%5D=2"
        },
        "meta": {
          "count": 1
        }
      },
      "domains": {
        "data": [
          {
            "type": "domain",
            "id": "2"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/teams/1/roles/3/domains",
          "first": "https://api.tintup.com/v2/teams/1/roles/3/domains",
          "next": "https://api.tintup.com/v2/teams/1/roles/3/domains?page%5Bnumber%5D=2"
        },
        "meta": {
          "count": 1
        }
      },
      "fonts": {
        "data": [
          {
            "type": "font",
            "id": "5"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/teams/1/roles/3/fonts",
          "first": "https://api.tintup.com/v2/teams/1/roles/3/fonts",
          "next": "https://api.tintup.com/v2/teams/1/roles/3/fonts?page%5Bnumber%5D=2"
        },
        "meta": {
          "count": 1
        }
      },
      "experiences": {
        "data": [
          {
            "type": "experience",
            "id": "21"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/teams/1/roles/3/experiences",
          "first": "https://api.tintup.com/v2/teams/1/roles/3/experiences",
          "next": "https://api.tintup.com/v2/teams/1/roles/3/experiences?page%5Bnumber%5D=2"
        },
        "meta": {
          "count": 2
        }
      },
      "product_accounts": {
        "data": [
          {
            "type": "product_account",
            "id": "4"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/teams/1/roles/3/product_accounts",
          "first": "https://api.tintup.com/v2/teams/1/roles/3/product_accounts",
          "next": "https://api.tintup.com/v2/teams/1/roles/3/product_accounts?page%5Bnumber%5D=2"
        },
        "meta": {
          "count": 1
        }
      },
      "product_feeds": {
        "data": [
          {
            "type": "product_feed",
            "id": "6"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/teams/1/roles/3/product_feeds",
          "first": "https://api.tintup.com/v2/teams/1/roles/3/product_feeds",
          "next": "https://api.tintup.com/v2/teams/1/roles/3/product_feeds?page%5Bnumber%5D=2"
        },
        "meta": {
          "count": 1
        }
      },
      "personalizations": {
        "data": [
          {
            "type": "personalization",
            "id": "9"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/teams/1/roles/3/personalizations",
          "first": "https://api.tintup.com/v2/teams/1/roles/3/personalizations",
          "next": "https://api.tintup.com/v2/teams/1/roles/3/personalizations?page%5Bnumber%5D=2"
        },
        "meta": {
          "count": 1
        }
      },
      "oauth_applications": {
        "data": [
          {
            "type": "oauth_application",
            "id": "7"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/teams/1/roles/3/oauth_applications",
          "first": "https://api.tintup.com/v2/teams/1/roles/3/oauth_applications",
          "next": "https://api.tintup.com/v2/teams/1/roles/3/oauth_applications?page%5Bnumber%5D=2"
        },
        "meta": {
          "count": 1
        }
      },
      "webhooks": {
        "data": [
          {
            "type": "webhook",
            "id": "11"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/teams/1/roles/3/webhooks",
          "first": "https://api.tintup.com/v2/teams/1/roles/3/webhooks",
          "next": "https://api.tintup.com/v2/teams/1/roles/3/webhooks?page%5Bnumber%5D=2"
        },
        "meta": {
          "count": 1
        }
      },
      "forms": {
        "data": [
          {
            "type": "form",
            "id": "14"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/teams/1/roles/3/forms",
          "first": "https://api.tintup.com/v2/teams/1/roles/3/forms",
          "next": "https://api.tintup.com/v2/teams/1/roles/3/forms?page%5Bnumber%5D=2"
        },
        "meta": {
          "count": 1
        }
      },
      "mixes": {
        "data": [
          {
            "type": "mix",
            "id": "10"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/teams/1/roles/3/mixes",
          "first": "https://api.tintup.com/v2/teams/1/roles/3/mixes",
          "next": "https://api.tintup.com/v2/teams/1/roles/3/mixes?page%5Bnumber%5D=2"
        },
        "meta": {
          "count": 1
        }
      }
    }
  },
  "included": [
    {}
  ]
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}
Common

Subaccounts

subaccounts

A subaccount is an account that can be accessed directly using the specified account credentials, such as an Instagram business or creator account or a Facebook page.

Retrieve a list of subaccounts for an account

GET
https://api.tintup.com/v2/teams/{team_id}/accounts/{account_id}/subaccounts

Returns the pages, organizations, channels, boards, etc. that can be accessed with the account, sorted by ID. Subaccounts are refreshed from the source whenever the account is authenticated.

Parameters

team_idintegerrequiredpath

The ID of the team.

account_idintegerrequiredpath

The ID of the account.

filterobjectquery

Filters the list of subaccounts. All filters are combined with AND.

pageobjectquery

Offset pagination. Use page[size] to set the number of items per page and page[number] to select a page. The response's links object contains ready-to-use URLs for the next and previous pages.

Response

200OKobject

A list of subaccounts.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: accounts:read

Retrieve a list of subaccounts for an account
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/accounts/{account_id}/subaccounts'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/accounts/{account_id}/subaccounts', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/accounts/{account_id}/subaccounts')
data = response.json()
{
  "data": [
    {
      "id": "17841401839964064",
      "type": "subaccount",
      "attributes": {
        "type": "page",
        "name": "Acme Inc.",
        "username": "acme",
        "biography": "Outdoor gear for every adventure.",
        "image_url": "https://cdn.example.com/avatars/acme.jpg",
        "url": "https://www.instagram.com/acme",
        "capabilities": [
          "ingest",
          "compose"
        ],
        "meta": {},
        "followers_count": 12840,
        "follows_count": 312,
        "media_count": 587
      },
      "relationships": {
        "account": {
          "data": {
            "id": "4821",
            "type": "account"
          },
          "meta": {
            "included": false
          }
        }
      }
    }
  ],
  "links": {
    "self": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=2",
    "first": "https://api.tintup.com/v2/teams/1/tints",
    "next": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=3",
    "prev": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=1"
  }
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Retrieve a list of subaccounts

GET
https://api.tintup.com/v2/teams/{team_id}/subaccounts

Parameters

team_idintegerrequiredpath

The ID of the team.

filterobjectquery
pageobjectquery

Offset pagination. Use page[size] to set the number of items per page and page[number] to select a page. The response's links object contains ready-to-use URLs for the next and previous pages.

Response

200OKobject

A list of subaccounts.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: accounts:read

Retrieve a list of subaccounts
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/subaccounts'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/subaccounts', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/subaccounts')
data = response.json()
200
{
  "data": [
    {
      "id": "17841401839964064",
      "type": "subaccount",
      "attributes": {
        "type": "page",
        "name": "Acme Inc.",
        "username": "acme",
        "biography": "Outdoor gear for every adventure.",
        "image_url": "https://cdn.example.com/avatars/acme.jpg",
        "url": "https://www.instagram.com/acme",
        "capabilities": [
          "ingest",
          "compose"
        ],
        "meta": {},
        "followers_count": 12840,
        "follows_count": 312,
        "media_count": 587
      },
      "relationships": {
        "account": {
          "data": {
            "id": "4821",
            "type": "account"
          },
          "meta": {
            "included": false
          }
        }
      }
    }
  ],
  "links": {
    "self": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=2",
    "first": "https://api.tintup.com/v2/teams/1/tints",
    "next": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=3",
    "prev": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=1"
  }
}
Common

Team Users

team_users

Retrieve my user

GET
https://api.tintup.com/v2/me

Returns the user who owns the access token.

Parameters

includeArray<string>authentication_factorsteamsteams.rolequery

A comma-separated list of related resources to include in the response.

Response

200OKobject

The authenticated user.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: identity

Retrieve my user
curl -X GET 'https://api.tintup.com/v2/me'
const response = await fetch('https://api.tintup.com/v2/me', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/me')
data = response.json()
{
  "data": {
    "id": "42",
    "type": "user",
    "attributes": {
      "first_name": "Jane",
      "last_name": "Doe",
      "organization": "Acme Inc.",
      "image_url": "https://cdn.example.com/avatars/jane-doe.png",
      "email": "jane.doe@example.com",
      "default_authentication_factor_id": 5,
      "temporary_support_access_ends_at": "2025-03-21T16:42:07.000Z",
      "created_at": "2024-11-02T10:05:44.000Z",
      "updated_at": "2025-03-14T16:42:07.000Z"
    },
    "relationships": {
      "authentication_factors": {
        "data": [
          {
            "type": "authentication_factor",
            "id": "5"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/authentication_factors"
        }
      },
      "teams": {
        "data": [
          {
            "type": "team",
            "id": "1"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/teams"
        }
      }
    },
    "links": {
      "self": "https://api.tintup.com/v2/me"
    }
  },
  "included": [
    {}
  ]
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}

Update my user

PATCH
https://api.tintup.com/v2/me

Updates the user who owns the access token. Changing the email or password attributes, or setting temporary_support_access_ends_at, additionally requires a valid ID token for the current access token, passed in the id_token query parameter; otherwise, the request fails with a 403 Forbidden error (code 4030002). A security email is sent to the user when their email or password is changed or when support access is granted.

Body

application/vnd.api+json

The attributes of the authenticated user to change.

dataMeUpdaterequired
Show child attributes
idstring

The ID of the user. Optional; the user is always the owner of the access token.

typestringuserrequired
attributesUserAttributes & MeAttributes & objectrequired

The attributes to change. Attributes that are omitted are left unchanged. Changing email or password, or setting temporary_support_access_ends_at, requires an id_token.

Response

200OKobject

The authenticated user.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: identity:write

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: identity:write

id_tokenapiKey in query

A short-lived token required, in addition to an access token, to change sensitive data. See Changes to Sensitive Data.

Update my user
curl -X PATCH 'https://api.tintup.com/v2/me' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "user",
      "attributes": {
        "first_name": "Jane",
        "last_name": "Doe",
        "organization": "Acme Inc."
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/me', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "user",
        "attributes": {
          "first_name": "Jane",
          "last_name": "Doe",
          "organization": "Acme Inc."
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "user",
    "attributes": {
      "first_name": "Jane",
      "last_name": "Doe",
      "organization": "Acme Inc."
    }
  }
}

response = requests.patch('https://api.tintup.com/v2/me', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "user",
    "attributes": {
      "first_name": "Jane",
      "last_name": "Doe",
      "organization": "Acme Inc."
    }
  }
}
{
  "data": {
    "id": "42",
    "type": "user",
    "attributes": {
      "first_name": "Jane",
      "last_name": "Doe",
      "organization": "Acme Inc.",
      "image_url": "https://cdn.example.com/avatars/jane-doe.png",
      "email": "jane.doe@example.com",
      "default_authentication_factor_id": 5,
      "temporary_support_access_ends_at": "2025-03-21T16:42:07.000Z",
      "created_at": "2024-11-02T10:05:44.000Z",
      "updated_at": "2025-03-14T16:42:07.000Z"
    },
    "relationships": {
      "authentication_factors": {
        "data": [
          {
            "type": "authentication_factor",
            "id": "5"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/authentication_factors"
        }
      },
      "teams": {
        "data": [
          {
            "type": "team",
            "id": "1"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/teams"
        }
      }
    },
    "links": {
      "self": "https://api.tintup.com/v2/me"
    }
  },
  "included": [
    {}
  ]
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Retrieve a list of users

GET
https://api.tintup.com/v2/teams/{team_id}/users

Returns the members of the team.

Parameters

team_idintegerrequiredpath

The ID of the team.

includeArray<string>rolequery

A comma-separated list of related resources to include in the response.

filterobjectquery

Filters the team's users. email, first_name and last_name are exact matches and are combined; the other filters are combined with them.

sortArray<string>id-idcreated_at-created_atupdated_at-updated_atskip_idp-skip_idp-idquery

A comma-separated list of attributes to sort by. Prefix an attribute with - to sort in descending order. id sorts by the order in which users were added to the team.

pageobjectquery

Offset pagination. Use page[size] to set the number of items per page and page[number] to select a page. The response's links object contains ready-to-use URLs for the next and previous pages.

Response

200OKobject

A list of team users.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: users:read

Retrieve a list of users
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/users'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/users', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/users')
data = response.json()
{
  "data": [
    {
      "id": "42",
      "type": "user",
      "attributes": {
        "first_name": "Jane",
        "last_name": "Doe",
        "organization": "Acme Inc.",
        "image_url": "https://cdn.example.com/avatars/jane-doe.png",
        "email": "jane.doe@example.com",
        "skip_idp": false,
        "created_at": "2025-01-08T13:22:10.000Z",
        "updated_at": "2025-03-14T16:42:07.000Z"
      },
      "relationships": {
        "role": {
          "data": {
            "type": "role",
            "id": "3"
          }
        }
      }
    }
  ],
  "included": [
    {}
  ],
  "links": {
    "self": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=2",
    "first": "https://api.tintup.com/v2/teams/1/tints",
    "next": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=3",
    "prev": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=1"
  },
  "meta": {
    "total": 12
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}

Invite users to a team

POST
https://api.tintup.com/v2/teams/{team_id}/users

Invites a single user (application/vnd.api+json with a single resource object) or multiple users (application/vnd.api+json; ext=bulk with an array of resource objects) to the team, and emails them an invitation. An account is created for email addresses that don't have one yet. The response contains a single user or an array of users accordingly.

Body

application/vnd.api+json

The user to invite, or, with the ext=bulk media type, an array of users to invite. When any of the users is invalid, none are invited.

application/vnd.api+jsonobject
dataNewTeamUserrequired
Show child attributes
typestringuserrequired
attributesTeamUserMembershipAttributes & TeamUserRoleId & objectrequired
application/vnd.api+json; ext=bulkobject
dataArray<NewTeamUser>required
Show child attributes
typestringuserrequired
attributesTeamUserMembershipAttributes & TeamUserRoleId & objectrequired

Parameters

team_idintegerrequiredpath

The ID of the team.

Response

201Createdobject

The invited user, or an array of the invited users when the request contained an array of resource objects.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

402Payment Requiredx-errors

Payment Required. Inviting the users would exceed the number of users allowed by the team's plan.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: users:write

Invite users to a team
curl -X POST 'https://api.tintup.com/v2/teams/{team_id}/users' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "user",
      "attributes": {
        "email": "john.smith@example.com",
        "role_id": 3
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/users', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "user",
        "attributes": {
          "email": "john.smith@example.com",
          "role_id": 3
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "user",
    "attributes": {
      "email": "john.smith@example.com",
      "role_id": 3
    }
  }
}

response = requests.post('https://api.tintup.com/v2/teams/{team_id}/users', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "user",
    "attributes": {
      "email": "john.smith@example.com",
      "role_id": 3
    }
  }
}
{
  "data": [
    {
      "type": "user",
      "attributes": {
        "email": "john.smith@example.com",
        "role_id": 3
      }
    },
    {
      "type": "user",
      "attributes": {
        "email": "maria.garcia@example.com",
        "role_id": 4,
        "skip_idp": true
      }
    }
  ]
}
{
  "data": {
    "id": "42",
    "type": "user",
    "attributes": {
      "first_name": "Jane",
      "last_name": "Doe",
      "organization": "Acme Inc.",
      "image_url": "https://cdn.example.com/avatars/jane-doe.png",
      "email": "jane.doe@example.com",
      "skip_idp": false,
      "created_at": "2025-01-08T13:22:10.000Z",
      "updated_at": "2025-03-14T16:42:07.000Z"
    },
    "relationships": {
      "role": {
        "data": {
          "type": "role",
          "id": "3"
        }
      }
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4020001",
      "title": "Payment Required",
      "status": "402",
      "detail": "You have exceeded your plan's limit of 10"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Remove multiple users from a team

DELETE
https://api.tintup.com/v2/teams/{team_id}/users

The authenticated user can't remove themselves and is skipped, as are users that aren't members of the team.

Body

application/vnd.api+json; ext=bulk

The users to remove from the team.

dataArray<TeamUserIdentifier>required
Show child attributes
idstringrequired

The ID of the user.

typestringuserrequired

Parameters

team_idintegerrequiredpath

The ID of the team.

Response

204No Content

No Content. The request succeeded and there is no response body.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: users:write

Remove multiple users from a team
curl -X DELETE 'https://api.tintup.com/v2/teams/{team_id}/users' \
  -H 'Content-Type: application/vnd.api+json; ext=bulk' \
  -d '{
    "data": [
      {
        "id": "42",
        "type": "user"
      },
      {
        "id": "57",
        "type": "user"
      }
    ]
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/users', {
  method: 'DELETE',
  headers: {
    'Content-Type': 'application/vnd.api+json; ext=bulk',
  },
  body: JSON.stringify({
      "data": [
        {
          "id": "42",
          "type": "user"
        },
        {
          "id": "57",
          "type": "user"
        }
      ]
    }),
});

const data = await response.json();
import requests

payload = {
  "data": [
    {
      "id": "42",
      "type": "user"
    },
    {
      "id": "57",
      "type": "user"
    }
  ]
}

response = requests.delete('https://api.tintup.com/v2/teams/{team_id}/users', json=payload)
data = response.json()
Request Body
{
  "data": [
    {
      "id": "42",
      "type": "user"
    },
    {
      "id": "57",
      "type": "user"
    }
  ]
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Update multiple users

PATCH
https://api.tintup.com/v2/teams/{team_id}/users

Updates the role and skip_idp attribute of several team members at once. Users that aren't members of the team are skipped, and you can't update yourself. PUT is also accepted.

Body

application/vnd.api+json; ext=bulk

The users to update. When any of the users is invalid, none are updated.

dataArray<TeamUserUpdate>required
Show child attributes
idstringrequired

The ID of the user. Required in bulk updates to identify the user; ignored when updating a single user, which is identified by the URL.

typestringuserrequired
attributesTeamUserMembershipAttributes & TeamUserRoleIdrequired

The attributes to change. Attributes that are omitted are left unchanged.

Parameters

team_idintegerrequiredpath

The ID of the team.

Response

200OKobject

The updated team users.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: users:write

Update multiple users
curl -X PATCH 'https://api.tintup.com/v2/teams/{team_id}/users' \
  -H 'Content-Type: application/vnd.api+json; ext=bulk' \
  -d '{
    "data": [
      {
        "id": "42",
        "type": "user",
        "attributes": {
          "role_id": 4
        }
      },
      {
        "id": "57",
        "type": "user",
        "attributes": {
          "skip_idp": true
        }
      }
    ]
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/users', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/vnd.api+json; ext=bulk',
  },
  body: JSON.stringify({
      "data": [
        {
          "id": "42",
          "type": "user",
          "attributes": {
            "role_id": 4
          }
        },
        {
          "id": "57",
          "type": "user",
          "attributes": {
            "skip_idp": true
          }
        }
      ]
    }),
});

const data = await response.json();
import requests

payload = {
  "data": [
    {
      "id": "42",
      "type": "user",
      "attributes": {
        "role_id": 4
      }
    },
    {
      "id": "57",
      "type": "user",
      "attributes": {
        "skip_idp": True
      }
    }
  ]
}

response = requests.patch('https://api.tintup.com/v2/teams/{team_id}/users', json=payload)
data = response.json()
Request Body
{
  "data": [
    {
      "id": "42",
      "type": "user",
      "attributes": {
        "role_id": 4
      }
    },
    {
      "id": "57",
      "type": "user",
      "attributes": {
        "skip_idp": true
      }
    }
  ]
}
{
  "data": [
    {
      "id": "42",
      "type": "user",
      "attributes": {
        "first_name": "Jane",
        "last_name": "Doe",
        "organization": "Acme Inc.",
        "image_url": "https://cdn.example.com/avatars/jane-doe.png",
        "email": "jane.doe@example.com",
        "skip_idp": false,
        "created_at": "2025-01-08T13:22:10.000Z",
        "updated_at": "2025-03-14T16:42:07.000Z"
      },
      "relationships": {
        "role": {
          "data": {
            "type": "role",
            "id": "3"
          }
        }
      }
    }
  ]
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Retrieve a user

GET
https://api.tintup.com/v2/teams/{team_id}/users/{user_id}

Returns a member of the team.

Parameters

team_idintegerrequiredpath

The ID of the team.

user_idintegerrequiredpath

The ID of the user.

includeArray<string>rolequery

A comma-separated list of related resources to include in the response.

Response

200OKobject

The team user.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: users:read

Retrieve a user
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/users/{user_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/users/{user_id}', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/users/{user_id}')
data = response.json()
{
  "data": {
    "id": "42",
    "type": "user",
    "attributes": {
      "first_name": "Jane",
      "last_name": "Doe",
      "organization": "Acme Inc.",
      "image_url": "https://cdn.example.com/avatars/jane-doe.png",
      "email": "jane.doe@example.com",
      "skip_idp": false,
      "created_at": "2025-01-08T13:22:10.000Z",
      "updated_at": "2025-03-14T16:42:07.000Z"
    },
    "relationships": {
      "role": {
        "data": {
          "type": "role",
          "id": "3"
        }
      }
    }
  },
  "included": [
    {}
  ]
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Remove a user from a team

DELETE
https://api.tintup.com/v2/teams/{team_id}/users/{user_id}

The authenticated user can't remove themselves.

Parameters

team_idintegerrequiredpath

The ID of the team.

user_idintegerrequiredpath

The ID of the user.

Response

204No Content

No Content. The request succeeded and there is no response body.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: users:write

Remove a user from a team
curl -X DELETE 'https://api.tintup.com/v2/teams/{team_id}/users/{user_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/users/{user_id}', {
  method: 'DELETE',
});

const data = await response.json();
import requests

response = requests.delete('https://api.tintup.com/v2/teams/{team_id}/users/{user_id}')
data = response.json()
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Update a user

PATCH
https://api.tintup.com/v2/teams/{team_id}/users/{user_id}

Updates the role and skip_idp attribute of a team member. You can't update yourself.

Body

application/vnd.api+json

The membership attributes of the user to change.

dataTeamUserUpdaterequired
Show child attributes
idstringrequired

The ID of the user. Required in bulk updates to identify the user; ignored when updating a single user, which is identified by the URL.

typestringuserrequired
attributesTeamUserMembershipAttributes & TeamUserRoleIdrequired

The attributes to change. Attributes that are omitted are left unchanged.

Parameters

team_idintegerrequiredpath

The ID of the team.

user_idintegerrequiredpath

The ID of the user.

includeArray<string>rolequery

A comma-separated list of related resources to include in the response.

Response

200OKobject

The team user.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: users:write

Update a user
curl -X PATCH 'https://api.tintup.com/v2/teams/{team_id}/users/{user_id}' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "id": "42",
      "type": "user",
      "attributes": {
        "role_id": 4
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/users/{user_id}', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "id": "42",
        "type": "user",
        "attributes": {
          "role_id": 4
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "id": "42",
    "type": "user",
    "attributes": {
      "role_id": 4
    }
  }
}

response = requests.patch('https://api.tintup.com/v2/teams/{team_id}/users/{user_id}', json=payload)
data = response.json()
Request Body
{
  "data": {
    "id": "42",
    "type": "user",
    "attributes": {
      "role_id": 4
    }
  }
}
{
  "data": {
    "id": "42",
    "type": "user",
    "attributes": {
      "first_name": "Jane",
      "last_name": "Doe",
      "organization": "Acme Inc.",
      "image_url": "https://cdn.example.com/avatars/jane-doe.png",
      "email": "jane.doe@example.com",
      "skip_idp": false,
      "created_at": "2025-01-08T13:22:10.000Z",
      "updated_at": "2025-03-14T16:42:07.000Z"
    },
    "relationships": {
      "role": {
        "data": {
          "type": "role",
          "id": "3"
        }
      }
    }
  },
  "included": [
    {}
  ]
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Create a user export request

POST
https://api.tintup.com/v2/teams/{team_id}/users/export/requests

Asynchronously exports the team's users to a CSV file. Once complete, a websocket message of type teams_user_export_request containing the ID, status and URL is delivered to the user's private channel (private-user- followed by the user's ID). You may also poll the status of the request using the endpoint below.

Body

application/vnd.api+json

The export request to create.

dataNewTeamsUserExportRequestrequired
Show child attributes
typestringteams_user_export_requestrequired
attributesobject
Show child attributes
filtersobject

Reserved for future use. Filters are currently ignored and every user of the team is exported.

Parameters

team_idintegerrequiredpath

The ID of the team.

Response

202Acceptedobject

The team user export request.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: users:read

Create a user export request
curl -X POST 'https://api.tintup.com/v2/teams/{team_id}/users/export/requests' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "teams_user_export_request"
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/users/export/requests', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "teams_user_export_request"
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "teams_user_export_request"
  }
}

response = requests.post('https://api.tintup.com/v2/teams/{team_id}/users/export/requests', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "teams_user_export_request"
  }
}
{
  "data": {
    "id": "OxZZQtuh5sXIKA",
    "type": "teams_user_export_request",
    "attributes": {
      "status": "pending",
      "url": null
    },
    "relationships": {
      "team": {
        "meta": {
          "included": false
        },
        "data": {
          "type": "team",
          "id": "1"
        }
      }
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}

Check the status of a user export request

GET
https://api.tintup.com/v2/teams/{team_id}/users/export/requests/{teams_user_export_request_id}

Retrieves the status of one of the team's user export requests.

Parameters

team_idintegerrequiredpath

The ID of the team.

teams_user_export_request_idstringrequiredpath

The ID of the export request, as returned when it was created.

Response

200OKobject

The team user export request.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: users:read

Check the status of a user export request
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/users/export/requests/{teams_user_export_request_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/users/export/requests/{teams_user_export_request_id}', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/users/export/requests/{teams_user_export_request_id}')
data = response.json()
{
  "data": {
    "id": "OxZZQtuh5sXIKA",
    "type": "teams_user_export_request",
    "attributes": {
      "status": "pending",
      "url": null
    },
    "relationships": {
      "team": {
        "meta": {
          "included": false
        },
        "data": {
          "type": "team",
          "id": "1"
        }
      }
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}
Common

Teams

teams

Retrieve a list of teams

GET
https://api.tintup.com/v2/teams

Returns the teams the authenticated user is a member of.

Parameters

includeArray<string>agentassetsformsmixespersonalizationsplanrolesocial_feedstintsquery

A comma-separated list of related resources to include in the response.

filterobjectquery

Filters the teams.

sortArray<string>id-idname-namecreated_at-created_at-idquery

A comma-separated list of attributes to sort by. Prefix an attribute with - to sort in descending order.

pageobjectquery

Offset pagination. Use page[size] to set the number of items per page and page[number] to select a page. The response's links object contains ready-to-use URLs for the next and previous pages.

Response

200OKobject

A list of the teams the authenticated user is a member of.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: teams:read

Retrieve a list of teams
curl -X GET 'https://api.tintup.com/v2/teams'
const response = await fetch('https://api.tintup.com/v2/teams', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams')
data = response.json()
{
  "data": [
    {
      "id": "1",
      "type": "team",
      "attributes": {
        "name": "Acme Inc.",
        "image_url": "https://cdn.example.com/logos/acme.png",
        "url_shortener_type": "tintly",
        "onboarding": "completed",
        "shared_tags": [
          "summer",
          "ugc"
        ],
        "saml_enabled": true,
        "idp_entity_id": "https://idp.example.com/metadata",
        "idp_sso_target_url": "https://idp.example.com/sso/saml",
        "idp_cert": "-----BEGIN CERTIFICATE-----\nMIIDdzCCAl+gAwIBAgIEbGx0ZTANBgkqhkiG9w0BAQsFADBsMRAwDgYDVQQGEwdV\n-----END CERTIFICATE-----",
        "force_authn": false,
        "authn_requests_signed": false,
        "want_assertions_signed": true,
        "want_assertions_encrypted": false,
        "saml_jit_provisioning": true,
        "oidc_enabled": false,
        "oidc_identifier": "0oa1b2c3d4e5f6g7h8i9",
        "oidc_secret": "9f8e7d6c5b4a39281706f5e4d3c2b1a0",
        "oidc_scope": "openid email profile",
        "oidc_issuer": "https://login.example.com",
        "oidc_authorization_endpoint": "https://login.example.com/oauth2/v1/authorize",
        "oidc_token_endpoint": "https://login.example.com/oauth2/v1/token",
        "oidc_userinfo_endpoint": "https://login.example.com/oauth2/v1/userinfo",
        "oidc_jwks_uri": "https://login.example.com/oauth2/v1/keys",
        "plan": "tint_professional",
        "plan_expires_at": "2026-03-14T00:00:00.000Z",
        "plan_changed_at": "2025-03-14T16:42:07.000Z",
        "self_service": false,
        "rewards_platform_id": "mrc_4f7a2b9c",
        "rewards_platform_key": "7d1e3c5a9b2f4e6d8c0a1b3d5f7e9c2a",
        "permissions": [
          "moderate_tint",
          "modify_tint",
          "assets_read"
        ],
        "created_at": "2024-11-02T10:05:44.000Z",
        "updated_at": "2025-03-14T16:42:07.000Z"
      },
      "relationships": {
        "role": {
          "data": {
            "type": "role",
            "id": "3"
          }
        },
        "plan": {
          "data": {
            "type": "plan",
            "id": "1"
          }
        },
        "agent": {
          "data": {
            "type": "agent",
            "id": "7"
          }
        },
        "tints": {
          "data": [
            {
              "type": "tint",
              "id": "1"
            }
          ],
          "meta": {
            "active_tints_count": 4,
            "count": 6
          }
        },
        "social_feeds": {
          "data": [
            {
              "type": "social_feed",
              "id": "1"
            }
          ],
          "meta": {
            "active_count": 12,
            "inactive_count": 3,
            "access_error_count": 1,
            "active_social_feeds_count": 12,
            "inactive_social_feeds_count": 3
          }
        },
        "posts": {
          "data": [
            {
              "type": "post",
              "id": "1"
            }
          ],
          "meta": {
            "posts_ingested_from_beginning_of_month": 18250
          }
        },
        "assets": {
          "data": [
            {
              "type": "asset",
              "id": "1"
            }
          ],
          "meta": {
            "count": 320,
            "uploaded_count": 45,
            "total": 320,
            "uploaded_total": 45
          }
        },
        "mixes": {
          "data": [
            {
              "type": "mix",
              "id": "1"
            }
          ],
          "meta": {
            "count": 2
          }
        },
        "forms": {
          "data": [
            {
              "type": "form",
              "id": "1"
            }
          ],
          "meta": {
            "count": 5,
            "published_count": 3
          }
        },
        "personalizations": {
          "data": [
            {
              "type": "personalization",
              "id": "1"
            }
          ],
          "meta": {
            "count": 8
          }
        }
      }
    }
  ],
  "included": [
    {}
  ],
  "links": {
    "self": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=2",
    "first": "https://api.tintup.com/v2/teams/1/tints",
    "next": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=3",
    "prev": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=1"
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}

Create a team

POST
https://api.tintup.com/v2/teams

Creates a team on a self-service plan, subscribes it to the plan using the payment token, and makes the authenticated user its administrator. If the payment token can't be processed, the request fails with a 422 Unprocessable Entity error on billing_platform_token.

Body

application/vnd.api+json

The team to create.

dataNewTeamrequired
Show child attributes
typestringteamrequired
attributesTeamAttributes & TeamWritableAttributes & objectrequired

Response

201Createdobject

The team.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: teams:write

Create a team
curl -X POST 'https://api.tintup.com/v2/teams' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "team",
      "attributes": {
        "name": "Acme Inc.",
        "plan": "tint_starter",
        "billing_platform_type": "chargify",
        "billing_platform_token": "tok_9s8d7f6g5h4j3k2l"
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "team",
        "attributes": {
          "name": "Acme Inc.",
          "plan": "tint_starter",
          "billing_platform_type": "chargify",
          "billing_platform_token": "tok_9s8d7f6g5h4j3k2l"
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "team",
    "attributes": {
      "name": "Acme Inc.",
      "plan": "tint_starter",
      "billing_platform_type": "chargify",
      "billing_platform_token": "tok_9s8d7f6g5h4j3k2l"
    }
  }
}

response = requests.post('https://api.tintup.com/v2/teams', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "team",
    "attributes": {
      "name": "Acme Inc.",
      "plan": "tint_starter",
      "billing_platform_type": "chargify",
      "billing_platform_token": "tok_9s8d7f6g5h4j3k2l"
    }
  }
}
{
  "data": {
    "id": "1",
    "type": "team",
    "attributes": {
      "name": "Acme Inc.",
      "image_url": "https://cdn.example.com/logos/acme.png",
      "url_shortener_type": "tintly",
      "onboarding": "completed",
      "shared_tags": [
        "summer",
        "ugc"
      ],
      "saml_enabled": true,
      "idp_entity_id": "https://idp.example.com/metadata",
      "idp_sso_target_url": "https://idp.example.com/sso/saml",
      "idp_cert": "-----BEGIN CERTIFICATE-----\nMIIDdzCCAl+gAwIBAgIEbGx0ZTANBgkqhkiG9w0BAQsFADBsMRAwDgYDVQQGEwdV\n-----END CERTIFICATE-----",
      "force_authn": false,
      "authn_requests_signed": false,
      "want_assertions_signed": true,
      "want_assertions_encrypted": false,
      "saml_jit_provisioning": true,
      "oidc_enabled": false,
      "oidc_identifier": "0oa1b2c3d4e5f6g7h8i9",
      "oidc_secret": "9f8e7d6c5b4a39281706f5e4d3c2b1a0",
      "oidc_scope": "openid email profile",
      "oidc_issuer": "https://login.example.com",
      "oidc_authorization_endpoint": "https://login.example.com/oauth2/v1/authorize",
      "oidc_token_endpoint": "https://login.example.com/oauth2/v1/token",
      "oidc_userinfo_endpoint": "https://login.example.com/oauth2/v1/userinfo",
      "oidc_jwks_uri": "https://login.example.com/oauth2/v1/keys",
      "plan": "tint_professional",
      "plan_expires_at": "2026-03-14T00:00:00.000Z",
      "plan_changed_at": "2025-03-14T16:42:07.000Z",
      "self_service": false,
      "rewards_platform_id": "mrc_4f7a2b9c",
      "rewards_platform_key": "7d1e3c5a9b2f4e6d8c0a1b3d5f7e9c2a",
      "permissions": [
        "moderate_tint",
        "modify_tint",
        "assets_read"
      ],
      "created_at": "2024-11-02T10:05:44.000Z",
      "updated_at": "2025-03-14T16:42:07.000Z"
    },
    "relationships": {
      "role": {
        "data": {
          "type": "role",
          "id": "3"
        }
      },
      "plan": {
        "data": {
          "type": "plan",
          "id": "1"
        }
      },
      "agent": {
        "data": {
          "type": "agent",
          "id": "7"
        }
      },
      "tints": {
        "data": [
          {
            "type": "tint",
            "id": "1"
          }
        ],
        "meta": {
          "active_tints_count": 4,
          "count": 6
        }
      },
      "social_feeds": {
        "data": [
          {
            "type": "social_feed",
            "id": "1"
          }
        ],
        "meta": {
          "active_count": 12,
          "inactive_count": 3,
          "access_error_count": 1,
          "active_social_feeds_count": 12,
          "inactive_social_feeds_count": 3
        }
      },
      "posts": {
        "data": [
          {
            "type": "post",
            "id": "1"
          }
        ],
        "meta": {
          "posts_ingested_from_beginning_of_month": 18250
        }
      },
      "assets": {
        "data": [
          {
            "type": "asset",
            "id": "1"
          }
        ],
        "meta": {
          "count": 320,
          "uploaded_count": 45,
          "total": 320,
          "uploaded_total": 45
        }
      },
      "mixes": {
        "data": [
          {
            "type": "mix",
            "id": "1"
          }
        ],
        "meta": {
          "count": 2
        }
      },
      "forms": {
        "data": [
          {
            "type": "form",
            "id": "1"
          }
        ],
        "meta": {
          "count": 5,
          "published_count": 3
        }
      },
      "personalizations": {
        "data": [
          {
            "type": "personalization",
            "id": "1"
          }
        ],
        "meta": {
          "count": 8
        }
      }
    }
  },
  "included": [
    {}
  ]
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Retrieve a team

GET
https://api.tintup.com/v2/teams/{team_id}

Returns a team the authenticated user is a member of.

Parameters

team_idintegerrequiredpath

The ID of the team.

includeArray<string>agentassetsformsmixespersonalizationsplanrolesocial_feedstintsquery

A comma-separated list of related resources to include in the response.

Response

200OKobject

The team.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: teams:read

Retrieve a team
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}')
data = response.json()
{
  "data": {
    "id": "1",
    "type": "team",
    "attributes": {
      "name": "Acme Inc.",
      "image_url": "https://cdn.example.com/logos/acme.png",
      "url_shortener_type": "tintly",
      "onboarding": "completed",
      "shared_tags": [
        "summer",
        "ugc"
      ],
      "saml_enabled": true,
      "idp_entity_id": "https://idp.example.com/metadata",
      "idp_sso_target_url": "https://idp.example.com/sso/saml",
      "idp_cert": "-----BEGIN CERTIFICATE-----\nMIIDdzCCAl+gAwIBAgIEbGx0ZTANBgkqhkiG9w0BAQsFADBsMRAwDgYDVQQGEwdV\n-----END CERTIFICATE-----",
      "force_authn": false,
      "authn_requests_signed": false,
      "want_assertions_signed": true,
      "want_assertions_encrypted": false,
      "saml_jit_provisioning": true,
      "oidc_enabled": false,
      "oidc_identifier": "0oa1b2c3d4e5f6g7h8i9",
      "oidc_secret": "9f8e7d6c5b4a39281706f5e4d3c2b1a0",
      "oidc_scope": "openid email profile",
      "oidc_issuer": "https://login.example.com",
      "oidc_authorization_endpoint": "https://login.example.com/oauth2/v1/authorize",
      "oidc_token_endpoint": "https://login.example.com/oauth2/v1/token",
      "oidc_userinfo_endpoint": "https://login.example.com/oauth2/v1/userinfo",
      "oidc_jwks_uri": "https://login.example.com/oauth2/v1/keys",
      "plan": "tint_professional",
      "plan_expires_at": "2026-03-14T00:00:00.000Z",
      "plan_changed_at": "2025-03-14T16:42:07.000Z",
      "self_service": false,
      "rewards_platform_id": "mrc_4f7a2b9c",
      "rewards_platform_key": "7d1e3c5a9b2f4e6d8c0a1b3d5f7e9c2a",
      "permissions": [
        "moderate_tint",
        "modify_tint",
        "assets_read"
      ],
      "created_at": "2024-11-02T10:05:44.000Z",
      "updated_at": "2025-03-14T16:42:07.000Z"
    },
    "relationships": {
      "role": {
        "data": {
          "type": "role",
          "id": "3"
        }
      },
      "plan": {
        "data": {
          "type": "plan",
          "id": "1"
        }
      },
      "agent": {
        "data": {
          "type": "agent",
          "id": "7"
        }
      },
      "tints": {
        "data": [
          {
            "type": "tint",
            "id": "1"
          }
        ],
        "meta": {
          "active_tints_count": 4,
          "count": 6
        }
      },
      "social_feeds": {
        "data": [
          {
            "type": "social_feed",
            "id": "1"
          }
        ],
        "meta": {
          "active_count": 12,
          "inactive_count": 3,
          "access_error_count": 1,
          "active_social_feeds_count": 12,
          "inactive_social_feeds_count": 3
        }
      },
      "posts": {
        "data": [
          {
            "type": "post",
            "id": "1"
          }
        ],
        "meta": {
          "posts_ingested_from_beginning_of_month": 18250
        }
      },
      "assets": {
        "data": [
          {
            "type": "asset",
            "id": "1"
          }
        ],
        "meta": {
          "count": 320,
          "uploaded_count": 45,
          "total": 320,
          "uploaded_total": 45
        }
      },
      "mixes": {
        "data": [
          {
            "type": "mix",
            "id": "1"
          }
        ],
        "meta": {
          "count": 2
        }
      },
      "forms": {
        "data": [
          {
            "type": "form",
            "id": "1"
          }
        ],
        "meta": {
          "count": 5,
          "published_count": 3
        }
      },
      "personalizations": {
        "data": [
          {
            "type": "personalization",
            "id": "1"
          }
        ],
        "meta": {
          "count": 8
        }
      }
    }
  },
  "included": [
    {}
  ]
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Delete a team

DELETE
https://api.tintup.com/v2/teams/{team_id}

Cancels the team's subscription at the end of the current billing period. Only available to teams billed through Chargify; otherwise, the request fails with a 403 Forbidden error.

Parameters

team_idintegerrequiredpath

The ID of the team.

Response

204No Content

No Content. The request succeeded and there is no response body.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: teams:write

Delete a team
curl -X DELETE 'https://api.tintup.com/v2/teams/{team_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}', {
  method: 'DELETE',
});

const data = await response.json();
import requests

response = requests.delete('https://api.tintup.com/v2/teams/{team_id}')
data = response.json()
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Update a team

PATCH
https://api.tintup.com/v2/teams/{team_id}

Updates the team.

Body

application/vnd.api+json

The attributes of the team to change.

dataTeamUpdaterequired
Show child attributes
idstring

The ID of the team. Optional; the team is identified by the URL.

typestringteamrequired
attributesTeamAttributes & TeamSsoAttributes & TeamWritableAttributesrequired

The attributes to change. Attributes that are omitted are left unchanged.

Parameters

team_idintegerrequiredpath

The ID of the team.

includeArray<string>agentassetsformsmixespersonalizationsplanrolesocial_feedstintsquery

A comma-separated list of related resources to include in the response.

Response

200OKobject

The team.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: teams:write

Update a team
curl -X PATCH 'https://api.tintup.com/v2/teams/{team_id}' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "id": "1",
      "type": "team",
      "attributes": {
        "name": "Acme Inc.",
        "image_url": "https://cdn.example.com/logos/acme.png",
        "shared_tags": true
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "id": "1",
        "type": "team",
        "attributes": {
          "name": "Acme Inc.",
          "image_url": "https://cdn.example.com/logos/acme.png",
          "shared_tags": true
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "id": "1",
    "type": "team",
    "attributes": {
      "name": "Acme Inc.",
      "image_url": "https://cdn.example.com/logos/acme.png",
      "shared_tags": True
    }
  }
}

response = requests.patch('https://api.tintup.com/v2/teams/{team_id}', json=payload)
data = response.json()
Request Body
{
  "data": {
    "id": "1",
    "type": "team",
    "attributes": {
      "name": "Acme Inc.",
      "image_url": "https://cdn.example.com/logos/acme.png",
      "shared_tags": true
    }
  }
}
{
  "data": {
    "id": "1",
    "type": "team",
    "attributes": {
      "name": "Acme Inc.",
      "image_url": "https://cdn.example.com/logos/acme.png",
      "url_shortener_type": "tintly",
      "onboarding": "completed",
      "shared_tags": [
        "summer",
        "ugc"
      ],
      "saml_enabled": true,
      "idp_entity_id": "https://idp.example.com/metadata",
      "idp_sso_target_url": "https://idp.example.com/sso/saml",
      "idp_cert": "-----BEGIN CERTIFICATE-----\nMIIDdzCCAl+gAwIBAgIEbGx0ZTANBgkqhkiG9w0BAQsFADBsMRAwDgYDVQQGEwdV\n-----END CERTIFICATE-----",
      "force_authn": false,
      "authn_requests_signed": false,
      "want_assertions_signed": true,
      "want_assertions_encrypted": false,
      "saml_jit_provisioning": true,
      "oidc_enabled": false,
      "oidc_identifier": "0oa1b2c3d4e5f6g7h8i9",
      "oidc_secret": "9f8e7d6c5b4a39281706f5e4d3c2b1a0",
      "oidc_scope": "openid email profile",
      "oidc_issuer": "https://login.example.com",
      "oidc_authorization_endpoint": "https://login.example.com/oauth2/v1/authorize",
      "oidc_token_endpoint": "https://login.example.com/oauth2/v1/token",
      "oidc_userinfo_endpoint": "https://login.example.com/oauth2/v1/userinfo",
      "oidc_jwks_uri": "https://login.example.com/oauth2/v1/keys",
      "plan": "tint_professional",
      "plan_expires_at": "2026-03-14T00:00:00.000Z",
      "plan_changed_at": "2025-03-14T16:42:07.000Z",
      "self_service": false,
      "rewards_platform_id": "mrc_4f7a2b9c",
      "rewards_platform_key": "7d1e3c5a9b2f4e6d8c0a1b3d5f7e9c2a",
      "permissions": [
        "moderate_tint",
        "modify_tint",
        "assets_read"
      ],
      "created_at": "2024-11-02T10:05:44.000Z",
      "updated_at": "2025-03-14T16:42:07.000Z"
    },
    "relationships": {
      "role": {
        "data": {
          "type": "role",
          "id": "3"
        }
      },
      "plan": {
        "data": {
          "type": "plan",
          "id": "1"
        }
      },
      "agent": {
        "data": {
          "type": "agent",
          "id": "7"
        }
      },
      "tints": {
        "data": [
          {
            "type": "tint",
            "id": "1"
          }
        ],
        "meta": {
          "active_tints_count": 4,
          "count": 6
        }
      },
      "social_feeds": {
        "data": [
          {
            "type": "social_feed",
            "id": "1"
          }
        ],
        "meta": {
          "active_count": 12,
          "inactive_count": 3,
          "access_error_count": 1,
          "active_social_feeds_count": 12,
          "inactive_social_feeds_count": 3
        }
      },
      "posts": {
        "data": [
          {
            "type": "post",
            "id": "1"
          }
        ],
        "meta": {
          "posts_ingested_from_beginning_of_month": 18250
        }
      },
      "assets": {
        "data": [
          {
            "type": "asset",
            "id": "1"
          }
        ],
        "meta": {
          "count": 320,
          "uploaded_count": 45,
          "total": 320,
          "uploaded_total": 45
        }
      },
      "mixes": {
        "data": [
          {
            "type": "mix",
            "id": "1"
          }
        ],
        "meta": {
          "count": 2
        }
      },
      "forms": {
        "data": [
          {
            "type": "form",
            "id": "1"
          }
        ],
        "meta": {
          "count": 5,
          "published_count": 3
        }
      },
      "personalizations": {
        "data": [
          {
            "type": "personalization",
            "id": "1"
          }
        ],
        "meta": {
          "count": 8
        }
      }
    }
  },
  "included": [
    {}
  ]
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Experience Builder

group_experience_builder
Experience Builder

Experiences

experiences

Retrieve a list of experiences

GET
https://api.tintup.com/v2/teams/{team_id}/experiences

Returns the experiences the user has access to.

Parameters

team_idintegerrequiredpath

The ID of the team.

includeArray<string>domainform_submission_keyssubmissionsuserquery

A comma-separated list of related resources to include in the response. Only applies to authenticated requests.

pageobjectquery

Offset pagination. Use page[size] to set the number of items per page and page[number] to select a page. The response's links object contains ready-to-use URLs for the next and previous pages.

filterobjectquery

Filters the list of experiences.

sortstring-idquery

A comma-separated list of attributes to sort by. Prefix an attribute with - to sort in descending order.

Response

200OKobject

A list of experiences.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: experiences:read

Retrieve a list of experiences
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/experiences'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/experiences', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/experiences')
data = response.json()
{
  "data": [
    {
      "id": "42",
      "type": "experience",
      "attributes": {
        "type": "sweepstakes",
        "title": "Win a trip to Hawaii",
        "description": "Enter our summer sweepstakes for a chance to win a trip for two.",
        "analytics_id": "GTM-5XK7Q2P",
        "analytics_type": "google_tag_manager",
        "captcha_type": null,
        "captcha_public_key": null,
        "cookie_consent": true,
        "noindex": false,
        "favicon_url": "https://cdn.example.com/favicons/acme.png",
        "maximum_image_size": 104857600,
        "maximum_video_size": 1048576000,
        "bypass_mime_type_validation": false,
        "name": "Summer Sweepstakes 2025",
        "status": "active",
        "slug": "summer-sweepstakes",
        "data": {
          "draft": [
            {
              "sectionType": "banner",
              "data": {
                "content": {
                  "title": "Win a trip to Hawaii"
                }
              }
            },
            {
              "sectionType": "form",
              "data": {
                "content": {
                  "fields": [
                    {
                      "key": "email",
                      "type": "email"
                    }
                  ]
                }
              }
            }
          ],
          "published": [
            {
              "sectionType": "banner",
              "data": {
                "content": {
                  "title": "Win a trip to Hawaii"
                }
              }
            },
            {
              "sectionType": "form",
              "data": {
                "content": {
                  "fields": [
                    {
                      "key": "email",
                      "type": "email"
                    }
                  ]
                }
              }
            }
          ],
          "locales": {
            "draft": [
              {
                "value": "en",
                "isDefault": true
              }
            ],
            "published": [
              {
                "value": "en",
                "isDefault": true
              }
            ]
          },
          "translations": {
            "draft": {
              "en": {}
            },
            "published": {
              "en": {}
            }
          },
          "customFonts": {
            "draft": {},
            "published": {}
          }
        },
        "created_at": "2025-03-14T16:42:07.000Z",
        "updated_at": "2025-03-18T09:12:44.000Z"
      },
      "relationships": {
        "domain": {
          "data": {
            "type": "domain",
            "id": "3"
          }
        },
        "form_submission_keys": {
          "data": [
            {
              "type": "form_submission_key",
              "id": "email"
            }
          ],
          "meta": {
            "included": false
          }
        },
        "user": {
          "data": {
            "type": "team",
            "id": "1"
          },
          "meta": {
            "included": false
          }
        },
        "submissions": {
          "data": [
            {
              "type": "form_submission",
              "id": "88213"
            }
          ],
          "links": {
            "related": "https://api.tintup.com/v2/teams/1/experiences/42/form_submissions",
            "first": "https://api.tintup.com/v2/teams/1/experiences/42/form_submissions",
            "next": "https://api.tintup.com/v2/teams/1/experiences/42/form_submissions?page%5Bnumber%5D=2"
          },
          "meta": {
            "total": 1289,
            "count": 1289
          }
        }
      },
      "links": {
        "public": "https://contests.example.com/summer-sweepstakes"
      }
    }
  ],
  "links": {
    "self": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=2",
    "first": "https://api.tintup.com/v2/teams/1/tints",
    "next": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=3",
    "prev": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=1"
  },
  "meta": {
    "total": 18
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}

Create an experience

POST
https://api.tintup.com/v2/teams/{team_id}/experiences

Creates an experience and grants access to it to the user's role and to the roles that have access to new experiences.

Body

application/vnd.api+json

The experience to create.

dataNewExperiencerequired
Show child attributes
typestringexperiencerequired
attributesExperienceWritableAttributes & objectrequired

Parameters

team_idintegerrequiredpath

The ID of the team.

includeArray<string>domainform_submission_keyssubmissionsuserquery

A comma-separated list of related resources to include in the response. Only applies to authenticated requests.

Response

201Createdobject

The experience.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: experiences:write

Create an experience
curl -X POST 'https://api.tintup.com/v2/teams/{team_id}/experiences' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "experience",
      "attributes": {
        "type": "sweepstakes",
        "name": "Summer Sweepstakes 2025",
        "title": "Win a trip to Hawaii",
        "slug": "summer-sweepstakes",
        "domain_id": 3,
        "cookie_consent": true
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/experiences', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "experience",
        "attributes": {
          "type": "sweepstakes",
          "name": "Summer Sweepstakes 2025",
          "title": "Win a trip to Hawaii",
          "slug": "summer-sweepstakes",
          "domain_id": 3,
          "cookie_consent": true
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "experience",
    "attributes": {
      "type": "sweepstakes",
      "name": "Summer Sweepstakes 2025",
      "title": "Win a trip to Hawaii",
      "slug": "summer-sweepstakes",
      "domain_id": 3,
      "cookie_consent": True
    }
  }
}

response = requests.post('https://api.tintup.com/v2/teams/{team_id}/experiences', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "experience",
    "attributes": {
      "type": "sweepstakes",
      "name": "Summer Sweepstakes 2025",
      "title": "Win a trip to Hawaii",
      "slug": "summer-sweepstakes",
      "domain_id": 3,
      "cookie_consent": true
    }
  }
}
{
  "data": {
    "id": "42",
    "type": "experience",
    "attributes": {
      "type": "sweepstakes",
      "title": "Win a trip to Hawaii",
      "description": "Enter our summer sweepstakes for a chance to win a trip for two.",
      "analytics_id": "GTM-5XK7Q2P",
      "analytics_type": "google_tag_manager",
      "captcha_type": null,
      "captcha_public_key": null,
      "cookie_consent": true,
      "noindex": false,
      "favicon_url": "https://cdn.example.com/favicons/acme.png",
      "maximum_image_size": 104857600,
      "maximum_video_size": 1048576000,
      "bypass_mime_type_validation": false,
      "name": "Summer Sweepstakes 2025",
      "status": "active",
      "slug": "summer-sweepstakes",
      "data": {
        "draft": [
          {
            "sectionType": "banner",
            "data": {
              "content": {
                "title": "Win a trip to Hawaii"
              }
            }
          },
          {
            "sectionType": "form",
            "data": {
              "content": {
                "fields": [
                  {
                    "key": "email",
                    "type": "email"
                  }
                ]
              }
            }
          }
        ],
        "published": [
          {
            "sectionType": "banner",
            "data": {
              "content": {
                "title": "Win a trip to Hawaii"
              }
            }
          },
          {
            "sectionType": "form",
            "data": {
              "content": {
                "fields": [
                  {
                    "key": "email",
                    "type": "email"
                  }
                ]
              }
            }
          }
        ],
        "locales": {
          "draft": [
            {
              "value": "en",
              "isDefault": true
            }
          ],
          "published": [
            {
              "value": "en",
              "isDefault": true
            }
          ]
        },
        "translations": {
          "draft": {
            "en": {}
          },
          "published": {
            "en": {}
          }
        },
        "customFonts": {
          "draft": {},
          "published": {}
        }
      },
      "created_at": "2025-03-14T16:42:07.000Z",
      "updated_at": "2025-03-18T09:12:44.000Z"
    },
    "relationships": {
      "domain": {
        "data": {
          "type": "domain",
          "id": "3"
        }
      },
      "form_submission_keys": {
        "data": [
          {
            "type": "form_submission_key",
            "id": "email"
          }
        ],
        "meta": {
          "included": false
        }
      },
      "user": {
        "data": {
          "type": "team",
          "id": "1"
        },
        "meta": {
          "included": false
        }
      },
      "submissions": {
        "data": [
          {
            "type": "form_submission",
            "id": "88213"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/teams/1/experiences/42/form_submissions",
          "first": "https://api.tintup.com/v2/teams/1/experiences/42/form_submissions",
          "next": "https://api.tintup.com/v2/teams/1/experiences/42/form_submissions?page%5Bnumber%5D=2"
        },
        "meta": {
          "total": 1289,
          "count": 1289
        }
      }
    },
    "links": {
      "public": "https://contests.example.com/summer-sweepstakes"
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Delete multiple experiences

DELETE
https://api.tintup.com/v2/teams/{team_id}/experiences

Deletes several experiences at once.

Body

application/vnd.api+json; ext=bulk

The experiences to delete. IDs the user can't access are ignored.

dataArray<ExperienceIdentifier>required
Show child attributes
idstringrequired

The ID of the experience.

typestringexperiencerequired

Parameters

team_idintegerrequiredpath

The ID of the team.

Response

204No Content

No Content. The request succeeded and there is no response body.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: experiences:write

Delete multiple experiences
curl -X DELETE 'https://api.tintup.com/v2/teams/{team_id}/experiences' \
  -H 'Content-Type: application/vnd.api+json; ext=bulk' \
  -d '{
    "data": [
      {
        "id": "42",
        "type": "experience"
      },
      {
        "id": "43",
        "type": "experience"
      }
    ]
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/experiences', {
  method: 'DELETE',
  headers: {
    'Content-Type': 'application/vnd.api+json; ext=bulk',
  },
  body: JSON.stringify({
      "data": [
        {
          "id": "42",
          "type": "experience"
        },
        {
          "id": "43",
          "type": "experience"
        }
      ]
    }),
});

const data = await response.json();
import requests

payload = {
  "data": [
    {
      "id": "42",
      "type": "experience"
    },
    {
      "id": "43",
      "type": "experience"
    }
  ]
}

response = requests.delete('https://api.tintup.com/v2/teams/{team_id}/experiences', json=payload)
data = response.json()
Request Body
{
  "data": [
    {
      "id": "42",
      "type": "experience"
    },
    {
      "id": "43",
      "type": "experience"
    }
  ]
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}

Update multiple experiences

PATCH
https://api.tintup.com/v2/teams/{team_id}/experiences

Updates several experiences in a single request. If any experience is invalid, none are updated and the errors are returned. The experience type can't be changed. PUT is accepted as an alias of PATCH.

Body

application/vnd.api+json; ext=bulk

The experiences to update. If any experience is invalid, none are updated.

dataArray<ExperienceBulkUpdate>required
Show child attributes
idstringrequired

The ID of the experience to update.

typestringexperiencerequired
attributesExperienceWritableAttributes

The attributes to change. The experience type can't be changed and is ignored.

Parameters

team_idintegerrequiredpath

The ID of the team.

Response

200OKobject

A list of experiences.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: experiences:write

Update multiple experiences
curl -X PATCH 'https://api.tintup.com/v2/teams/{team_id}/experiences' \
  -H 'Content-Type: application/vnd.api+json; ext=bulk' \
  -d '{
    "data": [
      {
        "id": "42",
        "type": "experience",
        "attributes": {
          "status": "archived"
        }
      },
      {
        "id": "43",
        "type": "experience",
        "attributes": {
          "status": "archived"
        }
      }
    ]
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/experiences', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/vnd.api+json; ext=bulk',
  },
  body: JSON.stringify({
      "data": [
        {
          "id": "42",
          "type": "experience",
          "attributes": {
            "status": "archived"
          }
        },
        {
          "id": "43",
          "type": "experience",
          "attributes": {
            "status": "archived"
          }
        }
      ]
    }),
});

const data = await response.json();
import requests

payload = {
  "data": [
    {
      "id": "42",
      "type": "experience",
      "attributes": {
        "status": "archived"
      }
    },
    {
      "id": "43",
      "type": "experience",
      "attributes": {
        "status": "archived"
      }
    }
  ]
}

response = requests.patch('https://api.tintup.com/v2/teams/{team_id}/experiences', json=payload)
data = response.json()
Request Body
{
  "data": [
    {
      "id": "42",
      "type": "experience",
      "attributes": {
        "status": "archived"
      }
    },
    {
      "id": "43",
      "type": "experience",
      "attributes": {
        "status": "archived"
      }
    }
  ]
}
{
  "data": [
    {
      "id": "42",
      "type": "experience",
      "attributes": {
        "type": "sweepstakes",
        "title": "Win a trip to Hawaii",
        "description": "Enter our summer sweepstakes for a chance to win a trip for two.",
        "analytics_id": "GTM-5XK7Q2P",
        "analytics_type": "google_tag_manager",
        "captcha_type": null,
        "captcha_public_key": null,
        "cookie_consent": true,
        "noindex": false,
        "favicon_url": "https://cdn.example.com/favicons/acme.png",
        "maximum_image_size": 104857600,
        "maximum_video_size": 1048576000,
        "bypass_mime_type_validation": false,
        "name": "Summer Sweepstakes 2025",
        "status": "active",
        "slug": "summer-sweepstakes",
        "data": {
          "draft": [
            {
              "sectionType": "banner",
              "data": {
                "content": {
                  "title": "Win a trip to Hawaii"
                }
              }
            },
            {
              "sectionType": "form",
              "data": {
                "content": {
                  "fields": [
                    {
                      "key": "email",
                      "type": "email"
                    }
                  ]
                }
              }
            }
          ],
          "published": [
            {
              "sectionType": "banner",
              "data": {
                "content": {
                  "title": "Win a trip to Hawaii"
                }
              }
            },
            {
              "sectionType": "form",
              "data": {
                "content": {
                  "fields": [
                    {
                      "key": "email",
                      "type": "email"
                    }
                  ]
                }
              }
            }
          ],
          "locales": {
            "draft": [
              {
                "value": "en",
                "isDefault": true
              }
            ],
            "published": [
              {
                "value": "en",
                "isDefault": true
              }
            ]
          },
          "translations": {
            "draft": {
              "en": {}
            },
            "published": {
              "en": {}
            }
          },
          "customFonts": {
            "draft": {},
            "published": {}
          }
        },
        "created_at": "2025-03-14T16:42:07.000Z",
        "updated_at": "2025-03-18T09:12:44.000Z"
      },
      "relationships": {
        "domain": {
          "data": {
            "type": "domain",
            "id": "3"
          }
        },
        "form_submission_keys": {
          "data": [
            {
              "type": "form_submission_key",
              "id": "email"
            }
          ],
          "meta": {
            "included": false
          }
        },
        "user": {
          "data": {
            "type": "team",
            "id": "1"
          },
          "meta": {
            "included": false
          }
        },
        "submissions": {
          "data": [
            {
              "type": "form_submission",
              "id": "88213"
            }
          ],
          "links": {
            "related": "https://api.tintup.com/v2/teams/1/experiences/42/form_submissions",
            "first": "https://api.tintup.com/v2/teams/1/experiences/42/form_submissions",
            "next": "https://api.tintup.com/v2/teams/1/experiences/42/form_submissions?page%5Bnumber%5D=2"
          },
          "meta": {
            "total": 1289,
            "count": 1289
          }
        }
      },
      "links": {
        "public": "https://contests.example.com/summer-sweepstakes"
      }
    }
  ],
  "links": {
    "self": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=2",
    "first": "https://api.tintup.com/v2/teams/1/tints",
    "next": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=3",
    "prev": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=1"
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Retrieve an experience

GET
https://api.tintup.com/v2/teams/{team_id}/experiences/{experience_id}

With an access token, retrieves one of the experiences the user has access to by ID. Without an Authorization header, retrieves a published experience by ID or by slug. When using a slug, team_id may also be the name of the experience's custom domain, the request's Referer must be allowed for the experience, and the experience's impression count is incremented.

Parameters

team_idinteger | stringrequiredpath

The ID of the team. When retrieving a published experience by slug, this can also be the name of the experience's custom domain.

experience_idinteger | stringrequiredpath

The ID or slug of the experience. Slugs are only accepted when retrieving a published experience without authentication.

includeArray<string>domainform_submission_keyssubmissionsuserquery

A comma-separated list of related resources to include in the response. Only applies to authenticated requests.

Response

200OKobject

The experience. Unauthenticated requests receive a reduced set of attributes.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: experiences:read

Retrieve an experience
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/experiences/{experience_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/experiences/{experience_id}', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/experiences/{experience_id}')
data = response.json()
{
  "data": {
    "id": "42",
    "type": "experience",
    "attributes": {
      "type": "sweepstakes",
      "title": "Win a trip to Hawaii",
      "description": "Enter our summer sweepstakes for a chance to win a trip for two.",
      "analytics_id": "GTM-5XK7Q2P",
      "analytics_type": "google_tag_manager",
      "captcha_type": null,
      "captcha_public_key": null,
      "cookie_consent": true,
      "noindex": false,
      "favicon_url": "https://cdn.example.com/favicons/acme.png",
      "maximum_image_size": 104857600,
      "maximum_video_size": 1048576000,
      "bypass_mime_type_validation": false,
      "name": "Summer Sweepstakes 2025",
      "status": "active",
      "slug": "summer-sweepstakes",
      "data": {
        "draft": [
          {
            "sectionType": "banner",
            "data": {
              "content": {
                "title": "Win a trip to Hawaii"
              }
            }
          },
          {
            "sectionType": "form",
            "data": {
              "content": {
                "fields": [
                  {
                    "key": "email",
                    "type": "email"
                  }
                ]
              }
            }
          }
        ],
        "published": [
          {
            "sectionType": "banner",
            "data": {
              "content": {
                "title": "Win a trip to Hawaii"
              }
            }
          },
          {
            "sectionType": "form",
            "data": {
              "content": {
                "fields": [
                  {
                    "key": "email",
                    "type": "email"
                  }
                ]
              }
            }
          }
        ],
        "locales": {
          "draft": [
            {
              "value": "en",
              "isDefault": true
            }
          ],
          "published": [
            {
              "value": "en",
              "isDefault": true
            }
          ]
        },
        "translations": {
          "draft": {
            "en": {}
          },
          "published": {
            "en": {}
          }
        },
        "customFonts": {
          "draft": {},
          "published": {}
        }
      },
      "created_at": "2025-03-14T16:42:07.000Z",
      "updated_at": "2025-03-18T09:12:44.000Z"
    },
    "relationships": {
      "domain": {
        "data": {
          "type": "domain",
          "id": "3"
        }
      },
      "form_submission_keys": {
        "data": [
          {
            "type": "form_submission_key",
            "id": "email"
          }
        ],
        "meta": {
          "included": false
        }
      },
      "user": {
        "data": {
          "type": "team",
          "id": "1"
        },
        "meta": {
          "included": false
        }
      },
      "submissions": {
        "data": [
          {
            "type": "form_submission",
            "id": "88213"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/teams/1/experiences/42/form_submissions",
          "first": "https://api.tintup.com/v2/teams/1/experiences/42/form_submissions",
          "next": "https://api.tintup.com/v2/teams/1/experiences/42/form_submissions?page%5Bnumber%5D=2"
        },
        "meta": {
          "total": 1289,
          "count": 1289
        }
      }
    },
    "links": {
      "public": "https://contests.example.com/summer-sweepstakes"
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Delete an experience

DELETE
https://api.tintup.com/v2/teams/{team_id}/experiences/{experience_id}

Deletes the experience.

Parameters

team_idintegerrequiredpath

The ID of the team.

experience_idintegerrequiredpath

The ID of the experience.

Response

204No Content

No Content. The request succeeded and there is no response body.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: experiences:write

Delete an experience
curl -X DELETE 'https://api.tintup.com/v2/teams/{team_id}/experiences/{experience_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/experiences/{experience_id}', {
  method: 'DELETE',
});

const data = await response.json();
import requests

response = requests.delete('https://api.tintup.com/v2/teams/{team_id}/experiences/{experience_id}')
data = response.json()
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Update an experience

PATCH
https://api.tintup.com/v2/teams/{team_id}/experiences/{experience_id}

PUT is accepted as an alias of PATCH.

Body

application/vnd.api+json

The attributes to change. Attributes that are left out are unchanged.

dataExperienceUpdaterequired
Show child attributes
typestringexperiencerequired
attributesExperienceWritableAttributes

The attributes to change. The experience type can't be changed and is ignored.

Parameters

team_idintegerrequiredpath

The ID of the team.

experience_idintegerrequiredpath

The ID of the experience.

includeArray<string>domainform_submission_keyssubmissionsuserquery

A comma-separated list of related resources to include in the response. Only applies to authenticated requests.

Response

200OKobject

The experience.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: experiences:write

Update an experience
curl -X PATCH 'https://api.tintup.com/v2/teams/{team_id}/experiences/{experience_id}' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "experience",
      "attributes": {
        "title": "Win a trip to Hawaii",
        "analytics_type": "google_tag_manager",
        "analytics_id": "GTM-5XK7Q2P"
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/experiences/{experience_id}', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "experience",
        "attributes": {
          "title": "Win a trip to Hawaii",
          "analytics_type": "google_tag_manager",
          "analytics_id": "GTM-5XK7Q2P"
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "experience",
    "attributes": {
      "title": "Win a trip to Hawaii",
      "analytics_type": "google_tag_manager",
      "analytics_id": "GTM-5XK7Q2P"
    }
  }
}

response = requests.patch('https://api.tintup.com/v2/teams/{team_id}/experiences/{experience_id}', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "experience",
    "attributes": {
      "title": "Win a trip to Hawaii",
      "analytics_type": "google_tag_manager",
      "analytics_id": "GTM-5XK7Q2P"
    }
  }
}
{
  "data": {
    "id": "42",
    "type": "experience",
    "attributes": {
      "type": "sweepstakes",
      "title": "Win a trip to Hawaii",
      "description": "Enter our summer sweepstakes for a chance to win a trip for two.",
      "analytics_id": "GTM-5XK7Q2P",
      "analytics_type": "google_tag_manager",
      "captcha_type": null,
      "captcha_public_key": null,
      "cookie_consent": true,
      "noindex": false,
      "favicon_url": "https://cdn.example.com/favicons/acme.png",
      "maximum_image_size": 104857600,
      "maximum_video_size": 1048576000,
      "bypass_mime_type_validation": false,
      "name": "Summer Sweepstakes 2025",
      "status": "active",
      "slug": "summer-sweepstakes",
      "data": {
        "draft": [
          {
            "sectionType": "banner",
            "data": {
              "content": {
                "title": "Win a trip to Hawaii"
              }
            }
          },
          {
            "sectionType": "form",
            "data": {
              "content": {
                "fields": [
                  {
                    "key": "email",
                    "type": "email"
                  }
                ]
              }
            }
          }
        ],
        "published": [
          {
            "sectionType": "banner",
            "data": {
              "content": {
                "title": "Win a trip to Hawaii"
              }
            }
          },
          {
            "sectionType": "form",
            "data": {
              "content": {
                "fields": [
                  {
                    "key": "email",
                    "type": "email"
                  }
                ]
              }
            }
          }
        ],
        "locales": {
          "draft": [
            {
              "value": "en",
              "isDefault": true
            }
          ],
          "published": [
            {
              "value": "en",
              "isDefault": true
            }
          ]
        },
        "translations": {
          "draft": {
            "en": {}
          },
          "published": {
            "en": {}
          }
        },
        "customFonts": {
          "draft": {},
          "published": {}
        }
      },
      "created_at": "2025-03-14T16:42:07.000Z",
      "updated_at": "2025-03-18T09:12:44.000Z"
    },
    "relationships": {
      "domain": {
        "data": {
          "type": "domain",
          "id": "3"
        }
      },
      "form_submission_keys": {
        "data": [
          {
            "type": "form_submission_key",
            "id": "email"
          }
        ],
        "meta": {
          "included": false
        }
      },
      "user": {
        "data": {
          "type": "team",
          "id": "1"
        },
        "meta": {
          "included": false
        }
      },
      "submissions": {
        "data": [
          {
            "type": "form_submission",
            "id": "88213"
          }
        ],
        "links": {
          "related": "https://api.tintup.com/v2/teams/1/experiences/42/form_submissions",
          "first": "https://api.tintup.com/v2/teams/1/experiences/42/form_submissions",
          "next": "https://api.tintup.com/v2/teams/1/experiences/42/form_submissions?page%5Bnumber%5D=2"
        },
        "meta": {
          "total": 1289,
          "count": 1289
        }
      }
    },
    "links": {
      "public": "https://contests.example.com/summer-sweepstakes"
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}
Experience Builder

Form Submissions

form_submissions

Retrieve a list of form submissions

GET
https://api.tintup.com/v2/teams/{team_id}/experiences/{experience_id}/form_submissions

Requires access to the experience.

Parameters

team_idintegerrequiredpath

The ID of the team.

experience_idintegerrequiredpath

The ID of the experience.

filterobjectquery

Filters the list of form submissions.

sortstring-idquery

A comma-separated list of attributes to sort by. Prefix an attribute with - to sort in descending order.

includeArray<string>experiencefilespostquery

A comma-separated list of related resources to include in the response.

pageobjectquery

Offset pagination. Use page[size] to set the number of items per page and page[number] to select a page. The response's links object contains ready-to-use URLs for the next and previous pages.

Response

200OKobject

A list of form submissions.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: form_submissions:read

Retrieve a list of form submissions
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/experiences/{experience_id}/form_submissions'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/experiences/{experience_id}/form_submissions', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/experiences/{experience_id}/form_submissions')
data = response.json()
{
  "data": [
    {
      "id": "88213",
      "type": "form_submission",
      "attributes": {
        "data": {
          "first_name": "Jane",
          "last_name": "Doe",
          "email": "jane.doe@example.com"
        },
        "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 14_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Safari/605.1.15",
        "referer": "https://contests.example.com/summer-sweepstakes",
        "locale": "en",
        "metadata": {
          "utm_source": "newsletter"
        },
        "remote_ip_city": "Vancouver",
        "remote_ip_most_specific_subdivision": "BC",
        "remote_ip_country": "CA",
        "city": "Vancouver, BC, CA",
        "created_at": "2025-03-14T16:42:07.000Z"
      },
      "relationships": {
        "person": {
          "data": {
            "type": "person",
            "id": "65f3a1c2e4b0a91d2c7e8f10"
          }
        },
        "experience": {
          "data": {
            "type": "experience",
            "id": "42"
          },
          "meta": {
            "included": false
          }
        },
        "post": {
          "data": {
            "type": "post",
            "id": "7731902"
          },
          "meta": {
            "included": false
          }
        },
        "terms": {
          "meta": {
            "included": false
          }
        },
        "files": {
          "data": [
            {
              "type": "upload",
              "id": "eyJfcmFpbHMiOnsiZGF0YSI6NDU2NzgsInB1ciI6ImJsb2JfaWQifX0=--1a2b3c4d5e6f70819a2b3c4d5e6f708192a3b4c5"
            }
          ],
          "meta": {
            "included": false
          }
        }
      }
    }
  ],
  "links": {
    "self": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=2",
    "first": "https://api.tintup.com/v2/teams/1/tints",
    "next": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=3",
    "prev": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=1"
  },
  "meta": {
    "impressions": 15230,
    "total": 1289
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Create a form submission

POST
https://api.tintup.com/v2/teams/{team_id}/experiences/{experience_id}/form_submissions

Submits the experience's form. This endpoint is public; the experience must be active, the request's Referer must be allowed for the experience, and the captcha token must be valid when the experience uses a captcha. For teams connected to a loyalty program, an optional Authorization: Bearer header may carry the loyalty member's JWT; the submission is then linked to that member, and an invalid token is rejected with a 403.

Body

application/x-www-form-urlencoded

The form's fields as key/value pairs.

application/x-www-form-urlencodedFormSubmissionFields

The experience's form fields as key/value pairs; they are stored as is in the submission's data. For poll experiences, send post_id (the ID of the post voted for) and vote (the number of votes, usually 1). When the experience uses a captcha, also send the g-recaptcha-response (Google reCAPTCHA) or h-captcha-response (hCaptcha) token.

FormSubmissionFields
multipart/form-dataFormSubmissionFields

The experience's form fields as key/value pairs; they are stored as is in the submission's data. For poll experiences, send post_id (the ID of the post voted for) and vote (the number of votes, usually 1). When the experience uses a captcha, also send the g-recaptcha-response (Google reCAPTCHA) or h-captcha-response (hCaptcha) token.

FormSubmissionFields

Parameters

team_idintegerrequiredpath

The ID of the team.

experience_idintegerrequiredpath

The ID of the experience.

localestringquery

The locale the form was displayed in, stored in the submission's locale attribute.

X-TINT-Metadatastringheader

Extra data to store in the submission's metadata attribute, as a URL-encoded query string.

X-TINT-Anonymous-UIDstringheader

An identifier of the anonymous visitor, stored with the submission.

X-TINT-Device-Fingerprintstringheader

A fingerprint of the visitor's device, stored with the submission.

Response

201Createdobject

The form submission was created.

402Payment Requiredx-errors

Payment Required. The team reached its plan's form submission limit.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Create a form submission
curl -X POST 'https://api.tintup.com/v2/teams/{team_id}/experiences/{experience_id}/form_submissions' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d '{
    "first_name": "Jane",
    "last_name": "Doe",
    "email": "jane.doe@example.com"
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/experiences/{experience_id}/form_submissions', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
  },
  body: JSON.stringify({
      "first_name": "Jane",
      "last_name": "Doe",
      "email": "jane.doe@example.com"
    }),
});

const data = await response.json();
import requests

payload = {
  "first_name": "Jane",
  "last_name": "Doe",
  "email": "jane.doe@example.com"
}

response = requests.post('https://api.tintup.com/v2/teams/{team_id}/experiences/{experience_id}/form_submissions', json=payload)
data = response.json()
Request Body
{
  "first_name": "Jane",
  "last_name": "Doe",
  "email": "jane.doe@example.com"
}
{
  "first_name": "Jane",
  "last_name": "Doe",
  "email": "jane.doe@example.com"
}
{
  "data": {
    "id": "88213",
    "type": "form_submission",
    "attributes": {
      "data": {
        "first_name": "Jane",
        "last_name": "Doe",
        "email": "jane.doe@example.com"
      },
      "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 14_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Safari/605.1.15",
      "referer": "https://contests.example.com/summer-sweepstakes",
      "locale": "en",
      "metadata": {
        "utm_source": "newsletter"
      },
      "remote_ip_city": "Vancouver",
      "remote_ip_most_specific_subdivision": "BC",
      "remote_ip_country": "CA",
      "city": "Vancouver, BC, CA",
      "created_at": "2025-03-14T16:42:07.000Z"
    },
    "relationships": {
      "person": {
        "data": {
          "type": "person",
          "id": "65f3a1c2e4b0a91d2c7e8f10"
        }
      },
      "experience": {
        "data": {
          "type": "experience",
          "id": "42"
        },
        "meta": {
          "included": false
        }
      },
      "post": {
        "data": {
          "type": "post",
          "id": "7731902"
        },
        "meta": {
          "included": false
        }
      },
      "terms": {
        "meta": {
          "included": false
        }
      },
      "files": {
        "data": [
          {
            "type": "upload",
            "id": "eyJfcmFpbHMiOnsiZGF0YSI6NDU2NzgsInB1ciI6ImJsb2JfaWQifX0=--1a2b3c4d5e6f70819a2b3c4d5e6f708192a3b4c5"
          }
        ],
        "meta": {
          "included": false
        }
      }
    }
  }
}
{
  "errors": [
    {
      "code": "4020002",
      "title": "Payment Required",
      "status": "402",
      "detail": "Form submission limit reached"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Delete all form submissions

DELETE
https://api.tintup.com/v2/teams/{team_id}/experiences/{experience_id}/form_submissions

Deletes all of the experience's form submissions. Requires access to the experience.

Parameters

team_idintegerrequiredpath

The ID of the team.

experience_idintegerrequiredpath

The ID of the experience.

Response

204No Content

No Content. The request succeeded and there is no response body.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: form_submissions:write

Delete all form submissions
curl -X DELETE 'https://api.tintup.com/v2/teams/{team_id}/experiences/{experience_id}/form_submissions'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/experiences/{experience_id}/form_submissions', {
  method: 'DELETE',
});

const data = await response.json();
import requests

response = requests.delete('https://api.tintup.com/v2/teams/{team_id}/experiences/{experience_id}/form_submissions')
data = response.json()
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Delete a form submission

DELETE
https://api.tintup.com/v2/teams/{team_id}/experiences/{experience_id}/form_submissions/{form_submission_id}

Deletes the form submission.

Parameters

team_idintegerrequiredpath

The ID of the team.

experience_idintegerrequiredpath

The ID of the experience.

form_submission_idintegerrequiredpath

The ID of the form submission.

Response

204No Content

No Content. The request succeeded and there is no response body.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: form_submissions:write

Delete a form submission
curl -X DELETE 'https://api.tintup.com/v2/teams/{team_id}/experiences/{experience_id}/form_submissions/{form_submission_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/experiences/{experience_id}/form_submissions/{form_submission_id}', {
  method: 'DELETE',
});

const data = await response.json();
import requests

response = requests.delete('https://api.tintup.com/v2/teams/{team_id}/experiences/{experience_id}/form_submissions/{form_submission_id}')
data = response.json()
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Retrieve form submission metrics

GET
https://api.tintup.com/v2/teams/{team_id}/experiences/{experience_id}/form_submissions/metrics

Returns form submission counts grouped by the group parameter. The request's Referer must be allowed for the experience. When called without an Authorization header, this endpoint is public.

Parameters

team_idintegerrequiredpath

The ID of the team.

experience_idintegerrequiredpath

The ID of the experience.

groupstringcreated_atcreated_at.minutecreated_at.hourcreated_at.daycreated_at.weekcreated_at.monthcreated_at.quartercreated_at.yearcreated_at.decadecreated_at.centurycreated_at.millenniumpost_idremote_ipdatadata.keyscreated_at.millenniumquery

How to group the submissions. created_at.{unit} groups by the beginning of each interval (created_at alone is the same as created_at.millennium, which returns a single total). post_id sums the votes per post of a poll experience. remote_ip groups by the submitter's IP address. data (or data.keys) sums the integer values of each data key.

filterobjectquery

Filters the form submissions that are counted.

includeArray<string>postquery

A comma-separated list of related resources to include in the response. post only applies when grouping by post_id for a poll experience.

pageobjectquery

Offset pagination. Use page[size] to set the number of items per page and page[number] to select a page. The response's links object contains ready-to-use URLs for the next and previous pages.

Response

200OKobject

A list of form submission metrics, sorted by group value in descending order.

400Bad Requestx-errors

Bad Request. The group query parameter is invalid.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Retrieve form submission metrics
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/experiences/{experience_id}/form_submissions/metrics'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/experiences/{experience_id}/form_submissions/metrics', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/experiences/{experience_id}/form_submissions/metrics')
data = response.json()
{
  "data": [
    {
      "id": "2025-03-01T00:00:00.000Z",
      "type": "form_submission_metric",
      "attributes": {
        "count": 128,
        "created_at": "2025-03-01T00:00:00.000Z",
        "key": "vote",
        "post_id": "7731902"
      },
      "relationships": {
        "post": {
          "data": {
            "type": "post",
            "id": "7731902"
          },
          "meta": {
            "included": false
          }
        }
      }
    }
  ],
  "links": {
    "self": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=2",
    "first": "https://api.tintup.com/v2/teams/1/tints",
    "next": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=3",
    "prev": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=1"
  }
}
{
  "errors": [
    {
      "code": "400",
      "title": "Bad request",
      "status": "400"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Create a form submission export request

POST
https://api.tintup.com/v2/teams/{team_id}/experiences/{experience_id}/form_submissions/export/requests

Form submissions are exported asynchronously. Once complete, a websocket message of type form_submissions_export_request containing the status and URL is delivered to the user's private channel (private-user- followed by the user's ID), and the exported webhook event is sent. You may also poll the export request until it completes.

Body

application/vnd.api+json

The experience and the submissions to export.

dataNewFormSubmissionExportRequestrequired
Show child attributes
typestringform_submission_export_requestrequired
attributesobjectrequired
Show child attributes
experience_idintegerrequired

The ID of the experience whose submissions are exported. This, not the experience_id in the path, determines which experience is exported; the user must have access to it.

filtersobject

Only exports the submissions matching these filters.

Show child attributes
created_atobject

Only exports the submissions created in this range. Either bound can be left out.

Show child attributes
$gtestring<date-time>

Created on or after this date and time.

$ltestring<date-time>

Created on or before this date and time.

include_filesbooleanfalse

Whether to add the submitted files to the ZIP file.

Parameters

team_idintegerrequiredpath

The ID of the team.

experience_idintegerrequiredpath

The ID of the experience.

includeArray<string>experienceformuserquery

A comma-separated list of related resources to include in the response.

Response

202Acceptedobject

The form submission export request.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: form_submissions:read

Create a form submission export request
curl -X POST 'https://api.tintup.com/v2/teams/{team_id}/experiences/{experience_id}/form_submissions/export/requests' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "form_submission_export_request",
      "attributes": {
        "experience_id": 42,
        "filters": {
          "created_at": {
            "$gte": "2025-03-01T00:00:00.000Z",
            "$lte": "2025-03-31T23:59:59.000Z"
          }
        },
        "include_files": true
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/experiences/{experience_id}/form_submissions/export/requests', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "form_submission_export_request",
        "attributes": {
          "experience_id": 42,
          "filters": {
            "created_at": {
              "$gte": "2025-03-01T00:00:00.000Z",
              "$lte": "2025-03-31T23:59:59.000Z"
            }
          },
          "include_files": true
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "form_submission_export_request",
    "attributes": {
      "experience_id": 42,
      "filters": {
        "created_at": {
          "$gte": "2025-03-01T00:00:00.000Z",
          "$lte": "2025-03-31T23:59:59.000Z"
        }
      },
      "include_files": True
    }
  }
}

response = requests.post('https://api.tintup.com/v2/teams/{team_id}/experiences/{experience_id}/form_submissions/export/requests', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "form_submission_export_request",
    "attributes": {
      "experience_id": 42,
      "filters": {
        "created_at": {
          "$gte": "2025-03-01T00:00:00.000Z",
          "$lte": "2025-03-31T23:59:59.000Z"
        }
      },
      "include_files": true
    }
  }
}
{
  "data": {
    "id": "OxZZQtuh5sXIKA",
    "type": "form_submission_export_request",
    "attributes": {
      "status": "pending",
      "url": null
    },
    "relationships": {
      "experience": {
        "data": {
          "type": "experience",
          "id": "42"
        },
        "meta": {
          "included": false
        }
      },
      "form": {
        "data": {
          "type": "experience",
          "id": "42"
        },
        "meta": {
          "included": false
        }
      },
      "user": {
        "data": {
          "type": "user",
          "id": "7"
        },
        "meta": {
          "included": false
        }
      }
    },
    "links": {
      "self": "https://api.tintup.com/v2/teams/1/experiences/42/form_submissions/export/requests/OxZZQtuh5sXIKA"
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Retrieve a form submission export request

GET
https://api.tintup.com/v2/teams/{team_id}/experiences/{experience_id}/form_submissions/export/requests/{form_submission_export_request_id}

Use this endpoint to check the status of an asynchronous form submission export request. Requires access to the exported experience.

Parameters

team_idintegerrequiredpath

The ID of the team.

experience_idintegerrequiredpath

The ID of the experience.

form_submission_export_request_idstringrequiredpath

The ID of the export request.

includeArray<string>experienceformuserquery

A comma-separated list of related resources to include in the response.

Response

200OKobject

The form submission export request.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: form_submissions:read

Retrieve a form submission export request
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/experiences/{experience_id}/form_submissions/export/requests/{form_submission_export_request_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/experiences/{experience_id}/form_submissions/export/requests/{form_submission_export_request_id}', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/experiences/{experience_id}/form_submissions/export/requests/{form_submission_export_request_id}')
data = response.json()
{
  "data": {
    "id": "OxZZQtuh5sXIKA",
    "type": "form_submission_export_request",
    "attributes": {
      "status": "pending",
      "url": null
    },
    "relationships": {
      "experience": {
        "data": {
          "type": "experience",
          "id": "42"
        },
        "meta": {
          "included": false
        }
      },
      "form": {
        "data": {
          "type": "experience",
          "id": "42"
        },
        "meta": {
          "included": false
        }
      },
      "user": {
        "data": {
          "type": "user",
          "id": "7"
        },
        "meta": {
          "included": false
        }
      }
    },
    "links": {
      "self": "https://api.tintup.com/v2/teams/1/experiences/42/form_submissions/export/requests/OxZZQtuh5sXIKA"
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

E-commerce

group_ecommerce
E-commerce

Product Accounts

product_accounts

Retrieve a list of product accounts

GET
https://api.tintup.com/v2/teams/{team_id}/product_accounts

Parameters

team_idintegerrequiredpath

The ID of the team.

filterobjectquery

Filters. List filters take comma-separated values and match any of them.

includeArray<string>catalogsproduct_feedsquery

A comma-separated list of related resources to include in the response.

pageobjectquery

Offset pagination. Use page[size] to set the number of items per page and page[number] to select a page. The response's links object contains ready-to-use URLs for the next and previous pages.

Response

200OKobject

A list of product accounts.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: product_accounts:read

Retrieve a list of product accounts
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/product_accounts'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/product_accounts', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/product_accounts')
data = response.json()
{
  "data": [
    {
      "id": "1",
      "type": "product_account",
      "attributes": {
        "type": "shopify",
        "external_id": "acme.myshopify.com",
        "name": "acme",
        "username": null,
        "image_url": null,
        "site": "https://acme.myshopify.com/",
        "status": "ok",
        "expires_at": null,
        "created_at": "2025-03-14T16:42:07.000Z",
        "updated_at": "2025-03-14T16:42:07.000Z"
      },
      "relationships": {
        "catalogs": {
          "data": [
            {
              "type": "catalog",
              "id": "1098765432101234"
            }
          ],
          "meta": {
            "included": false
          }
        },
        "product_feeds": {
          "data": [
            {
              "type": "product_feed",
              "id": "12"
            }
          ],
          "meta": {
            "count": 1
          }
        }
      }
    }
  ],
  "links": {
    "self": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=2",
    "first": "https://api.tintup.com/v2/teams/1/tints",
    "next": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=3",
    "prev": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=1"
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}

Create a product account

POST
https://api.tintup.com/v2/teams/{team_id}/product_accounts

Connects a product integration using credentials, without going through the authorization flow. Which attributes are required depends on type. The account profile is fetched from the source before the response is returned.

Body

application/vnd.api+json

The product account to create.

dataNewProductAccountrequired
Show child attributes
typestringproduct_account

The resource type.

attributesProductAccountCredentials & objectrequired

Parameters

team_idintegerrequiredpath

The ID of the team.

Response

201Createdobject

The product account.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: product_accounts:write

Create a product account
curl -X POST 'https://api.tintup.com/v2/teams/{team_id}/product_accounts' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "product_account",
      "attributes": {
        "site": "https://shop.example.com",
        "access_token": "ck_4f7e2a9c1b3d5e6f",
        "secret": "cs_9a8b7c6d5e4f3a2b",
        "external_id": "acme-product-exports",
        "type": "woocommerce"
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/product_accounts', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "product_account",
        "attributes": {
          "site": "https://shop.example.com",
          "access_token": "ck_4f7e2a9c1b3d5e6f",
          "secret": "cs_9a8b7c6d5e4f3a2b",
          "external_id": "acme-product-exports",
          "type": "woocommerce"
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "product_account",
    "attributes": {
      "site": "https://shop.example.com",
      "access_token": "ck_4f7e2a9c1b3d5e6f",
      "secret": "cs_9a8b7c6d5e4f3a2b",
      "external_id": "acme-product-exports",
      "type": "woocommerce"
    }
  }
}

response = requests.post('https://api.tintup.com/v2/teams/{team_id}/product_accounts', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "product_account",
    "attributes": {
      "type": "woocommerce",
      "site": "https://shop.example.com",
      "access_token": "ck_4f7e2a9c1b3d5e6f",
      "secret": "cs_9a8b7c6d5e4f3a2b"
    }
  }
}
{
  "data": {
    "type": "product_account",
    "attributes": {
      "type": "s3",
      "site": "us-east-1",
      "external_id": "acme-product-exports"
    }
  }
}
{
  "data": {
    "id": "1",
    "type": "product_account",
    "attributes": {
      "type": "shopify",
      "external_id": "acme.myshopify.com",
      "name": "acme",
      "username": null,
      "image_url": null,
      "site": "https://acme.myshopify.com/",
      "status": "ok",
      "expires_at": null,
      "created_at": "2025-03-14T16:42:07.000Z",
      "updated_at": "2025-03-14T16:42:07.000Z"
    },
    "relationships": {
      "catalogs": {
        "data": [
          {
            "type": "catalog",
            "id": "1098765432101234"
          }
        ],
        "meta": {
          "included": false
        }
      },
      "product_feeds": {
        "data": [
          {
            "type": "product_feed",
            "id": "12"
          }
        ],
        "meta": {
          "count": 1
        }
      }
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Retrieve a product account

GET
https://api.tintup.com/v2/teams/{team_id}/product_accounts/{product_account_id}

Parameters

team_idintegerrequiredpath

The ID of the team.

product_account_idintegerrequiredpath

The ID of the product account.

includeArray<string>catalogsproduct_feedsquery

A comma-separated list of related resources to include in the response.

Response

200OKobject

The product account.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: product_accounts:read

Retrieve a product account
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/product_accounts/{product_account_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/product_accounts/{product_account_id}', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/product_accounts/{product_account_id}')
data = response.json()
{
  "data": {
    "id": "1",
    "type": "product_account",
    "attributes": {
      "type": "shopify",
      "external_id": "acme.myshopify.com",
      "name": "acme",
      "username": null,
      "image_url": null,
      "site": "https://acme.myshopify.com/",
      "status": "ok",
      "expires_at": null,
      "created_at": "2025-03-14T16:42:07.000Z",
      "updated_at": "2025-03-14T16:42:07.000Z"
    },
    "relationships": {
      "catalogs": {
        "data": [
          {
            "type": "catalog",
            "id": "1098765432101234"
          }
        ],
        "meta": {
          "included": false
        }
      },
      "product_feeds": {
        "data": [
          {
            "type": "product_feed",
            "id": "12"
          }
        ],
        "meta": {
          "count": 1
        }
      }
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Delete a product account

DELETE
https://api.tintup.com/v2/teams/{team_id}/product_accounts/{product_account_id}

Only product accounts without product feeds can be deleted; otherwise the request fails with 403 Forbidden. Delete the product feeds first.

Parameters

team_idintegerrequiredpath

The ID of the team.

product_account_idintegerrequiredpath

The ID of the product account.

Response

204No Content

No Content. The request succeeded and there is no response body.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: product_accounts:write

Delete a product account
curl -X DELETE 'https://api.tintup.com/v2/teams/{team_id}/product_accounts/{product_account_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/product_accounts/{product_account_id}', {
  method: 'DELETE',
});

const data = await response.json();
import requests

response = requests.delete('https://api.tintup.com/v2/teams/{team_id}/product_accounts/{product_account_id}')
data = response.json()
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Update a product account

PATCH
https://api.tintup.com/v2/teams/{team_id}/product_accounts/{product_account_id}

Updates the credentials of a product account. Changing credentials resets status to ok.

Body

application/vnd.api+json

The product account credentials to change.

dataProductAccountUpdaterequired
Show child attributes
idstring

The ID of the product account being updated.

typestringproduct_account

The resource type.

attributesProductAccountCredentialsrequired

The credentials to change. The type of a product account can't be changed; the same per-type rules as on creation apply to the resulting credentials.

Parameters

team_idintegerrequiredpath

The ID of the team.

product_account_idintegerrequiredpath

The ID of the product account.

Response

200OKobject

The product account.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: product_accounts:write

Update a product account
curl -X PATCH 'https://api.tintup.com/v2/teams/{team_id}/product_accounts/{product_account_id}' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "id": "7",
      "type": "product_account",
      "attributes": {
        "access_token": "ck_1a2b3c4d5e6f7a8b",
        "secret": "cs_8b7a6f5e4d3c2b1a"
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/product_accounts/{product_account_id}', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "id": "7",
        "type": "product_account",
        "attributes": {
          "access_token": "ck_1a2b3c4d5e6f7a8b",
          "secret": "cs_8b7a6f5e4d3c2b1a"
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "id": "7",
    "type": "product_account",
    "attributes": {
      "access_token": "ck_1a2b3c4d5e6f7a8b",
      "secret": "cs_8b7a6f5e4d3c2b1a"
    }
  }
}

response = requests.patch('https://api.tintup.com/v2/teams/{team_id}/product_accounts/{product_account_id}', json=payload)
data = response.json()
Request Body
{
  "data": {
    "id": "7",
    "type": "product_account",
    "attributes": {
      "access_token": "ck_1a2b3c4d5e6f7a8b",
      "secret": "cs_8b7a6f5e4d3c2b1a"
    }
  }
}
{
  "data": {
    "id": "1",
    "type": "product_account",
    "attributes": {
      "type": "shopify",
      "external_id": "acme.myshopify.com",
      "name": "acme",
      "username": null,
      "image_url": null,
      "site": "https://acme.myshopify.com/",
      "status": "ok",
      "expires_at": null,
      "created_at": "2025-03-14T16:42:07.000Z",
      "updated_at": "2025-03-14T16:42:07.000Z"
    },
    "relationships": {
      "catalogs": {
        "data": [
          {
            "type": "catalog",
            "id": "1098765432101234"
          }
        ],
        "meta": {
          "included": false
        }
      },
      "product_feeds": {
        "data": [
          {
            "type": "product_feed",
            "id": "12"
          }
        ],
        "meta": {
          "count": 1
        }
      }
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Reauthenticate a product account

GET
https://api.tintup.com/v2/teams/{team_id}/product_accounts/{product_account_id}/edit

Returns the URL of the third-party authorization page for the product account. Open this URL (usually in a popup window) so the user can grant access again. Once the user completes the authorization flow, the product account is updated and the result is delivered using the origin or redirect_uri options.

Parameters

team_idintegerrequiredpath

The ID of the team.

product_account_idintegerrequiredpath

The ID of the product account.

originstringquery

When specified, once the user completes the authorization flow, the response body is posted to the window that opened the authorization page using window.postMessage, with this value as the target origin.

redirect_uristring<uri>query

When specified, once the user completes the authorization flow, the user is redirected to this URI with a data query parameter containing the response encoded using Base64.

Response

200OKobject

The URL of the third-party authorization page.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: product_accounts:write

Reauthenticate a product account
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/product_accounts/{product_account_id}/edit'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/product_accounts/{product_account_id}/edit', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/product_accounts/{product_account_id}/edit')
data = response.json()
{
  "data": {
    "id": "5d41402abc4b2a76b9719d911017c592",
    "type": "redirect",
    "attributes": {
      "url": "https://acme.myshopify.com/admin/oauth/authorize?client_id=3f2a1b&scope=read_products&state=eyJhbGciOiJIUzI1NiJ9"
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Authenticate a product account

GET
https://api.tintup.com/v2/teams/{team_id}/product_accounts/new

Returns the URL of the third-party authorization page for the requested product account type. Open this URL (usually in a popup window) so the user can grant access. Once the user completes the authorization flow, the product account is created and the result is delivered using the origin or redirect_uri options.

Parameters

team_idintegerrequiredpath

The ID of the team.

typestringfacebookshopifyrequiredquery

The type of product account to authenticate. Only types that use an authorization flow are supported.

sitestringquery

The Shopify store URL. Required when type is shopify; ignored otherwise.

originstringquery

When specified, once the user completes the authorization flow, the response body is posted to the window that opened the authorization page using window.postMessage, with this value as the target origin.

redirect_uristring<uri>query

When specified, once the user completes the authorization flow, the user is redirected to this URI with a data query parameter containing the response encoded using Base64.

Response

200OKobject

The URL of the third-party authorization page.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: product_accounts:write

Authenticate a product account
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/product_accounts/new'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/product_accounts/new', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/product_accounts/new')
data = response.json()
{
  "data": {
    "id": "5d41402abc4b2a76b9719d911017c592",
    "type": "redirect",
    "attributes": {
      "url": "https://acme.myshopify.com/admin/oauth/authorize?client_id=3f2a1b&scope=read_products&state=eyJhbGciOiJIUzI1NiJ9"
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
E-commerce

Product Feeds

product_feeds

Create a product feed refresh request

POST
https://api.tintup.com/v2/teams/{team_id}/product_feeds/{product_feed_id}/product_feed_refresh_requests

Asynchronously re-syncs a product feed or, for csv product feeds, imports a new CSV file. All product feeds, with the exception of manual feeds, can be refreshed.

We regularly update feeds managed through our integration partners, but you may trigger a refresh using this endpoint at any time. This is particularly useful if you have made product changes that you would like reflected in TrueLoyal immediately.

For csv product feeds, you can use this endpoint to upload a new CSV file. The file must be in the prescribed format.

When the request is invalid, the product feed's status is set to error and error_message describes the problem.

Body

application/vnd.api+json

The product feed to refresh and, for csv feeds, the CSV file to import.

dataNewProductFeedRefreshRequestrequired
Show child attributes
typestringproduct_feed_refresh_request

The resource type.

attributesobjectrequired
Show child attributes
product_feed_idstringrequired

The ID of the product feed to refresh. Must match the product_feed_id in the path.

urlstring<uri> | null

Required for csv product feeds, and must be omitted for other feeds. The HTTP or HTTPS URL of a CSV file formatted according to the import requirements.

Parameters

team_idintegerrequiredpath

The ID of the team.

product_feed_idintegerrequiredpath

The ID of the product feed.

Response

202Acceptedobject

The product feed refresh request.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: product_feeds:write

Create a product feed refresh request
curl -X POST 'https://api.tintup.com/v2/teams/{team_id}/product_feeds/{product_feed_id}/product_feed_refresh_requests' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "product_feed_refresh_request",
      "attributes": {
        "product_feed_id": "12",
        "url": "https://files.example.com/exports/products.csv"
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/product_feeds/{product_feed_id}/product_feed_refresh_requests', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "product_feed_refresh_request",
        "attributes": {
          "product_feed_id": "12",
          "url": "https://files.example.com/exports/products.csv"
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "product_feed_refresh_request",
    "attributes": {
      "product_feed_id": "12",
      "url": "https://files.example.com/exports/products.csv"
    }
  }
}

response = requests.post('https://api.tintup.com/v2/teams/{team_id}/product_feeds/{product_feed_id}/product_feed_refresh_requests', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "product_feed_refresh_request",
    "attributes": {
      "product_feed_id": "12",
      "url": "https://files.example.com/exports/products.csv"
    }
  }
}
{
  "data": {
    "type": "product_feed_refresh_request",
    "attributes": {
      "product_feed_id": "12"
    }
  }
}
{
  "data": {
    "id": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InByb2R1Y3RfaW1wb3J0X3JlcXVlc3R8NDIifQ.c2lnbmF0dXJl",
    "type": "product_feed_refresh_request",
    "attributes": {
      "status": "pending"
    },
    "relationships": {
      "product_feed": {
        "data": {
          "type": "product_feed",
          "id": "12"
        },
        "meta": {
          "included": false
        }
      }
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Retrieve a product feed refresh request

GET
https://api.tintup.com/v2/teams/{team_id}/product_feeds/{product_feed_id}/product_feed_refresh_requests/{product_feed_refresh_request_id}

Returns the status of a product feed refresh request.

Parameters

team_idintegerrequiredpath

The ID of the team.

product_feed_idintegerrequiredpath

The ID of the product feed.

product_feed_refresh_request_idstringrequiredpath

The ID of the product feed refresh request, as returned when the refresh was requested (an opaque string).

Response

200OKobject

The product feed refresh request.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: product_feeds:write

Retrieve a product feed refresh request
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/product_feeds/{product_feed_id}/product_feed_refresh_requests/{product_feed_refresh_request_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/product_feeds/{product_feed_id}/product_feed_refresh_requests/{product_feed_refresh_request_id}', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/product_feeds/{product_feed_id}/product_feed_refresh_requests/{product_feed_refresh_request_id}')
data = response.json()
{
  "data": {
    "id": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InByb2R1Y3RfaW1wb3J0X3JlcXVlc3R8NDIifQ.c2lnbmF0dXJl",
    "type": "product_feed_refresh_request",
    "attributes": {
      "status": "pending"
    },
    "relationships": {
      "product_feed": {
        "data": {
          "type": "product_feed",
          "id": "12"
        },
        "meta": {
          "included": false
        }
      }
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Retrieve a list of product feeds

GET
https://api.tintup.com/v2/teams/{team_id}/product_feeds

Parameters

team_idintegerrequiredpath

The ID of the team.

filterobjectquery

Filters. List filters take comma-separated values and match any of them.

sortstring-idquery

A comma-separated list of attributes to sort by (for example, name, created_at or id). Prefix an attribute with - to sort in descending order.

includeArray<string>catalogproduct_accountproductsquery

A comma-separated list of related resources to include in the response.

pageobjectquery

Offset pagination. Use page[size] to set the number of items per page and page[number] to select a page. The response's links object contains ready-to-use URLs for the next and previous pages.

Response

200OKobject

A list of product feeds.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: product_feeds:read

Retrieve a list of product feeds
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/product_feeds'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/product_feeds', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/product_feeds')
data = response.json()
{
  "data": [
    {
      "id": "1",
      "type": "product_feed",
      "attributes": {
        "name": "Acme spring collection",
        "source": "shopify",
        "status": "active",
        "options": {
          "delete_files_once_processed": false
        },
        "last_ingested_at": "2025-03-14T16:42:07.000Z",
        "error_message": null
      },
      "relationships": {
        "product_account": {
          "data": {
            "type": "product_account",
            "id": "7"
          },
          "meta": {
            "included": false
          }
        },
        "catalog": {
          "data": {
            "type": "catalog",
            "id": "1098765432101234"
          },
          "meta": {
            "included": false
          }
        },
        "products": {
          "data": [
            {
              "type": "product",
              "id": "1234"
            }
          ],
          "meta": {
            "count": 124
          }
        }
      }
    }
  ],
  "links": {
    "self": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=2",
    "first": "https://api.tintup.com/v2/teams/1/tints",
    "next": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=3",
    "prev": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=1"
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}

Create a product feed

POST
https://api.tintup.com/v2/teams/{team_id}/product_feeds

Creates a product feed and starts importing its products in the background (except for manual feeds, whose products are created using the API). Which attributes are required depends on source.

Body

application/vnd.api+json

The product feed to create.

dataNewProductFeedrequired
Show child attributes
typestringproduct_feed

The resource type.

attributesobjectrequired
Show child attributes
sourcesourceTypesbazaarvoicebigcommercecsvfacebookftphttpmagentomanuals3salesforce_commerce_cloudsftpshopifywoocommercerequired

The source of the products: the type of the product account (product integration) it syncs from, csv for a CSV file imported from a URL, or manual for products managed using the API.

namestring | null

The name of the product feed. Required when source is manual; optional for csv; must be omitted for the other sources (the name is derived from the source).

product_account_idinteger | null

The ID of the product account to sync from. Required for every source except csv and manual, for which it must be omitted. The product account's type must match source. Except for facebook, ftp, http, s3 and sftp, a product account can only have one product feed.

catalog_idstring | null

Required when source is facebook (the catalog ID), ftp, sftp or http (the path of the CSV file; for ftp and sftp, a path ending with / imports every .csv file in that directory), or s3 (the object key in the bucket). Must be omitted for the other sources. Must be unique for the product account.

urlstring<uri>write only

Required when source is csv, and must be omitted otherwise. The HTTP or HTTPS URL of the CSV file to import. Its header row must include the sku, name, image_url and url columns.

optionsProductFeedOptions

Source-specific options.

Show child attributes
delete_files_once_processedbooleanfalse

Whether to delete the file from the server or bucket once it has been imported. Only used when source is ftp, sftp or s3.

Parameters

team_idintegerrequiredpath

The ID of the team.

Response

201Createdobject

The product feed.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: product_feeds:write

Create a product feed
curl -X POST 'https://api.tintup.com/v2/teams/{team_id}/product_feeds' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "product_feed",
      "attributes": {
        "source": "shopify",
        "name": "Acme spring collection",
        "product_account_id": 7,
        "catalog_id": "/exports/products.csv",
        "url": "https://files.example.com/exports/products.csv",
        "options": {
          "delete_files_once_processed": false
        }
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/product_feeds', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "product_feed",
        "attributes": {
          "source": "shopify",
          "name": "Acme spring collection",
          "product_account_id": 7,
          "catalog_id": "/exports/products.csv",
          "url": "https://files.example.com/exports/products.csv",
          "options": {
            "delete_files_once_processed": false
          }
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "product_feed",
    "attributes": {
      "source": "shopify",
      "name": "Acme spring collection",
      "product_account_id": 7,
      "catalog_id": "/exports/products.csv",
      "url": "https://files.example.com/exports/products.csv",
      "options": {
        "delete_files_once_processed": False
      }
    }
  }
}

response = requests.post('https://api.tintup.com/v2/teams/{team_id}/product_feeds', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "product_feed",
    "attributes": {
      "source": "shopify",
      "product_account_id": 7
    }
  }
}
{
  "data": {
    "type": "product_feed",
    "attributes": {
      "source": "csv",
      "name": "Acme spring collection",
      "url": "https://files.example.com/exports/products.csv"
    }
  }
}
{
  "data": {
    "type": "product_feed",
    "attributes": {
      "source": "manual",
      "name": "Acme spring collection"
    }
  }
}
{
  "data": {
    "id": "1",
    "type": "product_feed",
    "attributes": {
      "name": "Acme spring collection",
      "source": "shopify",
      "status": "active",
      "options": {
        "delete_files_once_processed": false
      },
      "last_ingested_at": "2025-03-14T16:42:07.000Z",
      "error_message": null
    },
    "relationships": {
      "product_account": {
        "data": {
          "type": "product_account",
          "id": "7"
        },
        "meta": {
          "included": false
        }
      },
      "catalog": {
        "data": {
          "type": "catalog",
          "id": "1098765432101234"
        },
        "meta": {
          "included": false
        }
      },
      "products": {
        "data": [
          {
            "type": "product",
            "id": "1234"
          }
        ],
        "meta": {
          "count": 124
        }
      }
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Retrieve a product feed

GET
https://api.tintup.com/v2/teams/{team_id}/product_feeds/{product_feed_id}

Parameters

team_idintegerrequiredpath

The ID of the team.

product_feed_idintegerrequiredpath

The ID of the product feed.

includeArray<string>catalogproduct_accountproductsquery

A comma-separated list of related resources to include in the response.

Response

200OKobject

The product feed.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: product_feeds:read

Retrieve a product feed
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/product_feeds/{product_feed_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/product_feeds/{product_feed_id}', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/product_feeds/{product_feed_id}')
data = response.json()
{
  "data": {
    "id": "1",
    "type": "product_feed",
    "attributes": {
      "name": "Acme spring collection",
      "source": "shopify",
      "status": "active",
      "options": {
        "delete_files_once_processed": false
      },
      "last_ingested_at": "2025-03-14T16:42:07.000Z",
      "error_message": null
    },
    "relationships": {
      "product_account": {
        "data": {
          "type": "product_account",
          "id": "7"
        },
        "meta": {
          "included": false
        }
      },
      "catalog": {
        "data": {
          "type": "catalog",
          "id": "1098765432101234"
        },
        "meta": {
          "included": false
        }
      },
      "products": {
        "data": [
          {
            "type": "product",
            "id": "1234"
          }
        ],
        "meta": {
          "count": 124
        }
      }
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Delete a product feed

DELETE
https://api.tintup.com/v2/teams/{team_id}/product_feeds/{product_feed_id}

Deletes the product feed and all of its products.

Parameters

team_idintegerrequiredpath

The ID of the team.

product_feed_idintegerrequiredpath

The ID of the product feed.

Response

204No Content

No Content. The request succeeded and there is no response body.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: product_feeds:write

Delete a product feed
curl -X DELETE 'https://api.tintup.com/v2/teams/{team_id}/product_feeds/{product_feed_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/product_feeds/{product_feed_id}', {
  method: 'DELETE',
});

const data = await response.json();
import requests

response = requests.delete('https://api.tintup.com/v2/teams/{team_id}/product_feeds/{product_feed_id}')
data = response.json()
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}
E-commerce

Product Tags

product_tags

Create a product tag

POST
https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/product_tags

Tags a product in a post of the board, optionally within a bounding box of the post's media.

Body

application/vnd.api+json

The product tag to create.

dataNewProductTagrequired
Show child attributes
typestringproduct_tag

The resource type.

attributesProductTagCoordinates & objectrequired

Parameters

team_idintegerrequiredpath

The ID of the team.

tint_idintegerrequiredpath

The ID of the board.

includeArray<string>productquery

A comma-separated list of related resources to include in the response.

Response

201Createdobject

The product tag.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: posts:write

Create a product tag
curl -X POST 'https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/product_tags' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "product_tag",
      "attributes": {
        "product_id": 1234,
        "source": "instagram_business",
        "external_id": "17912345678901234",
        "attachment_id": "17895695668004550",
        "x": "50",
        "y": "4.3333333",
        "height": "30",
        "width": "30"
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/product_tags', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "product_tag",
        "attributes": {
          "product_id": 1234,
          "source": "instagram_business",
          "external_id": "17912345678901234",
          "attachment_id": "17895695668004550",
          "x": "50",
          "y": "4.3333333",
          "height": "30",
          "width": "30"
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "product_tag",
    "attributes": {
      "product_id": 1234,
      "source": "instagram_business",
      "external_id": "17912345678901234",
      "attachment_id": "17895695668004550",
      "x": "50",
      "y": "4.3333333",
      "height": "30",
      "width": "30"
    }
  }
}

response = requests.post('https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/product_tags', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "product_tag",
    "attributes": {
      "product_id": 1234,
      "source": "instagram_business",
      "external_id": "17912345678901234",
      "attachment_id": "17895695668004550",
      "x": "50",
      "y": "4.3333333",
      "height": "30",
      "width": "30"
    }
  }
}
{
  "data": {
    "id": "311",
    "type": "product_tag",
    "attributes": {
      "x": "50",
      "y": "4.3333333",
      "height": "30",
      "width": "30",
      "created_at": "2025-03-14T16:42:07.000Z",
      "updated_at": "2025-03-14T16:42:07.000Z"
    },
    "relationships": {
      "product": {
        "data": {
          "type": "product",
          "id": "1234"
        },
        "meta": {
          "included": false
        }
      }
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Delete a product tag

DELETE
https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/product_tags/{product_tag_id}

Removes the product tag from the post.

Parameters

team_idintegerrequiredpath

The ID of the team.

tint_idintegerrequiredpath

The ID of the board.

product_tag_idintegerrequiredpath

The ID of the product tag.

Response

204No Content

No Content. The request succeeded and there is no response body.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: posts:write

Delete a product tag
curl -X DELETE 'https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/product_tags/{product_tag_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/product_tags/{product_tag_id}', {
  method: 'DELETE',
});

const data = await response.json();
import requests

response = requests.delete('https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/product_tags/{product_tag_id}')
data = response.json()
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Update a product tag

PATCH
https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/product_tags/{product_tag_id}

Changes the bounding box or the tagged product.

Body

application/vnd.api+json

The product tag attributes to change.

dataProductTagUpdaterequired
Show child attributes
idstring

The ID of the product tag being updated.

typestringproduct_tag

The resource type.

attributesProductTagCoordinates & objectrequired

The attributes to change. The post a product tag belongs to (source, external_id and attachment_id) can't be changed.

Parameters

team_idintegerrequiredpath

The ID of the team.

tint_idintegerrequiredpath

The ID of the board.

product_tag_idintegerrequiredpath

The ID of the product tag.

includeArray<string>productquery

A comma-separated list of related resources to include in the response.

Response

200OKobject

The product tag.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: posts:write

Update a product tag
curl -X PATCH 'https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/product_tags/{product_tag_id}' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "id": "311",
      "type": "product_tag",
      "attributes": {
        "x": "42.5",
        "y": "10",
        "height": "25",
        "width": "25"
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/product_tags/{product_tag_id}', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "id": "311",
        "type": "product_tag",
        "attributes": {
          "x": "42.5",
          "y": "10",
          "height": "25",
          "width": "25"
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "id": "311",
    "type": "product_tag",
    "attributes": {
      "x": "42.5",
      "y": "10",
      "height": "25",
      "width": "25"
    }
  }
}

response = requests.patch('https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/product_tags/{product_tag_id}', json=payload)
data = response.json()
Request Body
{
  "data": {
    "id": "311",
    "type": "product_tag",
    "attributes": {
      "x": "42.5",
      "y": "10",
      "height": "25",
      "width": "25"
    }
  }
}
{
  "data": {
    "id": "311",
    "type": "product_tag",
    "attributes": {
      "x": "50",
      "y": "4.3333333",
      "height": "30",
      "width": "30",
      "created_at": "2025-03-14T16:42:07.000Z",
      "updated_at": "2025-03-14T16:42:07.000Z"
    },
    "relationships": {
      "product": {
        "data": {
          "type": "product",
          "id": "1234"
        },
        "meta": {
          "included": false
        }
      }
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}
E-commerce

Products

products

Retrieve a list of products

GET
https://api.tintup.com/v2/teams/{team_id}/products

Returns the products of the product feeds you have access to. Only active products are returned unless you filter on status. Also available as a CSV file (see the text/csv response).

Parameters

team_idintegerrequiredpath

The ID of the team.

filterobjectquery

Filters. List filters take comma-separated values and match any of them. Only products of the product feeds you have access to are returned.

sortstring-idquery

A comma-separated list of attributes to sort by (for example, name, price, created_at or id). Prefix an attribute with - to sort in descending order.

includeArray<string>product_feedquery

A comma-separated list of related resources to include in the response.

pageobjectquery

Offset pagination. Use page[size] to set the number of items per page and page[number] to select a page. The response's links object contains ready-to-use URLs for the next and previous pages.

Response

200OKobject

A list of products.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

503Service Unavailable

Service Unavailable. Product search is temporarily unavailable; retry later.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: products:read

Retrieve a list of products
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/products'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/products', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/products')
data = response.json()
{
  "data": [
    {
      "id": "1234",
      "type": "product",
      "attributes": {
        "name": "Acme Runner 2 sneakers",
        "description": "Lightweight running sneakers with a breathable mesh upper.",
        "sku": "ACME-RUN2-BLK-42",
        "brand": "Acme",
        "family": "Acme Runner 2",
        "categories": [
          "Footwear",
          "Running"
        ],
        "image_url": "https://cdn.example.com/products/acme-runner-2-black.jpg",
        "url": "https://shop.example.com/products/acme-runner-2",
        "currency": "USD",
        "price": "89.00",
        "sale_price": "69.00",
        "sale_price_starts_at": "2025-03-14T00:00:00.000Z",
        "sale_price_ends_at": "2025-03-31T23:59:59.000Z",
        "availability": "in_stock"
      },
      "relationships": {
        "product_feed": {
          "data": {
            "type": "product_feed",
            "id": "12"
          },
          "meta": {
            "included": false
          }
        }
      }
    }
  ],
  "links": {
    "self": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=2",
    "first": "https://api.tintup.com/v2/teams/1/tints",
    "next": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=3",
    "prev": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=1"
  },
  "meta": {
    "aggregations": {
      "brand": {
        "Acme": 124,
        "Globex": 37
      },
      "categories": {
        "Footwear": 98,
        "Running": 42
      },
      "family": {
        "Acme Runner 2": 6,
        "Acme Trail": 4
      }
    }
  }
}
sku,name,description,image_url,url,currency,categories,availability,price,sale_price,status,sale_price_starts_at,sale_price_ends_at,brand,family
ACME-RUN2-BLK-42,Acme Runner 2 sneakers,Lightweight running sneakers.,https://cdn.example.com/products/acme-runner-2-black.jpg,https://shop.example.com/products/acme-runner-2,USD,"Footwear,Running",in_stock,89.00,69.00,active,2025-03-14 00:00:00 UTC,2025-03-31 23:59:59 UTC,Acme,Acme Runner 2
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}

Create a product

POST
https://api.tintup.com/v2/teams/{team_id}/products

Creates a product in a manual product feed. Products of other product feeds are managed by their source and can't be created using the API.

Body

application/vnd.api+json

The product to create.

dataNewProductrequired
Show child attributes
typestringproduct

The resource type.

attributesProductWritableAttributes & objectrequired

Parameters

team_idintegerrequiredpath

The ID of the team.

Response

200OKobject

The product.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: products:write

Create a product
curl -X POST 'https://api.tintup.com/v2/teams/{team_id}/products' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "product",
      "attributes": {
        "product_feed_id": 12,
        "name": "Acme Runner 2 sneakers",
        "sku": "ACME-RUN2-BLK-42",
        "description": "Lightweight running sneakers with a breathable mesh upper.",
        "brand": "Acme",
        "family": "Acme Runner 2",
        "categories": [
          "Footwear",
          "Running"
        ],
        "image_url": "https://cdn.example.com/products/acme-runner-2-black.jpg",
        "url": "https://shop.example.com/products/acme-runner-2",
        "currency": "USD",
        "price": "89.00",
        "availability": "in_stock"
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/products', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "product",
        "attributes": {
          "product_feed_id": 12,
          "name": "Acme Runner 2 sneakers",
          "sku": "ACME-RUN2-BLK-42",
          "description": "Lightweight running sneakers with a breathable mesh upper.",
          "brand": "Acme",
          "family": "Acme Runner 2",
          "categories": [
            "Footwear",
            "Running"
          ],
          "image_url": "https://cdn.example.com/products/acme-runner-2-black.jpg",
          "url": "https://shop.example.com/products/acme-runner-2",
          "currency": "USD",
          "price": "89.00",
          "availability": "in_stock"
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "product",
    "attributes": {
      "product_feed_id": 12,
      "name": "Acme Runner 2 sneakers",
      "sku": "ACME-RUN2-BLK-42",
      "description": "Lightweight running sneakers with a breathable mesh upper.",
      "brand": "Acme",
      "family": "Acme Runner 2",
      "categories": [
        "Footwear",
        "Running"
      ],
      "image_url": "https://cdn.example.com/products/acme-runner-2-black.jpg",
      "url": "https://shop.example.com/products/acme-runner-2",
      "currency": "USD",
      "price": "89.00",
      "availability": "in_stock"
    }
  }
}

response = requests.post('https://api.tintup.com/v2/teams/{team_id}/products', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "product",
    "attributes": {
      "product_feed_id": 12,
      "name": "Acme Runner 2 sneakers",
      "sku": "ACME-RUN2-BLK-42",
      "description": "Lightweight running sneakers with a breathable mesh upper.",
      "brand": "Acme",
      "family": "Acme Runner 2",
      "categories": [
        "Footwear",
        "Running"
      ],
      "image_url": "https://cdn.example.com/products/acme-runner-2-black.jpg",
      "url": "https://shop.example.com/products/acme-runner-2",
      "currency": "USD",
      "price": "89.00",
      "availability": "in_stock"
    }
  }
}
{
  "data": {
    "id": "1234",
    "type": "product",
    "attributes": {
      "name": "Acme Runner 2 sneakers",
      "description": "Lightweight running sneakers with a breathable mesh upper.",
      "sku": "ACME-RUN2-BLK-42",
      "brand": "Acme",
      "family": "Acme Runner 2",
      "categories": [
        "Footwear",
        "Running"
      ],
      "image_url": "https://cdn.example.com/products/acme-runner-2-black.jpg",
      "url": "https://shop.example.com/products/acme-runner-2",
      "currency": "USD",
      "price": "89.00",
      "sale_price": "69.00",
      "sale_price_starts_at": "2025-03-14T00:00:00.000Z",
      "sale_price_ends_at": "2025-03-31T23:59:59.000Z",
      "availability": "in_stock"
    },
    "relationships": {
      "product_feed": {
        "data": {
          "type": "product_feed",
          "id": "12"
        },
        "meta": {
          "included": false
        }
      }
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Retrieve a product

GET
https://api.tintup.com/v2/teams/{team_id}/products/{product_id}

Parameters

team_idintegerrequiredpath

The ID of the team.

product_idintegerrequiredpath

The ID of the product.

includeArray<string>product_feedquery

A comma-separated list of related resources to include in the response.

Response

200OKobject

The product.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: products:read

Retrieve a product
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/products/{product_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/products/{product_id}', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/products/{product_id}')
data = response.json()
{
  "data": {
    "id": "1234",
    "type": "product",
    "attributes": {
      "name": "Acme Runner 2 sneakers",
      "description": "Lightweight running sneakers with a breathable mesh upper.",
      "sku": "ACME-RUN2-BLK-42",
      "brand": "Acme",
      "family": "Acme Runner 2",
      "categories": [
        "Footwear",
        "Running"
      ],
      "image_url": "https://cdn.example.com/products/acme-runner-2-black.jpg",
      "url": "https://shop.example.com/products/acme-runner-2",
      "currency": "USD",
      "price": "89.00",
      "sale_price": "69.00",
      "sale_price_starts_at": "2025-03-14T00:00:00.000Z",
      "sale_price_ends_at": "2025-03-31T23:59:59.000Z",
      "availability": "in_stock"
    },
    "relationships": {
      "product_feed": {
        "data": {
          "type": "product_feed",
          "id": "12"
        },
        "meta": {
          "included": false
        }
      }
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Delete a product

DELETE
https://api.tintup.com/v2/teams/{team_id}/products/{product_id}

Only products of manual product feeds can be deleted; other products return 404 Not Found.

Parameters

team_idintegerrequiredpath

The ID of the team.

product_idintegerrequiredpath

The ID of the product.

Response

204No Content

No Content. The request succeeded and there is no response body.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: products:write

Delete a product
curl -X DELETE 'https://api.tintup.com/v2/teams/{team_id}/products/{product_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/products/{product_id}', {
  method: 'DELETE',
});

const data = await response.json();
import requests

response = requests.delete('https://api.tintup.com/v2/teams/{team_id}/products/{product_id}')
data = response.json()
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Update a product

PATCH
https://api.tintup.com/v2/teams/{team_id}/products/{product_id}

Products of manual product feeds can be fully updated. Products of other product feeds are kept in sync with their source, so only their status can be changed (for example, to archive a product).

Body

application/vnd.api+json

The product attributes to change.

dataProductUpdaterequired
Show child attributes
idstring

The ID of the product being updated.

typestringproduct

The resource type.

attributesProductWritableAttributesrequired

The attributes to change. Products of manual product feeds accept every attribute below; products of other product feeds are kept in sync with their source, so only status is applied and the other attributes are ignored.

Parameters

team_idintegerrequiredpath

The ID of the team.

product_idintegerrequiredpath

The ID of the product.

Response

200OKobject

The product.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: products:write

Update a product
curl -X PATCH 'https://api.tintup.com/v2/teams/{team_id}/products/{product_id}' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "id": "1234",
      "type": "product",
      "attributes": {
        "sale_price": "69.00",
        "sale_price_starts_at": "2025-03-14T00:00:00.000Z",
        "sale_price_ends_at": "2025-03-31T23:59:59.000Z"
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/products/{product_id}', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "id": "1234",
        "type": "product",
        "attributes": {
          "sale_price": "69.00",
          "sale_price_starts_at": "2025-03-14T00:00:00.000Z",
          "sale_price_ends_at": "2025-03-31T23:59:59.000Z"
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "id": "1234",
    "type": "product",
    "attributes": {
      "sale_price": "69.00",
      "sale_price_starts_at": "2025-03-14T00:00:00.000Z",
      "sale_price_ends_at": "2025-03-31T23:59:59.000Z"
    }
  }
}

response = requests.patch('https://api.tintup.com/v2/teams/{team_id}/products/{product_id}', json=payload)
data = response.json()
Request Body
{
  "data": {
    "id": "1234",
    "type": "product",
    "attributes": {
      "sale_price": "69.00",
      "sale_price_starts_at": "2025-03-14T00:00:00.000Z",
      "sale_price_ends_at": "2025-03-31T23:59:59.000Z"
    }
  }
}
{
  "data": {
    "id": "1234",
    "type": "product",
    "attributes": {
      "name": "Acme Runner 2 sneakers",
      "description": "Lightweight running sneakers with a breathable mesh upper.",
      "sku": "ACME-RUN2-BLK-42",
      "brand": "Acme",
      "family": "Acme Runner 2",
      "categories": [
        "Footwear",
        "Running"
      ],
      "image_url": "https://cdn.example.com/products/acme-runner-2-black.jpg",
      "url": "https://shop.example.com/products/acme-runner-2",
      "currency": "USD",
      "price": "89.00",
      "sale_price": "69.00",
      "sale_price_starts_at": "2025-03-14T00:00:00.000Z",
      "sale_price_ends_at": "2025-03-31T23:59:59.000Z",
      "availability": "in_stock"
    },
    "relationships": {
      "product_feed": {
        "data": {
          "type": "product_feed",
          "id": "12"
        },
        "meta": {
          "included": false
        }
      }
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Rights Management

group_rights_management
Rights Management

Right Request Templates

right_request_templates

Retrieve a list of right request templates

GET
https://api.tintup.com/v2/teams/{team_id}/right_requests/templates

Returns the team's right request templates. When the team doesn't have any yet, a default set of templates is created for it first.

Parameters

team_idintegerrequiredpath

The ID of the team.

includeArray<string>tintquery

A comma-separated list of related resources to include in the response. tint is only available when the access token has the tints:read scope.

pageobjectquery

Offset pagination. Use page[size] to set the number of items per page and page[number] to select a page. The response's links object contains ready-to-use URLs for the next and previous pages.

sortArray<string>id-idcreated_at-created_atupdated_at-updated_at-idquery

A comma-separated list of fields to sort by. Prefix a field with - to sort in descending order. Defaults to -id (newest first).

filterobjectquery

Filters the right request templates.

Response

200OKobject

A list of right request templates.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: right_request_templates:read

Retrieve a list of right request templates
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/right_requests/templates'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/right_requests/templates', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/right_requests/templates')
data = response.json()
{
  "data": [
    {
      "id": "34",
      "type": "right_request_template",
      "attributes": {
        "name": "Instagram repost",
        "hashtag": "AcmeYes",
        "template": "Such a great shot! We would love to share this picture on our Instagram page. {{username}} if you agree, please reply {{approval_keyword}} and review our terms at {{terms.url}}",
        "created_at": "2025-02-20T14:05:12.000Z",
        "updated_at": "2025-03-10T08:30:45.000Z"
      },
      "relationships": {
        "tint": {
          "data": null
        }
      }
    }
  ],
  "included": [
    {}
  ],
  "links": {
    "self": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=2",
    "first": "https://api.tintup.com/v2/teams/1/tints",
    "next": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=3",
    "prev": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=1"
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}

Create a right request template

POST
https://api.tintup.com/v2/teams/{team_id}/right_requests/templates

Creates a right request template.

Body

application/vnd.api+json

The right request template to create.

dataNewRightRequestTemplaterequired
Show child attributes
typestringright_request_templaterequired

The resource type.

attributesRightRequestTemplateAttributesForWrite & objectrequired

Parameters

team_idintegerrequiredpath

The ID of the team.

includeArray<string>tintquery

A comma-separated list of related resources to include in the response. tint is only available when the access token has the tints:read scope.

Response

201Createdobject

The right request template.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: right_request_templates:write

Create a right request template
curl -X POST 'https://api.tintup.com/v2/teams/{team_id}/right_requests/templates' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "right_request_template",
      "attributes": {
        "name": "Instagram repost",
        "hashtag": "AcmeYes",
        "template": "Such a great shot! We would love to share this picture on our Instagram page. {{username}} if you agree, please reply {{approval_keyword}} and review our terms at {{terms.url}}"
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/right_requests/templates', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "right_request_template",
        "attributes": {
          "name": "Instagram repost",
          "hashtag": "AcmeYes",
          "template": "Such a great shot! We would love to share this picture on our Instagram page. {{username}} if you agree, please reply {{approval_keyword}} and review our terms at {{terms.url}}"
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "right_request_template",
    "attributes": {
      "name": "Instagram repost",
      "hashtag": "AcmeYes",
      "template": "Such a great shot! We would love to share this picture on our Instagram page. {{username}} if you agree, please reply {{approval_keyword}} and review our terms at {{terms.url}}"
    }
  }
}

response = requests.post('https://api.tintup.com/v2/teams/{team_id}/right_requests/templates', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "right_request_template",
    "attributes": {
      "name": "Instagram repost",
      "hashtag": "AcmeYes",
      "template": "Such a great shot! We would love to share this picture on our Instagram page. {{username}} if you agree, please reply {{approval_keyword}} and review our terms at {{terms.url}}"
    }
  }
}
{
  "data": {
    "id": "34",
    "type": "right_request_template",
    "attributes": {
      "name": "Instagram repost",
      "hashtag": "AcmeYes",
      "template": "Such a great shot! We would love to share this picture on our Instagram page. {{username}} if you agree, please reply {{approval_keyword}} and review our terms at {{terms.url}}",
      "created_at": "2025-02-20T14:05:12.000Z",
      "updated_at": "2025-03-10T08:30:45.000Z"
    },
    "relationships": {
      "tint": {
        "data": null
      }
    }
  },
  "included": [
    {}
  ]
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Retrieve a list of right request templates for a board

GET
https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/right_requests/templates

Returns the team's right request templates. The list isn't currently narrowed down to templates limited to the board. When the team doesn't have any templates yet, a default set is created for it first.

Parameters

team_idintegerrequiredpath

The ID of the team.

tint_idintegerrequiredpath

The ID of the board.

includeArray<string>tintquery

A comma-separated list of related resources to include in the response. tint is only available when the access token has the tints:read scope.

pageobjectquery

Offset pagination. Use page[size] to set the number of items per page and page[number] to select a page. The response's links object contains ready-to-use URLs for the next and previous pages.

sortArray<string>id-idcreated_at-created_atupdated_at-updated_at-idquery

A comma-separated list of fields to sort by. Prefix a field with - to sort in descending order. Defaults to -id (newest first).

filterobjectquery

Filters the right request templates.

Response

200OKobject

A list of right request templates.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: right_request_templates:read

Retrieve a list of right request templates for a board
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/right_requests/templates'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/right_requests/templates', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/right_requests/templates')
data = response.json()
{
  "data": [
    {
      "id": "34",
      "type": "right_request_template",
      "attributes": {
        "name": "Instagram repost",
        "hashtag": "AcmeYes",
        "template": "Such a great shot! We would love to share this picture on our Instagram page. {{username}} if you agree, please reply {{approval_keyword}} and review our terms at {{terms.url}}",
        "created_at": "2025-02-20T14:05:12.000Z",
        "updated_at": "2025-03-10T08:30:45.000Z"
      },
      "relationships": {
        "tint": {
          "data": null
        }
      }
    }
  ],
  "included": [
    {}
  ],
  "links": {
    "self": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=2",
    "first": "https://api.tintup.com/v2/teams/1/tints",
    "next": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=3",
    "prev": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=1"
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}

Delete a right request template

DELETE
https://api.tintup.com/v2/teams/{team_id}/right_requests/templates/{right_request_template_id}

Permanently deletes the template.

Parameters

team_idintegerrequiredpath

The ID of the team.

right_request_template_idintegerrequiredpath

The ID of the right request template.

Response

204No Content

No Content. The request succeeded and there is no response body.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: right_request_templates:write

Delete a right request template
curl -X DELETE 'https://api.tintup.com/v2/teams/{team_id}/right_requests/templates/{right_request_template_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/right_requests/templates/{right_request_template_id}', {
  method: 'DELETE',
});

const data = await response.json();
import requests

response = requests.delete('https://api.tintup.com/v2/teams/{team_id}/right_requests/templates/{right_request_template_id}')
data = response.json()
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Update a right request template

PATCH
https://api.tintup.com/v2/teams/{team_id}/right_requests/templates/{right_request_template_id}

Updates a right request template.

Body

application/vnd.api+json

The right request template changes.

dataRightRequestTemplateUpdaterequired
Show child attributes
idstring

The ID of the template. Optional; the template to update is identified by the right_request_template_id path parameter.

typestringright_request_templaterequired

The resource type.

attributesRightRequestTemplateAttributesForWriterequired

Only the attributes given are changed. hashtag and template can't be set to an empty value.

Parameters

team_idintegerrequiredpath

The ID of the team.

right_request_template_idintegerrequiredpath

The ID of the right request template.

includeArray<string>tintquery

A comma-separated list of related resources to include in the response. tint is only available when the access token has the tints:read scope.

Response

200OKobject

The right request template.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: right_request_templates:write

Update a right request template
curl -X PATCH 'https://api.tintup.com/v2/teams/{team_id}/right_requests/templates/{right_request_template_id}' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "id": "34",
      "type": "right_request_template",
      "attributes": {
        "hashtag": "AcmeSaysYes"
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/right_requests/templates/{right_request_template_id}', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "id": "34",
        "type": "right_request_template",
        "attributes": {
          "hashtag": "AcmeSaysYes"
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "id": "34",
    "type": "right_request_template",
    "attributes": {
      "hashtag": "AcmeSaysYes"
    }
  }
}

response = requests.patch('https://api.tintup.com/v2/teams/{team_id}/right_requests/templates/{right_request_template_id}', json=payload)
data = response.json()
Request Body
{
  "data": {
    "id": "34",
    "type": "right_request_template",
    "attributes": {
      "hashtag": "AcmeSaysYes"
    }
  }
}
{
  "data": {
    "id": "34",
    "type": "right_request_template",
    "attributes": {
      "name": "Instagram repost",
      "hashtag": "AcmeYes",
      "template": "Such a great shot! We would love to share this picture on our Instagram page. {{username}} if you agree, please reply {{approval_keyword}} and review our terms at {{terms.url}}",
      "created_at": "2025-02-20T14:05:12.000Z",
      "updated_at": "2025-03-10T08:30:45.000Z"
    },
    "relationships": {
      "tint": {
        "data": null
      }
    }
  },
  "included": [
    {}
  ]
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}
Rights Management

Right Request Terms

right_request_terms

Retrieve a list of right request terms

GET
https://api.tintup.com/v2/teams/{team_id}/right_requests/terms

Returns the team's published right request terms. Archived (deleted) terms are not included.

Parameters

team_idintegerrequiredpath

The ID of the team.

includeArray<string>tintquery

A comma-separated list of related resources to include in the response. tint is only available when the access token has the tints:read scope.

pageobjectquery

Offset pagination. Use page[size] to set the number of items per page and page[number] to select a page. The response's links object contains ready-to-use URLs for the next and previous pages.

sortArray<string>id-idname-namecreated_at-created_at-idquery

A comma-separated list of fields to sort by. Prefix a field with - to sort in descending order. Defaults to -id (newest first).

filterobjectquery

Filters the right request terms.

Response

200OKobject

A list of published right request terms.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: right_request_terms:read

Retrieve a list of right request terms
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/right_requests/terms'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/right_requests/terms', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/right_requests/terms')
data = response.json()
{
  "data": [
    {
      "id": "12",
      "type": "right_request_term",
      "attributes": {
        "name": "Standard content license",
        "title": "Acme Inc. Content License Agreement",
        "text": "# Content License Agreement\n\nBy replying with the approval hashtag, you grant Acme Inc. a non-exclusive, royalty-free, worldwide license to\nuse, reproduce, and display your post and its content on its websites, social media accounts, and marketing\nmaterials. You confirm that you own the content and that it doesn't infringe on anyone's rights.",
        "logo_url": "https://cdn.example.com/acme/logo.png",
        "url": "https://example.com/terms/12",
        "status": "published",
        "created_at": "2025-03-01T10:15:30.000Z"
      },
      "relationships": {
        "tint": {
          "data": null
        }
      }
    }
  ],
  "included": [
    {}
  ],
  "links": {
    "self": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=2",
    "first": "https://api.tintup.com/v2/teams/1/tints",
    "next": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=3",
    "prev": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=1"
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}

Create a right request term

POST
https://api.tintup.com/v2/teams/{team_id}/right_requests/terms

Creates a right request term.

Body

application/vnd.api+json

The right request term to create.

dataNewRightRequestTermrequired
Show child attributes
typestringright_request_termrequired

The resource type.

attributesobjectrequired

Either text or document is required, but not both.

Show child attributes
namestringrequired

The internal name of the terms, used to pick them when creating a right request.

titlestring | null

The title displayed on the terms page (in its title HTML element). Can't contain HTML. Must be omitted when document is given.

textstring | null

The terms, formatted with Markdown. Can't contain HTML. Required, with at least 100 characters, unless document is given, in which case it must be omitted.

logo_urlstring<uri> | null

The HTTP or HTTPS URL of the logo displayed on the terms page.

documentstringwrite only

The signed ID, as returned by a direct upload for right request terms, of a PDF or Word document (up to 20 MB) containing the terms. When given, text and title must be omitted.

Parameters

team_idintegerrequiredpath

The ID of the team.

includeArray<string>tintquery

A comma-separated list of related resources to include in the response. tint is only available when the access token has the tints:read scope.

Response

201Createdobject

The right request term.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: right_request_terms:write

Create a right request term
curl -X POST 'https://api.tintup.com/v2/teams/{team_id}/right_requests/terms' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "right_request_term",
      "attributes": {
        "name": "Standard content license",
        "title": "Acme Inc. Content License Agreement",
        "text": "# Content License Agreement\n\nBy replying with the approval hashtag, you grant Acme Inc. a non-exclusive, royalty-free, worldwide license\nto use, reproduce, and display your post and its content on its websites, social media accounts, and\nmarketing materials. You confirm that you own the content and that it doesn'\''t infringe on anyone'\''s rights.",
        "logo_url": "https://cdn.example.com/acme/logo.png",
        "document": "eyJfcmFpbHMiOnsiZGF0YSI6NDIsInB1ciI6ImJsb2JfaWQifX0=--9f8e7d6c5b4a39281706f5e4d3c2b1a098765432"
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/right_requests/terms', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "right_request_term",
        "attributes": {
          "name": "Standard content license",
          "title": "Acme Inc. Content License Agreement",
          "text": "# Content License Agreement\n\nBy replying with the approval hashtag, you grant Acme Inc. a non-exclusive, royalty-free, worldwide license\nto use, reproduce, and display your post and its content on its websites, social media accounts, and\nmarketing materials. You confirm that you own the content and that it doesn't infringe on anyone's rights.",
          "logo_url": "https://cdn.example.com/acme/logo.png",
          "document": "eyJfcmFpbHMiOnsiZGF0YSI6NDIsInB1ciI6ImJsb2JfaWQifX0=--9f8e7d6c5b4a39281706f5e4d3c2b1a098765432"
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "right_request_term",
    "attributes": {
      "name": "Standard content license",
      "title": "Acme Inc. Content License Agreement",
      "text": "# Content License Agreement\n\nBy replying with the approval hashtag, you grant Acme Inc. a non-exclusive, royalty-free, worldwide license\nto use, reproduce, and display your post and its content on its websites, social media accounts, and\nmarketing materials. You confirm that you own the content and that it doesn't infringe on anyone's rights.",
      "logo_url": "https://cdn.example.com/acme/logo.png",
      "document": "eyJfcmFpbHMiOnsiZGF0YSI6NDIsInB1ciI6ImJsb2JfaWQifX0=--9f8e7d6c5b4a39281706f5e4d3c2b1a098765432"
    }
  }
}

response = requests.post('https://api.tintup.com/v2/teams/{team_id}/right_requests/terms', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "right_request_term",
    "attributes": {
      "name": "Standard content license",
      "title": "Acme Inc. Content License Agreement",
      "logo_url": "https://cdn.example.com/acme/logo.png",
      "text": "# Content License Agreement\n\nBy replying with the approval hashtag, you grant Acme Inc. a non-exclusive, royalty-free, worldwide\nlicense to use, reproduce, and display your post and its content on its websites, social media\naccounts, and marketing materials. You confirm that you own the content and that it doesn't infringe\non anyone's rights."
    }
  }
}
{
  "data": {
    "type": "right_request_term",
    "attributes": {
      "name": "Legal-approved license (PDF)",
      "document": "eyJfcmFpbHMiOnsiZGF0YSI6NDIsInB1ciI6ImJsb2JfaWQifX0=--9f8e7d6c5b4a39281706f5e4d3c2b1a098765432"
    }
  }
}
{
  "data": {
    "id": "12",
    "type": "right_request_term",
    "attributes": {
      "name": "Standard content license",
      "title": "Acme Inc. Content License Agreement",
      "text": "# Content License Agreement\n\nBy replying with the approval hashtag, you grant Acme Inc. a non-exclusive, royalty-free, worldwide license to\nuse, reproduce, and display your post and its content on its websites, social media accounts, and marketing\nmaterials. You confirm that you own the content and that it doesn't infringe on anyone's rights.",
      "logo_url": "https://cdn.example.com/acme/logo.png",
      "url": "https://example.com/terms/12",
      "status": "published",
      "created_at": "2025-03-01T10:15:30.000Z"
    },
    "relationships": {
      "tint": {
        "data": null
      }
    }
  },
  "included": [
    {}
  ]
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Retrieve a list of right request terms for a board

GET
https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/right_requests/terms

Returns the team's published right request terms. The board must belong to the team (otherwise a 404 is returned), but the list isn't currently narrowed down to terms limited to that board.

Parameters

team_idintegerrequiredpath

The ID of the team.

tint_idintegerrequiredpath

The ID of the board.

includeArray<string>tintquery

A comma-separated list of related resources to include in the response. tint is only available when the access token has the tints:read scope.

pageobjectquery

Offset pagination. Use page[size] to set the number of items per page and page[number] to select a page. The response's links object contains ready-to-use URLs for the next and previous pages.

sortArray<string>id-idname-namecreated_at-created_at-idquery

A comma-separated list of fields to sort by. Prefix a field with - to sort in descending order. Defaults to -id (newest first).

filterobjectquery

Filters the right request terms.

Response

200OKobject

A list of published right request terms.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: right_request_terms:read

Retrieve a list of right request terms for a board
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/right_requests/terms'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/right_requests/terms', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/right_requests/terms')
data = response.json()
{
  "data": [
    {
      "id": "12",
      "type": "right_request_term",
      "attributes": {
        "name": "Standard content license",
        "title": "Acme Inc. Content License Agreement",
        "text": "# Content License Agreement\n\nBy replying with the approval hashtag, you grant Acme Inc. a non-exclusive, royalty-free, worldwide license to\nuse, reproduce, and display your post and its content on its websites, social media accounts, and marketing\nmaterials. You confirm that you own the content and that it doesn't infringe on anyone's rights.",
        "logo_url": "https://cdn.example.com/acme/logo.png",
        "url": "https://example.com/terms/12",
        "status": "published",
        "created_at": "2025-03-01T10:15:30.000Z"
      },
      "relationships": {
        "tint": {
          "data": null
        }
      }
    }
  ],
  "included": [
    {}
  ],
  "links": {
    "self": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=2",
    "first": "https://api.tintup.com/v2/teams/1/tints",
    "next": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=3",
    "prev": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=1"
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Retrieve a right request term

GET
https://api.tintup.com/v2/teams/{team_id}/right_requests/terms/{right_request_term_id}

Unlike the other right request term endpoints, this one also returns archived terms, so they can be displayed to authors who want to review the terms they were asked to accept. It requires an access token for a member of the team (a 403 is returned otherwise, including when no access token is given), but no specific scope. The tint relationship is only returned when the access token has the tints:read scope.

Parameters

team_idintegerrequiredpath

The ID of the team.

right_request_term_idintegerrequiredpath

The ID of the right request term.

includeArray<string>tintquery

A comma-separated list of related resources to include in the response. tint is only available when the access token has the tints:read scope.

Response

200OKobject

The right request term.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Retrieve a right request term
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/right_requests/terms/{right_request_term_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/right_requests/terms/{right_request_term_id}', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/right_requests/terms/{right_request_term_id}')
data = response.json()
{
  "data": {
    "id": "12",
    "type": "right_request_term",
    "attributes": {
      "name": "Standard content license",
      "title": "Acme Inc. Content License Agreement",
      "text": "# Content License Agreement\n\nBy replying with the approval hashtag, you grant Acme Inc. a non-exclusive, royalty-free, worldwide license to\nuse, reproduce, and display your post and its content on its websites, social media accounts, and marketing\nmaterials. You confirm that you own the content and that it doesn't infringe on anyone's rights.",
      "logo_url": "https://cdn.example.com/acme/logo.png",
      "url": "https://example.com/terms/12",
      "status": "published",
      "created_at": "2025-03-01T10:15:30.000Z"
    },
    "relationships": {
      "tint": {
        "data": null
      }
    }
  },
  "included": [
    {}
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Delete a right request term

DELETE
https://api.tintup.com/v2/teams/{team_id}/right_requests/terms/{right_request_term_id}

Archives the terms rather than permanently deleting them, so existing right requests keep pointing to them. Archived terms can't be deleted again (404).

Parameters

team_idintegerrequiredpath

The ID of the team.

right_request_term_idintegerrequiredpath

The ID of the right request term.

Response

204No Content

No Content. The request succeeded and there is no response body.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: right_request_terms:write

Delete a right request term
curl -X DELETE 'https://api.tintup.com/v2/teams/{team_id}/right_requests/terms/{right_request_term_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/right_requests/terms/{right_request_term_id}', {
  method: 'DELETE',
});

const data = await response.json();
import requests

response = requests.delete('https://api.tintup.com/v2/teams/{team_id}/right_requests/terms/{right_request_term_id}')
data = response.json()
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}
Rights Management

Right Requests

right_requests

Retrieve a list of right requests

GET
https://api.tintup.com/v2/teams/{team_id}/right_requests

Returns the team's right requests for posts in the team's boards, as well as requests for Instagram posts requested by URL.

Parameters

team_idintegerrequiredpath

The ID of the team.

includeArray<string>assetspoststemplatequery

A comma-separated list of related resources to include in the response. Each relationship is only available when the access token has the matching read scope (posts:read, assets:read, or right_request_templates:read).

pageobjectquery

Offset pagination. Use page[size] to set the number of items per page and page[number] to select a page. The response's links object contains ready-to-use URLs for the next and previous pages.

sortArray<string>id-idcreated_at-created_atupdated_at-updated_atapproved_at-approved_atstatus-status-idquery

A comma-separated list of fields to sort by. Prefix a field with - to sort in descending order. Defaults to -id (newest first).

filterobjectquery

Filters the right requests. List filters accept a comma-separated list of values and match any of them; time range filters accept one or more operators.

Response

200OKobject

A list of right requests.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: right_requests:read

Retrieve a list of right requests
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/right_requests'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/right_requests', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/right_requests')
data = response.json()
{
  "data": [
    {
      "id": "1234",
      "type": "right_request",
      "attributes": {
        "hashtag": "AcmeYes",
        "created_at": "2025-03-14T16:42:07.000Z",
        "updated_at": "2025-03-15T09:12:44.000Z",
        "approved_at": "2025-03-15T09:12:44.000Z",
        "status": "approved",
        "status_expires_at": null,
        "text": "Such a great shot! We would love to share this picture on our Instagram page. @janedoe if you agree, please reply #AcmeYes and review our terms at https://example.com/terms/12",
        "source": "instagram_business",
        "external_id": "17895695668004550"
      },
      "relationships": {
        "posts": {
          "meta": {
            "included": false
          }
        },
        "assets": {
          "meta": {
            "included": false
          }
        },
        "template": {
          "meta": {
            "included": false
          }
        }
      }
    }
  ],
  "included": [
    {}
  ],
  "links": {
    "self": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=2",
    "first": "https://api.tintup.com/v2/teams/1/tints",
    "next": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=3",
    "prev": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=1"
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}

Create a right request

POST
https://api.tintup.com/v2/teams/{team_id}/right_requests

Asks the author of a post for the rights to reuse it. The message is generated from the template and sent from the given account; for X (Twitter), it is sent a few seconds later, so the right request starts as pending. For the other sources, it starts as requested.

Body

application/vnd.api+json

The right request to send.

dataNewRightRequestrequired
Show child attributes
typestringright_requestrequired

The resource type.

attributesobjectrequired
Show child attributes
sourceRightRequestSourceForCreateexternally_sourced_postsinstagram_businesstiktok_businesstwitterrequired

Where the post comes from, which also determines how the request is sent: instagram_business sends a direct message from an Instagram Business account, externally_sourced_posts requests the rights to an Instagram post that isn't in any board yet (by URL), tiktok_business replies from a TikTok Business account, and twitter replies from an X (Twitter) account.

external_idstringrequired

The ID of the post at the source. When source is externally_sourced_posts, the URL of an Instagram post on instagram.com instead (its query string is removed). For other sources, the post must exist in one of the team's boards. Rejected if an active (pending, requested, approved, or soft_approved) right request already exists for the same post.

account_idinteger>= 1required

The ID of the account used to send the request, which must be connected by the current user: an X (Twitter) account when source is twitter, a TikTok Business account when source is tiktok_business, and an Instagram Business account otherwise.

subaccount_idstring | null

The ID of the Instagram Business subaccount (page) of account_id used to send the request. Required unless source is twitter or tiktok_business, in which case it must be omitted.

hashtagstringrequired

The hashtag, without the leading #, the author must reply with to approve the request. Must be a single valid hashtag (no spaces or punctuation other than underscores).

right_request_term_idinteger>= 1required

The ID of one of the team's right request terms the author is asked to agree to.

template_idinteger

The ID of the right request template used to generate the message sent to the author. Required unless template is given; the two are mutually exclusive.

templatestring

A custom Liquid template used to generate the message sent to the author, instead of a saved template. Required unless template_id is given; the two are mutually exclusive. Available variables: {{approval_keyword}} (the hashtag, with #), {{terms.url}}, {{account.subaccount.username}}, {{source}}, and {{posts}} (each with url, attachment_type, and author.username). The legacy variables {{hashtag}}, {{terms_url}}, {{username}} (the post author, with @), and {{mention}} (the subaccount, with @) are still supported.

tint_idinteger

The ID of the board in which to create the post once the request is approved. Required when source is externally_sourced_posts, and must be omitted otherwise.

Parameters

team_idintegerrequiredpath

The ID of the team.

includeArray<string>assetspoststemplatequery

A comma-separated list of related resources to include in the response. Each relationship is only available when the access token has the matching read scope (posts:read, assets:read, or right_request_templates:read).

Response

201Createdobject

The right request.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: right_requests:write

Create a right request
curl -X POST 'https://api.tintup.com/v2/teams/{team_id}/right_requests' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "right_request",
      "attributes": {
        "source": "instagram_business",
        "external_id": "17895695668004550",
        "account_id": 56,
        "subaccount_id": "464297566935356|17841401839964064",
        "hashtag": "AcmeYes",
        "right_request_term_id": 12,
        "template_id": 34,
        "template": "Such a great shot! We would love to share this picture on our Instagram page. @{{posts.first.author.username}} if you agree, please reply {{approval_keyword}} and review our terms at {{terms.url}}",
        "tint_id": 42
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/right_requests', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "right_request",
        "attributes": {
          "source": "instagram_business",
          "external_id": "17895695668004550",
          "account_id": 56,
          "subaccount_id": "464297566935356|17841401839964064",
          "hashtag": "AcmeYes",
          "right_request_term_id": 12,
          "template_id": 34,
          "template": "Such a great shot! We would love to share this picture on our Instagram page. @{{posts.first.author.username}} if you agree, please reply {{approval_keyword}} and review our terms at {{terms.url}}",
          "tint_id": 42
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "right_request",
    "attributes": {
      "source": "instagram_business",
      "external_id": "17895695668004550",
      "account_id": 56,
      "subaccount_id": "464297566935356|17841401839964064",
      "hashtag": "AcmeYes",
      "right_request_term_id": 12,
      "template_id": 34,
      "template": "Such a great shot! We would love to share this picture on our Instagram page. @{{posts.first.author.username}} if you agree, please reply {{approval_keyword}} and review our terms at {{terms.url}}",
      "tint_id": 42
    }
  }
}

response = requests.post('https://api.tintup.com/v2/teams/{team_id}/right_requests', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "right_request",
    "attributes": {
      "source": "instagram_business",
      "external_id": "17895695668004550",
      "account_id": 56,
      "subaccount_id": "464297566935356|17841401839964064",
      "hashtag": "AcmeYes",
      "right_request_term_id": 12,
      "template_id": 34
    }
  }
}
{
  "data": {
    "type": "right_request",
    "attributes": {
      "source": "externally_sourced_posts",
      "external_id": "https://www.instagram.com/p/C4xYz12AbCd/",
      "account_id": 56,
      "subaccount_id": "464297566935356|17841401839964064",
      "hashtag": "AcmeYes",
      "right_request_term_id": 12,
      "tint_id": 42,
      "template": "We love this post! If you agree to let Acme Inc. share it, reply {{approval_keyword}}. Terms: {{terms.url}}"
    }
  }
}
{
  "data": {
    "id": "1234",
    "type": "right_request",
    "attributes": {
      "hashtag": "AcmeYes",
      "created_at": "2025-03-14T16:42:07.000Z",
      "updated_at": "2025-03-15T09:12:44.000Z",
      "approved_at": "2025-03-15T09:12:44.000Z",
      "status": "approved",
      "status_expires_at": null,
      "text": "Such a great shot! We would love to share this picture on our Instagram page. @janedoe if you agree, please reply #AcmeYes and review our terms at https://example.com/terms/12",
      "source": "instagram_business",
      "external_id": "17895695668004550"
    },
    "relationships": {
      "posts": {
        "meta": {
          "included": false
        }
      },
      "assets": {
        "meta": {
          "included": false
        }
      },
      "template": {
        "meta": {
          "included": false
        }
      }
    }
  },
  "included": [
    {}
  ]
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Retrieve a right request

GET
https://api.tintup.com/v2/teams/{team_id}/right_requests/{right_request_id}

Retrieves a right request.

Parameters

team_idintegerrequiredpath

The ID of the team.

right_request_idintegerrequiredpath

The ID of the right request.

includeArray<string>assetspoststemplatequery

A comma-separated list of related resources to include in the response. Each relationship is only available when the access token has the matching read scope (posts:read, assets:read, or right_request_templates:read).

Response

200OKobject

The right request.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: right_requests:read

Retrieve a right request
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/right_requests/{right_request_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/right_requests/{right_request_id}', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/right_requests/{right_request_id}')
data = response.json()
{
  "data": {
    "id": "1234",
    "type": "right_request",
    "attributes": {
      "hashtag": "AcmeYes",
      "created_at": "2025-03-14T16:42:07.000Z",
      "updated_at": "2025-03-15T09:12:44.000Z",
      "approved_at": "2025-03-15T09:12:44.000Z",
      "status": "approved",
      "status_expires_at": null,
      "text": "Such a great shot! We would love to share this picture on our Instagram page. @janedoe if you agree, please reply #AcmeYes and review our terms at https://example.com/terms/12",
      "source": "instagram_business",
      "external_id": "17895695668004550"
    },
    "relationships": {
      "posts": {
        "meta": {
          "included": false
        }
      },
      "assets": {
        "meta": {
          "included": false
        }
      },
      "template": {
        "meta": {
          "included": false
        }
      }
    }
  },
  "included": [
    {}
  ]
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Retrieve right request metrics

GET
https://api.tintup.com/v2/teams/{team_id}/right_requests/metrics/{measure_name}

Counts the right requests created or approved over time, optionally grouped by one or more dimensions. Only right requests sent from accounts connected by the current user are counted.

Parameters

team_idintegerrequiredpath

The ID of the team.

measure_namestringcreatedapprovedrequiredpath

The event to count, either right requests created or right requests approved.

filterobjectquery

Filters the metrics. List filters accept a comma-separated list of values and match any of them. Only right requests sent from accounts connected by the current user are counted.

groupArray<string>timetime.minutetime.hourtime.daytime.weektime.monthtime.quartertime.yeartime.day_of_weektime.hour_of_daysourceuser_idaccount_idsubaccount_idquery

A comma-separated list of dimensions to group the metrics by. time groups by day. Time buckets are returned newest first.

Response

200OKobject

A list of right request metrics, one row per combination of the grouping dimensions, or a single row when the group query parameter isn't used. The list is not paginated.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: right_requests:read

Retrieve right request metrics
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/right_requests/metrics/{measure_name}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/right_requests/metrics/{measure_name}', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/right_requests/metrics/{measure_name}')
data = response.json()
{
  "data": [
    {
      "id": "f42c2ba98b72afee69976d52875fe313",
      "type": "right_requests_metric",
      "attributes": {
        "count": 41,
        "dimensions": {
          "source": "instagram_business",
          "time": "2025-03-14 00:00:00.000000000"
        }
      }
    },
    {
      "id": "0b9e4c7d2a8f41e3b5c6d7e8f9a0b1c2",
      "type": "right_requests_metric",
      "attributes": {
        "count": 17,
        "dimensions": {
          "source": "tiktok_business",
          "time": "2025-03-14 00:00:00.000000000"
        }
      }
    }
  ]
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}

Boards

group_boards
Boards

Boards

tints

Retrieve a list of boards

GET
https://api.tintup.com/v2/teams/{team_id}/tints

Returns the boards you have access to.

Parameters

team_idintegerrequiredpath

The ID of the team.

pageobjectquery

Offset pagination. Use page[size] to set the number of items per page and page[number] to select a page. The response's links object contains ready-to-use URLs for the next and previous pages.

includeArray<string>default_personalizationpersonalizationspostsrecently_active_embed_locationsrights_termssaved_filterssocial_feedsquery

A comma-separated list of related resources to include in the response.

filterobjectquery

Filters the boards.

sortArray<string>id-idname-nameslug-slugcreated_at-created_atlast_moderated_at-last_moderated_at-idquery

A comma-separated list of fields to sort by. Prefix a field with - to sort in descending order. Defaults to -id (newest first).

Response

200OKobject

A list of boards.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: tints:read

Retrieve a list of boards
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/tints'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/tints', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/tints')
data = response.json()
200
{
  "data": [
    {
      "id": "42",
      "type": "tint",
      "attributes": {
        "name": "Acme Summer Campaign",
        "slug": "acme-summer-campaign",
        "public_channel": null,
        "status": "active",
        "private": false,
        "tags": [
          "featured",
          "follow up"
        ],
        "auto_moderation_rules": [
          {
            "conditions": {
              "text": [
                "spam"
              ]
            },
            "changes": {
              "status": "private"
            }
          }
        ],
        "last_moderated_at": "2025-03-14T16:42:07.000Z",
        "created_at": "2025-01-06T09:15:00.000Z"
      },
      "relationships": {
        "personalizations": {
          "data": [],
          "meta": {
            "included": false
          }
        },
        "default_personalization": {
          "data": {
            "type": "personalization",
            "id": "7"
          }
        },
        "social_feeds": {
          "data": [
            {
              "type": "social_feed",
              "id": "311"
            }
          ],
          "meta": {
            "included": false,
            "total": 3,
            "count": 3,
            "access_error_count": 0
          }
        },
        "posts": {
          "data": [
            {
              "type": "post",
              "id": "9001"
            }
          ],
          "links": {
            "first": "https://api.tintup.com/v2/tints/42/posts",
            "next": "https://api.tintup.com/v2/tints/42/posts?page%5Bbefore%5D=MTc0MTk3MDUyN3w5MDAxfDA%3D",
            "previous": "https://api.tintup.com/v2/tints/42/posts?page%5Bafter%5D=MTc0MTk3MDUyN3w5MDAxfDA%3D"
          },
          "meta": {
            "included": false
          }
        },
        "saved_filters": {
          "data": [
            {
              "type": "saved_filter",
              "id": "15"
            }
          ],
          "meta": {
            "included": false
          }
        },
        "recently_active_embed_locations": {
          "data": [
            {
              "type": "recently_active_embed_location",
              "id": "https://example.com/summer"
            }
          ],
          "meta": {
            "included": false
          }
        },
        "rights_terms": {
          "data": [
            {
              "type": "right_request_term",
              "id": "5"
            }
          ],
          "meta": {
            "included": false
          }
        }
      },
      "links": {
        "self": "https://api.tintup.com/v2/teams/1/tints/42",
        "public_post_terms": "https://app.tintup.com/public_post_terms/acme-summer-campaign",
        "websocket": null
      }
    }
  ],
  "links": {
    "self": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=2",
    "first": "https://api.tintup.com/v2/teams/1/tints",
    "next": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=3",
    "prev": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=1"
  }
}

Create a board

POST
https://api.tintup.com/v2/teams/{team_id}/tints

Fails with 402 when the team has reached its plan's board limit.

Body

application/vnd.api+json

The board to create.

dataNewTintrequired

The board to create.

Show child attributes
typeTintTypetintrequired

The resource type. Always tint.

attributesTintWritableAttributes

Attributes that can be sent when creating or updating a board.

Show child attributes
namestring | null

The name of the board.

privatebooleanfalse

Whether the board is private. Posts of a private board aren't available publicly.

tagsArray<string>

The tags available to categorize posts in the board. A comma-separated string is also accepted. Duplicates (ignoring case) are removed. Removing a tag also removes it from the board's posts.

auto_moderation_rulesArray<AutoModerationRule>

The auto-moderation rules applied to new posts, in order. Rules that don't match the supported shapes are ignored. Sending this attribute replaces all existing rules.

Show child attributes
conditionsobjectrequired

The condition to match. Only one key is supported per rule.

Show child attributes
textArray<string>

Matches posts whose text contains any of these keywords.

author.usernameArray<string>

Matches posts whose author has any of these usernames.

author.remote_ipArray<string>

Matches posts submitted from any of these IP addresses. IP addresses are anonymized, so a specific address (/32) matches the entire block of 256 addresses (/24) it belongs to.

metadata.image_nsfwobject

Matches posts whose image NSFW score (from 0 to 1) is in the range. Use $gte and $lt together to make matching posts private, or $gte alone to delete them. The lower bound must not exceed the upper bound.

Show child attributes
$gtenumber<float>[0, 1]

The inclusive lower bound of the NSFW score.

$ltnumber<float>[0, 1]

The exclusive upper bound of the NSFW score.

changesobjectrequired

The change to apply to matching posts.

Show child attributes
statusstringpublicprivatedeletedrequired

The moderation status to give matching posts. deleted is only used by metadata.image_nsfw rules with a single $gte bound; text, username and IP address rules accept public and private.

default_personalization_idinteger | nullwrite only

The ID of the personalization used by default to display the board. It must be a personalization you have access to. It can only be changed on a board that already has a default personalization.

Parameters

team_idintegerrequiredpath

The ID of the team.

includeArray<string>default_personalizationpersonalizationspostsrecently_active_embed_locationsrights_termssaved_filterssocial_feedsquery

A comma-separated list of related resources to include in the response.

Response

201Createdobject

The board.

402Payment Requiredx-errors

Payment Required. The team already has as many active boards as its plan allows.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: tints:write

Create a board
curl -X POST 'https://api.tintup.com/v2/teams/{team_id}/tints' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "tint",
      "attributes": {
        "name": "Acme Summer Campaign",
        "private": false,
        "tags": [
          "featured",
          "follow up"
        ],
        "auto_moderation_rules": [
          {
            "conditions": {
              "text": [
                "spam"
              ]
            },
            "changes": {
              "status": "private"
            }
          }
        ]
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/tints', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "tint",
        "attributes": {
          "name": "Acme Summer Campaign",
          "private": false,
          "tags": [
            "featured",
            "follow up"
          ],
          "auto_moderation_rules": [
            {
              "conditions": {
                "text": [
                  "spam"
                ]
              },
              "changes": {
                "status": "private"
              }
            }
          ]
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "tint",
    "attributes": {
      "name": "Acme Summer Campaign",
      "private": False,
      "tags": [
        "featured",
        "follow up"
      ],
      "auto_moderation_rules": [
        {
          "conditions": {
            "text": [
              "spam"
            ]
          },
          "changes": {
            "status": "private"
          }
        }
      ]
    }
  }
}

response = requests.post('https://api.tintup.com/v2/teams/{team_id}/tints', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "tint",
    "attributes": {
      "name": "Acme Summer Campaign",
      "private": false,
      "tags": [
        "featured",
        "follow up"
      ],
      "auto_moderation_rules": [
        {
          "conditions": {
            "text": [
              "spam"
            ]
          },
          "changes": {
            "status": "private"
          }
        }
      ]
    }
  }
}
{
  "data": {
    "id": "42",
    "type": "tint",
    "attributes": {
      "name": "Acme Summer Campaign",
      "slug": "acme-summer-campaign",
      "public_channel": null,
      "status": "active",
      "private": false,
      "tags": [
        "featured",
        "follow up"
      ],
      "auto_moderation_rules": [
        {
          "conditions": {
            "text": [
              "spam"
            ]
          },
          "changes": {
            "status": "private"
          }
        }
      ],
      "last_moderated_at": "2025-03-14T16:42:07.000Z",
      "created_at": "2025-01-06T09:15:00.000Z"
    },
    "relationships": {
      "personalizations": {
        "data": [],
        "meta": {
          "included": false
        }
      },
      "default_personalization": {
        "data": {
          "type": "personalization",
          "id": "7"
        }
      },
      "social_feeds": {
        "data": [
          {
            "type": "social_feed",
            "id": "311"
          }
        ],
        "meta": {
          "included": false,
          "total": 3,
          "count": 3,
          "access_error_count": 0
        }
      },
      "posts": {
        "data": [
          {
            "type": "post",
            "id": "9001"
          }
        ],
        "links": {
          "first": "https://api.tintup.com/v2/tints/42/posts",
          "next": "https://api.tintup.com/v2/tints/42/posts?page%5Bbefore%5D=MTc0MTk3MDUyN3w5MDAxfDA%3D",
          "previous": "https://api.tintup.com/v2/tints/42/posts?page%5Bafter%5D=MTc0MTk3MDUyN3w5MDAxfDA%3D"
        },
        "meta": {
          "included": false
        }
      },
      "saved_filters": {
        "data": [
          {
            "type": "saved_filter",
            "id": "15"
          }
        ],
        "meta": {
          "included": false
        }
      },
      "recently_active_embed_locations": {
        "data": [
          {
            "type": "recently_active_embed_location",
            "id": "https://example.com/summer"
          }
        ],
        "meta": {
          "included": false
        }
      },
      "rights_terms": {
        "data": [
          {
            "type": "right_request_term",
            "id": "5"
          }
        ],
        "meta": {
          "included": false
        }
      }
    },
    "links": {
      "self": "https://api.tintup.com/v2/teams/1/tints/42",
      "public_post_terms": "https://app.tintup.com/public_post_terms/acme-summer-campaign",
      "websocket": null
    }
  }
}
{
  "errors": [
    {
      "code": "402",
      "title": "Plan limit exceeded",
      "status": "402"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Delete multiple boards

DELETE
https://api.tintup.com/v2/teams/{team_id}/tints

Deletes several boards at once.

Body

application/vnd.api+json; ext=bulk

The boards to delete, each identified by its id. Boards you don't have access to are ignored.

dataArray<TintBulkDelete>required
Show child attributes
idstringrequired

The ID of the board.

typeTintTypetintrequired

The resource type. Always tint.

Parameters

team_idintegerrequiredpath

The ID of the team.

Response

204No Content

No Content. The request succeeded and there is no response body.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: tints:write

Delete multiple boards
curl -X DELETE 'https://api.tintup.com/v2/teams/{team_id}/tints' \
  -H 'Content-Type: application/vnd.api+json; ext=bulk' \
  -d '{
    "data": [
      {
        "id": "42",
        "type": "tint"
      },
      {
        "id": "43",
        "type": "tint"
      }
    ]
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/tints', {
  method: 'DELETE',
  headers: {
    'Content-Type': 'application/vnd.api+json; ext=bulk',
  },
  body: JSON.stringify({
      "data": [
        {
          "id": "42",
          "type": "tint"
        },
        {
          "id": "43",
          "type": "tint"
        }
      ]
    }),
});

const data = await response.json();
import requests

payload = {
  "data": [
    {
      "id": "42",
      "type": "tint"
    },
    {
      "id": "43",
      "type": "tint"
    }
  ]
}

response = requests.delete('https://api.tintup.com/v2/teams/{team_id}/tints', json=payload)
data = response.json()
Request Body
{
  "data": [
    {
      "id": "42",
      "type": "tint"
    },
    {
      "id": "43",
      "type": "tint"
    }
  ]
}

Update multiple boards

PATCH
https://api.tintup.com/v2/teams/{team_id}/tints

The request is validated as a whole: if any board is invalid, none are updated.

Body

application/vnd.api+json; ext=bulk

The boards to update, each identified by its id.

dataArray<TintBulkUpdate>required
Show child attributes
idstring

The ID of the board.

typeTintTypetintrequired

The resource type. Always tint.

attributesTintWritableAttributes & object

A board to update, identified by its id. In bulk updates, only name, private, status and tags are saved; other attributes are ignored.

object

Parameters

team_idintegerrequiredpath

The ID of the team.

Response

200OKobject

The updated boards.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: tints:write

Update multiple boards
curl -X PATCH 'https://api.tintup.com/v2/teams/{team_id}/tints' \
  -H 'Content-Type: application/vnd.api+json; ext=bulk' \
  -d '{
    "data": [
      {
        "id": "42",
        "type": "tint",
        "attributes": {
          "status": "inactive"
        }
      },
      {
        "id": "43",
        "type": "tint",
        "attributes": {
          "private": true
        }
      }
    ]
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/tints', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/vnd.api+json; ext=bulk',
  },
  body: JSON.stringify({
      "data": [
        {
          "id": "42",
          "type": "tint",
          "attributes": {
            "status": "inactive"
          }
        },
        {
          "id": "43",
          "type": "tint",
          "attributes": {
            "private": true
          }
        }
      ]
    }),
});

const data = await response.json();
import requests

payload = {
  "data": [
    {
      "id": "42",
      "type": "tint",
      "attributes": {
        "status": "inactive"
      }
    },
    {
      "id": "43",
      "type": "tint",
      "attributes": {
        "private": True
      }
    }
  ]
}

response = requests.patch('https://api.tintup.com/v2/teams/{team_id}/tints', json=payload)
data = response.json()
Request Body
{
  "data": [
    {
      "id": "42",
      "type": "tint",
      "attributes": {
        "status": "inactive"
      }
    },
    {
      "id": "43",
      "type": "tint",
      "attributes": {
        "private": true
      }
    }
  ]
}
{
  "data": [
    {
      "id": "42",
      "type": "tint",
      "attributes": {
        "name": "Acme Summer Campaign",
        "slug": "acme-summer-campaign",
        "public_channel": null,
        "status": "active",
        "private": false,
        "tags": [
          "featured",
          "follow up"
        ],
        "auto_moderation_rules": [
          {
            "conditions": {
              "text": [
                "spam"
              ]
            },
            "changes": {
              "status": "private"
            }
          }
        ],
        "last_moderated_at": "2025-03-14T16:42:07.000Z",
        "created_at": "2025-01-06T09:15:00.000Z"
      },
      "relationships": {
        "personalizations": {
          "data": [],
          "meta": {
            "included": false
          }
        },
        "default_personalization": {
          "data": {
            "type": "personalization",
            "id": "7"
          }
        },
        "social_feeds": {
          "data": [
            {
              "type": "social_feed",
              "id": "311"
            }
          ],
          "meta": {
            "included": false,
            "total": 3,
            "count": 3,
            "access_error_count": 0
          }
        },
        "posts": {
          "data": [
            {
              "type": "post",
              "id": "9001"
            }
          ],
          "links": {
            "first": "https://api.tintup.com/v2/tints/42/posts",
            "next": "https://api.tintup.com/v2/tints/42/posts?page%5Bbefore%5D=MTc0MTk3MDUyN3w5MDAxfDA%3D",
            "previous": "https://api.tintup.com/v2/tints/42/posts?page%5Bafter%5D=MTc0MTk3MDUyN3w5MDAxfDA%3D"
          },
          "meta": {
            "included": false
          }
        },
        "saved_filters": {
          "data": [
            {
              "type": "saved_filter",
              "id": "15"
            }
          ],
          "meta": {
            "included": false
          }
        },
        "recently_active_embed_locations": {
          "data": [
            {
              "type": "recently_active_embed_location",
              "id": "https://example.com/summer"
            }
          ],
          "meta": {
            "included": false
          }
        },
        "rights_terms": {
          "data": [
            {
              "type": "right_request_term",
              "id": "5"
            }
          ],
          "meta": {
            "included": false
          }
        }
      },
      "links": {
        "self": "https://api.tintup.com/v2/teams/1/tints/42",
        "public_post_terms": "https://app.tintup.com/public_post_terms/acme-summer-campaign",
        "websocket": null
      }
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Retrieve aggregated board engagement metrics

GET
https://api.tintup.com/v2/teams/{team_id}/tints/metrics/engagements/{embed_engagement_type}

Counts the engagement events of the team's boards, optionally grouped by one or more dimensions.

Parameters

team_idintegerrequiredpath

The ID of the team.

embed_engagement_typestringembed_post_modal_openedembed_post_external_link_openedembed_post_cta_clickedembed_post_sharedembed_post_modal_navigate_rightembed_post_modal_navigate_leftembed_paginatedembed_post_author_clickedembed_post_product_clickedembed_loadedembed_viewedrequiredpath

The board engagement event type to count. Multiple types can be combined in a single path segment, separated by a pipe (|), for example embed_loaded|embed_viewed. Unknown types are ignored.

filterobjectquery

Filters the engagement events that are counted.

groupArray<string>time.hourtime.daytime.weektime.monthtime.quartertime.yeartime.day_of_weektime.hour_of_daytint_idpost_idpersonalization_typethemedevice_categorymedia_typeembed_urlremote_ip_countryquery

A comma-separated list of dimensions to group the metrics by. Time dimensions (time.*) return a time dimension truncated to the unit (time.day_of_week and time.hour_of_day return the day or hour number instead).

aggregationstringcountcount_uniquecountquery

How to count events: count sums all events, count_unique counts unique visitors (approximately).

Response

200OKobject

A list of board engagement metrics.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: tints:read

Retrieve aggregated board engagement metrics
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/tints/metrics/engagements/{embed_engagement_type}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/tints/metrics/engagements/{embed_engagement_type}', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/tints/metrics/engagements/{embed_engagement_type}')
data = response.json()
200
{
  "data": [
    {
      "id": "f42c2ba98b72afee69976d52875fe313",
      "type": "embed_engagement_metric",
      "attributes": {
        "count": 1284,
        "dimensions": {
          "tint_id": "42",
          "time": "2025-03-14T00:00:00.000-04:00",
          "created_at": "2025-03-14T00:00:00.000-04:00"
        }
      },
      "relationships": {
        "tint": {
          "data": {
            "type": "tint",
            "id": "42"
          }
        },
        "post": {
          "data": {
            "type": "post",
            "id": "9001"
          }
        }
      }
    }
  ]
}

Retrieve a board

GET
https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}

Parameters

team_idintegerrequiredpath

The ID of the team.

tint_idintegerrequiredpath

The ID of the board.

includeArray<string>default_personalizationpersonalizationspostsrecently_active_embed_locationsrights_termssaved_filterssocial_feedsquery

A comma-separated list of related resources to include in the response.

Response

200OKobject

The board.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: tints:read

Retrieve a board
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}')
data = response.json()
200
{
  "data": {
    "id": "42",
    "type": "tint",
    "attributes": {
      "name": "Acme Summer Campaign",
      "slug": "acme-summer-campaign",
      "public_channel": null,
      "status": "active",
      "private": false,
      "tags": [
        "featured",
        "follow up"
      ],
      "auto_moderation_rules": [
        {
          "conditions": {
            "text": [
              "spam"
            ]
          },
          "changes": {
            "status": "private"
          }
        }
      ],
      "last_moderated_at": "2025-03-14T16:42:07.000Z",
      "created_at": "2025-01-06T09:15:00.000Z"
    },
    "relationships": {
      "personalizations": {
        "data": [],
        "meta": {
          "included": false
        }
      },
      "default_personalization": {
        "data": {
          "type": "personalization",
          "id": "7"
        }
      },
      "social_feeds": {
        "data": [
          {
            "type": "social_feed",
            "id": "311"
          }
        ],
        "meta": {
          "included": false,
          "total": 3,
          "count": 3,
          "access_error_count": 0
        }
      },
      "posts": {
        "data": [
          {
            "type": "post",
            "id": "9001"
          }
        ],
        "links": {
          "first": "https://api.tintup.com/v2/tints/42/posts",
          "next": "https://api.tintup.com/v2/tints/42/posts?page%5Bbefore%5D=MTc0MTk3MDUyN3w5MDAxfDA%3D",
          "previous": "https://api.tintup.com/v2/tints/42/posts?page%5Bafter%5D=MTc0MTk3MDUyN3w5MDAxfDA%3D"
        },
        "meta": {
          "included": false
        }
      },
      "saved_filters": {
        "data": [
          {
            "type": "saved_filter",
            "id": "15"
          }
        ],
        "meta": {
          "included": false
        }
      },
      "recently_active_embed_locations": {
        "data": [
          {
            "type": "recently_active_embed_location",
            "id": "https://example.com/summer"
          }
        ],
        "meta": {
          "included": false
        }
      },
      "rights_terms": {
        "data": [
          {
            "type": "right_request_term",
            "id": "5"
          }
        ],
        "meta": {
          "included": false
        }
      }
    },
    "links": {
      "self": "https://api.tintup.com/v2/teams/1/tints/42",
      "public_post_terms": "https://app.tintup.com/public_post_terms/acme-summer-campaign",
      "websocket": null
    }
  }
}

Delete a board

DELETE
https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}

Deletes the board.

Parameters

team_idintegerrequiredpath

The ID of the team.

tint_idintegerrequiredpath

The ID of the board.

Response

204No Content

No Content. The request succeeded and there is no response body.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: tints:write

Delete a board
curl -X DELETE 'https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}', {
  method: 'DELETE',
});

const data = await response.json();
import requests

response = requests.delete('https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}')
data = response.json()

Update a board

PATCH
https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}

Updates the board.

Body

application/vnd.api+json

The board changes.

dataTintUpdaterequired

The board changes. Only the attributes sent are changed. The id is optional; the board is identified by the URL.

Show child attributes
idstring

The ID of the board.

typeTintTypetintrequired

The resource type. Always tint.

attributesTintWritableAttributes & object

Parameters

team_idintegerrequiredpath

The ID of the team.

tint_idintegerrequiredpath

The ID of the board.

includeArray<string>default_personalizationpersonalizationspostsrecently_active_embed_locationsrights_termssaved_filterssocial_feedsquery

A comma-separated list of related resources to include in the response.

Response

200OKobject

The board.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: tints:write

Update a board
curl -X PATCH 'https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "id": "42",
      "type": "tint",
      "attributes": {
        "name": "Acme Summer Campaign 2025",
        "status": "active"
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "id": "42",
        "type": "tint",
        "attributes": {
          "name": "Acme Summer Campaign 2025",
          "status": "active"
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "id": "42",
    "type": "tint",
    "attributes": {
      "name": "Acme Summer Campaign 2025",
      "status": "active"
    }
  }
}

response = requests.patch('https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}', json=payload)
data = response.json()
Request Body
{
  "data": {
    "id": "42",
    "type": "tint",
    "attributes": {
      "name": "Acme Summer Campaign 2025",
      "status": "active"
    }
  }
}
{
  "data": {
    "id": "42",
    "type": "tint",
    "attributes": {
      "name": "Acme Summer Campaign",
      "slug": "acme-summer-campaign",
      "public_channel": null,
      "status": "active",
      "private": false,
      "tags": [
        "featured",
        "follow up"
      ],
      "auto_moderation_rules": [
        {
          "conditions": {
            "text": [
              "spam"
            ]
          },
          "changes": {
            "status": "private"
          }
        }
      ],
      "last_moderated_at": "2025-03-14T16:42:07.000Z",
      "created_at": "2025-01-06T09:15:00.000Z"
    },
    "relationships": {
      "personalizations": {
        "data": [],
        "meta": {
          "included": false
        }
      },
      "default_personalization": {
        "data": {
          "type": "personalization",
          "id": "7"
        }
      },
      "social_feeds": {
        "data": [
          {
            "type": "social_feed",
            "id": "311"
          }
        ],
        "meta": {
          "included": false,
          "total": 3,
          "count": 3,
          "access_error_count": 0
        }
      },
      "posts": {
        "data": [
          {
            "type": "post",
            "id": "9001"
          }
        ],
        "links": {
          "first": "https://api.tintup.com/v2/tints/42/posts",
          "next": "https://api.tintup.com/v2/tints/42/posts?page%5Bbefore%5D=MTc0MTk3MDUyN3w5MDAxfDA%3D",
          "previous": "https://api.tintup.com/v2/tints/42/posts?page%5Bafter%5D=MTc0MTk3MDUyN3w5MDAxfDA%3D"
        },
        "meta": {
          "included": false
        }
      },
      "saved_filters": {
        "data": [
          {
            "type": "saved_filter",
            "id": "15"
          }
        ],
        "meta": {
          "included": false
        }
      },
      "recently_active_embed_locations": {
        "data": [
          {
            "type": "recently_active_embed_location",
            "id": "https://example.com/summer"
          }
        ],
        "meta": {
          "included": false
        }
      },
      "rights_terms": {
        "data": [
          {
            "type": "right_request_term",
            "id": "5"
          }
        ],
        "meta": {
          "included": false
        }
      }
    },
    "links": {
      "self": "https://api.tintup.com/v2/teams/1/tints/42",
      "public_post_terms": "https://app.tintup.com/public_post_terms/acme-summer-campaign",
      "websocket": null
    }
  }
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Retrieve a public board

GET
https://api.tintup.com/v2/tints/{tint_slug}

Returns a public board by its slug. No authentication is required; if an Authorization header is sent, the access token must have the tints:read scope.

Parameters

tint_slugstringrequiredpath

The slug of the board, the unique part of its public URL.

Response

200OKobject

The board. Without an access token, the public representation is returned; with one, the full representation (see "Retrieve a board") is returned.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: tints:read

Retrieve a public board
curl -X GET 'https://api.tintup.com/v2/tints/{tint_slug}'
const response = await fetch('https://api.tintup.com/v2/tints/{tint_slug}', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/tints/{tint_slug}')
data = response.json()
200
{
  "data": {
    "id": "42",
    "type": "tint",
    "attributes": {
      "name": "Acme Summer Campaign",
      "slug": "acme-summer-campaign",
      "public_channel": null
    },
    "relationships": {
      "personalizations": {
        "data": [],
        "meta": {
          "included": false
        }
      },
      "default_personalization": {
        "data": {
          "type": "personalization",
          "id": "7"
        }
      },
      "social_feeds": {
        "data": [
          {
            "type": "social_feed",
            "id": "311"
          }
        ],
        "meta": {
          "included": false,
          "total": 3,
          "count": 3,
          "access_error_count": 0
        }
      },
      "posts": {
        "data": [
          {
            "type": "post",
            "id": "9001"
          }
        ],
        "links": {
          "first": "https://api.tintup.com/v2/tints/42/posts",
          "next": "https://api.tintup.com/v2/tints/42/posts?page%5Bbefore%5D=MTc0MTk3MDUyN3w5MDAxfDA%3D",
          "previous": "https://api.tintup.com/v2/tints/42/posts?page%5Bafter%5D=MTc0MTk3MDUyN3w5MDAxfDA%3D"
        },
        "meta": {
          "included": false
        }
      }
    },
    "links": {
      "self": "https://api.tintup.com/v2/teams/1/tints/42",
      "public_post_terms": "https://app.tintup.com/public_post_terms/acme-summer-campaign",
      "websocket": null
    }
  }
}
Boards

CTAs

ctas

Retrieve a list of CTAs

GET
https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/ctas

Returns the CTAs of the board.

Parameters

team_idintegerrequiredpath

The ID of the team.

tint_idintegerrequiredpath

The ID of the board.

pageobjectquery

Offset pagination. Use page[size] to set the number of items per page and page[number] to select a page. The response's links object contains ready-to-use URLs for the next and previous pages.

includeArray<string>tintquery

A comma-separated list of related resources to include in the response.

sortArray<string>id-idname-namecreated_at-created_atupdated_at-updated_atposts_count-posts_countsaved_filters_count-saved_filters_count-idquery

A comma-separated list of fields to sort by. Prefix a field with - to sort in descending order.

Response

200OKobject

A list of CTAs.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: ctas:read

Retrieve a list of CTAs
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/ctas'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/ctas', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/ctas')
data = response.json()
{
  "data": [
    {
      "id": "731",
      "type": "cta",
      "attributes": {
        "name": "Spring sale booking",
        "text": "Book now",
        "url": "https://example.com/spring-sale?utm_source=board"
      },
      "relationships": {
        "tint": {
          "data": {
            "type": "tint",
            "id": "96"
          },
          "meta": {
            "included": false
          }
        }
      }
    }
  ],
  "links": {
    "self": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=2",
    "first": "https://api.tintup.com/v2/teams/1/tints",
    "next": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=3",
    "prev": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=1"
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Create a CTA

POST
https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/ctas

Creates a CTA on the board.

Body

application/vnd.api+json

The CTA to create.

dataNewCtarequired
Show child attributes
typestringctarequired

The resource type.

attributesCtaWritableAttributes & objectrequired

Parameters

team_idintegerrequiredpath

The ID of the team.

tint_idintegerrequiredpath

The ID of the board.

includeArray<string>tintquery

A comma-separated list of related resources to include in the response.

Response

201Createdobject

The CTA.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: ctas:write

Create a CTA
curl -X POST 'https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/ctas' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "cta",
      "attributes": {
        "name": "Spring sale booking",
        "text": "Book now",
        "url": "https://example.com/spring-sale?utm_source=board"
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/ctas', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "cta",
        "attributes": {
          "name": "Spring sale booking",
          "text": "Book now",
          "url": "https://example.com/spring-sale?utm_source=board"
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "cta",
    "attributes": {
      "name": "Spring sale booking",
      "text": "Book now",
      "url": "https://example.com/spring-sale?utm_source=board"
    }
  }
}

response = requests.post('https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/ctas', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "cta",
    "attributes": {
      "name": "Spring sale booking",
      "text": "Book now",
      "url": "https://example.com/spring-sale?utm_source=board"
    }
  }
}
{
  "data": {
    "id": "731",
    "type": "cta",
    "attributes": {
      "name": "Spring sale booking",
      "text": "Book now",
      "url": "https://example.com/spring-sale?utm_source=board"
    },
    "relationships": {
      "tint": {
        "data": {
          "type": "tint",
          "id": "96"
        },
        "meta": {
          "included": false
        }
      }
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Retrieve a CTA

GET
https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/ctas/{cta_id}

Retrieves one of the board's CTAs.

Parameters

team_idintegerrequiredpath

The ID of the team.

tint_idintegerrequiredpath

The ID of the board.

cta_idintegerrequiredpath

The ID of the CTA.

includeArray<string>tintquery

A comma-separated list of related resources to include in the response.

Response

200OKobject

The CTA.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: ctas:read

Retrieve a CTA
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/ctas/{cta_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/ctas/{cta_id}', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/ctas/{cta_id}')
data = response.json()
{
  "data": {
    "id": "731",
    "type": "cta",
    "attributes": {
      "name": "Spring sale booking",
      "text": "Book now",
      "url": "https://example.com/spring-sale?utm_source=board"
    },
    "relationships": {
      "tint": {
        "data": {
          "type": "tint",
          "id": "96"
        },
        "meta": {
          "included": false
        }
      }
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Delete a CTA

DELETE
https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/ctas/{cta_id}

Deletes the CTA and removes it from every post and saved filter it was applied to.

Parameters

team_idintegerrequiredpath

The ID of the team.

tint_idintegerrequiredpath

The ID of the board.

cta_idintegerrequiredpath

The ID of the CTA.

Response

204No Content

No Content. The request succeeded and there is no response body.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: ctas:write

Delete a CTA
curl -X DELETE 'https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/ctas/{cta_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/ctas/{cta_id}', {
  method: 'DELETE',
});

const data = await response.json();
import requests

response = requests.delete('https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/ctas/{cta_id}')
data = response.json()
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Update a CTA

PATCH
https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/ctas/{cta_id}

Updates the CTA.

Body

application/vnd.api+json

The attributes to change.

dataCtaUpdaterequired

Only the attributes that are sent are changed. Sent attributes can't be blank.

Show child attributes
idstring

The ID of the CTA.

typestringctarequired

The resource type.

attributesCtaWritableAttributesrequired
Show child attributes
namestring

Internal name used to identify the CTA in the app. Not displayed to visitors.

textstring

The label displayed on the CTA button.

urlstring<uri>

The URL visitors are sent to. Must start with http:// or https://.

Parameters

team_idintegerrequiredpath

The ID of the team.

tint_idintegerrequiredpath

The ID of the board.

cta_idintegerrequiredpath

The ID of the CTA.

includeArray<string>tintquery

A comma-separated list of related resources to include in the response.

Response

200OKobject

The CTA.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: ctas:write

Update a CTA
curl -X PATCH 'https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/ctas/{cta_id}' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "id": "731",
      "type": "cta",
      "attributes": {
        "name": "Spring sale booking",
        "text": "Book now",
        "url": "https://example.com/spring-sale?utm_source=board"
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/ctas/{cta_id}', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "id": "731",
        "type": "cta",
        "attributes": {
          "name": "Spring sale booking",
          "text": "Book now",
          "url": "https://example.com/spring-sale?utm_source=board"
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "id": "731",
    "type": "cta",
    "attributes": {
      "name": "Spring sale booking",
      "text": "Book now",
      "url": "https://example.com/spring-sale?utm_source=board"
    }
  }
}

response = requests.patch('https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/ctas/{cta_id}', json=payload)
data = response.json()
Request Body
{
  "data": {
    "id": "731",
    "type": "cta",
    "attributes": {
      "name": "Spring sale booking",
      "text": "Book now",
      "url": "https://example.com/spring-sale?utm_source=board"
    }
  }
}
{
  "data": {
    "id": "731",
    "type": "cta",
    "attributes": {
      "name": "Spring sale booking",
      "text": "Book now",
      "url": "https://example.com/spring-sale?utm_source=board"
    },
    "relationships": {
      "tint": {
        "data": {
          "type": "tint",
          "id": "96"
        },
        "meta": {
          "included": false
        }
      }
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Create a CTA association

POST
https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/cta_associations

Applies a CTA to a post or a saved filter of the board. A token with either the posts:write or the saved_filters:write scope is accepted.

Body

application/vnd.api+json

The CTA to apply and the post or saved filter to apply it to.

dataNewCtaAssociationrequired
Show child attributes
typestringcta_associationrequired

The resource type.

attributesobjectrequired

Specify cta_id and either post_id or saved_filter_id. A CTA can only be applied once to the same post or saved filter.

Show child attributes
cta_idintegerrequired

The ID of the CTA to apply.

post_idinteger

The ID of the post to apply the CTA to. Don't combine with saved_filter_id.

saved_filter_idinteger

The ID of the saved filter to apply the CTA to, so that every post matching the filter shows it. Don't combine with post_id.

Parameters

team_idintegerrequiredpath

The ID of the team.

tint_idintegerrequiredpath

The ID of the board.

includeArray<string>ctapostsaved_filterquery

A comma-separated list of related resources to include in the response.

Response

201Createdobject

The CTA association.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: posts:write

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: saved_filters:write

Create a CTA association
curl -X POST 'https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/cta_associations' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "cta_association",
      "attributes": {
        "cta_id": 731,
        "post_id": 902314,
        "saved_filter_id": 3317
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/cta_associations', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "cta_association",
        "attributes": {
          "cta_id": 731,
          "post_id": 902314,
          "saved_filter_id": 3317
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "cta_association",
    "attributes": {
      "cta_id": 731,
      "post_id": 902314,
      "saved_filter_id": 3317
    }
  }
}

response = requests.post('https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/cta_associations', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "cta_association",
    "attributes": {
      "cta_id": 731,
      "post_id": 902314,
      "saved_filter_id": 3317
    }
  }
}
{
  "data": {
    "id": "5120",
    "type": "cta_association",
    "attributes": {
      "type": "post"
    },
    "relationships": {
      "cta": {
        "data": {
          "type": "cta",
          "id": "731"
        },
        "meta": {
          "included": false
        }
      },
      "post": {
        "data": {
          "type": "post",
          "id": "902314"
        },
        "meta": {
          "included": false
        }
      },
      "saved_filter": {
        "data": null,
        "meta": {
          "included": false
        }
      }
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Delete a CTA association

DELETE
https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/cta_associations/{cta_association_id}

Removes a CTA from a post or a saved filter of the board. A token with either the posts:write or the saved_filters:write scope is accepted.

Parameters

team_idintegerrequiredpath

The ID of the team.

tint_idintegerrequiredpath

The ID of the board.

cta_association_idintegerrequiredpath

The ID of the CTA association.

Response

204No Content

No Content. The request succeeded and there is no response body.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: posts:write

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: saved_filters:write

Delete a CTA association
curl -X DELETE 'https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/cta_associations/{cta_association_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/cta_associations/{cta_association_id}', {
  method: 'DELETE',
});

const data = await response.json();
import requests

response = requests.delete('https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/cta_associations/{cta_association_id}')
data = response.json()
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}
Boards

Personalizations

personalizations

Retrieve a list of personalizations

GET
https://api.tintup.com/v2/teams/{team_id}/personalizations

Returns the personalizations the user has access to.

Parameters

team_idintegerrequiredpath

The ID of the team.

filterobjectquery

Filters the list of personalizations.

sortstring-idquery

A comma-separated list of attributes to sort by. Prefix an attribute with - to sort in descending order.

pageobjectquery

Offset pagination. Use page[size] to set the number of items per page and page[number] to select a page. The response's links object contains ready-to-use URLs for the next and previous pages.

Response

200OKobject

A list of personalizations.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: personalizations:read

Retrieve a list of personalizations
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/personalizations'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/personalizations', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/personalizations')
data = response.json()
{
  "data": [
    {
      "id": "301",
      "type": "personalization",
      "attributes": {
        "type": "embed",
        "theme": "classic_v3",
        "data": {
          "draft": {
            "custom_css": ".tint-post { border-radius: 8px; }",
            "popup_custom_css": ".tint-popup { background: #fff; }"
          },
          "published": {
            "custom_css": ".tint-post { border-radius: 8px; }",
            "popup_custom_css": ".tint-popup { background: #fff; }"
          }
        },
        "name": "Homepage wall",
        "tags": [
          "website",
          "spring"
        ],
        "created_at": "2025-03-14T16:42:07.000Z",
        "updated_at": "2025-03-18T09:12:44.000Z"
      }
    }
  ],
  "links": {
    "self": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=2",
    "first": "https://api.tintup.com/v2/teams/1/tints",
    "next": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=3",
    "prev": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=1"
  },
  "meta": {
    "aggregations": {
      "tags": {
        "spring": 3,
        "website": 5
      }
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}

Create a personalization

POST
https://api.tintup.com/v2/teams/{team_id}/personalizations

Creates a personalization and grants access to it to the user's role and to the roles that have access to new personalizations.

Body

application/vnd.api+json

The personalization to create.

dataNewPersonalizationrequired
Show child attributes
typestringpersonalizationrequired
attributesPersonalizationWritableAttributes & objectrequired

Parameters

team_idintegerrequiredpath

The ID of the team.

Response

201Createdobject

The personalization.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

402Payment Requiredx-errors

Payment Required. The team reached its plan's limit of personalizations.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: personalizations:write

Create a personalization
curl -X POST 'https://api.tintup.com/v2/teams/{team_id}/personalizations' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "personalization",
      "attributes": {
        "name": "Homepage wall",
        "theme": "classic_v3",
        "type": "embed",
        "tags": [
          "website"
        ]
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/personalizations', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "personalization",
        "attributes": {
          "name": "Homepage wall",
          "theme": "classic_v3",
          "type": "embed",
          "tags": [
            "website"
          ]
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "personalization",
    "attributes": {
      "name": "Homepage wall",
      "theme": "classic_v3",
      "type": "embed",
      "tags": [
        "website"
      ]
    }
  }
}

response = requests.post('https://api.tintup.com/v2/teams/{team_id}/personalizations', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "personalization",
    "attributes": {
      "name": "Homepage wall",
      "theme": "classic_v3",
      "type": "embed",
      "tags": [
        "website"
      ]
    }
  }
}
{
  "data": {
    "id": "301",
    "type": "personalization",
    "attributes": {
      "type": "embed",
      "theme": "classic_v3",
      "data": {
        "draft": {
          "custom_css": ".tint-post { border-radius: 8px; }",
          "popup_custom_css": ".tint-popup { background: #fff; }"
        },
        "published": {
          "custom_css": ".tint-post { border-radius: 8px; }",
          "popup_custom_css": ".tint-popup { background: #fff; }"
        }
      },
      "name": "Homepage wall",
      "tags": [
        "website",
        "spring"
      ],
      "created_at": "2025-03-14T16:42:07.000Z",
      "updated_at": "2025-03-18T09:12:44.000Z"
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4020001",
      "title": "Payment Required",
      "status": "402",
      "detail": "You have exceeded your plan's limit of 10"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Delete multiple personalizations

DELETE
https://api.tintup.com/v2/teams/{team_id}/personalizations

Deletes several personalizations at once.

Body

application/vnd.api+json; ext=bulk

The personalizations to delete. IDs the user can't access are ignored.

dataArray<PersonalizationIdentifier>required
Show child attributes
idstringrequired

The ID of the personalization.

typestringpersonalizationrequired

Parameters

team_idintegerrequiredpath

The ID of the team.

Response

204No Content

No Content. The request succeeded and there is no response body.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: personalizations:write

Delete multiple personalizations
curl -X DELETE 'https://api.tintup.com/v2/teams/{team_id}/personalizations' \
  -H 'Content-Type: application/vnd.api+json; ext=bulk' \
  -d '{
    "data": [
      {
        "id": "301",
        "type": "personalization"
      },
      {
        "id": "302",
        "type": "personalization"
      }
    ]
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/personalizations', {
  method: 'DELETE',
  headers: {
    'Content-Type': 'application/vnd.api+json; ext=bulk',
  },
  body: JSON.stringify({
      "data": [
        {
          "id": "301",
          "type": "personalization"
        },
        {
          "id": "302",
          "type": "personalization"
        }
      ]
    }),
});

const data = await response.json();
import requests

payload = {
  "data": [
    {
      "id": "301",
      "type": "personalization"
    },
    {
      "id": "302",
      "type": "personalization"
    }
  ]
}

response = requests.delete('https://api.tintup.com/v2/teams/{team_id}/personalizations', json=payload)
data = response.json()
Request Body
{
  "data": [
    {
      "id": "301",
      "type": "personalization"
    },
    {
      "id": "302",
      "type": "personalization"
    }
  ]
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Update multiple personalizations

PATCH
https://api.tintup.com/v2/teams/{team_id}/personalizations

Only name, theme, tags and status are saved. PUT is accepted as an alias of PATCH.

Body

application/vnd.api+json; ext=bulk

The personalizations to update. If any personalization is invalid, none are updated.

dataArray<PersonalizationBulkUpdate>required
Show child attributes
idstringrequired

The ID of the personalization to update.

typestringpersonalizationrequired
attributesPersonalizationWritableAttributes

The attributes to change. All attributes are validated, but only name, theme, tags and status are saved; type and data are ignored.

Parameters

team_idintegerrequiredpath

The ID of the team.

Response

200OKobject

A list of personalizations.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: personalizations:write

Update multiple personalizations
curl -X PATCH 'https://api.tintup.com/v2/teams/{team_id}/personalizations' \
  -H 'Content-Type: application/vnd.api+json; ext=bulk' \
  -d '{
    "data": [
      {
        "id": "301",
        "type": "personalization",
        "attributes": {
          "status": "archived"
        }
      },
      {
        "id": "302",
        "type": "personalization",
        "attributes": {
          "status": "archived"
        }
      }
    ]
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/personalizations', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/vnd.api+json; ext=bulk',
  },
  body: JSON.stringify({
      "data": [
        {
          "id": "301",
          "type": "personalization",
          "attributes": {
            "status": "archived"
          }
        },
        {
          "id": "302",
          "type": "personalization",
          "attributes": {
            "status": "archived"
          }
        }
      ]
    }),
});

const data = await response.json();
import requests

payload = {
  "data": [
    {
      "id": "301",
      "type": "personalization",
      "attributes": {
        "status": "archived"
      }
    },
    {
      "id": "302",
      "type": "personalization",
      "attributes": {
        "status": "archived"
      }
    }
  ]
}

response = requests.patch('https://api.tintup.com/v2/teams/{team_id}/personalizations', json=payload)
data = response.json()
Request Body
{
  "data": [
    {
      "id": "301",
      "type": "personalization",
      "attributes": {
        "status": "archived"
      }
    },
    {
      "id": "302",
      "type": "personalization",
      "attributes": {
        "status": "archived"
      }
    }
  ]
}
{
  "data": [
    {
      "id": "301",
      "type": "personalization",
      "attributes": {
        "type": "embed",
        "theme": "classic_v3",
        "data": {
          "draft": {
            "custom_css": ".tint-post { border-radius: 8px; }",
            "popup_custom_css": ".tint-popup { background: #fff; }"
          },
          "published": {
            "custom_css": ".tint-post { border-radius: 8px; }",
            "popup_custom_css": ".tint-popup { background: #fff; }"
          }
        },
        "name": "Homepage wall",
        "tags": [
          "website",
          "spring"
        ],
        "created_at": "2025-03-14T16:42:07.000Z",
        "updated_at": "2025-03-18T09:12:44.000Z"
      }
    }
  ],
  "links": {
    "self": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=2",
    "first": "https://api.tintup.com/v2/teams/1/tints",
    "next": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=3",
    "prev": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=1"
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Retrieve a personalization

GET
https://api.tintup.com/v2/teams/{team_id}/personalizations/{personalization_id}

With an access token, retrieves one of the personalizations the user has access to. Without an Authorization header, retrieves any active personalization with a reduced set of attributes and only the published settings.

Parameters

team_idintegerrequiredpath

The ID of the team.

personalization_idintegerrequiredpath

The ID of the personalization.

Response

200OKobject

The personalization.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: personalizations:read

Retrieve a personalization
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/personalizations/{personalization_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/personalizations/{personalization_id}', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/personalizations/{personalization_id}')
data = response.json()
{
  "data": {
    "id": "301",
    "type": "personalization",
    "attributes": {
      "type": "embed",
      "theme": "classic_v3",
      "data": {
        "draft": {
          "custom_css": ".tint-post { border-radius: 8px; }",
          "popup_custom_css": ".tint-popup { background: #fff; }"
        },
        "published": {
          "custom_css": ".tint-post { border-radius: 8px; }",
          "popup_custom_css": ".tint-popup { background: #fff; }"
        }
      },
      "name": "Homepage wall",
      "tags": [
        "website",
        "spring"
      ],
      "created_at": "2025-03-14T16:42:07.000Z",
      "updated_at": "2025-03-18T09:12:44.000Z"
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Delete a personalization

DELETE
https://api.tintup.com/v2/teams/{team_id}/personalizations/{personalization_id}

Deletes the personalization.

Parameters

team_idintegerrequiredpath

The ID of the team.

personalization_idintegerrequiredpath

The ID of the personalization.

Response

204No Content

No Content. The request succeeded and there is no response body.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: personalizations:write

Delete a personalization
curl -X DELETE 'https://api.tintup.com/v2/teams/{team_id}/personalizations/{personalization_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/personalizations/{personalization_id}', {
  method: 'DELETE',
});

const data = await response.json();
import requests

response = requests.delete('https://api.tintup.com/v2/teams/{team_id}/personalizations/{personalization_id}')
data = response.json()
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Update a personalization

PATCH
https://api.tintup.com/v2/teams/{team_id}/personalizations/{personalization_id}

PUT is accepted as an alias of PATCH.

Body

application/vnd.api+json

The attributes to change.

dataPersonalizationUpdaterequired
Show child attributes
typestringpersonalizationrequired
attributesPersonalizationWritableAttributes

The attributes to change. Attributes that are left out are unchanged.

Parameters

team_idintegerrequiredpath

The ID of the team.

personalization_idintegerrequiredpath

The ID of the personalization.

Response

200OKobject

The personalization.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: personalizations:write

Update a personalization
curl -X PATCH 'https://api.tintup.com/v2/teams/{team_id}/personalizations/{personalization_id}' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "personalization",
      "attributes": {
        "name": "Homepage wall",
        "data": {
          "draft": {
            "custom_css": ".tint-post { border-radius: 8px; }"
          },
          "published": {
            "custom_css": ".tint-post { border-radius: 8px; }"
          }
        }
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/personalizations/{personalization_id}', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "personalization",
        "attributes": {
          "name": "Homepage wall",
          "data": {
            "draft": {
              "custom_css": ".tint-post { border-radius: 8px; }"
            },
            "published": {
              "custom_css": ".tint-post { border-radius: 8px; }"
            }
          }
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "personalization",
    "attributes": {
      "name": "Homepage wall",
      "data": {
        "draft": {
          "custom_css": ".tint-post { border-radius: 8px; }"
        },
        "published": {
          "custom_css": ".tint-post { border-radius: 8px; }"
        }
      }
    }
  }
}

response = requests.patch('https://api.tintup.com/v2/teams/{team_id}/personalizations/{personalization_id}', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "personalization",
    "attributes": {
      "name": "Homepage wall",
      "data": {
        "draft": {
          "custom_css": ".tint-post { border-radius: 8px; }"
        },
        "published": {
          "custom_css": ".tint-post { border-radius: 8px; }"
        }
      }
    }
  }
}
{
  "data": {
    "id": "301",
    "type": "personalization",
    "attributes": {
      "type": "embed",
      "theme": "classic_v3",
      "data": {
        "draft": {
          "custom_css": ".tint-post { border-radius: 8px; }",
          "popup_custom_css": ".tint-popup { background: #fff; }"
        },
        "published": {
          "custom_css": ".tint-post { border-radius: 8px; }",
          "popup_custom_css": ".tint-popup { background: #fff; }"
        }
      },
      "name": "Homepage wall",
      "tags": [
        "website",
        "spring"
      ],
      "created_at": "2025-03-14T16:42:07.000Z",
      "updated_at": "2025-03-18T09:12:44.000Z"
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}
Boards

Post Summaries

posts_summaries

Generate or retrieve a posts summary

POST
https://api.tintup.com/v2/tints/{tint_slug}/posts/summaries

Generates or retrieves a summary of the posts of the specified board. No authentication is required; if an Authorization header is sent, the access token must have the posts:read scope.

If the summary already exists and is up to date, the request returns 200 OK with the summary, or 204 No Content if the summary is empty. If the summary needs to be generated, the request returns 202 Accepted and the summary will be available shortly.

Body

application/vnd.api+json

The posts to summarize.

The posts to summarize. These parameters can also be sent in the query string. Different parameters produce a different summary.

filterobject

The filters applied to the posts included in the summary. The same filters as "Retrieve a list of public posts for a board" are supported.

sortstring

The sort order applied to the posts included in the summary.

Parameters

tint_slugstringrequiredpath

The slug of the board, the unique part of its public URL.

includeArray<string>teamquery

A comma-separated list of related resources to include in the response.

Response

200OKobject

The posts summary for the given filters.

202Acceptedobject

The posts summary generation has been queued. Repeat the same request later to fetch the completed summary.

204No Content

No Content. The request succeeded and there is no response body.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: posts:read

Generate or retrieve a posts summary
curl -X POST 'https://api.tintup.com/v2/tints/{tint_slug}/posts/summaries' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "filter": {
      "rating": {
        "$gte": 60
      },
      "tag": "sku:ACME-SNK-001"
    },
    "sort": "-published_at"
  }'
const response = await fetch('https://api.tintup.com/v2/tints/{tint_slug}/posts/summaries', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "filter": {
        "rating": {
          "$gte": 60
        },
        "tag": "sku:ACME-SNK-001"
      },
      "sort": "-published_at"
    }),
});

const data = await response.json();
import requests

payload = {
  "filter": {
    "rating": {
      "$gte": 60
    },
    "tag": "sku:ACME-SNK-001"
  },
  "sort": "-published_at"
}

response = requests.post('https://api.tintup.com/v2/tints/{tint_slug}/posts/summaries', json=payload)
data = response.json()
Request Body
{
  "filter": {
    "rating": {
      "$gte": 60
    },
    "tag": "sku:ACME-SNK-001"
  },
  "sort": "-published_at"
}
{
  "data": {
    "id": "3b6d5c3e9a09a2b47a2d87b6d4a2c65a3b6d5c3e9a09a2b47a2d87b6d4a2c65a",
    "type": "posts_summary",
    "attributes": {
      "status": "ready",
      "fresh": true,
      "summary": "Customers love the comfort and design of the sneakers, but some mention sizing runs small.",
      "key_insights": [
        "Very comfortable for all-day wear",
        "Sizing runs half a size small"
      ],
      "created_at": "2025-03-14T16:42:07Z",
      "updated_at": "2025-03-14T16:42:31Z",
      "expires_at": "2025-03-15T16:42:07Z"
    },
    "relationships": {
      "team": {
        "data": {
          "type": "team",
          "id": "1"
        }
      }
    }
  }
}
{
  "data": {
    "id": "3b6d5c3e9a09a2b47a2d87b6d4a2c65a3b6d5c3e9a09a2b47a2d87b6d4a2c65a",
    "type": "posts_summary",
    "attributes": {
      "status": "ready",
      "fresh": true,
      "summary": "Customers love the comfort and design of the sneakers, but some mention sizing runs small.",
      "key_insights": [
        "Very comfortable for all-day wear",
        "Sizing runs half a size small"
      ],
      "created_at": "2025-03-14T16:42:07Z",
      "updated_at": "2025-03-14T16:42:31Z",
      "expires_at": "2025-03-15T16:42:07Z"
    },
    "relationships": {
      "team": {
        "data": {
          "type": "team",
          "id": "1"
        }
      }
    }
  }
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}
Boards

Posts

posts

Retrieve a list of posts

GET
https://api.tintup.com/v2/teams/{team_id}/posts

Returns the posts of the boards you have access to, newest pinned posts first by default. Returns 503 while search is temporarily unavailable.

Parameters

team_idintegerrequiredpath

The ID of the team.

filterobjectquery

Filters the posts. Unless noted, list filters take a comma-separated list of values and match any of them.

sortArray<string>pinned-pinnedpublished_at-published_atlast_moderated_at-last_moderated_atrating-ratingscore-score-pinnedquery

A comma-separated list of fields to sort by. Prefix a field with - to sort in descending order. Ties are broken by publication time and ID. score sorts by relevance to filter[q].

includeArray<string>assetauthorcta_associationscta_associations.ctaproduct_tagsproductsproducts.productrepliesright_requestssocial_feedtintquery

A comma-separated list of related resources to include in the response.

collapsestringsource,external_idquery

Use source,external_id to return a single post for posts ingested in several boards from the same source post. The other copies are returned in the siblings relationship, and the response uses offset pagination (page[offset], starting at 0) instead of cursors.

objectquery

Cursor pagination. Use page[size] to set the number of items per page. Cursors are opaque; don't build them yourself, follow the links.next and links.prev URLs from the previous response instead.

Response

200OKobject

A list of posts.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: posts:read

Retrieve a list of posts
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/posts'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/posts', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/posts')
data = response.json()
200
{
  "data": [
    {
      "id": "9001",
      "type": "post",
      "attributes": {
        "external_id": "17912345678901234",
        "url": "https://www.instagram.com/p/C4xYz12AbCd/",
        "title": null,
        "text": "Loving my new Acme sneakers!",
        "alternative_text": "A pair of white Acme sneakers on a beach.",
        "published_at": "2025-03-14T16:42:07.000Z",
        "highlighted": false,
        "pinned": false,
        "tags": [
          "featured"
        ],
        "carousel": false,
        "media_type": "image",
        "image_url": "https://cdn.example.com/posts/9001/media.jpg",
        "video_url": null,
        "attachment_id": "aHR0cHM6Ly9jZG4uZXhhbXBsZS5jb20vcG9zdHMvOTAwMS9tZWRpYS5qcGc=",
        "author": {
          "name": "Jane Doe",
          "username": "janedoe",
          "url": "https://example.com/janedoe",
          "image_url": "https://cdn.example.com/avatars/janedoe.jpg",
          "external_id": "17841400008460056",
          "email": "jane.doe@example.com",
          "phone": "+15555550123",
          "remote_ip": "203.0.113.0"
        },
        "metadata": {
          "language": "en",
          "sentiment": "positive",
          "image_nsfw": 0.02,
          "image_phash": "d1c4f0e0b0a09080",
          "image_sentiments": [
            "happy"
          ],
          "image_objects": [
            "shoe",
            "beach"
          ],
          "image_objects_rekognition": [
            "shoe",
            "beach"
          ]
        },
        "language": "en",
        "rating": 80,
        "verified": null,
        "incentivized": null,
        "status_reasons": null,
        "last_moderated_at": "2025-03-15T09:03:11.000Z",
        "custom_field": null,
        "sentiment": "positive",
        "image_nsfw": 0.02,
        "image_phash": null,
        "image_sentiments": null,
        "image_objects": [
          "shoe",
          "beach"
        ],
        "hue_probability": null
      },
      "relationships": {
        "social_feed": {
          "data": {
            "type": "social_feed",
            "id": "311"
          }
        },
        "tint": {
          "data": {
            "type": "tint",
            "id": "42"
          },
          "links": {
            "self": "https://api.tintup.com/v2/teams/1/tints/42"
          }
        },
        "author": {
          "data": {
            "type": "author",
            "id": "9001"
          },
          "meta": {
            "included": false
          }
        },
        "replies": {
          "data": [
            {
              "type": "reply",
              "id": "88"
            }
          ],
          "meta": {
            "included": false
          }
        },
        "products": {
          "data": [
            {
              "type": "product_tag",
              "id": "501"
            }
          ],
          "meta": {
            "included": false
          }
        },
        "product_tags": {
          "data": [
            {
              "type": "product_tag",
              "id": "501"
            }
          ],
          "meta": {
            "included": false
          }
        },
        "cta_associations": {
          "data": [
            {
              "type": "cta_association",
              "id": "64"
            }
          ],
          "meta": {
            "included": false
          }
        },
        "asset": {
          "data": {
            "type": "asset",
            "id": "7300"
          },
          "meta": {
            "included": false
          }
        },
        "right_requests": {
          "data": [
            {
              "type": "right_request",
              "id": "210"
            }
          ],
          "meta": {
            "included": false,
            "status": "approved",
            "status_expires_at": null
          }
        },
        "siblings": {
          "data": [
            {
              "type": "post",
              "id": "9002"
            }
          ]
        }
      }
    }
  ],
  "links": {
    "self": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=2",
    "first": "https://api.tintup.com/v2/teams/1/tints",
    "next": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=3",
    "prev": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=1"
  }
}

Delete multiple posts

DELETE
https://api.tintup.com/v2/teams/{team_id}/posts

Deletes several posts of the board at once.

Body

application/vnd.api+json; ext=bulk

The posts to delete, each identified by its id.

dataArray<PostDelete>required
Show child attributes
idstringrequired

The ID of the post.

typePostTypepostrequired

The resource type. Always post.

Parameters

team_idintegerrequiredpath

The ID of the team.

Response

204No Content

No Content. The request succeeded and there is no response body.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: posts:write

Delete multiple posts
curl -X DELETE 'https://api.tintup.com/v2/teams/{team_id}/posts' \
  -H 'Content-Type: application/vnd.api+json; ext=bulk' \
  -d '{
    "data": [
      {
        "id": "9001",
        "type": "post"
      },
      {
        "id": "9002",
        "type": "post"
      }
    ]
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/posts', {
  method: 'DELETE',
  headers: {
    'Content-Type': 'application/vnd.api+json; ext=bulk',
  },
  body: JSON.stringify({
      "data": [
        {
          "id": "9001",
          "type": "post"
        },
        {
          "id": "9002",
          "type": "post"
        }
      ]
    }),
});

const data = await response.json();
import requests

payload = {
  "data": [
    {
      "id": "9001",
      "type": "post"
    },
    {
      "id": "9002",
      "type": "post"
    }
  ]
}

response = requests.delete('https://api.tintup.com/v2/teams/{team_id}/posts', json=payload)
data = response.json()
Request Body
{
  "data": [
    {
      "id": "9001",
      "type": "post"
    },
    {
      "id": "9002",
      "type": "post"
    }
  ]
}

Update multiple posts

PATCH
https://api.tintup.com/v2/teams/{team_id}/posts

The request is validated as a whole: if any post is invalid, none are updated.

Body

application/vnd.api+json; ext=bulk

The posts to update, each identified by its id.

dataArray<PostBulkUpdate>required
Show child attributes
idstringrequired

The ID of the post.

typePostTypepostrequired

The resource type. Always post.

attributesPostWritableAttributes

Attributes that can be changed on an existing post. Only the attributes sent are changed. title, text, url, custom_field and author can only be changed on custom posts and are ignored for other posts.

Show child attributes
statusPostStatus

The moderation status of the post. Use public, private, or deleted to moderate posts.

status_reasonsArray<PostStatusReason> | nulllegal_transgressioninappropriateforeign_languagecontains_private_infounrelatedmisleadingfakeharmful_contentwrong_languageoff_topicspamlow_effortnonsenseauto_moderationauto_moderation_nsfwauto_moderation_authorauto_moderation_keywordauto_moderation_remote_ip

The reasons for the post's moderation status.

highlightedboolean

Whether the post is highlighted.

pinnedboolean

Whether the post is pinned to the top of the board.

tagsArray<string>

The tags assigned to the post. A comma-separated string is also accepted.

alternative_textstring | null

The alternative text describing the post's media, for accessibility.

verifiedboolean | null

Whether the review is from a verified buyer. Must be null (or omitted) for posts that aren't reviews.

incentivizedboolean | null

Whether the reviewer received an incentive. Must be null (or omitted) for posts that aren't reviews.

titlestring | null

The title of the post. Custom posts only.

textstring | null

The text of the post. Custom posts only.

urlstring<uri> | null

The URL the post links to. Must start with http:// or https://. Custom posts only.

custom_fieldstring | null

The value of the custom field. Custom posts only.

authorNewPostAuthor

The author of the post. Custom posts only. Send an empty image_id to remove the author's uploaded avatar.

Parameters

team_idintegerrequiredpath

The ID of the team.

Response

200OKobject

The updated posts.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: posts:write

Update multiple posts
curl -X PATCH 'https://api.tintup.com/v2/teams/{team_id}/posts' \
  -H 'Content-Type: application/vnd.api+json; ext=bulk' \
  -d '{
    "data": [
      {
        "id": "9001",
        "type": "post",
        "attributes": {
          "status": "public"
        }
      },
      {
        "id": "9002",
        "type": "post",
        "attributes": {
          "status": "private",
          "status_reasons": [
            "off_topic"
          ]
        }
      }
    ]
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/posts', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/vnd.api+json; ext=bulk',
  },
  body: JSON.stringify({
      "data": [
        {
          "id": "9001",
          "type": "post",
          "attributes": {
            "status": "public"
          }
        },
        {
          "id": "9002",
          "type": "post",
          "attributes": {
            "status": "private",
            "status_reasons": [
              "off_topic"
            ]
          }
        }
      ]
    }),
});

const data = await response.json();
import requests

payload = {
  "data": [
    {
      "id": "9001",
      "type": "post",
      "attributes": {
        "status": "public"
      }
    },
    {
      "id": "9002",
      "type": "post",
      "attributes": {
        "status": "private",
        "status_reasons": [
          "off_topic"
        ]
      }
    }
  ]
}

response = requests.patch('https://api.tintup.com/v2/teams/{team_id}/posts', json=payload)
data = response.json()
Request Body
{
  "data": [
    {
      "id": "9001",
      "type": "post",
      "attributes": {
        "status": "public"
      }
    },
    {
      "id": "9002",
      "type": "post",
      "attributes": {
        "status": "private",
        "status_reasons": [
          "off_topic"
        ]
      }
    }
  ]
}
{
  "data": [
    {
      "id": "9001",
      "type": "post",
      "attributes": {
        "external_id": "17912345678901234",
        "url": "https://www.instagram.com/p/C4xYz12AbCd/",
        "title": null,
        "text": "Loving my new Acme sneakers!",
        "alternative_text": "A pair of white Acme sneakers on a beach.",
        "published_at": "2025-03-14T16:42:07.000Z",
        "highlighted": false,
        "pinned": false,
        "tags": [
          "featured"
        ],
        "carousel": false,
        "media_type": "image",
        "image_url": "https://cdn.example.com/posts/9001/media.jpg",
        "video_url": null,
        "attachment_id": "aHR0cHM6Ly9jZG4uZXhhbXBsZS5jb20vcG9zdHMvOTAwMS9tZWRpYS5qcGc=",
        "author": {
          "name": "Jane Doe",
          "username": "janedoe",
          "url": "https://example.com/janedoe",
          "image_url": "https://cdn.example.com/avatars/janedoe.jpg",
          "external_id": "17841400008460056",
          "email": "jane.doe@example.com",
          "phone": "+15555550123",
          "remote_ip": "203.0.113.0"
        },
        "metadata": {
          "language": "en",
          "sentiment": "positive",
          "image_nsfw": 0.02,
          "image_phash": "d1c4f0e0b0a09080",
          "image_sentiments": [
            "happy"
          ],
          "image_objects": [
            "shoe",
            "beach"
          ],
          "image_objects_rekognition": [
            "shoe",
            "beach"
          ]
        },
        "language": "en",
        "rating": 80,
        "verified": null,
        "incentivized": null,
        "status_reasons": null,
        "last_moderated_at": "2025-03-15T09:03:11.000Z",
        "custom_field": null,
        "sentiment": "positive",
        "image_nsfw": 0.02,
        "image_phash": null,
        "image_sentiments": null,
        "image_objects": [
          "shoe",
          "beach"
        ],
        "hue_probability": null
      },
      "relationships": {
        "social_feed": {
          "data": {
            "type": "social_feed",
            "id": "311"
          }
        },
        "tint": {
          "data": {
            "type": "tint",
            "id": "42"
          },
          "links": {
            "self": "https://api.tintup.com/v2/teams/1/tints/42"
          }
        },
        "author": {
          "data": {
            "type": "author",
            "id": "9001"
          },
          "meta": {
            "included": false
          }
        },
        "replies": {
          "data": [
            {
              "type": "reply",
              "id": "88"
            }
          ],
          "meta": {
            "included": false
          }
        },
        "products": {
          "data": [
            {
              "type": "product_tag",
              "id": "501"
            }
          ],
          "meta": {
            "included": false
          }
        },
        "product_tags": {
          "data": [
            {
              "type": "product_tag",
              "id": "501"
            }
          ],
          "meta": {
            "included": false
          }
        },
        "cta_associations": {
          "data": [
            {
              "type": "cta_association",
              "id": "64"
            }
          ],
          "meta": {
            "included": false
          }
        },
        "asset": {
          "data": {
            "type": "asset",
            "id": "7300"
          },
          "meta": {
            "included": false
          }
        },
        "right_requests": {
          "data": [
            {
              "type": "right_request",
              "id": "210"
            }
          ],
          "meta": {
            "included": false,
            "status": "approved",
            "status_expires_at": null
          }
        },
        "siblings": {
          "data": [
            {
              "type": "post",
              "id": "9002"
            }
          ]
        }
      }
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Retrieve aggregated post moderation metrics

GET
https://api.tintup.com/v2/teams/{team_id}/posts/metrics/moderated

Parameters

team_idintegerrequiredpath

The ID of the team.

filterobjectquery

Filters the moderation events that are counted.

groupArray<string>time.hourtime.daytime.weektime.monthtime.quartertime.yeartime.day_of_weektime.hour_of_dayuser_idtint_idstatussourcequery

A comma-separated list of dimensions to group the metrics by.

Response

200OKobject

A list of moderated post metrics.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: posts:read

Retrieve aggregated post moderation metrics
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/posts/metrics/moderated'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/posts/metrics/moderated', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/posts/metrics/moderated')
data = response.json()
200
{
  "data": [
    {
      "id": "f42c2ba98b72afee69976d52875fe313",
      "type": "posts_metric",
      "attributes": {
        "count": 1284,
        "dimensions": {
          "tint_id": "42",
          "status": "public"
        }
      },
      "relationships": {
        "tint": {
          "data": {
            "type": "tint",
            "id": "42"
          }
        },
        "user": {
          "data": {
            "type": "user",
            "id": "16891"
          }
        }
      }
    }
  ]
}

Retrieve aggregated post engagement metrics

GET
https://api.tintup.com/v2/teams/{team_id}/posts/metrics/engagements/{post_engagement_type}

Parameters

team_idintegerrequiredpath

The ID of the team.

post_engagement_typestringembed_post_modal_openedembed_post_external_link_openedembed_post_cta_clickedembed_post_sharedembed_post_modal_navigate_rightembed_post_modal_navigate_leftembed_paginatedembed_post_author_clickedembed_post_product_clickedrequiredpath

The post engagement event type to count.

filterobjectquery

Filters the engagement events that are counted.

groupArray<string>time.hourtime.daytime.weektime.monthtime.quartertime.yeartime.day_of_weektime.hour_of_daytint_idpost_idpersonalization_typethemedevice_categorymedia_typequery

A comma-separated list of dimensions to group the metrics by.

Response

200OKobject

A list of post engagement metrics.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: posts:read

Retrieve aggregated post engagement metrics
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/posts/metrics/engagements/{post_engagement_type}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/posts/metrics/engagements/{post_engagement_type}', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/posts/metrics/engagements/{post_engagement_type}')
data = response.json()
200
{
  "data": [
    {
      "id": "f42c2ba98b72afee69976d52875fe313",
      "type": "embed_engagement_metric",
      "attributes": {
        "count": 1284,
        "dimensions": {
          "tint_id": "42",
          "time": "2025-03-14T00:00:00.000-04:00",
          "created_at": "2025-03-14T00:00:00.000-04:00"
        }
      },
      "relationships": {
        "tint": {
          "data": {
            "type": "tint",
            "id": "42"
          }
        },
        "post": {
          "data": {
            "type": "post",
            "id": "9001"
          }
        }
      }
    }
  ]
}

Retrieve aggregated post ingestion metrics

GET
https://api.tintup.com/v2/teams/{team_id}/posts/metrics/ingested

Provides up to 12 months of ingestion metrics. Authentication isn't required when filter[social_feed_id] or filter[tint_id] is specified; otherwise, the access token must have the posts:read scope.

Parameters

team_idintegerrequiredpath

The ID of the team.

filterobjectquery

Filters the ingested posts that are counted.

groupArray<string>time.hourtime.daytime.weektime.monthtime.quartertime.yeartime.day_of_weektime.hour_of_daysocial_feed_idsocial_feed_sourcetint_idaccount_idquery

A comma-separated list of dimensions to group the metrics by.

Response

200OKobject

A list of ingested post metrics.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: posts:read

Retrieve aggregated post ingestion metrics
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/posts/metrics/ingested'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/posts/metrics/ingested', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/posts/metrics/ingested')
data = response.json()
200
{
  "data": [
    {
      "id": "f42c2ba98b72afee69976d52875fe313",
      "type": "posts_ingested_metric",
      "attributes": {
        "count": 1284,
        "dimensions": {
          "social_feed_source": "instagram_business",
          "time": "2025-03-14T00:00:00.000Z",
          "created_at": "2025-03-14T00:00:00.000Z"
        }
      },
      "relationships": {
        "social_feed": {
          "data": {
            "type": "social_feed",
            "id": "311"
          }
        },
        "tint": {
          "data": {
            "type": "tint",
            "id": "42"
          }
        },
        "account": {
          "data": {
            "type": "account",
            "id": "77"
          }
        }
      }
    }
  ]
}

Delete a post

DELETE
https://api.tintup.com/v2/teams/{team_id}/posts/{post_id}

Deletes the post.

Parameters

team_idintegerrequiredpath

The ID of the team.

post_idintegerrequiredpath

The ID of the post.

Response

204No Content

No Content. The request succeeded and there is no response body.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: posts:write

Delete a post
curl -X DELETE 'https://api.tintup.com/v2/teams/{team_id}/posts/{post_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/posts/{post_id}', {
  method: 'DELETE',
});

const data = await response.json();
import requests

response = requests.delete('https://api.tintup.com/v2/teams/{team_id}/posts/{post_id}')
data = response.json()

Update a post

PATCH
https://api.tintup.com/v2/teams/{team_id}/posts/{post_id}

Updates the post.

Body

application/vnd.api+json

The post changes.

dataPostUpdaterequired

The post changes. The id is optional; the post is identified by the URL.

Show child attributes
idstring

The ID of the post.

typePostTypepostrequired

The resource type. Always post.

attributesPostWritableAttributes

Attributes that can be changed on an existing post. Only the attributes sent are changed. title, text, url, custom_field and author can only be changed on custom posts and are ignored for other posts.

Show child attributes
statusPostStatus

The moderation status of the post. Use public, private, or deleted to moderate posts.

status_reasonsArray<PostStatusReason> | nulllegal_transgressioninappropriateforeign_languagecontains_private_infounrelatedmisleadingfakeharmful_contentwrong_languageoff_topicspamlow_effortnonsenseauto_moderationauto_moderation_nsfwauto_moderation_authorauto_moderation_keywordauto_moderation_remote_ip

The reasons for the post's moderation status.

highlightedboolean

Whether the post is highlighted.

pinnedboolean

Whether the post is pinned to the top of the board.

tagsArray<string>

The tags assigned to the post. A comma-separated string is also accepted.

alternative_textstring | null

The alternative text describing the post's media, for accessibility.

verifiedboolean | null

Whether the review is from a verified buyer. Must be null (or omitted) for posts that aren't reviews.

incentivizedboolean | null

Whether the reviewer received an incentive. Must be null (or omitted) for posts that aren't reviews.

titlestring | null

The title of the post. Custom posts only.

textstring | null

The text of the post. Custom posts only.

urlstring<uri> | null

The URL the post links to. Must start with http:// or https://. Custom posts only.

custom_fieldstring | null

The value of the custom field. Custom posts only.

authorNewPostAuthor

The author of the post. Custom posts only. Send an empty image_id to remove the author's uploaded avatar.

Parameters

team_idintegerrequiredpath

The ID of the team.

post_idintegerrequiredpath

The ID of the post.

Response

200OKobject

The post.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: posts:write

Update a post
curl -X PATCH 'https://api.tintup.com/v2/teams/{team_id}/posts/{post_id}' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "id": "9001",
      "type": "post",
      "attributes": {
        "status": "public",
        "highlighted": true,
        "tags": [
          "featured",
          "follow up"
        ]
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/posts/{post_id}', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "id": "9001",
        "type": "post",
        "attributes": {
          "status": "public",
          "highlighted": true,
          "tags": [
            "featured",
            "follow up"
          ]
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "id": "9001",
    "type": "post",
    "attributes": {
      "status": "public",
      "highlighted": True,
      "tags": [
        "featured",
        "follow up"
      ]
    }
  }
}

response = requests.patch('https://api.tintup.com/v2/teams/{team_id}/posts/{post_id}', json=payload)
data = response.json()
Request Body
{
  "data": {
    "id": "9001",
    "type": "post",
    "attributes": {
      "status": "public",
      "highlighted": true,
      "tags": [
        "featured",
        "follow up"
      ]
    }
  }
}
{
  "data": {
    "id": "9001",
    "type": "post",
    "attributes": {
      "external_id": "17912345678901234",
      "url": "https://www.instagram.com/p/C4xYz12AbCd/",
      "title": null,
      "text": "Loving my new Acme sneakers!",
      "alternative_text": "A pair of white Acme sneakers on a beach.",
      "published_at": "2025-03-14T16:42:07.000Z",
      "highlighted": false,
      "pinned": false,
      "tags": [
        "featured"
      ],
      "carousel": false,
      "media_type": "image",
      "image_url": "https://cdn.example.com/posts/9001/media.jpg",
      "video_url": null,
      "attachment_id": "aHR0cHM6Ly9jZG4uZXhhbXBsZS5jb20vcG9zdHMvOTAwMS9tZWRpYS5qcGc=",
      "author": {
        "name": "Jane Doe",
        "username": "janedoe",
        "url": "https://example.com/janedoe",
        "image_url": "https://cdn.example.com/avatars/janedoe.jpg",
        "external_id": "17841400008460056",
        "email": "jane.doe@example.com",
        "phone": "+15555550123",
        "remote_ip": "203.0.113.0"
      },
      "metadata": {
        "language": "en",
        "sentiment": "positive",
        "image_nsfw": 0.02,
        "image_phash": "d1c4f0e0b0a09080",
        "image_sentiments": [
          "happy"
        ],
        "image_objects": [
          "shoe",
          "beach"
        ],
        "image_objects_rekognition": [
          "shoe",
          "beach"
        ]
      },
      "language": "en",
      "rating": 80,
      "verified": null,
      "incentivized": null,
      "status_reasons": null,
      "last_moderated_at": "2025-03-15T09:03:11.000Z",
      "custom_field": null,
      "sentiment": "positive",
      "image_nsfw": 0.02,
      "image_phash": null,
      "image_sentiments": null,
      "image_objects": [
        "shoe",
        "beach"
      ],
      "hue_probability": null
    },
    "relationships": {
      "social_feed": {
        "data": {
          "type": "social_feed",
          "id": "311"
        }
      },
      "tint": {
        "data": {
          "type": "tint",
          "id": "42"
        },
        "links": {
          "self": "https://api.tintup.com/v2/teams/1/tints/42"
        }
      },
      "author": {
        "data": {
          "type": "author",
          "id": "9001"
        },
        "meta": {
          "included": false
        }
      },
      "replies": {
        "data": [
          {
            "type": "reply",
            "id": "88"
          }
        ],
        "meta": {
          "included": false
        }
      },
      "products": {
        "data": [
          {
            "type": "product_tag",
            "id": "501"
          }
        ],
        "meta": {
          "included": false
        }
      },
      "product_tags": {
        "data": [
          {
            "type": "product_tag",
            "id": "501"
          }
        ],
        "meta": {
          "included": false
        }
      },
      "cta_associations": {
        "data": [
          {
            "type": "cta_association",
            "id": "64"
          }
        ],
        "meta": {
          "included": false
        }
      },
      "asset": {
        "data": {
          "type": "asset",
          "id": "7300"
        },
        "meta": {
          "included": false
        }
      },
      "right_requests": {
        "data": [
          {
            "type": "right_request",
            "id": "210"
          }
        ],
        "meta": {
          "included": false,
          "status": "approved",
          "status_expires_at": null
        }
      },
      "siblings": {
        "data": [
          {
            "type": "post",
            "id": "9002"
          }
        ]
      }
    }
  }
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Retrieve a list of posts for a board

deprecated
GET
https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/posts

This endpoint is deprecated. Use GET /v2/teams/{team_id}/posts?filter[tint_id]={tint_id} instead, which accepts the same parameters.

Parameters

team_idintegerrequiredpath

The ID of the team.

tint_idintegerrequiredpath

The ID of the board.

filterobjectquery

Filters the posts. Unless noted, list filters take a comma-separated list of values and match any of them.

sortArray<string>pinned-pinnedpublished_at-published_atlast_moderated_at-last_moderated_atrating-ratingscore-score-pinnedquery

A comma-separated list of fields to sort by. Prefix a field with - to sort in descending order. Ties are broken by publication time and ID. score sorts by relevance to filter[q].

includeArray<string>assetauthorcta_associationscta_associations.ctaproduct_tagsproductsproducts.productrepliesright_requestssocial_feedtintquery

A comma-separated list of related resources to include in the response.

collapsestringsource,external_idquery

Use source,external_id to return a single post for posts ingested in several boards from the same source post. The other copies are returned in the siblings relationship, and the response uses offset pagination (page[offset], starting at 0) instead of cursors.

objectquery

Cursor pagination. Use page[size] to set the number of items per page. Cursors are opaque; don't build them yourself, follow the links.next and links.prev URLs from the previous response instead.

Response

200OKobject

A list of posts.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: posts:read

Retrieve a list of posts for a board
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/posts'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/posts', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/posts')
data = response.json()
200
{
  "data": [
    {
      "id": "9001",
      "type": "post",
      "attributes": {
        "external_id": "17912345678901234",
        "url": "https://www.instagram.com/p/C4xYz12AbCd/",
        "title": null,
        "text": "Loving my new Acme sneakers!",
        "alternative_text": "A pair of white Acme sneakers on a beach.",
        "published_at": "2025-03-14T16:42:07.000Z",
        "highlighted": false,
        "pinned": false,
        "tags": [
          "featured"
        ],
        "carousel": false,
        "media_type": "image",
        "image_url": "https://cdn.example.com/posts/9001/media.jpg",
        "video_url": null,
        "attachment_id": "aHR0cHM6Ly9jZG4uZXhhbXBsZS5jb20vcG9zdHMvOTAwMS9tZWRpYS5qcGc=",
        "author": {
          "name": "Jane Doe",
          "username": "janedoe",
          "url": "https://example.com/janedoe",
          "image_url": "https://cdn.example.com/avatars/janedoe.jpg",
          "external_id": "17841400008460056",
          "email": "jane.doe@example.com",
          "phone": "+15555550123",
          "remote_ip": "203.0.113.0"
        },
        "metadata": {
          "language": "en",
          "sentiment": "positive",
          "image_nsfw": 0.02,
          "image_phash": "d1c4f0e0b0a09080",
          "image_sentiments": [
            "happy"
          ],
          "image_objects": [
            "shoe",
            "beach"
          ],
          "image_objects_rekognition": [
            "shoe",
            "beach"
          ]
        },
        "language": "en",
        "rating": 80,
        "verified": null,
        "incentivized": null,
        "status_reasons": null,
        "last_moderated_at": "2025-03-15T09:03:11.000Z",
        "custom_field": null,
        "sentiment": "positive",
        "image_nsfw": 0.02,
        "image_phash": null,
        "image_sentiments": null,
        "image_objects": [
          "shoe",
          "beach"
        ],
        "hue_probability": null
      },
      "relationships": {
        "social_feed": {
          "data": {
            "type": "social_feed",
            "id": "311"
          }
        },
        "tint": {
          "data": {
            "type": "tint",
            "id": "42"
          },
          "links": {
            "self": "https://api.tintup.com/v2/teams/1/tints/42"
          }
        },
        "author": {
          "data": {
            "type": "author",
            "id": "9001"
          },
          "meta": {
            "included": false
          }
        },
        "replies": {
          "data": [
            {
              "type": "reply",
              "id": "88"
            }
          ],
          "meta": {
            "included": false
          }
        },
        "products": {
          "data": [
            {
              "type": "product_tag",
              "id": "501"
            }
          ],
          "meta": {
            "included": false
          }
        },
        "product_tags": {
          "data": [
            {
              "type": "product_tag",
              "id": "501"
            }
          ],
          "meta": {
            "included": false
          }
        },
        "cta_associations": {
          "data": [
            {
              "type": "cta_association",
              "id": "64"
            }
          ],
          "meta": {
            "included": false
          }
        },
        "asset": {
          "data": {
            "type": "asset",
            "id": "7300"
          },
          "meta": {
            "included": false
          }
        },
        "right_requests": {
          "data": [
            {
              "type": "right_request",
              "id": "210"
            }
          ],
          "meta": {
            "included": false,
            "status": "approved",
            "status_expires_at": null
          }
        },
        "siblings": {
          "data": [
            {
              "type": "post",
              "id": "9002"
            }
          ]
        }
      }
    }
  ],
  "links": {
    "self": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=2",
    "first": "https://api.tintup.com/v2/teams/1/tints",
    "next": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=3",
    "prev": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=1"
  }
}

Create a custom post

POST
https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/posts

Asynchronously creates a post in the board's custom social feed (the feed is created if it doesn't exist). The response is a post create request; the post itself is created shortly after.

Body

application/vnd.api+json

The custom post to create.

dataNewPostrequired

The custom post to create. The post's status, external ID and publication time are set by the server. Each file in media creates a separate post; when several are sent, the posts are grouped as a carousel.

Show child attributes
typePostTypepostrequired

The resource type. Always post.

attributesobject
Show child attributes
textstring

The text of the post.

titlestring

The title of the post.

urlstring<uri>

The URL the post links to. Must start with http:// or https://.

alternative_textstring

The alternative text describing the post's media, for accessibility.

highlightedbooleanfalse

Whether the post is highlighted.

pinnedbooleanfalse

Whether the post is pinned to the top of the board.

tagsArray<string>

The tags to assign to the post. A comma-separated string is also accepted.

mediaArray<string>

The signed IDs of images or videos uploaded with POST /v2/teams/{team_id}/posts/upload. Files that aren't images or videos are ignored.

authorNewPostAuthor

The author of the post.

Show child attributes
namestring

The author's display name. Required for reviews when the Ratings & Reviews social feed requires the author's name.

usernamestring

The author's username.

emailstring<email>

The author's email address. Required for public posts and reviews when the social feed shows the email field.

phonestring

The author's phone number.

external_idstring

The author's ID in your system.

urlstring<uri>

The URL of the author's profile. Must start with http:// or https://.

image_urlstring<uri>

The URL of the author's avatar. Must start with http:// or https://.

image_idstring

The signed ID of a file uploaded with POST /v2/teams/{team_id}/posts/upload, used as the author's avatar. Only used for custom posts.

Parameters

team_idintegerrequiredpath

The ID of the team.

tint_idintegerrequiredpath

The ID of the board.

Response

202Acceptedobject

The post create request.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: posts:write

Create a custom post
curl -X POST 'https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/posts' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "post",
      "attributes": {
        "text": "Our summer collection just dropped!",
        "url": "https://example.com/summer",
        "alternative_text": "A pair of white Acme sneakers on a beach.",
        "pinned": true,
        "tags": [
          "featured"
        ],
        "media": [
          "eyJfcmFpbHMiOnsiZGF0YSI6MTIzNDUsInB1ciI6ImJsb2JfaWQifX0=--0f1e2d3c4b5a69788796a5b4c3d2e1f0a9b8c7d6"
        ],
        "author": {
          "name": "Acme Inc.",
          "username": "acme",
          "url": "https://example.com"
        }
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/posts', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "post",
        "attributes": {
          "text": "Our summer collection just dropped!",
          "url": "https://example.com/summer",
          "alternative_text": "A pair of white Acme sneakers on a beach.",
          "pinned": true,
          "tags": [
            "featured"
          ],
          "media": [
            "eyJfcmFpbHMiOnsiZGF0YSI6MTIzNDUsInB1ciI6ImJsb2JfaWQifX0=--0f1e2d3c4b5a69788796a5b4c3d2e1f0a9b8c7d6"
          ],
          "author": {
            "name": "Acme Inc.",
            "username": "acme",
            "url": "https://example.com"
          }
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "post",
    "attributes": {
      "text": "Our summer collection just dropped!",
      "url": "https://example.com/summer",
      "alternative_text": "A pair of white Acme sneakers on a beach.",
      "pinned": True,
      "tags": [
        "featured"
      ],
      "media": [
        "eyJfcmFpbHMiOnsiZGF0YSI6MTIzNDUsInB1ciI6ImJsb2JfaWQifX0=--0f1e2d3c4b5a69788796a5b4c3d2e1f0a9b8c7d6"
      ],
      "author": {
        "name": "Acme Inc.",
        "username": "acme",
        "url": "https://example.com"
      }
    }
  }
}

response = requests.post('https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/posts', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "post",
    "attributes": {
      "text": "Our summer collection just dropped!",
      "url": "https://example.com/summer",
      "alternative_text": "A pair of white Acme sneakers on a beach.",
      "pinned": true,
      "tags": [
        "featured"
      ],
      "media": [
        "eyJfcmFpbHMiOnsiZGF0YSI6MTIzNDUsInB1ciI6ImJsb2JfaWQifX0=--0f1e2d3c4b5a69788796a5b4c3d2e1f0a9b8c7d6"
      ],
      "author": {
        "name": "Acme Inc.",
        "username": "acme",
        "url": "https://example.com"
      }
    }
  }
}
{
  "data": {
    "id": "OxZZQtuh5sXIKA",
    "type": "post_create_request",
    "attributes": {
      "status": "pending"
    }
  }
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Retrieve a list of public posts for a board

GET
https://api.tintup.com/v2/tints/{tint_slug}/posts

Returns the public posts of a public board. No authentication is required; if an Authorization header is sent, the access token must have the posts:read scope.

Parameters

tint_slugstringrequiredpath

The slug of the board, the unique part of its public URL.

filterobjectquery

Filters the posts. Only public posts are returned. Unless noted, list filters take a comma-separated list of values and match any of them.

sortArray<string>pinned-pinnedpublished_at-published_atlast_moderated_at-last_moderated_atrating-ratingscore-score-pinnedquery

A comma-separated list of fields to sort by. Prefix a field with - to sort in descending order. Ties are broken by publication time and ID. score sorts by relevance to filter[q].

includeArray<string>authorcta_associationscta_associations.ctaproduct_tagsproductsproducts.productrepliessocial_feedquery

A comma-separated list of related resources to include in the response.

objectquery

Cursor pagination. Use page[size] to set the number of items per page. Cursors are opaque; don't build them yourself, follow the links.next and links.prev URLs from the previous response instead.

Response

200OKobject

A list of public posts. Without an access token, the public representation of posts is returned; with one, the authenticated representation is returned.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: posts:read

Retrieve a list of public posts for a board
curl -X GET 'https://api.tintup.com/v2/tints/{tint_slug}/posts'
const response = await fetch('https://api.tintup.com/v2/tints/{tint_slug}/posts', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/tints/{tint_slug}/posts')
data = response.json()
200
{
  "data": [
    {
      "id": "9001",
      "type": "post",
      "attributes": {
        "external_id": "17912345678901234",
        "url": "https://www.instagram.com/p/C4xYz12AbCd/",
        "title": null,
        "text": "Loving my new Acme sneakers!",
        "alternative_text": "A pair of white Acme sneakers on a beach.",
        "published_at": "2025-03-14T16:42:07.000Z",
        "highlighted": false,
        "pinned": false,
        "tags": [
          "featured"
        ],
        "carousel": false,
        "media_type": "image",
        "image_url": "https://cdn.example.com/posts/9001/media.jpg",
        "video_url": null,
        "attachment_id": "aHR0cHM6Ly9jZG4uZXhhbXBsZS5jb20vcG9zdHMvOTAwMS9tZWRpYS5qcGc=",
        "author": {
          "name": "Jane Doe",
          "username": "janedoe",
          "url": "https://example.com/janedoe",
          "image_url": "https://cdn.example.com/avatars/janedoe.jpg",
          "external_id": "17841400008460056",
          "email": "jane.doe@example.com",
          "phone": "+15555550123",
          "remote_ip": "203.0.113.0"
        },
        "metadata": {
          "language": "en",
          "sentiment": "positive",
          "image_nsfw": 0.02,
          "image_phash": "d1c4f0e0b0a09080",
          "image_sentiments": [
            "happy"
          ],
          "image_objects": [
            "shoe",
            "beach"
          ],
          "image_objects_rekognition": [
            "shoe",
            "beach"
          ]
        },
        "language": "en",
        "rating": 80,
        "verified": null,
        "incentivized": null,
        "status_reasons": null,
        "last_moderated_at": "2025-03-15T09:03:11.000Z",
        "custom_field": null,
        "sentiment": "positive",
        "image_nsfw": 0.02,
        "image_phash": null,
        "image_sentiments": null,
        "image_objects": [
          "shoe",
          "beach"
        ],
        "hue_probability": null
      },
      "relationships": {
        "social_feed": {
          "data": {
            "type": "social_feed",
            "id": "311"
          }
        },
        "tint": {
          "data": {
            "type": "tint",
            "id": "42"
          },
          "links": {
            "self": "https://api.tintup.com/v2/teams/1/tints/42"
          }
        },
        "author": {
          "data": {
            "type": "author",
            "id": "9001"
          },
          "meta": {
            "included": false
          }
        },
        "replies": {
          "data": [
            {
              "type": "reply",
              "id": "88"
            }
          ],
          "meta": {
            "included": false
          }
        },
        "products": {
          "data": [
            {
              "type": "product_tag",
              "id": "501"
            }
          ],
          "meta": {
            "included": false
          }
        },
        "product_tags": {
          "data": [
            {
              "type": "product_tag",
              "id": "501"
            }
          ],
          "meta": {
            "included": false
          }
        },
        "cta_associations": {
          "data": [
            {
              "type": "cta_association",
              "id": "64"
            }
          ],
          "meta": {
            "included": false
          }
        },
        "asset": {
          "data": {
            "type": "asset",
            "id": "7300"
          },
          "meta": {
            "included": false
          }
        },
        "right_requests": {
          "data": [
            {
              "type": "right_request",
              "id": "210"
            }
          ],
          "meta": {
            "included": false,
            "status": "approved",
            "status_expires_at": null
          }
        },
        "siblings": {
          "data": [
            {
              "type": "post",
              "id": "9002"
            }
          ]
        }
      }
    }
  ],
  "links": {
    "self": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=2",
    "first": "https://api.tintup.com/v2/teams/1/tints",
    "next": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=3",
    "prev": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=1"
  }
}

Create a public post

POST
https://api.tintup.com/v2/tints/{tint_slug}/posts

Asynchronously creates a post in the board's public post social feed. No authentication is required; if an Authorization header is sent, the access token must have the posts:write scope. The response is a post create request whose status can be checked using GET /v2/tints/{tint_slug}/posts/requests/{post_request_id}.

Body

application/vnd.api+json

The public post or review to create.

dataNewPublicPostrequired

The public post or review to create. The validation rules depend on the settings of the board's public post or Ratings & Reviews social feed. Each URL in media_url creates a separate post; when several are sent, the posts are grouped as a carousel.

Show child attributes
typePostTypepostrequired

The resource type. Always post.

attributesobject
Show child attributes
typestringpostreviewspost

The kind of submission, which selects the social feed: post for the board's public post social feed, reviews for its Ratings & Reviews social feed. The board must have a social feed of that kind.

textstring

The text of the post. Required for reviews.

titlestring

The title of the post.

ratinginteger[0, 100]

The rating from 0 to 100. Required for reviews; ignored otherwise.

custom_fieldstring

The value of the social feed's custom field. Required when the social feed shows the custom field.

media_urlArray<string>

The URLs of images or videos to attach, each starting with http:// or https://. A comma-separated string is also accepted. Required for reviews when the social feed requires media. Limited to one URL unless the social feed accepts multiple files.

tagsArray<string>

The tags to assign to the post. A comma-separated string is also accepted. Each tag must already exist in the board. For reviews, a tag can also be a product SKU (optionally prefixed with sku:) or a product family prefixed with family:.

authorNewPostAuthor

The author of the post.

Show child attributes
namestring

The author's display name. Required for reviews when the Ratings & Reviews social feed requires the author's name.

usernamestring

The author's username.

emailstring<email>

The author's email address. Required for public posts and reviews when the social feed shows the email field.

phonestring

The author's phone number.

external_idstring

The author's ID in your system.

urlstring<uri>

The URL of the author's profile. Must start with http:// or https://.

image_urlstring<uri>

The URL of the author's avatar. Must start with http:// or https://.

image_idstring

The signed ID of a file uploaded with POST /v2/teams/{team_id}/posts/upload, used as the author's avatar. Only used for custom posts.

Parameters

tint_slugstringrequiredpath

The slug of the board, the unique part of its public URL.

Response

202Acceptedobject

The post create request.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: posts:write

Create a public post
curl -X POST 'https://api.tintup.com/v2/tints/{tint_slug}/posts' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "post",
      "attributes": {
        "type": "reviews",
        "title": "Great everyday sneakers",
        "text": "Super comfortable and true to size. Would buy again!",
        "rating": 80,
        "media_url": [
          "https://cdn.example.com/uploads/sneakers.jpg"
        ],
        "tags": [
          "sku:ACME-SNK-001"
        ],
        "author": {
          "name": "Jane Doe",
          "email": "jane.doe@example.com"
        }
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/tints/{tint_slug}/posts', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "post",
        "attributes": {
          "type": "reviews",
          "title": "Great everyday sneakers",
          "text": "Super comfortable and true to size. Would buy again!",
          "rating": 80,
          "media_url": [
            "https://cdn.example.com/uploads/sneakers.jpg"
          ],
          "tags": [
            "sku:ACME-SNK-001"
          ],
          "author": {
            "name": "Jane Doe",
            "email": "jane.doe@example.com"
          }
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "post",
    "attributes": {
      "type": "reviews",
      "title": "Great everyday sneakers",
      "text": "Super comfortable and true to size. Would buy again!",
      "rating": 80,
      "media_url": [
        "https://cdn.example.com/uploads/sneakers.jpg"
      ],
      "tags": [
        "sku:ACME-SNK-001"
      ],
      "author": {
        "name": "Jane Doe",
        "email": "jane.doe@example.com"
      }
    }
  }
}

response = requests.post('https://api.tintup.com/v2/tints/{tint_slug}/posts', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "post",
    "attributes": {
      "type": "reviews",
      "title": "Great everyday sneakers",
      "text": "Super comfortable and true to size. Would buy again!",
      "rating": 80,
      "media_url": [
        "https://cdn.example.com/uploads/sneakers.jpg"
      ],
      "tags": [
        "sku:ACME-SNK-001"
      ],
      "author": {
        "name": "Jane Doe",
        "email": "jane.doe@example.com"
      }
    }
  }
}
{
  "data": {
    "id": "OxZZQtuh5sXIKA",
    "type": "post_create_request",
    "attributes": {
      "status": "pending"
    }
  }
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Check the status of a post create request

GET
https://api.tintup.com/v2/tints/{tint_slug}/posts/requests/{post_request_id}

Returns the status of an asynchronous request created by POST /v2/tints/{tint_slug}/posts. No authentication is required; if an Authorization header is sent, the access token must have the posts:read scope.

Parameters

tint_slugstringrequiredpath

The slug of the board, the unique part of its public URL.

post_request_idstringrequiredpath

The ID of the post create request, returned when the post was submitted.

Response

200OKobject

The post create request.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: posts:read

Check the status of a post create request
curl -X GET 'https://api.tintup.com/v2/tints/{tint_slug}/posts/requests/{post_request_id}'
const response = await fetch('https://api.tintup.com/v2/tints/{tint_slug}/posts/requests/{post_request_id}', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/tints/{tint_slug}/posts/requests/{post_request_id}')
data = response.json()
200
{
  "data": {
    "id": "OxZZQtuh5sXIKA",
    "type": "post_create_request",
    "attributes": {
      "status": "pending"
    }
  }
}

Create a post export request

POST
https://api.tintup.com/v2/teams/{team_id}/posts/export/requests

Asynchronously exports posts. Once complete, a websocket message of type post_export_request containing the response is delivered to the user's private channel (private-user- followed by the user's ID). You may also poll the status of the request using the endpoint below.

Body

application/vnd.api+json

The export to request.

dataNewPostExportRequestrequired

The export to request.

Show child attributes
typePostExportRequestTypepost_export_requestrequired

The resource type. Always post_export_request.

attributesobjectrequired
Show child attributes
tint_idintegerrequired

The ID of the board whose posts to export. You must have access to the board.

Parameters

team_idintegerrequiredpath

The ID of the team.

Response

202Acceptedobject

The post export request.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: posts:read

Create a post export request
curl -X POST 'https://api.tintup.com/v2/teams/{team_id}/posts/export/requests' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "post_export_request",
      "attributes": {
        "tint_id": 42
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/posts/export/requests', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "post_export_request",
        "attributes": {
          "tint_id": 42
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "post_export_request",
    "attributes": {
      "tint_id": 42
    }
  }
}

response = requests.post('https://api.tintup.com/v2/teams/{team_id}/posts/export/requests', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "post_export_request",
    "attributes": {
      "tint_id": 42
    }
  }
}
202
{
  "data": {
    "id": "OxZZQtuh5sXIKA",
    "type": "post_export_request",
    "attributes": {
      "status": "pending",
      "url": null
    },
    "relationships": {
      "tint": {
        "data": {
          "type": "tint",
          "id": "42"
        },
        "meta": {
          "included": false
        }
      },
      "user": {
        "data": {
          "type": "user",
          "id": "16891"
        },
        "meta": {
          "included": false
        }
      }
    },
    "links": {
      "self": "https://api.tintup.com/v2/teams/1/posts/export/requests/OxZZQtuh5sXIKA"
    }
  }
}

Check the status of a post export request

GET
https://api.tintup.com/v2/teams/{team_id}/posts/export/requests/{post_export_request_id}

Parameters

team_idintegerrequiredpath

The ID of the team.

post_export_request_idstringrequiredpath

The ID of the post export request.

Response

200OKobject

The post export request.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: posts:read

Check the status of a post export request
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/posts/export/requests/{post_export_request_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/posts/export/requests/{post_export_request_id}', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/posts/export/requests/{post_export_request_id}')
data = response.json()
200
{
  "data": {
    "id": "OxZZQtuh5sXIKA",
    "type": "post_export_request",
    "attributes": {
      "status": "pending",
      "url": null
    },
    "relationships": {
      "tint": {
        "data": {
          "type": "tint",
          "id": "42"
        },
        "meta": {
          "included": false
        }
      },
      "user": {
        "data": {
          "type": "user",
          "id": "16891"
        },
        "meta": {
          "included": false
        }
      }
    },
    "links": {
      "self": "https://api.tintup.com/v2/teams/1/posts/export/requests/OxZZQtuh5sXIKA"
    }
  }
}
Boards

Replies

posts_replies

Create a reply

POST
https://api.tintup.com/v2/teams/{team_id}/replies

Replies to a post. When the post's author has an email address and the social feed has an email template, the reply is also emailed to the author.

Body

application/vnd.api+json

The reply to create.

dataNewReplyrequired

The reply to create.

Show child attributes
typeReplyTypereplyrequired

The resource type. Always reply.

attributesobjectrequired
Show child attributes
textReplyTextrequired

The text of the reply. Plain text only (HTML isn't allowed), from 1 to 500 characters.

sourceSocialFeedSourcerequired

The source of the post the reply is for (the post's type attribute).

external_idstringrequired

The ID, at the source, of the post the reply is for (the post's external_id attribute). The post must belong to a board you have access to.

visibilityReplyVisibilityactive

Parameters

team_idintegerrequiredpath

The ID of the team.

includeArray<string>userquery

A comma-separated list of related resources to include in the response.

Response

201Createdobject

The reply.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: replies:write

Create a reply
curl -X POST 'https://api.tintup.com/v2/teams/{team_id}/replies' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "reply",
      "attributes": {
        "text": "Thank you for the kind review, Jane!",
        "source": "public_post",
        "external_id": "custom_public_1741970527000_4f3a2b1c9d8e",
        "visibility": "active"
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/replies', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "reply",
        "attributes": {
          "text": "Thank you for the kind review, Jane!",
          "source": "public_post",
          "external_id": "custom_public_1741970527000_4f3a2b1c9d8e",
          "visibility": "active"
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "reply",
    "attributes": {
      "text": "Thank you for the kind review, Jane!",
      "source": "public_post",
      "external_id": "custom_public_1741970527000_4f3a2b1c9d8e",
      "visibility": "active"
    }
  }
}

response = requests.post('https://api.tintup.com/v2/teams/{team_id}/replies', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "reply",
    "attributes": {
      "text": "Thank you for the kind review, Jane!",
      "source": "public_post",
      "external_id": "custom_public_1741970527000_4f3a2b1c9d8e",
      "visibility": "active"
    }
  }
}
{
  "data": {
    "id": "88",
    "type": "reply",
    "attributes": {
      "text": "Thank you for the kind review, Jane!",
      "external_id": "custom_public_1741970527000_4f3a2b1c9d8e",
      "visibility": "active",
      "created_at": "2025-03-15T10:12:45.000Z",
      "updated_at": "2025-03-15T10:12:45.000Z"
    },
    "relationships": {
      "user": {
        "data": {
          "type": "user",
          "id": "16891"
        },
        "meta": {
          "included": false
        }
      }
    }
  }
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Delete a reply

DELETE
https://api.tintup.com/v2/teams/{team_id}/replies/{reply_id}

Deletes the reply.

Parameters

team_idintegerrequiredpath

The ID of the team.

reply_idintegerrequiredpath

The ID of the reply.

Response

204No Content

No Content. The request succeeded and there is no response body.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: replies:write

Delete a reply
curl -X DELETE 'https://api.tintup.com/v2/teams/{team_id}/replies/{reply_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/replies/{reply_id}', {
  method: 'DELETE',
});

const data = await response.json();
import requests

response = requests.delete('https://api.tintup.com/v2/teams/{team_id}/replies/{reply_id}')
data = response.json()

Update a reply

PATCH
https://api.tintup.com/v2/teams/{team_id}/replies/{reply_id}

Updates the reply.

Body

application/vnd.api+json

The reply changes.

dataReplyUpdaterequired

The reply changes. Only text and visibility can be changed.

Show child attributes
idstring

The ID of the reply. Optional; the reply is identified by the URL.

typeReplyTypereplyrequired

The resource type. Always reply.

attributesobject
Show child attributes
textReplyText

The text of the reply. Plain text only (HTML isn't allowed), from 1 to 500 characters.

visibilityReplyVisibilityactiveinactive

Whether the reply is shown publicly with the post (active) or only visible to the team (inactive).

Parameters

team_idintegerrequiredpath

The ID of the team.

reply_idintegerrequiredpath

The ID of the reply.

Response

200OKobject

The reply.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: replies:write

Update a reply
curl -X PATCH 'https://api.tintup.com/v2/teams/{team_id}/replies/{reply_id}' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "id": "88",
      "type": "reply",
      "attributes": {
        "visibility": "inactive"
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/replies/{reply_id}', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "id": "88",
        "type": "reply",
        "attributes": {
          "visibility": "inactive"
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "id": "88",
    "type": "reply",
    "attributes": {
      "visibility": "inactive"
    }
  }
}

response = requests.patch('https://api.tintup.com/v2/teams/{team_id}/replies/{reply_id}', json=payload)
data = response.json()
Request Body
{
  "data": {
    "id": "88",
    "type": "reply",
    "attributes": {
      "visibility": "inactive"
    }
  }
}
{
  "data": {
    "id": "88",
    "type": "reply",
    "attributes": {
      "text": "Thank you for the kind review, Jane!",
      "external_id": "custom_public_1741970527000_4f3a2b1c9d8e",
      "visibility": "active",
      "created_at": "2025-03-15T10:12:45.000Z",
      "updated_at": "2025-03-15T10:12:45.000Z"
    },
    "relationships": {
      "user": {
        "data": {
          "type": "user",
          "id": "16891"
        },
        "meta": {
          "included": false
        }
      }
    }
  }
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}
Boards

Saved Filters

saved_filters

Retrieve a list of saved filters

GET
https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/saved_filters

Parameters

team_idintegerrequiredpath

The ID of the team.

tint_idintegerrequiredpath

The ID of the board.

includeArray<string>cta_associationscta_associations.ctatintquery

A comma-separated list of related resources to include in the response.

Response

200OKobject

A list of the board's saved filters. The list isn't paginated.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: saved_filters:read

Retrieve a list of saved filters
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/saved_filters'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/saved_filters', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/saved_filters')
data = response.json()
200
{
  "data": [
    {
      "id": "15",
      "type": "saved_filter",
      "attributes": {
        "name": "Summer favorites",
        "filter": {
          "q": "sneakers",
          "status": [
            "public",
            "recurring"
          ],
          "published_at": {
            "$gte": "2025-06-01T00:00:00.000Z",
            "$lte": "2025-08-31T23:59:59.000Z"
          },
          "type": [
            "instagram_business",
            "tiktok"
          ],
          "social_feed_id": [
            "311",
            "312"
          ],
          "media_type": [
            "image",
            "video"
          ],
          "language": [
            "en",
            "es"
          ],
          "sentiment": [
            "positive"
          ],
          "image_object": [
            "shoe",
            "beach"
          ],
          "tag": [
            "featured"
          ],
          "product_id": [
            "501"
          ],
          "right_request_status": [
            "approved"
          ],
          "right_request_status_expires_at": "+2592000",
          "rating": {
            "$gte": 60,
            "$lte": 100,
            "$range": "80-100"
          },
          "highlighted": true,
          "pinned": false,
          "incentivized": false
        },
        "created_at": "2025-03-14T16:42:07.000Z",
        "updated_at": "2025-03-14T16:42:07.000Z"
      },
      "relationships": {
        "tint": {
          "data": {
            "type": "tint",
            "id": "42"
          },
          "meta": {
            "included": false
          }
        },
        "cta_associations": {
          "data": [
            {
              "type": "cta_association",
              "id": "64"
            }
          ],
          "meta": {
            "included": false
          }
        }
      }
    }
  ]
}

Create a saved filter

POST
https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/saved_filters

Body

application/vnd.api+json

The saved filter to create.

dataNewSavedFilterrequired

The saved filter to create.

Show child attributes
typeSavedFilterTypesaved_filterrequired

The resource type. Always saved_filter.

attributesobjectrequired
Show child attributes
nameSavedFilterNamerequired

The name of the saved filter. It must be unique within the board.

filterSavedFilterCriteriarequired

The post filter criteria, using the same names as the filter query parameter of "Retrieve a list of posts". Lists are arrays (a comma-separated string is also accepted in requests). At least one criterion is required. Criteria that aren't sent are removed.

Show child attributes
qstring

A full-text search on the posts.

statusArray<string>publicrecurringprivateimage_moderation_failedmoderation_deletedimage_moderation_deleteddeletedprivacy_deleted

The moderation statuses to include. Only these combinations are supported (in any order), and any other value is ignored: all visible posts (public, recurring, private, image_moderation_failed), public posts (public, recurring), private posts (private, image_moderation_failed, recurring), and hidden posts (recurring, moderation_deleted, image_moderation_deleted, deleted, privacy_deleted).

published_atobject

The publication time range. Times are stored with a precision of one second.

Show child attributes
$gtestring<date-time>

At or after this time. Must not be after $lte.

$ltestring<date-time>

At or before this time.

typeArray<SocialFeedSource>creator_iqcustomemailexternally_sourced_postsfacebookflickrform_submissiongoogle_newshootsuiteinstagram_businesslinkedinmissionpinterestpublic_postreview_trackersrssslacksmssparkthreadstiktoktiktok_businesstumblrtwitteryoutube

The sources of the posts.

social_feed_idArray<string>

The IDs of the social feeds the posts come from.

media_typeArray<string>textimagevideocarousel

The media types of the posts.

languageArray<string>

The ISO 639-1 codes of the posts' languages.

sentimentArray<string>neutralpositivenegative

The sentiments of the posts' text.

image_objectArray<string>

Objects detected in the posts' images.

tagArray<string>

The tags of the posts.

product_idArray<string>

The IDs of the products tagged in the posts.

right_request_statusArray<string>approveddeclineddeletederrorexpiredmissingpendingrequestedsoft_approvedtoken_error

The statuses of the posts' most recent right request.

right_request_status_expires_atstring

When the status of the most recent right request expires, as a Unix timestamp in seconds, or relative to now in seconds when prefixed with + or -.

ratingobject

The review rating range (0 to 100).

Show child attributes
$gteinteger

At least this rating.

$lteinteger

At most this rating.

$rangestring

A comma-separated list of inclusive from-to ranges.

highlightedboolean

Whether the posts are highlighted.

pinnedboolean

Whether the posts are pinned.

incentivizedboolean

Whether the reviews are incentivized.

Parameters

team_idintegerrequiredpath

The ID of the team.

tint_idintegerrequiredpath

The ID of the board.

includeArray<string>cta_associationscta_associations.ctatintquery

A comma-separated list of related resources to include in the response.

Response

201Createdobject

The saved filter.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: saved_filters:write

Create a saved filter
curl -X POST 'https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/saved_filters' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "saved_filter",
      "attributes": {
        "name": "Summer favorites",
        "filter": {
          "q": "sneakers",
          "status": [
            "public",
            "recurring"
          ],
          "type": [
            "instagram_business",
            "tiktok"
          ],
          "media_type": [
            "image"
          ],
          "published_at": {
            "$gte": "2025-06-01T00:00:00.000Z",
            "$lte": "2025-08-31T23:59:59.000Z"
          }
        }
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/saved_filters', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "saved_filter",
        "attributes": {
          "name": "Summer favorites",
          "filter": {
            "q": "sneakers",
            "status": [
              "public",
              "recurring"
            ],
            "type": [
              "instagram_business",
              "tiktok"
            ],
            "media_type": [
              "image"
            ],
            "published_at": {
              "$gte": "2025-06-01T00:00:00.000Z",
              "$lte": "2025-08-31T23:59:59.000Z"
            }
          }
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "saved_filter",
    "attributes": {
      "name": "Summer favorites",
      "filter": {
        "q": "sneakers",
        "status": [
          "public",
          "recurring"
        ],
        "type": [
          "instagram_business",
          "tiktok"
        ],
        "media_type": [
          "image"
        ],
        "published_at": {
          "$gte": "2025-06-01T00:00:00.000Z",
          "$lte": "2025-08-31T23:59:59.000Z"
        }
      }
    }
  }
}

response = requests.post('https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/saved_filters', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "saved_filter",
    "attributes": {
      "name": "Summer favorites",
      "filter": {
        "q": "sneakers",
        "status": [
          "public",
          "recurring"
        ],
        "type": [
          "instagram_business",
          "tiktok"
        ],
        "media_type": [
          "image"
        ],
        "published_at": {
          "$gte": "2025-06-01T00:00:00.000Z",
          "$lte": "2025-08-31T23:59:59.000Z"
        }
      }
    }
  }
}
{
  "data": {
    "id": "15",
    "type": "saved_filter",
    "attributes": {
      "name": "Summer favorites",
      "filter": {
        "q": "sneakers",
        "status": [
          "public",
          "recurring"
        ],
        "published_at": {
          "$gte": "2025-06-01T00:00:00.000Z",
          "$lte": "2025-08-31T23:59:59.000Z"
        },
        "type": [
          "instagram_business",
          "tiktok"
        ],
        "social_feed_id": [
          "311",
          "312"
        ],
        "media_type": [
          "image",
          "video"
        ],
        "language": [
          "en",
          "es"
        ],
        "sentiment": [
          "positive"
        ],
        "image_object": [
          "shoe",
          "beach"
        ],
        "tag": [
          "featured"
        ],
        "product_id": [
          "501"
        ],
        "right_request_status": [
          "approved"
        ],
        "right_request_status_expires_at": "+2592000",
        "rating": {
          "$gte": 60,
          "$lte": 100,
          "$range": "80-100"
        },
        "highlighted": true,
        "pinned": false,
        "incentivized": false
      },
      "created_at": "2025-03-14T16:42:07.000Z",
      "updated_at": "2025-03-14T16:42:07.000Z"
    },
    "relationships": {
      "tint": {
        "data": {
          "type": "tint",
          "id": "42"
        },
        "meta": {
          "included": false
        }
      },
      "cta_associations": {
        "data": [
          {
            "type": "cta_association",
            "id": "64"
          }
        ],
        "meta": {
          "included": false
        }
      }
    }
  }
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Retrieve a saved filter

GET
https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/saved_filters/{saved_filter_id}

Parameters

team_idintegerrequiredpath

The ID of the team.

tint_idintegerrequiredpath

The ID of the board.

saved_filter_idintegerrequiredpath

The ID of the saved filter.

includeArray<string>cta_associationscta_associations.ctatintquery

A comma-separated list of related resources to include in the response.

Response

200OKobject

The saved filter.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: saved_filters:read

Retrieve a saved filter
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/saved_filters/{saved_filter_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/saved_filters/{saved_filter_id}', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/saved_filters/{saved_filter_id}')
data = response.json()
200
{
  "data": {
    "id": "15",
    "type": "saved_filter",
    "attributes": {
      "name": "Summer favorites",
      "filter": {
        "q": "sneakers",
        "status": [
          "public",
          "recurring"
        ],
        "published_at": {
          "$gte": "2025-06-01T00:00:00.000Z",
          "$lte": "2025-08-31T23:59:59.000Z"
        },
        "type": [
          "instagram_business",
          "tiktok"
        ],
        "social_feed_id": [
          "311",
          "312"
        ],
        "media_type": [
          "image",
          "video"
        ],
        "language": [
          "en",
          "es"
        ],
        "sentiment": [
          "positive"
        ],
        "image_object": [
          "shoe",
          "beach"
        ],
        "tag": [
          "featured"
        ],
        "product_id": [
          "501"
        ],
        "right_request_status": [
          "approved"
        ],
        "right_request_status_expires_at": "+2592000",
        "rating": {
          "$gte": 60,
          "$lte": 100,
          "$range": "80-100"
        },
        "highlighted": true,
        "pinned": false,
        "incentivized": false
      },
      "created_at": "2025-03-14T16:42:07.000Z",
      "updated_at": "2025-03-14T16:42:07.000Z"
    },
    "relationships": {
      "tint": {
        "data": {
          "type": "tint",
          "id": "42"
        },
        "meta": {
          "included": false
        }
      },
      "cta_associations": {
        "data": [
          {
            "type": "cta_association",
            "id": "64"
          }
        ],
        "meta": {
          "included": false
        }
      }
    }
  }
}

Delete a saved filter

DELETE
https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/saved_filters/{saved_filter_id}

Parameters

team_idintegerrequiredpath

The ID of the team.

tint_idintegerrequiredpath

The ID of the board.

saved_filter_idintegerrequiredpath

The ID of the saved filter.

Response

204No Content

No Content. The request succeeded and there is no response body.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: saved_filters:write

Delete a saved filter
curl -X DELETE 'https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/saved_filters/{saved_filter_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/saved_filters/{saved_filter_id}', {
  method: 'DELETE',
});

const data = await response.json();
import requests

response = requests.delete('https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/saved_filters/{saved_filter_id}')
data = response.json()

Update a saved filter

PATCH
https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/saved_filters/{saved_filter_id}

Body

application/vnd.api+json

The saved filter changes.

dataSavedFilterUpdaterequired

The saved filter changes. The id is optional; the saved filter is identified by the URL. The filter is always replaced: send the complete criteria, as the update fails if filter is missing or empty.

Show child attributes
idstring

The ID of the saved filter.

typeSavedFilterTypesaved_filterrequired

The resource type. Always saved_filter.

attributesobjectrequired
Show child attributes
nameSavedFilterName

The name of the saved filter. It must be unique within the board.

filterSavedFilterCriteriarequired

The post filter criteria, using the same names as the filter query parameter of "Retrieve a list of posts". Lists are arrays (a comma-separated string is also accepted in requests). At least one criterion is required. Criteria that aren't sent are removed.

Show child attributes
qstring

A full-text search on the posts.

statusArray<string>publicrecurringprivateimage_moderation_failedmoderation_deletedimage_moderation_deleteddeletedprivacy_deleted

The moderation statuses to include. Only these combinations are supported (in any order), and any other value is ignored: all visible posts (public, recurring, private, image_moderation_failed), public posts (public, recurring), private posts (private, image_moderation_failed, recurring), and hidden posts (recurring, moderation_deleted, image_moderation_deleted, deleted, privacy_deleted).

published_atobject

The publication time range. Times are stored with a precision of one second.

Show child attributes
$gtestring<date-time>

At or after this time. Must not be after $lte.

$ltestring<date-time>

At or before this time.

typeArray<SocialFeedSource>creator_iqcustomemailexternally_sourced_postsfacebookflickrform_submissiongoogle_newshootsuiteinstagram_businesslinkedinmissionpinterestpublic_postreview_trackersrssslacksmssparkthreadstiktoktiktok_businesstumblrtwitteryoutube

The sources of the posts.

social_feed_idArray<string>

The IDs of the social feeds the posts come from.

media_typeArray<string>textimagevideocarousel

The media types of the posts.

languageArray<string>

The ISO 639-1 codes of the posts' languages.

sentimentArray<string>neutralpositivenegative

The sentiments of the posts' text.

image_objectArray<string>

Objects detected in the posts' images.

tagArray<string>

The tags of the posts.

product_idArray<string>

The IDs of the products tagged in the posts.

right_request_statusArray<string>approveddeclineddeletederrorexpiredmissingpendingrequestedsoft_approvedtoken_error

The statuses of the posts' most recent right request.

right_request_status_expires_atstring

When the status of the most recent right request expires, as a Unix timestamp in seconds, or relative to now in seconds when prefixed with + or -.

ratingobject

The review rating range (0 to 100).

Show child attributes
$gteinteger

At least this rating.

$lteinteger

At most this rating.

$rangestring

A comma-separated list of inclusive from-to ranges.

highlightedboolean

Whether the posts are highlighted.

pinnedboolean

Whether the posts are pinned.

incentivizedboolean

Whether the reviews are incentivized.

Parameters

team_idintegerrequiredpath

The ID of the team.

tint_idintegerrequiredpath

The ID of the board.

saved_filter_idintegerrequiredpath

The ID of the saved filter.

Response

200OKobject

The saved filter.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: saved_filters:write

Update a saved filter
curl -X PATCH 'https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/saved_filters/{saved_filter_id}' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "id": "15",
      "type": "saved_filter",
      "attributes": {
        "name": "Summer favorites (images)",
        "filter": {
          "q": "sneakers",
          "media_type": [
            "image"
          ]
        }
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/saved_filters/{saved_filter_id}', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "id": "15",
        "type": "saved_filter",
        "attributes": {
          "name": "Summer favorites (images)",
          "filter": {
            "q": "sneakers",
            "media_type": [
              "image"
            ]
          }
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "id": "15",
    "type": "saved_filter",
    "attributes": {
      "name": "Summer favorites (images)",
      "filter": {
        "q": "sneakers",
        "media_type": [
          "image"
        ]
      }
    }
  }
}

response = requests.patch('https://api.tintup.com/v2/teams/{team_id}/tints/{tint_id}/saved_filters/{saved_filter_id}', json=payload)
data = response.json()
Request Body
{
  "data": {
    "id": "15",
    "type": "saved_filter",
    "attributes": {
      "name": "Summer favorites (images)",
      "filter": {
        "q": "sneakers",
        "media_type": [
          "image"
        ]
      }
    }
  }
}
{
  "data": {
    "id": "15",
    "type": "saved_filter",
    "attributes": {
      "name": "Summer favorites",
      "filter": {
        "q": "sneakers",
        "status": [
          "public",
          "recurring"
        ],
        "published_at": {
          "$gte": "2025-06-01T00:00:00.000Z",
          "$lte": "2025-08-31T23:59:59.000Z"
        },
        "type": [
          "instagram_business",
          "tiktok"
        ],
        "social_feed_id": [
          "311",
          "312"
        ],
        "media_type": [
          "image",
          "video"
        ],
        "language": [
          "en",
          "es"
        ],
        "sentiment": [
          "positive"
        ],
        "image_object": [
          "shoe",
          "beach"
        ],
        "tag": [
          "featured"
        ],
        "product_id": [
          "501"
        ],
        "right_request_status": [
          "approved"
        ],
        "right_request_status_expires_at": "+2592000",
        "rating": {
          "$gte": 60,
          "$lte": 100,
          "$range": "80-100"
        },
        "highlighted": true,
        "pinned": false,
        "incentivized": false
      },
      "created_at": "2025-03-14T16:42:07.000Z",
      "updated_at": "2025-03-14T16:42:07.000Z"
    },
    "relationships": {
      "tint": {
        "data": {
          "type": "tint",
          "id": "42"
        },
        "meta": {
          "included": false
        }
      },
      "cta_associations": {
        "data": [
          {
            "type": "cta_association",
            "id": "64"
          }
        ],
        "meta": {
          "included": false
        }
      }
    }
  }
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}
Boards

Social Feeds

social_feeds

Retrieve a list of social feeds

GET
https://api.tintup.com/v2/teams/{team_id}/social_feeds

Returns the social feeds of the boards you have access to.

Parameters

team_idintegerrequiredpath

The ID of the team.

filterobjectquery

Filters the social feeds.

includeArray<string>accountformright_request_termtintquery

A comma-separated list of related resources to include in the response.

pageobjectquery

Offset pagination. Use page[size] to set the number of items per page and page[number] to select a page. The response's links object contains ready-to-use URLs for the next and previous pages.

Response

200OKobject

A list of social feeds.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: social_feeds:read

Retrieve a list of social feeds
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/social_feeds'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/social_feeds', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/social_feeds')
data = response.json()
200
{
  "data": [
    {
      "id": "311",
      "type": "social_feed",
      "attributes": {
        "name": "#acmesummer",
        "source": "instagram_business",
        "moderated": true,
        "external_id": "17841400008460056",
        "options": {
          "email": true,
          "custom_field": false,
          "author_name": true,
          "media_url": false,
          "multiple_files": false,
          "terms": "https://example.com/terms"
        },
        "pre_processing_rules": [],
        "created_at": "2025-01-06T09:20:00.000Z",
        "updated_at": "2025-03-14T16:42:07.000Z"
      },
      "relationships": {
        "tint": {
          "data": {
            "type": "tint",
            "id": "42"
          },
          "links": {
            "self": "https://api.tintup.com/v2/teams/1/tints/42"
          },
          "meta": {
            "included": false
          }
        },
        "account": {
          "data": {
            "type": "account",
            "id": "77"
          },
          "meta": {
            "included": false
          }
        },
        "form": {
          "data": {
            "type": "form",
            "id": "19"
          },
          "meta": {
            "included": false
          }
        },
        "right_request_term": {
          "data": {
            "type": "right_request_term",
            "id": "5"
          },
          "meta": {
            "included": false
          }
        }
      }
    }
  ],
  "links": {
    "self": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=2",
    "first": "https://api.tintup.com/v2/teams/1/tints",
    "next": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=3",
    "prev": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=1"
  }
}

Create a social feed

POST
https://api.tintup.com/v2/teams/{team_id}/social_feeds

Fails with 402 when the team has reached its plan's limit of active social feeds. For influencer social feeds, an authorization request is emailed to the contact.

Body

application/vnd.api+json

The social feed to create.

dataNewSocialFeedrequired

The social feed to create. Which attributes are required depends on the source and type: accounts-based sources (facebook, instagram_business, twitter, threads, youtube, flickr, tumblr, tiktok, tiktok_business, hootsuite, slack, pinterest, creator_iq) require account_id (except when type is influencer), and other sources reject it; instagram_business, hootsuite, pinterest, creator_iq, slack, spark, form_submission and mission require external_id (the ID of the account's business account, board, channel, campaign, form, experience or mission); rss requires external_id (the feed URL); instagram_business with type hashtags requires search_term starting with #, and with social_listening a business username; twitter requires search_term (a hashtag starting with # when type is hashtag), except for influencer feeds, which require external_id; threads with type keyword, flickr with hashtag or user, google_news, slack and spark require search_term; influencer feeds require contact and right_request_term_id. A board can only have one social feed per source and identifier.

Show child attributes
typeSocialFeedTypesocial_feedrequired

The resource type. Always social_feed.

attributesobjectrequired
Show child attributes
sourceSocialFeedSourcerequired

The source to ingest posts from. linkedin is no longer supported.

tint_idintegerrequired

The ID of the board the social feed adds posts to. You must have access to the board.

typeSocialFeedKind | null

The kind of social feed (stored as its account type). The valid values depend on the source: facebook: account, page, others, hashtag, groups, tagged, ratings, influencer; instagram_business: mentioned, posted, tagged, hashtags, stories, comments, influencer, social_listening; twitter: username, hashtag, list, favorites, geocode, influencer; threads: posted, keyword, mentioned, influencer; youtube: channel, playlist, posted, keyword; flickr: user, hashtag, posted; tumblr: account, hashtag; tiktok: account; tiktok_business: account, mentioned; hootsuite: account, scheduled_posts; linkedin: person, company, tagged, mentioned; google_news: keyword, location, topic; public_post: post, reviews; form_submission: form, experience; creator_iq: campaign. Other sources don't have kinds.

namestring | null

A label that identifies the social feed. Defaults to a name derived from the source.

account_idinteger | null

The ID of the connected account used to ingest posts. It must be one of your accounts.

external_idstring | null

The ID of the feed at the source, or the feed URL for rss.

search_termstring | null

The hashtag, keyword, username or channel to ingest, depending on the source and type.

moderatedbooleantrue

Whether posts must be moderated before they're displayed.

optionsSocialFeedOptionsForRequest

Source-specific options. public_post: email, custom_field, author_name, media_url (booleans: whether the field is shown or required), multiple_files (boolean), terms (URL), email_template_id (the ID of an email template of type review_reply, as a string), and, for feeds linked to a form, the field mapping keys (author.name, author.email, author.avatar, media, text, alternative_text, rating, title, tags, incentivized). review_trackers (create only): name, address, city and country (required), state and zip. google_news: lang. form_submission: author_image_url_key, author_name_field, author_username_key, post_body_field, post_media_url_key, post_tags_key, post_title_key. mission: activity_item_types (array of strings). options is required when creating public_post, review_trackers, google_news, form_submission and mission social feeds.

pre_processing_rulesArray<PreProcessingRule>

The pre-processing rules that determine which content is ingested.

Show child attributes
conditionsobjectrequired

The conditions content must match. All conditions of a rule must match.

Show child attributes
textstring

Text the content must contain.

published_atobject

The publication time range of the content.

Show child attributes
$gtestring<date-time>

At or after this time.

$ltstring<date-time>

Before this time.

form_idinteger | null

The ID of a form to link to a public_post social feed. It must be one of your forms.

right_request_term_idinteger | null

The ID of the right request terms sent to the influencer. Required when type is influencer; must not be sent otherwise.

contactobject | null

The influencer to send the authorization request to. Required when type is influencer; must not be sent otherwise.

Show child attributes
emailstring<email>required

The influencer's email address.

Parameters

team_idintegerrequiredpath

The ID of the team.

includeArray<string>accountformright_request_termtintquery

A comma-separated list of related resources to include in the response.

Response

200OKobject

The social feed.

402Payment Requiredx-errors

Payment Required. The team already has as many active social feeds as its plan allows.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: social_feeds:write

Create a social feed
curl -X POST 'https://api.tintup.com/v2/teams/{team_id}/social_feeds' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "social_feed",
      "attributes": {
        "source": "instagram_business",
        "type": "hashtags",
        "tint_id": 42,
        "account_id": 77,
        "external_id": "17841400008460056",
        "search_term": "#acmesummer",
        "moderated": true
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/social_feeds', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "social_feed",
        "attributes": {
          "source": "instagram_business",
          "type": "hashtags",
          "tint_id": 42,
          "account_id": 77,
          "external_id": "17841400008460056",
          "search_term": "#acmesummer",
          "moderated": true
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "social_feed",
    "attributes": {
      "source": "instagram_business",
      "type": "hashtags",
      "tint_id": 42,
      "account_id": 77,
      "external_id": "17841400008460056",
      "search_term": "#acmesummer",
      "moderated": True
    }
  }
}

response = requests.post('https://api.tintup.com/v2/teams/{team_id}/social_feeds', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "social_feed",
    "attributes": {
      "source": "instagram_business",
      "type": "hashtags",
      "tint_id": 42,
      "account_id": 77,
      "external_id": "17841400008460056",
      "search_term": "#acmesummer",
      "moderated": true
    }
  }
}
{
  "data": {
    "id": "311",
    "type": "social_feed",
    "attributes": {
      "name": "#acmesummer",
      "source": "instagram_business",
      "moderated": true,
      "external_id": "17841400008460056",
      "options": {
        "email": true,
        "custom_field": false,
        "author_name": true,
        "media_url": false,
        "multiple_files": false,
        "terms": "https://example.com/terms"
      },
      "pre_processing_rules": [],
      "created_at": "2025-01-06T09:20:00.000Z",
      "updated_at": "2025-03-14T16:42:07.000Z"
    },
    "relationships": {
      "tint": {
        "data": {
          "type": "tint",
          "id": "42"
        },
        "links": {
          "self": "https://api.tintup.com/v2/teams/1/tints/42"
        },
        "meta": {
          "included": false
        }
      },
      "account": {
        "data": {
          "type": "account",
          "id": "77"
        },
        "meta": {
          "included": false
        }
      },
      "form": {
        "data": {
          "type": "form",
          "id": "19"
        },
        "meta": {
          "included": false
        }
      },
      "right_request_term": {
        "data": {
          "type": "right_request_term",
          "id": "5"
        },
        "meta": {
          "included": false
        }
      }
    }
  }
}
{
  "errors": [
    {
      "code": "4020001",
      "title": "Payment Required",
      "detail": "You have exceeded your plan's limit of 10",
      "status": "402"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Update multiple social feeds

PATCH
https://api.tintup.com/v2/teams/{team_id}/social_feeds

The request is validated as a whole: if any social feed is invalid, none are updated.

Body

application/vnd.api+json; ext=bulk

The social feeds to update, each identified by its id.

dataArray<SocialFeedBulkUpdate>required
Show child attributes
idstringrequired

The ID of the social feed.

typeSocialFeedTypesocial_feedrequired

The resource type. Always social_feed.

attributesSocialFeedWritableAttributes

Attributes that can be changed on an existing social feed. Only the attributes sent are changed.

Show child attributes
namestring | null

A label that identifies the social feed.

statusstringactiveinactive

Activates or deactivates the social feed. The status of a token_requested social feed can't be changed.

moderatedboolean

Whether posts must be moderated before they're displayed.

account_idinteger | null

The ID of the connected account used to ingest posts, which must be one of your accounts of the same source. Required (can't be removed) for account-based sources; can't be changed for influencer feeds; must be null for other sources.

optionsSocialFeedOptionsForRequest

Source-specific options. public_post: email, custom_field, author_name, media_url (booleans: whether the field is shown or required), multiple_files (boolean), terms (URL), email_template_id (the ID of an email template of type review_reply, as a string), and, for feeds linked to a form, the field mapping keys (author.name, author.email, author.avatar, media, text, alternative_text, rating, title, tags, incentivized). review_trackers (create only): name, address, city and country (required), state and zip. google_news: lang. form_submission: author_image_url_key, author_name_field, author_username_key, post_body_field, post_media_url_key, post_tags_key, post_title_key. mission: activity_item_types (array of strings). options is required when creating public_post, review_trackers, google_news, form_submission and mission social feeds.

pre_processing_rulesArray<PreProcessingRule>

The pre-processing rules that determine which content is ingested. Replaces all existing rules.

Show child attributes
conditionsobjectrequired

The conditions content must match. All conditions of a rule must match.

Show child attributes
textstring

Text the content must contain.

published_atobject

The publication time range of the content.

Show child attributes
$gtestring<date-time>

At or after this time.

$ltstring<date-time>

Before this time.

form_idinteger | null

The ID of a form linked to a public_post social feed; must be one of your forms. Must not be sent for other sources.

Parameters

team_idintegerrequiredpath

The ID of the team.

Response

200OKobject

The updated social feeds.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: social_feeds:write

Update multiple social feeds
curl -X PATCH 'https://api.tintup.com/v2/teams/{team_id}/social_feeds' \
  -H 'Content-Type: application/vnd.api+json; ext=bulk' \
  -d '{
    "data": [
      {
        "id": "311",
        "type": "social_feed",
        "attributes": {
          "status": "inactive"
        }
      },
      {
        "id": "312",
        "type": "social_feed",
        "attributes": {
          "status": "inactive"
        }
      }
    ]
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/social_feeds', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/vnd.api+json; ext=bulk',
  },
  body: JSON.stringify({
      "data": [
        {
          "id": "311",
          "type": "social_feed",
          "attributes": {
            "status": "inactive"
          }
        },
        {
          "id": "312",
          "type": "social_feed",
          "attributes": {
            "status": "inactive"
          }
        }
      ]
    }),
});

const data = await response.json();
import requests

payload = {
  "data": [
    {
      "id": "311",
      "type": "social_feed",
      "attributes": {
        "status": "inactive"
      }
    },
    {
      "id": "312",
      "type": "social_feed",
      "attributes": {
        "status": "inactive"
      }
    }
  ]
}

response = requests.patch('https://api.tintup.com/v2/teams/{team_id}/social_feeds', json=payload)
data = response.json()
Request Body
{
  "data": [
    {
      "id": "311",
      "type": "social_feed",
      "attributes": {
        "status": "inactive"
      }
    },
    {
      "id": "312",
      "type": "social_feed",
      "attributes": {
        "status": "inactive"
      }
    }
  ]
}
{
  "data": [
    {
      "id": "311",
      "type": "social_feed",
      "attributes": {
        "name": "#acmesummer",
        "source": "instagram_business",
        "moderated": true,
        "external_id": "17841400008460056",
        "options": {
          "email": true,
          "custom_field": false,
          "author_name": true,
          "media_url": false,
          "multiple_files": false,
          "terms": "https://example.com/terms"
        },
        "pre_processing_rules": [],
        "created_at": "2025-01-06T09:20:00.000Z",
        "updated_at": "2025-03-14T16:42:07.000Z"
      },
      "relationships": {
        "tint": {
          "data": {
            "type": "tint",
            "id": "42"
          },
          "links": {
            "self": "https://api.tintup.com/v2/teams/1/tints/42"
          },
          "meta": {
            "included": false
          }
        },
        "account": {
          "data": {
            "type": "account",
            "id": "77"
          },
          "meta": {
            "included": false
          }
        },
        "form": {
          "data": {
            "type": "form",
            "id": "19"
          },
          "meta": {
            "included": false
          }
        },
        "right_request_term": {
          "data": {
            "type": "right_request_term",
            "id": "5"
          },
          "meta": {
            "included": false
          }
        }
      }
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Retrieve a social feed

GET
https://api.tintup.com/v2/teams/{team_id}/social_feeds/{social_feed_id}

Parameters

team_idintegerrequiredpath

The ID of the team.

social_feed_idintegerrequiredpath

The ID of the social feed.

includeArray<string>accountformright_request_termtintquery

A comma-separated list of related resources to include in the response.

Response

200OKobject

The social feed.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: social_feeds:read

Retrieve a social feed
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/social_feeds/{social_feed_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/social_feeds/{social_feed_id}', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/social_feeds/{social_feed_id}')
data = response.json()
200
{
  "data": {
    "id": "311",
    "type": "social_feed",
    "attributes": {
      "name": "#acmesummer",
      "source": "instagram_business",
      "moderated": true,
      "external_id": "17841400008460056",
      "options": {
        "email": true,
        "custom_field": false,
        "author_name": true,
        "media_url": false,
        "multiple_files": false,
        "terms": "https://example.com/terms"
      },
      "pre_processing_rules": [],
      "created_at": "2025-01-06T09:20:00.000Z",
      "updated_at": "2025-03-14T16:42:07.000Z"
    },
    "relationships": {
      "tint": {
        "data": {
          "type": "tint",
          "id": "42"
        },
        "links": {
          "self": "https://api.tintup.com/v2/teams/1/tints/42"
        },
        "meta": {
          "included": false
        }
      },
      "account": {
        "data": {
          "type": "account",
          "id": "77"
        },
        "meta": {
          "included": false
        }
      },
      "form": {
        "data": {
          "type": "form",
          "id": "19"
        },
        "meta": {
          "included": false
        }
      },
      "right_request_term": {
        "data": {
          "type": "right_request_term",
          "id": "5"
        },
        "meta": {
          "included": false
        }
      }
    }
  }
}

Delete a social feed

DELETE
https://api.tintup.com/v2/teams/{team_id}/social_feeds/{social_feed_id}

Deletes the social feed and the posts it ingested.

Parameters

team_idintegerrequiredpath

The ID of the team.

social_feed_idintegerrequiredpath

The ID of the social feed.

Response

204No Content

No Content. The request succeeded and there is no response body.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: social_feeds:write

Delete a social feed
curl -X DELETE 'https://api.tintup.com/v2/teams/{team_id}/social_feeds/{social_feed_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/social_feeds/{social_feed_id}', {
  method: 'DELETE',
});

const data = await response.json();
import requests

response = requests.delete('https://api.tintup.com/v2/teams/{team_id}/social_feeds/{social_feed_id}')
data = response.json()

Update a social feed

PATCH
https://api.tintup.com/v2/teams/{team_id}/social_feeds/{social_feed_id}

Updates the social feed.

Body

application/vnd.api+json

The social feed changes.

dataSocialFeedUpdaterequired

The social feed changes. The id is optional; the social feed is identified by the URL.

Show child attributes
idstring

The ID of the social feed.

typeSocialFeedTypesocial_feedrequired

The resource type. Always social_feed.

attributesSocialFeedWritableAttributes

Attributes that can be changed on an existing social feed. Only the attributes sent are changed.

Show child attributes
namestring | null

A label that identifies the social feed.

statusstringactiveinactive

Activates or deactivates the social feed. The status of a token_requested social feed can't be changed.

moderatedboolean

Whether posts must be moderated before they're displayed.

account_idinteger | null

The ID of the connected account used to ingest posts, which must be one of your accounts of the same source. Required (can't be removed) for account-based sources; can't be changed for influencer feeds; must be null for other sources.

optionsSocialFeedOptionsForRequest

Source-specific options. public_post: email, custom_field, author_name, media_url (booleans: whether the field is shown or required), multiple_files (boolean), terms (URL), email_template_id (the ID of an email template of type review_reply, as a string), and, for feeds linked to a form, the field mapping keys (author.name, author.email, author.avatar, media, text, alternative_text, rating, title, tags, incentivized). review_trackers (create only): name, address, city and country (required), state and zip. google_news: lang. form_submission: author_image_url_key, author_name_field, author_username_key, post_body_field, post_media_url_key, post_tags_key, post_title_key. mission: activity_item_types (array of strings). options is required when creating public_post, review_trackers, google_news, form_submission and mission social feeds.

pre_processing_rulesArray<PreProcessingRule>

The pre-processing rules that determine which content is ingested. Replaces all existing rules.

Show child attributes
conditionsobjectrequired

The conditions content must match. All conditions of a rule must match.

Show child attributes
textstring

Text the content must contain.

published_atobject

The publication time range of the content.

Show child attributes
$gtestring<date-time>

At or after this time.

$ltstring<date-time>

Before this time.

form_idinteger | null

The ID of a form linked to a public_post social feed; must be one of your forms. Must not be sent for other sources.

Parameters

team_idintegerrequiredpath

The ID of the team.

social_feed_idintegerrequiredpath

The ID of the social feed.

includeArray<string>accountformright_request_termtintquery

A comma-separated list of related resources to include in the response.

Response

200OKobject

The social feed.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: social_feeds:write

Update a social feed
curl -X PATCH 'https://api.tintup.com/v2/teams/{team_id}/social_feeds/{social_feed_id}' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "id": "311",
      "type": "social_feed",
      "attributes": {
        "name": "Summer hashtag",
        "moderated": false
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/social_feeds/{social_feed_id}', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "id": "311",
        "type": "social_feed",
        "attributes": {
          "name": "Summer hashtag",
          "moderated": false
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "id": "311",
    "type": "social_feed",
    "attributes": {
      "name": "Summer hashtag",
      "moderated": False
    }
  }
}

response = requests.patch('https://api.tintup.com/v2/teams/{team_id}/social_feeds/{social_feed_id}', json=payload)
data = response.json()
Request Body
{
  "data": {
    "id": "311",
    "type": "social_feed",
    "attributes": {
      "name": "Summer hashtag",
      "moderated": false
    }
  }
}
{
  "data": {
    "id": "311",
    "type": "social_feed",
    "attributes": {
      "name": "#acmesummer",
      "source": "instagram_business",
      "moderated": true,
      "external_id": "17841400008460056",
      "options": {
        "email": true,
        "custom_field": false,
        "author_name": true,
        "media_url": false,
        "multiple_files": false,
        "terms": "https://example.com/terms"
      },
      "pre_processing_rules": [],
      "created_at": "2025-01-06T09:20:00.000Z",
      "updated_at": "2025-03-14T16:42:07.000Z"
    },
    "relationships": {
      "tint": {
        "data": {
          "type": "tint",
          "id": "42"
        },
        "links": {
          "self": "https://api.tintup.com/v2/teams/1/tints/42"
        },
        "meta": {
          "included": false
        }
      },
      "account": {
        "data": {
          "type": "account",
          "id": "77"
        },
        "meta": {
          "included": false
        }
      },
      "form": {
        "data": {
          "type": "form",
          "id": "19"
        },
        "meta": {
          "included": false
        }
      },
      "right_request_term": {
        "data": {
          "type": "right_request_term",
          "id": "5"
        },
        "meta": {
          "included": false
        }
      }
    }
  }
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Retrieve aggregated ingestion metrics for a social feed

deprecated
GET
https://api.tintup.com/v2/teams/{team_id}/social_feeds/{social_feed_id}/metrics

This endpoint is deprecated. Use GET /v2/teams/{team_id}/posts/metrics/ingested?filter[social_feed_id]={social_feed_id} instead.

Parameters

team_idintegerrequiredpath

The ID of the team.

social_feed_idintegerrequiredpath

The ID of the social feed.

groupstringcreated_at.hourcreated_at.daycreated_at.weekcreated_at.monthcreated_at.quartercreated_at.yearcreated_at.millenniumcreated_at.millenniumquery

The period to group the metrics by. created_at.millennium returns a single total.

filterobjectquery

Filters the periods that are counted.

pageobjectquery

Offset pagination. Use page[size] to set the number of items per page and page[number] to select a page. The response's links object contains ready-to-use URLs for the next and previous pages.

Response

200OKobject

A list of social feed metrics.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Retrieve aggregated ingestion metrics for a social feed
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/social_feeds/{social_feed_id}/metrics'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/social_feeds/{social_feed_id}/metrics', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/social_feeds/{social_feed_id}/metrics')
data = response.json()
200
{
  "data": [
    {
      "id": "1741910400000",
      "type": "social_feed_metric",
      "attributes": {
        "created_at": "2025-03-14T00:00:00.000Z",
        "count": 128
      }
    }
  ],
  "links": {
    "self": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=2",
    "first": "https://api.tintup.com/v2/teams/1/tints",
    "next": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=3",
    "prev": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=1"
  }
}

TINTmix

group_tintmix
TINTmix

Mixes

mixes

Retrieve a public mix

GET
https://api.tintup.com/v2/mixes/{mix_id}

This endpoint is public and doesn't require an access token.

Parameters

mix_idintegerrequiredpath

The ID of the mix.

Response

200OKobject

The mix. Without an access token, the public representation is returned; with one, the full representation is returned.

Retrieve a public mix
curl -X GET 'https://api.tintup.com/v2/mixes/{mix_id}'
const response = await fetch('https://api.tintup.com/v2/mixes/{mix_id}', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/mixes/{mix_id}')
data = response.json()
200
{
  "data": {
    "id": "12",
    "type": "mix",
    "attributes": {
      "scenes": [
        {
          "layout": "horizontal",
          "template": "\"logo feed\"",
          "areas": {
            "logo": [
              {
                "type": "image",
                "duration": 10,
                "name": "Acme logo",
                "url": "https://cdn.example.com/mixes/acme-logo.png"
              }
            ],
            "feed": [
              {
                "type": "tint",
                "duration": 30,
                "name": "Summer campaign board",
                "tint_id": 42,
                "personalization_id": 7
              }
            ]
          }
        }
      ]
    }
  }
}

Retrieve a list of mixes

GET
https://api.tintup.com/v2/teams/{team_id}/mixes

Returns the mixes you have access to.

Parameters

team_idintegerrequiredpath

The ID of the team.

filterobjectquery

Filters the mixes.

pageobjectquery

Offset pagination. Use page[size] to set the number of items per page and page[number] to select a page. The response's links object contains ready-to-use URLs for the next and previous pages.

Response

200OKobject

A list of mixes.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: mixes:read

Retrieve a list of mixes
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/mixes'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/mixes', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/mixes')
data = response.json()
200
{
  "data": [
    {
      "id": "12",
      "type": "mix",
      "attributes": {
        "name": "Lobby screen",
        "scenes": [
          {
            "layout": "horizontal",
            "template": "\"logo feed\"",
            "areas": {
              "logo": [
                {
                  "type": "image",
                  "duration": 10,
                  "name": "Acme logo",
                  "url": "https://cdn.example.com/mixes/acme-logo.png"
                }
              ],
              "feed": [
                {
                  "type": "tint",
                  "duration": 30,
                  "name": "Summer campaign board",
                  "tint_id": 42,
                  "personalization_id": 7
                }
              ]
            }
          }
        ],
        "created_at": "2025-02-10T15:00:00.000Z",
        "updated_at": "2025-03-14T16:42:07.000Z"
      }
    }
  ],
  "links": {
    "self": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=2",
    "first": "https://api.tintup.com/v2/teams/1/tints",
    "next": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=3",
    "prev": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=1"
  }
}

Create a mix

POST
https://api.tintup.com/v2/teams/{team_id}/mixes

Fails with 402 when the team has reached its plan's mix limit.

Body

application/vnd.api+json

The mix to create.

dataNewMixrequired

The mix to create.

Show child attributes
typeMixTypemixrequired

The resource type. Always mix.

attributesobjectrequired
Show child attributes
nameMixNamerequired

The name of the mix.

scenesArray<MixScene>required

The scenes of the mix, played in order. At least one scene is required.

Show child attributes
layoutstringfullscreenhorizontalverticalhero_top_righthero_top_lefthero_bottom_righthero_bottom_left

The name of the layout the template was built from, used by the editor.

templatestringrequired

The layout of the areas, using the same syntax as the CSS grid-template property, except that area names can't be .. The area names must be quoted.

areasobjectrequired

The items to display in each area, keyed by area name. Every area named in template must be defined, and no other areas are allowed.

Parameters

team_idintegerrequiredpath

The ID of the team.

Response

201Createdobject

The mix.

402Payment Requiredx-errors

Payment Required. The team already has as many mixes as its plan allows.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: mixes:write

Create a mix
curl -X POST 'https://api.tintup.com/v2/teams/{team_id}/mixes' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "mix",
      "attributes": {
        "name": "Lobby screen",
        "scenes": [
          {
            "layout": "horizontal",
            "template": "\"logo feed\"",
            "areas": {
              "logo": [
                {
                  "type": "image",
                  "duration": 10,
                  "name": "Acme logo",
                  "url": "https://cdn.example.com/mixes/acme-logo.png"
                }
              ],
              "feed": [
                {
                  "type": "tint",
                  "duration": 30,
                  "name": "Summer campaign board",
                  "tint_id": 42,
                  "personalization_id": 7
                }
              ]
            }
          }
        ]
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/mixes', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "mix",
        "attributes": {
          "name": "Lobby screen",
          "scenes": [
            {
              "layout": "horizontal",
              "template": "\"logo feed\"",
              "areas": {
                "logo": [
                  {
                    "type": "image",
                    "duration": 10,
                    "name": "Acme logo",
                    "url": "https://cdn.example.com/mixes/acme-logo.png"
                  }
                ],
                "feed": [
                  {
                    "type": "tint",
                    "duration": 30,
                    "name": "Summer campaign board",
                    "tint_id": 42,
                    "personalization_id": 7
                  }
                ]
              }
            }
          ]
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "mix",
    "attributes": {
      "name": "Lobby screen",
      "scenes": [
        {
          "layout": "horizontal",
          "template": "\"logo feed\"",
          "areas": {
            "logo": [
              {
                "type": "image",
                "duration": 10,
                "name": "Acme logo",
                "url": "https://cdn.example.com/mixes/acme-logo.png"
              }
            ],
            "feed": [
              {
                "type": "tint",
                "duration": 30,
                "name": "Summer campaign board",
                "tint_id": 42,
                "personalization_id": 7
              }
            ]
          }
        }
      ]
    }
  }
}

response = requests.post('https://api.tintup.com/v2/teams/{team_id}/mixes', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "mix",
    "attributes": {
      "name": "Lobby screen",
      "scenes": [
        {
          "layout": "horizontal",
          "template": "\"logo feed\"",
          "areas": {
            "logo": [
              {
                "type": "image",
                "duration": 10,
                "name": "Acme logo",
                "url": "https://cdn.example.com/mixes/acme-logo.png"
              }
            ],
            "feed": [
              {
                "type": "tint",
                "duration": 30,
                "name": "Summer campaign board",
                "tint_id": 42,
                "personalization_id": 7
              }
            ]
          }
        }
      ]
    }
  }
}
{
  "data": {
    "id": "12",
    "type": "mix",
    "attributes": {
      "name": "Lobby screen",
      "scenes": [
        {
          "layout": "horizontal",
          "template": "\"logo feed\"",
          "areas": {
            "logo": [
              {
                "type": "image",
                "duration": 10,
                "name": "Acme logo",
                "url": "https://cdn.example.com/mixes/acme-logo.png"
              }
            ],
            "feed": [
              {
                "type": "tint",
                "duration": 30,
                "name": "Summer campaign board",
                "tint_id": 42,
                "personalization_id": 7
              }
            ]
          }
        }
      ],
      "created_at": "2025-02-10T15:00:00.000Z",
      "updated_at": "2025-03-14T16:42:07.000Z"
    }
  }
}
{
  "errors": [
    {
      "code": "4020001",
      "title": "Payment Required",
      "detail": "You have exceeded your plan's limit of 5",
      "status": "402"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Delete multiple mixes

DELETE
https://api.tintup.com/v2/teams/{team_id}/mixes

Deletes several mixes at once.

Body

application/vnd.api+json; ext=bulk

The mixes to delete, each identified by its id.

dataArray<MixBulkDelete>required
Show child attributes
idstringrequired

The ID of the mix.

typeMixTypemixrequired

The resource type. Always mix.

Parameters

team_idintegerrequiredpath

The ID of the team.

Response

204No Content

No Content. The request succeeded and there is no response body.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: mixes:write

Delete multiple mixes
curl -X DELETE 'https://api.tintup.com/v2/teams/{team_id}/mixes' \
  -H 'Content-Type: application/vnd.api+json; ext=bulk' \
  -d '{
    "data": [
      {
        "id": "12",
        "type": "mix"
      },
      {
        "id": "13",
        "type": "mix"
      }
    ]
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/mixes', {
  method: 'DELETE',
  headers: {
    'Content-Type': 'application/vnd.api+json; ext=bulk',
  },
  body: JSON.stringify({
      "data": [
        {
          "id": "12",
          "type": "mix"
        },
        {
          "id": "13",
          "type": "mix"
        }
      ]
    }),
});

const data = await response.json();
import requests

payload = {
  "data": [
    {
      "id": "12",
      "type": "mix"
    },
    {
      "id": "13",
      "type": "mix"
    }
  ]
}

response = requests.delete('https://api.tintup.com/v2/teams/{team_id}/mixes', json=payload)
data = response.json()
Request Body
{
  "data": [
    {
      "id": "12",
      "type": "mix"
    },
    {
      "id": "13",
      "type": "mix"
    }
  ]
}

Retrieve a mix

GET
https://api.tintup.com/v2/teams/{team_id}/mixes/{mix_id}

Retrieves one of the team's mixes.

Parameters

team_idintegerrequiredpath

The ID of the team.

mix_idintegerrequiredpath

The ID of the mix.

Response

200OKobject

The mix.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: mixes:read

Retrieve a mix
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/mixes/{mix_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/mixes/{mix_id}', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/mixes/{mix_id}')
data = response.json()
200
{
  "data": {
    "id": "12",
    "type": "mix",
    "attributes": {
      "name": "Lobby screen",
      "scenes": [
        {
          "layout": "horizontal",
          "template": "\"logo feed\"",
          "areas": {
            "logo": [
              {
                "type": "image",
                "duration": 10,
                "name": "Acme logo",
                "url": "https://cdn.example.com/mixes/acme-logo.png"
              }
            ],
            "feed": [
              {
                "type": "tint",
                "duration": 30,
                "name": "Summer campaign board",
                "tint_id": 42,
                "personalization_id": 7
              }
            ]
          }
        }
      ],
      "created_at": "2025-02-10T15:00:00.000Z",
      "updated_at": "2025-03-14T16:42:07.000Z"
    }
  }
}

Delete a mix

DELETE
https://api.tintup.com/v2/teams/{team_id}/mixes/{mix_id}

Deletes the mix.

Parameters

team_idintegerrequiredpath

The ID of the team.

mix_idintegerrequiredpath

The ID of the mix.

Response

204No Content

No Content. The request succeeded and there is no response body.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: mixes:write

Delete a mix
curl -X DELETE 'https://api.tintup.com/v2/teams/{team_id}/mixes/{mix_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/mixes/{mix_id}', {
  method: 'DELETE',
});

const data = await response.json();
import requests

response = requests.delete('https://api.tintup.com/v2/teams/{team_id}/mixes/{mix_id}')
data = response.json()

Update a mix

PATCH
https://api.tintup.com/v2/teams/{team_id}/mixes/{mix_id}

Updates the mix.

Body

application/vnd.api+json

The mix changes.

dataMixUpdaterequired

The mix changes. The id is optional; the mix is identified by the URL. scenes replaces all existing scenes.

Show child attributes
idstring

The ID of the mix.

typeMixTypemixrequired

The resource type. Always mix.

attributesobject
Show child attributes
nameMixName

The name of the mix.

scenesArray<MixScene>

The scenes of the mix, played in order. At least one scene is required.

Show child attributes
layoutstringfullscreenhorizontalverticalhero_top_righthero_top_lefthero_bottom_righthero_bottom_left

The name of the layout the template was built from, used by the editor.

templatestringrequired

The layout of the areas, using the same syntax as the CSS grid-template property, except that area names can't be .. The area names must be quoted.

areasobjectrequired

The items to display in each area, keyed by area name. Every area named in template must be defined, and no other areas are allowed.

Parameters

team_idintegerrequiredpath

The ID of the team.

mix_idintegerrequiredpath

The ID of the mix.

Response

200OKobject

The mix.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: mixes:write

Update a mix
curl -X PATCH 'https://api.tintup.com/v2/teams/{team_id}/mixes/{mix_id}' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "id": "12",
      "type": "mix",
      "attributes": {
        "name": "Lobby screen (summer)"
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/mixes/{mix_id}', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "id": "12",
        "type": "mix",
        "attributes": {
          "name": "Lobby screen (summer)"
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "id": "12",
    "type": "mix",
    "attributes": {
      "name": "Lobby screen (summer)"
    }
  }
}

response = requests.patch('https://api.tintup.com/v2/teams/{team_id}/mixes/{mix_id}', json=payload)
data = response.json()
Request Body
{
  "data": {
    "id": "12",
    "type": "mix",
    "attributes": {
      "name": "Lobby screen (summer)"
    }
  }
}
{
  "data": {
    "id": "12",
    "type": "mix",
    "attributes": {
      "name": "Lobby screen",
      "scenes": [
        {
          "layout": "horizontal",
          "template": "\"logo feed\"",
          "areas": {
            "logo": [
              {
                "type": "image",
                "duration": 10,
                "name": "Acme logo",
                "url": "https://cdn.example.com/mixes/acme-logo.png"
              }
            ],
            "feed": [
              {
                "type": "tint",
                "duration": 30,
                "name": "Summer campaign board",
                "tint_id": 42,
                "personalization_id": 7
              }
            ]
          }
        }
      ],
      "created_at": "2025-02-10T15:00:00.000Z",
      "updated_at": "2025-03-14T16:42:07.000Z"
    }
  }
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

UGC Studio

group_ugc_studio
UGC Studio

Assets

assets

Retrieve a list of assets

GET
https://api.tintup.com/v2/teams/{team_id}/assets

Returns the team's assets that are in a collection the user has access to or in no collection. Returns 503 while search is temporarily unavailable.

Parameters

team_idintegerrequiredpath

The ID of the team.

pageobjectquery

Offset pagination. Use page[size] to set the number of items per page and page[number] to select a page. The response's links object contains ready-to-use URLs for the next and previous pages.

includeArray<string>collectionsimported_frommediateamquery

A comma-separated list of related resources to include in the response.

sortArray<string>id-idcreated_at-created_atupdated_at-updated_atsize-size-idquery

A comma-separated list of fields to sort by. Prefix a field with - to sort in descending order.

filterobjectquery

Filters that accept multiple values take a comma-separated list.

Response

200OKobject

A list of assets.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

503Service Unavailable

Service Unavailable. Search is temporarily unavailable; retry later.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: assets:read

Retrieve a list of assets
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/assets'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/assets', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/assets')
data = response.json()
{
  "data": [
    {
      "id": "190245",
      "type": "asset",
      "attributes": {
        "created_at": "2025-03-10T09:15:32.000Z",
        "updated_at": "2025-03-14T16:42:07.000Z",
        "status": "active",
        "source": "branded",
        "name": "Beach picnic with the Acme cooler",
        "description": "Customer photo submitted during the summer campaign.",
        "alternative_text": "Two friends sitting on a beach towel next to a red cooler.",
        "caption": "Two friends sitting on a beach towel next to a red cooler.",
        "tags": [
          "spring-launch",
          "ugc"
        ],
        "objects": [
          "beach",
          "cooler",
          "person"
        ],
        "emotions": [
          "happy"
        ],
        "infections": null,
        "licenses": false,
        "sfw": true,
        "insights": null,
        "imported_from_data": {},
        "source_url": "https://cdn.example.com/uploads/beach-picnic.jpg",
        "expanded_url": "https://cdn.example.com/uploads/beach-picnic.jpg",
        "download_url": "https://cdn.example.com/uploads/beach-picnic.jpg",
        "url": "https://media.example.com/assets/190245/beach-picnic.jpg",
        "thumbnail_url": "https://media.example.com/assets/190245/thumbnail.jpg",
        "mime_type": "image/jpeg",
        "size": 2483910,
        "dimensions": [
          1080,
          1350
        ],
        "duration": null,
        "author": null,
        "text": null,
        "post_title": null,
        "post_text": null
      },
      "relationships": {
        "media": {
          "data": null
        },
        "person": {
          "data": {
            "type": "person",
            "id": null
          }
        },
        "team": {
          "data": {
            "type": "team",
            "id": "212"
          },
          "links": {
            "self": "https://api.tintup.com/v2/teams/212"
          }
        },
        "collections": {
          "data": [
            {
              "type": "collection",
              "id": "48"
            }
          ],
          "meta": {
            "included": false
          }
        },
        "imported_from": {
          "data": {
            "type": "right_request",
            "id": "7710"
          },
          "meta": {
            "included": false
          }
        },
        "variants": {
          "data": [
            {
              "type": "variant",
              "id": "190245"
            }
          ],
          "meta": {
            "total": 1
          }
        }
      },
      "links": {
        "self": "https://api.tintup.com/v2/teams/212/assets/190245"
      }
    }
  ],
  "links": {
    "self": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=2",
    "first": "https://api.tintup.com/v2/teams/1/tints",
    "next": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=3",
    "prev": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=1"
  },
  "meta": {
    "aggregations": {
      "objects": {
        "beach": 18,
        "person": 42
      },
      "sources": {
        "branded": 120,
        "instagram_business": 64
      },
      "mime_types": {
        "image": 170,
        "video": 14
      },
      "tags": {
        "spring-launch": 31,
        "ugc": 77
      },
      "emotions": {
        "happy": 25
      }
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}

Create assets

POST
https://api.tintup.com/v2/teams/{team_id}/assets

Creates one or more assets asynchronously. Once complete, a websocket message of type asset_bulk_create_request is delivered to the team's private channel (private-team- followed by the team's ID) with the request's id and final status. Creation fails when the plan's limit of uploaded assets is reached.

Body

application/vnd.api+json; ext=bulk

One asset, or several assets using the bulk extension. If any asset is invalid, none are created and a 422 is returned.

application/vnd.api+json; ext=bulkobject
dataArray<NewAsset>required
Show child attributes
typestringassetrequired

The resource type.

attributesAssetWritableAttributes & objectrequired
application/vnd.api+jsonobject
dataNewAssetrequired

Specify either source_url or media. The file is downloaded and analyzed asynchronously, and counts toward the plan's limit of uploaded assets.

Show child attributes
typestringassetrequired

The resource type.

attributesAssetWritableAttributes & objectrequired

Parameters

team_idintegerrequiredpath

The ID of the team.

Response

202Acceptedobject

Accepted. The assets are being created.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: assets:write

Create assets
curl -X POST 'https://api.tintup.com/v2/teams/{team_id}/assets' \
  -H 'Content-Type: application/vnd.api+json; ext=bulk' \
  -d '{
    "data": [
      {
        "type": "asset",
        "attributes": {
          "status": "active",
          "name": "Beach picnic with the Acme cooler",
          "title": "Beach picnic with the Acme cooler",
          "description": "Customer photo submitted during the summer campaign.",
          "alternative_text": "Two friends sitting on a beach towel next to a red cooler.",
          "tags": [
            "spring-launch",
            "ugc"
          ],
          "collection_ids": [
            48,
            52
          ],
          "source_url": "https://cdn.example.com/uploads/beach-picnic.jpg",
          "media": "eyJfcmFpbHMiOnsiZGF0YSI6ODgyMTUsInB1ciI6ImJsb2JfaWQifX0=--1c3e5a7b9d2f4a6c8e0b1d3f5a7c9e2b4d6f8a0c",
          "parent_id": 190233
        }
      }
    ]
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/assets', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.api+json; ext=bulk',
  },
  body: JSON.stringify({
      "data": [
        {
          "type": "asset",
          "attributes": {
            "status": "active",
            "name": "Beach picnic with the Acme cooler",
            "title": "Beach picnic with the Acme cooler",
            "description": "Customer photo submitted during the summer campaign.",
            "alternative_text": "Two friends sitting on a beach towel next to a red cooler.",
            "tags": [
              "spring-launch",
              "ugc"
            ],
            "collection_ids": [
              48,
              52
            ],
            "source_url": "https://cdn.example.com/uploads/beach-picnic.jpg",
            "media": "eyJfcmFpbHMiOnsiZGF0YSI6ODgyMTUsInB1ciI6ImJsb2JfaWQifX0=--1c3e5a7b9d2f4a6c8e0b1d3f5a7c9e2b4d6f8a0c",
            "parent_id": 190233
          }
        }
      ]
    }),
});

const data = await response.json();
import requests

payload = {
  "data": [
    {
      "type": "asset",
      "attributes": {
        "status": "active",
        "name": "Beach picnic with the Acme cooler",
        "title": "Beach picnic with the Acme cooler",
        "description": "Customer photo submitted during the summer campaign.",
        "alternative_text": "Two friends sitting on a beach towel next to a red cooler.",
        "tags": [
          "spring-launch",
          "ugc"
        ],
        "collection_ids": [
          48,
          52
        ],
        "source_url": "https://cdn.example.com/uploads/beach-picnic.jpg",
        "media": "eyJfcmFpbHMiOnsiZGF0YSI6ODgyMTUsInB1ciI6ImJsb2JfaWQifX0=--1c3e5a7b9d2f4a6c8e0b1d3f5a7c9e2b4d6f8a0c",
        "parent_id": 190233
      }
    }
  ]
}

response = requests.post('https://api.tintup.com/v2/teams/{team_id}/assets', json=payload)
data = response.json()
Request Body
{
  "data": [
    {
      "type": "asset",
      "attributes": {
        "status": "active",
        "name": "Beach picnic with the Acme cooler",
        "title": "Beach picnic with the Acme cooler",
        "description": "Customer photo submitted during the summer campaign.",
        "alternative_text": "Two friends sitting on a beach towel next to a red cooler.",
        "tags": [
          "spring-launch",
          "ugc"
        ],
        "collection_ids": [
          48,
          52
        ],
        "source_url": "https://cdn.example.com/uploads/beach-picnic.jpg",
        "media": "eyJfcmFpbHMiOnsiZGF0YSI6ODgyMTUsInB1ciI6ImJsb2JfaWQifX0=--1c3e5a7b9d2f4a6c8e0b1d3f5a7c9e2b4d6f8a0c",
        "parent_id": 190233
      }
    }
  ]
}
{
  "data": {
    "type": "asset",
    "attributes": {
      "status": "active",
      "name": "Beach picnic with the Acme cooler",
      "title": "Beach picnic with the Acme cooler",
      "description": "Customer photo submitted during the summer campaign.",
      "alternative_text": "Two friends sitting on a beach towel next to a red cooler.",
      "tags": [
        "spring-launch",
        "ugc"
      ],
      "collection_ids": [
        48,
        52
      ],
      "source_url": "https://cdn.example.com/uploads/beach-picnic.jpg",
      "media": "eyJfcmFpbHMiOnsiZGF0YSI6ODgyMTUsInB1ciI6ImJsb2JfaWQifX0=--1c3e5a7b9d2f4a6c8e0b1d3f5a7c9e2b4d6f8a0c",
      "parent_id": 190233
    }
  }
}
{
  "data": {
    "id": "3f9c1a7e5b2d4c86a0e1",
    "type": "asset_bulk_create_request",
    "attributes": {
      "status": "pending"
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Delete multiple assets

DELETE
https://api.tintup.com/v2/teams/{team_id}/assets

Deletes several assets at once.

Body

application/vnd.api+json; ext=bulk

The assets to delete. Assets that don't exist or that the user can't access are skipped.

dataArray<AssetDelete>required
Show child attributes
idstringrequired

The ID of the asset to delete.

typestringassetrequired

The resource type.

Parameters

team_idintegerrequiredpath

The ID of the team.

Response

204No Content

No Content. The request succeeded and there is no response body.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: assets:write

Delete multiple assets
curl -X DELETE 'https://api.tintup.com/v2/teams/{team_id}/assets' \
  -H 'Content-Type: application/vnd.api+json; ext=bulk' \
  -d '{
    "data": [
      {
        "id": "190245",
        "type": "asset"
      }
    ]
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/assets', {
  method: 'DELETE',
  headers: {
    'Content-Type': 'application/vnd.api+json; ext=bulk',
  },
  body: JSON.stringify({
      "data": [
        {
          "id": "190245",
          "type": "asset"
        }
      ]
    }),
});

const data = await response.json();
import requests

payload = {
  "data": [
    {
      "id": "190245",
      "type": "asset"
    }
  ]
}

response = requests.delete('https://api.tintup.com/v2/teams/{team_id}/assets', json=payload)
data = response.json()
Request Body
{
  "data": [
    {
      "id": "190245",
      "type": "asset"
    }
  ]
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}

Update multiple assets

PATCH
https://api.tintup.com/v2/teams/{team_id}/assets

Updates several assets at once. If any asset is invalid, none are updated.

Body

application/vnd.api+json; ext=bulk

The assets to update and the attributes to change for each. Assets that don't exist or that the user can't access are skipped.

dataArray<AssetBulkUpdate>required
Show child attributes
idstring

The ID of the asset.

typestringassetrequired

The resource type.

attributesAssetWritableAttributesrequired
Show child attributes
statusassetStatusactive
namestring | null

The asset's name, used in search.

titlestring | nullwrite onlydeprecated

Deprecated alias of name.

descriptionstring | null

A longer description of the asset, used in search.

alternative_textstring | null

Text describing the image for screen readers.

tagsArray<string> | string | object

Tags to set on the asset, either as a list (or a comma-separated string) that replaces the existing tags, or as an object with + (tags to add) and/or - (tags to remove). Duplicates are removed case-insensitively.

collection_idsArray<integer> | string | objectwrite only

Collections the asset belongs to, either as a list of collection IDs (or a comma-separated string) that replaces the collections the user has access to (collections the user can't access are kept), or as an object with + (collection IDs to add) and/or - (collection IDs to remove). Every ID must be a collection the user has access to. Write-only: use the collections relationship to read them.

object

Parameters

team_idintegerrequiredpath

The ID of the team.

includeArray<string>collectionsimported_frommediateamquery

A comma-separated list of related resources to include in the response.

Response

200OKobject

The updated assets.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: assets:write

Update multiple assets
curl -X PATCH 'https://api.tintup.com/v2/teams/{team_id}/assets' \
  -H 'Content-Type: application/vnd.api+json; ext=bulk' \
  -d '{
    "data": [
      {
        "id": "190245",
        "type": "asset",
        "attributes": {
          "status": "active",
          "name": "Beach picnic with the Acme cooler",
          "title": "Beach picnic with the Acme cooler",
          "description": "Customer photo submitted during the summer campaign.",
          "alternative_text": "Two friends sitting on a beach towel next to a red cooler.",
          "tags": [
            "spring-launch",
            "ugc"
          ],
          "collection_ids": [
            48,
            52
          ]
        }
      }
    ]
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/assets', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/vnd.api+json; ext=bulk',
  },
  body: JSON.stringify({
      "data": [
        {
          "id": "190245",
          "type": "asset",
          "attributes": {
            "status": "active",
            "name": "Beach picnic with the Acme cooler",
            "title": "Beach picnic with the Acme cooler",
            "description": "Customer photo submitted during the summer campaign.",
            "alternative_text": "Two friends sitting on a beach towel next to a red cooler.",
            "tags": [
              "spring-launch",
              "ugc"
            ],
            "collection_ids": [
              48,
              52
            ]
          }
        }
      ]
    }),
});

const data = await response.json();
import requests

payload = {
  "data": [
    {
      "id": "190245",
      "type": "asset",
      "attributes": {
        "status": "active",
        "name": "Beach picnic with the Acme cooler",
        "title": "Beach picnic with the Acme cooler",
        "description": "Customer photo submitted during the summer campaign.",
        "alternative_text": "Two friends sitting on a beach towel next to a red cooler.",
        "tags": [
          "spring-launch",
          "ugc"
        ],
        "collection_ids": [
          48,
          52
        ]
      }
    }
  ]
}

response = requests.patch('https://api.tintup.com/v2/teams/{team_id}/assets', json=payload)
data = response.json()
Request Body
{
  "data": [
    {
      "id": "190245",
      "type": "asset",
      "attributes": {
        "status": "active",
        "name": "Beach picnic with the Acme cooler",
        "title": "Beach picnic with the Acme cooler",
        "description": "Customer photo submitted during the summer campaign.",
        "alternative_text": "Two friends sitting on a beach towel next to a red cooler.",
        "tags": [
          "spring-launch",
          "ugc"
        ],
        "collection_ids": [
          48,
          52
        ]
      }
    }
  ]
}
{
  "data": [
    {
      "id": "190245",
      "type": "asset",
      "attributes": {
        "created_at": "2025-03-10T09:15:32.000Z",
        "updated_at": "2025-03-14T16:42:07.000Z",
        "status": "active",
        "source": "branded",
        "name": "Beach picnic with the Acme cooler",
        "description": "Customer photo submitted during the summer campaign.",
        "alternative_text": "Two friends sitting on a beach towel next to a red cooler.",
        "caption": "Two friends sitting on a beach towel next to a red cooler.",
        "tags": [
          "spring-launch",
          "ugc"
        ],
        "objects": [
          "beach",
          "cooler",
          "person"
        ],
        "emotions": [
          "happy"
        ],
        "infections": null,
        "licenses": false,
        "sfw": true,
        "insights": null,
        "imported_from_data": {},
        "source_url": "https://cdn.example.com/uploads/beach-picnic.jpg",
        "expanded_url": "https://cdn.example.com/uploads/beach-picnic.jpg",
        "download_url": "https://cdn.example.com/uploads/beach-picnic.jpg",
        "url": "https://media.example.com/assets/190245/beach-picnic.jpg",
        "thumbnail_url": "https://media.example.com/assets/190245/thumbnail.jpg",
        "mime_type": "image/jpeg",
        "size": 2483910,
        "dimensions": [
          1080,
          1350
        ],
        "duration": null,
        "author": null,
        "text": null,
        "post_title": null,
        "post_text": null
      },
      "relationships": {
        "media": {
          "data": null
        },
        "person": {
          "data": {
            "type": "person",
            "id": null
          }
        },
        "team": {
          "data": {
            "type": "team",
            "id": "212"
          },
          "links": {
            "self": "https://api.tintup.com/v2/teams/212"
          }
        },
        "collections": {
          "data": [
            {
              "type": "collection",
              "id": "48"
            }
          ],
          "meta": {
            "included": false
          }
        },
        "imported_from": {
          "data": {
            "type": "right_request",
            "id": "7710"
          },
          "meta": {
            "included": false
          }
        },
        "variants": {
          "data": [
            {
              "type": "variant",
              "id": "190245"
            }
          ],
          "meta": {
            "total": 1
          }
        }
      },
      "links": {
        "self": "https://api.tintup.com/v2/teams/212/assets/190245"
      }
    }
  ]
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Retrieve an asset

GET
https://api.tintup.com/v2/teams/{team_id}/assets/{asset_id}

Returns 404 when the asset is only in collections the user doesn't have access to.

Parameters

team_idintegerrequiredpath

The ID of the team.

asset_idintegerrequiredpath

The ID of the asset.

includeArray<string>collectionsimported_frommediateamquery

A comma-separated list of related resources to include in the response.

Response

200OKobject

The asset.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: assets:read

Retrieve an asset
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/assets/{asset_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/assets/{asset_id}', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/assets/{asset_id}')
data = response.json()
{
  "data": {
    "id": "190245",
    "type": "asset",
    "attributes": {
      "created_at": "2025-03-10T09:15:32.000Z",
      "updated_at": "2025-03-14T16:42:07.000Z",
      "status": "active",
      "source": "branded",
      "name": "Beach picnic with the Acme cooler",
      "description": "Customer photo submitted during the summer campaign.",
      "alternative_text": "Two friends sitting on a beach towel next to a red cooler.",
      "caption": "Two friends sitting on a beach towel next to a red cooler.",
      "tags": [
        "spring-launch",
        "ugc"
      ],
      "objects": [
        "beach",
        "cooler",
        "person"
      ],
      "emotions": [
        "happy"
      ],
      "infections": null,
      "licenses": false,
      "sfw": true,
      "insights": null,
      "imported_from_data": {},
      "source_url": "https://cdn.example.com/uploads/beach-picnic.jpg",
      "expanded_url": "https://cdn.example.com/uploads/beach-picnic.jpg",
      "download_url": "https://cdn.example.com/uploads/beach-picnic.jpg",
      "url": "https://media.example.com/assets/190245/beach-picnic.jpg",
      "thumbnail_url": "https://media.example.com/assets/190245/thumbnail.jpg",
      "mime_type": "image/jpeg",
      "size": 2483910,
      "dimensions": [
        1080,
        1350
      ],
      "duration": null,
      "author": null,
      "text": null,
      "post_title": null,
      "post_text": null
    },
    "relationships": {
      "media": {
        "data": null
      },
      "person": {
        "data": {
          "type": "person",
          "id": null
        }
      },
      "team": {
        "data": {
          "type": "team",
          "id": "212"
        },
        "links": {
          "self": "https://api.tintup.com/v2/teams/212"
        }
      },
      "collections": {
        "data": [
          {
            "type": "collection",
            "id": "48"
          }
        ],
        "meta": {
          "included": false
        }
      },
      "imported_from": {
        "data": {
          "type": "right_request",
          "id": "7710"
        },
        "meta": {
          "included": false
        }
      },
      "variants": {
        "data": [
          {
            "type": "variant",
            "id": "190245"
          }
        ],
        "meta": {
          "total": 1
        }
      }
    },
    "links": {
      "self": "https://api.tintup.com/v2/teams/212/assets/190245"
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Delete an asset

DELETE
https://api.tintup.com/v2/teams/{team_id}/assets/{asset_id}

Deletes the asset.

Parameters

team_idintegerrequiredpath

The ID of the team.

asset_idintegerrequiredpath

The ID of the asset.

Response

204No Content

No Content. The request succeeded and there is no response body.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: assets:write

Delete an asset
curl -X DELETE 'https://api.tintup.com/v2/teams/{team_id}/assets/{asset_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/assets/{asset_id}', {
  method: 'DELETE',
});

const data = await response.json();
import requests

response = requests.delete('https://api.tintup.com/v2/teams/{team_id}/assets/{asset_id}')
data = response.json()
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Update an asset

PATCH
https://api.tintup.com/v2/teams/{team_id}/assets/{asset_id}

Updates the asset.

Body

application/vnd.api+json

The attributes to change.

dataAssetUpdaterequired

Only the attributes that are sent are changed.

Show child attributes
idstring

The ID of the asset.

typestringassetrequired

The resource type.

attributesAssetWritableAttributesrequired
Show child attributes
statusassetStatusactive
namestring | null

The asset's name, used in search.

titlestring | nullwrite onlydeprecated

Deprecated alias of name.

descriptionstring | null

A longer description of the asset, used in search.

alternative_textstring | null

Text describing the image for screen readers.

tagsArray<string> | string | object

Tags to set on the asset, either as a list (or a comma-separated string) that replaces the existing tags, or as an object with + (tags to add) and/or - (tags to remove). Duplicates are removed case-insensitively.

collection_idsArray<integer> | string | objectwrite only

Collections the asset belongs to, either as a list of collection IDs (or a comma-separated string) that replaces the collections the user has access to (collections the user can't access are kept), or as an object with + (collection IDs to add) and/or - (collection IDs to remove). Every ID must be a collection the user has access to. Write-only: use the collections relationship to read them.

Parameters

team_idintegerrequiredpath

The ID of the team.

asset_idintegerrequiredpath

The ID of the asset.

includeArray<string>collectionsimported_frommediateamquery

A comma-separated list of related resources to include in the response.

Response

200OKobject

The asset.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: assets:write

Update an asset
curl -X PATCH 'https://api.tintup.com/v2/teams/{team_id}/assets/{asset_id}' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "id": "190245",
      "type": "asset",
      "attributes": {
        "status": "active",
        "name": "Beach picnic with the Acme cooler",
        "title": "Beach picnic with the Acme cooler",
        "description": "Customer photo submitted during the summer campaign.",
        "alternative_text": "Two friends sitting on a beach towel next to a red cooler.",
        "tags": [
          "spring-launch",
          "ugc"
        ],
        "collection_ids": [
          48,
          52
        ]
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/assets/{asset_id}', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "id": "190245",
        "type": "asset",
        "attributes": {
          "status": "active",
          "name": "Beach picnic with the Acme cooler",
          "title": "Beach picnic with the Acme cooler",
          "description": "Customer photo submitted during the summer campaign.",
          "alternative_text": "Two friends sitting on a beach towel next to a red cooler.",
          "tags": [
            "spring-launch",
            "ugc"
          ],
          "collection_ids": [
            48,
            52
          ]
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "id": "190245",
    "type": "asset",
    "attributes": {
      "status": "active",
      "name": "Beach picnic with the Acme cooler",
      "title": "Beach picnic with the Acme cooler",
      "description": "Customer photo submitted during the summer campaign.",
      "alternative_text": "Two friends sitting on a beach towel next to a red cooler.",
      "tags": [
        "spring-launch",
        "ugc"
      ],
      "collection_ids": [
        48,
        52
      ]
    }
  }
}

response = requests.patch('https://api.tintup.com/v2/teams/{team_id}/assets/{asset_id}', json=payload)
data = response.json()
Request Body
{
  "data": {
    "id": "190245",
    "type": "asset",
    "attributes": {
      "status": "active",
      "name": "Beach picnic with the Acme cooler",
      "title": "Beach picnic with the Acme cooler",
      "description": "Customer photo submitted during the summer campaign.",
      "alternative_text": "Two friends sitting on a beach towel next to a red cooler.",
      "tags": [
        "spring-launch",
        "ugc"
      ],
      "collection_ids": [
        48,
        52
      ]
    }
  }
}
{
  "data": {
    "id": "190245",
    "type": "asset",
    "attributes": {
      "created_at": "2025-03-10T09:15:32.000Z",
      "updated_at": "2025-03-14T16:42:07.000Z",
      "status": "active",
      "source": "branded",
      "name": "Beach picnic with the Acme cooler",
      "description": "Customer photo submitted during the summer campaign.",
      "alternative_text": "Two friends sitting on a beach towel next to a red cooler.",
      "caption": "Two friends sitting on a beach towel next to a red cooler.",
      "tags": [
        "spring-launch",
        "ugc"
      ],
      "objects": [
        "beach",
        "cooler",
        "person"
      ],
      "emotions": [
        "happy"
      ],
      "infections": null,
      "licenses": false,
      "sfw": true,
      "insights": null,
      "imported_from_data": {},
      "source_url": "https://cdn.example.com/uploads/beach-picnic.jpg",
      "expanded_url": "https://cdn.example.com/uploads/beach-picnic.jpg",
      "download_url": "https://cdn.example.com/uploads/beach-picnic.jpg",
      "url": "https://media.example.com/assets/190245/beach-picnic.jpg",
      "thumbnail_url": "https://media.example.com/assets/190245/thumbnail.jpg",
      "mime_type": "image/jpeg",
      "size": 2483910,
      "dimensions": [
        1080,
        1350
      ],
      "duration": null,
      "author": null,
      "text": null,
      "post_title": null,
      "post_text": null
    },
    "relationships": {
      "media": {
        "data": null
      },
      "person": {
        "data": {
          "type": "person",
          "id": null
        }
      },
      "team": {
        "data": {
          "type": "team",
          "id": "212"
        },
        "links": {
          "self": "https://api.tintup.com/v2/teams/212"
        }
      },
      "collections": {
        "data": [
          {
            "type": "collection",
            "id": "48"
          }
        ],
        "meta": {
          "included": false
        }
      },
      "imported_from": {
        "data": {
          "type": "right_request",
          "id": "7710"
        },
        "meta": {
          "included": false
        }
      },
      "variants": {
        "data": [
          {
            "type": "variant",
            "id": "190245"
          }
        ],
        "meta": {
          "total": 1
        }
      }
    },
    "links": {
      "self": "https://api.tintup.com/v2/teams/212/assets/190245"
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Retrieve asset aggregations

GET
https://api.tintup.com/v2/teams/{team_id}/assets/aggregations

Returns the number of the team's assets per source, detected object, emotion, media type and tag. Returns 503 while search is temporarily unavailable.

Parameters

team_idintegerrequiredpath

The ID of the team.

filterobjectquery

Filters that accept multiple values take a comma-separated list.

Response

200OKobject

The number of the team's assets per source, detected object, emotion, media type and tag.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

503Service Unavailable

Service Unavailable. Search is temporarily unavailable; retry later.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: assets:read

Retrieve asset aggregations
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/assets/aggregations'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/assets/aggregations', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/assets/aggregations')
data = response.json()
{
  "data": [
    {
      "id": "tags",
      "type": "aggregation",
      "attributes": {
        "buckets": {
          "spring-launch": 31,
          "ugc": 77
        }
      }
    }
  ]
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
UGC Studio

Collections

collections

Retrieve a list of collections

GET
https://api.tintup.com/v2/teams/{team_id}/collections

Returns the collections you have access to.

Parameters

team_idintegerrequiredpath

The ID of the team.

filterobjectquery

Filters the collections.

sortArray<string>id-idname-namecreated_at-created_atupdated_at-updated_at-idquery

A comma-separated list of fields to sort by. Prefix a field with - to sort in descending order. Defaults to -id (newest first).

includeArray<string>assetsquery

A comma-separated list of related resources to include in the response.

pageobjectquery

Offset pagination. Use page[size] to set the number of items per page and page[number] to select a page. The response's links object contains ready-to-use URLs for the next and previous pages.

Response

200OKobject

A list of collections.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: collections:read

Retrieve a list of collections
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/collections'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/collections', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/collections')
data = response.json()
200
{
  "data": [
    {
      "id": "27",
      "type": "collection",
      "attributes": {
        "name": "Summer campaign",
        "status": "active",
        "public": false,
        "slug": null,
        "assets_count": 48,
        "created_at": "2025-02-03T11:30:00.000Z",
        "updated_at": "2025-03-14T16:42:07.000Z"
      },
      "relationships": {
        "assets": {
          "data": [
            {
              "type": "asset",
              "id": "7300"
            }
          ],
          "links": {
            "first": "https://api.tintup.com/v2/teams/1/collections/27/assets",
            "next": "https://api.tintup.com/v2/teams/1/collections/27/assets?page%5Bnumber%5D=2",
            "previous": "https://api.tintup.com/v2/teams/1/collections/27/assets?page%5Bnumber%5D=1"
          },
          "meta": {
            "included": false,
            "total": 48
          }
        }
      }
    }
  ],
  "links": {
    "self": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=2",
    "first": "https://api.tintup.com/v2/teams/1/tints",
    "next": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=3",
    "prev": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=1"
  }
}

Create a collection

POST
https://api.tintup.com/v2/teams/{team_id}/collections

Creates a collection.

Body

application/vnd.api+json

The collection to create.

dataNewCollectionrequired

The collection to create. New collections are active.

Show child attributes
typeCollectionTypecollectionrequired

The resource type. Always collection.

attributesobjectrequired
Show child attributes
nameCollectionNamerequired

The name of the collection.

publicCollectionPublicfalse

Parameters

team_idintegerrequiredpath

The ID of the team.

includeArray<string>assetsquery

A comma-separated list of related resources to include in the response.

Response

201Createdobject

The collection.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: collections:write

Create a collection
curl -X POST 'https://api.tintup.com/v2/teams/{team_id}/collections' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "collection",
      "attributes": {
        "name": "Summer campaign",
        "public": false
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/collections', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "collection",
        "attributes": {
          "name": "Summer campaign",
          "public": false
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "collection",
    "attributes": {
      "name": "Summer campaign",
      "public": False
    }
  }
}

response = requests.post('https://api.tintup.com/v2/teams/{team_id}/collections', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "collection",
    "attributes": {
      "name": "Summer campaign",
      "public": false
    }
  }
}
{
  "data": {
    "id": "27",
    "type": "collection",
    "attributes": {
      "name": "Summer campaign",
      "status": "active",
      "public": false,
      "slug": null,
      "assets_count": 48,
      "created_at": "2025-02-03T11:30:00.000Z",
      "updated_at": "2025-03-14T16:42:07.000Z"
    },
    "relationships": {
      "assets": {
        "data": [
          {
            "type": "asset",
            "id": "7300"
          }
        ],
        "links": {
          "first": "https://api.tintup.com/v2/teams/1/collections/27/assets",
          "next": "https://api.tintup.com/v2/teams/1/collections/27/assets?page%5Bnumber%5D=2",
          "previous": "https://api.tintup.com/v2/teams/1/collections/27/assets?page%5Bnumber%5D=1"
        },
        "meta": {
          "included": false,
          "total": 48
        }
      }
    }
  }
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Delete multiple collections

DELETE
https://api.tintup.com/v2/teams/{team_id}/collections

Deletes several collections at once.

Body

application/vnd.api+json; ext=bulk

The collections to delete, each identified by its id.

dataArray<CollectionBulkDelete>required
Show child attributes
idstringrequired

The ID of the collection.

typeCollectionTypecollectionrequired

The resource type. Always collection.

Parameters

team_idintegerrequiredpath

The ID of the team.

Response

204No Content

No Content. The request succeeded and there is no response body.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: collections:write

Delete multiple collections
curl -X DELETE 'https://api.tintup.com/v2/teams/{team_id}/collections' \
  -H 'Content-Type: application/vnd.api+json; ext=bulk' \
  -d '{
    "data": [
      {
        "id": "27",
        "type": "collection"
      },
      {
        "id": "28",
        "type": "collection"
      }
    ]
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/collections', {
  method: 'DELETE',
  headers: {
    'Content-Type': 'application/vnd.api+json; ext=bulk',
  },
  body: JSON.stringify({
      "data": [
        {
          "id": "27",
          "type": "collection"
        },
        {
          "id": "28",
          "type": "collection"
        }
      ]
    }),
});

const data = await response.json();
import requests

payload = {
  "data": [
    {
      "id": "27",
      "type": "collection"
    },
    {
      "id": "28",
      "type": "collection"
    }
  ]
}

response = requests.delete('https://api.tintup.com/v2/teams/{team_id}/collections', json=payload)
data = response.json()
Request Body
{
  "data": [
    {
      "id": "27",
      "type": "collection"
    },
    {
      "id": "28",
      "type": "collection"
    }
  ]
}

Update multiple collections

PATCH
https://api.tintup.com/v2/teams/{team_id}/collections

The request is validated as a whole: if any collection is invalid, none are updated.

Body

application/vnd.api+json; ext=bulk

The collections to update, each identified by its id.

dataArray<CollectionBulkUpdate>required
Show child attributes
idstringrequired

The ID of the collection.

typeCollectionTypecollectionrequired

The resource type. Always collection.

attributesCollectionWritableAttributes

Attributes that can be changed on an existing collection. Only the attributes sent are changed.

Show child attributes
nameCollectionName

The name of the collection.

statusCollectionStatusactivearchived

Whether the collection is active or archived.

publicCollectionPublic

Whether the collection can be viewed publicly using its slug. Making a collection public generates a new slug; making it private removes the slug.

Parameters

team_idintegerrequiredpath

The ID of the team.

Response

200OKobject

The updated collections.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: collections:write

Update multiple collections
curl -X PATCH 'https://api.tintup.com/v2/teams/{team_id}/collections' \
  -H 'Content-Type: application/vnd.api+json; ext=bulk' \
  -d '{
    "data": [
      {
        "id": "27",
        "type": "collection",
        "attributes": {
          "status": "archived"
        }
      },
      {
        "id": "28",
        "type": "collection",
        "attributes": {
          "status": "archived"
        }
      }
    ]
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/collections', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/vnd.api+json; ext=bulk',
  },
  body: JSON.stringify({
      "data": [
        {
          "id": "27",
          "type": "collection",
          "attributes": {
            "status": "archived"
          }
        },
        {
          "id": "28",
          "type": "collection",
          "attributes": {
            "status": "archived"
          }
        }
      ]
    }),
});

const data = await response.json();
import requests

payload = {
  "data": [
    {
      "id": "27",
      "type": "collection",
      "attributes": {
        "status": "archived"
      }
    },
    {
      "id": "28",
      "type": "collection",
      "attributes": {
        "status": "archived"
      }
    }
  ]
}

response = requests.patch('https://api.tintup.com/v2/teams/{team_id}/collections', json=payload)
data = response.json()
Request Body
{
  "data": [
    {
      "id": "27",
      "type": "collection",
      "attributes": {
        "status": "archived"
      }
    },
    {
      "id": "28",
      "type": "collection",
      "attributes": {
        "status": "archived"
      }
    }
  ]
}
{
  "data": [
    {
      "id": "27",
      "type": "collection",
      "attributes": {
        "name": "Summer campaign",
        "status": "active",
        "public": false,
        "slug": null,
        "assets_count": 48,
        "created_at": "2025-02-03T11:30:00.000Z",
        "updated_at": "2025-03-14T16:42:07.000Z"
      },
      "relationships": {
        "assets": {
          "data": [
            {
              "type": "asset",
              "id": "7300"
            }
          ],
          "links": {
            "first": "https://api.tintup.com/v2/teams/1/collections/27/assets",
            "next": "https://api.tintup.com/v2/teams/1/collections/27/assets?page%5Bnumber%5D=2",
            "previous": "https://api.tintup.com/v2/teams/1/collections/27/assets?page%5Bnumber%5D=1"
          },
          "meta": {
            "included": false,
            "total": 48
          }
        }
      }
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Delete a collection

DELETE
https://api.tintup.com/v2/teams/{team_id}/collections/{collection_id}

Deletes the collection.

Parameters

team_idintegerrequiredpath

The ID of the team.

collection_idintegerrequiredpath

The ID of the collection.

Response

204No Content

No Content. The request succeeded and there is no response body.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: collections:write

Delete a collection
curl -X DELETE 'https://api.tintup.com/v2/teams/{team_id}/collections/{collection_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/collections/{collection_id}', {
  method: 'DELETE',
});

const data = await response.json();
import requests

response = requests.delete('https://api.tintup.com/v2/teams/{team_id}/collections/{collection_id}')
data = response.json()

Update a collection

PATCH
https://api.tintup.com/v2/teams/{team_id}/collections/{collection_id}

Updates the collection.

Body

application/vnd.api+json

The collection changes.

dataCollectionUpdaterequired

The collection changes. The id is optional; the collection is identified by the URL.

Show child attributes
idstring

The ID of the collection.

typeCollectionTypecollectionrequired

The resource type. Always collection.

attributesCollectionWritableAttributes

Attributes that can be changed on an existing collection. Only the attributes sent are changed.

Show child attributes
nameCollectionName

The name of the collection.

statusCollectionStatusactivearchived

Whether the collection is active or archived.

publicCollectionPublic

Whether the collection can be viewed publicly using its slug. Making a collection public generates a new slug; making it private removes the slug.

Parameters

team_idintegerrequiredpath

The ID of the team.

collection_idintegerrequiredpath

The ID of the collection.

includeArray<string>assetsquery

A comma-separated list of related resources to include in the response.

Response

200OKobject

The collection.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: collections:write

Update a collection
curl -X PATCH 'https://api.tintup.com/v2/teams/{team_id}/collections/{collection_id}' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "id": "27",
      "type": "collection",
      "attributes": {
        "public": true
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/collections/{collection_id}', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "id": "27",
        "type": "collection",
        "attributes": {
          "public": true
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "id": "27",
    "type": "collection",
    "attributes": {
      "public": True
    }
  }
}

response = requests.patch('https://api.tintup.com/v2/teams/{team_id}/collections/{collection_id}', json=payload)
data = response.json()
Request Body
{
  "data": {
    "id": "27",
    "type": "collection",
    "attributes": {
      "public": true
    }
  }
}
200
{
  "data": {
    "id": "27",
    "type": "collection",
    "attributes": {
      "name": "Summer campaign",
      "status": "active",
      "public": false,
      "slug": null,
      "assets_count": 48,
      "created_at": "2025-02-03T11:30:00.000Z",
      "updated_at": "2025-03-14T16:42:07.000Z"
    },
    "relationships": {
      "assets": {
        "data": [
          {
            "type": "asset",
            "id": "7300"
          }
        ],
        "links": {
          "first": "https://api.tintup.com/v2/teams/1/collections/27/assets",
          "next": "https://api.tintup.com/v2/teams/1/collections/27/assets?page%5Bnumber%5D=2",
          "previous": "https://api.tintup.com/v2/teams/1/collections/27/assets?page%5Bnumber%5D=1"
        },
        "meta": {
          "included": false,
          "total": 48
        }
      }
    }
  }
}
UGC Studio

Marketing Integrations

marketing_integrations

Retrieve a list of marketing integrations

GET
https://api.tintup.com/v2/teams/{team_id}/marketing_integrations

Parameters

team_idintegerrequiredpath

The ID of the team.

pageobjectquery

Offset pagination. Use page[size] to set the number of items per page and page[number] to select a page. The response's links object contains ready-to-use URLs for the next and previous pages.

Response

200OKobject

A list of marketing integrations.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: marketing_integrations:read

Retrieve a list of marketing integrations
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/marketing_integrations'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/marketing_integrations', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/marketing_integrations')
data = response.json()
{
  "data": [
    {
      "id": "318",
      "type": "marketing_integration",
      "attributes": {
        "status": "ready",
        "site": "https://acme.bynder.com",
        "external_id": "acme.bynder.com",
        "name": "Acme Inc.",
        "username": "jane.doe@example.com",
        "image_url": "https://cdn.example.com/avatars/acme.png"
      }
    }
  ],
  "links": {
    "self": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=2",
    "first": "https://api.tintup.com/v2/teams/1/tints",
    "next": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=3",
    "prev": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=1"
  }
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}

Create a marketing integration

POST
https://api.tintup.com/v2/teams/{team_id}/marketing_integrations

Connects a marketing integration using credentials. Except for twitter, the credentials are checked by fetching the account's profile from the source. The credentials are never returned.

Body

application/vnd.api+json

The marketing integration to connect. Only sources that use credentials can be created this way; other sources are connected with Authenticate a marketing integration.

dataNewMarketingIntegrationrequired

Connects a marketing integration using credentials instead of OAuth. Which attributes are required depends on source; see each attribute.

Show child attributes
typestringmarketing_integrationrequired

The resource type.

attributesobjectrequired
Show child attributes
sourcemarketingIntegrationSourcesForCreateadobe_experience_managerbrandfolderbyndergoogle_drivesalesforce_marketing_cloudtwitterwiden_collectiverequired

The external service to connect with credentials. dropbox, facebook, hubspot, and mailchimp can only be connected using the OAuth flow (see Authenticate a marketing integration). A twitter integration can only be added once per team.

access_tokenstringwrite only

The credentials used to connect to the source. Required when source is adobe_experience_manager (username|password), brandfolder (API key), bynder or salesforce_marketing_cloud (client_id|client_secret), twitter, or widen_collective (API key).

sitestring<uri>write only

The API endpoint of the source. Required when source is adobe_experience_manager or bynder (must start with http:// or https://), or salesforce_marketing_cloud (must match https://<subdomain>.rest.marketingcloudapis.com). The same endpoint can only be connected once per team.

external_idstringwrite only

The ID of the account at the source. Required when source is twitter.

Parameters

team_idintegerrequiredpath

The ID of the team.

Response

201Createdobject

The marketing integration.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: marketing_integrations:write

Create a marketing integration
curl -X POST 'https://api.tintup.com/v2/teams/{team_id}/marketing_integrations' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "marketing_integration",
      "attributes": {
        "source": "bynder",
        "access_token": "3f1c9a7e-5d2b-4e8a-9c61-7b0d2e4f8a13|Zm9vYmFyLWNsaWVudC1zZWNyZXQ",
        "site": "https://acme.bynder.com"
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/marketing_integrations', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "marketing_integration",
        "attributes": {
          "source": "bynder",
          "access_token": "3f1c9a7e-5d2b-4e8a-9c61-7b0d2e4f8a13|Zm9vYmFyLWNsaWVudC1zZWNyZXQ",
          "site": "https://acme.bynder.com"
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "marketing_integration",
    "attributes": {
      "source": "bynder",
      "access_token": "3f1c9a7e-5d2b-4e8a-9c61-7b0d2e4f8a13|Zm9vYmFyLWNsaWVudC1zZWNyZXQ",
      "site": "https://acme.bynder.com"
    }
  }
}

response = requests.post('https://api.tintup.com/v2/teams/{team_id}/marketing_integrations', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "marketing_integration",
    "attributes": {
      "source": "bynder",
      "access_token": "3f1c9a7e-5d2b-4e8a-9c61-7b0d2e4f8a13|Zm9vYmFyLWNsaWVudC1zZWNyZXQ",
      "site": "https://acme.bynder.com"
    }
  }
}
{
  "data": {
    "id": "318",
    "type": "marketing_integration",
    "attributes": {
      "status": "ready",
      "site": "https://acme.bynder.com",
      "external_id": "acme.bynder.com",
      "name": "Acme Inc.",
      "username": "jane.doe@example.com",
      "image_url": "https://cdn.example.com/avatars/acme.png"
    }
  }
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Delete a marketing integration

DELETE
https://api.tintup.com/v2/teams/{team_id}/marketing_integrations/{marketing_integration_id}

Parameters

team_idintegerrequiredpath

The ID of the team.

marketing_integration_idintegerrequiredpath

The ID of the marketing integration.

Response

204No Content

No Content. The request succeeded and there is no response body.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: marketing_integrations:write

Delete a marketing integration
curl -X DELETE 'https://api.tintup.com/v2/teams/{team_id}/marketing_integrations/{marketing_integration_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/marketing_integrations/{marketing_integration_id}', {
  method: 'DELETE',
});

const data = await response.json();
import requests

response = requests.delete('https://api.tintup.com/v2/teams/{team_id}/marketing_integrations/{marketing_integration_id}')
data = response.json()
404
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Reauthenticate a marketing integration

GET
https://api.tintup.com/v2/teams/{team_id}/marketing_integrations/{marketing_integration_id}/edit

Returns the URL of the third-party authorization page for the marketing integration. Open this URL (usually in a popup window) so the user can grant access again. Once the user completes the authorization flow, the marketing integration is updated and the result is delivered using the origin or redirect_uri options.

Parameters

team_idintegerrequiredpath

The ID of the team.

marketing_integration_idintegerrequiredpath

The ID of the marketing integration.

originstring<uri>query

When specified, once the user completes the authorization flow, the callback page posts a message to window.opener using window.postMessage with this value as the target origin. The message is a JSON string of the form {"type": "marketing_integration_new", "data": <response body>, "status": <HTTP status>} (marketing_integration_edit when reauthenticating), where the response body is the marketing integration (or errors).

redirect_uristring<uri>query

When specified, once the user completes the authorization flow, the user is redirected to this URI with a data query parameter containing the same JSON message as for origin, encoded using Base64. Takes precedence over origin.

Response

200OKobject

The URL of the third-party authorization page. Open it (usually in a popup window) so the user can grant access.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: marketing_integrations:write

Reauthenticate a marketing integration
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/marketing_integrations/{marketing_integration_id}/edit'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/marketing_integrations/{marketing_integration_id}/edit', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/marketing_integrations/{marketing_integration_id}/edit')
data = response.json()
{
  "data": {
    "id": "9e107d9d372bb6826bd81d3542a419d6",
    "type": "redirect",
    "attributes": {
      "url": "https://auth.example.com/oauth/authorize?client_id=8f14e45f&response_type=code&state=eyJhbGciOiJIUzI1NiJ9"
    }
  }
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Retrieve a list of marketing integration folders

GET
https://api.tintup.com/v2/teams/{team_id}/marketing_integrations/{marketing_integration_id}/folders

A folder is a remote group or collection that can be accessed directly using the specified marketing integration's credentials. Use a folder's id as the folder_id when creating marketing integration requests. Sources without folders return an empty list.

Parameters

team_idintegerrequiredpath

The ID of the team.

marketing_integration_idintegerrequiredpath

The ID of the marketing integration.

Response

200OKobject

A list of folders in the marketing integration. This list is not paginated.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: marketing_integrations:write

Retrieve a list of marketing integration folders
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/marketing_integrations/{marketing_integration_id}/folders'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/marketing_integrations/{marketing_integration_id}/folders', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/marketing_integrations/{marketing_integration_id}/folders')
data = response.json()
{
  "data": [
    {
      "id": "41736560",
      "type": "marketing_integration_folder",
      "attributes": {
        "name": "Marketing assets"
      }
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Authenticate a marketing integration

GET
https://api.tintup.com/v2/teams/{team_id}/marketing_integrations/new

Returns the URL of the third-party authorization page for the requested source. Open this URL (usually in a popup window) so the user can grant access. Once the user completes the authorization flow, the marketing integration is created and the result is delivered using the origin or redirect_uri options.

Parameters

team_idintegerrequiredpath

The ID of the team.

sourcestringdropboxfacebookgoogle_drivehubspotmailchimprequiredquery

The source of the marketing integration to authenticate.

sitestring<uri>query

The API endpoint to use, for sources that require one.

originstring<uri>query

When specified, once the user completes the authorization flow, the callback page posts a message to window.opener using window.postMessage with this value as the target origin. The message is a JSON string of the form {"type": "marketing_integration_new", "data": <response body>, "status": <HTTP status>} (marketing_integration_edit when reauthenticating), where the response body is the marketing integration (or errors).

redirect_uristring<uri>query

When specified, once the user completes the authorization flow, the user is redirected to this URI with a data query parameter containing the same JSON message as for origin, encoded using Base64. Takes precedence over origin.

Response

200OKobject

The URL of the third-party authorization page. Open it (usually in a popup window) so the user can grant access.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: marketing_integrations:write

Authenticate a marketing integration
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/marketing_integrations/new'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/marketing_integrations/new', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/marketing_integrations/new')
data = response.json()
{
  "data": {
    "id": "9e107d9d372bb6826bd81d3542a419d6",
    "type": "redirect",
    "attributes": {
      "url": "https://auth.example.com/oauth/authorize?client_id=8f14e45f&response_type=code&state=eyJhbGciOiJIUzI1NiJ9"
    }
  }
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}

Create marketing integration requests

POST
https://api.tintup.com/v2/teams/{team_id}/marketing_integrations/{marketing_integration_id}/requests

Asynchronously publishes assets or collections to a marketing integration. One request is created per published asset (publishing a collection creates one request per asset in the collection).

Body

application/vnd.api+json

The assets or collections to publish. Send a single resource with application/vnd.api+json, or several at once with application/vnd.api+json; ext=bulk. If any of them is invalid, nothing is created.

application/vnd.api+jsonobject
dataNewMarketingIntegrationRequestrequired

Publishes an asset, or every asset of a collection, to a folder of the marketing integration.

Show child attributes
typestringmarketing_integration_requestrequired

The resource type.

attributesobjectrequired
Show child attributes
asset_idintegerwrite only

The ID of the asset to publish. Required unless collection_id is provided; can't be combined with collection_id.

collection_idintegerwrite only

The ID of a collection whose assets are all published (one request is created per asset). Required unless asset_id is provided; can't be combined with asset_id.

folder_idstringrequired

The ID of the folder at the source to upload to, as returned by Retrieve a list of marketing integration folders.

marketing_integration_idintegerwrite only

Defaults to the marketing integration in the path. If provided, it must be a marketing integration of the team; the asset is still published to the marketing integration in the path.

application/vnd.api+json; ext=bulkobject
dataArray<NewMarketingIntegrationRequest>required
Show child attributes
typestringmarketing_integration_requestrequired

The resource type.

attributesobjectrequired
Show child attributes
asset_idintegerwrite only

The ID of the asset to publish. Required unless collection_id is provided; can't be combined with collection_id.

collection_idintegerwrite only

The ID of a collection whose assets are all published (one request is created per asset). Required unless asset_id is provided; can't be combined with asset_id.

folder_idstringrequired

The ID of the folder at the source to upload to, as returned by Retrieve a list of marketing integration folders.

marketing_integration_idintegerwrite only

Defaults to the marketing integration in the path. If provided, it must be a marketing integration of the team; the asset is still published to the marketing integration in the path.

Parameters

team_idintegerrequiredpath

The ID of the team.

marketing_integration_idintegerrequiredpath

The ID of the marketing integration.

Response

202Acceptedobject

The marketing integration requests that were created, one per published asset. The uploads happen asynchronously; each request starts as pending.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: marketing_integrations_requests:write

Create marketing integration requests
curl -X POST 'https://api.tintup.com/v2/teams/{team_id}/marketing_integrations/{marketing_integration_id}/requests' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "marketing_integration_request",
      "attributes": {
        "asset_id": 2750981,
        "folder_id": "41736560"
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/marketing_integrations/{marketing_integration_id}/requests', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "marketing_integration_request",
        "attributes": {
          "asset_id": 2750981,
          "folder_id": "41736560"
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "marketing_integration_request",
    "attributes": {
      "asset_id": 2750981,
      "folder_id": "41736560"
    }
  }
}

response = requests.post('https://api.tintup.com/v2/teams/{team_id}/marketing_integrations/{marketing_integration_id}/requests', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "marketing_integration_request",
    "attributes": {
      "asset_id": 2750981,
      "folder_id": "41736560"
    }
  }
}
{
  "data": [
    {
      "type": "marketing_integration_request",
      "attributes": {
        "asset_id": 2750981,
        "folder_id": "41736560"
      }
    },
    {
      "type": "marketing_integration_request",
      "attributes": {
        "collection_id": 1184,
        "folder_id": "41736560"
      }
    }
  ]
}
{
  "data": [
    {
      "id": "70412",
      "type": "marketing_integration_request",
      "attributes": {
        "status": "pending",
        "folder_id": "41736560"
      },
      "relationships": {
        "marketing_integration": {
          "data": {
            "id": "318",
            "type": "marketing_integration"
          },
          "meta": {
            "included": false
          }
        },
        "asset": {
          "data": {
            "id": "2750981",
            "type": "asset"
          },
          "meta": {
            "included": false
          }
        }
      }
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Publisher

group_publisher
Publisher

Campaigns

campaigns

Retrieve a list of campaigns

GET
https://api.tintup.com/v2/teams/{team_id}/campaigns

Returns the team's campaigns.

Parameters

team_idintegerrequiredpath

The ID of the team.

filterobjectquery

Filters the list of campaigns. All filters are combined with AND. Date filters accept ISO 8601 date-times and the operators $eq, $gt, $gte, $lt, and $lte, for example filter[starts_at][$gte]=2025-06-01T00:00:00Z.

sortstring-idquery

A comma-separated list of attributes to sort by (for example name, starts_at, ends_at, created_at). Prefix an attribute with - to sort in descending order.

pageobjectquery

Offset pagination. Use page[size] to set the number of items per page and page[number] to select a page. The response's links object contains ready-to-use URLs for the next and previous pages.

Response

200OKobject

A list of campaigns.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: campaigns:read

Retrieve a list of campaigns
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/campaigns'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/campaigns', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/campaigns')
data = response.json()
{
  "data": [
    {
      "id": "57",
      "type": "campaign",
      "attributes": {
        "name": "Summer collection",
        "starts_at": "2025-06-01T00:00:00.000Z",
        "ends_at": "2025-08-31T23:59:59.000Z",
        "label_color": "#f5a623",
        "created_at": "2025-03-14T16:42:07.000Z",
        "updated_at": "2025-03-14T16:42:07.000Z"
      },
      "links": {
        "self": "https://api.example.com/v2/teams/1024/campaigns/57"
      }
    }
  ],
  "links": {
    "self": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=2",
    "first": "https://api.tintup.com/v2/teams/1/tints",
    "next": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=3",
    "prev": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=1"
  }
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}

Create a campaign

POST
https://api.tintup.com/v2/teams/{team_id}/campaigns

Creates a campaign.

Body

application/vnd.api+json

The campaign to create.

dataNewCampaignrequired
Show child attributes
typestringcampaignrequired

The resource type.

attributesCampaignAttributes & objectrequired

Parameters

team_idintegerrequiredpath

The ID of the team.

Response

201Createdobject

The campaign.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: campaigns:write

Create a campaign
curl -X POST 'https://api.tintup.com/v2/teams/{team_id}/campaigns' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "campaign",
      "attributes": {
        "name": "Summer collection",
        "starts_at": "2025-06-01T00:00:00.000Z",
        "ends_at": "2025-08-31T23:59:59.000Z",
        "label_color": "#f5a623"
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/campaigns', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "campaign",
        "attributes": {
          "name": "Summer collection",
          "starts_at": "2025-06-01T00:00:00.000Z",
          "ends_at": "2025-08-31T23:59:59.000Z",
          "label_color": "#f5a623"
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "campaign",
    "attributes": {
      "name": "Summer collection",
      "starts_at": "2025-06-01T00:00:00.000Z",
      "ends_at": "2025-08-31T23:59:59.000Z",
      "label_color": "#f5a623"
    }
  }
}

response = requests.post('https://api.tintup.com/v2/teams/{team_id}/campaigns', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "campaign",
    "attributes": {
      "name": "Summer collection",
      "starts_at": "2025-06-01T00:00:00.000Z",
      "ends_at": "2025-08-31T23:59:59.000Z",
      "label_color": "#f5a623"
    }
  }
}
{
  "data": {
    "id": "57",
    "type": "campaign",
    "attributes": {
      "name": "Summer collection",
      "starts_at": "2025-06-01T00:00:00.000Z",
      "ends_at": "2025-08-31T23:59:59.000Z",
      "label_color": "#f5a623",
      "created_at": "2025-03-14T16:42:07.000Z",
      "updated_at": "2025-03-14T16:42:07.000Z"
    },
    "links": {
      "self": "https://api.example.com/v2/teams/1024/campaigns/57"
    }
  }
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Retrieve a campaign

GET
https://api.tintup.com/v2/teams/{team_id}/campaigns/{campaign_id}

Parameters

team_idintegerrequiredpath

The ID of the team.

campaign_idintegerrequiredpath

The ID of the campaign.

Response

200OKobject

The campaign.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: campaigns:read

Retrieve a campaign
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/campaigns/{campaign_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/campaigns/{campaign_id}', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/campaigns/{campaign_id}')
data = response.json()
{
  "data": {
    "id": "57",
    "type": "campaign",
    "attributes": {
      "name": "Summer collection",
      "starts_at": "2025-06-01T00:00:00.000Z",
      "ends_at": "2025-08-31T23:59:59.000Z",
      "label_color": "#f5a623",
      "created_at": "2025-03-14T16:42:07.000Z",
      "updated_at": "2025-03-14T16:42:07.000Z"
    },
    "links": {
      "self": "https://api.example.com/v2/teams/1024/campaigns/57"
    }
  }
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Delete a campaign

DELETE
https://api.tintup.com/v2/teams/{team_id}/campaigns/{campaign_id}

Deleting a campaign also removes it from the scheduled content it was associated with.

Parameters

team_idintegerrequiredpath

The ID of the team.

campaign_idintegerrequiredpath

The ID of the campaign.

Response

204No Content

No Content. The request succeeded and there is no response body.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: campaigns:write

Delete a campaign
curl -X DELETE 'https://api.tintup.com/v2/teams/{team_id}/campaigns/{campaign_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/campaigns/{campaign_id}', {
  method: 'DELETE',
});

const data = await response.json();
import requests

response = requests.delete('https://api.tintup.com/v2/teams/{team_id}/campaigns/{campaign_id}')
data = response.json()
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Update a campaign

PATCH
https://api.tintup.com/v2/teams/{team_id}/campaigns/{campaign_id}

Body

application/vnd.api+json

The campaign attributes to change.

dataCampaignUpdaterequired
Show child attributes
idstring

The ID of the campaign. Optional and ignored; the campaign in the path is updated.

typestringcampaignrequired

The resource type.

attributesCampaignAttributesrequired

The attributes to change. Omitted attributes keep their current values.

Parameters

team_idintegerrequiredpath

The ID of the team.

campaign_idintegerrequiredpath

The ID of the campaign.

Response

200OKobject

The campaign.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: campaigns:write

Update a campaign
curl -X PATCH 'https://api.tintup.com/v2/teams/{team_id}/campaigns/{campaign_id}' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "id": "57",
      "type": "campaign",
      "attributes": {
        "ends_at": "2025-09-15T23:59:59.000Z"
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/campaigns/{campaign_id}', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "id": "57",
        "type": "campaign",
        "attributes": {
          "ends_at": "2025-09-15T23:59:59.000Z"
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "id": "57",
    "type": "campaign",
    "attributes": {
      "ends_at": "2025-09-15T23:59:59.000Z"
    }
  }
}

response = requests.patch('https://api.tintup.com/v2/teams/{team_id}/campaigns/{campaign_id}', json=payload)
data = response.json()
Request Body
{
  "data": {
    "id": "57",
    "type": "campaign",
    "attributes": {
      "ends_at": "2025-09-15T23:59:59.000Z"
    }
  }
}
{
  "data": {
    "id": "57",
    "type": "campaign",
    "attributes": {
      "name": "Summer collection",
      "starts_at": "2025-06-01T00:00:00.000Z",
      "ends_at": "2025-08-31T23:59:59.000Z",
      "label_color": "#f5a623",
      "created_at": "2025-03-14T16:42:07.000Z",
      "updated_at": "2025-03-14T16:42:07.000Z"
    },
    "links": {
      "self": "https://api.example.com/v2/teams/1024/campaigns/57"
    }
  }
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}
Publisher

Scheduled Content

scheduled_contents

Retrieve a list of scheduled contents

GET
https://api.tintup.com/v2/teams/{team_id}/scheduled_contents

By default, only contents scheduled to be published in the last 14 days or later are returned; use filter[published_at] to change the range.

Parameters

team_idintegerrequiredpath

The ID of the team.

pageobjectquery

Offset pagination. Use page[size] to set the number of items per page and page[number] to select a page. The response's links object contains ready-to-use URLs for the next and previous pages.

includeArray<string>accountcampaignmediasubaccountteamquery

A comma-separated list of related resources to include in the response.

filterobjectquery

Filters that accept multiple values take a comma-separated list.

Response

200OKobject

A list of scheduled contents.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: scheduled_contents:read

Retrieve a list of scheduled contents
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/scheduled_contents'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/scheduled_contents', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/scheduled_contents')
data = response.json()
{
  "data": [
    {
      "id": "4821",
      "type": "scheduled_content",
      "attributes": {
        "status": "pending",
        "text": "Our spring collection drops Friday. Which color are you picking? 🌸",
        "published_at": "2025-03-14T16:42:07.000Z",
        "created_at": "2025-03-10T09:15:32.000Z",
        "updated_at": "2025-03-11T13:02:48.000Z",
        "tags": [
          "spring-launch",
          "instagram"
        ],
        "source": "instagram_business",
        "subaccount_id": "17841400008460056",
        "privacy": null,
        "options": {}
      },
      "relationships": {
        "media": {
          "data": [
            {
              "type": "upload",
              "id": "eyJfcmFpbHMiOnsiZGF0YSI6ODgyMTQsInB1ciI6ImJsb2JfaWQifX0=--7b1f0c7c3e5e0a9d2b6f4e1c8a3d5f7e9b2c4a6d"
            }
          ],
          "meta": {
            "included": false
          }
        },
        "account": {
          "data": {
            "type": "account",
            "id": "1375"
          },
          "meta": {
            "included": false
          }
        },
        "subaccount": {
          "data": {
            "type": "subaccount",
            "id": "17841400008460056"
          },
          "meta": {
            "included": false
          }
        },
        "team": {
          "data": {
            "type": "team",
            "id": "212"
          },
          "meta": {
            "included": false
          }
        },
        "campaign": {
          "data": {
            "type": "campaign",
            "id": "58"
          },
          "meta": {
            "included": false
          }
        }
      }
    }
  ],
  "links": {
    "self": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=2",
    "first": "https://api.tintup.com/v2/teams/1/tints",
    "next": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=3",
    "prev": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=1"
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}

Create a scheduled content

POST
https://api.tintup.com/v2/teams/{team_id}/scheduled_contents

Schedules content to be published to a connected account. Validation rules (required attributes, caption length and file limits) depend on the account's network.

Body

application/vnd.api+json

The content to schedule.

dataNewScheduledContentrequired
Show child attributes
typestringscheduled_contentrequired

The resource type.

attributesScheduledContentWritableAttributes & objectrequired

Parameters

team_idintegerrequiredpath

The ID of the team.

includeArray<string>accountcampaignmediasubaccountteamquery

A comma-separated list of related resources to include in the response.

Response

201Createdobject

The scheduled content.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: scheduled_contents:write

Create a scheduled content
curl -X POST 'https://api.tintup.com/v2/teams/{team_id}/scheduled_contents' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "scheduled_content",
      "attributes": {
        "text": "Our spring collection drops Friday. Which color are you picking? 🌸",
        "title": null,
        "tags": [
          "spring-launch",
          "instagram"
        ],
        "published_at": "2025-03-14T16:42:07.000Z",
        "media": [
          "eyJfcmFpbHMiOnsiZGF0YSI6ODgyMTQsInB1ciI6ImJsb2JfaWQifX0=--7b1f0c7c3e5e0a9d2b6f4e1c8a3d5f7e9b2c4a6d"
        ],
        "campaign_id": "58",
        "privacy": null,
        "options": {},
        "account_id": "1375",
        "subaccount_id": "17841400008460056"
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/scheduled_contents', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "scheduled_content",
        "attributes": {
          "text": "Our spring collection drops Friday. Which color are you picking? 🌸",
          "title": null,
          "tags": [
            "spring-launch",
            "instagram"
          ],
          "published_at": "2025-03-14T16:42:07.000Z",
          "media": [
            "eyJfcmFpbHMiOnsiZGF0YSI6ODgyMTQsInB1ciI6ImJsb2JfaWQifX0=--7b1f0c7c3e5e0a9d2b6f4e1c8a3d5f7e9b2c4a6d"
          ],
          "campaign_id": "58",
          "privacy": null,
          "options": {},
          "account_id": "1375",
          "subaccount_id": "17841400008460056"
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "scheduled_content",
    "attributes": {
      "text": "Our spring collection drops Friday. Which color are you picking? 🌸",
      "title": None,
      "tags": [
        "spring-launch",
        "instagram"
      ],
      "published_at": "2025-03-14T16:42:07.000Z",
      "media": [
        "eyJfcmFpbHMiOnsiZGF0YSI6ODgyMTQsInB1ciI6ImJsb2JfaWQifX0=--7b1f0c7c3e5e0a9d2b6f4e1c8a3d5f7e9b2c4a6d"
      ],
      "campaign_id": "58",
      "privacy": None,
      "options": {},
      "account_id": "1375",
      "subaccount_id": "17841400008460056"
    }
  }
}

response = requests.post('https://api.tintup.com/v2/teams/{team_id}/scheduled_contents', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "scheduled_content",
    "attributes": {
      "text": "Our spring collection drops Friday. Which color are you picking? 🌸",
      "title": null,
      "tags": [
        "spring-launch",
        "instagram"
      ],
      "published_at": "2025-03-14T16:42:07.000Z",
      "media": [
        "eyJfcmFpbHMiOnsiZGF0YSI6ODgyMTQsInB1ciI6ImJsb2JfaWQifX0=--7b1f0c7c3e5e0a9d2b6f4e1c8a3d5f7e9b2c4a6d"
      ],
      "campaign_id": "58",
      "privacy": null,
      "options": {},
      "account_id": "1375",
      "subaccount_id": "17841400008460056"
    }
  }
}
{
  "data": {
    "id": "4821",
    "type": "scheduled_content",
    "attributes": {
      "status": "pending",
      "text": "Our spring collection drops Friday. Which color are you picking? 🌸",
      "published_at": "2025-03-14T16:42:07.000Z",
      "created_at": "2025-03-10T09:15:32.000Z",
      "updated_at": "2025-03-11T13:02:48.000Z",
      "tags": [
        "spring-launch",
        "instagram"
      ],
      "source": "instagram_business",
      "subaccount_id": "17841400008460056",
      "privacy": null,
      "options": {}
    },
    "relationships": {
      "media": {
        "data": [
          {
            "type": "upload",
            "id": "eyJfcmFpbHMiOnsiZGF0YSI6ODgyMTQsInB1ciI6ImJsb2JfaWQifX0=--7b1f0c7c3e5e0a9d2b6f4e1c8a3d5f7e9b2c4a6d"
          }
        ],
        "meta": {
          "included": false
        }
      },
      "account": {
        "data": {
          "type": "account",
          "id": "1375"
        },
        "meta": {
          "included": false
        }
      },
      "subaccount": {
        "data": {
          "type": "subaccount",
          "id": "17841400008460056"
        },
        "meta": {
          "included": false
        }
      },
      "team": {
        "data": {
          "type": "team",
          "id": "212"
        },
        "meta": {
          "included": false
        }
      },
      "campaign": {
        "data": {
          "type": "campaign",
          "id": "58"
        },
        "meta": {
          "included": false
        }
      }
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Retrieve a scheduled content

GET
https://api.tintup.com/v2/teams/{team_id}/scheduled_contents/{scheduled_content_id}

Retrieves one of the team's scheduled contents.

Parameters

team_idintegerrequiredpath

The ID of the team.

scheduled_content_idintegerrequiredpath

The ID of the scheduled content.

includeArray<string>accountcampaignmediasubaccountteamquery

A comma-separated list of related resources to include in the response.

Response

200OKobject

The scheduled content.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: scheduled_contents:read

Retrieve a scheduled content
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/scheduled_contents/{scheduled_content_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/scheduled_contents/{scheduled_content_id}', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/scheduled_contents/{scheduled_content_id}')
data = response.json()
{
  "data": {
    "id": "4821",
    "type": "scheduled_content",
    "attributes": {
      "status": "pending",
      "text": "Our spring collection drops Friday. Which color are you picking? 🌸",
      "published_at": "2025-03-14T16:42:07.000Z",
      "created_at": "2025-03-10T09:15:32.000Z",
      "updated_at": "2025-03-11T13:02:48.000Z",
      "tags": [
        "spring-launch",
        "instagram"
      ],
      "source": "instagram_business",
      "subaccount_id": "17841400008460056",
      "privacy": null,
      "options": {}
    },
    "relationships": {
      "media": {
        "data": [
          {
            "type": "upload",
            "id": "eyJfcmFpbHMiOnsiZGF0YSI6ODgyMTQsInB1ciI6ImJsb2JfaWQifX0=--7b1f0c7c3e5e0a9d2b6f4e1c8a3d5f7e9b2c4a6d"
          }
        ],
        "meta": {
          "included": false
        }
      },
      "account": {
        "data": {
          "type": "account",
          "id": "1375"
        },
        "meta": {
          "included": false
        }
      },
      "subaccount": {
        "data": {
          "type": "subaccount",
          "id": "17841400008460056"
        },
        "meta": {
          "included": false
        }
      },
      "team": {
        "data": {
          "type": "team",
          "id": "212"
        },
        "meta": {
          "included": false
        }
      },
      "campaign": {
        "data": {
          "type": "campaign",
          "id": "58"
        },
        "meta": {
          "included": false
        }
      }
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Delete a scheduled content

DELETE
https://api.tintup.com/v2/teams/{team_id}/scheduled_contents/{scheduled_content_id}

Deletes the scheduled content.

Parameters

team_idintegerrequiredpath

The ID of the team.

scheduled_content_idintegerrequiredpath

The ID of the scheduled content.

Response

204No Content

No Content. The request succeeded and there is no response body.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: scheduled_contents:write

Delete a scheduled content
curl -X DELETE 'https://api.tintup.com/v2/teams/{team_id}/scheduled_contents/{scheduled_content_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/scheduled_contents/{scheduled_content_id}', {
  method: 'DELETE',
});

const data = await response.json();
import requests

response = requests.delete('https://api.tintup.com/v2/teams/{team_id}/scheduled_contents/{scheduled_content_id}')
data = response.json()
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Update a scheduled content

PATCH
https://api.tintup.com/v2/teams/{team_id}/scheduled_contents/{scheduled_content_id}

Only pending and failed scheduled contents can be updated; a success content returns 404.

Body

application/vnd.api+json

The attributes to change.

dataScheduledContentUpdaterequired

Only the attributes that are sent are changed; account_id and subaccount_id can't be changed. media is always replaced: omitting it removes the existing files.

Show child attributes
idstring

The ID of the scheduled content.

typestringscheduled_contentrequired

The resource type.

attributesScheduledContentWritableAttributesrequired
Show child attributes
textstring | null

The caption to publish. Required for every network except YouTube and Threads. Maximum length depends on the network: X (Twitter) 280, Threads 500, Facebook and Hootsuite 2,000, Instagram 2,200, LinkedIn 3,000, TikTok 150 and YouTube 5,000 characters.

titlestring | nullwrite only

The video title. Required for YouTube accounts and must be empty for every other network. Write-only: it isn't returned in responses.

tagsArray<string> | null

Internal labels used to organize and filter scheduled contents. They aren't published.

published_atstring<date-time> | null

When to publish the content. Must be in the future. When omitted on create, the content is published right away.

mediaArray<string> | nullwrite only

Signed IDs of the files to publish, as returned by a direct upload. The number of files and their type, size, duration, dimensions and aspect ratio are validated against the network's limits (for example, Instagram requires 1 to 10 files, X (Twitter) accepts up to 4, and TikTok and YouTube require exactly 1 video). Facebook posts with more than one file must only contain images. Write-only: published files are returned in the media relationship.

campaign_idstring | nullwrite only

The ID of a campaign of the team to associate the content with. Must be a string of digits.

privacyscheduledContentPrivacy | nulleveryonefollowersmutual_followersself_onlyunlistednull

Who can see the published content. Required for TikTok accounts (everyone, followers, mutual_followers or self_only; private TikTok accounts can't use everyone and public ones can't use followers) and YouTube accounts (everyone, self_only or unlisted). Must be empty (null) for every other network.

optionsScheduledContentOptions

Network-specific publishing options. Only used by TikTok; each option must be false (or omitted) when the TikTok account has disabled the corresponding interaction.

Show child attributes
allow_commentsboolean | null

Whether viewers can comment on the TikTok video.

allow_combineboolean | null

Whether viewers can use the TikTok video in a Stitch.

allow_side_by_sideboolean | null

Whether viewers can use the TikTok video in a Duet.

Parameters

team_idintegerrequiredpath

The ID of the team.

scheduled_content_idintegerrequiredpath

The ID of the scheduled content.

includeArray<string>accountcampaignmediasubaccountteamquery

A comma-separated list of related resources to include in the response.

Response

200OKobject

The scheduled content.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

404Not Foundx-errors

Not Found.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: scheduled_contents:write

Update a scheduled content
curl -X PATCH 'https://api.tintup.com/v2/teams/{team_id}/scheduled_contents/{scheduled_content_id}' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "id": "4821",
      "type": "scheduled_content",
      "attributes": {
        "text": "Our spring collection drops Friday. Which color are you picking? 🌸",
        "title": null,
        "tags": [
          "spring-launch",
          "instagram"
        ],
        "published_at": "2025-03-14T16:42:07.000Z",
        "media": [
          "eyJfcmFpbHMiOnsiZGF0YSI6ODgyMTQsInB1ciI6ImJsb2JfaWQifX0=--7b1f0c7c3e5e0a9d2b6f4e1c8a3d5f7e9b2c4a6d"
        ],
        "campaign_id": "58",
        "privacy": null,
        "options": {}
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/scheduled_contents/{scheduled_content_id}', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "id": "4821",
        "type": "scheduled_content",
        "attributes": {
          "text": "Our spring collection drops Friday. Which color are you picking? 🌸",
          "title": null,
          "tags": [
            "spring-launch",
            "instagram"
          ],
          "published_at": "2025-03-14T16:42:07.000Z",
          "media": [
            "eyJfcmFpbHMiOnsiZGF0YSI6ODgyMTQsInB1ciI6ImJsb2JfaWQifX0=--7b1f0c7c3e5e0a9d2b6f4e1c8a3d5f7e9b2c4a6d"
          ],
          "campaign_id": "58",
          "privacy": null,
          "options": {}
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "id": "4821",
    "type": "scheduled_content",
    "attributes": {
      "text": "Our spring collection drops Friday. Which color are you picking? 🌸",
      "title": None,
      "tags": [
        "spring-launch",
        "instagram"
      ],
      "published_at": "2025-03-14T16:42:07.000Z",
      "media": [
        "eyJfcmFpbHMiOnsiZGF0YSI6ODgyMTQsInB1ciI6ImJsb2JfaWQifX0=--7b1f0c7c3e5e0a9d2b6f4e1c8a3d5f7e9b2c4a6d"
      ],
      "campaign_id": "58",
      "privacy": None,
      "options": {}
    }
  }
}

response = requests.patch('https://api.tintup.com/v2/teams/{team_id}/scheduled_contents/{scheduled_content_id}', json=payload)
data = response.json()
Request Body
{
  "data": {
    "id": "4821",
    "type": "scheduled_content",
    "attributes": {
      "text": "Our spring collection drops Friday. Which color are you picking? 🌸",
      "title": null,
      "tags": [
        "spring-launch",
        "instagram"
      ],
      "published_at": "2025-03-14T16:42:07.000Z",
      "media": [
        "eyJfcmFpbHMiOnsiZGF0YSI6ODgyMTQsInB1ciI6ImJsb2JfaWQifX0=--7b1f0c7c3e5e0a9d2b6f4e1c8a3d5f7e9b2c4a6d"
      ],
      "campaign_id": "58",
      "privacy": null,
      "options": {}
    }
  }
}
{
  "data": {
    "id": "4821",
    "type": "scheduled_content",
    "attributes": {
      "status": "pending",
      "text": "Our spring collection drops Friday. Which color are you picking? 🌸",
      "published_at": "2025-03-14T16:42:07.000Z",
      "created_at": "2025-03-10T09:15:32.000Z",
      "updated_at": "2025-03-11T13:02:48.000Z",
      "tags": [
        "spring-launch",
        "instagram"
      ],
      "source": "instagram_business",
      "subaccount_id": "17841400008460056",
      "privacy": null,
      "options": {}
    },
    "relationships": {
      "media": {
        "data": [
          {
            "type": "upload",
            "id": "eyJfcmFpbHMiOnsiZGF0YSI6ODgyMTQsInB1ciI6ImJsb2JfaWQifX0=--7b1f0c7c3e5e0a9d2b6f4e1c8a3d5f7e9b2c4a6d"
          }
        ],
        "meta": {
          "included": false
        }
      },
      "account": {
        "data": {
          "type": "account",
          "id": "1375"
        },
        "meta": {
          "included": false
        }
      },
      "subaccount": {
        "data": {
          "type": "subaccount",
          "id": "17841400008460056"
        },
        "meta": {
          "included": false
        }
      },
      "team": {
        "data": {
          "type": "team",
          "id": "212"
        },
        "meta": {
          "included": false
        }
      },
      "campaign": {
        "data": {
          "type": "campaign",
          "id": "58"
        },
        "meta": {
          "included": false
        }
      }
    }
  }
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Retrieve aggregations for scheduled contents

GET
https://api.tintup.com/v2/teams/{team_id}/scheduled_contents/aggregations

Returns the number of scheduled contents of the team per tag, account and subaccount, across all statuses and dates.

Parameters

team_idintegerrequiredpath

The ID of the team.

Response

200OKobject

The number of scheduled contents of the team per tag, account and subaccount.

401Unauthorizedx-errors

Unauthorized. The access token is missing, invalid, expired or revoked.

403Forbiddenx-errors

Forbidden. The access token doesn't have the required scope, the user isn't allowed to perform this action, or the id_token is missing or invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: scheduled_contents:read

Retrieve aggregations for scheduled contents
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/scheduled_contents/aggregations'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/scheduled_contents/aggregations', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/scheduled_contents/aggregations')
data = response.json()
{
  "data": [
    {
      "id": "account_ids",
      "type": "aggregation",
      "attributes": {
        "buckets": {
          "1375": 42,
          "1402": 7
        }
      }
    }
  ]
}
{
  "errors": [
    {
      "code": "401",
      "title": "Unauthorized",
      "status": "401"
    }
  ]
}
{
  "errors": [
    {
      "code": "4030000",
      "title": "Forbidden",
      "status": "403"
    }
  ]
}

Webhooks

group_webhooks
Webhooks

Webhooks

webhooks

A webhook subscribes to exactly one event. Create a separate webhook per event, which lets each one carry its own filter, serialization and body settings. See Receiving Webhooks for how events are delivered, and Webhook Events for what each event contains.

Beyond the endpoint and the event, a webhook can set a filter, the HTTP method, extra request headers, which related resources to include, which fields to keep, and a Liquid template that reshapes the body entirely.

Retrieve a list of webhooks

GET
https://api.tintup.com/v2/teams/{team_id}/webhooks

Returns the webhooks the current user has access to.

Parameters

team_idintegerrequiredpath

The ID of the team.

pageobjectquery

Offset pagination. Use page[size] to set the number of items per page and page[number] to select a page. The response's links object contains ready-to-use URLs for the next and previous pages.

sortstring-idquery

A comma-separated list of fields to sort by. Prefix a field with - to sort in descending order. Defaults to -id (newest first).

Response

200OKobject

A list of webhooks.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: webhooks:read

Retrieve a list of webhooks
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/webhooks'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/webhooks', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/webhooks')
data = response.json()
200
{
  "data": [
    {
      "id": "1",
      "type": "webhook",
      "attributes": {
        "url": "https://hooks.example.com/trueloyal",
        "description": "Sync new UGC assets to our DAM.",
        "events": [
          "asset_created"
        ],
        "status": "active",
        "version": 20190326,
        "signing_secret": "whsec_8f14e45fceea167a5a36dedd4bea2543",
        "filter": {
          "form_id": "2012",
          "created_at": {
            "$gte": "2025-01-01T00:00:00Z"
          }
        },
        "http_method": "post",
        "headers": {
          "Authorization": "Bearer 3f2a9c71d04b"
        },
        "payload_include": [
          "object.person"
        ],
        "payload_fields": {
          "form_submission": [
            "data",
            "created_at",
            "person"
          ]
        },
        "payload_transformation_template": "{\"text\": \"New submission {{ data.relationships.object.data.id }}\"}",
        "created_at": "2020-01-01T00:00:00.000Z",
        "updated_at": "2020-01-01T00:00:00.000Z"
      }
    }
  ],
  "links": {
    "self": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=2",
    "first": "https://api.tintup.com/v2/teams/1/tints",
    "next": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=3",
    "prev": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=1"
  }
}

Create a webhook

POST
https://api.tintup.com/v2/teams/{team_id}/webhooks

The new webhook is shared with the roles that are granted access to new webhooks and with the current user's role.

Body

application/vnd.api+json

The webhook to create.

dataNewWebhookrequired
Show child attributes
typestringwebhookrequired
attributesWebhookAttributes & objectrequired

Parameters

team_idintegerrequiredpath

The ID of the team.

Response

201Createdobject

The webhook was created.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: webhooks:write

Create a webhook
curl -X POST 'https://api.tintup.com/v2/teams/{team_id}/webhooks' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "type": "webhook",
      "attributes": {
        "url": "https://hooks.example.com/trueloyal",
        "description": "Forward new contest entries to our CRM.",
        "events": [
          "form_submission_created"
        ],
        "signing_secret": "whsec_8f14e45fceea167a5a36dedd4bea2543",
        "filter": {
          "experience_id": "2012"
        },
        "payload_include": [
          "object.person"
        ],
        "payload_fields": {
          "form_submission": [
            "data",
            "created_at",
            "person"
          ]
        }
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/webhooks', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "type": "webhook",
        "attributes": {
          "url": "https://hooks.example.com/trueloyal",
          "description": "Forward new contest entries to our CRM.",
          "events": [
            "form_submission_created"
          ],
          "signing_secret": "whsec_8f14e45fceea167a5a36dedd4bea2543",
          "filter": {
            "experience_id": "2012"
          },
          "payload_include": [
            "object.person"
          ],
          "payload_fields": {
            "form_submission": [
              "data",
              "created_at",
              "person"
            ]
          }
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "type": "webhook",
    "attributes": {
      "url": "https://hooks.example.com/trueloyal",
      "description": "Forward new contest entries to our CRM.",
      "events": [
        "form_submission_created"
      ],
      "signing_secret": "whsec_8f14e45fceea167a5a36dedd4bea2543",
      "filter": {
        "experience_id": "2012"
      },
      "payload_include": [
        "object.person"
      ],
      "payload_fields": {
        "form_submission": [
          "data",
          "created_at",
          "person"
        ]
      }
    }
  }
}

response = requests.post('https://api.tintup.com/v2/teams/{team_id}/webhooks', json=payload)
data = response.json()
Request Body
{
  "data": {
    "type": "webhook",
    "attributes": {
      "url": "https://hooks.example.com/trueloyal",
      "description": "Forward new contest entries to our CRM.",
      "events": [
        "form_submission_created"
      ],
      "signing_secret": "whsec_8f14e45fceea167a5a36dedd4bea2543",
      "filter": {
        "experience_id": "2012"
      },
      "payload_include": [
        "object.person"
      ],
      "payload_fields": {
        "form_submission": [
          "data",
          "created_at",
          "person"
        ]
      }
    }
  }
}
{
  "data": {
    "id": "1",
    "type": "webhook",
    "attributes": {
      "url": "https://hooks.example.com/trueloyal",
      "description": "Sync new UGC assets to our DAM.",
      "events": [
        "asset_created"
      ],
      "status": "active",
      "version": 20190326,
      "signing_secret": "whsec_8f14e45fceea167a5a36dedd4bea2543",
      "filter": {
        "form_id": "2012",
        "created_at": {
          "$gte": "2025-01-01T00:00:00Z"
        }
      },
      "http_method": "post",
      "headers": {
        "Authorization": "Bearer 3f2a9c71d04b"
      },
      "payload_include": [
        "object.person"
      ],
      "payload_fields": {
        "form_submission": [
          "data",
          "created_at",
          "person"
        ]
      },
      "payload_transformation_template": "{\"text\": \"New submission {{ data.relationships.object.data.id }}\"}",
      "created_at": "2020-01-01T00:00:00.000Z",
      "updated_at": "2020-01-01T00:00:00.000Z"
    }
  }
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}

Retrieve a webhook

GET
https://api.tintup.com/v2/teams/{team_id}/webhooks/{webhook_id}

Retrieves one of the team's webhooks.

Parameters

team_idintegerrequiredpath

The ID of the team.

webhook_idintegerrequiredpath

The ID of the webhook.

Response

200OKobject

The webhook.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: webhooks:read

Retrieve a webhook
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/webhooks/{webhook_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/webhooks/{webhook_id}', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/webhooks/{webhook_id}')
data = response.json()
{
  "data": {
    "id": "1",
    "type": "webhook",
    "attributes": {
      "url": "https://hooks.example.com/trueloyal",
      "description": "Sync new UGC assets to our DAM.",
      "events": [
        "asset_created"
      ],
      "status": "active",
      "version": 20190326,
      "signing_secret": "whsec_8f14e45fceea167a5a36dedd4bea2543",
      "filter": {
        "form_id": "2012",
        "created_at": {
          "$gte": "2025-01-01T00:00:00Z"
        }
      },
      "http_method": "post",
      "headers": {
        "Authorization": "Bearer 3f2a9c71d04b"
      },
      "payload_include": [
        "object.person"
      ],
      "payload_fields": {
        "form_submission": [
          "data",
          "created_at",
          "person"
        ]
      },
      "payload_transformation_template": "{\"text\": \"New submission {{ data.relationships.object.data.id }}\"}",
      "created_at": "2020-01-01T00:00:00.000Z",
      "updated_at": "2020-01-01T00:00:00.000Z"
    }
  }
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Delete a webhook

DELETE
https://api.tintup.com/v2/teams/{team_id}/webhooks/{webhook_id}

Deleting a webhook also deletes its events.

Parameters

team_idintegerrequiredpath

The ID of the team.

webhook_idintegerrequiredpath

The ID of the webhook.

Response

204No Content

No Content. The request succeeded and there is no response body.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: webhooks:write

Delete a webhook
curl -X DELETE 'https://api.tintup.com/v2/teams/{team_id}/webhooks/{webhook_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/webhooks/{webhook_id}', {
  method: 'DELETE',
});

const data = await response.json();
import requests

response = requests.delete('https://api.tintup.com/v2/teams/{team_id}/webhooks/{webhook_id}')
data = response.json()
404
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Update a webhook

PATCH
https://api.tintup.com/v2/teams/{team_id}/webhooks/{webhook_id}

Updates the webhook.

Body

application/vnd.api+json

The webhook changes. Only the attributes you send are changed.

dataIdAsString & objectrequired

Parameters

team_idintegerrequiredpath

The ID of the team.

webhook_idintegerrequiredpath

The ID of the webhook.

Response

200OKobject

The webhook.

404Not Foundx-errors

Not Found.

422Unprocessable Entityx-errors

Unprocessable Entity. The request is missing required parameters or the resource is invalid.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: webhooks:write

Update a webhook
curl -X PATCH 'https://api.tintup.com/v2/teams/{team_id}/webhooks/{webhook_id}' \
  -H 'Content-Type: application/vnd.api+json' \
  -d '{
    "data": {
      "id": "15",
      "type": "webhook",
      "attributes": {
        "status": "inactive"
      }
    }
  }'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/webhooks/{webhook_id}', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/vnd.api+json',
  },
  body: JSON.stringify({
      "data": {
        "id": "15",
        "type": "webhook",
        "attributes": {
          "status": "inactive"
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "data": {
    "id": "15",
    "type": "webhook",
    "attributes": {
      "status": "inactive"
    }
  }
}

response = requests.patch('https://api.tintup.com/v2/teams/{team_id}/webhooks/{webhook_id}', json=payload)
data = response.json()
Request Body
{
  "data": {
    "id": "15",
    "type": "webhook",
    "attributes": {
      "status": "inactive"
    }
  }
}
{
  "data": {
    "id": "1",
    "type": "webhook",
    "attributes": {
      "url": "https://hooks.example.com/trueloyal",
      "description": "Sync new UGC assets to our DAM.",
      "events": [
        "asset_created"
      ],
      "status": "active",
      "version": 20190326,
      "signing_secret": "whsec_8f14e45fceea167a5a36dedd4bea2543",
      "filter": {
        "form_id": "2012",
        "created_at": {
          "$gte": "2025-01-01T00:00:00Z"
        }
      },
      "http_method": "post",
      "headers": {
        "Authorization": "Bearer 3f2a9c71d04b"
      },
      "payload_include": [
        "object.person"
      ],
      "payload_fields": {
        "form_submission": [
          "data",
          "created_at",
          "person"
        ]
      },
      "payload_transformation_template": "{\"text\": \"New submission {{ data.relationships.object.data.id }}\"}",
      "created_at": "2020-01-01T00:00:00.000Z",
      "updated_at": "2020-01-01T00:00:00.000Z"
    }
  }
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}
{
  "errors": [
    {
      "title": "Invalid name",
      "detail": "Name can't be blank",
      "source": {
        "pointer": "/data/attributes/name"
      }
    }
  ]
}
Webhooks

Webhook Event Log

webhook_events

Every event we send is recorded with the payload, its delivery status and, with include=attempts, each delivery attempt and your endpoint's response. Use these endpoints to debug your endpoint or to recover events you missed. The event id is the data.id of the payload.

Retrieve a list of webhook events

GET
https://api.tintup.com/v2/teams/{team_id}/webhooks/{webhook_id}/events

Returns the events recorded for a webhook, with the payload we sent and their delivery status.

Parameters

team_idintegerrequiredpath

The ID of the team.

webhook_idintegerrequiredpath

The ID of the webhook.

pageobjectquery

Offset pagination. Use page[size] to set the number of items per page and page[number] to select a page. The response's links object contains ready-to-use URLs for the next and previous pages.

filterobjectquery

Filters the webhook events.

sortstring-idquery

A comma-separated list of fields to sort by. Prefix a field with - to sort in descending order. Defaults to -id (newest first).

includeArray<string>attemptsquery

A comma-separated list of related resources to include. attempts returns the delivery attempts.

Response

200OKobject

A list of webhook events.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: webhooks:read

Retrieve a list of webhook events
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/webhooks/{webhook_id}/events'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/webhooks/{webhook_id}/events', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/webhooks/{webhook_id}/events')
data = response.json()
{
  "data": [
    {
      "id": "1",
      "type": "event",
      "attributes": {
        "payload": "{\"data\":{\"id\":\"1377451\",\"type\":\"event\",\"attributes\":{\"created_at\":\"2025-03-14T16:42:07.000Z\",\"name\":\"asset_created\"},\"relationships\":{\"object\":{\"data\":{\"type\":\"asset\",\"id\":\"5501\"}},\"team\":{\"data\":{\"type\":\"team\",\"id\":\"1\"}}}},\"included\":[]}",
        "status": "success",
        "version": 20190326,
        "created_at": "2020-01-01T00:00:00.000Z"
      },
      "relationships": {
        "attempts": {
          "data": [
            {
              "type": "attempt",
              "id": "2210987"
            }
          ],
          "meta": {
            "included": false
          }
        }
      }
    }
  ],
  "included": [
    {
      "id": "1",
      "type": "attempt",
      "attributes": {
        "webhook_url": "https://hooks.example.com/trueloyal",
        "response_status": "200",
        "response_body": "{\"received\":true}",
        "response_headers": {
          "content-type": "application/json"
        },
        "created_at": "2020-01-01T00:00:00.000Z"
      }
    }
  ],
  "links": {
    "self": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=2",
    "first": "https://api.tintup.com/v2/teams/1/tints",
    "next": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=3",
    "prev": "https://api.tintup.com/v2/teams/1/tints?page%5Bnumber%5D=1"
  }
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}

Retrieve a webhook event

GET
https://api.tintup.com/v2/teams/{team_id}/webhooks/{webhook_id}/events/{webhook_event_id}

Retrieves one of the webhook's events, with the payload we sent and its delivery status.

Parameters

team_idintegerrequiredpath

The ID of the team.

webhook_idintegerrequiredpath

The ID of the webhook.

webhook_event_idintegerrequiredpath

The ID of the webhook event (the data.id of the payload we sent).

includeArray<string>attemptsquery

A comma-separated list of related resources to include. attempts returns the delivery attempts.

Response

200OKobject

The webhook event.

404Not Foundx-errors

Not Found.

Authorization

access_tokenoauth2

OAuth 2.0 authorization code flow.

Scopes: webhooks:read

Retrieve a webhook event
curl -X GET 'https://api.tintup.com/v2/teams/{team_id}/webhooks/{webhook_id}/events/{webhook_event_id}'
const response = await fetch('https://api.tintup.com/v2/teams/{team_id}/webhooks/{webhook_id}/events/{webhook_event_id}', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://api.tintup.com/v2/teams/{team_id}/webhooks/{webhook_id}/events/{webhook_event_id}')
data = response.json()
{
  "data": {
    "id": "1",
    "type": "event",
    "attributes": {
      "payload": "{\"data\":{\"id\":\"1377451\",\"type\":\"event\",\"attributes\":{\"created_at\":\"2025-03-14T16:42:07.000Z\",\"name\":\"asset_created\"},\"relationships\":{\"object\":{\"data\":{\"type\":\"asset\",\"id\":\"5501\"}},\"team\":{\"data\":{\"type\":\"team\",\"id\":\"1\"}}}},\"included\":[]}",
      "status": "success",
      "version": 20190326,
      "created_at": "2020-01-01T00:00:00.000Z"
    },
    "relationships": {
      "attempts": {
        "data": [
          {
            "type": "attempt",
            "id": "2210987"
          }
        ],
        "meta": {
          "included": false
        }
      }
    }
  },
  "included": [
    {
      "id": "1",
      "type": "attempt",
      "attributes": {
        "webhook_url": "https://hooks.example.com/trueloyal",
        "response_status": "200",
        "response_body": "{\"received\":true}",
        "response_headers": {
          "content-type": "application/json"
        },
        "created_at": "2020-01-01T00:00:00.000Z"
      }
    }
  ]
}
{
  "errors": [
    {
      "code": "404",
      "title": "Not found",
      "status": "404"
    }
  ]
}