# About the iFrame
Source: https://developer.sendoso.com/iframe/abouttheiframe
With the Sendoso iFrame we handle the sending & user experience; you display it.
Embedding the Sendoso iFrame enables your user to use the power of Sendoso without leaving your own application. You can use the iFrame integration to:
* embed Sendoso into their internal CRM
* embed Sendoso into a channel partner application
* communicate with Sendoso outside of the Sendoso application
This can include a messaging application (see our Outreach use case) as well as a custom integration housed directly on your internal CRM like for example our [SalesLoft integration](https://sendoso.zendesk.com/hc/en-us/articles/115000872071-SalesLoft-Integration).
# Using the Sendoso iFrame
## Enable the iFrame Connection
To leverage the Sendoso iFrame, please email [developers@sendoso.com](mailto:developers@sendoso.com) with a summary of your use case and the URL for your application. Our team will work with you to authorize and host Sendoso iFrame within your application.
## Set up the Sendoso iFrame
1. Enable the Sendoso icon within your application/portal and create its associated iFrame link
2. Enable the Sendoso iFrame within your platform
3. Input required to send
* Sender Information
* Recipient Information
* Delivery Location
* For electronic gifts
* Recipient Email
* For physical gifts
* Recipient Name
* Street
* City
* State
* Country
* Postal Code (If applicable)
## iFrame Reference
* iFrame URL: [https://app.sendoso.com/v2/plugin/sends](https://app.sendoso.com/v2/plugin/sends)
* Setup URL(POST) Example: [https://app.sendoso.com/\{\{Custom}}/setup](https://app.sendoso.com/\{\{Custom}}/setup)
* iFrame Dimensions: width 435 px, height 500 px
* Sendoso icon: download the icon
The iFrame endpoint also supports optional URL parameters to prepopulate the recipient information within the send flow. A list of the URL parameters along with a description of each is below. All special characters must be HTML encoded.
| URL Param |
Description |
| name |
The recipient's full name |
| email |
The recipient's email address |
| address1 |
The recipient's street address |
| address2 |
The recipient's extended address (e.g., apartment or suite) |
| State |
The recipient's state |
| zip |
The recipient's postal code |
| country |
The recipient's country |
Example usage: [https://app.sendoso.com/v2/plugin/sends?email=\{email\_address}](https://app.sendoso.com/v2/plugin/sends?email=\{email_address})
# Authentication & Authorization
Source: https://developer.sendoso.com/marketplace/overview/authentication
## Introduction
Sendoso follows the standard OAuth 2.0 spec, using the Authorization Code grant type.
OAuth is an open standard for access delegation, commonly used as a way for Internet users to grant websites or applications access to their information on other websites but without giving them the passwords. This is known as a "two-legged" OAuth, or "two-step" authentication process. Refer to the [OAuth 2.0 Authorization Framework RFC: Section 4.1](https://www.rfc-editor.org/rfc/rfc6749#section-4.1) for additional details.
To authenticate with the Sendoso API using OAuth, you will need to first register your application and obtain a client ID and client secret. You can then use these credentials to request an access token from the Sendoso OAuth endpoint.
Once you have an access token, you can include it in the Authorization header of your API requests. For example, to make a GET request to the `GET /sends` endpoint, you would include the following header:
```js theme={null}
Authorization: Bearer YOUR_ACCESS_TOKEN
```
## Registering your application
To get started with the API, you’ll need a client ID and client secret. Request these credentials by contacting [developers@sendoso.com](mailto:developers@sendoso.com).
By default, the standard Postman redirect URI will be allowlisted. For production use, we recommend including your own redirect URI when reaching out to register your application.
## Authorization Flow
### 1. Direct user to authorization endpoint
The first step of the flow is to direct the user to the authorization endpoint providing as URL parameters its client identifier, requested scope, local state, and a redirection URI to which the authorization server will send the user-agent back once access is granted.
```js theme={null}
https://app.sendoso.com/oauth/authorize
```
The client identifier from your application (provided by Sendoso).
Client's redirection endpoint previously established with the authorization server during the client registration process.
Value MUST be set to "code".
The scope of the access request as described below.
An opaque value used by the client to maintain state between the request and callback. The authorization server includes this value when redirecting the user-agent back to the client. The parameter SHOULD be used for preventing cross-site request forgery.
#### Permission scopes
Sendoso's API supports the use of permissions scopes to specify the level of access that your application is requesting for a user's account. Scopes are used to grant access to specific resources or actions within the Sendoso platform.
When a user grants your application access to their account, they will also be prompted to grant specific scopes of access.
The available scopes for Sendoso API are:
* `public`: Allows your application to access the user's basic information.
* `write`: Allows your application to send gifts on the user's behalf.
* `update`: Allows your application to update the user's account details.
* `marketplace`: Allows your application to access the marketplace api.
* `smartsend`: Allows your application to access the smartsend api.
To request specific scopes, you can include them as a space-separated list in the scope parameter of the OAuth authorization request. For example, to request access to send gifts and to update user's account details, you would include the following scope parameter:
```js theme={null}
scope=write update
```
Please note that the user must grant your application access to each scope individually.
### 2. Authorization granted
After the user logs in and grants access to your application they will be redirected to the redirect URI specified in the previous step along with an authorization code as parameter named `code`.
### 3. Exchange code for access token
Once you have the `code` after the user granted access to your application, you need to exchange this code for an access token by making a `POST` to the endpoint and the body below:
```js theme={null}
https://app.sendoso.com/oauth/token
```
Value MUST be set to "authorization\_code".
The authorization code you just received
The same redirect URI that you initiated the flow with.
The client identifier from your application (provided by Sendoso).
The client secret from your application (provided by Sendoso).
The server will respond with an access token and a refresh token as follows:
```
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"access_token":"2YotnFZFEjr1zCsicMWpAA",
"token_type":"bearer",
"expires_in":7200,
"refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
"scope":"public"
"created_at":1693513711
}
```
The access token issued by the authorization server.
The type of the token issued. Value will ALWAYS be "bearer".
The lifetime in seconds of the access token. Value will ALWAYS be "7200". It denotes that the access token will expire in 2 hours from the time the token was created (see `created_at`)
The refresh token, which can be used to obtain new access tokens using the same authorization grant
The scope(s) granted to this specific token.
Timestamp when the token was created in the authorization server. Could be used to calculate when the token is set to expire.
You will need to use the access token in the Authorization header of your API requests:
```js theme={null}
Authorization: Bearer YOUR_ACCESS_TOKEN
```
## Refresh token
Please note that access tokens have a limited lifespan of 7200 seconds (2 hours) and will need to be refreshed.
To refresh your OAuth access token, you will need to make a `POST` request to the Sendoso OAuth token refresh endpoint:
```js theme={null}
https://app.sendoso.com/oauth/token
```
You will need to include the following parameters in the request body:
Value MUST be set to "refresh\_token".
The refresh token associated to the access token that you want to refresh.
The client identifier from your application (provided by Sendoso).
The client secret from your application (provided by Sendoso).
The server will respond with a new access token and refresh token as follows:
```
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"access_token":"2YotnFZFEjr1zCsicMWpAA",
"token_type":"bearer",
"expires_in":7200,
"refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
"scope":"public"
"created_at":1693513711
}
```
The new access token issued by the authorization server.
The type of the token issued. Value will ALWAYS be "bearer".
The lifetime in seconds of the access token. Value will ALWAYS be "7200". It denotes that the access token will expire in 2 hours from the time the token was created (see `created_at`)
The new refresh token, which can be used to obtain new access tokens using the same authorization grant
The scope(s) granted to this specific token.
Timestampt when the new token was created in the authorization server. Could be used to calculate when the token is set to expire.
Refresh tokens only expire after they are used
## Revoke access token
In order to revoke access tokens (and their associated refresh token), you can make a `POST` request to the following endpoint and parameters:
```
https://app.sendoso.com/oauth/revoke
```
**Headers:**
Basic authorization by base 64 encoding the application client id and client secret separated with ":". e.g. `Basic ENCODED_CLIENT_ID_AND_SECRET` where `ENCODED_CLIENT_ID_AND_SECRET` is the following operation `Base64(client_id:client_secret)`.
**Parameters:**
The access token that you want to revoke.
For example:
```bash theme={null}
curl --location \
--request POST 'https://app.sendoso.com/oauth/revoke?token=YOUR_ACCESS_TOKEN' \
--header 'Authorization: Basic ENCODED_CLIENT_ID_AND_SECRET'
```
# Introduction
Source: https://developer.sendoso.com/marketplace/overview/introduction
Send from a large selection of gifts and direct mail options.
Sendoso's Marketplace and SmartSend API allows you to send physical gifts and
direct mail to your customers, leads, and employees. With our API, you can
automate the sending of gifts and direct mail to your recipients.
With the power of SmartSend, you can have Sendoso decide the best gift to send
based on the recipient's interests and preferences.
To get started, you will first need to sign up for a Sendoso account and obtain
your API key. Once you have your API key, you can begin making API calls to
access and manipulate data within your Sendoso account.
Our API is organized around REST principles and is designed to have predictable,
resource-oriented URLs and to use HTTP response codes to indicate API errors. We
support both GET and POST requests, and all data is sent and received in JSON
format.
If you have any questions or need further assistance, please contact our support
team at [developers@sendoso.com](mailto:developers@sendoso.com).
# Rate Limits
Source: https://developer.sendoso.com/marketplace/overview/rate-limits
Sendoso's Marketplace / SmartSend APIs enforces rate limiting to ensure that the
resources of the platform are shared fairly among all users and to prevent abuse
or misuse of the API.
Rate limiting is based on the number of requests made by an application or user
within a given time period. Once the rate limit is exceeded, the API will return
a `429 Too Many Requests` response and the application will be temporarily
blocked from making further requests.
Currently, the rate limits for the Sendoso Marketplace and SmartSend APIs are as
100 requests per minute per user. If you exceed this limit, you will receive a
`429 Too Many Requests` response.
The APIs return a `X-Rate-Limit-Reset` header in the response, which indicates
the time at which the rate limit will reset. You can use this information to
determine when you can make requests again.
# Get Marketplace Products
Source: https://developer.sendoso.com/marketplace/reference/products/get-products
GET /api/v3/marketplace/products
Retrieves a paginated list of all products in the marketplace catalog.
### Required Auth Scopes
`marketplace`
### Parameters
The start for cursor for pagination. This is returned in the `pagination`
object of the previous response.
The minimum price of products in USD.
The maximum price of products in USD.
The country codes to ship to.
Category IDs to filter products by.
Filter products by exact text search.
### Response
Pagination information.
The cursor to use in the next request to fetch the next page of products.
The URL to fetch the next page of products.
List of group of nested categories in the marketplace for the result set.
The name of the group of categories.
List of categories in the group.
The category's identifier. This is used to filter products by category.
The category's name.
List of products in the marketplace
The product's identifier.
The product's name.
The product's description.
List of product variants
The variant's identifier.
The currency of the price.
The price per unit.
List of images
The image's URL.
The main image's URL on a CDN (recommended).
The thumbnail image's URL on a CDN.
# Send a Product (variant)
Source: https://developer.sendoso.com/marketplace/reference/products/send
POST /api/v3/marketplace/products/send
Send a product variant to a recipient.
### Required Auth Scopes
`marketplace` or `smartsend`
### Body
The catalog product variant ids (fetched from the marketplace) to be sent.
Note that currently only one product variant can be sent at a time. If more
than one product variant is sent, only the first one will be processed.
The email of the recipient.
The first name of the recipient.
The last name of the recipient.
The first name of the sender.
The last name of the sender.
The email of the sender.
The organization name of the sender.
An optional message to include with the product.
Optional parameter. If set to true, recipients will be able to exchange the gift for a similar value or lower value item available in the marketplace.
An optional URL to a meeting.
Optional parameter. If set to true, the send will be placed on hold for a manager to approve it from the send tracker.
### Response
The sent product variant ID.
The send ID.
# Get Gift Recommendations
Source: https://developer.sendoso.com/marketplace/reference/recommendations/get-recommendations
GET /api/v3/smartsend/recommendations
Retrieves a list of recommendations for a given recipient email.
### Required Auth Scopes
`smartsend`
### Parameters
The email of the recipient.
The maximum price of products in USD.
The country codes to ship to.
### Response
List of products in the marketplace
The product's identifier.
The product's name.
The product's description.
List of interests based on which the product was recommended.
List of product variants
The variant's identifier.
The currency of the price.
The price per unit.
List of images
The image's URL.
The main image's URL on a CDN (recommended).
The thumbnail image's URL on a CDN.
# Send a Recommendation
Source: https://developer.sendoso.com/marketplace/reference/recommendations/send
POST /api/v3/smartsend/recommendations/send
Automatically pick and send a recommendation to a recipient.
### Required Auth Scopes
`smartsend`
### Body
The email of the recipient.
The first name of the recipient.
The last name of the recipient.
Limit the maximum price of product in USD.
Restrict the products to ship to a specific country.
An optional message to include with the product.
Optional parameter. If set to true, recipients will be able to exchange the gift for a similar value or lower value item available in the marketplace.
An optional URL to a meeting.
Optional parameter. If set to true, the send will be placed on hold for a manager to approve it from the send tracker.
### Response
The sent product variant's ID.
The send ID.
# Authentication & Authorization
Source: https://developer.sendoso.com/rest-api/overview/authentication
## Introduction
Sendoso follows the standard OAuth 2.0 spec, using the Authorization Code grant type.
OAuth is an open standard for access delegation, commonly used as a way for Internet users to grant websites or applications access to their information on other websites but without giving them the passwords. This is known as a "two-legged" OAuth, or "two-step" authentication process. Refer to the [OAuth 2.0 Authorization Framework RFC: Section 4.1](https://www.rfc-editor.org/rfc/rfc6749#section-4.1) for additional details.
To authenticate with the Sendoso API using OAuth, you will need to first register your application and obtain a client ID and client secret. You can then use these credentials to request an access token from the Sendoso OAuth endpoint.
Once you have an access token, you can include it in the Authorization header of your API requests. For example, to make a GET request to the `GET /sends` endpoint, you would include the following header:
```js theme={null}
Authorization: Bearer YOUR_ACCESS_TOKEN
```
## Registering your application
To get started with the API, you’ll need a client ID and client secret. Request these credentials by contacting [developers@sendoso.com](mailto:developers@sendoso.com).
By default, the standard Postman redirect URI will be allowlisted. For production use, we recommend including your own redirect URI when reaching out to register your application.
## Authorization Flow
### 1. Direct user to authorization endpoint
The first step of the flow is to direct the user to the authorization endpoint providing as URL parameters its client identifier, requested scope, local state, and a redirection URI to which the authorization server will send the user-agent back once access is granted.
```js theme={null}
https://app.sendoso.com/oauth/authorize
```
The client identifier from your application (provided by Sendoso).
Client's redirection endpoint previously established with the authorization server during the client registration process.
Value MUST be set to "code".
The scope of the access request as described below.
An opaque value used by the client to maintain state between the request and callback. The authorization server includes this value when redirecting the user-agent back to the client. The parameter SHOULD be used for preventing cross-site request forgery.
#### Permission scopes
Sendoso's API supports the use of permissions scopes to specify the level of access that your application is requesting for a user's account. Scopes are used to grant access to specific resources or actions within the Sendoso platform.
When a user grants your application access to their account, they will also be prompted to grant specific scopes of access.
The available scopes for Sendoso API are:
* `public`: Allows your application to access the user's basic information.
* `write`: Allows your application to send gifts on the user's behalf.
* `update`: Allows your application to update the user's account details.
* `marketplace`: Allows your application to access the marketplace api.
* `smartsend`: Allows your application to access the smartsend api.
To request specific scopes, you can include them as a space-separated list in the scope parameter of the OAuth authorization request. For example, to request access to send gifts and to update user's account details, you would include the following scope parameter:
```js theme={null}
scope=write update
```
Please note that the user must grant your application access to each scope individually.
### 2. Authorization granted
After the user logs in and grants access to your application they will be redirected to the redirect URI specified in the previous step along with an authorization code as parameter named `code`.
### 3. Exchange code for access token
Once you have the `code` after the user granted access to your application, you need to exchange this code for an access token by making a `POST` to the endpoint and the body below:
```js theme={null}
https://app.sendoso.com/oauth/token
```
Value MUST be set to "authorization\_code".
The authorization code you just received
The same redirect URI that you initiated the flow with.
The client identifier from your application (provided by Sendoso).
The client secret from your application (provided by Sendoso).
The server will respond with an access token and a refresh token as follows:
```
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"access_token":"2YotnFZFEjr1zCsicMWpAA",
"token_type":"bearer",
"expires_in":7200,
"refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
"scope":"public"
"created_at":1693513711
}
```
The access token issued by the authorization server.
The type of the token issued. Value will ALWAYS be "bearer".
The lifetime in seconds of the access token. Value will ALWAYS be "7200". It denotes that the access token will expire in 2 hours from the time the token was created (see `created_at`)
The refresh token, which can be used to obtain new access tokens using the same authorization grant
The scope(s) granted to this specific token.
Timestamp when the token was created in the authorization server. Could be used to calculate when the token is set to expire.
You will need to use the access token in the Authorization header of your API requests:
```js theme={null}
Authorization: Bearer YOUR_ACCESS_TOKEN
```
## Refresh token
Please note that access tokens have a limited lifespan of 7200 seconds (2 hours) and will need to be refreshed.
To refresh your OAuth access token, you will need to make a `POST` request to the Sendoso OAuth token refresh endpoint:
```js theme={null}
https://app.sendoso.com/oauth/token
```
You will need to include the following parameters in the request body:
Value MUST be set to "refresh\_token".
The refresh token associated to the access token that you want to refresh.
The client identifier from your application (provided by Sendoso).
The client secret from your application (provided by Sendoso).
The server will respond with a new access token and refresh token as follows:
```
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"access_token":"2YotnFZFEjr1zCsicMWpAA",
"token_type":"bearer",
"expires_in":7200,
"refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
"scope":"public"
"created_at":1693513711
}
```
The new access token issued by the authorization server.
The type of the token issued. Value will ALWAYS be "bearer".
The lifetime in seconds of the access token. Value will ALWAYS be "7200". It denotes that the access token will expire in 2 hours from the time the token was created (see `created_at`)
The new refresh token, which can be used to obtain new access tokens using the same authorization grant
The scope(s) granted to this specific token.
Timestampt when the new token was created in the authorization server. Could be used to calculate when the token is set to expire.
Refresh tokens only expire after they are used
## Revoke access token
In order to revoke access tokens (and their associated refresh token), you can make a `POST` request to the following endpoint and parameters:
```
https://app.sendoso.com/oauth/revoke
```
**Headers:**
Basic authorization by base 64 encoding the application client id and client secret separated with ":". e.g. `Basic ENCODED_CLIENT_ID_AND_SECRET` where `ENCODED_CLIENT_ID_AND_SECRET` is the following operation `Base64(client_id:client_secret)`.
**Parameters:**
The access token that you want to revoke.
For example:
```bash theme={null}
curl --location \
--request POST 'https://app.sendoso.com/oauth/revoke?token=YOUR_ACCESS_TOKEN' \
--header 'Authorization: Basic ENCODED_CLIENT_ID_AND_SECRET'
```
# Frequently Asked Questions
Source: https://developer.sendoso.com/rest-api/overview/faq
### What happens if duplicate payloads are sent?
Sendoso does not handle duplicate payloads. Any order that is sent to Sendoso will be processed immediately.
### Does Sendoso throttle API requests in any manner?
Sendoso will throttle application clients sending more than 10 requests/second. If you have a use case that requires a higher limit, please contact [developers@sendoso.com](mailto:developers@sendoso.com).
### How does Sendoso handle history tracking?
Sendoso does not publish history via the API. However, any updates or sends completed via the API will be recorded in the platform.
### Can the API handle dynamic notes/templates?
Yes, dynamic text is supported for notes.
### Does the Sandbox environment mirror the Production environment?
The sandbox environment mirrors the production environment workflow except that the touch IDs will differ and package status will not be triggered beyond processing.
### How does the API interact with the platform?
The API and the platform are intimately connected. All adjustments made via the API will be registered in the Sendoso application. All items sent by the API will register on the Send Tracker tab of the platform.
### Can I change the notification email address?
No. Notifications are sent to the sender who is initiating the send.
### What is the Sendoso deployment schedule?
Sendoso has a zero-downtime deployment. Should you run into any issues, please email [developers@sendoso.com](mailto:developers@sendoso.com) with the environment, API request, error response, and timestamp.
# Introduction
Source: https://developer.sendoso.com/rest-api/overview/introduction
With the Sendoso API we handle the sending; you automate it.
Sendoso API allows you to integrate Sendoso's direct mail and gifting capabilities into your own application or platform. With our API, you can automate the sending of physical gifts and direct mail to your customers, leads, and employees.
You can use the API to:
* Programmatically trigger sends (e.g., re-activate stale leads in your pipeline)
* Embed sending functionality directly into custom forms
* Mass marketing outreach based on criteria you select
To get started, you will first need to sign up for a Sendoso account and obtain your API key. Once you have your API key, you can begin making API calls to access and manipulate data within your Sendoso account.
Our API is organized around REST principles and is designed to have predictable, resource-oriented URLs and to use HTTP response codes to indicate API errors. We support both GET and POST requests, and all data is sent and received in JSON format.
If you have any questions or need further assistance, please contact our support team at [developers@sendoso.com](mailto:developers@sendoso.com).
# Pagination
Source: https://developer.sendoso.com/rest-api/overview/pagination
Sendoso's API supports pagination for most of the GET endpoints to allow you to retrieve a large number of resources in smaller chunks. This can be useful when retrieving lists of resources, such as `sends` or `users`, that exceed the maximum number of resources that can be returned in a single response.
Pagination can be achieved by using the `page` and `page_size` query parameters in your API requests.
The page number of the results you want to retrieve. The first page is 1.
The number of resources to be returned per page.
For example, to retrieve the second page of `campaigns` with a page size of `50`, you would make the following GET request:
```js theme={null}
GET https://app.sendoso.com/campaigns?page=2&per_page=50
```
If your request returns a paginated result, the response will include the following fields at the root with the following pagination information:
The total number of resources available.
The number of resources per page.
The total number of resources available.
```js theme={null}
{
"campaigns": [...],
"current_page": 2,
"per_page": 50,
"total_campaigns": 234
}
```
# Rate Limits
Source: https://developer.sendoso.com/rest-api/overview/rate-limits
Sendoso's API enforces rate limiting to ensure that the resources of the platform are shared fairly among all users and to prevent abuse or misuse of the API.
Rate limiting is based on the number of requests made by an application or user within a given time period. Once the rate limit is exceeded, the API will return a `429 Too Many Requests` response and the application will be temporarily blocked from making further requests.
# Security
Source: https://developer.sendoso.com/rest-api/overview/security
Sendoso's API provides several security features to ensure that your data is protected and only accessible by authorized users.
## Authentication
Sendoso API uses Oauth standards to authenticate your API requests. The access token should be passed in the request headers for each API call. [See more information](/api/overview/authentication).
## Authorization
All requests to the Sendoso API are authorized based on the permissions associated with the Oauth application and the scopes available and requested. The permissions specify which resources the application has access to and what actions can be performed on those resources. [See more information](/api/overview/authentication).
## Security of transmitted data
All data sent to the Sendoso API is encrypted at REST with AES-256 standards and using HTTPS TLS 1.2 with RSA 256-bit, which ensures that the data is transmitted securely over the internet.
## Rate limiting
The Sendoso API has rate limits in place to prevent abuse and ensure fair usage of resources. If you exceed the rate limit, your IP address will be temporarily blocked from making further requests. [See more information](/api/overview/rate-limits).
## Logging
All requests to the Sendoso API are logged, including the IP address of the request, the request method, the resource requested, and the response status. This allows us to monitor for suspicious activity and detect any potential security breaches.
When you're done using the Sendoso API, it is recommended that you revoke your API key.
If you have any questions or concerns about the security of the Sendoso API, please contact the Sendoso support team at [developers@sendoso.com](mailto:developers@sendoso.com).
# Get Campaign
Source: https://developer.sendoso.com/rest-api/reference/campaigns/get-campaign
GET /api/v3/touches/{touch_id}
Retrieve additional details on a specific campaign.
### Parameters
The campaign identifier.
### Response
Whether or not the request was successful. Always `true` for 200 response.
The campaign's identifier.
The campaign's name.
The campaign's start date (in `ISO 8601` format). Gifts cannot be sent for this campaign before this start date.
The campaign's end date (in `ISO 8601` format). Gifts cannot be sent for this campaign after this end date.
The campaign's description.
The campaign's creation date (in `ISO 8601` format).
The identifier of the user that created this campaign.
The campaign's general gift identifier.
The campaign's `starting_egift_price` and `ending_egift_price` represent the range amount from which the sender can pick the egift denominiation to send. Only present for eGift campaigns. When this range is present, `is_default_price` will be false.
The campaign's `starting_egift_price` and `ending_egift_price` represent the range amount from which the sender can pick the egift denominiation to send. Only present for eGift campaigns. When this range is present, `is_default_price` will be false.
The campaign's status. It will ALWAYS be `Active` since this endpoint only returns active campaigns.
Whether or not the sender can pick the eGift amount from a range or if it is a set price.
The type of gift that is associated to this campaign. Valid options are `mail` which means physical item or `email` which means eGift.
The campaign's key to be used for HubSpot integration.
List of countries that this campaign's gift(s) can be sent to (in `ISO 3166-1` alpha-2 format).
The campaign's gift currency (in `ISO 4217` format).
```json 200 - Ok theme={null}
{
"success": true,
"touch": {
"id": 123456,
"name": "Sendoso Gift",
"start_date": "2023-10-25T00:00:00.000-07:00",
"end_date": null,
"description": "",
"created_at": "2023-10-25T05:21:59.000-07:00",
"user_id": 78901,
"gift_id": 39,
"starting_egift_price": null,
"ending_egift_price": null,
"status": "Active",
"is_default_price": true,
"delivery_type": "mail",
"hubspot_key": null,
"ship_to_countries": ["US", "ES", "CA"],
"currency": "USD"
}
}
```
```json 404 - Not Found theme={null}
{
"message": "Touch not found!"
}
```
# Get All Campaigns
Source: https://developer.sendoso.com/rest-api/reference/campaigns/get-campaigns
GET /api/v3/touches
Retrieve a list of all active campaigns associated to the organization.
### Parameters
The page number of the results you want to retrieve (the first page is 1). See [Pagination](https://developer.sendoso.com/rest-api/overview/pagination) for more information.
The number of campaigns to be returned per page (max is 100). See [Pagination](https://developer.sendoso.com/rest-api/overview/pagination) for more information.
Optional parameter to filter the results by the gift type. Valid options are `mail` which returns all physical item campaigns or `email` which returns all eGift campaigns.
### Response
The current page being returned (used for pagination purposes).
The number of results being returned per page (used for pagination purposes).
The total number of campaigns (used for pagination purposes).
List of campaigns
The campaign's identifier.
The campaign's name.
The campaign's start date (in `ISO 8601` format). Gifts cannot be sent for this campaign before this start date.
The campaign's end date (in `ISO 8601` format). Gifts cannot be sent for this campaign after this end date.
The campaign's description.
The campaign's creation date (in `ISO 8601` format).
The identifier of the user that created this campaign.
The campaign's general gift identifier.
The campaign's `starting_egift_price` and `ending_egift_price` represent the range amount from which the sender can pick the egift denominiation to send. Only present for eGift campaigns. When this range is present, `is_default_price` will be false.
The campaign's `starting_egift_price` and `ending_egift_price` represent the range amount from which the sender can pick the egift denominiation to send. Only present for eGift campaigns. When this range is present, `is_default_price` will be false.
The campaign's status. It will ALWAYS be `Active` since this endpoint only returns active campaigns.
Whether or not the sender can pick the eGift amount from a range or if it is a set price.
The type of gift that is associated to this campaign. Valid options are `mail` which means physical item or `email` which means eGift.
The campaign's key to be used for HubSpot integration.
List of countries that this campaign's gift(s) can be sent to (in `ISO 3166-1` alpha-2 format).
The campaign's gift currency (in `ISO 4217` format).
```json theme={null}
{
"current_page": 1,
"per_page": 1,
"total_posts": 5,
"touches": [
{
"id": 123456,
"name": "Sendoso Gift",
"start_date": "2023-10-25T00:00:00.000-07:00",
"end_date": null,
"description": "",
"created_at": "2023-10-25T05:21:59.000-07:00",
"user_id": 78901,
"gift_id": 39,
"starting_egift_price": null,
"ending_egift_price": null,
"status": "Active",
"is_default_price": true,
"delivery_type": "mail",
"hubspot_key": null,
"ship_to_countries": ["US", "ES", "CA"],
"currency": "USD"
}
]
}
```
# Send eGift via Sendoso Email
Source: https://developer.sendoso.com/rest-api/reference/sends/egift/eGift
POST /api/v3/send
This endpoint allows you to send an eGift directly to a recipient.
### Body
The ID of the campaign within Sendoso you are wanting to send.
The recipient's name.
The recipient's email.
The message that goes in the body of the eGift email.
Value must be `single_email_address`.
The name of the application making the send request. Please make sure this is consistent per application.
### Response
Whether or not the request was successful. Always `true` for 2xx responses.
Response message.
The send's unique tracking code.
The send's unique tracking URL.
```json Example Request theme={null}
{
"send": {
"touch_id": 123456,
"name": "John Smith",
"email": "developers@sendoso.com",
"custom_message": "Hi John, I wanted to personally invite you to...",
"via": "single_email_address",
"via_from": "YOUR APPLICATION NAME"
}
}
```
```json 200 - Success theme={null}
{
"success": true,
"message": "EGifts send Successfully",
"tracking_code": "df934732d35e597e87ca47990a6ada5c61f890fe",
"tracking_url": "https://app.sendoso.com/track/df934732d35e597e87ca47990a6ada5c61f890d6"
}
```
```json 400 - Bad Request theme={null}
{
"success": false,
"message": "email can't be blank"
}
```
```json 401 - Unauthorized theme={null}
{
"success": false,
"description": "The access token is invalid",
"expired": false
}
```
```json 404 - Not Found theme={null}
{
"success": false,
"message": "Touch not found"
}
```
# Generate eGift Links
Source: https://developer.sendoso.com/rest-api/reference/sends/egift/eGiftlink
POST /api/v3/send/generate_egift_links
This endpoint allows you to generate one or more eGift links to embed in your own outreach to the recipient(s).
Each recipient will have a unique link generated that is associated to the email you passed in the request
### Body
The ID of the campaign within Sendoso you are wanting to send.
Value must be `generate_egift_links`.
The name of the application making the send request. Please make sure this is consistent per application.
An array of recipient emails that you are generating the links for.
The recipient's email.
### Response
Whether or not the request was successful. Always `true` for 2xx responses.
Response message.
The sends links to share with the recipients.
The link generated for this specific recipient for you to embed in your own outreach.
The recipient's email or phone number associated to this link.
```json Example Request theme={null}
{
"send": {
"touch_id": 123456,
"via": "generate_egift_links",
"via_from": "Your Application Name",
"recipient_users": [
{
"email": "developers@sendoso.com"
},
{
"email": "developers2@sendoso.com"
}
]
}
}
```
```json 200 - Success theme={null}
{
"success": true,
"message": "Success! Here are your 2 eGift Card links:",
"egift_links": [
{
"egift_link": "https://sendo.so/g/NzOHQCUf9eqw0",
"recipient_email_or_phone_number": "developers@sendoso.com"
},
{
"egift_link": "https://sendo.so/g/9d91rKc7O3d4",
"recipient_email_or_phone_number": "developers2@sendoso.com"
}
],
"expiration_days": 30
}
```
```json 400 - Bad Request theme={null}
{
"success": false,
"message": "email can't be blank"
}
```
```json 401 - Unauthorized theme={null}
{
"success": false,
"message": "The access token is invalid",
}
```
```json 404 - Not Found theme={null}
{
"success": false,
"message": "Touch not found"
}
```
# Retrieve All Sends
Source: https://developer.sendoso.com/rest-api/reference/sends/get-sends
GET /api/v3/send
Retrieves a list of all sends initiated by anyone in the organization.
### Parameters
The page number of the results you want to retrieve (the first page is 1). See [Pagination](https://developer.sendoso.com/rest-api/overview/pagination) for more information.
The number of sends to be returned per page (max is 100). See [Pagination](https://developer.sendoso.com/rest-api/overview/pagination) for more information.
### Response
The current page being returned (used for pagination purposes).
The number of results being returned per page (used for pagination purposes).
The total number of sends (used for pagination purposes).
List of sends
The send's identifier.
The gid of the send.
The send's type. Possible values are `Amazon`, `Handwritten Notes`, `Inventoried Sends`, `Sendoso Choice`, `Sendoso Direct`, `eGifts International`, `eGifts USA`
The send's subtype. Possible values are `Bundles`, `Buy/Send via Amazon`, `Buy/Send via Amazon UK`, `Coffee`, `Custom`, `Custom Bundles`, `DDO_GIFT`, `Donate to Charity`, `Experiences`, `Handwritten Notes`, `Lunch`, `On-Demand`, `Visa eGift Credit Card (US)`, `Wine`, `eGift Cards Australia`, `eGift Cards Brazil`, `eGift Cards Canada`, `eGift Cards France`, `eGift Cards Germany`, `eGift Cards India`, `eGift Cards Ireland`, `eGift Cards Italy`, `eGift Cards Mexico`, `eGift Cards Netherlands`, `eGift Cards New Zealand`, `eGift Cards Poland`, `eGift Cards Singapore`, `eGift Cards Slovakia`, `eGift Cards UK`, `eGift Cards USA`
The send's gift currency (in `ISO 4217` format).
The send's cost at the time that this request was made. Note that this cost could change overtime until the send is in a final status.
The current send's status. Possible values are `Address Confirmation - Cancelled`, `Bounced and Credited`, `Cancelled`, `Clicked`, `Collecting recipient info`, `Confirming Address`, `Delivered`, `Expired and Credited`, `Failed`, `Opened`, `Packed`, `Paused`, `Processing`, `Refunded`, `Sent`, `Shipped`, `Undeliverable`, `Used`, `pending`.
The date and time the send was initiated (in `ISO 8601` format).
The campaign from which this send was initiated.
The campaign's identifier.
The campaign's name.
The recipient that the gifts were sent to.
The recipient's name.
The recipient's email.
The recipient's company name.
The user that initiated the send.
The sender user's identifier.
The sender's name.
The sender's email address.
The sender's team identifier.
The sender's team name.
Platform where the sent was initiated from.
List of the different send status changes and when they occurred.
The status that the send changed to
The date and time when the status change occurred (in `ISO 4217` format).
```json theme={null}
{
"current_page": 1,
"per_page": 10,
"total_count": 892,
"sends": [
{
"id": 1,
"send_gid": "Z2lkOi8vc2VuZG9zby9TZW5kLzQ0",
"type": "eGifts USA",
"subtype": "eGift Cards USA",
"currency": "USD",
"current_total_cost": "2.0",
"status": "Expired",
"created_at": "2022-09-12T12:08:27-07:00",
"touch": {
"id": 12,
"name": "eGift Cards USA"
},
"recipient": {
"name": "John Doe",
"email": "johndoe@acme.com",
"company_name": "Acme"
},
"sender": {
"id": 123,
"name": "Marc Fernandez",
"email": "marc.fernandez@sendoso.com",
"team_id": 123,
"team_name": "Marketing Ops"
},
"sent_via": "Sendoso.com",
"status_updates": [
{
"status": "Sent",
"occurred_at": "2022-09-12T12:08:27-07:00"
},
{
"status": "Opened",
"occurred_at": "2022-09-12T12:08:58-07:00"
},
{
"status": "Clicked",
"occurred_at": "2022-09-12T12:08:58-07:00"
},
{
"status": "Expired",
"occurred_at": "2022-12-11T00:00:02-08:00"
}
]
},
{
"id": 2,
"send_gid": "Z2lkOi8vc2VuZG9zby9TZW5kLzE",
"type": "Inventoried Sends",
"subtype": "Custom",
"currency": "USD",
"current_total_cost": "5.0",
"status": "Address Confirmation - Cancelled",
"created_at": "2022-12-21T23:37:22-08:00",
"touch": {
"id": 25,
"name": "Triggered inventory"
},
"recipient": {
"name": "Marc Fernandez Girones",
"email": "marc.fernandez@sendoso.com",
"company_name": "Sendoso"
},
"sender": {
"id": 123,
"name": "Marc Fernandez",
"email": "marc.fernandez@sendoso.com",
"team_id": 123,
"team_name": "Marketing Ops"
},
"sent_via": "Salesforce Trigger",
"status_updates": [
{
"status": "Confirming Address",
"occurred_at": "2022-12-22T05:42:27-08:00"
},
{
"status": "Address Confirmation - Cancelled",
"occurred_at": "2022-12-27T09:00:05-08:00"
}
]
}
]
}
```
# Send Physical Gift
Source: https://developer.sendoso.com/rest-api/reference/sends/physical/physical
POST /api/v3/send
This endpoint allows you to send a physical item directly to a recipient when their address is known.
### Body
The ID of the campaign within Sendoso you are wanting to send.
The recipient's name
The recipient's email address.
The recipient's street address.
The recipient's city.
The recipient's state.
The recipient's zip/postal code.
The recipient's country.
The recipient's phone number. Required for non-US addresses - sending a request to this endpoint without this parameter will fail for any non-US address.
The message that goes on the notecard in the gift box (if applicable).
Indicates if you are sending the address collection email. If are providing the recipient address, just send `false`.
Value must be `single_person_or_company`.
The name of the application making the send request. Please make sure this is consistent per application.
### Response
Whether or not the request was successful. Always `true` for 2xx responses.
Response message.
The send's unique tracking code.
```json Example Request theme={null}
{
"send": {
"touch_id": 123456,
"name": "John Smith",
"email": "developers@sendoso.com",
"address": "639 Front St, Floor 3",
"city": "San Francisco",
"state": "CA",
"zip": "94111",
"country": "USA",
"mobile_no": 1234567890,
"custom_message": "Hi John, I wanted to personally invite you to...",
"confirm_address": false,
"via": "single_person_or_company",
"via_from": "YOUR APPLICATION NAME"
}
}
```
```json 200 - Success theme={null}
{
"success": true,
"message": "Gift send Successfully",
"tracking_code": "116d64dc686937dd17b1865019cee71d295bcf38"
}
```
```json 400 - Bad Request theme={null}
{
"success": false,
"message": "email can't be blank"
}
```
```json 401 - Unauthorized theme={null}
{
"success": false,
"message": "The access token is invalid"
}
```
```json 404 - Not Found theme={null}
{
"success": false,
"message": "Touch not found"
}
```
# Send Physical Gift with Address Collection
Source: https://developer.sendoso.com/rest-api/reference/sends/physical/physicalAC
POST /api/v3/send
This endpoint allows you to send a physical item when you do not know the recipient address.
### Body
The ID of the campaign within Sendoso you are wanting to send.
The recipient's name
The recipient's email address.
The message that goes on the notecard in the gift box (if applicable).
Indicates whether the recipient's address is provided in the payload or not. Value must be `true`.
Indicates if you are sending the address collection email. Value must be `true`.
How the recipient will be asked to confirm their address. Options are `email`, which sends the recipient an email, or `link` which provides a link in the response, and sends a link to the sender's email address.
Whether or not the gift should be sent if the user does NOT confirm their address. For this endpoint, please leave as **FALSE**.
Sets the number of days the address collection form will be valid. Valid values are from `2` to `7` inclusive.
Determines whether or not the gift name & image will appear on the address collection page.
The message that is on the address collection email. **Note** - this is only applicable if you are sending the address collectionn via the email method.
Value must be `single_person_or_company`.
The name of the application making the send request. Please make sure this is consistent per application.
### Response
Whether or not the request was successful. Always `true` for 2xx responses.
Response message.
The send's unique tracking code.
```json Example Request theme={null}
{
"send":
{
"touch_id": 123456,
"name": "John Smith",
"email": "developers@sendoso.com",
"custom_message": "Hi John, I wanted to personally invite you to...",
"no_address": true,
"confirm_address": true,
"address_confirmation_via": "email",
"resume_with_unconfirmed_address": false,
"expire_after_days": 5,
"hide_product_info": true,
"address_confirmation_custom_message": "Please update your shipping address!",
"via": "single_person_or_company",
"via_from": "YOUR APPLICATION NAME"
}
}
```
```json 200 - Success theme={null}
{
"success": true,
"message": "Gift send Successfully",
"tracking_code": "116d64dc686937dd17b1865019cee71d295bcf38"
}
```
```json 400 - Bad Request theme={null}
{
"success": false,
"message": "email can't be blank"
}
```
```json 401 - Unauthorized theme={null}
{
"success": false,
"message": "The access token is invalid",
}
```
```json 404 - Not Found theme={null}
{
"success": false,
"message": "Touch not found"
}
```
# Get All Team Group Users
Source: https://developer.sendoso.com/rest-api/reference/teams/get-team-users
GET /api/v3/groups/{team_group_id}/members
Get the list of users for the specific team.
### Parameters
The team group id to get the users from
### Response
Array of user objects with the following properties:
The user's identifier
The user's first name
The user's last name
The user's email
The user's personal balance
Whether or not this user is a sandbox user or not
The user's team group id
The team's organization id
The user's invitation key - the user invitation identifier that was used by this user to sign up.
```json 200 - Ok theme={null}
[
{
"id": 12345,
"balance": "578.0",
"first_name": "Sendoso",
"last_name": "Devs",
"email": "developers@sendoso.com",
"team_group_id": 6789,
"team_id": 4321,
"sandbox": false,
"key": "b7afc3c89f84e56d4731f8d6c2c0c543"
},
{
"id": 987,
"balance": "500.0",
"first_name": "Sendoso",
"last_name": "Devs 2",
"email": "developers2@sendoso.com",
"team_group_id": 6789,
"team_id": 4321,
"sandbox": false,
"key": "3cd39d35349da5ec6a67a248c661asw4"
}
]
```
```json 404 - Not Found theme={null}
{
"message": "Group not found!"
}
```
# Get All Team Groups
Source: https://developer.sendoso.com/rest-api/reference/teams/get-teams
GET /api/v3/groups
Retrieve information of all the organization's active team groups.
### Parameters
The page number of the results you want to retrieve (the first page is 1). See [Pagination](https://developer.sendoso.com/rest-api/overview/pagination) for more information.
The number of users to be returned per page (max is 100). See [Pagination](https://developer.sendoso.com/rest-api/overview/pagination) for more information.
### Response
The current page being returned (used for pagination purposes).
The number of results being returned per page (used for pagination purposes).
The total number of team groups (used for pagination purposes).
List of team group objects
The team groups's identifier
The team groups's budget
The team group's creation date (in `ISO 8601` format)
The team group's monthly allocated budget
The team group's name
The team group's one time budget
Whether or not the monthly budget rolls over to the next month or not.
The team group's organization id
The team group's last updated date (in `ISO 8601` format)
```json theme={null}
{
"current_page": 1,
"per_page": 1,
"total_groups": 20,
"groups": [
{
"id": 1234,
"budget": 50,
"created_at": "2020-05-01T13:53:05.000-07:00",
"monthly_budget": "50000",
"name": "Field Marketing",
"one_time_budget": 0,
"rollover": true,
"team_id": 5678,
"updated_at": "2022-09-26T11:49:50.000-07:00"
}
]
}
```
# Get Current User
Source: https://developer.sendoso.com/rest-api/reference/users/get-current-user
GET /api/v3/me
Get information about the current authorized user.
### Response
The user's identifier
The user's first name
The user's last name
The user's email
The user's role
The user's personal balance
The sum of all the users balance
```json theme={null}
{
"id": 123456,
"first_name": "Sendoso",
"last_name": "Devs",
"email": "developers@sendoso.com",
"balance": "500.0",
"team_balance": 1543,
"role": "manager"
}
```
# Get All Users
Source: https://developer.sendoso.com/rest-api/reference/users/get-users
GET /api/v3/users
Retrieve a paginated list of all active users associated to the organization.
### Parameters
The page number of the results you want to retrieve (the first page is 1). See [Pagination](https://developer.sendoso.com/rest-api/overview/pagination) for more information.
The number of users to be returned per page (max is 100). See [Pagination](https://developer.sendoso.com/rest-api/overview/pagination) for more information.
### Response
The current page being returned (used for pagination purposes).
The number of results being returned per page (used for pagination purposes).
The total number of users (used for pagination purposes).
List of user objects
The user's identifier
The user's first name
The user's last name
The user's email
The user's team group id
```json theme={null}
{
"current_page": 1,
"per_page": 5,
"total_users": 20,
"users": [
{
"id": 12345,
"first_name": "Sendoso",
"last_name": "Devs",
"email": "developers@sendoso.com",
"team_group_id": 6789
}
]
}
```
# Invite New User
Source: https://developer.sendoso.com/rest-api/reference/users/invite-user
POST /api/v3/users
Create a new user invitation for a specific team group.
### Body
The new user's first name
The new user's last name
The new user's email address
The new user's role. Valid options are `regular` and `manager`.
The ID of the team you'd like to invite the user to. To obtain the ID of the current team's in Sendoso, use [Retrieve All Teams](https://developer.sendoso.com/rest-api/reference/teams/get-teams).
### Response
Wheter or not the invitation was successfully created
The response message
The email address that the invitation was addressed to
The team group id that the user was invited to
The role that the new user was invited with
The invitation's status. Valid values are `pending`, `accepted`, or `expired`.
The date & time when the invitation will expire (in `ISO 8601` format).
```json 201 - Created theme={null}
{
"success": true,
"message": "Invitation sent successfully",
"receiver_email": "devleopers@sendoso.com",
"team_group_id": 1234,
"user_role": "manager",
"invitation_status": "pending",
"expires_at": "2023-11-11T12:18:55.000-08:00"
}
```
```json 400 - Bad Request theme={null}
{
"success": false,
"message": "Please enter a valid team group"
}
```
```json 400 - Bad Request theme={null}
{
"success": false,
"message": "Role can be one of these: manager,regular"
}
```
# Authentication & Authorization
Source: https://developer.sendoso.com/scim/overview/authentication
## Introduction
Sendoso follows the standard OAuth 2.0 spec, using the Authorization Code grant type.
OAuth is an open standard for access delegation, commonly used as a way for Internet users to grant websites or applications access to their information on other websites but without giving them the passwords. This is known as a "two-legged" OAuth, or "two-step" authentication process. Refer to the [OAuth 2.0 Authorization Framework RFC: Section 4.1](https://www.rfc-editor.org/rfc/rfc6749#section-4.1) for additional details.
To authenticate with the Sendoso API using OAuth, you will need to first register your application and obtain a client ID and client secret. You can then use these credentials to request an access token from the Sendoso OAuth endpoint.
Once you have an access token, you can include it in the Authorization header of your API requests. For example, to make a GET request to the `GET /api/scim/v2/Users` endpoint, you would include the following header:
```js theme={null}
Authorization: Bearer YOUR_ACCESS_TOKEN
```
## Registering your application
In order to start using the SCIM API, you'll need a client id and client secret specific for the SCIM API. You can obtain those by contacting our support at [developers@sendoso.com](mailto:developers@sendoso.com)
## Authorization Flow
### 1. Direct user to authorization endpoint
The first step of the flow is to direct the user to the authorization endpoint providing as URL parameters its client identifier, requested scope, local state, and a redirection URI to which the authorization server will send the user-agent back once access is granted.
```js theme={null}
https://app.sendoso.com/oauth/authorize
```
The client identifier from your application (provided by Sendoso).
Client's redirection endpoint previously established with the authorization server during the client registration process.
Value MUST be set to `code`.
Value MUST be set to `scim`.
An opaque value used by the client to maintain state between the request and callback. The authorization server includes this value when redirecting the user-agent back to the client. The parameter SHOULD be used for preventing cross-site request forgery.
### 2. Authorization granted
After the user logs in and grants access to your application they will be redirected to the redirect URI specified in the previous step along with an authorization code as parameter named `code`.
### 3. Exchange code for access token
Once you have the `code` after the user granted access to your application, you need to exchange this code for an access token by making a `POST` to the endpoint and the body below:
```js theme={null}
https://app.sendoso.com/oauth/token
```
Value MUST be set to `authorization_code`.
The authorization code you just received
The same redirect URI that you initiated the flow with.
The client identifier from your application (provided by Sendoso).
The client secret from your application (provided by Sendoso).
The server will respond with an access token and a refresh token as follows:
```
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"access_token":"2YotnFZFEjr1zCsicMWpAA",
"token_type":"bearer",
"expires_in":7200,
"refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
"scope":"public"
"created_at":1693513711
}
```
The access token issued by the authorization server.
The type of the token issued. Value will ALWAYS be "bearer".
The lifetime in seconds of the access token. Value will ALWAYS be "7200". It denotes that the access token will expire in 2 hours from the time the token was created (see `created_at`)
The refresh token, which can be used to obtain new access tokens using the same authorization grant
The scope(s) granted to this specific token.
Timestampt when the token was created in the authorization server. Could be used to calculate when the token is set to expire.
You will need to use the access token in the Authorization header of your API requests:
```js theme={null}
Authorization: Bearer YOUR_ACCESS_TOKEN
```
## Refresh token
Please note that access tokens have a limited lifespan of 7200 seconds (2 hours) and will need to be refreshed.
To refresh your OAuth access token, you will need to make a `POST` request to the Sendoso OAuth token refresh endpoint:
```js theme={null}
https://app.sendoso.com/oauth/token
```
You will need to include the following parameters in the request body:
Value MUST be set to "refresh\_token".
The refresh token associated to the access token that you want to refresh.
The client identifier from your application (provided by Sendoso).
The client secret from your application (provided by Sendoso).
The server will respond with a new access token and refresh token as follows:
```
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"access_token":"2YotnFZFEjr1zCsicMWpAA",
"token_type":"bearer",
"expires_in":7200,
"refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
"scope":"public"
"created_at":1693513711
}
```
The new access token issued by the authorization server.
The type of the token issued. Value will ALWAYS be "bearer".
The lifetime in seconds of the access token. Value will ALWAYS be "7200". It denotes that the access token will expire in 2 hours from the time the token was created (see `created_at`)
The new refresh token, which can be used to obtain new access tokens using the same authorization grant
The scope(s) granted to this specific token.
Timestampt when the new token was created in the authorization server. Could be used to calculate when the token is set to expire.
Refresh tokens only expire after they are used
## Revoke access token
In order to revoke access tokens (and their associated refresh token), you can make a `POST` request to the following endpoint and parameters:
```
https://app.sendoso.com/oauth/revoke
```
**Headers:**
Basic authorization by base 64 encoding the application client id and client secret separated with ":". e.g. `Basic ENCODED_CLIENT_ID_AND_SECRET` where `ENCODED_CLIENT_ID_AND_SECRET` is the following operation `Base64(client_id:client_secret)`.
**Parameters:**
The access token that you want to revoke.
For example:
```bash theme={null}
curl --location \
--request POST 'https://app.sendoso.com/oauth/revoke?token=YOUR_ACCESS_TOKEN' \
--header 'Authorization: Basic ENCODED_CLIENT_ID_AND_SECRET'
```
# Introduction
Source: https://developer.sendoso.com/scim/overview/introduction
Automate user provisioning & deprovisioning with Sendoso SCIM.
Sendoso implements the [SCIM Version 2.0](https://datatracker.ietf.org/doc/html/rfc7642) protocol so you can easily manage users in the Sendoso platform.
You can use the SCIM API to:
* Automatically provision users.
* Assign users to specific teams within Sendoso
* Manage users' roles within Sendoso
* Deprovision users
To get started, you will first need to sign up for a Sendoso account and obtain your client id and secret. Once you have your account and credentials, you can begin making API calls to the SCIM API and manage your users.
If you have any questions or need further assistance, please contact our support team at [developers@sendoso.com](mailto:developers@sendoso.com).
# Rate Limits
Source: https://developer.sendoso.com/scim/overview/rate-limits
Sendoso's SCIM API enforces rate limiting to ensure that the resources of the platform are shared fairly among all users and to prevent abuse or misuse of the API.
Rate limiting is based on the number of requests made by an application or user within a given time period. Once the rate limit is exceeded, the API will return a `429 Too Many Requests` response and the application will be temporarily blocked from making further requests.
# Security
Source: https://developer.sendoso.com/scim/overview/security
Sendoso's SCIM API provides several security features to ensure that your data is protected and only accessible by authorized users.
## Authentication
Sendoso SCIM API uses Oauth standards to authenticate your API requests. The access token should be passed in the request headers for each API call. [See more information](/scim/overview/authentication).
## Authorization
All requests to the Sendoso SCIM API are authorized based on the permissions associated with the Oauth application and the SCIM scope. If you need to access other resources besides the SCIM API you'll need a different set of credentials to access the Core API. [See more information](/api/overview).
## Security of transmitted data
All data sent to the Sendoso API is encrypted at REST with AES-256 standards and using HTTPS TLS 1.2 with RSA 256-bit, which ensures that the data is transmitted securely over the internet.
## Rate limiting
The Sendoso SCIM API has rate limits in place to prevent abuse and ensure fair usage of resources. If you exceed the rate limit, your IP address will be temporarily blocked from making further requests. [See more information](/api/overview/rate-limits).
## Logging
All requests to the Sendoso SCIM API are logged, including the IP address of the request, the request method, the resource requested, and the response status. This allows us to monitor for suspicious activity and detect any potential security breaches.
When you're done using the Sendoso SCIM API, it is recommended that you revoke your API key.
If you have any questions or concerns about the security of the Sendoso SCIM API, please contact the Sendoso support team at [developers@sendoso.com](mailto:developers@sendoso.com).
# Create User
Source: https://developer.sendoso.com/scim/reference/create-users
POST https://app.sendoso.com/api/scim/v2/Users
Create a new user and assign them a role and a team
### Body
The user's email address
The user's first name
The user's last name
The user's role. Values can be `sender`, `manager`, `admin`.
The user's team. This value needs to match the exact team group name in Sendoso. See more information to get [team group names](/rest-api/reference/teams/get-teams).
### Response
The SCIM RFC schema for the user resource - always `urn:ietf:params:scim:schemas:core:2.0:User`
The user's identifier
The user's email address
Whether or not the user is active or not in the Sendoso platform.
The user's first name
The user's last name
The user's personal balance
The user's email address
The user's role. Values can be `sender`, `manager`, `admin`.
The user's team.
```json theme={null}
{
schemas: ["urn:ietf:params:scim:schemas:core:2.0:User"],
id: "1000",
userName: "john.doe@sendoso.com",
active: true,
name: {
givenName: "John",
familyName: "Doe",
},
emails: [
{ value: "john.doe@sendoso.com" },
],
userType: "sender",
division: "Marketing Ops",
}
```
# Get Single User
Source: https://developer.sendoso.com/scim/reference/get-user
GET https://app.sendoso.com/api/scim/v2/Users
Get single user
### Body
The new user's email address
The new user's first name
The new user's last name
The new user's role. Values can be `sender`, `manager`, `admin`.
The new user's team. This value needs to match the exact team group name in Sendoso. See more information to get [team group names](/rest-api/reference/teams/get-teams).
### Response
The SCIM RFC schema for the user resource - always `urn:ietf:params:scim:schemas:core:2.0:User`
The user's identifier
The user's email address
Whether or not the user is active or not in the Sendoso platform.
The user's first name
The user's last name
The user's personal balance
The user's email address
The user's role. Values can be `sender`, `manager`, `admin`.
The user's team.
```json theme={null}
{
schemas: ["urn:ietf:params:scim:schemas:core:2.0:User"],
id: "1000",
userName: "john.doe@sendoso.com",
active: true,
name: {
givenName: "John",
familyName: "Doe",
},
emails: [
{ value: "john.doe@sendoso.com" },
],
userType: "sender",
division: "Marketing Ops",
}
```
# Get All Users
Source: https://developer.sendoso.com/scim/reference/get-users
GET https://app.sendoso.com/api/scim/v2/Users
Get all users
### Parameters
The 1-based index of the first query result. A value less than 1 SHALL be interpreted as 1. By default this value is `1`
Non-negative integer. Specifies the desired maximum number of query results per page, e.g., `10`. When specified, the service provider MUST NOT return more results than specified, although it MAY return fewer results. If unspecified, the maximum will be `100`
### Response
The SCIM RFC schema for the User List resource - always `urn:ietf:params:scim:api:messages:2.0:ListResponse`
Non-negative integer. Specifies the number of query results returned in a query response page, e.g., `10`.
Non-negative integer. Specifies the total number of results matching the client query, e.g., `1000`.
The 1-based index of the first result in the current set of query results, e.g., `1`.
The user's identifier
The user's email address
Whether or not the user is active or not in the Sendoso platform.
The user's first name
The user's last name
The user's personal balance
The user's email address
The user's role. Values can be `sender`, `manager`, `admin`.
The user's team.
```json theme={null}
{
schemas: ["urn:ietf:params:scim:schemas:core:2.0:User"],
itemsPerPage: 2,
startIndex: 1,
totalResults: 100,
Resources: [
{
id: "1000",
userName: "john.doe@sendoso.com",
active: false,
name: {
givenName: "John",
familyName: "Doe",
},
emails: [
{ value: "john.doe@sendoso.com" },
],
userType: "sender",
division: "Marketing Ops",
},
{
id: "2000",
userName: "jane.doe@sendoso.com",
active: true,
name: {
givenName: "Jane",
familyName: "Doe",
},
emails: [
{ value: "jane.doe@sendoso.com" },
],
userType: "admin",
division: "Sales",
}
]
}
```
# Update User
Source: https://developer.sendoso.com/scim/reference/update-user
PUT https://app.sendoso.com/api/scim/v2/Users/{user_id}
Updates user
### Parameters
The team group id to get the users from
### Body
The user's new first name
The user's new last name
Wheter or not the user needs to be activated or deactivated from the Sendoso platform.
The user's new role. Values can be `sender`, `manager`, `admin`.
The user's new team. This value needs to match the exact team group name in Sendoso. See more information to get [team group names](/rest-api/reference/teams/get-teams).
### Response
The SCIM RFC schema for the user resource - always `urn:ietf:params:scim:schemas:core:2.0:User`
The user's identifier
The user's email address
Whether or not the user is active or not in the Sendoso platform.
The user's first name
The user's last name
The user's personal balance
The user's email address
The user's role. Values can be `sender`, `manager`, `admin`.
The user's team.
```json theme={null}
{
schemas: ["urn:ietf:params:scim:schemas:core:2.0:User"],
id: "1000",
userName: "john.doe@sendoso.com",
active: true,
name: {
givenName: "John",
familyName: "Doe",
},
emails: [
{ value: "john.doe@sendoso.com" },
],
userType: "sender",
division: "Marketing Ops",
}
```
# Endpoints
Source: https://developer.sendoso.com/webhooks/endpoints
## Adding an Endpoint
In order to start listening to messages, you will need to configure your endpoints. Adding an endpoint is as simple as providing a URL that you control and selecting the event types that you want to listen to. The endpoint can be whatever you want, and you can just add them from your webhooks portal. If you don't specify any event types, by default, your endpoint will receive all events, regardless of type.
For example, if you receive webhooks from Sendoso, you can structure your URL like: [https://www.example.com/sendoso/webhooks/](https://www.example.com/sendoso/webhooks/).
Visit the Security tab to learn more about verifying the webhooks from your endpoint application.
## Testing an Endpoint
Once you've added an endpoint, you'll want to make sure its working. The "Testing" tab lets you send test events to your endpoint. After sending an example event, you can click into the message to view the message payload, all of the message attempts, and whether it succeeded or failed.
# Events
Source: https://developer.sendoso.com/webhooks/events
Each webhook has an associated event type. The events that are triggered reflect what is seen in the send tracker. You can subscribe to any or all of the following event types within your webhooks portal.
## Event Types
### send.amazon\_fulfilling
Triggered when the Amazon send is being processed.
### send.amazon\_shipped
Triggered when the send has shipped from Amazon and is in transit to Sendoso.
### send.blocked
Triggered when a request to redeem the send has been blocked.
### send.bounced
Triggered when the send cannot be redeemed and will be refunded.
### send.canceled
Triggered when the send has been canceled by the sender.
### send.clicked
Triggered when the eGift send has been viewed by the recipient.
### send.confirmation\_canceled
Triggered when address confirmation for a send has been canceled by the sender.
### send.confirming\_address
Triggered when the send is awaiting address confirmation from the recipient.
### send.delivered
Triggered when the send has been delivered to the recipient.
### send.email\_blacklist
Triggered when a request to redeem the send has been blacklisted.
### send.expired
Triggered when the link to redeem the send has expired.
### send.failed
Triggered when the send has failed.
### send.fulfilling
Triggered when the send is being processed by Sendoso.
### send.fulfillment\_issue
Triggered when there is an issue on the fulfillment side for the send.
### send.initiated
Triggered when the send is in the process of being created.
### send.insufficient\_funds
Triggered when the send cannot be processed due to insufficient funds.
### send.invalid\_email\_format
Triggered when the recipient email in the send is not a valid email.
### send.opened
Triggered when the eGift send has been opened by the recipient.
### send.order\_received
Triggered when the send order has been received and is being processed.
### send.out\_of\_stock
Triggered when the product for the send is out of stock.
### send.pending\_approval
Triggered when the send is pending approval by the sender.
### send.pending\_sendoso\_approval
Triggered when the send is pending approval by a Sendoso Admin.
### send.redeemed
Triggered when the eGift send has been redeemed by the recipient.
### send.refunded
Triggered when the send has been refunded.
### send.sent
Triggered when the eGift send has been sent to the recipient.
### send.shipped
Triggered when the send is in transit to the recipient.
### send.suspicious\_email
Triggered when the recipient email for the send is flagged as suspicious.
### send.undeliverable
Triggered when the send cannot be delivered to the recipient.
## Schema
The schema (payload) for all event types will be:
```
{
"send_gid": ""
"status_changed_at": ""
}
```
The gid of the send.
The time at which the send's status was changed in ISO 8601 format.
# Introduction
Source: https://developer.sendoso.com/webhooks/introduction
Enable Sendoso webhooks to receive real time status updates on your sends.
## Getting Started
Sendoso's webhooks allow you to seamlessly receive updates about your sends. To activate webhooks:
* Contact our support team to enable it for your organization.
* Once enabled, visit the integrations page to retrieve the webhooks portal URL where your events will be sent.
* From this portal, you can subscribe to different events and create your endpoints.
If you have any questions or need further assistance, please contact our support team at [developers@sendoso.com](mailto:developers@sendoso.com).
# Retries
Source: https://developer.sendoso.com/webhooks/retries
## Schedule
We attempt to deliver each webhook message based on a retry schedule with exponential backoff.
Each message is attempted based on the following schedule, where each period is started following the failure of the preceding attempt:
* Immediately
* 5 seconds
* 5 minutes
* 30 minutes
* 2 hours
* 5 hours
* 10 hours
* 10 hours (in addition to the previous)
If an endpoint is removed or disabled, delivery attempts to the endpoint will be disabled as well.
For example, an attempt that fails three times before eventually succeeding will be delivered roughly 35 minutes and 5 seconds following the first attempt.
## Manual retries
You can also use the webhooks portal to manually retry each message at any time, or automatically retry ("Recover") all failed messages starting from a given date.
# Security
Source: https://developer.sendoso.com/webhooks/security
## Verifying Webhooks
Because of the way webhooks work, attackers can impersonate services by simply sending a fake webhook to an endpoint. It's just an HTTP POST from an unknown source. This is a potential security hole for many applications, or at the very least, a source of problems. In order to prevent it, every webhook and its metadata are signed with a unique key for each endpoint. This signature can then be used to verify the webhook, and only process it if it's valid.
Another potential security hole is what's called replay attacks. A [replay attack](https://en.wikipedia.org/wiki/Replay_attack) is when an attacker intercepts a valid payload (including the signature), and re-transmits it to your endpoint. This payload will pass signature validation, and will therefore be acted upon. To mitigate this attack, a timestamp for when the webhook attempt occurred is included. Webhooks with a timestamp that are more than five minutes away (past or future) from the current time are automatically rejected. This requires your server's clock to be synchronised and accurate, and it's recommended that you use [NTP](https://en.wikipedia.org/wiki/Network_Time_Protocol) to achieve this.
Here is a short example in Ruby of how to verify signatures to get you started.
```ruby theme={null}
require 'rack'
require 'rack/handler/puma'
require 'json'
require 'logger'
require 'openssl'
require 'base64'
# In the portal, you can retrieve the secret for your endpoint once it's created
secret = "whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw";
class VerifyWebhook
def initialize(secret)
@secret = secret
end
def call(env)
request = Rack::Request.new(env)
body = request.body.read
if valid_signature?(request, body)
# Process the webhook as you'd like
return [200, {'content-type' => 'application/json'}, [{ message: "Webhook Received" }.to_json]]
else
# Handle and return the error accordingly
return [403, {'content-type' => 'text/plain'}, ['Forbidden']]
end
end
private
def valid_signature?(request, body)
webhook_id = request.env['HTTP_SVIX_ID']
webhook_timestamp = request.env['HTTP_SVIX_TIMESTAMP']
received_signatures = request.env['HTTP_SVIX_SIGNATURE'].split(' ')
signed_content = "#{webhook_id}.#{webhook_timestamp}.#{body}"
expected_signature = compute_signature(signed_content)
received_signatures.any? do |sig|
version, signature = sig.split(',')
secure_compare(signature, expected_signature)
end
end
def compute_signature(data)
# Webhooks are signed using an HMAC with SHA-256
key = Base64.decode64(@secret.split('_')[1])
digest = OpenSSL::Digest.new('sha256')
hmac = OpenSSL::HMAC.digest(digest, key, data)
Base64.strict_encode64(hmac)
end
def secure_compare(a, b)
# This method is used to mitigate timing attacks
return false unless a.bytesize == b.bytesize
l = a.unpack "C#{a.bytesize}"
res = 0
b.each_byte { |byte| res |= byte ^ l.shift }
res.zero?
end
end
Rack::Handler::Puma.run VerifyWebhook.new(secret), Port: 4567
```
### Firewalls (IP blocking)
In case your webhook receiving endpoint is behind a firewall or NAT, you may need to allow traffic from these IP addresses. This is the US list of IP addresses that webhooks may originate from.
#### US
```
44.228.126.217
50.112.21.217
52.24.126.164
54.148.139.208
2600:1f24:64:8000::/52
```
# Troubleshooting
Source: https://developer.sendoso.com/webhooks/troubleshooting
## Tips
There are some common reasons why your webhook endpoint might be failing:
### Not using the raw payload body
This is the most common issue. When generating the signed content, we use the raw string body of the message payload. If you convert JSON payloads into strings using methods like stringify, different implementations may produce different string representations of the JSON object, which can lead to discrepancies when verifying the signature. It's crucial to verify the payload exactly as it was sent, byte-for-byte or string-for-string, to ensure accurate verification.
### Missing the secret key
From time to time we see people simple using the wrong secret key. Remember that keys are unique to endpoints.
### Sending the wrong response codes
When we receive a response with a 2xx status code, we interpret that as a successful delivery even if you indicate a failure in the response payload. Make sure to use the right response status codes so we know when message are supposed to succeed vs fail.
### Responses timing out
We will consider any message that fails to send a response within 15 seconds a failed message. If your endpoint is also processing complicated workflows, it may timeout and result in failed messages. We suggest having your endpoint simply receive the message and add it to a queue to be processed asynchronously so you can respond promptly and avoiding getting timed out.
## Failure Recovery
### Re-enable a disabled endpoint
If all attempts to a specific endpoint fail for a period of 5 days, the endpoint will be disabled. To re-enable a disabled endpoint, go to the webhook dashboard, find the endpoint from the list and select "Enable Endpoint".
### Recovering/Resending failed messages
If your service has downtime or if your endpoint was misconfigured, you probably want to recover any messages that failed during the downtime.
If you want to replay a single event, you can find the message from the UI and click the options menu next to any of the attempts. From there, click "resend" to have the same message send to your endpoint again.
If you need to recover from a service outage and want to replay all the events since a given time, you can do so from the Endpoint page. On an endpoint's details page, click "Options > Recover Failed Messages". From there, you can choose a time window to recover from.
For a more granular recovery - for example, if you know the exact timestamp that you want to recover from - you can click the options menu on any message from the endpoint page. From there, you can click "Replay..." and choose to "Replay all failed messages since this time."