Class: Sendly::TenDlcResource

Inherits:
Object
  • Object
show all
Defined in:
lib/sendly/tendlc_resource.rb

Overview

10DLC resource — register your business for carrier review so you can text from local (10-digit) US numbers. The flow has three steps:

  1. Register a brand with #create_brand, then poll #get_brand until it is verified.
  2. Create a campaign under the verified brand with #create_campaign, then poll #get_campaign until it is active. #qualify pre-checks a use case before you create the campaign.
  3. Attach a number you own with #assign_number. Once the assignment is "Active", the number can send.

Writes require a live API key with the tendlc:write scope.

Examples:

Register a brand and poll until it's verified

brand = client.ten_dlc.create_brand(
  legal_name: "Acme Holdings LLC",
  ein: "12-3456789",
  website: "https://acme.example",
  email: "ops@acme.example"
)
# ...poll client.ten_dlc.get_brand(brand.id) until brand.verified?

Pre-check the use case, then create a campaign

check = client.ten_dlc.qualify(brand.id, "MIXED")
if check.qualified?
  campaign = client.ten_dlc.create_campaign(
    brand_id: brand.id,
    use_case: "MIXED",
    description: "Order updates and support replies for Acme customers",
    message_flow: "Customers opt in at checkout on acme.example",
    sample_messages: ["Your order #123 has shipped!"]
  )
  # ...poll client.ten_dlc.get_campaign(campaign.id) until campaign.active?
end

Assign a number you own

client.ten_dlc.assign_number(campaign.id, phone_number: "+15551234567")

Instance Method Summary collapse

Constructor Details

#initialize(client) ⇒ TenDlcResource

Returns a new instance of TenDlcResource.



197
198
199
# File 'lib/sendly/tendlc_resource.rb', line 197

def initialize(client)
  @client = client
end

Instance Method Details

#assign_number(campaign_id, phone_number:) ⇒ TenDlcAssignment

Assign a phone number you own to an active (carrier-approved) campaign, making the number sendable. Requires a live API key.

Idempotent — re-assigning the same number to the same campaign returns the existing assignment.

Parameters:

  • campaign_id (String)

    Campaign identifier

  • phone_number (String)

    E.164 number the workspace already owns

Returns:

Raises:



379
380
381
382
383
384
385
386
# File 'lib/sendly/tendlc_resource.rb', line 379

def assign_number(campaign_id, phone_number:)
  raise ValidationError, "Campaign ID is required" if campaign_id.nil? || campaign_id.to_s.empty?
  raise ValidationError, "phone_number is required" if phone_number.nil? || phone_number.to_s.empty?

  encoded_id = URI.encode_www_form_component(campaign_id)
  response = @client.post("/tendlc/campaigns/#{encoded_id}/assign", { phoneNumber: phone_number })
  TenDlcAssignment.new(response["data"] || {})
end

#create_brand(legal_name:, dba: nil, ein: nil, entity_type: nil, vertical: nil, website: nil, email: nil, phone: nil, mobile_phone: nil, street: nil, city: nil, state: nil, postal_code: nil, country: nil, verification_id: nil) ⇒ TenDlcBrand

Register a brand for carrier review — step 1 of enabling local-number texting. Requires a live API key.

The brand starts pending. Poll #get_brand until it is verified before creating a campaign.

Parameters:

  • legal_name (String)

    Legal business name

  • dba (String, nil) (defaults to: nil)

    "Doing business as" name, if different from the legal name

  • ein (String, nil) (defaults to: nil)

    Business registration number (e.g. EIN)

  • entity_type (String, nil) (defaults to: nil)

    Business entity type (e.g. "PRIVATE_PROFIT", "SOLE_PROPRIETOR"); the API defaults to "PRIVATE_PROFIT"

  • vertical (String, nil) (defaults to: nil)

    Industry vertical

  • website (String, nil) (defaults to: nil)

    Business website URL

  • email (String, nil) (defaults to: nil)

    Business contact email

  • phone (String, nil) (defaults to: nil)

    Business phone number

  • mobile_phone (String, nil) (defaults to: nil)

    Business mobile phone number

  • street (String, nil) (defaults to: nil)

    Street address

  • city (String, nil) (defaults to: nil)

    City

  • state (String, nil) (defaults to: nil)

    State or region

  • postal_code (String, nil) (defaults to: nil)

    Postal code

  • country (String, nil) (defaults to: nil)

    ISO 3166-1 alpha-2 country code; the API defaults to "US"

  • verification_id (String, nil) (defaults to: nil)

    Existing Sendly verification to prefill business details from

