openapi: 3.0.0
info:
title: Partner API
description: ValiMail Integration API
version: 1.0.0
servers:
- url: https://api.valimail.com
description: API services
- url: https://api.valimail-staging.com
description: Stage test server
- url: http://localhost:7001
description: Local development server
paths:
/auth:
post:
tags:
- Authentication
summary: Authenticates the API user with the credentials (client-id and app-id)
description: When the authentication is successful, the response will include a bearer token and a timestamp of when the token expires.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/KeyRequest'
example:
client-id: "34acfc47-e910-4dcc-bb22-e2816f7e1e4c"
app-id: "358e2665-dfb9-4a9f-b8db-c0404b7bf087"
responses:
'200':
description: Ok - Authenticated successfully
content:
application/json:
schema:
$ref: '#/components/schemas/KeyResponse'
example:
token: "M2I2ZjU1NWUtN2E0Mi00NTkyLWEyNWYtNjIwNGNlNTI3NzVh"
expires-at: "2029-10-31T18:26:50.597068836Z"
'400':
description: Bad Request - Invalid input data
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationResponse'
'422':
description: Unprocessable Entity - Failed to normalize or parse
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'429':
description: Over Rate - Rate limit exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal Server Error - Service, database, or unclassified error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/accounts/packages:
get:
summary: Returns a list of packages available for a partner account.
description: This endpoint returns a list of packages available for a partner
account. The response will include the package slug and package name. (Packages
are listed according to the authenticated credential)
tags:
- Accounts
responses:
'200':
description: OK - Packages slugs are provided
content:
application/json:
schema:
type: array
items:
type: object
properties:
package-slug:
type: string
package-name:
type: string
example:
- package-slug: package-slug-1
package-name: package-name-1
- package-slug: package-slug-2
package-name: package-name-2
'400':
description: Bad Request - Invalid input data
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationResponse'
'401':
description: Unauthorized - Authentication failed
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden - Authorization failed
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'422':
description: Unprocessable Entity - Failed to normalize or parse
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'429':
description: Over Rate - Rate limit exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal Server Error - Service, database, or unclassified
error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/accounts:
get:
summary: Returns accounts and subsidiaries that are linked to the partner account.
(If no query parameters are provided, all accounts and subsidiaries linked
to the partner account will be returned.)
tags:
- Accounts
parameters:
- name: domains
in: query
description: Filter by List of Organizational Domain Names (org domains).
required: false
schema:
type: array
items:
type: string
example:
- dmarceverywhere.com
- heytest.com
- name: name
in: query
description: Filter by List of Account Names
required: false
schema:
type: array
items:
type: string
example:
- Valimail
- MyCompanyName
- name: slug
in: query
description: Filter by List of Account Slugs
required: false
schema:
type: array
items:
type: string
example:
- valimail
- mycompanyslug
- name: parent-slug
in: query
description: Filter by List of Parent Account Slugs (Only valid for admin
accounts)
schema:
type: array
items:
type: string
example:
- valimail
- mycompanyslug
- name: reverse
in: query
description: Reverse the order of the list to be provided.
schema:
type: boolean
example: false
- name: sort-key
in: query
description: 'Sorts the given list by a key. Allowed values: slug, name, parent_slug,
enabled_org_domains_limit, blocked_org_domains_limit, sending_sub_domains_limit,
approved_senders_limit.'
schema:
type: string
example: name
- name: page
in: query
description: Page to be accessed according to the division of items provided
in conjunction with the 'per-page' parameter.
schema:
type: integer
example: 1
- name: per-page
in: query
description: Number of accounts per page on the provided list.
schema:
type: integer
example: 100
responses:
'200':
description: OK - Accounts and subsidiaries linked to the partner account
are provided. Response fields are omitted when the value is empty or
null.
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/AccountListItem'
example:
- name: Valimail
org-domain-name:
- dmarceverywhere.com
- heytest.com
parent-slug: valimail
slug: valimail
enabled-org-domains-limit: "100"
blocked-org-domains-limit: "100"
sending-sub-domains-limit: "100"
approved-senders-limit: "100"
- name: MyCompanyName
org-domain-name:
- dmarceverywhere.com
- heytest.com
parent-slug: valimail
slug: mycompanyslug
enabled-org-domains-limit: "100"
blocked-org-domains-limit: "100"
sending-sub-domains-limit: "100"
approved-senders-limit: "100"
'400':
description: Bad Request - Invalid input data
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationResponse'
example:
params: slug=invalid-account
detail:
- field: slug
value: invalid-account
message: invalid slug provided
'401':
description: Unauthorized - Authentication failed
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden - Authorization failed
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'422':
description: Unprocessable Entity - Failed to normalize or parse
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'429':
description: Over Rate - Rate limit exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal Server Error - Service, database, or unclassified
error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
post:
summary: Creates a new account with the partner account as the parent account
and also creates all domains provided in the request body as enabled domains
linked to the account that was created.
description: <b>Optional:</b> <br> - org-domain-name (the list of the domains
that will be associated with the account) <br> - enabled-org-domains-limit
(the limit of enabled domains) <br> - blocked-org-domains-limit (the limit
of blocked domains) <br> - sending-sub-domains-limit (the limit of domains
with sender services) <br> - approved-senders-limit (the limit of approved
senders) <br> - package-slug (if it is not provided, the account will be
created with the default package Valimail Core, subject to partner package
permissions. To get the package-slug, please use [GET]/accounts/packages
endpoint) <br> <b>Required:</b> <br> - name (the name of the account. It
also is the base for the account slug to be created) <br><br> <b>Response
notes:</b> <br> - empty or null fields are omitted from the response payload
<br> - numeric limit fields are serialized as strings in the response payload
tags:
- Accounts
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
name:
type: string
description: Name of the account.
org-domain-name:
type: array
items:
type: string
description: List of domains associated with the account.
enabled-org-domains-limit:
type: integer
description: Limit of enabled domains.
blocked-org-domains-limit:
type: integer
description: Limit of blocked domains.
sending-sub-domains-limit:
type: integer
description: Limit of domains with sender services.
approved-senders-limit:
type: integer
description: Limit of approved senders.
package-slug:
type: string
description: Package slug (optional) for the account creation
example:
name: valimail
org-domain-name:
- dmarceverywhere.com
- heytest.com
enabled-org-domains-limit: 100
blocked-org-domains-limit: 100
sending-sub-domains-limit: 100
approved-senders-limit: 100
package-slug: custom-package
responses:
'200':
description: OK - Account created. Response fields are omitted when the
value is empty or null, and numeric limit fields are returned as strings.
content:
application/json:
schema:
$ref: '#/components/schemas/Account'
example:
name: valimail
org-domain-name:
- dmarceverywhere.com
- heytest.com
parent-slug: valimail
slug: valimail
package-slug: custom-package
enabled-org-domains-limit: "100"
blocked-org-domains-limit: "100"
sending-sub-domains-limit: "100"
approved-senders-limit: "100"
'400':
description: Bad Request - Invalid request payload, invalid app-id, or
package not available for the partner
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/DelegatedAPIValidationErrorResponse'
- $ref: '#/components/schemas/DefaultDelegatedAPIErrorResponse'
examples:
missing-name:
value:
params: "{\"org-domain-name\":[\"alpha-example.com\",\"beta-example.com\"],\"enabled-org-domains-limit\":100,\"blocked-org-domains-limit\":200,\"sending-sub-domains-limit\":300,\"approved-senders-limit\":400,\"package-slug\":\"custom-package\"}"
details:
- field: name
value: ""
message: can't be blank
invalid-package:
value:
request: /accounts
message: package not specified or not available
type: invalid-package-error
call: internal
invalid-app-id:
value:
request: /accounts
message: invalid app-id provided
type: invalid-app-id
call: internal
'401':
description: Unauthorized - Authentication failed
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden - Authorization failed
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'422':
description: Unprocessable Entity - Domain creation failed or one of the
requested domains is invalid
content:
application/json:
schema:
$ref: '#/components/schemas/DefaultDelegatedAPIErrorResponse'
example:
request: /accounts
message: Enter a valid organizational domain name.
type: invalid-domain
call: internal
'429':
description: Over Rate - Rate limit exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal Server Error - Internal API lookup failed or another
unclassified server error occurred
content:
application/json:
schema:
$ref: '#/components/schemas/DefaultDelegatedAPIErrorResponse'
example:
request: /accounts
message: Error response from Internal API
type: internal-api-error
call: internal
/accounts/{slug}:
get:
summary: Returns a single account that are linked to the partner account according
to the account slug provided.
tags:
- Accounts
parameters:
- name: slug
in: path
description: Account slug to be queried.
required: true
schema:
type: string
example: valimail
responses:
'200':
description: Ok - Account is provided. Response fields are omitted when
the value is empty or null.
content:
application/json:
schema:
$ref: '#/components/schemas/AccountListItem'
example:
name: Valimail
org-domain-name:
- dmarceverywhere.com
- heytest.com
parent-slug: valimail
slug: valimail
enabled-org-domains-limit: "100"
blocked-org-domains-limit: "100"
sending-sub-domains-limit: "100"
approved-senders-limit: "100"
'400':
description: Bad Request - Invalid input data
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationResponse'
example:
params: slug=invalid+slug
detail:
- field: account-slug
value: invalid slug
message: only allowed alphanumerics, underscore and hyphen
'404':
description: Not Found - Account slug does not exist or is not authorized
for the authenticated partner.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
request: /accounts/missing-account
message: account not found
type: not-found
call: api
'401':
description: Unauthorized - Authentication failed
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden - Authorization failed
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'422':
description: Unprocessable Entity - Failed to normalize or parse
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'429':
description: Over Rate - Rate limit exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal Server Error - Service, database, or unclassified
error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
put:
summary: Updates name, limits, and package of authorized accounts according
to the slug provided in the path.
description: Empty string values are treated as not provided. Numeric 0 values
are treated as not provided. If approved-senders-limit is -1, the account
stores a null approved sender limit and reads it back as -1. If package-slug
is omitted, the existing package is preserved.
tags:
- Accounts
parameters:
- name: slug
in: path
description: Account slug to be updated.
required: true
schema:
type: string
example: valimail
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateAccount'
example:
name: valimail
enabled-org-domains-limit: 100
blocked-org-domains-limit: 100
sending-sub-domains-limit: 100
approved-senders-limit: 100
package-slug: custom-package
responses:
'200':
description: Ok - Account updated. Response fields are omitted when the
value is empty or null, and numeric limit fields are returned as strings.
content:
application/json:
schema:
$ref: '#/components/schemas/Account'
example:
name: valimail
org-domain-name:
- dmarceverywhere.com
- heytest.com
parent-slug: valimail
slug: valimail
package-slug: custom-package
enabled-org-domains-limit: "100"
blocked-org-domains-limit: "100"
sending-sub-domains-limit: "100"
approved-senders-limit: "100"
'400':
description: Bad Request - Invalid app-id or package-slug
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
request: /accounts/valimail
message: package not specified or not available
type: invalid-package-error
call: internal
'404':
description: Not Found - Account slug is invalid or not authorized for
the authenticated partner
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
request: /accounts/valimail
message: account not found
type: not-found
call: internal
'401':
description: Unauthorized - Authentication failed
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden - Authorization failed
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'422':
description: Unprocessable Entity - Failed to normalize or parse
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'429':
description: Over Rate - Rate limit exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal Server Error - Service, database, or unclassified
error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
delete:
summary: Deactivates account by updating the account limits to zero
tags:
- Accounts
parameters:
- name: slug
in: path
description: Account slug to be deactivated.
required: true
schema:
type: string
example: valimail
responses:
'200':
description: account limits deleted
content:
application/json:
schema:
$ref: '#/components/schemas/Account'
'400':
description: Bad Request - Invalid input data
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationResponse'
'401':
description: Unauthorized - Authentication failed
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden - Authorization failed
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'422':
description: Unprocessable Entity - Failed to normalize or parse
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'429':
description: Over Rate - Rate limit exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal Server Error - Service, database, or unclassified
error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/accounts/{slug}/users:
get:
summary: Returns users linked to the account slug provided.
tags:
- Users
parameters:
- name: slug
in: path
description: Filter by Account slug.
required: true
schema:
type: string
example: valimail
- name: email
in: query
description: Filter by List of emails.
schema:
type: array
items:
type: string
example:
- test@email.com
- anothertest@email.com
- name: first-name
in: query
description: Filter by List of First Names.
schema:
type: array
items:
type: string
example:
- John
- Jane
- name: last-name
in: query
description: Filter by List of Last Names.
schema:
type: array
items:
type: string
example:
- Doe
- Smith
- name: user-slug
in: query
description: Filter by List of User slugs.
schema:
type: array
items:
type: string
example:
- john-doe
- jane-smith
- name: has-accepted-invitation
in: query
description: Boolean flag. Use true to return users whose invitation has already been accepted, and false to return users whose invitation has not been accepted.
schema:
type: boolean
example: true
- name: user-type
in: query
description: Filter by List of user types.
schema:
type: array
items:
type: string
enum:
- member
- owner
- marketer
example:
- owner
- marketer
- name: reverse
in: query
description: Reverse the order of the list to be provided.
schema:
type: boolean
example: false
- name: sort-key
in: query
description: 'Sorts the given list by a key. Allowed values: slug, email, first_name, last_name, account_slug, last_active_at, user_type.'
schema:
type: string
example: email
- name: page
in: query
description: Page to be accessed according to the division of items provided
in conjunction with the 'per-page' parameter.
schema:
type: integer
example: 1
- name: per-page
in: query
description: Number of users per page on the provided list.
schema:
type: integer
example: 100
responses:
'200':
description: OK - List of the Users linked to the account slug are provided
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/User'
'400':
description: Bad Request - Invalid input data
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationResponse'
'401':
description: Unauthorized - Authentication failed
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden - Authorization failed
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'422':
description: Unprocessable Entity - Failed to normalize or parse
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'429':
description: Over Rate - Rate limit exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal Server Error - Service, database, or unclassified
error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
post:
summary: Creates a new user linked to the account slug provided and sends an invitation email.
tags:
- Users
parameters:
- name: slug
in: path
description: Account slug to create an user.
required: true
schema:
type: string
example: valimail
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateUser'
responses:
'200':
description: Ok - New user created and invitation generated. The response
includes the activation link that was generated for the invitation.
content:
application/json:
schema:
$ref: '#/components/schemas/InvitedUser'
'400':
description: Bad Request - Invalid input data
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationResponse'
'401':
description: Unauthorized - Authentication failed
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden - Authorization failed
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'422':
description: Unprocessable Entity - Failed to normalize or parse
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'429':
description: Over Rate - Rate limit exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal Server Error - Service, database, or unclassified
error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/accounts/{slug}/users/{user-slug}/invitation:
post:
summary: Sends a new invitation email for the existing user and returns the latest activation link.
description: If the user has already accepted the invitation, the response
returns invitation-accepted-at and an empty activation-link.
tags:
- Users
parameters:
- name: slug
in: path
description: Account slug to find the user.
required: true
schema:
type: string
example: valimail
- name: user-slug
in: path
description: User slug to receive a new invitation.
required: true
schema:
type: string
example: john-doe
responses:
'200':
description: Ok - Invitation email processed. The response includes the
latest activation link, or invitation-accepted-at with an empty activation-link
when the invitation has already been accepted.
content:
application/json:
schema:
$ref: '#/components/schemas/InvitedUser'
examples:
success-invitation-resend:
summary: Invitation resent successfully
value:
email: test@234.com
first-name: John
last-name: Doe
slug: john-doe
account-slug: valimail
last-active-at: '2026-02-24T12:30:00Z'
user-type: owner
activation-link: 'https://app.valimail.com/users/invitation/accept?invitation_token=example-token'
invitation-already-accepted:
summary: User already accepted the invitation
value:
email: test@234.com
# --- truncated at 32 KB (68 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/valimail/refs/heads/main/openapi/_original/valimail-partner-openapi-original.yml