class HelpScout

Constants

CONVERSATION_STATUSES

developer.helpscout.com/mailbox-api/endpoints/conversations/list/

HTTP_BAD_REQUEST
HTTP_CREATED
HTTP_FORBIDDEN
HTTP_INTERNAL_SERVER_ERROR
HTTP_NOT_FOUND
HTTP_NO_CONTENT
HTTP_OK

Status codes used by Help Scout, not all are implemented in this gem yet. developer.helpscout.com/mailbox-api/overview/status_codes/

HTTP_SERVICE_UNAVAILABLE
HTTP_TOO_MANY_REQUESTS
HTTP_UNAUTHORIZED
VERSION

Attributes

last_response[RW]

Public Class Methods

new(api_key, api_secret, token_storage = TokenStorage::Memory.new) click to toggle source
# File lib/help_scout.rb, line 53
def initialize(api_key, api_secret, token_storage = TokenStorage::Memory.new)
  @api_key = api_key
  @api_secret = api_secret
  @token_storage = token_storage
end

Public Instance Methods

create_conversation(data) click to toggle source

Public: Create conversation

data - hash with data note: since v2 the status is now required, which had a default of “active” in v1.

More info: developer.helpscout.com/mailbox-api/endpoints/conversations/create/

Returns conversation ID

# File lib/help_scout.rb, line 67
def create_conversation(data)
  # required_fields = ["subject", "type", "mailboxId", "status", "customer", "threads"]

  post("conversations", { body: data })

  last_response.headers["Resource-ID"]
end
create_customer_email(customer_id, data) click to toggle source

Public: Create email

More info: developer.helpscout.com/mailbox-api/endpoints/customers/emails/create/

# File lib/help_scout.rb, line 283
def create_customer_email(customer_id, data)
  post("customers/#{customer_id}/emails", { body: data })
end
create_customer_phone(customer_id, data) click to toggle source

Public: Create phone number

More info: developer.helpscout.com/mailbox-api/endpoints/customers/phones/create/

# File lib/help_scout.rb, line 269
def create_customer_phone(customer_id, data)
  post("customers/#{customer_id}/phones", { body: data })
end
create_note(conversation_id:, text:, user: nil, imported: false) click to toggle source

Public: Create note thread

imported: no outgoing e-mails or notifications will be generated

More info: developer.helpscout.com/mailbox-api/endpoints/conversations/threads/note/

# File lib/help_scout.rb, line 198
def create_note(conversation_id:, text:, user: nil, imported: false)
  data = {
    text: text,
    user: user,
    imported: imported,
  }
  post("conversations/#{conversation_id}/notes", body: data)

  last_response.code == HTTP_CREATED
end
create_phone(conversation_id:, text:, customer:, imported: false) click to toggle source

Public: Create phone thread

More info: developer.helpscout.com/mailbox-api/endpoints/conversations/threads/phone/

# File lib/help_scout.rb, line 212
def create_phone(conversation_id:, text:, customer:, imported: false)
  # Note, hs does not list user as an accepted type
  # https://developer.helpscout.com/mailbox-api/endpoints/conversations/threads/phone/
  data = {
    text: text,
    customer: {
      id: customer
    },
    imported: imported,
  }
  post("conversations/#{conversation_id}/phones", body: data)

  last_response.code == HTTP_CREATED
end
create_reply(conversation_id:, text:, customer:, user: nil, imported: false) click to toggle source

Public: Create reply thread

More info: developer.helpscout.com/mailbox-api/endpoints/conversations/threads/reply/

# File lib/help_scout.rb, line 230
def create_reply(conversation_id:, text:, customer:, user: nil, imported: false)
  data = {
    text: text,
    user: user,
    customer: {
      id: customer
    },
    imported: imported,
  }
  post("conversations/#{conversation_id}/reply", body: data)

  last_response.code == HTTP_CREATED
end
delete_conversation(id) click to toggle source

Public: Delete conversation

id - conversation id

