Aptly Contacts API

The Contacts API from Aptly — 5 operation(s) for contacts.

OpenAPI Specification

aptly-contacts-api-openapi.yml Raw ↑
openapi: 3.0.3
info:
  title: Aptly App Contacts API
  version: '1.0'
  description: 'The Aptly API lets you read and write cards on any Aptly board from external systems.


    All requests require an API key passed as the `x-token` header.

    API keys are scoped to your company and work across all boards.

    '
servers:
- url: https://core-api.getaptly.com
  description: Production
security:
- ApiKeyHeader: []
tags:
- name: Contacts
paths:
  /api/contacts:
    get:
      summary: List contacts
      description: 'Returns a paginated list of contacts scoped to your company. All filter params are optional and ANDed together.

        '
      operationId: listContacts
      tags:
      - Contacts
      security:
      - ApiKeyHeader: []
      - DelegateToken: []
      parameters:
      - name: page
        in: query
        required: true
        schema:
          type: integer
          minimum: 0
        description: Zero-based page index.
      - name: contact_type
        in: query
        schema:
          type: string
        description: Filter by contact type name.
      - name: email
        in: query
        schema:
          type: string
        description: Filter by exact email address (case-insensitive).
      - name: phone
        in: query
        schema:
          type: string
        description: Filter by phone number (digits only, partial match).
      - name: name
        in: query
        schema:
          type: string
        description: Filter by full name (case-insensitive, all words must match).
      - name: updated_after
        in: query
        schema:
          type: string
          format: date-time
        description: Return only contacts updated after this ISO 8601 timestamp.
      - name: updated_before
        in: query
        schema:
          type: string
          format: date-time
        description: Return only contacts updated before this ISO 8601 timestamp.
      responses:
        '200':
          description: Paginated contact list.
          headers:
            x-offset:
              schema:
                type: integer
              description: Current page index.
            x-count:
              schema:
                type: integer
              description: Total matching contacts.
            x-size:
              schema:
                type: integer
              description: Page size.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                  count:
                    type: integer
                  page:
                    type: integer
                  pageSize:
                    type: integer
        '400':
          description: Missing or invalid parameters.
        '401':
          description: Invalid or missing API key.
    post:
      summary: Create or update a contact
      description: 'Creates a new contact or updates an existing one (upsert).


        **Lookup order:**

        1. If `_id` is provided, finds by ID.

        2. Otherwise finds by first email address.

        3. If no match is found, creates a new contact.


        **Body formats** — either native or legacy (capitalized keys) are accepted:


        *Native:* `firstname`, `lastname`, `email` (string or array), `phone` (array of `{number, type}`),

        `typeId`, `contactType`, `isCompany`, `title`, `company`, `imageUrl`, `customFields`


        *Legacy:* `"First Name"`, `"Last Name"`, `Email`, `"Mobile Phone"`, `"Work Phone"`,

        `"Home Phone"`, `"Contact Type"`, `Title`, `Company`


        Returns the enriched contact with custom fields populated by their type definitions.

        '
      operationId: upsertContact
      tags:
      - Contacts
      security:
      - ApiKeyHeader: []
      - DelegateToken: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                _id:
                  type: string
                  description: Existing contact ID — when provided, updates that contact.
                firstname:
                  type: string
                lastname:
                  type: string
                email:
                  oneOf:
                  - type: string
                  - type: array
                    items:
                      type: string
                  description: One or more email addresses.
                phone:
                  type: array
                  items:
                    type: object
                    properties:
                      number:
                        type: string
                      type:
                        type: string
                        enum:
                        - mobile
                        - work
                        - home
                typeId:
                  type: string
                  description: Contact type ID.
                contactType:
                  type: string
                  description: Contact type name (alternative to `typeId` — resolved to an ID automatically).
                isCompany:
                  type: boolean
                title:
                  type: string
                company:
                  type: string
                imageUrl:
                  type: string
                  description: Absolute URL to a JPG or PNG photo.
                customFields:
                  type: object
                  description: Map of custom field ID to value. Unknown field IDs are rejected.
            example:
              firstname: Jane
              lastname: Smith
              email: jane@example.com
              phone:
              - number: '+15555550100'
                type: mobile
              contactType: Tenant
      responses:
        '200':
          description: Contact created or updated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Contact'
        '400':
          description: Invalid input (bad URL, unknown custom field, invalid date, etc.).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Invalid or missing API key.
  /api/contacts/by-email:
    post:
      summary: Look up contacts by email
      description: 'Returns contacts whose email address matches one or more of the provided values.

        Matching is case-insensitive and exact. Results are scoped to your company.

        '
      operationId: getContactsByEmail
      tags:
      - Contacts
      security:
      - ApiKeyHeader: []
      - DelegateToken: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - email
              properties:
                email:
                  oneOf:
                  - type: string
                  - type: array
                    items:
                      type: string
                  description: A single email address or an array of email addresses to look up.
                limit:
                  type: integer
                  default: 20
                  description: Maximum number of results to return.
                skip:
                  type: integer
                  default: 0
                  description: Number of results to skip (for pagination).
            example:
              email: jane@example.com
              limit: 20
              skip: 0
      responses:
        '200':
          description: Matching contacts.
          content:
            application/json:
              schema:
                type: object
                properties:
                  contacts:
                    type: array
                    items:
                      $ref: '#/components/schemas/Contact'
        '400':
          description: Missing or invalid email field.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Invalid or missing API key.
  /api/contacts/verify-email:
    post:
      summary: Initiate contact email verification
      description: 'Looks up an email address against your org''s contact database. If a match is found,

        generates a cryptographically strong 6-digit code, sends it to the address, and

        returns a `requestId` and `verifyUrl` to complete the verification.


        The code expires after 10 minutes and can only be used once.

        '
      operationId: initiateContactVerification
      tags:
      - Contacts
      security:
      - ApiKeyHeader: []
      - DelegateToken: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - email
              properties:
                email:
                  type: string
                  description: The email address to verify.
                emailSubject:
                  type: string
                  description: Subject line for the verification email. Defaults to "Your verification code".
                replyTo:
                  type: string
                  description: Reply-To address for the verification email.
                emailHtml:
                  type: string
                  description: 'Custom HTML body for the verification email. Supports two placeholders:

                    `{{ verificationCode }}` — replaced with the 6-digit code.

                    `{{ expirationTime }}` — replaced with the expiry duration (e.g. "10 minutes").

                    '
            example:
              email: jane@example.com
              emailSubject: Your access code
              replyTo: support@example.com
              emailHtml: <p>Your code is <strong>{{ verificationCode }}</strong>. It expires in {{ expirationTime }}.</p>
      responses:
        '200':
          description: Verification initiated — code sent to the email address.
          content:
            application/json:
              schema:
                type: object
                properties:
                  requestId:
                    type: string
                    description: Opaque ID used to complete the verification.
                  verifyUrl:
                    type: string
                    description: API path to POST the code to (relative URL).
              example:
                requestId: a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4
                verifyUrl: /api/contacts/verify-email/a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4/confirm
        '400':
          description: Missing or invalid email field.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Invalid or missing API key.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: No contact found with that email address.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: Verification request was created but the email could not be delivered (EMAIL_SEND_FAILURE).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /api/contacts/verify-email/{requestId}/confirm:
    post:
      summary: Confirm contact email verification
      description: 'Submits the 6-digit code received by email. Returns the matching contact records

        if the code is valid, not expired, and has not already been used.


        After 5 consecutive failed attempts the verification is permanently invalidated.

        The caller must re-initiate a new verification to try again.

        '
      operationId: confirmContactVerification
      tags:
      - Contacts
      security:
      - ApiKeyHeader: []
      - DelegateToken: []
      parameters:
      - name: requestId
        in: path
        required: true
        schema:
          type: string
        description: The `requestId` returned by the initiate endpoint.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - code
              properties:
                code:
                  type: string
                  description: The 6-digit verification code sent to the email address.
            example:
              code: 042815
      responses:
        '200':
          description: Code accepted — returns verified status and matching contacts.
          content:
            application/json:
              schema:
                type: object
                properties:
                  verified:
                    type: boolean
                    example: true
                  contacts:
                    type: array
                    items:
                      $ref: '#/components/schemas/Contact'
        '400':
          description: Missing code field.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Invalid or missing API key, or code is invalid/expired/already used.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /api/contacts/{contactId}:
    get:
      summary: Get a contact
      description: Returns a single contact by its ID, with custom fields enriched by their type definitions.
      operationId: getContact
      tags:
      - Contacts
      security:
      - ApiKeyHeader: []
      - DelegateToken: []
      parameters:
      - name: contactId
        in: path
        required: true
        schema:
          type: string
        description: The contact's `_id`.
      responses:
        '200':
          description: Contact record.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Contact'
                  count:
                    type: integer
                  page:
                    type: integer
                  pageSize:
                    type: integer
        '401':
          description: Invalid or missing API key.
    post:
      summary: Update a contact
      description: 'Updates an existing contact by ID using the same upsert logic as `POST /api/contacts`.

        The `_id` is taken from the URL — any `_id` in the body is ignored.


        Accepts the same **native** or **legacy** body formats as `POST /api/contacts`.

        Returns the updated, enriched contact.

        '
      operationId: updateContact
      tags:
      - Contacts
      security:
      - ApiKeyHeader: []
      - DelegateToken: []
      parameters:
      - name: contactId
        in: path
        required: true
        schema:
          type: string
        description: The contact's `_id`.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                firstname:
                  type: string
                lastname:
                  type: string
                email:
                  oneOf:
                  - type: string
                  - type: array
                    items:
                      type: string
                  description: One or more email addresses.
                phone:
                  type: array
                  items:
                    type: object
                    properties:
                      number:
                        type: string
                      type:
                        type: string
                        enum:
                        - mobile
                        - work
                        - home
                typeId:
                  type: string
                  description: Contact type ID.
                contactType:
                  type: string
                  description: Contact type name (alternative to `typeId`).
                isCompany:
                  type: boolean
                title:
                  type: string
                company:
                  type: string
                imageUrl:
                  type: string
                  description: Absolute URL to a JPG or PNG photo.
                customFields:
                  type: object
                  description: Map of custom field ID to value.
            example:
              firstname: Jane
              lastname: Smith
              email: jane@example.com
      responses:
        '200':
          description: Updated contact.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Contact'
        '400':
          description: Invalid input.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Invalid or missing API key.
