openapi: 3.1.0 info: title: Sendoso Core API version: '3' summary: Automate physical gift, direct mail and eGift sending, and read campaigns, users and teams. description: >- The Sendoso Core API (v3) lets you programmatically trigger sends, embed sending into your own forms, and read the campaigns ("touches"), users and team groups behind them. Sendoso describes the API as "organized around REST principles ... predictable, resource-oriented URLs ... HTTP response codes to indicate API errors", supporting GET and POST with JSON request and response bodies. Sendoso does not publish an OpenAPI document. This description was generated by API Evangelist from Sendoso's own published reference pages at https://developer.sendoso.com — every path, method, parameter and response field below is traceable to the page named in that operation's `externalDocs`. contact: name: Sendoso Developer Support email: developers@sendoso.com url: https://developer.sendoso.com/ x-generated-from: documentation x-generated-by: API Evangelist enrichment pipeline (local-v1) x-generated-on: '2026-08-13' x-source-docs: https://developer.sendoso.com/llms.txt servers: - url: https://app.sendoso.com description: Production - url: https://app.staging.sendo.so description: Sandbox / staging (declared in Sendoso's own reference-page code samples) externalDocs: description: Sendoso REST API documentation url: https://developer.sendoso.com/rest-api/overview/introduction security: - OAuth2: [] tags: - name: Users description: Read the authorized user, list organization users, invite new users. - name: Teams description: Team groups and their members. - name: Campaigns description: Campaigns, called "touches" in the API. - name: Sends description: Create and retrieve gift, direct mail and eGift sends. paths: /api/v3/me: get: operationId: getCurrentUser summary: Get Current User description: Get information about the current authorized user. tags: [Users] externalDocs: url: https://developer.sendoso.com/rest-api/reference/users/get-current-user responses: '200': description: The authorized user. content: application/json: schema: $ref: '#/components/schemas/CurrentUser' '401': $ref: '#/components/responses/Unauthorized' '429': $ref: '#/components/responses/TooManyRequests' /api/v3/users: get: operationId: getUsers summary: Get All Users description: Retrieve a paginated list of all active users associated to the organization. tags: [Users] externalDocs: url: https://developer.sendoso.com/rest-api/reference/users/get-users parameters: - $ref: '#/components/parameters/Page' - $ref: '#/components/parameters/PerPage' responses: '200': description: A page of users. content: application/json: schema: type: object required: [current_page, per_page, total_users, users] properties: current_page: type: integer description: The current page being returned. per_page: type: integer description: The number of results being returned per page. total_users: type: integer description: The total number of users. users: type: array items: $ref: '#/components/schemas/User' '401': $ref: '#/components/responses/Unauthorized' '429': $ref: '#/components/responses/TooManyRequests' post: operationId: inviteUser summary: Invite New User description: Create a new user invitation for a specific team group. tags: [Users] externalDocs: url: https://developer.sendoso.com/rest-api/reference/users/invite-user requestBody: required: true content: application/json: schema: type: object required: [user] properties: user: type: object required: [first_name, last_name, email, role, team_group_id] properties: first_name: type: string description: The new user's first name. last_name: type: string description: The new user's last name. email: type: string description: The new user's email address. role: type: string enum: [regular, manager] description: The new user's role. team_group_id: type: integer description: >- The ID of the team to invite the user to. Obtain it from GET /api/v3/groups. responses: '201': description: Invitation created. content: application/json: schema: type: object required: [success, message, receiver_email, team_group_id, user_role, invitation_status, expires_at] properties: success: type: boolean message: type: string receiver_email: type: string team_group_id: type: integer user_role: type: string invitation_status: type: string enum: [pending, accepted, expired] expires_at: type: string description: When the invitation expires, in ISO 8601 format. '400': description: >- Bad request. Documented messages include "Please enter a valid team group" and "Role can be one of these: manager,regular". content: application/json: schema: $ref: '#/components/schemas/Error' '401': $ref: '#/components/responses/Unauthorized' '429': $ref: '#/components/responses/TooManyRequests' /api/v3/groups: get: operationId: getTeamGroups summary: Get All Team Groups description: Retrieve information of all the organization's active team groups. tags: [Teams] externalDocs: url: https://developer.sendoso.com/rest-api/reference/teams/get-teams parameters: - $ref: '#/components/parameters/Page' - $ref: '#/components/parameters/PerPage' responses: '200': description: A page of team groups. content: application/json: schema: type: object required: [current_page, per_page, total_groups, groups] properties: current_page: type: integer per_page: type: integer total_groups: type: integer groups: type: array items: $ref: '#/components/schemas/TeamGroup' '401': $ref: '#/components/responses/Unauthorized' '429': $ref: '#/components/responses/TooManyRequests' /api/v3/groups/{team_group_id}/members: get: operationId: getTeamGroupUsers summary: Get All Team Group Users description: Get the list of users for the specific team. tags: [Teams] externalDocs: url: https://developer.sendoso.com/rest-api/reference/teams/get-team-users parameters: - name: team_group_id in: path required: true description: The team group id to get the users from. schema: type: integer responses: '200': description: Array of user objects. content: application/json: schema: type: array items: $ref: '#/components/schemas/TeamGroupMember' '401': $ref: '#/components/responses/Unauthorized' '404': description: 'Group not found. Documented body: {"message": "Group not found!"}' content: application/json: schema: $ref: '#/components/schemas/Error' '429': $ref: '#/components/responses/TooManyRequests' /api/v3/touches: get: operationId: getCampaigns summary: Get All Campaigns description: Retrieve a list of all active campaigns associated to the organization. tags: [Campaigns] externalDocs: url: https://developer.sendoso.com/rest-api/reference/campaigns/get-campaigns parameters: - $ref: '#/components/parameters/Page' - $ref: '#/components/parameters/PerPage' - name: delivery_type in: query required: false description: >- Filter results by gift type. `mail` returns physical item campaigns, `email` returns eGift campaigns. schema: type: string enum: [mail, email] responses: '200': description: A page of campaigns. content: application/json: schema: type: object required: [current_page, per_page, total_posts, touches] properties: current_page: type: integer per_page: type: integer total_posts: type: integer description: The total number of campaigns. touches: type: array items: $ref: '#/components/schemas/Touch' '401': $ref: '#/components/responses/Unauthorized' '429': $ref: '#/components/responses/TooManyRequests' /api/v3/touches/{touch_id}: get: operationId: getCampaign summary: Get Campaign description: Retrieve additional details on a specific campaign. tags: [Campaigns] externalDocs: url: https://developer.sendoso.com/rest-api/reference/campaigns/get-campaign parameters: - name: touch_id in: path required: true description: The campaign (touch) identifier. schema: type: integer responses: '200': description: The campaign. content: application/json: schema: $ref: '#/components/schemas/Touch' '401': $ref: '#/components/responses/Unauthorized' '404': description: 'Campaign not found. Documented message: "Touch not found".' content: application/json: schema: $ref: '#/components/schemas/Error' '429': $ref: '#/components/responses/TooManyRequests' /api/v3/send: get: operationId: getSends summary: Retrieve All Sends description: Retrieves a list of all sends initiated by anyone in the organization. tags: [Sends] externalDocs: url: https://developer.sendoso.com/rest-api/reference/sends/get-sends parameters: - $ref: '#/components/parameters/Page' - $ref: '#/components/parameters/PerPage' responses: '200': description: A page of sends. content: application/json: schema: type: object required: [current_page, per_page, total_count, sends] properties: current_page: type: integer per_page: type: integer total_count: type: integer sends: type: array items: $ref: '#/components/schemas/Send' '401': $ref: '#/components/responses/Unauthorized' '429': $ref: '#/components/responses/TooManyRequests' post: operationId: createSend summary: Create a Send description: >- Create a send. Sendoso documents three request shapes against this single path and method, distinguished by the `via` discriminator and the address fields: a physical gift to a known address, a physical gift with address collection, and an eGift sent via Sendoso email. Sendoso does NOT deduplicate payloads — an identical request sent twice creates two sends. tags: [Sends] externalDocs: description: Send Physical Gift url: https://developer.sendoso.com/rest-api/reference/sends/physical/physical x-documented-variants: - title: Send Physical Gift url: https://developer.sendoso.com/rest-api/reference/sends/physical/physical - title: Send Physical Gift with Address Collection url: https://developer.sendoso.com/rest-api/reference/sends/physical/physicalAC - title: Send eGift via Sendoso Email url: https://developer.sendoso.com/rest-api/reference/sends/egift/eGift requestBody: required: true content: application/json: schema: type: object required: [send] properties: send: oneOf: - $ref: '#/components/schemas/PhysicalSendRequest' - $ref: '#/components/schemas/PhysicalSendAddressCollectionRequest' - $ref: '#/components/schemas/EgiftSendRequest' responses: '200': description: Send created. content: application/json: schema: $ref: '#/components/schemas/SendResult' '400': description: 'Bad request. Documented message example: "email can''t be blank".' content: application/json: schema: $ref: '#/components/schemas/Error' '401': $ref: '#/components/responses/Unauthorized' '404': description: 'Campaign not found. Documented message: "Touch not found".' content: application/json: schema: $ref: '#/components/schemas/Error' '429': $ref: '#/components/responses/TooManyRequests' /api/v3/send/generate_egift_links: post: operationId: generateEgiftLinks summary: Generate eGift Links description: >- Generate one or more eGift links to embed in your own outreach to the recipient(s). Each recipient gets a unique link associated to the email passed in the request. tags: [Sends] externalDocs: url: https://developer.sendoso.com/rest-api/reference/sends/egift/eGiftlink requestBody: required: true content: application/json: schema: type: object required: [send] properties: send: type: object required: [touch_id, via, via_from, recipient_users] properties: touch_id: type: integer description: The ID of the campaign within Sendoso you want to send. via: type: string const: generate_egift_links via_from: type: string description: >- The name of the application making the send request. Keep this consistent per application. recipient_users: type: array description: An array of recipient emails to generate links for. items: type: object required: [email] properties: email: type: string responses: '200': description: Links generated. content: application/json: schema: type: object required: [success, message, egift_links] properties: success: type: boolean message: type: string egift_links: type: array items: type: object required: [egift_link, recipient_email_or_phone_number] properties: egift_link: type: string description: The link generated for this specific recipient. recipient_email_or_phone_number: type: string '400': description: Bad request. content: application/json: schema: $ref: '#/components/schemas/Error' '401': $ref: '#/components/responses/Unauthorized' '404': description: 'Campaign not found. Documented message: "Touch not found".' content: application/json: schema: $ref: '#/components/schemas/Error' '429': $ref: '#/components/responses/TooManyRequests' components: securitySchemes: OAuth2: type: oauth2 description: >- OAuth 2.0 Authorization Code grant. Register your application by contacting developers@sendoso.com to receive a client ID and client secret. Access tokens live 7200 seconds (2 hours) and are refreshed at the same token endpoint. Tokens are sent as `Authorization: Bearer `. flows: authorizationCode: authorizationUrl: https://app.sendoso.com/oauth/authorize tokenUrl: https://app.sendoso.com/oauth/token refreshUrl: https://app.sendoso.com/oauth/token scopes: public: Access the user's basic information. write: Send gifts on the user's behalf. update: Update the user's account details. marketplace: Access the marketplace API. smartsend: Access the smartsend API. parameters: Page: name: page in: query required: false description: The page number of the results you want to retrieve. The first page is 1. schema: type: integer minimum: 1 PerPage: name: per_page in: query required: false description: The number of results to be returned per page. Max is 100. schema: type: integer maximum: 100 responses: Unauthorized: description: 'Unauthorized. Documented message: "The access token is invalid".' content: application/json: schema: $ref: '#/components/schemas/Error' TooManyRequests: description: >- Too Many Requests. Sendoso throttles application clients sending more than 10 requests/second; the client is temporarily blocked from making further requests. content: application/json: schema: $ref: '#/components/schemas/Error' schemas: Error: type: object description: >- Sendoso's error envelope. Not RFC 9457 problem+json — errors are returned as `application/json` with a `success` flag and a human-readable `message`. Some documented 401 bodies use `description` and `expired` instead of `message`. properties: success: type: boolean message: type: string description: type: string expired: type: boolean CurrentUser: type: object required: [id, first_name, last_name, email, role, balance, team_balance] properties: id: type: integer first_name: type: string last_name: type: string email: type: string role: type: string balance: type: string description: The user's personal balance. team_balance: type: integer description: The sum of all the users' balance. User: type: object required: [id, first_name, last_name, email, team_group_id] properties: id: type: string first_name: type: string last_name: type: string email: type: string team_group_id: type: number TeamGroupMember: type: object required: [id, first_name, last_name, email, balance, sandbox, team_group_id, team_id, key] properties: id: type: string first_name: type: string last_name: type: string email: type: string balance: type: string sandbox: type: boolean description: Whether this user is a sandbox user. team_group_id: type: integer team_id: type: integer description: The team's organization id. key: type: string description: The user's invitation key. TeamGroup: type: object required: [id, budget, created_at, monthly_budget, name, one_time_budget, rollover, team_id, updated_at] properties: id: type: string budget: type: integer created_at: type: string description: ISO 8601. monthly_budget: type: string name: type: string one_time_budget: type: integer rollover: type: boolean description: Whether the monthly budget rolls over to the next month. team_id: type: integer description: The team group's organization id. updated_at: type: string description: ISO 8601. Touch: type: object description: A campaign. Called a "touch" throughout the API. required: [id, name, start_date, description, created_at, user_id, gift_id, status, is_default_price, delivery_type] properties: id: type: integer name: type: string start_date: type: string description: ISO 8601. Gifts cannot be sent for this campaign before this date. end_date: type: string description: ISO 8601. Gifts cannot be sent for this campaign after this date. description: type: string created_at: type: string description: ISO 8601. user_id: type: integer description: The identifier of the user that created this campaign. gift_id: type: integer starting_egift_price: type: number description: Lower bound of the eGift denomination range. eGift campaigns only. ending_egift_price: type: number description: Upper bound of the eGift denomination range. eGift campaigns only. status: type: string description: Always `Active` — this endpoint only returns active campaigns. is_default_price: type: boolean delivery_type: type: string enum: [mail, email] description: '`mail` = physical item, `email` = eGift.' Send: type: object required: [id, send_gid, type, subtype, currency, current_total_cost] properties: id: type: integer send_gid: type: string description: The gid of the send. type: type: string description: >- The send's type. Documented values: Amazon, Handwritten Notes, Inventoried Sends, Sendoso Choice, Sendoso Direct, eGifts International, eGifts USA. subtype: type: string description: >- The send's subtype. Documented values include Bundles, Buy/Send via Amazon, Coffee, Custom, Donate to Charity, Experiences, Handwritten Notes, Lunch, On-Demand, Wine, and the per-country eGift Cards variants. currency: type: string description: ISO 4217. current_total_cost: type: string description: >- The send's cost at the time of the request. May change until the send reaches a final status. PhysicalSendRequest: title: Send Physical Gift type: object description: Send a physical item directly to a recipient when their address is known. required: [touch_id, name, email, address, city, state, zip, country, confirm_address, via, via_from] properties: touch_id: type: integer name: type: string email: type: string address: type: string city: type: string state: type: string zip: type: string country: type: string mobile_no: type: number description: >- Required for non-US addresses — a request without it will fail for any non-US address. custom_message: type: string description: The message that goes on the notecard in the gift box, if applicable. confirm_address: type: boolean description: Send `false` when you are providing the recipient address. via: type: string const: single_person_or_company via_from: type: string PhysicalSendAddressCollectionRequest: title: Send Physical Gift with Address Collection type: object description: Send a physical item when the recipient address is unknown. required: [touch_id, name, email, no_address, confirm_address, address_confirmation_via, resume_with_unconfirmed_address, expire_after_days, hide_product_info, via, via_from] properties: touch_id: type: integer name: type: string email: type: string custom_message: type: string no_address: type: boolean const: true confirm_address: type: boolean const: true address_confirmation_via: type: string enum: [email, link] description: >- `email` sends the recipient an email; `link` returns a link in the response and also mails a link to the sender. resume_with_unconfirmed_address: type: boolean description: Sendoso documents leaving this FALSE for this endpoint. expire_after_days: type: integer minimum: 2 maximum: 7 description: How many days the address collection form stays valid. hide_product_info: type: boolean description: Whether the gift name and image appear on the address collection page. address_confirmation_custom_message: type: string description: Only applicable when sending address collection via the email method. via: type: string const: single_person_or_company via_from: type: string EgiftSendRequest: title: Send eGift via Sendoso Email type: object description: Send an eGift directly to a recipient. required: [touch_id, email, via, via_from] properties: touch_id: type: integer name: type: string email: type: string custom_message: type: string description: The message that goes in the body of the eGift email. via: type: string const: single_email_address via_from: type: string SendResult: type: object required: [success, message, tracking_code] properties: success: type: boolean description: Always `true` for 2xx responses. message: type: string tracking_code: type: string description: The send's unique tracking code. tracking_url: type: string description: The send's unique tracking URL. Returned for eGift sends.