More info: developer.helpscout.com/mailbox-api/endpoints/conversations/delete/

# File lib/help_scout.rb, line 182
def delete_conversation(id)
  delete("conversations/#{id}")
end
delete_customer_email(customer_id, email_id) click to toggle source

Public: Delete email

More info: developer.helpscout.com/mailbox-api/endpoints/customers/emails/delete/

# File lib/help_scout.rb, line 290
def delete_customer_email(customer_id, email_id)
  delete("customers/#{customer_id}/emails/#{email_id}")
end
delete_customer_phone(customer_id, phone_id) click to toggle source

Public: Delete phone number

More info: developer.helpscout.com/mailbox-api/endpoints/customers/phones/delete/

# File lib/help_scout.rb, line 276
def delete_customer_phone(customer_id, phone_id)
  delete("customers/#{customer_id}/phones/#{phone_id}")
end
generate_oauth_token() click to toggle source

developer.helpscout.com/mailbox-api/overview/authentication/#client-credentials-flow

# File lib/help_scout.rb, line 35
def generate_oauth_token
  options = {
    headers: {
      "Content-Type": "application/json"
    },
    body: {
      grant_type: "client_credentials",
      client_id: @api_key,
      client_secret: @api_secret,
    }
  }
  options[:body] = options[:body].to_json
  response = HTTParty.post("https://api.helpscout.net/v2/oauth2/token", options)
  JSON.parse(response.body)["access_token"]
end
get_conversation(id, embed_threads: false) click to toggle source

Public: Get conversation

id - conversation ID embed_threads - boolean - This will load in subentities, currently only Threads are supported by HS

More info: developer.helpscout.com/mailbox-api/endpoints/conversations/get/

Returns hash from HS with conversation data

# File lib/help_scout.rb, line 84
def get_conversation(id, embed_threads: false)
  if embed_threads
    get("conversations/#{id}?embed=threads")
  else
    get("conversations/#{id}")
  end
end
get_customer(id) click to toggle source

Public: Get customer

id - customer id

More info: developer.helpscout.com/mailbox-api/endpoints/customers/get/

# File lib/help_scout.rb, line 249
def get_customer(id)
  get("customers/#{id}")
end
get_mailboxes() click to toggle source

Public: List all mailboxes

More info: developer.helpscout.com/mailbox-api/endpoints/mailboxes/list/

# File lib/help_scout.rb, line 189
def get_mailboxes
  get("mailboxes")
end
search_conversations(query) click to toggle source

Public: Search for conversations

query - term to search for

More info: developer.helpscout.com/mailbox-api/endpoints/conversations/list/

# File lib/help_scout.rb, line 173
def search_conversations(query)
  search("conversations", query)
end
update_conversation(id, data) click to toggle source

Public: Update conversation

id - conversation id data - hash with data

More info: developer.helpscout.com/mailbox-api/endpoints/conversations/update/

# File lib/help_scout.rb, line 98
def update_conversation(id, data)
  instructions = []

  if data[:subject]
    instructions << {
      op: "replace",
      path: "/subject",
      value: data[:subject],
    }
  end
  if data[:mailboxId]
    instructions << {
      op: "move",
      path: "/mailboxId",
      value: data[:mailboxId],
    }
  end
  if data[:status]
    status = data[:status]
    if !CONVERSATION_STATUSES.include?(status)
      raise InvalidDataError.new("status \"#{status}\" not supported, must be one of #{CONVERSATION_STATUSES}")
    end

    instructions << {
      op: "replace",
      path: "/status",
      value: data[:status],
    }
  end
  if data.key?(:assignTo)
    # change owner
    if data[:assignTo]
      instructions << {
        op: "replace",
        path: "/assignTo",
        value: data[:assignTo],
      }
    else
      # un assign
      instructions << {
        op: "remove",
        path: "/assignTo",
      }
    end
  end

  # Note: HelpScout currently does not support multiple
  # instructions in the same request, well have to do them
  # individually :-)
  instructions.each do |instruction|
    patch("conversations/#{id}", { body: instruction })
  end
