Ruby

How to Fix Close.io (Close) API Connection Issues in Ruby

Fix Close.io (Close) API Connection Issues in Ruby

When integrating the Close (formerly Close.io) API with Ruby, one of the most common frustrations developers face is updating Lead custom fields without accidentally deleting others or triggering confusing Ruby syntax errors.

If you have ever seen:

  • Custom fields being erased after updating another one
  • NameError: undefined local variable or method 'custom'
  • Syntax errors pointing at a colon after field_name:

This article explains exactly why it happens and provides a complete working Ruby example.

The Problem

According to Close’s documentation:

To update a single custom field without removing others, use
custom.field_name: updated_value
instead of
custom: { all: 'fields', listed: 'here' }

But when trying to use that syntax in Ruby, you run into:

custom.field_name: some_value

Which throws a syntax error.

Or:

custom.field_name => some_value

Which throws:

NameError: undefined local variable or method `custom' for main:Object

Meanwhile, using:

custom: { kk_referral: 2.0 }

works but then updating another field removes the first one.

Understanding the Root Cause

There are two separate issues here:

Ruby Syntax vs API Syntax:

The Close API documentation shows this:

custom.field_name: value

That syntax works in JSON — not in Ruby.

Ruby does not allow dots in symbol-style hash keys like:

custom.field_name: 2.0   # Invalid Ruby

Ruby thinks you’re calling a method named custom, then calling field_name, and then adding a label — which is invalid.

That’s why you get syntax errors.

Why Updating One Field Deletes the Others

When you do this:

Closeio::Lead.update(
lead_id,
custom: { kk_referral: 2.0 }
)

Depending on the wrapper implementation, the custom object may be treated as a full replacement, not a partial patch.

So when you later run:

Closeio::Lead.update(
lead_id,
custom: { kk_blog_posts_submitted: 3.0 }
)

The API receives only that one field and the previous kk_referral value is overwritten.

That’s why it appears as if fields are being deleted.

The Correct Way to Update a Single Custom Field in Ruby

Instead of using nested custom: {} syntax, use a flat hash with a string key.

Ruby allows string keys with dots.

Correct Syntax:

Closeio::Lead.update(
lead_id,
"custom.kk_referral" => 2.0
)

That matches the API format while remaining valid Ruby.

Complete Working Example

Let’s walk through a clean, production-safe implementation.

Find the Lead:

lead = Closeio::Lead.where(
query: "email:['#{current_user.email}']"
).firstraise "Lead not found" unless leadlead_id = lead["id"]

Calculate Your Values:

referral_count = Referral.where(
user_id: current_user.id
).count.to_fcomment_count = Comment.where(
user_id: current_user.id
).count.to_f

Update Multiple Custom Fields Safely (Recommended):

Instead of making two separate API calls, send everything at once.

Closeio::Lead.update(
lead_id,
{
"custom.kk_referral" => referral_count,
"custom.kk_blog_posts_submitted" => comment_count
}
)

This:

  • Prevents overwriting issues
  • Reduces API calls
  • Avoids race conditions

If You Must Update Fields Separately

This also works safely:

Closeio::Lead.update(
lead_id,
"custom.kk_referral" => referral_count
)Closeio::Lead.update(
lead_id,
"custom.kk_blog_posts_submitted" => comment_count
)

The key is:

Use "custom.FIELD_NAME" as a STRING key not nested inside custom: {}

Important Close Now Recommends Using Field IDs

Close’s newer API versions prefer:

custom.cf_abc123XYZ

Instead of:

custom.kk_referral

Example:

Closeio::Lead.update(
lead_id,
"custom.cf_v6S011I6MqcbVvB2FA5Nk8dr5MkL8sWuCiG8cUleO9c" => referral_count
)

Using field IDs:

  • Avoids problems if field names change
  • Is future-proof
  • Matches the latest API recommendations

Why Your Earlier Attempts Failed

This fails (invalid Ruby):

custom.kk_blog_posts_submitted: value

Reason: Ruby does not allow dotted keys in label syntax.

This fails (NameError):

custom.kk_blog_posts_submitted => value

Reason: Ruby thinks custom is a variable or method which doesn’t exist.

This may overwrite fields:

custom: { kk_blog_posts_submitted: value }

Reason: Some wrappers treat custom as a full object replacement.

This works:

"custom.kk_blog_posts_submitted" => value

Final Best-Practice Version (Production Ready)

class CloseLeadUpdater
def self.sync_user_stats(user)
lead = Closeio::Lead.where(
query: "email:['#{user.email}']"
).first return unless lead lead_id = lead["id"] referral_count = Referral.where(user_id: user.id).count.to_f
comment_count = Comment.where(user_id: user.id).count.to_f Closeio::Lead.update(
lead_id,
{
"custom.kk_referral" => referral_count,
"custom.kk_blog_posts_submitted" => comment_count
}
)
end
end

Clean. Safe. Predictable.

ProblemCauseSolution
Syntax error after field_name:Ruby doesn’t allow dotted label keysUse string keys
undefined local variable customRuby thinks custom is a methoUse "custom.field" as string
Other custom fields erasedNested custom: {} replaces objectUse flat "custom.field" keys
Want future-proof integrationField names deprecatedUse custom.cf_FIELDID

Final Takeaway

When working with Close’s API in Ruby:

Always use flat string keys like
"custom.field_name" => value

Never try to directly copy JSON-style dotted syntax into Ruby hash labels.

author-avatar

About Shaheen Ullah

Hi, I am Shaheen At FSIBlog, a professional and an experienced Front End Web Developer . I can develop any type of responsive website for you with high speed on both Mobile and Desktop. You can count on me to build you a responsive website so that it looks great on all screens, both small and wide screens. As a Front End Developer, I primarily strive to deliver complete work of high quality to you. I have a great amount of skills in HTML5, CSS3, Bootstrap5, JavaScript, etc . I can build you a website based on the technology that you want in HTML / CSS / Java Script / Bootstrap. I can convert PSD to HTML

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments