Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
270 changes: 240 additions & 30 deletions specs/contacts.openapi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,165 @@ tags:
description: Manage contact events
paths:
'/api/contacts':
get:
operationId: getContacts
summary: Get a list of contacts
description: |-
Returns a paginated list of the account's contacts.

Pagination is cursor based. Every response carries a `pagination` object; pass its
`next_token` value back as the `token` query parameter to fetch the next page, and stop
when `next_token` is `null`. Cursors cannot be walked backwards, so `prev_token` and
`prev_url` are always `null`. No total count is returned.

{% hint style="info" %}
Filter values are validated rather than ignored. An unknown `status`, a non-integer
`list_id`, a repeated filter parameter, or a malformed `token` is rejected with `422`,
so a mistyped filter can never widen the result set.
{% endhint %}
tags:
- Contacts
parameters:
- name: list_id
in: query
required: false
description: Return only contacts that belong to this contact list.
schema:
type: integer
format: int64
minimum: 1
example: 3229
- name: status
in: query
required: false
description: |-
Return only contacts with this subscription status. Matches the `status` field of the
returned contact.
schema:
type: string
enum:
- subscribed
- unsubscribed
example: subscribed
- name: email
in: query
required: false
description: |-
Return only contacts whose email contains this value (case-insensitive substring match).
`*` and `?` are matched literally, not as wildcards.
schema:
type: string
example: john@
- name: per_page
in: query
required: false
description: |-
Number of contacts per page. Defaults to `25`, maximum `50`. Larger values are clamped
to the maximum.
schema:
type: integer
minimum: 1
maximum: 50
default: 25
example: 25
- name: token
in: query
required: false
description: |-
Opaque cursor taken from the `next_token` of a previous response. Omit it to fetch the
first page. Tokens are not page numbers and must not be constructed by hand.
schema:
type: string
example: WzE3NDI4MjA2MDAyMzAsIjAxOGRkNWUzLWY2ZDItN2MwMC04ZjliLWU1YzNmMmQ4YTEzMiJd
x-codeSamples:
- lang: shell
label: 'cURL'
source: |
curl -X GET https://mailtrap.io/api/contacts \
-H 'Authorization: Bearer YOUR_API_KEY'

# Filter by list, status and email substring
curl -X GET 'https://mailtrap.io/api/contacts?list_id=3229&status=subscribed&email=john%40' \
-H 'Authorization: Bearer YOUR_API_KEY'