Returns:

Raises:



234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
# File 'lib/sendly/tendlc_resource.rb', line 234

def create_brand(legal_name:, dba: nil, ein: nil, entity_type: nil,
                 vertical: nil, website: nil, email: nil, phone: nil,
                 mobile_phone: nil, street: nil, city: nil, state: nil,
                 postal_code: nil, country: nil, verification_id: nil)
  raise ValidationError, "legal_name is required" if legal_name.nil? || legal_name.to_s.empty?

  body = { legalName: legal_name }
  body[:dba] = dba if dba
  body[:ein] = ein if ein
  body[:entityType] = entity_type if entity_type
  body[:vertical] = vertical if vertical
  body[:website] = website if website
  body[:email] = email if email
  body[:phone] = phone if phone
  body[:mobilePhone] = mobile_phone if mobile_phone
  body[:street] = street if street
  body[:city] = city if city
  body[:state] = state if state
  body[:postalCode] = postal_code if postal_code
  body[:country] = country if country
  body[:verificationId] = verification_id if verification_id

  response = @client.post("/tendlc/brands", body)
  TenDlcBrand.new(response["data"] || {})
end

#create_campaign(brand_id:, use_case:, description:, message_flow:, sample_messages:, sub_use_cases: nil, opt_in_keywords: nil, opt_out_keywords: nil, help_keywords: nil, opt_in_message: nil, opt_out_message: nil, help_message: nil, embedded_link: nil, embedded_phone: nil) ⇒ TenDlcCampaign

Create a messaging campaign under a verified brand and submit it for carrier review. Requires a live API key.

The campaign starts pending. Poll #get_campaign until it is active before assigning numbers.

Parameters:

  • brand_id (String)

    The verified brand to create the campaign under

  • use_case (String)

    Primary use-case code (e.g. "MIXED", "MARKETING")

  • description (String)

    What the campaign sends and why

  • message_flow (String)

    How recipients opt in to receive messages

  • sample_messages (Array<String>)

    Example messages the campaign sends (the first 5 are used)

  • sub_use_cases (Array<String>, nil) (defaults to: nil)

    Sub-use-case codes

  • opt_in_keywords (String, nil) (defaults to: nil)

    Comma-separated keywords that opt a recipient in

  • opt_out_keywords (String, nil) (defaults to: nil)

    Comma-separated keywords that opt a recipient out

  • help_keywords (String, nil) (defaults to: nil)

    Comma-separated keywords that request help

  • opt_in_message (String, nil) (defaults to: nil)

    Auto-reply sent on opt-in

  • opt_out_message (String, nil) (defaults to: nil)

    Auto-reply sent on opt-out

  • help_message (String, nil) (defaults to: nil)

    Auto-reply sent on a help request

  • embedded_link (Boolean, nil) (defaults to: nil)

    Whether messages may contain links; the API defaults to true

  • embedded_phone (Boolean, nil) (defaults to: nil)

    Whether messages may contain phone numbers; the API defaults to false

Returns:

Raises:



323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
# File 'lib/sendly/tendlc_resource.rb', line 323

def create_campaign(brand_id:, use_case:, description:, message_flow:,
                    sample_messages:, sub_use_cases: nil,
                    opt_in_keywords: nil, opt_out_keywords: nil,
                    help_keywords: nil, opt_in_message: nil,
                    opt_out_message: nil, help_message: nil,
                    embedded_link: nil, embedded_phone: nil)
  raise ValidationError, "brand_id is required" if brand_id.nil? || brand_id.to_s.empty?
  raise ValidationError, "use_case is required" if use_case.nil? || use_case.to_s.empty?
  raise ValidationError, "description is required" if description.nil? || description.to_s.empty?
  raise ValidationError, "message_flow is required" if message_flow.nil? || message_flow.to_s.empty?
  raise ValidationError, "sample_messages is required" if sample_messages.nil? || sample_messages.empty?

  body = {
    brandId: brand_id,
    useCase: use_case,
    description: description,
    messageFlow: message_flow,
    sampleMessages: sample_messages
  }
  body[:subUseCases] = sub_use_cases if sub_use_cases
  body[:optInKeywords] = opt_in_keywords if opt_in_keywords
  body[:optOutKeywords] = opt_out_keywords if opt_out_keywords
  body[:helpKeywords] = help_keywords if help_keywords
  body[:optInMessage] = opt_in_message if opt_in_message
  body[:optOutMessage] = opt_out_message if opt_out_message
  body[:helpMessage] = help_message if help_message
  body[:embeddedLink] = embedded_link unless embedded_link.nil?
  body[:embeddedPhone] = embedded_phone unless embedded_phone.nil?

  response = @client.post("/tendlc/campaigns", body)
  TenDlcCampaign.new(response["data"] || {})
end

#get_brand(id) ⇒ TenDlcBrand

Fetch one brand. Also refreshes its carrier-review status, so polling this method shows progress (pending -> verified/failed).

Parameters:

  • id (String)

    Brand identifier

Returns:

Raises:



265
266
267
268
269
270
271
# File 'lib/sendly/tendlc_resource.rb', line 265

def get_brand(id)
  raise ValidationError, "Brand ID is required" if id.nil? || id.to_s.empty?

  encoded_id = URI.encode_www_form_component(id)
  response = @client.get("/tendlc/brands/#{encoded_id}")
  TenDlcBrand.new(response["data"] || {})
end

#get_campaign(id) ⇒ TenDlcCampaign

Fetch one campaign. Also refreshes its carrier-review status, so polling this method shows progress (pending -> active) including throughput once carriers approve.

Parameters:

  • id (String)

    Campaign identifier

Returns:

Raises:



362
363
364
365
366
367
368
# File 'lib/sendly/tendlc_resource.rb', line 362

def get_campaign(id)
  raise ValidationError, "Campaign ID is required" if id.nil? || id.to_s.empty?

  encoded_id = URI.encode_www_form_component(id)
  response = @client.get("/tendlc/campaigns/#{encoded_id}")
  TenDlcCampaign.new(response["data"] || {})
end

#list_assignmentsHash

List your number-to-campaign assignments.

Returns:

  • (Hash)

    { assignments: Array<TenDlcAssignment> }



391
392
393
394
395
# File 'lib/sendly/tendlc_resource.rb', line 391

def list_assignments
  response = @client.get("/tendlc/assignments")
  assignments = (response["data"] || []).map { |a| TenDlcAssignment.new(a) }
  { assignments: assignments }
end

#list_brandsHash

List the brands registered for carrier review.

Returns:

  • (Hash)

    { brands: Array<TenDlcBrand> }



204
205
206
207
208
# File 'lib/sendly/tendlc_resource.rb', line 204

def list_brands
  response = @client.get("/tendlc/brands")
  brands = (response["data"] || []).map { |b| TenDlcBrand.new(b) }
  { brands: brands }
end

#list_campaignsHash

List your messaging campaigns.

Returns:

  • (Hash)

    { campaigns: Array<TenDlcCampaign> }



293
294
295
296
297
# File 'lib/sendly/tendlc_resource.rb', line 293

def list_campaigns
  response = @client.get("/tendlc/campaigns")
  campaigns = (response["data"] || []).map { |c| TenDlcCampaign.new(c) }
  { campaigns: campaigns }
end

#qualify(brand_id, use_case) ⇒ TenDlcQualifyResult

Pre-check whether a use case qualifies for a brand on the carrier network before creating a campaign.

Parameters:

  • brand_id (String)

    Brand identifier

  • use_case (String)

    Use-case code (e.g. "MIXED", "MARKETING", "ACCOUNT_NOTIFICATION", "2FA")

Returns:

Raises:



280
281
282
283
284
285
286
287
288
# File 'lib/sendly/tendlc_resource.rb', line 280

def qualify(brand_id, use_case)
  raise ValidationError, "Brand ID is required" if brand_id.nil? || brand_id.to_s.empty?
  raise ValidationError, "use_case is required" if use_case.nil? || use_case.to_s.empty?

  encoded_id = URI.encode_www_form_component(brand_id)
  encoded_use_case = URI.encode_www_form_component(use_case)
  response = @client.get("/tendlc/brands/#{encoded_id}/qualify/#{encoded_use_case}")
  TenDlcQualifyResult.new(response["data"] || {})
end