end
update_conversation_custom_fields(id, fields) click to toggle source

Public: Update conversation custom fields

More info: developer.helpscout.com/mailbox-api/endpoints/conversations/custom_fields/update/

# File lib/help_scout.rb, line 163
def update_conversation_custom_fields(id, fields)
  data = { fields: fields }
  put("conversations/#{id}/fields", { body: data })
end
update_conversation_tags(id, tags) click to toggle source

Public: Update conversation tags

More info: developer.helpscout.com/mailbox-api/endpoints/conversations/tags/update/

# File lib/help_scout.rb, line 155
def update_conversation_tags(id, tags)
  data = { tags: tags }
  put("conversations/#{id}/tags", { body: data })
end
update_customer(id, data) click to toggle source

Public: Update customer

Note: to update address, chat handles, emails, phones, social profiles or websites, separate endpoints have to be used.

id - customer id data - hash with data

More info: developer.helpscout.com/mailbox-api/endpoints/customers/update/

# File lib/help_scout.rb, line 262
def update_customer(id, data)
  put("customers/#{id}", { body: data })
end

Protected Instance Methods

delete(path, options = {}) click to toggle source
# File lib/help_scout.rb, line 312
def delete(path, options = {})
  request(:delete, path, options)
end
get(path, options = {}) click to toggle source
# File lib/help_scout.rb, line 308
def get(path, options = {})
  request(:get, path, options)
end
patch(path, options = {}) click to toggle source
# File lib/help_scout.rb, line 316
def patch(path, options = {})
  options[:body] = options[:body].to_json if options[:body]

  request(:patch, path, options)
end
post(path, options = {}) click to toggle source
# File lib/help_scout.rb, line 296
def post(path, options = {})
  options[:body] = options[:body].to_json if options[:body]

  request(:post, path, options)
end
put(path, options = {}) click to toggle source
# File lib/help_scout.rb, line 302
def put(path, options = {})
  options[:body] = options[:body].to_json if options[:body]

  request(:put, path, options)
end
request(method, path, options) click to toggle source
# File lib/help_scout.rb, line 339
def request(method, path, options)
  uri = URI("https://api.helpscout.net/v2/#{path}")

  token = @token_storage.token
  if token.nil?
    token = generate_oauth_token
    @token_storage.store_token(token)
  end

  options = {
    headers: {
      "Content-Type": "application/json",
      "Authorization": "Bearer #{token}",
    }
  }.merge(options)

  @last_response = HTTParty.send(method, uri, options)

  case last_response.code
  when HTTP_UNAUTHORIZED
    # Unauthorized means our token is expired. We will fetch a new one, and
    # retry the original request
    new_token = generate_oauth_token
    @token_storage.store_token(new_token)
    options.delete(:headers)
    request(method, path, options)
  when HTTP_OK, HTTP_CREATED, HTTP_NO_CONTENT
    last_response.parsed_response
  when HTTP_BAD_REQUEST
    raise ValidationError, JSON.parse(last_response.body)["_embedded"]["errors"]
  when HTTP_FORBIDDEN
    raise ForbiddenError
  when HTTP_NOT_FOUND
    raise NotFoundError
  when HTTP_INTERNAL_SERVER_ERROR
    error_message = JSON.parse(last_response.body)["error"]
    raise InternalServerError, error_message
  when HTTP_SERVICE_UNAVAILABLE
    raise ServiceUnavailable
  when HTTP_TOO_MANY_REQUESTS
    retry_after = last_response.headers["X-RateLimit-Retry-After"]
    message = "Rate limit of 200 RPM or 12 POST/PUT/DELETE requests per 5 " +
      "seconds reached. Next request possible in #{retry_after} seconds."
    raise TooManyRequestsError, message
  else
    raise NotImplementedError, "Help Scout returned something that is not implemented by the help_scout gem yet: #{last_response.code}: #{last_response.parsed_response["message"] if last_response.parsed_response}"
  end
end