# Fetch the next page using the cursor from the previous response
curl -X GET 'https://mailtrap.io/api/contacts?per_page=25&token=WzE3NDI4MjA2MDAyMzAsIjAxOGRkNWUzLWY2ZDItN2MwMC04ZjliLWU1YzNmMmQ4YTEzMiJd' \
-H 'Authorization: Bearer YOUR_API_KEY'
responses:
'200':
description: A paginated list of contacts.
content:
application/json:
schema:
$ref: '#/components/schemas/ContactsCollection'
example:
data:
- id: 018dd5e3-f6d2-7c00-8f9b-e5c3f2d8a132
email: john.smith@example.com
created_at: 1742820600230
updated_at: 1742820600230
list_ids:
- 1
- 2
status: subscribed
fields:
first_name: John
last_name: Smith
- id: 018dd5e3-f6d2-7c00-8f9b-000000000002
email: jane.doe@example.com
created_at: 1742906999123
updated_at: 1742906999123
list_ids:
- 3
status: unsubscribed
fields: {}
pagination:
token: null
prev_token: null
next_token: WzE3NDI5MDY5OTkxMjMsIjAxOGRkNWUzLWY2ZDItN2MwMC04ZjliLTAwMDAwMDAwMDAwMiJd
first_url: 'https://mailtrap.io/api/contacts?per_page=25'
prev_url: null
current_url: 'https://mailtrap.io/api/contacts?per_page=25'
next_url: 'https://mailtrap.io/api/contacts?per_page=25&token=WzE3NDI5MDY5OTkxMjMsIjAxOGRkNWUzLWY2ZDItN2MwMC04ZjliLTAwMDAwMDAwMDAwMiJd'
'401':
$ref: '#/components/responses/UNAUTHENTICATED'
'403':
$ref: '#/components/responses/PERMISSION_DENIED'
'422':
description: A filter value or the pagination cursor was invalid. The request is rejected instead of the filter being ignored.
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/UnprocessableEntity'
- $ref: '#/components/schemas/ErrorResponse'
examples:
invalid_list_id:
summary: list_id is not an integer
value:
errors:
list_id:
- must be an integer
invalid_status:
summary: status is not a known value
value:
errors:
status:
- 'must be one of: subscribed, unsubscribed'
repeated_parameter:
summary: A filter was supplied more than once or as an array
value:
errors:
list_id:
- must be a single value
invalid_token:
summary: The pagination cursor is malformed
value:
errors: Invalid token
'429':
$ref: '#/components/responses/LIMIT_EXCEEDED'
'500':
$ref: '#/components/responses/INTERNAL_ERROR'
post:
operationId: createContact
summary: Create a new Contact
Expand Down Expand Up @@ -2297,36 +2456,7 @@ components:
type: object
properties:
data:
type: object
properties:
id:
type: string
email:
type: string
fields:
type: object
description: |-
Object of fields in the following format:
field_1_merge_tag: string | integer | float | boolean | date string in ISO-8601 format (yyyy-mm-dd);
list_ids:
type: array
items:
type: integer
status:
type: string
enum:
- subscribed
- unsubscribed
description: |-
The status of the contact:
- "subscribed" if its email was NOT in the suppression list
- "unsubscribed" otherwise
created_at:
type: integer
format: timestampMillis
updated_at:
type: integer
format: timestampMillis
$ref: '#/components/schemas/ContactObject'
ContactCreateRequest_2:
title: ContactCreateRequest
type: object
Expand Down Expand Up @@ -2657,6 +2787,86 @@ components:
example:
id: 26730
name: My Contact List
ContactObject:
title: Contact
type: object
properties:
id:
type: string
email:
type: string
fields:
type: object
description: |-
Object of fields in the following format:
field_1_merge_tag: string | integer | float | boolean | date string in ISO-8601 format (yyyy-mm-dd);
list_ids:
type: array
items:
type: integer
status:
type: string
enum:
- subscribed
- unsubscribed
description: |-
The status of the contact:
- "subscribed" if its email was NOT in the suppression list
- "unsubscribed" otherwise
created_at:
type: integer
format: timestampMillis
description: Creation time as a Unix timestamp in milliseconds.
updated_at:
type: integer
format: timestampMillis
description: Last update time as a Unix timestamp in milliseconds.
ContactsCollection:
title: ContactsCollection
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/ContactObject'
pagination:
$ref: '#/components/schemas/ContactsPagination'
ContactsPagination:
title: ContactsPagination
type: object
description: |-
Keyset (cursor) pagination metadata. Tokens are opaque cursors rather than page numbers,
and the response carries no total count.
properties:
token:
type: [string, 'null']
description: The cursor used for the current request, or `null` on the first page.
example: null
prev_token:
type: [string, 'null']
description: Always `null`. Keyset pagination cannot walk backwards.
example: null
next_token:
type: [string, 'null']
description: Cursor for the next page, or `null` once the last page has been reached.
example: WzE3NDI5MDY5OTkxMjMsIjAxOGRkNWUzLWY2ZDItN2MwMC04ZjliLTAwMDAwMDAwMDAwMiJd
first_url:
type: string
format: uri
example: 'https://mailtrap.io/api/contacts?per_page=25'
prev_url:
type: [string, 'null']
format: uri
description: Always `null`. Keyset pagination cannot walk backwards.
example: null
current_url:
type: string
format: uri
example: 'https://mailtrap.io/api/contacts?per_page=25'
next_url:
type: [string, 'null']
format: uri
example: 'https://mailtrap.io/api/contacts?per_page=25&token=WzE3NDI5MDY5OTkxMjMsIjAxOGRkNWUzLWY2ZDItN2MwMC04ZjliLTAwMDAwMDAwMDAwMiJd'
ContactUpdateRequest_2:
title: ContactUpdateRequest
type: object
Expand Down
Loading