components:
  schemas:
    Contact:
      type: object
      properties:
        _id:
          type: string
          description: MongoDB ObjectId of the contact.
        uuid:
          type: string
        firstname:
          type: string
        lastname:
          type: string
        fullName:
          type: string
          description: Computed display name (first + last, or company name for org records).
        duogram:
          type: string
          description: Two-letter initials derived from first and last name.
        photoId:
          type: string
          nullable: true
        imageUrl:
          type: string
          nullable: true
          description: CDN thumbnail URL for the contact's photo, or null if none.
        email:
          type: string
        phone:
          type: string
        typeId:
          type: string
        companyId:
          type: string
        address:
          type: object
        title:
          type: string
        alerts:
          type: array
          items:
            type: object
        company:
          type: string
          description: Company name — populated when isCompany is true.
        isCompany:
          type: boolean
    Error:
      type: object
      properties:
        error:
          type: string
        message:
          type: string
  securitySchemes:
    ApiKeyHeader:
      type: apiKey
      in: header
      name: x-token
    DelegateToken:
      type: apiKey
      in: header
      name: Authorization
      description: 'Delegate token issued by the platform. Format: `DelegateToken <token>`'
    PartnerBearer:
      type: http
      scheme: bearer
      description: 'Partner token. Format: `Authorization: Bearer <token>`'