linqgo

package module
v0.55.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 6, 2026 License: Apache-2.0 Imports: 23 Imported by: 0

README

Linq API V3 Go API Library

Go Reference

The Linq API V3 Go library provides convenient access to the Linq API V3 REST API from applications written in Go.

It is generated with Stainless.

MCP Server

Use the Linq API V3 MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application.

Add to Cursor Install in VS Code

Note: You may need to set environment variables in your MCP client.

Installation

import (
	"github.com/linq-team/linq-go" // imported as linqgo
)

Or to pin the version:

go get -u 'github.com/linq-team/linq-go@v0.55.0'

Requirements

This library requires Go 1.22+.

Usage

The full API of this library can be found in api.md.

package main

import (
	"context"
	"fmt"

	"github.com/linq-team/linq-go"
	"github.com/linq-team/linq-go/option"
)

func main() {
	client := linqgo.NewClient(
		option.WithAPIKey("My API Key"), // defaults to os.LookupEnv("LINQ_API_V3_API_KEY")
	)
	chat, err := client.Chats.New(context.TODO(), linqgo.ChatNewParams{
		From:    "+12052535597",
		Message: linqgo.MessageContentParam{},
		To:      []string{"+12052532136"},
	})
	if err != nil {
		panic(err.Error())
	}
	fmt.Printf("%+v\n", chat.Chat)
}

Request fields

The linqgo library uses the omitzero semantics from the Go 1.24+ encoding/json release for request fields.

Required primitive fields (int64, string, etc.) feature the tag `api:"required"`. These fields are always serialized, even their zero values.

Optional primitive types are wrapped in a param.Opt[T]. These fields can be set with the provided constructors, linqgo.String(string), linqgo.Int(int64), etc.

Any param.Opt[T], map, slice, struct or string enum uses the tag `json:"...,omitzero"`. Its zero value is considered omitted.

The param.IsOmitted(any) function can confirm the presence of any omitzero field.

p := linqgo.ExampleParams{
	ID:   "id_xxx",             // required property
	Name: linqgo.String("..."), // optional property

	Point: linqgo.Point{
		X: 0,             // required field will serialize as 0
		Y: linqgo.Int(1), // optional field will serialize as 1
		// ... omitted non-required fields will not be serialized
	},

	Origin: linqgo.Origin{}, // the zero value of [Origin] is considered omitted
}

To send null instead of a param.Opt[T], use param.Null[T](). To send null instead of a struct T, use param.NullStruct[T]().

p.Name = param.Null[string]()       // 'null' instead of string
p.Point = param.NullStruct[Point]() // 'null' instead of struct

param.IsNull(p.Name)  // true
param.IsNull(p.Point) // true

Request structs contain a .SetExtraFields(map[string]any) method which can send non-conforming fields in the request body. Extra fields overwrite any struct fields with a matching key. For security reasons, only use SetExtraFields with trusted data.

To send a custom value instead of a struct, use param.Override[T](value).

// In cases where the API specifies a given type,
// but you want to send something else, use [SetExtraFields]:
p.SetExtraFields(map[string]any{
	"x": 0.01, // send "x" as a float instead of int
})

// Send a number instead of an object
custom := param.Override[linqgo.FooParams](12)
Request unions

Unions are represented as a struct with fields prefixed by "Of" for each of its variants, only one field can be non-zero. The non-zero field will be serialized.

Sub-properties of the union can be accessed via methods on the union struct. These methods return a mutable pointer to the underlying data, if present.

// Only one field can be non-zero, use param.IsOmitted() to check if a field is set
type AnimalUnionParam struct {
	OfCat *Cat `json:",omitzero,inline`
	OfDog *Dog `json:",omitzero,inline`
}

animal := AnimalUnionParam{
	OfCat: &Cat{
		Name: "Whiskers",
		Owner: PersonParam{
			Address: AddressParam{Street: "3333 Coyote Hill Rd", Zip: 0},
		},
	},
}

// Mutating a field
if address := animal.GetOwner().GetAddress(); address != nil {
	address.ZipCode = 94304
}
Response objects

All fields in response structs are ordinary value types (not pointers or wrappers). Response structs also include a special JSON field containing metadata about each property.

type Animal struct {
	Name   string `json:"name,nullable"`
	Owners int    `json:"owners"`
	Age    int    `json:"age"`
	JSON   struct {
		Name        respjson.Field
		Owner       respjson.Field
		Age         respjson.Field
		ExtraFields map[string]respjson.Field
	} `json:"-"`
}

To handle optional data, use the .Valid() method on the JSON field. .Valid() returns true if a field is not null, not present, or couldn't be marshaled.

If .Valid() is false, the corresponding field will simply be its zero value.

raw := `{"owners": 1, "name": null}`

var res Animal
json.Unmarshal([]byte(raw), &res)

// Accessing regular fields

res.Owners // 1
res.Name   // ""
res.Age    // 0

// Optional field checks

res.JSON.Owners.Valid() // true
res.JSON.Name.Valid()   // false
res.JSON.Age.Valid()    // false

// Raw JSON values

res.JSON.Owners.Raw()                  // "1"
res.JSON.Name.Raw() == "null"          // true
res.JSON.Name.Raw() == respjson.Null   // true
res.JSON.Age.Raw() == ""               // true
res.JSON.Age.Raw() == respjson.Omitted // true

These .JSON structs also include an ExtraFields map containing any properties in the json response that were not specified in the struct. This can be useful for API features not yet present in the SDK.

body := res.JSON.ExtraFields["my_unexpected_field"].Raw()
Response Unions

In responses, unions are represented by a flattened struct containing all possible fields from each of the object variants. To convert it to a variant use the .AsFooVariant() method or the .AsAny() method if present.

If a response value union contains primitive values, primitive fields will be alongside the properties but prefixed with Of and feature the tag json:"...,inline".

type AnimalUnion struct {
	// From variants [Dog], [Cat]
	Owner Person `json:"owner"`
	// From variant [Dog]
	DogBreed string `json:"dog_breed"`
	// From variant [Cat]
	CatBreed string `json:"cat_breed"`
	// ...

	JSON struct {
		Owner respjson.Field
		// ...
	} `json:"-"`
}

// If animal variant
if animal.Owner.Address.ZipCode == "" {
	panic("missing zip code")
}

// Switch on the variant
switch variant := animal.AsAny().(type) {
case Dog:
case Cat:
default:
	panic("unexpected type")
}
RequestOptions

This library uses the functional options pattern. Functions defined in the option package return a RequestOption, which is a closure that mutates a RequestConfig. These options can be supplied to the client or at individual requests. For example:

client := linqgo.NewClient(
	// Adds a header to every request made by the client
	option.WithHeader("X-Some-Header", "custom_header_info"),
)

client.Chats.New(context.TODO(), ...,
	// Override the header
	option.WithHeader("X-Some-Header", "some_other_custom_header_info"),
	// Add an undocumented field to the request body, using sjson syntax
	option.WithJSONSet("some.json.path", map[string]string{"my": "object"}),
)

The request option option.WithDebugLog(nil) may be helpful while debugging.

See the full list of request options.

Pagination

This library provides some conveniences for working with paginated list endpoints.

You can use .ListAutoPaging() methods to iterate through items across all pages:

iter := client.Chats.ListChatsAutoPaging(context.TODO(), linqgo.ChatListChatsParams{})
// Automatically fetches more pages as needed.
for iter.Next() {
	chat := iter.Current()
	fmt.Printf("%+v\n", chat)
}
if err := iter.Err(); err != nil {
	panic(err.Error())
}

Or you can use simple .List() methods to fetch a single page and receive a standard response object with additional helper methods like .GetNextPage(), e.g.:

page, err := client.Chats.ListChats(context.TODO(), linqgo.ChatListChatsParams{})
for page != nil {
	for _, chat := range page.Chats {
		fmt.Printf("%+v\n", chat)
	}
	page, err = page.GetNextPage()
}
if err != nil {
	panic(err.Error())
}
Errors

When the API returns a non-success status code, we return an error with type *linqgo.Error. This contains the StatusCode, *http.Request, and *http.Response values of the request, as well as the JSON of the error body (much like other response objects in the SDK).

To handle errors, we recommend that you use the errors.As pattern:

_, err := client.Chats.New(context.TODO(), linqgo.ChatNewParams{
	From:    "+12052535597",
	Message: linqgo.MessageContentParam{},
	To:      []string{"+12052532136"},
})
if err != nil {
	var apierr *linqgo.Error
	if errors.As(err, &apierr) {
		println(string(apierr.DumpRequest(true)))  // Prints the serialized HTTP request
		println(string(apierr.DumpResponse(true))) // Prints the serialized HTTP response
	}
	panic(err.Error()) // GET "/v3/chats": 400 Bad Request { ... }
}

When other errors occur, they are returned unwrapped; for example, if HTTP transport fails, you might receive *url.Error wrapping *net.OpError.

Timeouts

Requests do not time out by default; use context to configure a timeout for a request lifecycle.

Note that if a request is retried, the context timeout does not start over. To set a per-retry timeout, use option.WithRequestTimeout().

// This sets the timeout for the request, including all the retries.
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
defer cancel()
client.Chats.New(
	ctx,
	linqgo.ChatNewParams{
		From:    "+12052535597",
		Message: linqgo.MessageContentParam{},
		To:      []string{"+12052532136"},
	},
	// This sets the per-retry timeout
	option.WithRequestTimeout(20*time.Second),
)
File uploads

Request parameters that correspond to file uploads in multipart requests are typed as io.Reader. The contents of the io.Reader will by default be sent as a multipart form part with the file name of "anonymous_file" and content-type of "application/octet-stream".

The file name and content-type can be customized by implementing Name() string or ContentType() string on the run-time type of io.Reader. Note that os.File implements Name() string, so a file returned by os.Open will be sent with the file name on disk.

We also provide a helper linqgo.File(reader io.Reader, filename string, contentType string) which can be used to wrap any io.Reader with the appropriate file name and content type.

Retries

Certain errors will be automatically retried 2 times by default, with a short exponential backoff. We retry by default all connection errors, 408 Request Timeout, 409 Conflict, 429 Rate Limit, and >=500 Internal errors.

You can use the WithMaxRetries option to configure or disable this:

// Configure the default for all requests:
client := linqgo.NewClient(
	option.WithMaxRetries(0), // default is 2
)

// Override per-request:
client.Chats.New(
	context.TODO(),
	linqgo.ChatNewParams{
		From:    "+12052535597",
		Message: linqgo.MessageContentParam{},
		To:      []string{"+12052532136"},
	},
	option.WithMaxRetries(5),
)
Accessing raw response data (e.g. response headers)

You can access the raw HTTP response data by using the option.WithResponseInto() request option. This is useful when you need to examine response headers, status codes, or other details.

// Create a variable to store the HTTP response
var response *http.Response
chat, err := client.Chats.New(
	context.TODO(),
	linqgo.ChatNewParams{
		From:    "+12052535597",
		Message: linqgo.MessageContentParam{},
		To:      []string{"+12052532136"},
	},
	option.WithResponseInto(&response),
)
if err != nil {
	// handle error
}
fmt.Printf("%+v\n", chat)

fmt.Printf("Status Code: %d\n", response.StatusCode)
fmt.Printf("Headers: %+#v\n", response.Header)
Making custom/undocumented requests

This library is typed for convenient access to the documented API. If you need to access undocumented endpoints, params, or response properties, the library can still be used.

Undocumented endpoints

To make requests to undocumented endpoints, you can use client.Get, client.Post, and other HTTP verbs. RequestOptions on the client, such as retries, will be respected when making these requests.

var (
    // params can be an io.Reader, a []byte, an encoding/json serializable object,
    // or a "…Params" struct defined in this library.
    params map[string]any

    // result can be an []byte, *http.Response, a encoding/json deserializable object,
    // or a model defined in this library.
    result *http.Response
)
err := client.Post(context.Background(), "/unspecified", params, &result)
if err != nil {
    …
}
Undocumented request params

To make requests using undocumented parameters, you may use either the option.WithQuerySet() or the option.WithJSONSet() methods.

params := FooNewParams{
    ID:   "id_xxxx",
    Data: FooNewParamsData{
        FirstName: linqgo.String("John"),
    },
}
client.Foo.New(context.Background(), params, option.WithJSONSet("data.last_name", "Doe"))
Undocumented response properties

To access undocumented response properties, you may either access the raw JSON of the response as a string with result.JSON.RawJSON(), or get the raw JSON of a particular field on the result with result.JSON.Foo.Raw().

Any fields that are not present on the response struct will be saved and can be accessed by result.JSON.ExtraFields() which returns the extra fields as a map[string]Field.

Middleware

We provide option.WithMiddleware which applies the given middleware to requests.

func Logger(req *http.Request, next option.MiddlewareNext) (res *http.Response, err error) {
	// Before the request
	start := time.Now()
	LogReq(req)

	// Forward the request to the next handler
	res, err = next(req)

	// Handle stuff after the request
	end := time.Now()
	LogRes(res, err, start - end)

    return res, err
}

client := linqgo.NewClient(
	option.WithMiddleware(Logger),
)

When multiple middlewares are provided as variadic arguments, the middlewares are applied left to right. If option.WithMiddleware is given multiple times, for example first in the client then the method, the middleware in the client will run first and the middleware given in the method will run next.

You may also replace the default http.Client with option.WithHTTPClient(client). Only one http client is accepted (this overwrites any previous client) and receives requests after any middleware has been applied.

Semantic versioning

This package generally follows SemVer conventions, though certain backwards-incompatible changes may be released as minor versions:

  1. Changes to library internals which are technically public but not intended or documented for external use. (Please open a GitHub issue to let us know if you are relying on such internals.)
  2. Changes that we do not expect to impact the vast majority of users in practice.

We take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.

We are keen for your feedback; please open an issue with questions, bugs, or suggestions.

Contributing

See the contributing documentation.

Documentation

Index

Constants

View Source
const ChatHandleStatusActive = shared.ChatHandleStatusActive

Equals "active"

View Source
const ChatHandleStatusLeft = shared.ChatHandleStatusLeft

Equals "left"

View Source
const ChatHandleStatusRemoved = shared.ChatHandleStatusRemoved

Equals "removed"

View Source
const LinkPartResponseTypeLink = shared.LinkPartResponseTypeLink

Equals "link"

View Source
const MediaPartResponseTypeMedia = shared.MediaPartResponseTypeMedia

Equals "media"

View Source
const ReactionTypeCustom = shared.ReactionTypeCustom

Equals "custom"

View Source
const ReactionTypeDislike = shared.ReactionTypeDislike

Equals "dislike"

View Source
const ReactionTypeEmphasize = shared.ReactionTypeEmphasize

Equals "emphasize"

View Source
const ReactionTypeLaugh = shared.ReactionTypeLaugh

Equals "laugh"

View Source
const ReactionTypeLike = shared.ReactionTypeLike

Equals "like"

View Source
const ReactionTypeLove = shared.ReactionTypeLove

Equals "love"

View Source
const ReactionTypeQuestion = shared.ReactionTypeQuestion

Equals "question"

View Source
const ReactionTypeSticker = shared.ReactionTypeSticker

Equals "sticker"

View Source
const ServiceTypeIMessage = shared.ServiceTypeIMessage

Equals "iMessage"

View Source
const ServiceTypeRCS = shared.ServiceTypeRCS

Equals "RCS"

View Source
const ServiceTypeSMS = shared.ServiceTypeSMS

Equals "SMS"

View Source
const TextDecorationAnimationBig = shared.TextDecorationAnimationBig

Equals "big"

View Source
const TextDecorationAnimationBloom = shared.TextDecorationAnimationBloom

Equals "bloom"

View Source
const TextDecorationAnimationExplode = shared.TextDecorationAnimationExplode

Equals "explode"

View Source
const TextDecorationAnimationJitter = shared.TextDecorationAnimationJitter

Equals "jitter"

View Source
const TextDecorationAnimationNod = shared.TextDecorationAnimationNod

Equals "nod"

View Source
const TextDecorationAnimationRipple = shared.TextDecorationAnimationRipple

Equals "ripple"

View Source
const TextDecorationAnimationShake = shared.TextDecorationAnimationShake

Equals "shake"

View Source
const TextDecorationAnimationSmall = shared.TextDecorationAnimationSmall

Equals "small"

View Source
const TextDecorationStyleBold = shared.TextDecorationStyleBold

Equals "bold"

View Source
const TextDecorationStyleItalic = shared.TextDecorationStyleItalic

Equals "italic"

View Source
const TextDecorationStyleStrikethrough = shared.TextDecorationStyleStrikethrough

Equals "strikethrough"

View Source
const TextDecorationStyleUnderline = shared.TextDecorationStyleUnderline

Equals "underline"

View Source
const TextPartResponseTypeText = shared.TextPartResponseTypeText

Equals "text"

Variables

This section is empty.

Functions

func Bool

func Bool(b bool) param.Opt[bool]

func BoolPtr

func BoolPtr(v bool) *bool

func DefaultClientOptions

func DefaultClientOptions() []option.RequestOption

DefaultClientOptions read from the environment (LINQ_API_V3_API_KEY, LINQ_WEBHOOK_SECRET, LINQ_API_V3_BASE_URL). This should be used to initialize new clients.

func File

func File(rdr io.Reader, filename string, contentType string) file

func Float

func Float(f float64) param.Opt[float64]

func FloatPtr

func FloatPtr(v float64) *float64

func Int

func Int(i int64) param.Opt[int64]

func IntPtr

func IntPtr(v int64) *int64

func Opt

func Opt[T comparable](v T) param.Opt[T]

func Ptr

func Ptr[T any](v T) *T

func String

func String(s string) param.Opt[string]

func StringPtr

func StringPtr(v string) *string

func Time

func Time(t time.Time) param.Opt[time.Time]

func TimePtr

func TimePtr(v time.Time) *time.Time

Types

type AttachmentGetResponse

type AttachmentGetResponse struct {
	// Unique identifier for the attachment (UUID)
	ID string `json:"id" api:"required"`
	// Supported MIME types for file attachments and media URLs.
	//
	// **Images:** image/jpeg, image/png, image/gif, image/heic, image/heif,
	// image/tiff, image/bmp, image/svg+xml, image/webp, image/x-icon
	//
	// **Videos:** video/mp4, video/quicktime, video/mpeg, video/mpeg2,
	// video/x-msvideo, video/3gpp
	//
	// **Audio:** audio/mpeg, audio/x-m4a, audio/x-caf, audio/x-wav, audio/x-aiff,
	// audio/aac, audio/midi, audio/amr
	//
	// **Wallet passes:** application/vnd.apple.pkpass
	//
	// **Documents:** application/pdf, text/plain, text/markdown, text/vcard, text/rtf,
	// text/csv, text/html, text/calendar, text/xml, application/json,
	// application/msword,
	// application/vnd.openxmlformats-officedocument.wordprocessingml.document,
	// application/vnd.ms-excel,
	// application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,
	// application/vnd.ms-powerpoint,
	// application/vnd.openxmlformats-officedocument.presentationml.presentation,
	// application/x-iwork-pages-sffpages, application/x-iwork-numbers-sffnumbers,
	// application/x-iwork-keynote-sffkey, application/epub+zip, application/zip,
	// application/x-gzip
	//
	// **Transcoded on delivery:**
	//
	// - `audio/x-caf` — CAF files are transcoded to `audio/mp4` for delivery.
	//
	// **Deprecated (accepted but transcoded):**
	//
	//   - `audio/mp3` — Deprecated. Use `audio/mpeg` instead. Files sent as audio/mp3
	//     will be delivered as audio/mpeg.
	//   - `audio/mp4` — Deprecated. Use `audio/x-m4a` instead. Files sent as audio/mp4
	//     will be delivered as audio/x-m4a.
	//   - `audio/aiff` — Deprecated. Use `audio/x-aiff` instead. Files sent as
	//     audio/aiff will be delivered as audio/x-aiff.
	//   - `image/tiff` — Accepted, but TIFF images are transcoded to JPEG for delivery.
	//
	// **Unsupported:** FLAC, OGG, and executable files are explicitly rejected.
	//
	// Any of "image/jpeg", "image/png", "image/gif", "image/heic", "image/heif",
	// "image/tiff", "image/bmp", "image/svg+xml", "image/webp", "image/x-icon",
	// "video/mp4", "video/quicktime", "video/mpeg", "video/mpeg2", "video/x-m4v",
	// "video/x-msvideo", "video/3gpp", "audio/mpeg", "audio/mp3", "audio/x-m4a",
	// "audio/mp4", "audio/x-caf", "audio/x-wav", "audio/x-aiff", "audio/aiff",
	// "audio/aac", "audio/midi", "audio/amr", "application/pdf",
	// "application/vnd.apple.pkpass", "text/plain", "text/markdown", "text/vcard",
	// "text/rtf", "text/csv", "text/html", "text/calendar", "application/msword",
	// "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
	// "application/vnd.ms-excel",
	// "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
	// "application/vnd.ms-powerpoint",
	// "application/vnd.openxmlformats-officedocument.presentationml.presentation",
	// "application/x-iwork-pages-sffpages", "application/x-iwork-numbers-sffnumbers",
	// "application/x-iwork-keynote-sffkey", "application/epub+zip", "text/xml",
	// "application/json", "application/zip", "application/x-gzip".
	ContentType SupportedContentType `json:"content_type" api:"required"`
	// When the attachment was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// Original filename of the attachment
	Filename string `json:"filename" api:"required"`
	// Size of the attachment in bytes
	SizeBytes int64 `json:"size_bytes" api:"required"`
	// **DEPRECATED:** This field is deprecated and will be removed in a future API
	// version.
	//
	// Any of "pending", "complete", "failed".
	//
	// Deprecated: status is no longer a useful signal
	Status AttachmentGetResponseStatus `json:"status" api:"required"`
	// URL to download the attachment
	DownloadURL string `json:"download_url" format:"uri"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ID          respjson.Field
		ContentType respjson.Field
		CreatedAt   respjson.Field
		Filename    respjson.Field
		SizeBytes   respjson.Field
		Status      respjson.Field
		DownloadURL respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (AttachmentGetResponse) RawJSON

func (r AttachmentGetResponse) RawJSON() string

Returns the unmodified JSON received from the API

func (*AttachmentGetResponse) UnmarshalJSON

func (r *AttachmentGetResponse) UnmarshalJSON(data []byte) error

type AttachmentGetResponseStatus

type AttachmentGetResponseStatus string

**DEPRECATED:** This field is deprecated and will be removed in a future API version.

const (
	AttachmentGetResponseStatusPending  AttachmentGetResponseStatus = "pending"
	AttachmentGetResponseStatusComplete AttachmentGetResponseStatus = "complete"
	AttachmentGetResponseStatusFailed   AttachmentGetResponseStatus = "failed"
)

type AttachmentNewParams

type AttachmentNewParams struct {
	// Supported MIME types for file attachments and media URLs.
	//
	// **Images:** image/jpeg, image/png, image/gif, image/heic, image/heif,
	// image/tiff, image/bmp, image/svg+xml, image/webp, image/x-icon
	//
	// **Videos:** video/mp4, video/quicktime, video/mpeg, video/mpeg2,
	// video/x-msvideo, video/3gpp
	//
	// **Audio:** audio/mpeg, audio/x-m4a, audio/x-caf, audio/x-wav, audio/x-aiff,
	// audio/aac, audio/midi, audio/amr
	//
	// **Wallet passes:** application/vnd.apple.pkpass
	//
	// **Documents:** application/pdf, text/plain, text/markdown, text/vcard, text/rtf,
	// text/csv, text/html, text/calendar, text/xml, application/json,
	// application/msword,
	// application/vnd.openxmlformats-officedocument.wordprocessingml.document,
	// application/vnd.ms-excel,
	// application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,
	// application/vnd.ms-powerpoint,
	// application/vnd.openxmlformats-officedocument.presentationml.presentation,
	// application/x-iwork-pages-sffpages, application/x-iwork-numbers-sffnumbers,
	// application/x-iwork-keynote-sffkey, application/epub+zip, application/zip,
	// application/x-gzip
	//
	// **Transcoded on delivery:**
	//
	// - `audio/x-caf` — CAF files are transcoded to `audio/mp4` for delivery.
	//
	// **Deprecated (accepted but transcoded):**
	//
	//   - `audio/mp3` — Deprecated. Use `audio/mpeg` instead. Files sent as audio/mp3
	//     will be delivered as audio/mpeg.
	//   - `audio/mp4` — Deprecated. Use `audio/x-m4a` instead. Files sent as audio/mp4
	//     will be delivered as audio/x-m4a.
	//   - `audio/aiff` — Deprecated. Use `audio/x-aiff` instead. Files sent as
	//     audio/aiff will be delivered as audio/x-aiff.
	//   - `image/tiff` — Accepted, but TIFF images are transcoded to JPEG for delivery.
	//
	// **Unsupported:** FLAC, OGG, and executable files are explicitly rejected.
	//
	// Any of "image/jpeg", "image/png", "image/gif", "image/heic", "image/heif",
	// "image/tiff", "image/bmp", "image/svg+xml", "image/webp", "image/x-icon",
	// "video/mp4", "video/quicktime", "video/mpeg", "video/mpeg2", "video/x-m4v",
	// "video/x-msvideo", "video/3gpp", "audio/mpeg", "audio/mp3", "audio/x-m4a",
	// "audio/mp4", "audio/x-caf", "audio/x-wav", "audio/x-aiff", "audio/aiff",
	// "audio/aac", "audio/midi", "audio/amr", "application/pdf",
	// "application/vnd.apple.pkpass", "text/plain", "text/markdown", "text/vcard",
	// "text/rtf", "text/csv", "text/html", "text/calendar", "application/msword",
	// "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
	// "application/vnd.ms-excel",
	// "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
	// "application/vnd.ms-powerpoint",
	// "application/vnd.openxmlformats-officedocument.presentationml.presentation",
	// "application/x-iwork-pages-sffpages", "application/x-iwork-numbers-sffnumbers",
	// "application/x-iwork-keynote-sffkey", "application/epub+zip", "text/xml",
	// "application/json", "application/zip", "application/x-gzip".
	ContentType SupportedContentType `json:"content_type,omitzero" api:"required"`
	// Name of the file to upload
	Filename string `json:"filename" api:"required"`
	// Size of the file in bytes (max 100MB)
	SizeBytes int64 `json:"size_bytes" api:"required"`
	// contains filtered or unexported fields
}

func (AttachmentNewParams) MarshalJSON

func (r AttachmentNewParams) MarshalJSON() (data []byte, err error)

func (*AttachmentNewParams) UnmarshalJSON

func (r *AttachmentNewParams) UnmarshalJSON(data []byte) error

type AttachmentNewResponse

type AttachmentNewResponse struct {
	// Unique identifier for the attachment
	AttachmentID string `json:"attachment_id" api:"required" format:"uuid"`
	// Stable CDN URL for the file. Use the `attachment_id` to reference this file in
	// media parts when sending messages. Files on the ephemeral attachments tier — and
	// this URL — are removed within roughly 24–48 hours of upload, independently of
	// any message retention window.
	DownloadURL string `json:"download_url" api:"required" format:"uri"`
	// When the upload URL expires (15 minutes from now)
	ExpiresAt time.Time `json:"expires_at" api:"required" format:"date-time"`
	// HTTP method to use for upload (always PUT)
	//
	// Any of "PUT".
	HTTPMethod AttachmentNewResponseHTTPMethod `json:"http_method" api:"required"`
	// HTTP headers that must be set on the upload request. The presigned URL is signed
	// with these exact values — S3 will reject the upload if they don't match.
	RequiredHeaders map[string]string `json:"required_headers" api:"required"`
	// Presigned URL for uploading the file. PUT the raw binary file content to this
	// URL with the `required_headers`. Do not JSON-encode or multipart-wrap the body.
	// Expires after 15 minutes. Treat the URL as opaque — the hostname depends on
	// partner configuration and is the same across sandbox and production.
	UploadURL string `json:"upload_url" api:"required" format:"uri"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		AttachmentID    respjson.Field
		DownloadURL     respjson.Field
		ExpiresAt       respjson.Field
		HTTPMethod      respjson.Field
		RequiredHeaders respjson.Field
		UploadURL       respjson.Field
		ExtraFields     map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (AttachmentNewResponse) RawJSON

func (r AttachmentNewResponse) RawJSON() string

Returns the unmodified JSON received from the API

func (*AttachmentNewResponse) UnmarshalJSON

func (r *AttachmentNewResponse) UnmarshalJSON(data []byte) error

type AttachmentNewResponseHTTPMethod

type AttachmentNewResponseHTTPMethod string

HTTP method to use for upload (always PUT)

const (
	AttachmentNewResponseHTTPMethodPut AttachmentNewResponseHTTPMethod = "PUT"
)

type AttachmentService

type AttachmentService struct {
	Options []option.RequestOption
}

Send files (images, videos, documents, audio) with messages by providing a URL in a media part. Pre-uploading via `POST /v3/attachments` is **optional** and only needed for specific optimization scenarios.

## Sending Media via URL (up to 10MB)

Provide a publicly accessible HTTPS URL with a [supported media type](#supported-file-types) in the `url` field of a media part.

```json

{
  "parts": [{ "type": "media", "url": "https://your-cdn.com/images/photo.jpg" }]
}

```

This works with any URL you already host — no pre-upload step required. **Maximum file size: 10MB.**

## Pre-Upload (required for files over 10MB)

Use `POST /v3/attachments` when you want to:

  • **Send files larger than 10MB** (up to 100MB) — URL-based downloads are limited to 10MB
  • **Send the same file to many recipients** — upload once, reuse the `attachment_id` without re-downloading each time
  • **Reduce message send latency** — the file is already stored, so sending is faster

**How it works:**

  1. `POST /v3/attachments` with file metadata → returns a presigned `upload_url` (valid for **15 minutes**) and a reusable `attachment_id`
  2. PUT the raw file bytes to the `upload_url` with the `required_headers` (no JSON or multipart — just the binary content)
  3. Reference the `attachment_id` in your media part when sending messages (stays valid unless deleted — see [Attachment Lifetime](#attachment-lifetime))

**Key difference:** When you provide an external `url`, we download and process the file on every send. When you use a pre-uploaded `attachment_id`, the file is already stored — so repeated sends skip the download step entirely.

## Attachment Lifetime

An `attachment_id` and its CDN URL stay valid until the file is deleted. Three things delete it:

| Trigger | Applies to | | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `DELETE /v3/attachments/{attachmentId}` | Any attachment you own | | Ephemeral **attachments** tier (24–48h storage backstop) | Attachments on ephemeral-tier partners or phone numbers | | Ephemeral **messages** tier | Does **not** remove attachment bytes on its own: ephemeral-tier objects are removed by the 24–48h storage backstop above, and persistent-tier attachments are kept until you `DELETE` them explicitly. |

Deletion is not reversible, and there is no `attachment.deleted` webhook. On either ephemeral tier, download anything you need to keep when you receive it rather than re-fetching later, and do not assume a pre-uploaded `attachment_id` can be reused indefinitely.

## Domain Allowlisting

Attachment URLs in API responses are served from `cdn.linqapp.com`. This includes:

- `url` fields in media and voice memo message parts - `download_url` fields in attachment and upload response objects

If your application enforces domain allowlists (e.g., for SSRF protection), add:

``` cdn.linqapp.com ```

## Supported File Types

- **Images:** JPEG, PNG, GIF, HEIC, HEIF, TIFF, BMP - **Videos:** MP4, MOV, M4V - **Audio:** M4A, AAC, MP3, WAV, AIFF, CAF, AMR - **Documents:** PDF, TXT, RTF, CSV, Office formats, ZIP - **Contact & Calendar:** VCF, ICS

## Audio: Attachment vs Voice Memo

Audio files sent as media parts appear as **downloadable file attachments** in iMessage. To send audio as an **iMessage voice memo bubble** (with native inline playback UI), use the dedicated `POST /v3/chats/{chatId}/voicememo` endpoint instead.

## File Size Limits

- **URL-based (`url` field):** 10MB maximum - **Pre-upload (`attachment_id`):** 100MB maximum

## Security & Ownership

Every attachment is bound to the partner account that created or received it. The API enforces ownership on every operation that touches an attachment — sending, retrieving, deleting.

**What this means for you:**

  • An attachment created under your API key can only be referenced by your API key.
  • Submitting another partner's `attachment_id` returns `404 Not Found`. We do not disclose whether the id exists or belongs to someone else.
  • Submitting a CDN URL that resolves to another partner's attachment is rejected before the send is attempted.
  • Ownership enforcement applies uniformly across send, create-chat, voice memo, retrieve, and delete operations.

Every attachment-affecting endpoint requires a valid partner API key. Unauthenticated calls return `401 Unauthorized`.

## Attachment URL Patterns

Attachment URLs in API responses and webhook payloads use one of two layouts, depending on the attachment's tier:

| Tier | URL pattern | TTL | | -------------------- | -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | | Persistent (default) | `https://cdn.linqapp.com/attachments/partners/{partner_id}/{attachment_id}/{filename}` | Long-lived — the URL itself does not expire, but see [Attachment Lifetime](#attachment-lifetime) | | Ephemeral | Pre-signed URL pointing at the ephemeral prefix on `cdn.linqapp.com` | 15 minutes per signed URL — re-fetch via the API for a fresh URL |

Inbound media you receive over webhooks uses the same layout your outbound sends produce, so the URL you store and the URL you build look identical — no special casing in your client.

## Ephemeral Attachments (Privacy Tier)

For regulated or sensitive content, opt in to the **ephemeral attachments** tier by contacting your Linq support contact. You can request it at two scopes:

| Scope | Effect | | -------------------- | -------------------------------------------------------------------------------------------------------------------------- | | **Partner-wide** | Every outbound and inbound attachment on every phone number under your account is routed through the ephemeral tier. | | **Per phone number** | Only the specified phone numbers route their attachments through the ephemeral tier. The rest stay on the persistent tier. |

**Behavioral differences vs the persistent default:**

| Aspect | Persistent | Ephemeral | | ----------------------- | ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | | Download URL form | Long-lived CDN URL | Pre-signed URL with short TTL | | Retention floor | Until you call `DELETE` | **Hard backstop: 24–48h** — even without an explicit `DELETE`, the platform removes the underlying bytes within roughly 24–48 hours of upload | | URL re-fetch | Not required | Fetch via `GET /v3/attachments/{attachmentId}` for a fresh signed URL after TTL expiry | | Cross-partner isolation | Enforced | Enforced |

**When to choose ephemeral:**

  • Your downstream system processes the file immediately on receipt and does not need to re-read it later.
  • You have a compliance requirement that the platform must not retain attachments beyond a short window.
  • The content is high-sensitivity (PHI, financial documents, identity verification) and you do not want it sitting behind a long-lived URL.

**Important:** ephemeral applies in _both directions_ — outbound files you upload **and** inbound media received by the phone numbers in that scope. Download bytes you need to keep promptly, or fetch a fresh signed URL via the API when needed.

## Deleting an Attachment

To permanently remove an attachment you own, use:

```http DELETE /v3/attachments/{attachmentId} Authorization: Bearer <your_api_key> ```

**What this does:**

1. Verifies the attachment is owned by your account. Returns `404` otherwise. 2. Removes the underlying file from Linq storage. 3. Records an audit entry (timestamp, partner, attachment id).

**Response codes:**

| Status | Meaning | | --------------------------- | ---------------------------------------------------------------- | | `204 No Content` | Deletion succeeded. The attachment is removed from Linq storage. | | `400 Bad Request` | `attachmentId` is not a valid UUID. | | `401 Unauthorized` | Missing or invalid API key. | | `404 Not Found` | Attachment does not exist or is not owned by your account. | | `500 Internal Server Error` | Transient infrastructure issue — safe to retry. |

**Effect on message history:**

  • Messages that referenced the deleted attachment remain visible.
  • The message part that pointed at the attachment is preserved with no attachment reference.
  • Webhook payloads previously delivered to you retain the original URL string, but downloads from that URL return `404` going forward.

Deletion is **irreversible**. Once `204` is returned, the bytes are gone — there is no undelete.

## Inbound Media Flow

When one of your phone numbers receives a message with media (image, video, audio, document), the platform:

  1. Stores the file under your partner account.
  2. Records metadata linked to the inbound message.
  3. Delivers a webhook whose `parts[]` array includes a `media` part with a `url` pointing at `cdn.linqapp.com`.
  4. If the receiving phone is opted in to ephemeral, the `url` is a short-TTL signed URL.

You can acknowledge the webhook without fetching the file inline, and lazy-load via `GET /v3/attachments/{attachmentId}` later. For ephemeral attachments, retrieving via the API always returns a freshly-signed URL.

## Data Lifecycle Summary

| Data | Persistent tier | Ephemeral tier | | --------------------------------------------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Attachment bytes | Retained until you `DELETE` | **Auto-removed within roughly 24–48 hours** of upload, independently of any message window. Also removable via `DELETE` | | Attachment metadata (id, filename, mime type, size) | Retained until you `DELETE` | Removed alongside the bytes | | Message body & parts | Retained per message-retention policy | Retained per message-retention policy — unless the line also has **ephemeral messages** enabled (see the Messages page), in which case the message's text, formatting, and attachment references are no longer retrievable through the API after that account's configured retention window (60 minutes – 24 hours, default 24 hours) from creation. Metadata is retained; see the Messages page for details | | Audit log of deletions | Retained per platform retention policy | Retained per platform retention policy |

**In transit:** TLS 1.2+ everywhere. **At rest:** AES-256 (server-side encryption).

## Compliance Checklist

If you're integrating Linq under a security or privacy review, here is the short list:

  • Allowlist exactly one outbound domain: `cdn.linqapp.com`.
  • Decide whether you need ephemeral attachments (high-sensitivity content) — request enablement through your Linq support contact.
  • Implement `DELETE /v3/attachments/{attachmentId}` calls in your deletion workflow.
  • Persist any attachments your application needs long-term — Linq is the authoritative source until you delete, but the ephemeral tier auto-purges within roughly 24–48 hours of upload.
  • For audit: every deletion is logged on Linq's side. Surface a confirmation in your application UI based on the `204` response.
  • For end-user "right to delete" requests: enumerate attachment ids and `DELETE` each. The platform does not provide a partner-wide wipe endpoint — deletion is per-attachment by design.

AttachmentService contains methods and other services that help with interacting with the linq-api-v3 API.

Note, unlike clients, this service does not read variables from the environment automatically. You should not instantiate this service directly, and instead use the NewAttachmentService method instead.

func NewAttachmentService

func NewAttachmentService(opts ...option.RequestOption) (r AttachmentService)

NewAttachmentService generates a new service that applies the given options to each request. These options are applied after the parent client's options (if there is one), and before any request-specific options.

func (*AttachmentService) Delete added in v0.20.0

func (r *AttachmentService) Delete(ctx context.Context, attachmentID string, opts ...option.RequestOption) (err error)

Permanently delete an attachment owned by the authenticated partner.

func (*AttachmentService) Get

func (r *AttachmentService) Get(ctx context.Context, attachmentID string, opts ...option.RequestOption) (res *AttachmentGetResponse, err error)

Retrieve metadata for a specific attachment including file information, and URLs for downloading.

`status`: (**deprecated** — will be removed in a future API version)

func (*AttachmentService) New

**This endpoint is optional.** You can send media by simply providing a URL in your message's media part — no pre-upload required. Use this endpoint only when you want to upload a file ahead of time for reuse or latency optimization.

Returns a presigned upload URL and a reusable `attachment_id` you can reference in future messages. Attachments stored on the **ephemeral attachments tier** (and their URLs) are removed within roughly 24–48 hours of upload, independently of any message retention window. Attachments on the persistent tier are kept until you `DELETE` them, regardless of message expiry.

## Step 1: Request an upload URL

Call `POST /v3/attachments` with file metadata:

```json

{
  "filename": "photo.jpg",
  "content_type": "image/jpeg",
  "size_bytes": 1024000
}

```

The response includes an `upload_url` (valid for 15 minutes) and a reusable `attachment_id`.

## Step 2: Upload the file

Make a PUT request to the `upload_url` with the raw file bytes as the request body. You **must** include all headers from `required_headers` exactly as returned — the presigned URL is signed with these values and S3 will reject the upload if they don't match.

The request body is the binary file content — **not** JSON, **not** multipart form data. The file must equal `size_bytes` bytes (the value you declared in step 1).

```bash

curl -X PUT "<upload_url from step 1>" \
  -H "Content-Type: image/jpeg" \
  -H "Content-Length: 1024000" \
  --data-binary @photo.jpg

```

## Step 3: Send a message with the attachment

Reference the `attachment_id` in a media part with `POST /v3/chats`. The ID stays valid for as many messages as you want — unless the attachment is stored on the ephemeral attachments tier, in which case it is removed within roughly 24–48 hours of upload.

```json

{
  "from": "+15559876543",
  "to": ["+15551234567"],
  "message": {
    "parts": [
      { "type": "media", "attachment_id": "<attachment_id from step 1>" }
    ]
  }
}

```

## When to use this instead of a URL in the media part

- Sending the same file to multiple recipients (avoids re-downloading each time) - Large files where you want to separate upload from message send - Latency-sensitive sends where the file should already be stored

If you just need to send a file once, skip all of this and pass a `url` directly in the media part instead.

**File Size Limit:** 100MB

**Unsupported Types:** WebP, SVG, FLAC, OGG, and executable files are explicitly rejected.

type AvailableNumberGetParams added in v0.26.1

type AvailableNumberGetParams struct {
	// Lines (E.164) to leave out of this selection. Applies to the returned
	// `phone_number`, to the sticky choice when `to` is given, and to the vCard's
	// backup numbers. Repeat the parameter for multiple lines; use `%2B` for the
	// leading `+`.
	//
	// Numbers that are not your lines are ignored. Every entry must be E.164 — a value
	// like `4155551234` is rejected rather than silently skipped. Excluding every one
	// of your available lines returns 400.
	ExcludeFrom []string `query:"exclude_from,omitzero" json:"-"`
	// Recipient handles (E.164 or email) the message is destined for. When provided,
	// an existing chat with these recipients makes the choice sticky. Repeat the
	// parameter for multiple recipients.
	To []string `query:"to,omitzero" json:"-"`
	// contains filtered or unexported fields
}

func (AvailableNumberGetParams) URLQuery added in v0.26.1

func (r AvailableNumberGetParams) URLQuery() (v url.Values, err error)

URLQuery serializes AvailableNumberGetParams's query parameters as `url.Values`.

type AvailableNumberGetResponse added in v0.26.1

type AvailableNumberGetResponse struct {
	// The selected sending line in E.164 format.
	PhoneNumber string `json:"phone_number" api:"required"`
	// Time-limited link to a vCard (`.vcf`) for the selected line. The card carries
	// the line's contact details with the selected number as the primary `TEL` and the
	// partner's other available lines as backups. The link expires; re-call this
	// endpoint to mint a fresh one.
	VcfURL string `json:"vcf_url" api:"required" format:"uri"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		PhoneNumber respjson.Field
		VcfURL      respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

The line smart number assignment selected, plus a shareable vCard.

func (AvailableNumberGetResponse) RawJSON added in v0.26.1

func (r AvailableNumberGetResponse) RawJSON() string

Returns the unmodified JSON received from the API

func (*AvailableNumberGetResponse) UnmarshalJSON added in v0.26.1

func (r *AvailableNumberGetResponse) UnmarshalJSON(data []byte) error

type AvailableNumberService added in v0.26.1

type AvailableNumberService struct {
	Options []option.RequestOption
}

Phone Numbers represent the phone numbers assigned to your partner account.

Use the list phone numbers endpoint to discover which phone numbers are available for sending messages.

When creating chats, listing chats, or sending a voice memo, use one of your assigned phone numbers in the `from` field.

**Ineligible numbers.** A number can temporarily lose the ability to deliver messages. While it is in that state, requests that would produce new activity on it — sending a message, creating a chat, reacting, typing, group actions — are rejected with `403` (error code `2027`) before anything is created. Reads keep working, so your existing chats, messages, and history stay available. Omit `from` on `POST /v3/messages` and we pick an eligible number for you, skipping ineligible ones; if none of your assigned numbers are eligible, you get `409` (no `from` number was ever chosen, so there's no specific number to blame with a `403`).

AvailableNumberService contains methods and other services that help with interacting with the linq-api-v3 API.

Note, unlike clients, this service does not read variables from the environment automatically. You should not instantiate this service directly, and instead use the NewAvailableNumberService method instead.

func NewAvailableNumberService added in v0.26.1

func NewAvailableNumberService(opts ...option.RequestOption) (r AvailableNumberService)

NewAvailableNumberService generates a new service that applies the given options to each request. These options are applied after the parent client's options (if there is one), and before any request-specific options.

func (*AvailableNumberService) Get added in v0.26.1

Returns the best available line (E.164) to send from, applying smart number assignment. Optionally pass `to` recipients to make the choice "sticky" — reusing the line an existing chat with those recipients is already on. Without `to`, the best available line is chosen, always preferring lines with a healthier reputation.

This does not reserve the line. Without `to`, the least-recently-used available line is returned — suggestions and your own sends (including an explicit `from` on chat creation) both count as use, so successive calls cycle through your available lines and traffic spreads evenly. Pass the returned `phone_number` as `from` when you create the chat to guarantee the same line.

Also returns `vcf_url`: a time-limited link to a vCard (`.vcf`) for the chosen line, carrying its contact card (name/photo) with the chosen number as the primary `TEL` and the partner's other available lines as backups. Share it with recipients so they can save the line as a contact. Lines you pass in `exclude_from` are left out of the vCard too.

type BlockedHandleBlockParams added in v0.30.0

type BlockedHandleBlockParams struct {
	// The handle to block: an E.164 phone number, an email address, an SMS short code
	// (3-8 digits), or an alphanumeric sender ID.
	Handle string `json:"handle" api:"required"`
	// Optional free-text note on why the handle was blocked
	Reason param.Opt[string] `json:"reason,omitzero"`
	// contains filtered or unexported fields
}

func (BlockedHandleBlockParams) MarshalJSON added in v0.30.0

func (r BlockedHandleBlockParams) MarshalJSON() (data []byte, err error)

func (*BlockedHandleBlockParams) UnmarshalJSON added in v0.30.0

func (r *BlockedHandleBlockParams) UnmarshalJSON(data []byte) error

type BlockedHandleBlockResponse added in v0.30.0

type BlockedHandleBlockResponse struct {
	BlockedHandle BlockedHandleEntry `json:"blocked_handle" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		BlockedHandle respjson.Field
		ExtraFields   map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (BlockedHandleBlockResponse) RawJSON added in v0.30.0

func (r BlockedHandleBlockResponse) RawJSON() string

Returns the unmodified JSON received from the API

func (*BlockedHandleBlockResponse) UnmarshalJSON added in v0.30.0

func (r *BlockedHandleBlockResponse) UnmarshalJSON(data []byte) error

type BlockedHandleEntry added in v0.30.0

type BlockedHandleEntry struct {
	// When the handle was blocked
	BlockedAt time.Time `json:"blocked_at" api:"required" format:"date-time"`
	// The blocked handle, normalized (E.164 phone, lowercased email, short code, or
	// sender ID)
	Handle string `json:"handle" api:"required"`
	// Optional note recorded when the handle was blocked
	Reason string `json:"reason"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		BlockedAt   respjson.Field
		Handle      respjson.Field
		Reason      respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (BlockedHandleEntry) RawJSON added in v0.30.0

func (r BlockedHandleEntry) RawJSON() string

Returns the unmodified JSON received from the API

func (*BlockedHandleEntry) UnmarshalJSON added in v0.30.0

func (r *BlockedHandleEntry) UnmarshalJSON(data []byte) error

type BlockedHandleListResponse added in v0.30.0

type BlockedHandleListResponse struct {
	// All handles blocked by the partner, newest first
	BlockedHandles []BlockedHandleEntry `json:"blocked_handles" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		BlockedHandles respjson.Field
		ExtraFields    map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (BlockedHandleListResponse) RawJSON added in v0.30.0

func (r BlockedHandleListResponse) RawJSON() string

Returns the unmodified JSON received from the API

func (*BlockedHandleListResponse) UnmarshalJSON added in v0.30.0

func (r *BlockedHandleListResponse) UnmarshalJSON(data []byte) error

type BlockedHandleService added in v0.30.0

type BlockedHandleService struct {
	Options []option.RequestOption
}

Block handles — phone numbers, email addresses, SMS short codes, or sender IDs. Inbound messages from a blocked handle are dropped before they reach your webhooks, and direct sends to a blocked handle are rejected with `403` (error code `2026`). Group sends that include unblocked members are not restricted.

BlockedHandleService contains methods and other services that help with interacting with the linq-api-v3 API.

Note, unlike clients, this service does not read variables from the environment automatically. You should not instantiate this service directly, and instead use the NewBlockedHandleService method instead.

func NewBlockedHandleService added in v0.30.0

func NewBlockedHandleService(opts ...option.RequestOption) (r BlockedHandleService)

NewBlockedHandleService generates a new service that applies the given options to each request. These options are applied after the parent client's options (if there is one), and before any request-specific options.

func (*BlockedHandleService) Block added in v0.30.0

Blocks a handle — an E.164 phone number, an email address (iMessage sender), an SMS short code (e.g. `262966`), or an alphanumeric sender ID. Inbound messages from it are dropped and produce no webhooks, and direct sends to it are rejected with `403` (error code `2026`); group sends that include unblocked members are not restricted. Blocking is idempotent — re-blocking an already blocked handle returns the existing entry.

func (*BlockedHandleService) List added in v0.30.0

Returns all handles you have blocked. Inbound messages from a blocked handle are dropped and produce no webhooks, and direct sends to a blocked handle are rejected with `403` (error code `2026`). Group sends that include unblocked members are not restricted.

func (*BlockedHandleService) Unblock added in v0.30.0

Removes a handle from your blocklist. Inbound messages from it will be delivered again and sends to it are allowed again. The handle goes in the request body, mirroring block — no URL encoding needed.

type BlockedHandleUnblockParams added in v0.30.0

type BlockedHandleUnblockParams struct {
	// The handle to unblock
	Handle string `json:"handle" api:"required"`
	// contains filtered or unexported fields
}

func (BlockedHandleUnblockParams) MarshalJSON added in v0.30.0

func (r BlockedHandleUnblockParams) MarshalJSON() (data []byte, err error)

func (*BlockedHandleUnblockParams) UnmarshalJSON added in v0.30.0

func (r *BlockedHandleUnblockParams) UnmarshalJSON(data []byte) error

type CapabilityCheckIMessageParams added in v0.25.0

type CapabilityCheckIMessageParams struct {
	HandleCheck HandleCheckParam
	// contains filtered or unexported fields
}

func (CapabilityCheckIMessageParams) MarshalJSON added in v0.25.0

func (r CapabilityCheckIMessageParams) MarshalJSON() (data []byte, err error)

func (*CapabilityCheckIMessageParams) UnmarshalJSON added in v0.25.0

func (r *CapabilityCheckIMessageParams) UnmarshalJSON(data []byte) error

type CapabilityCheckRCSParams added in v0.2.0

type CapabilityCheckRCSParams struct {
	HandleCheck HandleCheckParam
	// contains filtered or unexported fields
}

func (CapabilityCheckRCSParams) MarshalJSON added in v0.2.0

func (r CapabilityCheckRCSParams) MarshalJSON() (data []byte, err error)

func (*CapabilityCheckRCSParams) UnmarshalJSON added in v0.2.0

func (r *CapabilityCheckRCSParams) UnmarshalJSON(data []byte) error

type CapabilityService

type CapabilityService struct {
	Options []option.RequestOption
}

Check whether a recipient address supports iMessage or RCS before sending a message.

CapabilityService contains methods and other services that help with interacting with the linq-api-v3 API.

Note, unlike clients, this service does not read variables from the environment automatically. You should not instantiate this service directly, and instead use the NewCapabilityService method instead.

func NewCapabilityService

func NewCapabilityService(opts ...option.RequestOption) (r CapabilityService)

NewCapabilityService generates a new service that applies the given options to each request. These options are applied after the parent client's options (if there is one), and before any request-specific options.

func (*CapabilityService) CheckIMessage added in v0.25.0

Check whether a recipient address (phone number or email) is reachable via iMessage.

func (*CapabilityService) CheckRCS added in v0.2.0

Check whether a recipient address (phone number) supports RCS messaging.

`address` must be an E.164 phone number. RCS has no email addressing, so an email is rejected with a `400` rather than attempted.

A `200` means the check ran and the answer is about the **recipient**. A `503` means the check could not produce an answer because of a fault on the **sender** line — `4004` (RCS not turned on for the line), `4009` (line has no RCS account), or `4010` (the check could not run). Treat all three as "unknown", never as "the recipient does not support RCS", and do not cache them as a negative result.

type Chat

type Chat struct {
	// Unique identifier for the chat
	ID string `json:"id" api:"required" format:"uuid"`
	// When the chat was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// Display name for the chat. Defaults to a comma-separated list of recipient
	// handles. Can be updated for group chats.
	DisplayName string `json:"display_name" api:"required"`
	// List of chat participants with full handle details. Always contains at least two
	// handles (your phone number and the other participant).
	Handles []shared.ChatHandle `json:"handles" api:"required"`
	// **[BETA]** Current health for a chat. Always present — chats start at `HEALTHY`
	// and may shift based on engagement and delivery signals on the conversation. Many
	// `AT_RISK` or `CRITICAL` chats on a single line increase the risk of line
	// flagging.
	//
	// Switch on `status` to surface chat and line health in your UI — the enum is the
	// long-term contract. Each status carries a `doc_url` that deep-links to the
	// relevant section of the Chat Health guide. To gate a send, act on the response
	// rather than the status: a `403` is the authoritative answer.
	//
	// See the [Chat Health guide](/channel/imessage/guides/chats/chat-health) for what
	// each status means and how to react.
	HealthStatus ChatHealthStatus `json:"health_status" api:"required"`
	// **DEPRECATED:** This field is deprecated and will be removed in a future API
	// version.
	//
	// Deprecated: is_archived is no longer a useful signal
	IsArchived bool `json:"is_archived" api:"required"`
	// Whether this is a group chat
	IsGroup bool `json:"is_group" api:"required"`
	// When the chat was last updated
	UpdatedAt time.Time `json:"updated_at" api:"required" format:"date-time"`
	// URL of the group chat icon. Only set for group chats that have an icon; `null`
	// otherwise.
	GroupChatIcon string `json:"group_chat_icon" api:"nullable" format:"uri"`
	// Messaging service type
	//
	// Any of "iMessage", "SMS", "RCS".
	Service shared.ServiceType `json:"service" api:"nullable"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ID            respjson.Field
		CreatedAt     respjson.Field
		DisplayName   respjson.Field
		Handles       respjson.Field
		HealthStatus  respjson.Field
		IsArchived    respjson.Field
		IsGroup       respjson.Field
		UpdatedAt     respjson.Field
		GroupChatIcon respjson.Field
		Service       respjson.Field
		ExtraFields   map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (Chat) RawJSON

func (r Chat) RawJSON() string

Returns the unmodified JSON received from the API

func (*Chat) UnmarshalJSON

func (r *Chat) UnmarshalJSON(data []byte) error

type ChatBackgroundService added in v0.34.0

type ChatBackgroundService struct {
	Options []option.RequestOption
}

A Chat is a conversation thread with one or more participants.

To begin a chat, you must create a Chat with at least one recipient handle. Including multiple handles creates a group chat.

When creating a chat, the `from` field specifies which of your authorized phone numbers the message originates from. Your authentication token grants access to one or more phone numbers, but the `from` field determines the actual sender.

**Handle Format:**

  • Handles can be phone numbers or email addresses
  • Phone numbers MUST be in E.164 format (starting with +)
  • Phone format: `+[country code][subscriber number]`
  • Example phone: `+12223334444` (US), `+442071234567` (UK), `+81312345678` (Japan)
  • Example email: `user@example.com`
  • No spaces, dashes, or parentheses in phone numbers

ChatBackgroundService contains methods and other services that help with interacting with the linq-api-v3 API.

Note, unlike clients, this service does not read variables from the environment automatically. You should not instantiate this service directly, and instead use the NewChatBackgroundService method instead.

func NewChatBackgroundService added in v0.34.0

func NewChatBackgroundService(opts ...option.RequestOption) (r ChatBackgroundService)

NewChatBackgroundService generates a new service that applies the given options to each request. These options are applied after the parent client's options (if there is one), and before any request-specific options.

func (*ChatBackgroundService) Remove added in v0.34.0

func (r *ChatBackgroundService) Remove(ctx context.Context, chatID string, opts ...option.RequestOption) (err error)

Remove the transcript background from a chat, resetting it to the default.

func (*ChatBackgroundService) Set added in v0.34.0

Set the transcript background for a chat.

Provide one of: a **color** (a named preset or a custom 2-stop gradient), a **dynamic** animated style, or a **photo** (by URL). The request is accepted asynchronously; the terminal result arrives via the `chat.background_updated` webhook on success, or `chat.background_update_failed` on failure.

**Group chats are supported.** Requests for RCS or SMS chats are accepted (`202`) but no background is applied and no `chat.background_updated` webhook fires.

type ChatBackgroundSetParams added in v0.34.0

type ChatBackgroundSetParams struct {
	// The background family.
	//
	// Any of "color", "dynamic", "photo".
	Type ChatBackgroundSetParamsType `json:"type,omitzero" api:"required"`
	// Photo: the image URL to embed in the background. Must be an absolute `https` URL
	// pointing at an image (`.jpg`, `.png`, `.heic`, `.webp`), and the image is
	// fetched and re-hosted on our CDN before the request is accepted — the same way
	// `group_chat_icon` works. A URL we cannot fetch, or one that isn't an image, is
	// rejected with a `400` (`5007`/`5006`) rather than failing later on the device.
	//
	// Example: `https://cdn.linqapp.com/u/bg.jpg`.
	ImageURL param.Opt[string] `json:"image_url,omitzero" format:"uri"`
	// Color: a named swatch — `mango`, `ice`, `plum`, `deep_sea`, `green_apple`,
	// `cherry`, `bubblegum`, `tangerine`, `magenta`, `lime`, `silver`, `carbon`,
	// `stone` — or `custom` (supply `shades`). Omitting `variant` is equivalent to
	// `custom`, so it still requires `shades`.
	//
	// Dynamic: required — the variant within the `style`. `sky`: `dusk`, `haze`,
	// `sunset`, `clear`, `sunrise`, `dawn`. `water`: `light`, `dark`. `aurora`:
	// `green`, `purple`, `pink`.
	//
	// An unrecognized value is rejected with `400`.
	Variant param.Opt[string] `json:"variant,omitzero"`
	// Color with `variant: custom`: the two gradient stops as hex, top then bottom —
	// e.g. `["#F2C4E1", "#F5A623"]`. Ignored for named color variants (they carry
	// their own two colors).
	Shades []string `json:"shades,omitzero"`
	// Dynamic: the animated style — `sky`, `water`, or `aurora`.
	//
	// Any of "sky", "water", "aurora".
	Style ChatBackgroundSetParamsStyle `json:"style,omitzero"`
	// contains filtered or unexported fields
}

func (ChatBackgroundSetParams) MarshalJSON added in v0.34.0

func (r ChatBackgroundSetParams) MarshalJSON() (data []byte, err error)

func (*ChatBackgroundSetParams) UnmarshalJSON added in v0.34.0

func (r *ChatBackgroundSetParams) UnmarshalJSON(data []byte) error

type ChatBackgroundSetParamsStyle added in v0.34.0

type ChatBackgroundSetParamsStyle string

Dynamic: the animated style — `sky`, `water`, or `aurora`.

const (
	ChatBackgroundSetParamsStyleSky    ChatBackgroundSetParamsStyle = "sky"
	ChatBackgroundSetParamsStyleWater  ChatBackgroundSetParamsStyle = "water"
	ChatBackgroundSetParamsStyleAurora ChatBackgroundSetParamsStyle = "aurora"
)

type ChatBackgroundSetParamsType added in v0.34.0

type ChatBackgroundSetParamsType string

The background family.

const (
	ChatBackgroundSetParamsTypeColor   ChatBackgroundSetParamsType = "color"
	ChatBackgroundSetParamsTypeDynamic ChatBackgroundSetParamsType = "dynamic"
	ChatBackgroundSetParamsTypePhoto   ChatBackgroundSetParamsType = "photo"
)

type ChatBackgroundUpdateFailedWebhookEvent added in v0.41.0

type ChatBackgroundUpdateFailedWebhookEvent struct {
	// API version for the webhook payload format
	APIVersion string `json:"api_version" api:"required"`
	// When the event was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// Error details for chat.background_update_failed webhook events. See
	// [WebhookErrorCode](#/components/schemas/WebhookErrorCode) for the full error
	// code reference.
	Data ChatBackgroundUpdateFailedWebhookEventData `json:"data" api:"required"`
	// Unique identifier for this event (for deduplication)
	EventID string `json:"event_id" api:"required" format:"uuid"`
	// Valid webhook event types that can be subscribed to.
	//
	// **Note:** `message.edited` is only delivered to subscriptions using
	// `webhook_version: "2026-02-03"`. Subscribing to this event on a v2025
	// subscription will not produce any deliveries.
	//
	// Any of "message.sent", "message.received", "message.read", "message.delivered",
	// "message.failed", "message.edited", "reaction.added", "reaction.removed",
	// "poll.received", "poll.failed", "poll.sent", "poll.delivered", "poll.read",
	// "poll.updated", "poll.vote.added", "poll.vote.removed", "poll.reaction.added",
	// "participant.added", "participant.removed", "chat.created",
	// "chat.group_name_updated", "chat.group_icon_updated",
	// "chat.group_name_update_failed", "chat.group_icon_update_failed",
	// "chat.background_updated", "chat.background_update_failed",
	// "chat.typing_indicator.started", "chat.typing_indicator.stopped",
	// "phone_number.status_updated", "contact_card.received", "call.initiated",
	// "call.ringing", "call.answered", "call.ended", "call.failed", "call.declined",
	// "call.no_answer", "location.sharing.started", "location.sharing.stopped",
	// "payment.succeeded", "payment.canceled", "payment.expired", "payment.declined",
	// "payment.authorized", "connection.created", "connection.revoked".
	EventType WebhookEventType `json:"event_type" api:"required"`
	// Partner identifier. Present on all webhooks for cross-referencing.
	PartnerID string `json:"partner_id" api:"required"`
	// Trace ID for debugging and correlation across systems.
	TraceID string `json:"trace_id" api:"required"`
	// Date-based webhook payload version. Determined by the `?version=` query
	// parameter in your webhook subscription URL. If no version parameter is
	// specified, defaults based on subscription creation date.
	WebhookVersion string `json:"webhook_version" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		APIVersion     respjson.Field
		CreatedAt      respjson.Field
		Data           respjson.Field
		EventID        respjson.Field
		EventType      respjson.Field
		PartnerID      respjson.Field
		TraceID        respjson.Field
		WebhookVersion respjson.Field
		ExtraFields    map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Complete webhook payload for chat.background_update_failed events

func (ChatBackgroundUpdateFailedWebhookEvent) RawJSON added in v0.41.0

Returns the unmodified JSON received from the API

func (*ChatBackgroundUpdateFailedWebhookEvent) UnmarshalJSON added in v0.41.0

func (r *ChatBackgroundUpdateFailedWebhookEvent) UnmarshalJSON(data []byte) error

type ChatBackgroundUpdateFailedWebhookEventData added in v0.41.0

type ChatBackgroundUpdateFailedWebhookEventData struct {
	// Chat identifier (UUID) whose background update failed
	ChatID string `json:"chat_id" api:"required"`
	// Error codes in webhook failure events. The possible set varies by event:
	// message.failed and poll.failed can carry 3007, 4001, 4002, 4005, 4006, 4007, or
	// 4008; the group update failure events (chat.group_name_update_failed,
	// chat.group_icon_update_failed) carry 3007 or 4001; chat.background_update_failed
	// carries 1005, 2011, 4001, or 5002.
	ErrorCode int64 `json:"error_code" api:"required"`
	// When the failure was detected
	FailedAt time.Time `json:"failed_at" api:"required" format:"date-time"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ChatID      respjson.Field
		ErrorCode   respjson.Field
		FailedAt    respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Error details for chat.background_update_failed webhook events. See [WebhookErrorCode](#/components/schemas/WebhookErrorCode) for the full error code reference.

func (ChatBackgroundUpdateFailedWebhookEventData) RawJSON added in v0.41.0

Returns the unmodified JSON received from the API

func (*ChatBackgroundUpdateFailedWebhookEventData) UnmarshalJSON added in v0.41.0

func (r *ChatBackgroundUpdateFailedWebhookEventData) UnmarshalJSON(data []byte) error

type ChatBackgroundUpdatedWebhookEvent added in v0.34.0

type ChatBackgroundUpdatedWebhookEvent struct {
	// API version for the webhook payload format
	APIVersion string `json:"api_version" api:"required"`
	// When the event was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// Payload for chat.background_updated webhook events.
	Data ChatBackgroundUpdatedWebhookEventData `json:"data" api:"required"`
	// Unique identifier for this event (for deduplication)
	EventID string `json:"event_id" api:"required" format:"uuid"`
	// Valid webhook event types that can be subscribed to.
	//
	// **Note:** `message.edited` is only delivered to subscriptions using
	// `webhook_version: "2026-02-03"`. Subscribing to this event on a v2025
	// subscription will not produce any deliveries.
	//
	// Any of "message.sent", "message.received", "message.read", "message.delivered",
	// "message.failed", "message.edited", "reaction.added", "reaction.removed",
	// "poll.received", "poll.failed", "poll.sent", "poll.delivered", "poll.read",
	// "poll.updated", "poll.vote.added", "poll.vote.removed", "poll.reaction.added",
	// "participant.added", "participant.removed", "chat.created",
	// "chat.group_name_updated", "chat.group_icon_updated",
	// "chat.group_name_update_failed", "chat.group_icon_update_failed",
	// "chat.background_updated", "chat.background_update_failed",
	// "chat.typing_indicator.started", "chat.typing_indicator.stopped",
	// "phone_number.status_updated", "contact_card.received", "call.initiated",
	// "call.ringing", "call.answered", "call.ended", "call.failed", "call.declined",
	// "call.no_answer", "location.sharing.started", "location.sharing.stopped",
	// "payment.succeeded", "payment.canceled", "payment.expired", "payment.declined",
	// "payment.authorized", "connection.created", "connection.revoked".
	EventType WebhookEventType `json:"event_type" api:"required"`
	// Partner identifier. Present on all webhooks for cross-referencing.
	PartnerID string `json:"partner_id" api:"required"`
	// Trace ID for debugging and correlation across systems.
	TraceID string `json:"trace_id" api:"required"`
	// Date-based webhook payload version. Determined by the `?version=` query
	// parameter in your webhook subscription URL. If no version parameter is
	// specified, defaults based on subscription creation date.
	WebhookVersion string `json:"webhook_version" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		APIVersion     respjson.Field
		CreatedAt      respjson.Field
		Data           respjson.Field
		EventID        respjson.Field
		EventType      respjson.Field
		PartnerID      respjson.Field
		TraceID        respjson.Field
		WebhookVersion respjson.Field
		ExtraFields    map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Complete webhook payload for chat.background_updated events

func (ChatBackgroundUpdatedWebhookEvent) RawJSON added in v0.34.0

Returns the unmodified JSON received from the API

func (*ChatBackgroundUpdatedWebhookEvent) UnmarshalJSON added in v0.34.0

func (r *ChatBackgroundUpdatedWebhookEvent) UnmarshalJSON(data []byte) error

type ChatBackgroundUpdatedWebhookEventData added in v0.34.0

type ChatBackgroundUpdatedWebhookEventData struct {
	// Chat information
	Chat ChatBackgroundUpdatedWebhookEventDataChat `json:"chat" api:"required"`
	// Who changed it. `is_me` is true when your own number set it.
	ActorHandle shared.ChatHandle `json:"actor_handle" api:"nullable"`
	// A chat transcript background. Fields are populated per `type`.
	Background ChatBackgroundUpdatedWebhookEventDataBackground `json:"background" api:"nullable"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Chat        respjson.Field
		ActorHandle respjson.Field
		Background  respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Payload for chat.background_updated webhook events.

func (ChatBackgroundUpdatedWebhookEventData) RawJSON added in v0.34.0

Returns the unmodified JSON received from the API

func (*ChatBackgroundUpdatedWebhookEventData) UnmarshalJSON added in v0.34.0

func (r *ChatBackgroundUpdatedWebhookEventData) UnmarshalJSON(data []byte) error

type ChatBackgroundUpdatedWebhookEventDataBackground added in v0.34.0

type ChatBackgroundUpdatedWebhookEventDataBackground struct {
	// The background family.
	//
	// Any of "color", "dynamic", "photo".
	Type string `json:"type" api:"required"`
	// Photo: a hosted URL for the background image, whether you set it or a
	// participant did. Apple stores the image, not the URL it came from, so the image
	// is re-hosted and this is our URL rather than the one you supplied. `null` only
	// if the image could not be hosted.
	ImageURL string `json:"image_url" api:"nullable"`
	// Color: the two gradient stops as hex, top then bottom.
	Shades []string `json:"shades" api:"nullable"`
	// Dynamic: the animated style.
	//
	// Any of "sky", "water", "aurora", "glitter".
	Style string `json:"style" api:"nullable"`
	// Color: `custom` (the stored two colors) or a named swatch. Dynamic: the variant
	// within the `style` (e.g. `sunrise`).
	Variant string `json:"variant" api:"nullable"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Type        respjson.Field
		ImageURL    respjson.Field
		Shades      respjson.Field
		Style       respjson.Field
		Variant     respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

A chat transcript background. Fields are populated per `type`.

func (ChatBackgroundUpdatedWebhookEventDataBackground) RawJSON added in v0.34.0

Returns the unmodified JSON received from the API

func (*ChatBackgroundUpdatedWebhookEventDataBackground) UnmarshalJSON added in v0.34.0

type ChatBackgroundUpdatedWebhookEventDataChat added in v0.34.0

type ChatBackgroundUpdatedWebhookEventDataChat struct {
	// Chat identifier
	ID string `json:"id" api:"required" format:"uuid"`
	// Whether this is a group chat
	IsGroup bool `json:"is_group" api:"nullable"`
	// Your phone number's handle. Always has is_me=true.
	OwnerHandle shared.ChatHandle `json:"owner_handle" api:"nullable"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ID          respjson.Field
		IsGroup     respjson.Field
		OwnerHandle respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Chat information

func (ChatBackgroundUpdatedWebhookEventDataChat) RawJSON added in v0.34.0

Returns the unmodified JSON received from the API

func (*ChatBackgroundUpdatedWebhookEventDataChat) UnmarshalJSON added in v0.34.0

func (r *ChatBackgroundUpdatedWebhookEventDataChat) UnmarshalJSON(data []byte) error

type ChatCreatedWebhookEvent added in v0.12.0

type ChatCreatedWebhookEvent struct {
	// API version for the webhook payload format
	APIVersion string `json:"api_version" api:"required"`
	// When the event was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// Payload for chat.created webhook events. Matches GET /v3/chats/{chatId}
	// response.
	Data ChatCreatedWebhookEventData `json:"data" api:"required"`
	// Unique identifier for this event (for deduplication)
	EventID string `json:"event_id" api:"required" format:"uuid"`
	// Valid webhook event types that can be subscribed to.
	//
	// **Note:** `message.edited` is only delivered to subscriptions using
	// `webhook_version: "2026-02-03"`. Subscribing to this event on a v2025
	// subscription will not produce any deliveries.
	//
	// Any of "message.sent", "message.received", "message.read", "message.delivered",
	// "message.failed", "message.edited", "reaction.added", "reaction.removed",
	// "poll.received", "poll.failed", "poll.sent", "poll.delivered", "poll.read",
	// "poll.updated", "poll.vote.added", "poll.vote.removed", "poll.reaction.added",
	// "participant.added", "participant.removed", "chat.created",
	// "chat.group_name_updated", "chat.group_icon_updated",
	// "chat.group_name_update_failed", "chat.group_icon_update_failed",
	// "chat.background_updated", "chat.background_update_failed",
	// "chat.typing_indicator.started", "chat.typing_indicator.stopped",
	// "phone_number.status_updated", "contact_card.received", "call.initiated",
	// "call.ringing", "call.answered", "call.ended", "call.failed", "call.declined",
	// "call.no_answer", "location.sharing.started", "location.sharing.stopped",
	// "payment.succeeded", "payment.canceled", "payment.expired", "payment.declined",
	// "payment.authorized", "connection.created", "connection.revoked".
	EventType WebhookEventType `json:"event_type" api:"required"`
	// Partner identifier. Present on all webhooks for cross-referencing.
	PartnerID string `json:"partner_id" api:"required"`
	// Trace ID for debugging and correlation across systems.
	TraceID string `json:"trace_id" api:"required"`
	// Date-based webhook payload version. Determined by the `?version=` query
	// parameter in your webhook subscription URL. If no version parameter is
	// specified, defaults based on subscription creation date.
	WebhookVersion string `json:"webhook_version" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		APIVersion     respjson.Field
		CreatedAt      respjson.Field
		Data           respjson.Field
		EventID        respjson.Field
		EventType      respjson.Field
		PartnerID      respjson.Field
		TraceID        respjson.Field
		WebhookVersion respjson.Field
		ExtraFields    map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Complete webhook payload for chat.created events

func (ChatCreatedWebhookEvent) RawJSON added in v0.12.0

func (r ChatCreatedWebhookEvent) RawJSON() string

Returns the unmodified JSON received from the API

func (*ChatCreatedWebhookEvent) UnmarshalJSON added in v0.12.0

func (r *ChatCreatedWebhookEvent) UnmarshalJSON(data []byte) error

type ChatCreatedWebhookEventData added in v0.12.0

type ChatCreatedWebhookEventData struct {
	// Unique identifier for the chat
	ID string `json:"id" api:"required" format:"uuid"`
	// When the chat was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// Display name for the chat. Defaults to a comma-separated list of recipient
	// handles. Can be updated for group chats.
	DisplayName string `json:"display_name" api:"required"`
	// List of chat participants with full handle details. Always contains at least two
	// handles (your phone number and the other participant).
	Handles []shared.ChatHandle `json:"handles" api:"required"`
	// **[BETA]** Current health for a chat. Always present — chats start at `HEALTHY`
	// and may shift based on engagement and delivery signals on the conversation. Many
	// `AT_RISK` or `CRITICAL` chats on a single line increase the risk of line
	// flagging.
	//
	// Switch on `status` to surface chat and line health in your UI — the enum is the
	// long-term contract. Each status carries a `doc_url` that deep-links to the
	// relevant section of the Chat Health guide. To gate a send, act on the response
	// rather than the status: a `403` is the authoritative answer.
	//
	// See the [Chat Health guide](/channel/imessage/guides/chats/chat-health) for what
	// each status means and how to react.
	HealthStatus ChatCreatedWebhookEventDataHealthStatus `json:"health_status" api:"required"`
	// Whether this is a group chat
	IsGroup bool `json:"is_group" api:"required"`
	// When the chat was last updated
	UpdatedAt time.Time `json:"updated_at" api:"required" format:"date-time"`
	// Messaging service type
	//
	// Any of "iMessage", "SMS", "RCS".
	Service shared.ServiceType `json:"service" api:"nullable"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ID           respjson.Field
		CreatedAt    respjson.Field
		DisplayName  respjson.Field
		Handles      respjson.Field
		HealthStatus respjson.Field
		IsGroup      respjson.Field
		UpdatedAt    respjson.Field
		Service      respjson.Field
		ExtraFields  map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Payload for chat.created webhook events. Matches GET /v3/chats/{chatId} response.

func (ChatCreatedWebhookEventData) RawJSON added in v0.12.0

func (r ChatCreatedWebhookEventData) RawJSON() string

Returns the unmodified JSON received from the API

func (*ChatCreatedWebhookEventData) UnmarshalJSON added in v0.12.0

func (r *ChatCreatedWebhookEventData) UnmarshalJSON(data []byte) error

type ChatCreatedWebhookEventDataHealthStatus added in v0.19.0

type ChatCreatedWebhookEventDataHealthStatus struct {
	// Deep-link to the relevant section of the Chat Health guide for this status.
	DocURL string `json:"doc_url" api:"required" format:"uri"`
	// Current health bucket for the chat. See the
	// [Chat Health guide](/channel/imessage/guides/chats/chat-health) for what each
	// value means and how to react. `doc_url` deep-links to the relevant section.
	//
	// `OPTED_OUT` — the recipient sent `STOP`, `UNSUBSCRIBE`, `OPTOUT`, `CANCEL`,
	// `END`, or `QUIT`. The keyword must be the whole trimmed message, never part of a
	// longer one: `STOP` counts, `please stop` does not. Most keywords must match
	// exactly, including case. `OPT OUT` is the exception — it matches in any casing,
	// with or without the space or a hyphen, so `opt out`, `Opt-Out` and `optout` all
	// count. It clears as soon as they reply again: any later message from them that
	// is not itself an opt-out keyword opts them back in immediately — a reply in any
	// conversation with you counts, the same way the block does.
	//
	// `OPTED_OUT` marks only the conversation the keyword arrived in. The block below
	// is wider than the mark, so a conversation still reading `HEALTHY` can be blocked
	// as well — gate on the `403`, not on the status. Group threads are never marked
	// and are never blocked.
	//
	// Linq enforces this: while a recipient is opted out, every send to them is
	// rejected with `403` (error code `2024`) before the message is queued, across
	// every chat and every line on your account. Nothing is delivered, including a
	// final courtesy message — to send one, set `override_optout: true` on that single
	// request.
	//
	// Any of "HEALTHY", "AT_RISK", "CRITICAL", "OPTED_OUT".
	Status string `json:"status" api:"required"`
	// When this status last changed.
	UpdatedAt time.Time `json:"updated_at" api:"required" format:"date-time"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		DocURL      respjson.Field
		Status      respjson.Field
		UpdatedAt   respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

**[BETA]** Current health for a chat. Always present — chats start at `HEALTHY` and may shift based on engagement and delivery signals on the conversation. Many `AT_RISK` or `CRITICAL` chats on a single line increase the risk of line flagging.

Switch on `status` to surface chat and line health in your UI — the enum is the long-term contract. Each status carries a `doc_url` that deep-links to the relevant section of the Chat Health guide. To gate a send, act on the response rather than the status: a `403` is the authoritative answer.

See the [Chat Health guide](/channel/imessage/guides/chats/chat-health) for what each status means and how to react.

func (ChatCreatedWebhookEventDataHealthStatus) RawJSON added in v0.19.0

Returns the unmodified JSON received from the API

func (*ChatCreatedWebhookEventDataHealthStatus) UnmarshalJSON added in v0.19.0

func (r *ChatCreatedWebhookEventDataHealthStatus) UnmarshalJSON(data []byte) error

type ChatGroupIconUpdateFailedWebhookEvent added in v0.12.0

type ChatGroupIconUpdateFailedWebhookEvent struct {
	// API version for the webhook payload format
	APIVersion string `json:"api_version" api:"required"`
	// When the event was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// Error details for chat.group_icon_update_failed webhook events. See
	// [WebhookErrorCode](#/components/schemas/WebhookErrorCode) for the full error
	// code reference.
	Data ChatGroupIconUpdateFailedWebhookEventData `json:"data" api:"required"`
	// Unique identifier for this event (for deduplication)
	EventID string `json:"event_id" api:"required" format:"uuid"`
	// Valid webhook event types that can be subscribed to.
	//
	// **Note:** `message.edited` is only delivered to subscriptions using
	// `webhook_version: "2026-02-03"`. Subscribing to this event on a v2025
	// subscription will not produce any deliveries.
	//
	// Any of "message.sent", "message.received", "message.read", "message.delivered",
	// "message.failed", "message.edited", "reaction.added", "reaction.removed",
	// "poll.received", "poll.failed", "poll.sent", "poll.delivered", "poll.read",
	// "poll.updated", "poll.vote.added", "poll.vote.removed", "poll.reaction.added",
	// "participant.added", "participant.removed", "chat.created",
	// "chat.group_name_updated", "chat.group_icon_updated",
	// "chat.group_name_update_failed", "chat.group_icon_update_failed",
	// "chat.background_updated", "chat.background_update_failed",
	// "chat.typing_indicator.started", "chat.typing_indicator.stopped",
	// "phone_number.status_updated", "contact_card.received", "call.initiated",
	// "call.ringing", "call.answered", "call.ended", "call.failed", "call.declined",
	// "call.no_answer", "location.sharing.started", "location.sharing.stopped",
	// "payment.succeeded", "payment.canceled", "payment.expired", "payment.declined",
	// "payment.authorized", "connection.created", "connection.revoked".
	EventType WebhookEventType `json:"event_type" api:"required"`
	// Partner identifier. Present on all webhooks for cross-referencing.
	PartnerID string `json:"partner_id" api:"required"`
	// Trace ID for debugging and correlation across systems.
	TraceID string `json:"trace_id" api:"required"`
	// Date-based webhook payload version. Determined by the `?version=` query
	// parameter in your webhook subscription URL. If no version parameter is
	// specified, defaults based on subscription creation date.
	WebhookVersion string `json:"webhook_version" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		APIVersion     respjson.Field
		CreatedAt      respjson.Field
		Data           respjson.Field
		EventID        respjson.Field
		EventType      respjson.Field
		PartnerID      respjson.Field
		TraceID        respjson.Field
		WebhookVersion respjson.Field
		ExtraFields    map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Complete webhook payload for chat.group_icon_update_failed events

func (ChatGroupIconUpdateFailedWebhookEvent) RawJSON added in v0.12.0

Returns the unmodified JSON received from the API

func (*ChatGroupIconUpdateFailedWebhookEvent) UnmarshalJSON added in v0.12.0

func (r *ChatGroupIconUpdateFailedWebhookEvent) UnmarshalJSON(data []byte) error

type ChatGroupIconUpdateFailedWebhookEventData added in v0.12.0

type ChatGroupIconUpdateFailedWebhookEventData struct {
	// Chat identifier (UUID) of the group chat
	ChatID string `json:"chat_id" api:"required"`
	// Error codes in webhook failure events. The possible set varies by event:
	// message.failed and poll.failed can carry 3007, 4001, 4002, 4005, 4006, 4007, or
	// 4008; the group update failure events (chat.group_name_update_failed,
	// chat.group_icon_update_failed) carry 3007 or 4001; chat.background_update_failed
	// carries 1005, 2011, 4001, or 5002.
	ErrorCode int64 `json:"error_code" api:"required"`
	// When the failure was detected
	FailedAt time.Time `json:"failed_at" api:"required" format:"date-time"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ChatID      respjson.Field
		ErrorCode   respjson.Field
		FailedAt    respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Error details for chat.group_icon_update_failed webhook events. See [WebhookErrorCode](#/components/schemas/WebhookErrorCode) for the full error code reference.

func (ChatGroupIconUpdateFailedWebhookEventData) RawJSON added in v0.12.0

Returns the unmodified JSON received from the API

func (*ChatGroupIconUpdateFailedWebhookEventData) UnmarshalJSON added in v0.12.0

func (r *ChatGroupIconUpdateFailedWebhookEventData) UnmarshalJSON(data []byte) error

type ChatGroupIconUpdatedWebhookEvent added in v0.12.0

type ChatGroupIconUpdatedWebhookEvent struct {
	// API version for the webhook payload format
	APIVersion string `json:"api_version" api:"required"`
	// When the event was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// Payload for chat.group_icon_updated webhook events
	Data ChatGroupIconUpdatedWebhookEventData `json:"data" api:"required"`
	// Unique identifier for this event (for deduplication)
	EventID string `json:"event_id" api:"required" format:"uuid"`
	// Valid webhook event types that can be subscribed to.
	//
	// **Note:** `message.edited` is only delivered to subscriptions using
	// `webhook_version: "2026-02-03"`. Subscribing to this event on a v2025
	// subscription will not produce any deliveries.
	//
	// Any of "message.sent", "message.received", "message.read", "message.delivered",
	// "message.failed", "message.edited", "reaction.added", "reaction.removed",
	// "poll.received", "poll.failed", "poll.sent", "poll.delivered", "poll.read",
	// "poll.updated", "poll.vote.added", "poll.vote.removed", "poll.reaction.added",
	// "participant.added", "participant.removed", "chat.created",
	// "chat.group_name_updated", "chat.group_icon_updated",
	// "chat.group_name_update_failed", "chat.group_icon_update_failed",
	// "chat.background_updated", "chat.background_update_failed",
	// "chat.typing_indicator.started", "chat.typing_indicator.stopped",
	// "phone_number.status_updated", "contact_card.received", "call.initiated",
	// "call.ringing", "call.answered", "call.ended", "call.failed", "call.declined",
	// "call.no_answer", "location.sharing.started", "location.sharing.stopped",
	// "payment.succeeded", "payment.canceled", "payment.expired", "payment.declined",
	// "payment.authorized", "connection.created", "connection.revoked".
	EventType WebhookEventType `json:"event_type" api:"required"`
	// Partner identifier. Present on all webhooks for cross-referencing.
	PartnerID string `json:"partner_id" api:"required"`
	// Trace ID for debugging and correlation across systems.
	TraceID string `json:"trace_id" api:"required"`
	// Date-based webhook payload version. Determined by the `?version=` query
	// parameter in your webhook subscription URL. If no version parameter is
	// specified, defaults based on subscription creation date.
	WebhookVersion string `json:"webhook_version" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		APIVersion     respjson.Field
		CreatedAt      respjson.Field
		Data           respjson.Field
		EventID        respjson.Field
		EventType      respjson.Field
		PartnerID      respjson.Field
		TraceID        respjson.Field
		WebhookVersion respjson.Field
		ExtraFields    map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Complete webhook payload for chat.group_icon_updated events

func (ChatGroupIconUpdatedWebhookEvent) RawJSON added in v0.12.0

Returns the unmodified JSON received from the API

func (*ChatGroupIconUpdatedWebhookEvent) UnmarshalJSON added in v0.12.0

func (r *ChatGroupIconUpdatedWebhookEvent) UnmarshalJSON(data []byte) error

type ChatGroupIconUpdatedWebhookEventData added in v0.12.0

type ChatGroupIconUpdatedWebhookEventData struct {
	// Chat identifier (UUID) of the group chat
	ChatID string `json:"chat_id" api:"required"`
	// When the update occurred
	UpdatedAt time.Time `json:"updated_at" api:"required" format:"date-time"`
	// The handle who made the change.
	ChangedByHandle shared.ChatHandle `json:"changed_by_handle" api:"nullable"`
	// New icon URL (null if the icon was removed)
	NewValue string `json:"new_value" api:"nullable"`
	// Previous icon URL (null if no previous icon)
	OldValue string `json:"old_value" api:"nullable"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ChatID          respjson.Field
		UpdatedAt       respjson.Field
		ChangedByHandle respjson.Field
		NewValue        respjson.Field
		OldValue        respjson.Field
		ExtraFields     map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Payload for chat.group_icon_updated webhook events

func (ChatGroupIconUpdatedWebhookEventData) RawJSON added in v0.12.0

Returns the unmodified JSON received from the API

func (*ChatGroupIconUpdatedWebhookEventData) UnmarshalJSON added in v0.12.0

func (r *ChatGroupIconUpdatedWebhookEventData) UnmarshalJSON(data []byte) error

type ChatGroupNameUpdateFailedWebhookEvent added in v0.12.0

type ChatGroupNameUpdateFailedWebhookEvent struct {
	// API version for the webhook payload format
	APIVersion string `json:"api_version" api:"required"`
	// When the event was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// Error details for chat.group_name_update_failed webhook events. See
	// [WebhookErrorCode](#/components/schemas/WebhookErrorCode) for the full error
	// code reference.
	Data ChatGroupNameUpdateFailedWebhookEventData `json:"data" api:"required"`
	// Unique identifier for this event (for deduplication)
	EventID string `json:"event_id" api:"required" format:"uuid"`
	// Valid webhook event types that can be subscribed to.
	//
	// **Note:** `message.edited` is only delivered to subscriptions using
	// `webhook_version: "2026-02-03"`. Subscribing to this event on a v2025
	// subscription will not produce any deliveries.
	//
	// Any of "message.sent", "message.received", "message.read", "message.delivered",
	// "message.failed", "message.edited", "reaction.added", "reaction.removed",
	// "poll.received", "poll.failed", "poll.sent", "poll.delivered", "poll.read",
	// "poll.updated", "poll.vote.added", "poll.vote.removed", "poll.reaction.added",
	// "participant.added", "participant.removed", "chat.created",
	// "chat.group_name_updated", "chat.group_icon_updated",
	// "chat.group_name_update_failed", "chat.group_icon_update_failed",
	// "chat.background_updated", "chat.background_update_failed",
	// "chat.typing_indicator.started", "chat.typing_indicator.stopped",
	// "phone_number.status_updated", "contact_card.received", "call.initiated",
	// "call.ringing", "call.answered", "call.ended", "call.failed", "call.declined",
	// "call.no_answer", "location.sharing.started", "location.sharing.stopped",
	// "payment.succeeded", "payment.canceled", "payment.expired", "payment.declined",
	// "payment.authorized", "connection.created", "connection.revoked".
	EventType WebhookEventType `json:"event_type" api:"required"`
	// Partner identifier. Present on all webhooks for cross-referencing.
	PartnerID string `json:"partner_id" api:"required"`
	// Trace ID for debugging and correlation across systems.
	TraceID string `json:"trace_id" api:"required"`
	// Date-based webhook payload version. Determined by the `?version=` query
	// parameter in your webhook subscription URL. If no version parameter is
	// specified, defaults based on subscription creation date.
	WebhookVersion string `json:"webhook_version" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		APIVersion     respjson.Field
		CreatedAt      respjson.Field
		Data           respjson.Field
		EventID        respjson.Field
		EventType      respjson.Field
		PartnerID      respjson.Field
		TraceID        respjson.Field
		WebhookVersion respjson.Field
		ExtraFields    map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Complete webhook payload for chat.group_name_update_failed events

func (ChatGroupNameUpdateFailedWebhookEvent) RawJSON added in v0.12.0

Returns the unmodified JSON received from the API

func (*ChatGroupNameUpdateFailedWebhookEvent) UnmarshalJSON added in v0.12.0

func (r *ChatGroupNameUpdateFailedWebhookEvent) UnmarshalJSON(data []byte) error

type ChatGroupNameUpdateFailedWebhookEventData added in v0.12.0

type ChatGroupNameUpdateFailedWebhookEventData struct {
	// Chat identifier (UUID) of the group chat
	ChatID string `json:"chat_id" api:"required"`
	// Error codes in webhook failure events. The possible set varies by event:
	// message.failed and poll.failed can carry 3007, 4001, 4002, 4005, 4006, 4007, or
	// 4008; the group update failure events (chat.group_name_update_failed,
	// chat.group_icon_update_failed) carry 3007 or 4001; chat.background_update_failed
	// carries 1005, 2011, 4001, or 5002.
	ErrorCode int64 `json:"error_code" api:"required"`
	// When the failure was detected
	FailedAt time.Time `json:"failed_at" api:"required" format:"date-time"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ChatID      respjson.Field
		ErrorCode   respjson.Field
		FailedAt    respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Error details for chat.group_name_update_failed webhook events. See [WebhookErrorCode](#/components/schemas/WebhookErrorCode) for the full error code reference.

func (ChatGroupNameUpdateFailedWebhookEventData) RawJSON added in v0.12.0

Returns the unmodified JSON received from the API

func (*ChatGroupNameUpdateFailedWebhookEventData) UnmarshalJSON added in v0.12.0

func (r *ChatGroupNameUpdateFailedWebhookEventData) UnmarshalJSON(data []byte) error

type ChatGroupNameUpdatedWebhookEvent added in v0.12.0

type ChatGroupNameUpdatedWebhookEvent struct {
	// API version for the webhook payload format
	APIVersion string `json:"api_version" api:"required"`
	// When the event was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// Payload for chat.group_name_updated webhook events
	Data ChatGroupNameUpdatedWebhookEventData `json:"data" api:"required"`
	// Unique identifier for this event (for deduplication)
	EventID string `json:"event_id" api:"required" format:"uuid"`
	// Valid webhook event types that can be subscribed to.
	//
	// **Note:** `message.edited` is only delivered to subscriptions using
	// `webhook_version: "2026-02-03"`. Subscribing to this event on a v2025
	// subscription will not produce any deliveries.
	//
	// Any of "message.sent", "message.received", "message.read", "message.delivered",
	// "message.failed", "message.edited", "reaction.added", "reaction.removed",
	// "poll.received", "poll.failed", "poll.sent", "poll.delivered", "poll.read",
	// "poll.updated", "poll.vote.added", "poll.vote.removed", "poll.reaction.added",
	// "participant.added", "participant.removed", "chat.created",
	// "chat.group_name_updated", "chat.group_icon_updated",
	// "chat.group_name_update_failed", "chat.group_icon_update_failed",
	// "chat.background_updated", "chat.background_update_failed",
	// "chat.typing_indicator.started", "chat.typing_indicator.stopped",
	// "phone_number.status_updated", "contact_card.received", "call.initiated",
	// "call.ringing", "call.answered", "call.ended", "call.failed", "call.declined",
	// "call.no_answer", "location.sharing.started", "location.sharing.stopped",
	// "payment.succeeded", "payment.canceled", "payment.expired", "payment.declined",
	// "payment.authorized", "connection.created", "connection.revoked".
	EventType WebhookEventType `json:"event_type" api:"required"`
	// Partner identifier. Present on all webhooks for cross-referencing.
	PartnerID string `json:"partner_id" api:"required"`
	// Trace ID for debugging and correlation across systems.
	TraceID string `json:"trace_id" api:"required"`
	// Date-based webhook payload version. Determined by the `?version=` query
	// parameter in your webhook subscription URL. If no version parameter is
	// specified, defaults based on subscription creation date.
	WebhookVersion string `json:"webhook_version" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		APIVersion     respjson.Field
		CreatedAt      respjson.Field
		Data           respjson.Field
		EventID        respjson.Field
		EventType      respjson.Field
		PartnerID      respjson.Field
		TraceID        respjson.Field
		WebhookVersion respjson.Field
		ExtraFields    map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Complete webhook payload for chat.group_name_updated events

func (ChatGroupNameUpdatedWebhookEvent) RawJSON added in v0.12.0

Returns the unmodified JSON received from the API

func (*ChatGroupNameUpdatedWebhookEvent) UnmarshalJSON added in v0.12.0

func (r *ChatGroupNameUpdatedWebhookEvent) UnmarshalJSON(data []byte) error

type ChatGroupNameUpdatedWebhookEventData added in v0.12.0

type ChatGroupNameUpdatedWebhookEventData struct {
	// Chat identifier (UUID) of the group chat
	ChatID string `json:"chat_id" api:"required"`
	// When the update occurred
	UpdatedAt time.Time `json:"updated_at" api:"required" format:"date-time"`
	// The handle who made the change.
	ChangedByHandle shared.ChatHandle `json:"changed_by_handle" api:"nullable"`
	// New group name (null if the name was removed)
	NewValue string `json:"new_value" api:"nullable"`
	// Previous group name (null if no previous name)
	OldValue string `json:"old_value" api:"nullable"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ChatID          respjson.Field
		UpdatedAt       respjson.Field
		ChangedByHandle respjson.Field
		NewValue        respjson.Field
		OldValue        respjson.Field
		ExtraFields     map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Payload for chat.group_name_updated webhook events

func (ChatGroupNameUpdatedWebhookEventData) RawJSON added in v0.12.0

Returns the unmodified JSON received from the API

func (*ChatGroupNameUpdatedWebhookEventData) UnmarshalJSON added in v0.12.0

func (r *ChatGroupNameUpdatedWebhookEventData) UnmarshalJSON(data []byte) error

type ChatHandle

type ChatHandle = shared.ChatHandle

This is an alias to an internal type.

type ChatHandleStatus

type ChatHandleStatus = shared.ChatHandleStatus

Participant status

This is an alias to an internal type.

type ChatHealthStatus added in v0.19.0

type ChatHealthStatus struct {
	// Deep-link to the relevant section of the Chat Health guide for this status.
	DocURL string `json:"doc_url" api:"required" format:"uri"`
	// Current health bucket for the chat. See the
	// [Chat Health guide](/channel/imessage/guides/chats/chat-health) for what each
	// value means and how to react. `doc_url` deep-links to the relevant section.
	//
	// `OPTED_OUT` — the recipient sent `STOP`, `UNSUBSCRIBE`, `OPTOUT`, `CANCEL`,
	// `END`, or `QUIT`. The keyword must be the whole trimmed message, never part of a
	// longer one: `STOP` counts, `please stop` does not. Most keywords must match
	// exactly, including case. `OPT OUT` is the exception — it matches in any casing,
	// with or without the space or a hyphen, so `opt out`, `Opt-Out` and `optout` all
	// count. It clears as soon as they reply again: any later message from them that
	// is not itself an opt-out keyword opts them back in immediately — a reply in any
	// conversation with you counts, the same way the block does.
	//
	// `OPTED_OUT` marks only the conversation the keyword arrived in. The block below
	// is wider than the mark, so a conversation still reading `HEALTHY` can be blocked
	// as well — gate on the `403`, not on the status. Group threads are never marked
	// and are never blocked.
	//
	// Linq enforces this: while a recipient is opted out, every send to them is
	// rejected with `403` (error code `2024`) before the message is queued, across
	// every chat and every line on your account. Nothing is delivered, including a
	// final courtesy message — to send one, set `override_optout: true` on that single
	// request.
	//
	// Any of "HEALTHY", "AT_RISK", "CRITICAL", "OPTED_OUT".
	Status string `json:"status" api:"required"`
	// When this status last changed.
	UpdatedAt time.Time `json:"updated_at" api:"required" format:"date-time"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		DocURL      respjson.Field
		Status      respjson.Field
		UpdatedAt   respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

**[BETA]** Current health for a chat. Always present — chats start at `HEALTHY` and may shift based on engagement and delivery signals on the conversation. Many `AT_RISK` or `CRITICAL` chats on a single line increase the risk of line flagging.

Switch on `status` to surface chat and line health in your UI — the enum is the long-term contract. Each status carries a `doc_url` that deep-links to the relevant section of the Chat Health guide. To gate a send, act on the response rather than the status: a `403` is the authoritative answer.

See the [Chat Health guide](/channel/imessage/guides/chats/chat-health) for what each status means and how to react.

func (ChatHealthStatus) RawJSON added in v0.19.0

func (r ChatHealthStatus) RawJSON() string

Returns the unmodified JSON received from the API

func (*ChatHealthStatus) UnmarshalJSON added in v0.19.0

func (r *ChatHealthStatus) UnmarshalJSON(data []byte) error

type ChatLeaveChatResponse added in v0.8.0

type ChatLeaveChatResponse struct {
	Message string `json:"message"`
	Status  string `json:"status"`
	TraceID string `json:"trace_id"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Message     respjson.Field
		Status      respjson.Field
		TraceID     respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (ChatLeaveChatResponse) RawJSON added in v0.8.0

func (r ChatLeaveChatResponse) RawJSON() string

Returns the unmodified JSON received from the API

func (*ChatLeaveChatResponse) UnmarshalJSON added in v0.8.0

func (r *ChatLeaveChatResponse) UnmarshalJSON(data []byte) error

type ChatListChatsParams added in v0.2.0

type ChatListChatsParams struct {
	// Pagination cursor from the previous response's `next_cursor` field. Omit this
	// parameter for the first page of results.
	Cursor param.Opt[string] `query:"cursor,omitzero" json:"-"`
	// Phone number to filter chats by. Returns chats made from this phone number. Must
	// be in E.164 format (e.g., `+13343284472`). The `+` is automatically URL-encoded
	// by HTTP clients. If omitted, returns chats across all phone numbers owned by the
	// partner.
	From param.Opt[string] `query:"from,omitzero" json:"-"`
	// Maximum number of chats to return per page
	Limit param.Opt[int64] `query:"limit,omitzero" json:"-"`
	// Filter chats by a participant handle. Only returns chats where this handle is a
	// participant. Can be an E.164 phone number (e.g., `+13343284472`) or an email
	// address (e.g., `user@example.com`). For phone numbers, the `+` is automatically
	// URL-encoded by HTTP clients.
	To param.Opt[string] `query:"to,omitzero" json:"-"`
	// contains filtered or unexported fields
}

func (ChatListChatsParams) URLQuery added in v0.2.0

func (r ChatListChatsParams) URLQuery() (v url.Values, err error)

URLQuery serializes ChatListChatsParams's query parameters as `url.Values`.

type ChatLocationService added in v0.23.0

type ChatLocationService struct {
	Options []option.RequestOption
}

Request a contact's location, retrieve location for contacts sharing with you, and subscribe to webhooks when someone starts or stops sharing.

**Coordinates** are returned in [GeoJSON](https://datatracker.ietf.org/doc/html/rfc7946) format: `[longitude, latitude]`.

### Reading location is poll-based

Poll `GET /v3/chats/{chatId}/location` whenever you need the latest position. **There is no webhook that pushes updated coordinates** — the `location.sharing.started` / `location.sharing.stopped` webhooks fire only when a contact begins or ends sharing, not on each position update. To track a moving contact, poll the `GET` endpoint.

### Freshness

Each feature's `properties.updated_at` tells you when that participant's location was last updated — use it to judge freshness.

### Polling guidance

Locations refresh on Apple's cadence, not per request — polling faster than a participant's location actually updates just returns the same position. Poll at a modest interval (for example, once every few minutes per chat) rather than continuously.

### Why is location empty after `location.sharing.started` fired?

If the contact started sharing from the **standalone Find My app** instead of the Messages conversation, the share may be tied to their **Apple ID email** rather than their phone number — the webhook's `shared_by` field shows the email in that case. Location is readable only through a chat with the handle that shared, so `GET /v3/chats/{chatId}/location` on the phone-number chat stays empty.

The fix: have the contact stop sharing and re-share from **Find My inside the Messages conversation** with your number.

ChatLocationService contains methods and other services that help with interacting with the linq-api-v3 API.

Note, unlike clients, this service does not read variables from the environment automatically. You should not instantiate this service directly, and instead use the NewChatLocationService method instead.

func NewChatLocationService added in v0.23.0

func NewChatLocationService(opts ...option.RequestOption) (r ChatLocationService)

NewChatLocationService generates a new service that applies the given options to each request. These options are applied after the parent client's options (if there is one), and before any request-specific options.

func (*ChatLocationService) Get added in v0.23.0

Retrieve the current location for contacts sharing with you in a chat.

The response is wrapped in the standard `{ "success": true, "data": ... }` envelope — the body is **not** a bare GeoJSON document. `data` is a [GeoJSON](https://datatracker.ietf.org/doc/html/rfc7946) `FeatureCollection` with a `Feature` for each participant actively sharing their location.

Works for both 1:1 and group chats. In group chats, `data.features` contains a separate feature for each participant who is sharing. Each feature's `properties.handle` identifies the user.

A participant appears as soon as their first position arrives, typically within a second or two of sharing starting.

Returns an empty `data.features` array if no one is sharing or no location data is available yet. If sharing started but this stays empty, see the **Location Sharing** overview.

Poll this endpoint to track a moving contact. `properties.updated_at` reflects when each participant's location was last updated. There is no coordinate-update webhook. See the **Location Sharing** overview for polling guidance.

func (*ChatLocationService) Request added in v0.23.0

func (r *ChatLocationService) Request(ctx context.Context, chatID string, opts ...option.RequestOption) (res *LocationRequestResponse, err error)

Request a contact in a chat to share their location. They receive an iMessage prompt and must accept before any location is available; once they do, read their location coordinates with `GET /v3/chats/{chatId}/location`.

The request is delivered asynchronously. The endpoint returns immediately with `{ "success": true, "message": "Location request sent" }` and does not return coordinates.

Rejected with `409` if the recipient is already sharing — read their location with `GET /v3/chats/{chatId}/location` instead of re-requesting.

Rate limited per chat, since each request prompts the recipient's device. Exceeding it returns `429` with a `Retry-After` header.

Location requests only work in **1:1 iMessage chats** (Apple limitation):

  • Group chats (any service) return `409` with code `2016` (`GroupChatNotSupported`).
  • 1:1 SMS and RCS chats return `409` with code `2017` (`ChatServiceNotSupported`).

type ChatMessageListParams

type ChatMessageListParams struct {
	// Pagination cursor from previous next_cursor response
	Cursor param.Opt[string] `query:"cursor,omitzero" json:"-"`
	// Maximum number of messages to return
	Limit param.Opt[int64] `query:"limit,omitzero" json:"-"`
	// contains filtered or unexported fields
}

func (ChatMessageListParams) URLQuery

func (r ChatMessageListParams) URLQuery() (v url.Values, err error)

URLQuery serializes ChatMessageListParams's query parameters as `url.Values`.

type ChatMessageSendParams

type ChatMessageSendParams struct {
	// Message content container. Groups all message-related fields together,
	// separating the "what" (message content) from the "where" (routing fields like
	// from/to).
	//
	// A message carries EITHER `parts` — text and attachments, which compose into one
	// bubble — or a single `experience` invocation, which renders an experience inside
	// Linq's iMessage app. Never both: an app card is the whole message (Apple's
	// `MSMessage` cannot coexist with text), so copy and a card are two sends, not
	// one.
	Message MessageContentParam `json:"message,omitzero" api:"required"`
	// Send even though the recipient asked you to stop (`403`, error code `2024`).
	// Applies to this request only: the opt-out stays in place, so the next send
	// without this flag is rejected again. Every override is recorded against your API
	// key.
	OverrideOptout param.Opt[bool] `json:"override_optout,omitzero"`
	// contains filtered or unexported fields
}

func (ChatMessageSendParams) MarshalJSON

func (r ChatMessageSendParams) MarshalJSON() (data []byte, err error)

func (*ChatMessageSendParams) UnmarshalJSON

func (r *ChatMessageSendParams) UnmarshalJSON(data []byte) error

type ChatMessageSendResponse

type ChatMessageSendResponse struct {
	// Unique identifier of the chat this message was sent to
	ChatID string `json:"chat_id" api:"required" format:"uuid"`
	// A message that was sent (used in CreateChat and SendMessage responses)
	Message SentMessage `json:"message" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ChatID      respjson.Field
		Message     respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Response for sending a message to a chat

func (ChatMessageSendResponse) RawJSON

func (r ChatMessageSendResponse) RawJSON() string

Returns the unmodified JSON received from the API

func (*ChatMessageSendResponse) UnmarshalJSON

func (r *ChatMessageSendResponse) UnmarshalJSON(data []byte) error

type ChatMessageService

type ChatMessageService struct {
	Options []option.RequestOption
}

Messages are individual communications within a chat thread.

Messages can include text, media attachments, rich link previews, special effects (like confetti or fireworks), and reactions. All messages are associated with a specific chat and sent from a phone number you own.

Messages support delivery status tracking, read receipts, and editing capabilities.

## Rich Link Previews

Send a URL as a `link` part to deliver it with a rich preview card showing the page's title, description, and image (when available). A `link` part must be the **only** part in the message — it cannot be combined with text or media parts. To send a URL without a preview card, include it in a `text` part instead.

**Limitations:**

- A `link` part cannot be combined with other parts in the same message. - Maximum URL length: 2,048 characters.

## App Clips

An `app_clip` part sends a **registered App Clip** — not only Linq's Apple Pay checkout, but any partner's own App Clip. Like a `link` part it must be the **only** part in the message, and it is **iMessage only** — it never downgrades to SMS or RCS. The payment-checkout use of this part is covered in the **Payments** section.

## Ephemeral Messages (Privacy Tier)

For regulated or sensitive conversations, opt in to the **ephemeral messages** tier by contacting your Linq support contact. When enabled, every message on the covered phone numbers is given a **retention window configured for your account**. After that window, the message's text, formatting, and attachment references are no longer retrievable through the API — see the Attachments row below for how the attachment media itself is handled. Metadata about the message is retained: message identifiers, timestamps, phone numbers, and delivery state. Metadata retention is not bounded by this window. Bounded operational copies, such as backups and delivery queues, expire on their own separate schedules. There is no per-message flag; ephemerality is applied automatically based on your configuration.

The window can be set anywhere from **60 minutes to 24 hours**, and defaults to **24 hours**. Ask your Linq support contact to configure a shorter window; it cannot be changed through the API.

You can request it at two scopes:

| Scope | Effect | | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Partner-wide** | Every outbound and inbound message on every phone number under your account has its content removed from the API surface after your configured window. Metadata is retained. | | **Per phone number** | Only the specified phone numbers have message content removed from the API surface this way. The rest follow the standard message-retention policy. |

**Behavioral differences vs the standard default:**

| Aspect | Standard | Ephemeral | | ----------------------- | -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Retention | Retained per the standard message-retention policy | **Hard backstop: your configured window** (60 minutes – 24 hours, default 24 hours) from when the message is created | | After expiry | Message stays retrievable | Message content is no longer retrievable — `GET /v3/messages/{messageId}` returns `404` and it no longer appears in `GET /v3/chats/{chatId}/messages` | | Content on expiry | N/A | Text, formatting, and attachment references are removed from the API surface, not blanked out in place. Metadata (identifiers, timestamps, phone numbers, delivery state) is retained; its retention is not bounded by this window | | Attachments | Retained | Media sent on the **ephemeral attachments tier** is removed on its own storage backstop — within roughly 24–48 hours of upload — independently of the message window, so it can outlast a window shorter than a day. Attachments on the persistent tier (including pre-uploads via `POST /v3/attachments`) are kept until you `DELETE` them | | Cross-partner isolation | Enforced | Enforced |

**How the retention window works:**

  • The window runs from **message creation** (`created_at`). It is configured for your account (60 minutes – 24 hours, default 24 hours) and cannot be set per message.
  • Attachment media follows its own storage backstop rather than the message window — see the Attachments row above.
  • Expiry is delivery-independent — the clock starts when the message is created, not when it is delivered or read.
  • **Deletion happens shortly _after_ the window, not exactly at it.** A background sweep runs every ~5 minutes, so a message typically stops being retrievable within about 5 minutes of its expiry, and longer while a backlog is being worked through. Treat the window as the guaranteed _minimum_ retention, never as an exact deletion time or an upper bound.

**What you observe:**

  • **No expiry timestamp is exposed.** API responses and webhook payloads do not include the deletion time, and they do not report your configured window either — so if you are on a window shorter than 24 hours you cannot derive a message's expiry from the API today. Track the window you agreed with your Linq support contact and compute `created_at + window` yourself.
  • **No deletion webhook is sent.** There is no `message.deleted` event — a message simply stops being retrievable once its window passes.
  • **The attachment backstop is separate from the message window.** API retrievability (the `404` behavior above) ends at your configured window. Ephemeral-tier media objects are removed on their own storage backstop — within roughly 24–48 hours of upload — which is independent of the message window and can outlast a window shorter than a day. Removal of the corresponding entries from the sending device happens asynchronously and can complete after the backstop.
  • **Delivery is unaffected.** Ephemeral messages send, deliver, and fire the usual `message.sent` / `message.received` and status webhooks exactly like standard messages. Only retention changes.

**When to choose ephemeral:**

  • You have a compliance requirement that the platform must not retain message content beyond a short window.
  • The conversation is high-sensitivity (PHI, financial, identity verification) and you do not want it sitting in storage long-term.
  • Your application is the system of record — you capture what you need from the delivery webhook in real time and do not rely on reading message history back from Linq later.

**Important:** ephemeral applies in _both directions_ — messages you send **and** messages received by the phone numbers in that scope. Because Linq can no longer return the message once its window passes, persist anything you need to keep from the webhook payload at the time it is delivered.

ChatMessageService contains methods and other services that help with interacting with the linq-api-v3 API.

Note, unlike clients, this service does not read variables from the environment automatically. You should not instantiate this service directly, and instead use the NewChatMessageService method instead.

func NewChatMessageService

func NewChatMessageService(opts ...option.RequestOption) (r ChatMessageService)

NewChatMessageService generates a new service that applies the given options to each request. These options are applied after the parent client's options (if there is one), and before any request-specific options.

func (*ChatMessageService) List

Retrieve messages from a specific chat with pagination support.

func (*ChatMessageService) ListAutoPaging added in v0.2.0

Retrieve messages from a specific chat with pagination support.

func (*ChatMessageService) Send

Send a message to an existing chat. Use this endpoint when you already have a chat ID and want to send additional messages to it.

## Message Effects

You can add iMessage effects to make your messages more expressive. Effects are optional and can be either screen effects (full-screen animations) or bubble effects (message bubble animations).

**Screen Effects:** `confetti`, `fireworks`, `lasers`, `sparkles`, `celebration`, `hearts`, `love`, `balloons`, `happy_birthday`, `echo`, `spotlight`

**Bubble Effects:** `slam`, `loud`, `gentle`, `invisible`

Only one effect type can be applied per message.

## Inline Text Decorations (iMessage only)

Use the `text_decorations` array on a text part to apply styling and animations to character ranges.

Each decoration specifies a `range: [start, end)` and exactly one of `style` or `animation`.

**Styles:** `bold`, `italic`, `strikethrough`, `underline` **Animations:** `big`, `small`, `shake`, `nod`, `explode`, `ripple`, `bloom`, `jitter`

```json

{
  "type": "text",
  "value": "Hello world",
  "text_decorations": [
    { "range": [0, 5], "style": "bold" },
    { "range": [6, 11], "animation": "shake" }
  ]
}

```

**Note:** Style ranges (bold, italic, etc.) may overlap, but animation ranges must not overlap with other animations or styles. Decorations render per recipient, not per message: in a group with both iMessage and SMS/RCS participants, iMessage recipients see the decorations and SMS/RCS recipients receive the same message as plain text.

type ChatNewParams

type ChatNewParams struct {
	// Sender phone number in E.164 format. Must be a phone number that the
	// authenticated partner has permission to send from.
	From string `json:"from" api:"required"`
	// Message content container. Groups all message-related fields together,
	// separating the "what" (message content) from the "where" (routing fields like
	// from/to).
	//
	// A message carries EITHER `parts` — text and attachments, which compose into one
	// bubble — or a single `experience` invocation, which renders an experience inside
	// Linq's iMessage app. Never both: an app card is the whole message (Apple's
	// `MSMessage` cannot coexist with text), so copy and a card are two sends, not
	// one.
	Message MessageContentParam `json:"message,omitzero" api:"required"`
	// Array of recipient handles (phone numbers in E.164 format or email addresses).
	// For individual chats, provide one recipient. For group chats, provide multiple.
	To []string `json:"to,omitzero" api:"required"`
	// Send even though the recipient asked you to stop (`403`, error code `2024`).
	// Applies to this request only: the opt-out stays in place, so the next send
	// without this flag is rejected again. Every override is recorded against your API
	// key.
	OverrideOptout param.Opt[bool] `json:"override_optout,omitzero"`
	// contains filtered or unexported fields
}

func (ChatNewParams) MarshalJSON

func (r ChatNewParams) MarshalJSON() (data []byte, err error)

func (*ChatNewParams) UnmarshalJSON

func (r *ChatNewParams) UnmarshalJSON(data []byte) error

type ChatNewResponse

type ChatNewResponse struct {
	Chat ChatNewResponseChat `json:"chat" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Chat        respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Response for creating a new chat with an initial message

func (ChatNewResponse) RawJSON

func (r ChatNewResponse) RawJSON() string

Returns the unmodified JSON received from the API

func (*ChatNewResponse) UnmarshalJSON

func (r *ChatNewResponse) UnmarshalJSON(data []byte) error

type ChatNewResponseChat

type ChatNewResponseChat struct {
	// Unique identifier for the created chat (UUID)
	ID string `json:"id" api:"required" format:"uuid"`
	// Display name for the chat. Defaults to a comma-separated list of recipient
	// handles. Can be updated for group chats.
	DisplayName string `json:"display_name" api:"required"`
	// List of participants in the chat. Always contains at least two handles (your
	// phone number and the other participant).
	Handles []shared.ChatHandle `json:"handles" api:"required"`
	// **[BETA]** Current health for a chat. Always present — chats start at `HEALTHY`
	// and may shift based on engagement and delivery signals on the conversation. Many
	// `AT_RISK` or `CRITICAL` chats on a single line increase the risk of line
	// flagging.
	//
	// Switch on `status` to surface chat and line health in your UI — the enum is the
	// long-term contract. Each status carries a `doc_url` that deep-links to the
	// relevant section of the Chat Health guide. To gate a send, act on the response
	// rather than the status: a `403` is the authoritative answer.
	//
	// See the [Chat Health guide](/channel/imessage/guides/chats/chat-health) for what
	// each status means and how to react.
	HealthStatus ChatNewResponseChatHealthStatus `json:"health_status" api:"required"`
	// Whether this is a group chat
	IsGroup bool `json:"is_group" api:"required"`
	// A message that was sent (used in CreateChat and SendMessage responses)
	Message SentMessage `json:"message" api:"required"`
	// Messaging service type
	//
	// Any of "iMessage", "SMS", "RCS".
	Service shared.ServiceType `json:"service" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ID           respjson.Field
		DisplayName  respjson.Field
		Handles      respjson.Field
		HealthStatus respjson.Field
		IsGroup      respjson.Field
		Message      respjson.Field
		Service      respjson.Field
		ExtraFields  map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (ChatNewResponseChat) RawJSON

func (r ChatNewResponseChat) RawJSON() string

Returns the unmodified JSON received from the API

func (*ChatNewResponseChat) UnmarshalJSON

func (r *ChatNewResponseChat) UnmarshalJSON(data []byte) error

type ChatNewResponseChatHealthStatus added in v0.19.0

type ChatNewResponseChatHealthStatus struct {
	// Deep-link to the relevant section of the Chat Health guide for this status.
	DocURL string `json:"doc_url" api:"required" format:"uri"`
	// Current health bucket for the chat. See the
	// [Chat Health guide](/channel/imessage/guides/chats/chat-health) for what each
	// value means and how to react. `doc_url` deep-links to the relevant section.
	//
	// `OPTED_OUT` — the recipient sent `STOP`, `UNSUBSCRIBE`, `OPTOUT`, `CANCEL`,
	// `END`, or `QUIT`. The keyword must be the whole trimmed message, never part of a
	// longer one: `STOP` counts, `please stop` does not. Most keywords must match
	// exactly, including case. `OPT OUT` is the exception — it matches in any casing,
	// with or without the space or a hyphen, so `opt out`, `Opt-Out` and `optout` all
	// count. It clears as soon as they reply again: any later message from them that
	// is not itself an opt-out keyword opts them back in immediately — a reply in any
	// conversation with you counts, the same way the block does.
	//
	// `OPTED_OUT` marks only the conversation the keyword arrived in. The block below
	// is wider than the mark, so a conversation still reading `HEALTHY` can be blocked
	// as well — gate on the `403`, not on the status. Group threads are never marked
	// and are never blocked.
	//
	// Linq enforces this: while a recipient is opted out, every send to them is
	// rejected with `403` (error code `2024`) before the message is queued, across
	// every chat and every line on your account. Nothing is delivered, including a
	// final courtesy message — to send one, set `override_optout: true` on that single
	// request.
	//
	// Any of "HEALTHY", "AT_RISK", "CRITICAL", "OPTED_OUT".
	Status string `json:"status" api:"required"`
	// When this status last changed.
	UpdatedAt time.Time `json:"updated_at" api:"required" format:"date-time"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		DocURL      respjson.Field
		Status      respjson.Field
		UpdatedAt   respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

**[BETA]** Current health for a chat. Always present — chats start at `HEALTHY` and may shift based on engagement and delivery signals on the conversation. Many `AT_RISK` or `CRITICAL` chats on a single line increase the risk of line flagging.

Switch on `status` to surface chat and line health in your UI — the enum is the long-term contract. Each status carries a `doc_url` that deep-links to the relevant section of the Chat Health guide. To gate a send, act on the response rather than the status: a `403` is the authoritative answer.

See the [Chat Health guide](/channel/imessage/guides/chats/chat-health) for what each status means and how to react.

func (ChatNewResponseChatHealthStatus) RawJSON added in v0.19.0

Returns the unmodified JSON received from the API

func (*ChatNewResponseChatHealthStatus) UnmarshalJSON added in v0.19.0

func (r *ChatNewResponseChatHealthStatus) UnmarshalJSON(data []byte) error

type ChatParticipantAddParams

type ChatParticipantAddParams struct {
	// Phone number (E.164 format) or email address of the participant to add
	Handle string `json:"handle" api:"required"`
	// contains filtered or unexported fields
}

func (ChatParticipantAddParams) MarshalJSON

func (r ChatParticipantAddParams) MarshalJSON() (data []byte, err error)

func (*ChatParticipantAddParams) UnmarshalJSON

func (r *ChatParticipantAddParams) UnmarshalJSON(data []byte) error

type ChatParticipantAddResponse

type ChatParticipantAddResponse struct {
	Message string `json:"message"`
	Status  string `json:"status"`
	TraceID string `json:"trace_id"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Message     respjson.Field
		Status      respjson.Field
		TraceID     respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (ChatParticipantAddResponse) RawJSON

func (r ChatParticipantAddResponse) RawJSON() string

Returns the unmodified JSON received from the API

func (*ChatParticipantAddResponse) UnmarshalJSON

func (r *ChatParticipantAddResponse) UnmarshalJSON(data []byte) error

type ChatParticipantRemoveParams

type ChatParticipantRemoveParams struct {
	// Phone number (E.164 format) or email address of the participant to remove
	Handle string `json:"handle" api:"required"`
	// contains filtered or unexported fields
}

func (ChatParticipantRemoveParams) MarshalJSON

func (r ChatParticipantRemoveParams) MarshalJSON() (data []byte, err error)

func (*ChatParticipantRemoveParams) UnmarshalJSON

func (r *ChatParticipantRemoveParams) UnmarshalJSON(data []byte) error

type ChatParticipantRemoveResponse

type ChatParticipantRemoveResponse struct {
	Message string `json:"message"`
	Status  string `json:"status"`
	TraceID string `json:"trace_id"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Message     respjson.Field
		Status      respjson.Field
		TraceID     respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (ChatParticipantRemoveResponse) RawJSON

Returns the unmodified JSON received from the API

func (*ChatParticipantRemoveResponse) UnmarshalJSON

func (r *ChatParticipantRemoveResponse) UnmarshalJSON(data []byte) error

type ChatParticipantService

type ChatParticipantService struct {
	Options []option.RequestOption
}

A Chat is a conversation thread with one or more participants.

To begin a chat, you must create a Chat with at least one recipient handle. Including multiple handles creates a group chat.

When creating a chat, the `from` field specifies which of your authorized phone numbers the message originates from. Your authentication token grants access to one or more phone numbers, but the `from` field determines the actual sender.

**Handle Format:**

  • Handles can be phone numbers or email addresses
  • Phone numbers MUST be in E.164 format (starting with +)
  • Phone format: `+[country code][subscriber number]`
  • Example phone: `+12223334444` (US), `+442071234567` (UK), `+81312345678` (Japan)
  • Example email: `user@example.com`
  • No spaces, dashes, or parentheses in phone numbers

ChatParticipantService contains methods and other services that help with interacting with the linq-api-v3 API.

Note, unlike clients, this service does not read variables from the environment automatically. You should not instantiate this service directly, and instead use the NewChatParticipantService method instead.

func NewChatParticipantService

func NewChatParticipantService(opts ...option.RequestOption) (r ChatParticipantService)

NewChatParticipantService generates a new service that applies the given options to each request. These options are applied after the parent client's options (if there is one), and before any request-specific options.

func (*ChatParticipantService) Add

Add a new participant to an existing group chat.

**Requirements:**

  • Group chats only (3+ existing participants)
  • New participant must support the same messaging service as the group
  • Cross-service additions not allowed (e.g., can't add RCS-only user to iMessage group)
  • For cross-service scenarios, create a new chat instead

func (*ChatParticipantService) Remove

Remove a participant from an existing group chat.

**Requirements:**

- Group chats only - Must have 3+ participants after removal

type ChatPollNewParams added in v0.29.1

type ChatPollNewParams struct {
	// Poll content to create. A poll needs at least two options. Options are add-only
	// and immutable — there is no title/question (send that as a normal text message).
	Poll ChatPollNewParamsPoll `json:"poll,omitzero" api:"required"`
	// contains filtered or unexported fields
}

func (ChatPollNewParams) MarshalJSON added in v0.29.1

func (r ChatPollNewParams) MarshalJSON() (data []byte, err error)

func (*ChatPollNewParams) UnmarshalJSON added in v0.29.1

func (r *ChatPollNewParams) UnmarshalJSON(data []byte) error

type ChatPollNewParamsPoll added in v0.29.1

type ChatPollNewParamsPoll struct {
	Options []ChatPollNewParamsPollOption `json:"options,omitzero" api:"required"`
	// Optional key to deduplicate the poll creation.
	IdempotencyKey param.Opt[string] `json:"idempotency_key,omitzero"`
	// contains filtered or unexported fields
}

Poll content to create. A poll needs at least two options. Options are add-only and immutable — there is no title/question (send that as a normal text message).

The property Options is required.

func (ChatPollNewParamsPoll) MarshalJSON added in v0.29.1

func (r ChatPollNewParamsPoll) MarshalJSON() (data []byte, err error)

func (*ChatPollNewParamsPoll) UnmarshalJSON added in v0.29.1

func (r *ChatPollNewParamsPoll) UnmarshalJSON(data []byte) error

type ChatPollNewParamsPollOption added in v0.29.1

type ChatPollNewParamsPollOption struct {
	Text string `json:"text" api:"required"`
	// contains filtered or unexported fields
}

The property Text is required.

func (ChatPollNewParamsPollOption) MarshalJSON added in v0.29.1

func (r ChatPollNewParamsPollOption) MarshalJSON() (data []byte, err error)

func (*ChatPollNewParamsPollOption) UnmarshalJSON added in v0.29.1

func (r *ChatPollNewParamsPollOption) UnmarshalJSON(data []byte) error

type ChatPollService added in v0.29.1

type ChatPollService struct {
	Options []option.RequestOption
}

Messages are individual communications within a chat thread.

Messages can include text, media attachments, rich link previews, special effects (like confetti or fireworks), and reactions. All messages are associated with a specific chat and sent from a phone number you own.

Messages support delivery status tracking, read receipts, and editing capabilities.

## Rich Link Previews

Send a URL as a `link` part to deliver it with a rich preview card showing the page's title, description, and image (when available). A `link` part must be the **only** part in the message — it cannot be combined with text or media parts. To send a URL without a preview card, include it in a `text` part instead.

**Limitations:**

- A `link` part cannot be combined with other parts in the same message. - Maximum URL length: 2,048 characters.

## App Clips

An `app_clip` part sends a **registered App Clip** — not only Linq's Apple Pay checkout, but any partner's own App Clip. Like a `link` part it must be the **only** part in the message, and it is **iMessage only** — it never downgrades to SMS or RCS. The payment-checkout use of this part is covered in the **Payments** section.

## Ephemeral Messages (Privacy Tier)

For regulated or sensitive conversations, opt in to the **ephemeral messages** tier by contacting your Linq support contact. When enabled, every message on the covered phone numbers is given a **retention window configured for your account**. After that window, the message's text, formatting, and attachment references are no longer retrievable through the API — see the Attachments row below for how the attachment media itself is handled. Metadata about the message is retained: message identifiers, timestamps, phone numbers, and delivery state. Metadata retention is not bounded by this window. Bounded operational copies, such as backups and delivery queues, expire on their own separate schedules. There is no per-message flag; ephemerality is applied automatically based on your configuration.

The window can be set anywhere from **60 minutes to 24 hours**, and defaults to **24 hours**. Ask your Linq support contact to configure a shorter window; it cannot be changed through the API.

You can request it at two scopes:

| Scope | Effect | | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Partner-wide** | Every outbound and inbound message on every phone number under your account has its content removed from the API surface after your configured window. Metadata is retained. | | **Per phone number** | Only the specified phone numbers have message content removed from the API surface this way. The rest follow the standard message-retention policy. |

**Behavioral differences vs the standard default:**

| Aspect | Standard | Ephemeral | | ----------------------- | -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Retention | Retained per the standard message-retention policy | **Hard backstop: your configured window** (60 minutes – 24 hours, default 24 hours) from when the message is created | | After expiry | Message stays retrievable | Message content is no longer retrievable — `GET /v3/messages/{messageId}` returns `404` and it no longer appears in `GET /v3/chats/{chatId}/messages` | | Content on expiry | N/A | Text, formatting, and attachment references are removed from the API surface, not blanked out in place. Metadata (identifiers, timestamps, phone numbers, delivery state) is retained; its retention is not bounded by this window | | Attachments | Retained | Media sent on the **ephemeral attachments tier** is removed on its own storage backstop — within roughly 24–48 hours of upload — independently of the message window, so it can outlast a window shorter than a day. Attachments on the persistent tier (including pre-uploads via `POST /v3/attachments`) are kept until you `DELETE` them | | Cross-partner isolation | Enforced | Enforced |

**How the retention window works:**

  • The window runs from **message creation** (`created_at`). It is configured for your account (60 minutes – 24 hours, default 24 hours) and cannot be set per message.
  • Attachment media follows its own storage backstop rather than the message window — see the Attachments row above.
  • Expiry is delivery-independent — the clock starts when the message is created, not when it is delivered or read.
  • **Deletion happens shortly _after_ the window, not exactly at it.** A background sweep runs every ~5 minutes, so a message typically stops being retrievable within about 5 minutes of its expiry, and longer while a backlog is being worked through. Treat the window as the guaranteed _minimum_ retention, never as an exact deletion time or an upper bound.

**What you observe:**

  • **No expiry timestamp is exposed.** API responses and webhook payloads do not include the deletion time, and they do not report your configured window either — so if you are on a window shorter than 24 hours you cannot derive a message's expiry from the API today. Track the window you agreed with your Linq support contact and compute `created_at + window` yourself.
  • **No deletion webhook is sent.** There is no `message.deleted` event — a message simply stops being retrievable once its window passes.
  • **The attachment backstop is separate from the message window.** API retrievability (the `404` behavior above) ends at your configured window. Ephemeral-tier media objects are removed on their own storage backstop — within roughly 24–48 hours of upload — which is independent of the message window and can outlast a window shorter than a day. Removal of the corresponding entries from the sending device happens asynchronously and can complete after the backstop.
  • **Delivery is unaffected.** Ephemeral messages send, deliver, and fire the usual `message.sent` / `message.received` and status webhooks exactly like standard messages. Only retention changes.

**When to choose ephemeral:**

  • You have a compliance requirement that the platform must not retain message content beyond a short window.
  • The conversation is high-sensitivity (PHI, financial, identity verification) and you do not want it sitting in storage long-term.
  • Your application is the system of record — you capture what you need from the delivery webhook in real time and do not rely on reading message history back from Linq later.

**Important:** ephemeral applies in _both directions_ — messages you send **and** messages received by the phone numbers in that scope. Because Linq can no longer return the message once its window passes, persist anything you need to keep from the webhook payload at the time it is delivered.

ChatPollService contains methods and other services that help with interacting with the linq-api-v3 API.

Note, unlike clients, this service does not read variables from the environment automatically. You should not instantiate this service directly, and instead use the NewChatPollService method instead.

func NewChatPollService added in v0.29.1

func NewChatPollService(opts ...option.RequestOption) (r ChatPollService)

NewChatPollService generates a new service that applies the given options to each request. These options are applied after the parent client's options (if there is one), and before any request-specific options.

func (*ChatPollService) New added in v0.29.1

func (r *ChatPollService) New(ctx context.Context, chatID string, body ChatPollNewParams, opts ...option.RequestOption) (res *PollEnvelope, err error)

Create an iMessage poll in an existing chat and send it. Polls are iMessage-only.

The chat must already exist — **a poll cannot be the first message of a new chat** (use `POST /v3/chats` for that). Options are **add-only and immutable**: you can add options later via `POST /v3/messages/{messageId}/poll/options`, but never edit or remove them.

type ChatSendVoicememoParams

type ChatSendVoicememoParams struct {
	// Reference to a voice memo file pre-uploaded via `POST /v3/attachments`. The file
	// is already stored, so sends using this ID skip the download step.
	//
	// Either `voice_memo_url` or `attachment_id` must be provided, but not both.
	AttachmentID param.Opt[string] `json:"attachment_id,omitzero" format:"uuid"`
	// Send even though the recipient asked you to stop (`403`, error code `2024`).
	// Applies to this request only: the opt-out stays in place, so the next send
	// without this flag is rejected again. Every override is recorded against your API
	// key.
	OverrideOptout param.Opt[bool] `json:"override_optout,omitzero"`
	// URL of the voice memo audio file. Must be a publicly accessible HTTPS URL.
	//
	// Either `voice_memo_url` or `attachment_id` must be provided, but not both.
	VoiceMemoURL param.Opt[string] `json:"voice_memo_url,omitzero" format:"uri"`
	// contains filtered or unexported fields
}

func (ChatSendVoicememoParams) MarshalJSON

func (r ChatSendVoicememoParams) MarshalJSON() (data []byte, err error)

func (*ChatSendVoicememoParams) UnmarshalJSON

func (r *ChatSendVoicememoParams) UnmarshalJSON(data []byte) error

type ChatSendVoicememoResponse

type ChatSendVoicememoResponse struct {
	VoiceMemo ChatSendVoicememoResponseVoiceMemo `json:"voice_memo" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		VoiceMemo   respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Response for sending a voice memo to a chat

func (ChatSendVoicememoResponse) RawJSON

func (r ChatSendVoicememoResponse) RawJSON() string

Returns the unmodified JSON received from the API

func (*ChatSendVoicememoResponse) UnmarshalJSON

func (r *ChatSendVoicememoResponse) UnmarshalJSON(data []byte) error

type ChatSendVoicememoResponseVoiceMemo

type ChatSendVoicememoResponseVoiceMemo struct {
	// Message identifier
	ID   string                                 `json:"id" api:"required" format:"uuid"`
	Chat ChatSendVoicememoResponseVoiceMemoChat `json:"chat" api:"required"`
	// When the voice memo was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// Sender phone number
	From string `json:"from" api:"required"`
	// Current delivery status
	Status string `json:"status" api:"required"`
	// Recipient handles (phone numbers or email addresses)
	To        []string                                    `json:"to" api:"required"`
	VoiceMemo ChatSendVoicememoResponseVoiceMemoVoiceMemo `json:"voice_memo" api:"required"`
	// Messaging service type
	//
	// Any of "iMessage", "SMS", "RCS".
	Service shared.ServiceType `json:"service" api:"nullable"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ID          respjson.Field
		Chat        respjson.Field
		CreatedAt   respjson.Field
		From        respjson.Field
		Status      respjson.Field
		To          respjson.Field
		VoiceMemo   respjson.Field
		Service     respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (ChatSendVoicememoResponseVoiceMemo) RawJSON

Returns the unmodified JSON received from the API

func (*ChatSendVoicememoResponseVoiceMemo) UnmarshalJSON

func (r *ChatSendVoicememoResponseVoiceMemo) UnmarshalJSON(data []byte) error

type ChatSendVoicememoResponseVoiceMemoChat

type ChatSendVoicememoResponseVoiceMemoChat struct {
	// Chat identifier
	ID string `json:"id" api:"required" format:"uuid"`
	// Chat participants
	Handles []shared.ChatHandle `json:"handles" api:"required"`
	// Whether the chat is active
	IsActive bool `json:"is_active" api:"required"`
	// Whether this is a group chat
	IsGroup bool `json:"is_group" api:"required"`
	// Messaging service type
	//
	// Any of "iMessage", "SMS", "RCS".
	Service shared.ServiceType `json:"service" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ID          respjson.Field
		Handles     respjson.Field
		IsActive    respjson.Field
		IsGroup     respjson.Field
		Service     respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (ChatSendVoicememoResponseVoiceMemoChat) RawJSON

Returns the unmodified JSON received from the API

func (*ChatSendVoicememoResponseVoiceMemoChat) UnmarshalJSON

func (r *ChatSendVoicememoResponseVoiceMemoChat) UnmarshalJSON(data []byte) error

type ChatSendVoicememoResponseVoiceMemoVoiceMemo

type ChatSendVoicememoResponseVoiceMemoVoiceMemo struct {
	// Attachment identifier
	ID string `json:"id" api:"required" format:"uuid"`
	// Original filename
	Filename string `json:"filename" api:"required"`
	// Audio MIME type
	MimeType string `json:"mime_type" api:"required"`
	// File size in bytes
	SizeBytes int64 `json:"size_bytes" api:"required"`
	// CDN URL for downloading the voice memo
	URL string `json:"url" api:"required" format:"uri"`
	// Duration in milliseconds
	DurationMs int64 `json:"duration_ms" api:"nullable"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ID          respjson.Field
		Filename    respjson.Field
		MimeType    respjson.Field
		SizeBytes   respjson.Field
		URL         respjson.Field
		DurationMs  respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (ChatSendVoicememoResponseVoiceMemoVoiceMemo) RawJSON

Returns the unmodified JSON received from the API

func (*ChatSendVoicememoResponseVoiceMemoVoiceMemo) UnmarshalJSON

func (r *ChatSendVoicememoResponseVoiceMemoVoiceMemo) UnmarshalJSON(data []byte) error

type ChatService

type ChatService struct {
	Options []option.RequestOption
	// A Chat is a conversation thread with one or more participants.
	//
	// To begin a chat, you must create a Chat with at least one recipient handle.
	// Including multiple handles creates a group chat.
	//
	// When creating a chat, the `from` field specifies which of your authorized phone
	// numbers the message originates from. Your authentication token grants access to
	// one or more phone numbers, but the `from` field determines the actual sender.
	//
	// **Handle Format:**
	//
	//   - Handles can be phone numbers or email addresses
	//   - Phone numbers MUST be in E.164 format (starting with +)
	//   - Phone format: `+[country code][subscriber number]`
	//   - Example phone: `+12223334444` (US), `+442071234567` (UK), `+81312345678`
	//     (Japan)
	//   - Example email: `user@example.com`
	//   - No spaces, dashes, or parentheses in phone numbers
	Participants ChatParticipantService
	// A Chat is a conversation thread with one or more participants.
	//
	// To begin a chat, you must create a Chat with at least one recipient handle.
	// Including multiple handles creates a group chat.
	//
	// When creating a chat, the `from` field specifies which of your authorized phone
	// numbers the message originates from. Your authentication token grants access to
	// one or more phone numbers, but the `from` field determines the actual sender.
	//
	// **Handle Format:**
	//
	//   - Handles can be phone numbers or email addresses
	//   - Phone numbers MUST be in E.164 format (starting with +)
	//   - Phone format: `+[country code][subscriber number]`
	//   - Example phone: `+12223334444` (US), `+442071234567` (UK), `+81312345678`
	//     (Japan)
	//   - Example email: `user@example.com`
	//   - No spaces, dashes, or parentheses in phone numbers
	Typing ChatTypingService
	// Messages are individual communications within a chat thread.
	//
	// Messages can include text, media attachments, rich link previews, special
	// effects (like confetti or fireworks), and reactions. All messages are associated
	// with a specific chat and sent from a phone number you own.
	//
	// Messages support delivery status tracking, read receipts, and editing
	// capabilities.
	//
	// ## Rich Link Previews
	//
	// Send a URL as a `link` part to deliver it with a rich preview card showing the
	// page's title, description, and image (when available). A `link` part must be the
	// **only** part in the message — it cannot be combined with text or media parts.
	// To send a URL without a preview card, include it in a `text` part instead.
	//
	// **Limitations:**
	//
	// - A `link` part cannot be combined with other parts in the same message.
	// - Maximum URL length: 2,048 characters.
	//
	// ## App Clips
	//
	// An `app_clip` part sends a **registered App Clip** — not only Linq's Apple Pay
	// checkout, but any partner's own App Clip. Like a `link` part it must be the
	// **only** part in the message, and it is **iMessage only** — it never downgrades
	// to SMS or RCS. The payment-checkout use of this part is covered in the
	// **Payments** section.
	//
	// ## Ephemeral Messages (Privacy Tier)
	//
	// For regulated or sensitive conversations, opt in to the **ephemeral messages**
	// tier by contacting your Linq support contact. When enabled, every message on the
	// covered phone numbers is given a **retention window configured for your
	// account**. After that window, the message's text, formatting, and attachment
	// references are no longer retrievable through the API — see the Attachments row
	// below for how the attachment media itself is handled. Metadata about the message
	// is retained: message identifiers, timestamps, phone numbers, and delivery state.
	// Metadata retention is not bounded by this window. Bounded operational copies,
	// such as backups and delivery queues, expire on their own separate schedules.
	// There is no per-message flag; ephemerality is applied automatically based on
	// your configuration.
	//
	// The window can be set anywhere from **60 minutes to 24 hours**, and defaults to
	// **24 hours**. Ask your Linq support contact to configure a shorter window; it
	// cannot be changed through the API.
	//
	// You can request it at two scopes:
	//
	// | Scope                | Effect                                                                                                                                                                       |
	// | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
	// | **Partner-wide**     | Every outbound and inbound message on every phone number under your account has its content removed from the API surface after your configured window. Metadata is retained. |
	// | **Per phone number** | Only the specified phone numbers have message content removed from the API surface this way. The rest follow the standard message-retention policy.                          |
	//
	// **Behavioral differences vs the standard default:**
	//
	// | Aspect                  | Standard                                           | Ephemeral                                                                                                                                                                                                                                                                                                                                   |
	// | ----------------------- | -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
	// | Retention               | Retained per the standard message-retention policy | **Hard backstop: your configured window** (60 minutes – 24 hours, default 24 hours) from when the message is created                                                                                                                                                                                                                        |
	// | After expiry            | Message stays retrievable                          | Message content is no longer retrievable — `GET /v3/messages/{messageId}` returns `404` and it no longer appears in `GET /v3/chats/{chatId}/messages`                                                                                                                                                                                       |
	// | Content on expiry       | N/A                                                | Text, formatting, and attachment references are removed from the API surface, not blanked out in place. Metadata (identifiers, timestamps, phone numbers, delivery state) is retained; its retention is not bounded by this window                                                                                                          |
	// | Attachments             | Retained                                           | Media sent on the **ephemeral attachments tier** is removed on its own storage backstop — within roughly 24–48 hours of upload — independently of the message window, so it can outlast a window shorter than a day. Attachments on the persistent tier (including pre-uploads via `POST /v3/attachments`) are kept until you `DELETE` them |
	// | Cross-partner isolation | Enforced                                           | Enforced                                                                                                                                                                                                                                                                                                                                    |
	//
	// **How the retention window works:**
	//
	//   - The window runs from **message creation** (`created_at`). It is configured for
	//     your account (60 minutes – 24 hours, default 24 hours) and cannot be set per
	//     message.
	//   - Attachment media follows its own storage backstop rather than the message
	//     window — see the Attachments row above.
	//   - Expiry is delivery-independent — the clock starts when the message is created,
	//     not when it is delivered or read.
	//   - **Deletion happens shortly _after_ the window, not exactly at it.** A
	//     background sweep runs every ~5 minutes, so a message typically stops being
	//     retrievable within about 5 minutes of its expiry, and longer while a backlog
	//     is being worked through. Treat the window as the guaranteed _minimum_
	//     retention, never as an exact deletion time or an upper bound.
	//
	// **What you observe:**
	//
	//   - **No expiry timestamp is exposed.** API responses and webhook payloads do not
	//     include the deletion time, and they do not report your configured window
	//     either — so if you are on a window shorter than 24 hours you cannot derive a
	//     message's expiry from the API today. Track the window you agreed with your
	//     Linq support contact and compute `created_at + window` yourself.
	//   - **No deletion webhook is sent.** There is no `message.deleted` event — a
	//     message simply stops being retrievable once its window passes.
	//   - **The attachment backstop is separate from the message window.** API
	//     retrievability (the `404` behavior above) ends at your configured window.
	//     Ephemeral-tier media objects are removed on their own storage backstop —
	//     within roughly 24–48 hours of upload — which is independent of the message
	//     window and can outlast a window shorter than a day. Removal of the
	//     corresponding entries from the sending device happens asynchronously and can
	//     complete after the backstop.
	//   - **Delivery is unaffected.** Ephemeral messages send, deliver, and fire the
	//     usual `message.sent` / `message.received` and status webhooks exactly like
	//     standard messages. Only retention changes.
	//
	// **When to choose ephemeral:**
	//
	//   - You have a compliance requirement that the platform must not retain message
	//     content beyond a short window.
	//   - The conversation is high-sensitivity (PHI, financial, identity verification)
	//     and you do not want it sitting in storage long-term.
	//   - Your application is the system of record — you capture what you need from the
	//     delivery webhook in real time and do not rely on reading message history back
	//     from Linq later.
	//
	// **Important:** ephemeral applies in _both directions_ — messages you send
	// **and** messages received by the phone numbers in that scope. Because Linq can
	// no longer return the message once its window passes, persist anything you need
	// to keep from the webhook payload at the time it is delivered.
	Messages ChatMessageService
	// Request a contact's location, retrieve location for contacts sharing with you,
	// and subscribe to webhooks when someone starts or stops sharing.
	//
	// **Coordinates** are returned in
	// [GeoJSON](https://datatracker.ietf.org/doc/html/rfc7946) format:
	// `[longitude, latitude]`.
	//
	// ### Reading location is poll-based
	//
	// Poll `GET /v3/chats/{chatId}/location` whenever you need the latest position.
	// **There is no webhook that pushes updated coordinates** — the
	// `location.sharing.started` / `location.sharing.stopped` webhooks fire only when
	// a contact begins or ends sharing, not on each position update. To track a moving
	// contact, poll the `GET` endpoint.
	//
	// ### Freshness
	//
	// Each feature's `properties.updated_at` tells you when that participant's
	// location was last updated — use it to judge freshness.
	//
	// ### Polling guidance
	//
	// Locations refresh on Apple's cadence, not per request — polling faster than a
	// participant's location actually updates just returns the same position. Poll at
	// a modest interval (for example, once every few minutes per chat) rather than
	// continuously.
	//
	// ### Why is location empty after `location.sharing.started` fired?
	//
	// If the contact started sharing from the **standalone Find My app** instead of
	// the Messages conversation, the share may be tied to their **Apple ID email**
	// rather than their phone number — the webhook's `shared_by` field shows the email
	// in that case. Location is readable only through a chat with the handle that
	// shared, so `GET /v3/chats/{chatId}/location` on the phone-number chat stays
	// empty.
	//
	// The fix: have the contact stop sharing and re-share from **Find My inside the
	// Messages conversation** with your number.
	Location ChatLocationService
	// Messages are individual communications within a chat thread.
	//
	// Messages can include text, media attachments, rich link previews, special
	// effects (like confetti or fireworks), and reactions. All messages are associated
	// with a specific chat and sent from a phone number you own.
	//
	// Messages support delivery status tracking, read receipts, and editing
	// capabilities.
	//
	// ## Rich Link Previews
	//
	// Send a URL as a `link` part to deliver it with a rich preview card showing the
	// page's title, description, and image (when available). A `link` part must be the
	// **only** part in the message — it cannot be combined with text or media parts.
	// To send a URL without a preview card, include it in a `text` part instead.
	//
	// **Limitations:**
	//
	// - A `link` part cannot be combined with other parts in the same message.
	// - Maximum URL length: 2,048 characters.
	//
	// ## App Clips
	//
	// An `app_clip` part sends a **registered App Clip** — not only Linq's Apple Pay
	// checkout, but any partner's own App Clip. Like a `link` part it must be the
	// **only** part in the message, and it is **iMessage only** — it never downgrades
	// to SMS or RCS. The payment-checkout use of this part is covered in the
	// **Payments** section.
	//
	// ## Ephemeral Messages (Privacy Tier)
	//
	// For regulated or sensitive conversations, opt in to the **ephemeral messages**
	// tier by contacting your Linq support contact. When enabled, every message on the
	// covered phone numbers is given a **retention window configured for your
	// account**. After that window, the message's text, formatting, and attachment
	// references are no longer retrievable through the API — see the Attachments row
	// below for how the attachment media itself is handled. Metadata about the message
	// is retained: message identifiers, timestamps, phone numbers, and delivery state.
	// Metadata retention is not bounded by this window. Bounded operational copies,
	// such as backups and delivery queues, expire on their own separate schedules.
	// There is no per-message flag; ephemerality is applied automatically based on
	// your configuration.
	//
	// The window can be set anywhere from **60 minutes to 24 hours**, and defaults to
	// **24 hours**. Ask your Linq support contact to configure a shorter window; it
	// cannot be changed through the API.
	//
	// You can request it at two scopes:
	//
	// | Scope                | Effect                                                                                                                                                                       |
	// | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
	// | **Partner-wide**     | Every outbound and inbound message on every phone number under your account has its content removed from the API surface after your configured window. Metadata is retained. |
	// | **Per phone number** | Only the specified phone numbers have message content removed from the API surface this way. The rest follow the standard message-retention policy.                          |
	//
	// **Behavioral differences vs the standard default:**
	//
	// | Aspect                  | Standard                                           | Ephemeral                                                                                                                                                                                                                                                                                                                                   |
	// | ----------------------- | -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
	// | Retention               | Retained per the standard message-retention policy | **Hard backstop: your configured window** (60 minutes – 24 hours, default 24 hours) from when the message is created                                                                                                                                                                                                                        |
	// | After expiry            | Message stays retrievable                          | Message content is no longer retrievable — `GET /v3/messages/{messageId}` returns `404` and it no longer appears in `GET /v3/chats/{chatId}/messages`                                                                                                                                                                                       |
	// | Content on expiry       | N/A                                                | Text, formatting, and attachment references are removed from the API surface, not blanked out in place. Metadata (identifiers, timestamps, phone numbers, delivery state) is retained; its retention is not bounded by this window                                                                                                          |
	// | Attachments             | Retained                                           | Media sent on the **ephemeral attachments tier** is removed on its own storage backstop — within roughly 24–48 hours of upload — independently of the message window, so it can outlast a window shorter than a day. Attachments on the persistent tier (including pre-uploads via `POST /v3/attachments`) are kept until you `DELETE` them |
	// | Cross-partner isolation | Enforced                                           | Enforced                                                                                                                                                                                                                                                                                                                                    |
	//
	// **How the retention window works:**
	//
	//   - The window runs from **message creation** (`created_at`). It is configured for
	//     your account (60 minutes – 24 hours, default 24 hours) and cannot be set per
	//     message.
	//   - Attachment media follows its own storage backstop rather than the message
	//     window — see the Attachments row above.
	//   - Expiry is delivery-independent — the clock starts when the message is created,
	//     not when it is delivered or read.
	//   - **Deletion happens shortly _after_ the window, not exactly at it.** A
	//     background sweep runs every ~5 minutes, so a message typically stops being
	//     retrievable within about 5 minutes of its expiry, and longer while a backlog
	//     is being worked through. Treat the window as the guaranteed _minimum_
	//     retention, never as an exact deletion time or an upper bound.
	//
	// **What you observe:**
	//
	//   - **No expiry timestamp is exposed.** API responses and webhook payloads do not
	//     include the deletion time, and they do not report your configured window
	//     either — so if you are on a window shorter than 24 hours you cannot derive a
	//     message's expiry from the API today. Track the window you agreed with your
	//     Linq support contact and compute `created_at + window` yourself.
	//   - **No deletion webhook is sent.** There is no `message.deleted` event — a
	//     message simply stops being retrievable once its window passes.
	//   - **The attachment backstop is separate from the message window.** API
	//     retrievability (the `404` behavior above) ends at your configured window.
	//     Ephemeral-tier media objects are removed on their own storage backstop —
	//     within roughly 24–48 hours of upload — which is independent of the message
	//     window and can outlast a window shorter than a day. Removal of the
	//     corresponding entries from the sending device happens asynchronously and can
	//     complete after the backstop.
	//   - **Delivery is unaffected.** Ephemeral messages send, deliver, and fire the
	//     usual `message.sent` / `message.received` and status webhooks exactly like
	//     standard messages. Only retention changes.
	//
	// **When to choose ephemeral:**
	//
	//   - You have a compliance requirement that the platform must not retain message
	//     content beyond a short window.
	//   - The conversation is high-sensitivity (PHI, financial, identity verification)
	//     and you do not want it sitting in storage long-term.
	//   - Your application is the system of record — you capture what you need from the
	//     delivery webhook in real time and do not rely on reading message history back
	//     from Linq later.
	//
	// **Important:** ephemeral applies in _both directions_ — messages you send
	// **and** messages received by the phone numbers in that scope. Because Linq can
	// no longer return the message once its window passes, persist anything you need
	// to keep from the webhook payload at the time it is delivered.
	Polls ChatPollService
	// A Chat is a conversation thread with one or more participants.
	//
	// To begin a chat, you must create a Chat with at least one recipient handle.
	// Including multiple handles creates a group chat.
	//
	// When creating a chat, the `from` field specifies which of your authorized phone
	// numbers the message originates from. Your authentication token grants access to
	// one or more phone numbers, but the `from` field determines the actual sender.
	//
	// **Handle Format:**
	//
	//   - Handles can be phone numbers or email addresses
	//   - Phone numbers MUST be in E.164 format (starting with +)
	//   - Phone format: `+[country code][subscriber number]`
	//   - Example phone: `+12223334444` (US), `+442071234567` (UK), `+81312345678`
	//     (Japan)
	//   - Example email: `user@example.com`
	//   - No spaces, dashes, or parentheses in phone numbers
	Background ChatBackgroundService
}

ChatService contains methods and other services that help with interacting with the linq-api-v3 API.

Note, unlike clients, this service does not read variables from the environment automatically. You should not instantiate this service directly, and instead use the NewChatService method instead.

func NewChatService

func NewChatService(opts ...option.RequestOption) (r ChatService)

NewChatService generates a new service that applies the given options to each request. These options are applied after the parent client's options (if there is one), and before any request-specific options.

func (*ChatService) Get

func (r *ChatService) Get(ctx context.Context, chatID string, opts ...option.RequestOption) (res *Chat, err error)

Retrieve a chat by its unique identifier.

func (*ChatService) LeaveChat added in v0.8.0

func (r *ChatService) LeaveChat(ctx context.Context, chatID string, opts ...option.RequestOption) (res *ChatLeaveChatResponse, err error)

Removes your phone number from a group chat. Once you leave, you will no longer receive messages from the group and all interaction endpoints (send message, typing, mark read, etc.) will return 409.

A `participant.removed` webhook will fire once the leave has been processed.

**Supported**

- iMessage group chats with 4 or more active participants (including yourself)

**Not supported**

- DM (1-on-1) chats — use the chat directly to continue the conversation

func (*ChatService) ListChats added in v0.2.0

Retrieves a paginated list of chats for the authenticated partner.

**Filtering:**

  • If `from` is provided, returns chats for that specific phone number
  • If `from` is omitted, returns chats across all phone numbers owned by the partner
  • If `to` is provided, only returns chats where the specified handle is a participant

**Pagination:**

- Use `limit` to control page size (default: 20, max: 100) - The response includes `next_cursor` for fetching the next page - When `next_cursor` is `null`, there are no more results to fetch - Pass the `next_cursor` value as the `cursor` parameter for the next request

**Example pagination flow:**

1. First request: `GET /v3/chats?from=%2B12223334444&limit=20` 2. Response includes `next_cursor: "20"` (more results exist) 3. Next request: `GET /v3/chats?from=%2B12223334444&limit=20&cursor=20` 4. Response includes `next_cursor: null` (no more results)

func (*ChatService) ListChatsAutoPaging added in v0.2.0

Retrieves a paginated list of chats for the authenticated partner.

**Filtering:**

  • If `from` is provided, returns chats for that specific phone number
  • If `from` is omitted, returns chats across all phone numbers owned by the partner
  • If `to` is provided, only returns chats where the specified handle is a participant

**Pagination:**

- Use `limit` to control page size (default: 20, max: 100) - The response includes `next_cursor` for fetching the next page - When `next_cursor` is `null`, there are no more results to fetch - Pass the `next_cursor` value as the `cursor` parameter for the next request

**Example pagination flow:**

1. First request: `GET /v3/chats?from=%2B12223334444&limit=20` 2. Response includes `next_cursor: "20"` (more results exist) 3. Next request: `GET /v3/chats?from=%2B12223334444&limit=20&cursor=20` 4. Response includes `next_cursor: null` (no more results)

func (*ChatService) MarkAsRead

func (r *ChatService) MarkAsRead(ctx context.Context, chatID string, opts ...option.RequestOption) (err error)

Mark all messages in a chat as read.

func (*ChatService) New

func (r *ChatService) New(ctx context.Context, body ChatNewParams, opts ...option.RequestOption) (res *ChatNewResponse, err error)

Create a new chat with specified participants and send an initial message. The initial message is required when creating a chat.

## Message Effects

You can add iMessage effects to make your messages more expressive. Effects are optional and can be either screen effects (full-screen animations) or bubble effects (message bubble animations).

**Screen Effects:** `confetti`, `fireworks`, `lasers`, `sparkles`, `celebration`, `hearts`, `love`, `balloons`, `happy_birthday`, `echo`, `spotlight`

**Bubble Effects:** `slam`, `loud`, `gentle`, `invisible`

Only one effect type can be applied per message.

## Inline Text Decorations (iMessage only)

Use the `text_decorations` array on a text part to apply styling and animations to character ranges.

Each decoration specifies a `range: [start, end)` and exactly one of `style` or `animation`.

**Styles:** `bold`, `italic`, `strikethrough`, `underline` **Animations:** `big`, `small`, `shake`, `nod`, `explode`, `ripple`, `bloom`, `jitter`

```json

{
  "type": "text",
  "value": "Hello world",
  "text_decorations": [
    { "range": [0, 5], "style": "bold" },
    { "range": [6, 11], "animation": "shake" }
  ]
}

```

**Note:** Style ranges (bold, italic, etc.) may overlap, but animation ranges must not overlap with other animations or styles. Decorations render per recipient, not per message: in a group with both iMessage and SMS/RCS participants, iMessage recipients see the decorations and SMS/RCS recipients receive the same message as plain text.

## First-Message Link Restriction

To protect sender deliverability, the **first outbound message** of a new chat cannot be a link. The request is rejected with `400` (error code `1005`) when:

- The message contains a `link` part (explicit rich-preview link), or - Any `text` part contains a URL.

This rule applies only to `POST /v3/chats`. Follow-up messages on an existing chat (`POST /v3/chats/{chatId}/messages`) are not subject to this restriction.

## Reusing an Existing Chat

Chats are keyed on the `from` line plus the exact set of `to` handles. Repeating this request with the same `from` and `to` returns the **existing** chat and sends the message into it instead of starting a second conversation.

A group chat that has a `display_name` is excluded from that matching. To run several parallel groups over the same participants, name each one with `PUT /v3/chats/{chatId}` before creating the next: the following `POST /v3/chats` with the same `to` then returns a new, separate `chat_id`. Two other cases also produce a new chat instead of reusing one — the participant set changed (a participant was added or removed), or the `from` line left the group.

Whenever the response is a new chat, the first-message rules above apply to that request: no link in the first message, and no `reply_to` or message effect. To send into a chat you already know, use `POST /v3/chats/{chatId}/messages` with its `chat_id`.

func (*ChatService) SendVoicememo

func (r *ChatService) SendVoicememo(ctx context.Context, chatID string, body ChatSendVoicememoParams, opts ...option.RequestOption) (res *ChatSendVoicememoResponse, err error)

Send an audio file as an **iMessage voice memo bubble** to all participants in a chat. Voice memos appear with iMessage's native inline playback UI, unlike regular audio attachments sent via media parts which appear as downloadable files.

**Supported audio formats:**

- MP3 (audio/mpeg) - M4A (audio/x-m4a, audio/mp4) - AAC (audio/aac) - CAF (audio/x-caf) - Core Audio Format - WAV (audio/wav) - AIFF (audio/aiff, audio/x-aiff) - AMR (audio/amr)

func (*ChatService) ShareContactCard

func (r *ChatService) ShareContactCard(ctx context.Context, chatID string, opts ...option.RequestOption) (err error)

Share your contact information (Name and Photo Sharing) with a chat.

**Note:** A contact card must be configured before sharing. You can set up your contact card via the [Contact Card API](#tag/Contact-Card) or on the [Linq dashboard](https://dashboard.linqapp.com/contact-cards).

func (*ChatService) Update

func (r *ChatService) Update(ctx context.Context, chatID string, body ChatUpdateParams, opts ...option.RequestOption) (res *ChatUpdateResponse, err error)

Update chat properties such as display name and group chat icon.

Listen for `chat.group_name_updated`, `chat.group_icon_updated`, `chat.group_name_update_failed`, or `chat.group_icon_update_failed` webhook events to confirm the outcome.

type ChatTypingIndicatorStartedWebhookEvent added in v0.12.0

type ChatTypingIndicatorStartedWebhookEvent struct {
	// API version for the webhook payload format
	APIVersion string `json:"api_version" api:"required"`
	// When the event was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// Payload for chat.typing_indicator.started webhook events
	Data ChatTypingIndicatorStartedWebhookEventData `json:"data" api:"required"`
	// Unique identifier for this event (for deduplication)
	EventID string `json:"event_id" api:"required" format:"uuid"`
	// Valid webhook event types that can be subscribed to.
	//
	// **Note:** `message.edited` is only delivered to subscriptions using
	// `webhook_version: "2026-02-03"`. Subscribing to this event on a v2025
	// subscription will not produce any deliveries.
	//
	// Any of "message.sent", "message.received", "message.read", "message.delivered",
	// "message.failed", "message.edited", "reaction.added", "reaction.removed",
	// "poll.received", "poll.failed", "poll.sent", "poll.delivered", "poll.read",
	// "poll.updated", "poll.vote.added", "poll.vote.removed", "poll.reaction.added",
	// "participant.added", "participant.removed", "chat.created",
	// "chat.group_name_updated", "chat.group_icon_updated",
	// "chat.group_name_update_failed", "chat.group_icon_update_failed",
	// "chat.background_updated", "chat.background_update_failed",
	// "chat.typing_indicator.started", "chat.typing_indicator.stopped",
	// "phone_number.status_updated", "contact_card.received", "call.initiated",
	// "call.ringing", "call.answered", "call.ended", "call.failed", "call.declined",
	// "call.no_answer", "location.sharing.started", "location.sharing.stopped",
	// "payment.succeeded", "payment.canceled", "payment.expired", "payment.declined",
	// "payment.authorized", "connection.created", "connection.revoked".
	EventType WebhookEventType `json:"event_type" api:"required"`
	// Partner identifier. Present on all webhooks for cross-referencing.
	PartnerID string `json:"partner_id" api:"required"`
	// Trace ID for debugging and correlation across systems.
	TraceID string `json:"trace_id" api:"required"`
	// Date-based webhook payload version. Determined by the `?version=` query
	// parameter in your webhook subscription URL. If no version parameter is
	// specified, defaults based on subscription creation date.
	WebhookVersion string `json:"webhook_version" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		APIVersion     respjson.Field
		CreatedAt      respjson.Field
		Data           respjson.Field
		EventID        respjson.Field
		EventType      respjson.Field
		PartnerID      respjson.Field
		TraceID        respjson.Field
		WebhookVersion respjson.Field
		ExtraFields    map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Complete webhook payload for chat.typing_indicator.started events

func (ChatTypingIndicatorStartedWebhookEvent) RawJSON added in v0.12.0

Returns the unmodified JSON received from the API

func (*ChatTypingIndicatorStartedWebhookEvent) UnmarshalJSON added in v0.12.0

func (r *ChatTypingIndicatorStartedWebhookEvent) UnmarshalJSON(data []byte) error

type ChatTypingIndicatorStartedWebhookEventData added in v0.12.0

type ChatTypingIndicatorStartedWebhookEventData struct {
	// Chat identifier
	ChatID string `json:"chat_id" api:"required" format:"uuid"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ChatID      respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Payload for chat.typing_indicator.started webhook events

func (ChatTypingIndicatorStartedWebhookEventData) RawJSON added in v0.12.0

Returns the unmodified JSON received from the API

func (*ChatTypingIndicatorStartedWebhookEventData) UnmarshalJSON added in v0.12.0

func (r *ChatTypingIndicatorStartedWebhookEventData) UnmarshalJSON(data []byte) error

type ChatTypingIndicatorStoppedWebhookEvent added in v0.12.0

type ChatTypingIndicatorStoppedWebhookEvent struct {
	// API version for the webhook payload format
	APIVersion string `json:"api_version" api:"required"`
	// When the event was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// Payload for chat.typing_indicator.stopped webhook events
	Data ChatTypingIndicatorStoppedWebhookEventData `json:"data" api:"required"`
	// Unique identifier for this event (for deduplication)
	EventID string `json:"event_id" api:"required" format:"uuid"`
	// Valid webhook event types that can be subscribed to.
	//
	// **Note:** `message.edited` is only delivered to subscriptions using
	// `webhook_version: "2026-02-03"`. Subscribing to this event on a v2025
	// subscription will not produce any deliveries.
	//
	// Any of "message.sent", "message.received", "message.read", "message.delivered",
	// "message.failed", "message.edited", "reaction.added", "reaction.removed",
	// "poll.received", "poll.failed", "poll.sent", "poll.delivered", "poll.read",
	// "poll.updated", "poll.vote.added", "poll.vote.removed", "poll.reaction.added",
	// "participant.added", "participant.removed", "chat.created",
	// "chat.group_name_updated", "chat.group_icon_updated",
	// "chat.group_name_update_failed", "chat.group_icon_update_failed",
	// "chat.background_updated", "chat.background_update_failed",
	// "chat.typing_indicator.started", "chat.typing_indicator.stopped",
	// "phone_number.status_updated", "contact_card.received", "call.initiated",
	// "call.ringing", "call.answered", "call.ended", "call.failed", "call.declined",
	// "call.no_answer", "location.sharing.started", "location.sharing.stopped",
	// "payment.succeeded", "payment.canceled", "payment.expired", "payment.declined",
	// "payment.authorized", "connection.created", "connection.revoked".
	EventType WebhookEventType `json:"event_type" api:"required"`
	// Partner identifier. Present on all webhooks for cross-referencing.
	PartnerID string `json:"partner_id" api:"required"`
	// Trace ID for debugging and correlation across systems.
	TraceID string `json:"trace_id" api:"required"`
	// Date-based webhook payload version. Determined by the `?version=` query
	// parameter in your webhook subscription URL. If no version parameter is
	// specified, defaults based on subscription creation date.
	WebhookVersion string `json:"webhook_version" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		APIVersion     respjson.Field
		CreatedAt      respjson.Field
		Data           respjson.Field
		EventID        respjson.Field
		EventType      respjson.Field
		PartnerID      respjson.Field
		TraceID        respjson.Field
		WebhookVersion respjson.Field
		ExtraFields    map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Complete webhook payload for chat.typing_indicator.stopped events

func (ChatTypingIndicatorStoppedWebhookEvent) RawJSON added in v0.12.0

Returns the unmodified JSON received from the API

func (*ChatTypingIndicatorStoppedWebhookEvent) UnmarshalJSON added in v0.12.0

func (r *ChatTypingIndicatorStoppedWebhookEvent) UnmarshalJSON(data []byte) error

type ChatTypingIndicatorStoppedWebhookEventData added in v0.12.0

type ChatTypingIndicatorStoppedWebhookEventData struct {
	// Chat identifier
	ChatID string `json:"chat_id" api:"required" format:"uuid"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ChatID      respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Payload for chat.typing_indicator.stopped webhook events

func (ChatTypingIndicatorStoppedWebhookEventData) RawJSON added in v0.12.0

Returns the unmodified JSON received from the API

func (*ChatTypingIndicatorStoppedWebhookEventData) UnmarshalJSON added in v0.12.0

func (r *ChatTypingIndicatorStoppedWebhookEventData) UnmarshalJSON(data []byte) error

type ChatTypingService

type ChatTypingService struct {
	Options []option.RequestOption
}

A Chat is a conversation thread with one or more participants.

To begin a chat, you must create a Chat with at least one recipient handle. Including multiple handles creates a group chat.

When creating a chat, the `from` field specifies which of your authorized phone numbers the message originates from. Your authentication token grants access to one or more phone numbers, but the `from` field determines the actual sender.

**Handle Format:**

  • Handles can be phone numbers or email addresses
  • Phone numbers MUST be in E.164 format (starting with +)
  • Phone format: `+[country code][subscriber number]`
  • Example phone: `+12223334444` (US), `+442071234567` (UK), `+81312345678` (Japan)
  • Example email: `user@example.com`
  • No spaces, dashes, or parentheses in phone numbers

ChatTypingService contains methods and other services that help with interacting with the linq-api-v3 API.

Note, unlike clients, this service does not read variables from the environment automatically. You should not instantiate this service directly, and instead use the NewChatTypingService method instead.

func NewChatTypingService

func NewChatTypingService(opts ...option.RequestOption) (r ChatTypingService)

NewChatTypingService generates a new service that applies the given options to each request. These options are applied after the parent client's options (if there is one), and before any request-specific options.

func (*ChatTypingService) Start

func (r *ChatTypingService) Start(ctx context.Context, chatID string, opts ...option.RequestOption) (err error)

Send a typing indicator to show that someone is typing in the chat.

## Behavior

Typing indicators are best-effort signals that behave as follows:

  • **iMessage chats only:** Typing indicators are only supported for iMessage chats. Requests for RCS or SMS chats are accepted (`204`) but no indicator is delivered.

  • **Send a message first for reliable delivery:** Typing indicators are best-effort. If you have not sent a message in this chat recently (roughly the **last 5 minutes**), a typing indicator may not reach the recipient — the request is still accepted (`204`), but delivery is not deterministic. Once you have sent a message in the chat, typing indicators reliably reach the recipient.

  • **No delivery guarantee:** Even for active chats, a `204` response only indicates the request was accepted for processing.

  • **Direct and group chats:** Typing indicators work in both direct and group chats.

## Duration & keeping it visible

  • A single call shows the indicator for about **85–90 seconds**, then it clears automatically.

  • To keep it visible longer, call this endpoint again every **60 seconds**. Each call refreshes the indicator so it stays visible continuously.

- Sending a message clears the indicator.

- To resume typing after sending a message, call this endpoint again.

- Incoming messages do not affect the indicator.

## Recipient re-opening the chat

If the recipient brings their messaging app to the foreground while the chat has an unread message, their device clears any showing typing indicator. Calling this endpoint again on its own may not bring it back. To make it reappear, either send a message, or call `DELETE /v3/chats/{chatId}/typing` (stop) and then call start typing again.

## Recommended usage

Call this endpoint when composing begins, call it again every 60 seconds while composing, and send the message to clear the indicator. To clear the indicator without sending a message, call `DELETE /v3/chats/{chatId}/typing`.

func (*ChatTypingService) Stop

func (r *ChatTypingService) Stop(ctx context.Context, chatID string, opts ...option.RequestOption) (err error)

Immediately clears the typing indicator for the chat, without sending a message.

The typing indicator also clears automatically when you send a message, or about 85–90 seconds after the last `POST /v3/chats/{chatId}/typing` (start typing) request.

See the start typing endpoint (`POST /v3/chats/{chatId}/typing`) above for behavior details.

**Note:** Works in both direct and group chats.

type ChatUpdateParams

type ChatUpdateParams struct {
	// New display name for the chat (group chats only)
	DisplayName param.Opt[string] `json:"display_name,omitzero"`
	// URL of an image to set as the group chat icon (group chats only)
	GroupChatIcon param.Opt[string] `json:"group_chat_icon,omitzero" format:"uri"`
	// contains filtered or unexported fields
}

func (ChatUpdateParams) MarshalJSON

func (r ChatUpdateParams) MarshalJSON() (data []byte, err error)

func (*ChatUpdateParams) UnmarshalJSON

func (r *ChatUpdateParams) UnmarshalJSON(data []byte) error

type ChatUpdateResponse added in v0.6.1

type ChatUpdateResponse struct {
	ChatID string `json:"chat_id" format:"uuid"`
	Status string `json:"status"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ChatID      respjson.Field
		Status      respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (ChatUpdateResponse) RawJSON added in v0.6.1

func (r ChatUpdateResponse) RawJSON() string

Returns the unmodified JSON received from the API

func (*ChatUpdateResponse) UnmarshalJSON added in v0.6.1

func (r *ChatUpdateResponse) UnmarshalJSON(data []byte) error

type Client

type Client struct {
	Options []option.RequestOption
	Chats   ChatService
	// Messages are individual communications within a chat thread.
	//
	// Messages can include text, media attachments, rich link previews, special
	// effects (like confetti or fireworks), and reactions. All messages are associated
	// with a specific chat and sent from a phone number you own.
	//
	// Messages support delivery status tracking, read receipts, and editing
	// capabilities.
	//
	// ## Rich Link Previews
	//
	// Send a URL as a `link` part to deliver it with a rich preview card showing the
	// page's title, description, and image (when available). A `link` part must be the
	// **only** part in the message — it cannot be combined with text or media parts.
	// To send a URL without a preview card, include it in a `text` part instead.
	//
	// **Limitations:**
	//
	// - A `link` part cannot be combined with other parts in the same message.
	// - Maximum URL length: 2,048 characters.
	//
	// ## App Clips
	//
	// An `app_clip` part sends a **registered App Clip** — not only Linq's Apple Pay
	// checkout, but any partner's own App Clip. Like a `link` part it must be the
	// **only** part in the message, and it is **iMessage only** — it never downgrades
	// to SMS or RCS. The payment-checkout use of this part is covered in the
	// **Payments** section.
	//
	// ## Ephemeral Messages (Privacy Tier)
	//
	// For regulated or sensitive conversations, opt in to the **ephemeral messages**
	// tier by contacting your Linq support contact. When enabled, every message on the
	// covered phone numbers is given a **retention window configured for your
	// account**. After that window, the message's text, formatting, and attachment
	// references are no longer retrievable through the API — see the Attachments row
	// below for how the attachment media itself is handled. Metadata about the message
	// is retained: message identifiers, timestamps, phone numbers, and delivery state.
	// Metadata retention is not bounded by this window. Bounded operational copies,
	// such as backups and delivery queues, expire on their own separate schedules.
	// There is no per-message flag; ephemerality is applied automatically based on
	// your configuration.
	//
	// The window can be set anywhere from **60 minutes to 24 hours**, and defaults to
	// **24 hours**. Ask your Linq support contact to configure a shorter window; it
	// cannot be changed through the API.
	//
	// You can request it at two scopes:
	//
	// | Scope                | Effect                                                                                                                                                                       |
	// | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
	// | **Partner-wide**     | Every outbound and inbound message on every phone number under your account has its content removed from the API surface after your configured window. Metadata is retained. |
	// | **Per phone number** | Only the specified phone numbers have message content removed from the API surface this way. The rest follow the standard message-retention policy.                          |
	//
	// **Behavioral differences vs the standard default:**
	//
	// | Aspect                  | Standard                                           | Ephemeral                                                                                                                                                                                                                                                                                                                                   |
	// | ----------------------- | -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
	// | Retention               | Retained per the standard message-retention policy | **Hard backstop: your configured window** (60 minutes – 24 hours, default 24 hours) from when the message is created                                                                                                                                                                                                                        |
	// | After expiry            | Message stays retrievable                          | Message content is no longer retrievable — `GET /v3/messages/{messageId}` returns `404` and it no longer appears in `GET /v3/chats/{chatId}/messages`                                                                                                                                                                                       |
	// | Content on expiry       | N/A                                                | Text, formatting, and attachment references are removed from the API surface, not blanked out in place. Metadata (identifiers, timestamps, phone numbers, delivery state) is retained; its retention is not bounded by this window                                                                                                          |
	// | Attachments             | Retained                                           | Media sent on the **ephemeral attachments tier** is removed on its own storage backstop — within roughly 24–48 hours of upload — independently of the message window, so it can outlast a window shorter than a day. Attachments on the persistent tier (including pre-uploads via `POST /v3/attachments`) are kept until you `DELETE` them |
	// | Cross-partner isolation | Enforced                                           | Enforced                                                                                                                                                                                                                                                                                                                                    |
	//
	// **How the retention window works:**
	//
	//   - The window runs from **message creation** (`created_at`). It is configured for
	//     your account (60 minutes – 24 hours, default 24 hours) and cannot be set per
	//     message.
	//   - Attachment media follows its own storage backstop rather than the message
	//     window — see the Attachments row above.
	//   - Expiry is delivery-independent — the clock starts when the message is created,
	//     not when it is delivered or read.
	//   - **Deletion happens shortly _after_ the window, not exactly at it.** A
	//     background sweep runs every ~5 minutes, so a message typically stops being
	//     retrievable within about 5 minutes of its expiry, and longer while a backlog
	//     is being worked through. Treat the window as the guaranteed _minimum_
	//     retention, never as an exact deletion time or an upper bound.
	//
	// **What you observe:**
	//
	//   - **No expiry timestamp is exposed.** API responses and webhook payloads do not
	//     include the deletion time, and they do not report your configured window
	//     either — so if you are on a window shorter than 24 hours you cannot derive a
	//     message's expiry from the API today. Track the window you agreed with your
	//     Linq support contact and compute `created_at + window` yourself.
	//   - **No deletion webhook is sent.** There is no `message.deleted` event — a
	//     message simply stops being retrievable once its window passes.
	//   - **The attachment backstop is separate from the message window.** API
	//     retrievability (the `404` behavior above) ends at your configured window.
	//     Ephemeral-tier media objects are removed on their own storage backstop —
	//     within roughly 24–48 hours of upload — which is independent of the message
	//     window and can outlast a window shorter than a day. Removal of the
	//     corresponding entries from the sending device happens asynchronously and can
	//     complete after the backstop.
	//   - **Delivery is unaffected.** Ephemeral messages send, deliver, and fire the
	//     usual `message.sent` / `message.received` and status webhooks exactly like
	//     standard messages. Only retention changes.
	//
	// **When to choose ephemeral:**
	//
	//   - You have a compliance requirement that the platform must not retain message
	//     content beyond a short window.
	//   - The conversation is high-sensitivity (PHI, financial, identity verification)
	//     and you do not want it sitting in storage long-term.
	//   - Your application is the system of record — you capture what you need from the
	//     delivery webhook in real time and do not rely on reading message history back
	//     from Linq later.
	//
	// **Important:** ephemeral applies in _both directions_ — messages you send
	// **and** messages received by the phone numbers in that scope. Because Linq can
	// no longer return the message once its window passes, persist anything you need
	// to keep from the webhook payload at the time it is delivered.
	Messages MessageService
	// Send files (images, videos, documents, audio) with messages by providing a URL
	// in a media part. Pre-uploading via `POST /v3/attachments` is **optional** and
	// only needed for specific optimization scenarios.
	//
	// ## Sending Media via URL (up to 10MB)
	//
	// Provide a publicly accessible HTTPS URL with a
	// [supported media type](#supported-file-types) in the `url` field of a media
	// part.
	//
	// “`json
	//
	//	{
	//	  "parts": [{ "type": "media", "url": "https://your-cdn.com/images/photo.jpg" }]
	//	}
	//
	// “`
	//
	// This works with any URL you already host — no pre-upload step required.
	// **Maximum file size: 10MB.**
	//
	// ## Pre-Upload (required for files over 10MB)
	//
	// Use `POST /v3/attachments` when you want to:
	//
	//   - **Send files larger than 10MB** (up to 100MB) — URL-based downloads are
	//     limited to 10MB
	//   - **Send the same file to many recipients** — upload once, reuse the
	//     `attachment_id` without re-downloading each time
	//   - **Reduce message send latency** — the file is already stored, so sending is
	//     faster
	//
	// **How it works:**
	//
	//  1. `POST /v3/attachments` with file metadata → returns a presigned `upload_url`
	//     (valid for **15 minutes**) and a reusable `attachment_id`
	//  2. PUT the raw file bytes to the `upload_url` with the `required_headers` (no
	//     JSON or multipart — just the binary content)
	//  3. Reference the `attachment_id` in your media part when sending messages (stays
	//     valid unless deleted — see [Attachment Lifetime](#attachment-lifetime))
	//
	// **Key difference:** When you provide an external `url`, we download and process
	// the file on every send. When you use a pre-uploaded `attachment_id`, the file is
	// already stored — so repeated sends skip the download step entirely.
	//
	// ## Attachment Lifetime
	//
	// An `attachment_id` and its CDN URL stay valid until the file is deleted. Three
	// things delete it:
	//
	// | Trigger                                                  | Applies to                                                                                                                                                                                             |
	// | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
	// | `DELETE /v3/attachments/{attachmentId}`                  | Any attachment you own                                                                                                                                                                                 |
	// | Ephemeral **attachments** tier (24–48h storage backstop) | Attachments on ephemeral-tier partners or phone numbers                                                                                                                                                |
	// | Ephemeral **messages** tier                              | Does **not** remove attachment bytes on its own: ephemeral-tier objects are removed by the 24–48h storage backstop above, and persistent-tier attachments are kept until you `DELETE` them explicitly. |
	//
	// Deletion is not reversible, and there is no `attachment.deleted` webhook. On
	// either ephemeral tier, download anything you need to keep when you receive it
	// rather than re-fetching later, and do not assume a pre-uploaded `attachment_id`
	// can be reused indefinitely.
	//
	// ## Domain Allowlisting
	//
	// Attachment URLs in API responses are served from `cdn.linqapp.com`. This
	// includes:
	//
	// - `url` fields in media and voice memo message parts
	// - `download_url` fields in attachment and upload response objects
	//
	// If your application enforces domain allowlists (e.g., for SSRF protection), add:
	//
	// “`
	// cdn.linqapp.com
	// “`
	//
	// ## Supported File Types
	//
	// - **Images:** JPEG, PNG, GIF, HEIC, HEIF, TIFF, BMP
	// - **Videos:** MP4, MOV, M4V
	// - **Audio:** M4A, AAC, MP3, WAV, AIFF, CAF, AMR
	// - **Documents:** PDF, TXT, RTF, CSV, Office formats, ZIP
	// - **Contact & Calendar:** VCF, ICS
	//
	// ## Audio: Attachment vs Voice Memo
	//
	// Audio files sent as media parts appear as **downloadable file attachments** in
	// iMessage. To send audio as an **iMessage voice memo bubble** (with native inline
	// playback UI), use the dedicated `POST /v3/chats/{chatId}/voicememo` endpoint
	// instead.
	//
	// ## File Size Limits
	//
	// - **URL-based (`url` field):** 10MB maximum
	// - **Pre-upload (`attachment_id`):** 100MB maximum
	//
	// ## Security & Ownership
	//
	// Every attachment is bound to the partner account that created or received it.
	// The API enforces ownership on every operation that touches an attachment —
	// sending, retrieving, deleting.
	//
	// **What this means for you:**
	//
	//   - An attachment created under your API key can only be referenced by your API
	//     key.
	//   - Submitting another partner's `attachment_id` returns `404 Not Found`. We do
	//     not disclose whether the id exists or belongs to someone else.
	//   - Submitting a CDN URL that resolves to another partner's attachment is rejected
	//     before the send is attempted.
	//   - Ownership enforcement applies uniformly across send, create-chat, voice memo,
	//     retrieve, and delete operations.
	//
	// Every attachment-affecting endpoint requires a valid partner API key.
	// Unauthenticated calls return `401 Unauthorized`.
	//
	// ## Attachment URL Patterns
	//
	// Attachment URLs in API responses and webhook payloads use one of two layouts,
	// depending on the attachment's tier:
	//
	// | Tier                 | URL pattern                                                                            | TTL                                                                                              |
	// | -------------------- | -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
	// | Persistent (default) | `https://cdn.linqapp.com/attachments/partners/{partner_id}/{attachment_id}/{filename}` | Long-lived — the URL itself does not expire, but see [Attachment Lifetime](#attachment-lifetime) |
	// | Ephemeral            | Pre-signed URL pointing at the ephemeral prefix on `cdn.linqapp.com`                   | 15 minutes per signed URL — re-fetch via the API for a fresh URL                                 |
	//
	// Inbound media you receive over webhooks uses the same layout your outbound sends
	// produce, so the URL you store and the URL you build look identical — no special
	// casing in your client.
	//
	// ## Ephemeral Attachments (Privacy Tier)
	//
	// For regulated or sensitive content, opt in to the **ephemeral attachments** tier
	// by contacting your Linq support contact. You can request it at two scopes:
	//
	// | Scope                | Effect                                                                                                                     |
	// | -------------------- | -------------------------------------------------------------------------------------------------------------------------- |
	// | **Partner-wide**     | Every outbound and inbound attachment on every phone number under your account is routed through the ephemeral tier.       |
	// | **Per phone number** | Only the specified phone numbers route their attachments through the ephemeral tier. The rest stay on the persistent tier. |
	//
	// **Behavioral differences vs the persistent default:**
	//
	// | Aspect                  | Persistent              | Ephemeral                                                                                                                                     |
	// | ----------------------- | ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
	// | Download URL form       | Long-lived CDN URL      | Pre-signed URL with short TTL                                                                                                                 |
	// | Retention floor         | Until you call `DELETE` | **Hard backstop: 24–48h** — even without an explicit `DELETE`, the platform removes the underlying bytes within roughly 24–48 hours of upload |
	// | URL re-fetch            | Not required            | Fetch via `GET /v3/attachments/{attachmentId}` for a fresh signed URL after TTL expiry                                                        |
	// | Cross-partner isolation | Enforced                | Enforced                                                                                                                                      |
	//
	// **When to choose ephemeral:**
	//
	//   - Your downstream system processes the file immediately on receipt and does not
	//     need to re-read it later.
	//   - You have a compliance requirement that the platform must not retain
	//     attachments beyond a short window.
	//   - The content is high-sensitivity (PHI, financial documents, identity
	//     verification) and you do not want it sitting behind a long-lived URL.
	//
	// **Important:** ephemeral applies in _both directions_ — outbound files you
	// upload **and** inbound media received by the phone numbers in that scope.
	// Download bytes you need to keep promptly, or fetch a fresh signed URL via the
	// API when needed.
	//
	// ## Deleting an Attachment
	//
	// To permanently remove an attachment you own, use:
	//
	// “`http
	// DELETE /v3/attachments/{attachmentId}
	// Authorization: Bearer <your_api_key>
	// “`
	//
	// **What this does:**
	//
	// 1. Verifies the attachment is owned by your account. Returns `404` otherwise.
	// 2. Removes the underlying file from Linq storage.
	// 3. Records an audit entry (timestamp, partner, attachment id).
	//
	// **Response codes:**
	//
	// | Status                      | Meaning                                                          |
	// | --------------------------- | ---------------------------------------------------------------- |
	// | `204 No Content`            | Deletion succeeded. The attachment is removed from Linq storage. |
	// | `400 Bad Request`           | `attachmentId` is not a valid UUID.                              |
	// | `401 Unauthorized`          | Missing or invalid API key.                                      |
	// | `404 Not Found`             | Attachment does not exist or is not owned by your account.       |
	// | `500 Internal Server Error` | Transient infrastructure issue — safe to retry.                  |
	//
	// **Effect on message history:**
	//
	//   - Messages that referenced the deleted attachment remain visible.
	//   - The message part that pointed at the attachment is preserved with no
	//     attachment reference.
	//   - Webhook payloads previously delivered to you retain the original URL string,
	//     but downloads from that URL return `404` going forward.
	//
	// Deletion is **irreversible**. Once `204` is returned, the bytes are gone — there
	// is no undelete.
	//
	// ## Inbound Media Flow
	//
	// When one of your phone numbers receives a message with media (image, video,
	// audio, document), the platform:
	//
	//  1. Stores the file under your partner account.
	//  2. Records metadata linked to the inbound message.
	//  3. Delivers a webhook whose `parts[]` array includes a `media` part with a `url`
	//     pointing at `cdn.linqapp.com`.
	//  4. If the receiving phone is opted in to ephemeral, the `url` is a short-TTL
	//     signed URL.
	//
	// You can acknowledge the webhook without fetching the file inline, and lazy-load
	// via `GET /v3/attachments/{attachmentId}` later. For ephemeral attachments,
	// retrieving via the API always returns a freshly-signed URL.
	//
	// ## Data Lifecycle Summary
	//
	// | Data                                                | Persistent tier                        | Ephemeral tier                                                                                                                                                                                                                                                                                                                                                                                               |
	// | --------------------------------------------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
	// | Attachment bytes                                    | Retained until you `DELETE`            | **Auto-removed within roughly 24–48 hours** of upload, independently of any message window. Also removable via `DELETE`                                                                                                                                                                                                                                                                                      |
	// | Attachment metadata (id, filename, mime type, size) | Retained until you `DELETE`            | Removed alongside the bytes                                                                                                                                                                                                                                                                                                                                                                                  |
	// | Message body & parts                                | Retained per message-retention policy  | Retained per message-retention policy — unless the line also has **ephemeral messages** enabled (see the Messages page), in which case the message's text, formatting, and attachment references are no longer retrievable through the API after that account's configured retention window (60 minutes – 24 hours, default 24 hours) from creation. Metadata is retained; see the Messages page for details |
	// | Audit log of deletions                              | Retained per platform retention policy | Retained per platform retention policy                                                                                                                                                                                                                                                                                                                                                                       |
	//
	// **In transit:** TLS 1.2+ everywhere. **At rest:** AES-256 (server-side
	// encryption).
	//
	// ## Compliance Checklist
	//
	// If you're integrating Linq under a security or privacy review, here is the short
	// list:
	//
	//   - Allowlist exactly one outbound domain: `cdn.linqapp.com`.
	//   - Decide whether you need ephemeral attachments (high-sensitivity content) —
	//     request enablement through your Linq support contact.
	//   - Implement `DELETE /v3/attachments/{attachmentId}` calls in your deletion
	//     workflow.
	//   - Persist any attachments your application needs long-term — Linq is the
	//     authoritative source until you delete, but the ephemeral tier auto-purges
	//     within roughly 24–48 hours of upload.
	//   - For audit: every deletion is logged on Linq's side. Surface a confirmation in
	//     your application UI based on the `204` response.
	//   - For end-user "right to delete" requests: enumerate attachment ids and `DELETE`
	//     each. The platform does not provide a partner-wide wipe endpoint — deletion is
	//     per-attachment by design.
	Attachments AttachmentService
	// Phone Numbers represent the phone numbers assigned to your partner account.
	//
	// Use the list phone numbers endpoint to discover which phone numbers are
	// available for sending messages.
	//
	// When creating chats, listing chats, or sending a voice memo, use one of your
	// assigned phone numbers in the `from` field.
	//
	// **Ineligible numbers.** A number can temporarily lose the ability to deliver
	// messages. While it is in that state, requests that would produce new activity on
	// it — sending a message, creating a chat, reacting, typing, group actions — are
	// rejected with `403` (error code `2027`) before anything is created. Reads keep
	// working, so your existing chats, messages, and history stay available. Omit
	// `from` on `POST /v3/messages` and we pick an eligible number for you, skipping
	// ineligible ones; if none of your assigned numbers are eligible, you get `409`
	// (no `from` number was ever chosen, so there's no specific number to blame with a
	// `403`).
	Phonenumbers PhonenumberService
	// Phone Numbers represent the phone numbers assigned to your partner account.
	//
	// Use the list phone numbers endpoint to discover which phone numbers are
	// available for sending messages.
	//
	// When creating chats, listing chats, or sending a voice memo, use one of your
	// assigned phone numbers in the `from` field.
	//
	// **Ineligible numbers.** A number can temporarily lose the ability to deliver
	// messages. While it is in that state, requests that would produce new activity on
	// it — sending a message, creating a chat, reacting, typing, group actions — are
	// rejected with `403` (error code `2027`) before anything is created. Reads keep
	// working, so your existing chats, messages, and history stay available. Omit
	// `from` on `POST /v3/messages` and we pick an eligible number for you, skipping
	// ineligible ones; if none of your assigned numbers are eligible, you get `409`
	// (no `from` number was ever chosen, so there's no specific number to blame with a
	// `403`).
	PhoneNumbers PhoneNumberService
	// Phone Numbers represent the phone numbers assigned to your partner account.
	//
	// Use the list phone numbers endpoint to discover which phone numbers are
	// available for sending messages.
	//
	// When creating chats, listing chats, or sending a voice memo, use one of your
	// assigned phone numbers in the `from` field.
	//
	// **Ineligible numbers.** A number can temporarily lose the ability to deliver
	// messages. While it is in that state, requests that would produce new activity on
	// it — sending a message, creating a chat, reacting, typing, group actions — are
	// rejected with `403` (error code `2027`) before anything is created. Reads keep
	// working, so your existing chats, messages, and history stay available. Omit
	// `from` on `POST /v3/messages` and we pick an eligible number for you, skipping
	// ineligible ones; if none of your assigned numbers are eligible, you get `409`
	// (no `from` number was ever chosen, so there's no specific number to blame with a
	// `403`).
	AvailableNumber AvailableNumberService
	// Request a payment from a recipient over iMessage. You create a payment request,
	// send its `checkout_url` to the recipient, and they pay with Apple Pay or card.
	// Funds settle **directly to your own Stripe account** — Linq never holds the
	// money.
	//
	// ## How it works
	//
	//  1. **Create** a payment request with an amount and currency. You get back a
	//     `checkout_url` and a `status` of `requested`.
	//  2. **Send** the `checkout_url` to the recipient as a `link` message part so it
	//     arrives as a tappable card (see _Sending the link_ below).
	//  3. The recipient **pays** on the hosted checkout (Apple Pay App Clip on a
	//     supported iPhone, web checkout everywhere else).
	//  4. You receive a **`payment.succeeded`** webhook and the request's `status`
	//     becomes `succeeded`. Requests you don't collect eventually `expire`.
	//
	// ## Connected accounts (Stripe Standard, direct charges)
	//
	// Payments run on **Stripe Connect Standard accounts** using **direct charges**:
	// the charge is created on _your_ connected account and **you are the merchant of
	// record**. That means the money, the payout schedule, the customer relationship,
	// and the compliance surface are all yours — Linq orchestrates the request and the
	// checkout but is never in the funds flow.
	//
	// **Refunds, disputes, and chargebacks are handled by you, in your own Stripe
	// Dashboard.** Because charges settle directly to your account, Linq has no
	// custody of the funds and cannot issue refunds or contest disputes on your behalf
	// — and there is no refund/dispute endpoint in this API by design. Use the Stripe
	// Dashboard (or the Stripe API on your own account) for the money lifecycle after
	// a payment succeeds.
	//
	// ## Getting set up
	//
	// Open **Agent Pay** in your Linq dashboard
	// (`https://zero.linqapp.com/organization/payments`), click **Connect Stripe**,
	// and complete Stripe's onboarding (business details + a bank account). When your
	// account reaches `charges_enabled`, request creation unlocks; until you connect
	// Stripe, `POST /v3/payment_requests` returns `403`. You can keep collecting even
	// while Stripe finishes background verification.
	//
	// ## Subscriptions
	//
	// Set `mode: subscription` on `POST /v3/payment_requests` to start an
	// **auto-renewing subscription** instead of a one-time charge. Instead of an
	// amount, you pass a `price_id` — an active **recurring Price** on your connected
	// Stripe account (create one in your Stripe Dashboard under Product catalog; if
	// you sell through Stripe Payment Links today, reuse the price your link is built
	// from). The recipient pays the first invoice at the same checkout, and their
	// payment method is saved to the subscription for automatic renewals.
	//
	// The division of labor is deliberate: **Linq handles the first payment, your
	// Stripe account handles the rest.** The request reaches `succeeded` when the
	// first invoice is paid; from then on the subscription lives entirely on your
	// connected account. The response's `stripe` object gives you the join keys —
	// `customer_id` and `subscription_id` — so renewals, plan changes, dunning, and
	// cancellation are managed with your own Stripe Dashboard/API and your own Stripe
	// webhooks. Your `metadata` is stamped on the Customer and Subscription, so
	// correlating in either direction is trivial. There are no renewal webhooks from
	// Linq by design.
	//
	// ### Discounts
	//
	// Pass a `discount` with a **coupon** or **promotion code** from your connected
	// Stripe account to apply it to the subscription. Create either in your Stripe
	// Dashboard under Product catalog → Coupons; Linq only forwards the id.
	//
	// “`json
	//
	//	{
	//	  "mode": "subscription",
	//	  "price_id": "price_1QAbCdEfGhIjKlMn",
	//	  "discount": {
	//	    "coupon": "7fKCMvBh",
	//	    "label": "50% OFF FIRST MONTH"
	//	  }
	//	}
	//
	// “`
	//
	// Stripe applies the coupon and prices the first invoice; the `amount` we return
	// is that invoice's amount due, so a `$50.00/month` price with a
	// 50%-off-first-month coupon comes back as `2500` and the recipient is charged
	// **$25.00** at checkout. A coupon that covers the whole first invoice returns
	// `amount: 0`; checkout shows $0.00 and collects the card for the renewal rather
	// than charging now. Renewals bill at the full price automatically — how long a
	// discount lasts is the coupon's `duration`, enforced by Stripe on your account,
	// and Linq never re-prices anything.
	//
	// Use `promotion_code` instead of `coupon` to apply a promotion code by id
	// (`promo_...`, not the customer-facing code string); pass one or the other, never
	// both.
	//
	// `label` is the customer-facing promotion name displayed at checkout instead of
	// the coupon or promotion code ID. The label is displayed exactly as provided, so
	// include important terms such as "FIRST MONTH" or "FIRST 3 MONTHS" when
	// applicable. These terms are not displayed elsewhere on the checkout screen.
	//
	// If omitted, Stripe uses the coupon's name as the promotion label.
	//
	// ### Free trials
	//
	// Add `trial_period_days` (or a fixed `trial_end` timestamp) to start the
	// subscription with a free trial. The checkout still collects the recipient's
	// payment method — the pay sheet shows "$0 due today" with the first charge date —
	// and saves it to the subscription; Stripe bills it automatically when the trial
	// ends. The request reaches `succeeded` when the card is collected, and the
	// response carries `trial_end`. If the trial would end without a payment method on
	// file, the subscription cancels rather than generating unpayable invoices. Trial
	// lifecycle after checkout (extending, ending early) is managed in your own Stripe
	// account via `stripe.subscription_id`.
	//
	// A subscription request you cancel (or that expires unpaid) cancels the
	// incomplete Stripe subscription — nothing lingers on your account.
	//
	// ## Pre-created customers
	//
	// By default each request stands alone: payment mode attaches no Customer, and
	// subscription mode creates a fresh one. If you already manage Customers on your
	// connected account, pass their id as `customer_id` (`cus_...`) on create — in
	// payment mode the charge lands on that customer's payment history, and in
	// subscription mode the subscription is created on them instead of on a new
	// Customer. The id must reference an existing, non-deleted customer on your
	// connected account or the request fails with `400`. We never modify a customer
	// you pass — no metadata is stamped on it.
	//
	// ## Sending the link
	//
	// Deliver the `checkout_url` as a **`link` message part** via
	// `POST /v3/chats/{chatId}/messages` — it renders as a rich card with your
	// branding (title, amount, image) instead of a bare URL, which converts far
	// better. A `link` part must be the only part in the message. See
	// [Rich Link Previews](/channel/imessage/guides/messaging/sending-messages).
	//
	// On a supported iPhone the link opens an **Apple Pay App Clip** — a native,
	// no-install checkout sheet. Everywhere else (Android, desktop, iPhones without
	// the App Clip yet) the same URL opens the web checkout, so the link always works.
	// The App Clip experience for your payment links is registered automatically by
	// Linq and refreshed whenever you update your payments branding; a newly
	// registered experience can take up to ~24 hours to activate on Apple's side,
	// during which links open the web checkout.
	//
	// ## Sending it as a card instead
	//
	// A `link` part is one way to deliver a request. The other is the **`agentpay`
	// experience**, which sends the same request as a native card in Linq's iMessage
	// app — the amount and reason are drawn in the bubble, and it turns itself into
	// "Paid" in place once the payment succeeds, without a second message.
	//
	// Send it to `POST /v3/chats/{chatId}/messages`:
	//
	// “`json
	//
	//	{
	//	  "message": {
	//	    "experience": {
	//	      "name": "agentpay",
	//	      "action": "request_payment",
	//	      "params": {
	//	        "checkout_url": "https://zero.linqapp.com/pay/acme?session=tok_..."
	//	      }
	//	    }
	//	  }
	//	}
	//
	// “`
	//
	// `checkout_url` is the only required field — pass back exactly what
	// `POST /v3/payment_requests` returned. **The amount and reason are read from that
	// request, never from you**, so the card can never claim a different figure than
	// the checkout will charge. Optional `title` and `note` override the copy only.
	// The link must be one of your own payment requests; another partner's is
	// rejected.
	//
	// The trade-off against a `link` part: a card is an app card, so it is
	// iMessage-only, and recipients without the app see a static version of it. A link
	// works everywhere and is what opens the Apple Pay App Clip. Send whichever suits
	// the conversation — both settle the same payment request and fire the same
	// webhooks.
	//
	// ## Webhooks
	//
	// Subscribe to payment lifecycle events to reconcile server-side rather than
	// polling: `payment.succeeded`, `payment.canceled`, and `payment.expired`. Each
	// event carries the payment request id, amount, currency, and your `metadata`. See
	// [Webhooks](/channel/imessage/guides/webhooks).
	PaymentRequests PaymentRequestService
	// Let an agent pay on a customer's behalf with a single-use virtual card. Connect
	// a customer once, then create a payment — a virtual card is minted scoped to that
	// purchase and the card details are handed back for checkout.
	PaymentProviders PaymentProviderService
	// Let an agent pay on a customer's behalf with a single-use virtual card. Connect
	// a customer once, then create a payment — a virtual card is minted scoped to that
	// purchase and the card details are handed back for checkout.
	PaymentHandles PaymentHandleService
	// Let an agent pay on a customer's behalf with a single-use virtual card. Connect
	// a customer once, then create a payment — a virtual card is minted scoped to that
	// purchase and the card details are handed back for checkout.
	Payments        PaymentService
	LinkConnections LinkConnectionService
	LinkPayments    LinkPaymentService
	// Block handles — phone numbers, email addresses, SMS short codes, or sender IDs.
	// Inbound messages from a blocked handle are dropped before they reach your
	// webhooks, and direct sends to a blocked handle are rejected with `403` (error
	// code `2026`). Group sends that include unblocked members are not restricted.
	BlockedHandles BlockedHandleService
	// An **experience** renders inside Linq's iMessage app as a native card, instead
	// of as text or a link. You invoke one by name; Linq resolves the recipient, mints
	// any session it needs, composes the card and sends it.
	//
	// Send it to `POST /v3/chats/{chatId}/messages`:
	//
	// “`json
	//
	//	{
	//	  "message": {
	//	    "experience": {
	//	      "name": "agentpay",
	//	      "action": "request_payment",
	//	      "params": {
	//	        "checkout_url": "https://zero.linqapp.com/pay/acme?session=tok_..."
	//	      }
	//	    }
	//	  }
	//	}
	//
	// “`
	//
	// The key is `experience` — what you're invoking. Nested under it is its `name`,
	// the action you're invoking on it, and that action's params. A card **is** the
	// whole message on Apple's side, so a message carries either `experience` or
	// `parts`, never both, and an action goes to exactly one recipient.
	//
	// ## What you can invoke
	//
	// | Experience  | Action            | What the customer sees                                                                        |
	// | ----------- | ----------------- | --------------------------------------------------------------------------------------------- |
	// | `agentpay`  | `request_payment` | A payment request they can pay in the app. Turns itself into "Paid" in place once it settles. |
	// | `agentcard` | `attach_card`     | A prompt to add a card to their wallet.                                                       |
	// | `agentcard` | `approve_card`    | A passkey approval for a virtual card.                                                        |
	// | `link`      | `open`            | A card that opens a URL you supply.                                                           |
	//
	// `GET /v3/experiences` is the list to build against, with every action and the
	// fields each accepts — anything not described there is unsupported. Fields are
	// display copy unless documented otherwise.
	//
	// ## Params are checked before the card is sent
	//
	// Unknown fields are **rejected rather than ignored**, so copy that would never
	// have rendered fails for you now instead of arriving wrong on somebody's phone.
	// Some fields are read rather than sent: `agentpay`'s `request_payment` takes only
	// a `checkout_url` and resolves the amount and reason from that payment request,
	// so a card can never claim a figure the checkout will not charge.
	//
	// Cards are **iMessage-only**. Recipients without the app see a static version
	// built from the same copy; SMS and RCS recipients cannot receive one at all
	// (error codes 2018 and 4005).
	Experiences ExperienceService
	// Webhook Subscriptions allow you to receive real-time notifications when events
	// occur on your account.
	//
	// Configure webhook endpoints to receive events such as messages sent/received,
	// delivery status changes, reactions, typing indicators, and more.
	//
	// Failed deliveries (5xx, 429, network errors) are retried up to 10 times over ~25
	// minutes with exponential backoff. Each event includes a unique ID for
	// deduplication.
	//
	// ## Webhook Headers
	//
	// All webhook requests include two sets of headers. **If you have an existing
	// integration using the `X-Webhook-*` headers, nothing changes** — those headers
	// are still sent on every delivery and work exactly as before. The new `webhook-*`
	// headers follow the
	// [Standard Webhooks](https://github.com/standard-webhooks/standard-webhooks)
	// specification. You can safely ignore them if your current verification code
	// works and you don't want to use this convention.
	//
	// ### Standard Webhooks Headers (Recommended)
	//
	// Used by [our SDK](https://github.com/linq-team/linq-node) and any
	// [Standard Webhooks library](https://github.com/standard-webhooks/standard-webhooks).
	//
	// | Header              | Description                                        |
	// | ------------------- | -------------------------------------------------- |
	// | `webhook-id`        | Unique event identifier (use as idempotency key)   |
	// | `webhook-timestamp` | Unix timestamp (seconds) when the webhook was sent |
	// | `webhook-signature` | Standard Webhooks signature (`v1,{base64}` format) |
	//
	// ### Legacy Headers (Deprecated)
	//
	// Still sent on every delivery for backwards compatibility. Existing verification
	// code using these headers continues to work — no changes required.
	//
	// | Header                      | Description                                        |
	// | --------------------------- | -------------------------------------------------- |
	// | `X-Webhook-Event`           | _(deprecated)_ Event type (e.g., `message.sent`)   |
	// | `X-Webhook-Subscription-ID` | _(deprecated)_ Webhook subscription ID             |
	// | `X-Webhook-Timestamp`       | _(deprecated)_ Unix timestamp (seconds)            |
	// | `X-Webhook-Signature`       | _(deprecated)_ HMAC-SHA256 signature (hex-encoded) |
	//
	// ## Signing Secrets
	//
	// Signing secrets use the Standard Webhooks format: a `whsec_` prefix followed by
	// base64-encoded random bytes (e.g.,
	// `whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw7Jxx2Oll+OE=`).
	//
	// Strip the `whsec_` prefix and base64-decode the remainder to get the raw key
	// bytes.
	//
	// ## Verifying Webhook Signatures
	//
	// Webhooks are signed following the
	// [Standard Webhooks specification](https://github.com/standard-webhooks/standard-webhooks).
	// You can use any
	// [Standard Webhooks library](https://github.com/standard-webhooks/standard-webhooks)
	// to verify signatures, or implement verification manually:
	//
	// **Signed content:** `{webhook-id}.{webhook-timestamp}.{body}`
	//
	// **Verification Steps:**
	//
	//  1. Extract the `webhook-id`, `webhook-timestamp`, and `webhook-signature`
	//     headers
	//  2. Reject if the timestamp is more than 5 minutes old (replay protection)
	//  3. Get the raw request body bytes (do not parse and re-serialize)
	//  4. Construct signed content: `"{webhook-id}.{webhook-timestamp}.{body}"`
	//  5. Strip the `whsec_` prefix from your secret and base64-decode to get key bytes
	//  6. Compute HMAC-SHA256 using the key bytes over the signed content
	//  7. Base64-encode the result and compare with the value after `v1,` in
	//     `webhook-signature`
	//  8. Use constant-time comparison to prevent timing attacks
	//
	// **Example (Python):**
	//
	// “`python
	// import base64, hmac, hashlib
	//
	// def verify_webhook(secret, body, headers):
	//
	//	msg_id = headers['webhook-id']
	//	timestamp = headers['webhook-timestamp']
	//	signature = headers['webhook-signature']
	//
	//	secret_str = secret.removeprefix('whsec_')
	//	key = base64.b64decode(secret_str)
	//
	//	signed_content = f"{msg_id}.{timestamp}.{body}"
	//	expected = base64.b64encode(
	//	    hmac.new(key, signed_content.encode(), hashlib.sha256).digest()
	//	).decode()
	//
	//	for sig in signature.split(' '):
	//	    if sig.startswith('v1,') and hmac.compare_digest(expected, sig[3:]):
	//	        return True
	//	return False
	//
	// “`
	//
	// **Example (Node.js):**
	//
	// “`javascript
	// const crypto = require("crypto");
	//
	//	function verifyWebhook(secret, rawBody, headers) {
	//	  const msgId = headers["webhook-id"];
	//	  const timestamp = headers["webhook-timestamp"];
	//	  const signature = headers["webhook-signature"];
	//
	//	  const secretStr = secret.startsWith("whsec_") ? secret.slice(6) : secret;
	//	  const keyBytes = Buffer.from(secretStr, "base64");
	//	  const signedContent = `${msgId}.${timestamp}.${rawBody}`;
	//	  const expected = crypto
	//	    .createHmac("sha256", keyBytes)
	//	    .update(signedContent)
	//	    .digest("base64");
	//
	//	  return signature.split(" ").some((sig) => {
	//	    if (!sig.startsWith("v1,")) return false;
	//	    try {
	//	      return crypto.timingSafeEqual(
	//	        Buffer.from(expected, "base64"),
	//	        Buffer.from(sig.slice(3), "base64")
	//	      );
	//	    } catch {
	//	      return false;
	//	    }
	//	  });
	//	}
	//
	// “`
	//
	// **Security Best Practices:**
	//
	//   - Reject webhooks with timestamps older than 5 minutes to prevent replay attacks
	//   - Always use constant-time comparison for signature verification
	//   - Store your signing secret securely (e.g., environment variable, secrets
	//     manager)
	//   - Return a 2xx status code quickly, then process the webhook asynchronously
	WebhookEvents WebhookEventService
	// Webhook Subscriptions allow you to receive real-time notifications when events
	// occur on your account.
	//
	// Configure webhook endpoints to receive events such as messages sent/received,
	// delivery status changes, reactions, typing indicators, and more.
	//
	// Failed deliveries (5xx, 429, network errors) are retried up to 10 times over ~25
	// minutes with exponential backoff. Each event includes a unique ID for
	// deduplication.
	//
	// ## Webhook Headers
	//
	// All webhook requests include two sets of headers. **If you have an existing
	// integration using the `X-Webhook-*` headers, nothing changes** — those headers
	// are still sent on every delivery and work exactly as before. The new `webhook-*`
	// headers follow the
	// [Standard Webhooks](https://github.com/standard-webhooks/standard-webhooks)
	// specification. You can safely ignore them if your current verification code
	// works and you don't want to use this convention.
	//
	// ### Standard Webhooks Headers (Recommended)
	//
	// Used by [our SDK](https://github.com/linq-team/linq-node) and any
	// [Standard Webhooks library](https://github.com/standard-webhooks/standard-webhooks).
	//
	// | Header              | Description                                        |
	// | ------------------- | -------------------------------------------------- |
	// | `webhook-id`        | Unique event identifier (use as idempotency key)   |
	// | `webhook-timestamp` | Unix timestamp (seconds) when the webhook was sent |
	// | `webhook-signature` | Standard Webhooks signature (`v1,{base64}` format) |
	//
	// ### Legacy Headers (Deprecated)
	//
	// Still sent on every delivery for backwards compatibility. Existing verification
	// code using these headers continues to work — no changes required.
	//
	// | Header                      | Description                                        |
	// | --------------------------- | -------------------------------------------------- |
	// | `X-Webhook-Event`           | _(deprecated)_ Event type (e.g., `message.sent`)   |
	// | `X-Webhook-Subscription-ID` | _(deprecated)_ Webhook subscription ID             |
	// | `X-Webhook-Timestamp`       | _(deprecated)_ Unix timestamp (seconds)            |
	// | `X-Webhook-Signature`       | _(deprecated)_ HMAC-SHA256 signature (hex-encoded) |
	//
	// ## Signing Secrets
	//
	// Signing secrets use the Standard Webhooks format: a `whsec_` prefix followed by
	// base64-encoded random bytes (e.g.,
	// `whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw7Jxx2Oll+OE=`).
	//
	// Strip the `whsec_` prefix and base64-decode the remainder to get the raw key
	// bytes.
	//
	// ## Verifying Webhook Signatures
	//
	// Webhooks are signed following the
	// [Standard Webhooks specification](https://github.com/standard-webhooks/standard-webhooks).
	// You can use any
	// [Standard Webhooks library](https://github.com/standard-webhooks/standard-webhooks)
	// to verify signatures, or implement verification manually:
	//
	// **Signed content:** `{webhook-id}.{webhook-timestamp}.{body}`
	//
	// **Verification Steps:**
	//
	//  1. Extract the `webhook-id`, `webhook-timestamp`, and `webhook-signature`
	//     headers
	//  2. Reject if the timestamp is more than 5 minutes old (replay protection)
	//  3. Get the raw request body bytes (do not parse and re-serialize)
	//  4. Construct signed content: `"{webhook-id}.{webhook-timestamp}.{body}"`
	//  5. Strip the `whsec_` prefix from your secret and base64-decode to get key bytes
	//  6. Compute HMAC-SHA256 using the key bytes over the signed content
	//  7. Base64-encode the result and compare with the value after `v1,` in
	//     `webhook-signature`
	//  8. Use constant-time comparison to prevent timing attacks
	//
	// **Example (Python):**
	//
	// “`python
	// import base64, hmac, hashlib
	//
	// def verify_webhook(secret, body, headers):
	//
	//	msg_id = headers['webhook-id']
	//	timestamp = headers['webhook-timestamp']
	//	signature = headers['webhook-signature']
	//
	//	secret_str = secret.removeprefix('whsec_')
	//	key = base64.b64decode(secret_str)
	//
	//	signed_content = f"{msg_id}.{timestamp}.{body}"
	//	expected = base64.b64encode(
	//	    hmac.new(key, signed_content.encode(), hashlib.sha256).digest()
	//	).decode()
	//
	//	for sig in signature.split(' '):
	//	    if sig.startswith('v1,') and hmac.compare_digest(expected, sig[3:]):
	//	        return True
	//	return False
	//
	// “`
	//
	// **Example (Node.js):**
	//
	// “`javascript
	// const crypto = require("crypto");
	//
	//	function verifyWebhook(secret, rawBody, headers) {
	//	  const msgId = headers["webhook-id"];
	//	  const timestamp = headers["webhook-timestamp"];
	//	  const signature = headers["webhook-signature"];
	//
	//	  const secretStr = secret.startsWith("whsec_") ? secret.slice(6) : secret;
	//	  const keyBytes = Buffer.from(secretStr, "base64");
	//	  const signedContent = `${msgId}.${timestamp}.${rawBody}`;
	//	  const expected = crypto
	//	    .createHmac("sha256", keyBytes)
	//	    .update(signedContent)
	//	    .digest("base64");
	//
	//	  return signature.split(" ").some((sig) => {
	//	    if (!sig.startsWith("v1,")) return false;
	//	    try {
	//	      return crypto.timingSafeEqual(
	//	        Buffer.from(expected, "base64"),
	//	        Buffer.from(sig.slice(3), "base64")
	//	      );
	//	    } catch {
	//	      return false;
	//	    }
	//	  });
	//	}
	//
	// “`
	//
	// **Security Best Practices:**
	//
	//   - Reject webhooks with timestamps older than 5 minutes to prevent replay attacks
	//   - Always use constant-time comparison for signature verification
	//   - Store your signing secret securely (e.g., environment variable, secrets
	//     manager)
	//   - Return a 2xx status code quickly, then process the webhook asynchronously
	WebhookSubscriptions WebhookSubscriptionService
	Webhooks             WebhookService
	// Check whether a recipient address supports iMessage or RCS before sending a
	// message.
	Capability CapabilityService
	// Contact Card lets you set and share your contact information (name and profile
	// photo) with chat participants via iMessage Name and Photo Sharing.
	//
	// Use `POST /v3/contact_card` to create or update a card for a phone number. Use
	// `PATCH /v3/contact_card` to update an existing active card. Use
	// `GET /v3/contact_card` to retrieve the active card(s) for your partner account.
	//
	// **Sharing behavior:** Sharing may not take effect in every chat due to
	// limitations outside our control. We recommend calling the share endpoint once
	// per day, after the first outbound activity.
	ContactCard ContactCardService
}

Client creates a struct with services and top level methods that help with interacting with the linq-api-v3 API. You should not instantiate this client directly, and instead use the NewClient method instead.

func NewClient

func NewClient(opts ...option.RequestOption) (r Client)

NewClient generates a new client with the default option read from the environment (LINQ_API_V3_API_KEY, LINQ_WEBHOOK_SECRET, LINQ_API_V3_BASE_URL). The option passed in as arguments are applied after these default arguments, and all option will be passed down to the services and requests that this client makes.

func (*Client) Delete

func (r *Client) Delete(ctx context.Context, path string, params any, res any, opts ...option.RequestOption) error

Delete makes a DELETE request with the given URL, params, and optionally deserializes to a response. See [Execute] documentation on the params and response.

func (*Client) Execute

func (r *Client) Execute(ctx context.Context, method string, path string, params any, res any, opts ...option.RequestOption) error

Execute makes a request with the given context, method, URL, request params, response, and request options. This is useful for hitting undocumented endpoints while retaining the base URL, auth, retries, and other options from the client.

If a byte slice or an io.Reader is supplied to params, it will be used as-is for the request body.

The params is by default serialized into the body using encoding/json. If your type implements a MarshalJSON function, it will be used instead to serialize the request. If a URLQuery method is implemented, the returned url.Values will be used as query strings to the url.

If your params struct uses param.Field, you must provide either [MarshalJSON], [URLQuery], and/or [MarshalForm] functions. It is undefined behavior to use a struct uses param.Field without specifying how it is serialized.

Any "…Params" object defined in this library can be used as the request argument. Note that 'path' arguments will not be forwarded into the url.

The response body will be deserialized into the res variable, depending on its type:

  • A pointer to a *http.Response is populated by the raw response.
  • A pointer to a byte array will be populated with the contents of the request body.
  • A pointer to any other type uses this library's default JSON decoding, which respects UnmarshalJSON if it is defined on the type.
  • A nil value will not read the response body.

For even greater flexibility, see option.WithResponseInto and option.WithResponseBodyInto.

func (*Client) Get

func (r *Client) Get(ctx context.Context, path string, params any, res any, opts ...option.RequestOption) error

Get makes a GET request with the given URL, params, and optionally deserializes to a response. See [Execute] documentation on the params and response.

func (*Client) Patch

func (r *Client) Patch(ctx context.Context, path string, params any, res any, opts ...option.RequestOption) error

Patch makes a PATCH request with the given URL, params, and optionally deserializes to a response. See [Execute] documentation on the params and response.

func (*Client) Post

func (r *Client) Post(ctx context.Context, path string, params any, res any, opts ...option.RequestOption) error

Post makes a POST request with the given URL, params, and optionally deserializes to a response. See [Execute] documentation on the params and response.

func (*Client) Put

func (r *Client) Put(ctx context.Context, path string, params any, res any, opts ...option.RequestOption) error

Put makes a PUT request with the given URL, params, and optionally deserializes to a response. See [Execute] documentation on the params and response.

type ConnectionCreatedWebhookEvent added in v0.49.0

type ConnectionCreatedWebhookEvent struct {
	// API version for the webhook payload format
	APIVersion string `json:"api_version" api:"required"`
	// When the event was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// The payment request, as returned by
	// `GET /v3/payment_requests/{paymentRequestId}`.
	Data ConnectionCreatedWebhookEventData `json:"data" api:"required"`
	// Unique identifier for this event (for deduplication)
	EventID string `json:"event_id" api:"required" format:"uuid"`
	// Any of "payment.succeeded", "payment.canceled", "payment.expired",
	// "message.sent", "message.received", "message.read", "message.delivered",
	// "message.failed", "message.edited", "reaction.added", "reaction.removed",
	// "poll.received", "poll.failed", "poll.sent", "poll.delivered", "poll.read",
	// "poll.updated", "poll.vote.added", "poll.vote.removed", "poll.reaction.added",
	// "participant.added", "participant.removed", "chat.created",
	// "chat.group_name_updated", "chat.group_icon_updated",
	// "chat.group_name_update_failed", "chat.group_icon_update_failed",
	// "chat.background_updated", "chat.background_update_failed",
	// "chat.typing_indicator.started", "chat.typing_indicator.stopped",
	// "phone_number.status_updated", "contact_card.received", "call.initiated",
	// "call.ringing", "call.answered", "call.ended", "call.failed", "call.declined",
	// "call.no_answer", "location.sharing.started", "location.sharing.stopped",
	// "payment.declined", "payment.authorized", "connection.created",
	// "connection.revoked".
	EventType ConnectionCreatedWebhookEventEventType `json:"event_type" api:"required"`
	// Partner identifier. Present on all webhooks for cross-referencing.
	PartnerID string `json:"partner_id" api:"required"`
	// Trace ID for debugging and correlation across systems.
	TraceID string `json:"trace_id" api:"required"`
	// Date-based webhook payload version. Determined by the `?version=` query
	// parameter in your webhook subscription URL. If no version parameter is
	// specified, defaults based on subscription creation date.
	WebhookVersion string `json:"webhook_version" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		APIVersion     respjson.Field
		CreatedAt      respjson.Field
		Data           respjson.Field
		EventID        respjson.Field
		EventType      respjson.Field
		PartnerID      respjson.Field
		TraceID        respjson.Field
		WebhookVersion respjson.Field
		ExtraFields    map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (ConnectionCreatedWebhookEvent) RawJSON added in v0.49.0

Returns the unmodified JSON received from the API

func (*ConnectionCreatedWebhookEvent) UnmarshalJSON added in v0.49.0

func (r *ConnectionCreatedWebhookEvent) UnmarshalJSON(data []byte) error

type ConnectionCreatedWebhookEventData added in v0.49.0

type ConnectionCreatedWebhookEventData struct {
	// The payment request id.
	ID string `json:"id" api:"required" format:"uuid"`
	// What was charged at checkout, in the currency's minor units. In `subscription`
	// mode this is the first invoice's total — all items after any discounts are
	// applied.
	Amount int64 `json:"amount" api:"required"`
	// URL the recipient opens to pay
	// (`https://zero.linqapp.com/pay/{slug}?session=...`).
	CheckoutURL string    `json:"checkout_url" api:"required"`
	CreatedAt   time.Time `json:"created_at" api:"required" format:"date-time"`
	Currency    string    `json:"currency" api:"required"`
	Object      string    `json:"object" api:"required"`
	// Any of "succeeded", "failed", "canceled", "expired".
	Status      string `json:"status" api:"required"`
	Description string `json:"description"`
	// Subscription mode — the discount Stripe applied, read back from the coupon.
	// Absent when none was applied.
	Discount ConnectionCreatedWebhookEventDataDiscount `json:"discount"`
	// Subscription mode — how often the subscription renews.
	//
	// Any of "day", "week", "month", "year".
	Interval string `json:"interval"`
	// Subscription mode — intervals per renewal.
	IntervalCount int64             `json:"interval_count"`
	Metadata      map[string]string `json:"metadata"`
	// Whether the request collected a one-time charge or started a subscription.
	//
	// Any of "payment", "subscription".
	Mode string `json:"mode"`
	// Natural-rail join keys, present when `rail: natural`.
	Natural ConnectionCreatedWebhookEventDataNatural `json:"natural"`
	// Subscription mode — the recurring price subscribed to.
	PriceID string `json:"price_id"`
	// Subscription mode — units of the price subscribed to.
	Quantity int64 `json:"quantity"`
	// The rail this request settled on.
	//
	// Any of "stripe", "natural".
	Rail string `json:"rail"`
	// Ids of the Stripe objects on your connected account — join keys into your own
	// Stripe Dashboard/API. Manage a subscription's post-checkout lifecycle with
	// `subscription_id`.
	Stripe ConnectionCreatedWebhookEventDataStripe `json:"stripe"`
	// Subscription mode — when the free trial ends and the first charge happens. On a
	// trial request, `payment.succeeded` means the payment method was collected ($0
	// moved).
	TrialEnd  time.Time `json:"trial_end" format:"date-time"`
	UpdatedAt time.Time `json:"updated_at" format:"date-time"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ID            respjson.Field
		Amount        respjson.Field
		CheckoutURL   respjson.Field
		CreatedAt     respjson.Field
		Currency      respjson.Field
		Object        respjson.Field
		Status        respjson.Field
		Description   respjson.Field
		Discount      respjson.Field
		Interval      respjson.Field
		IntervalCount respjson.Field
		Metadata      respjson.Field
		Mode          respjson.Field
		Natural       respjson.Field
		PriceID       respjson.Field
		Quantity      respjson.Field
		Rail          respjson.Field
		Stripe        respjson.Field
		TrialEnd      respjson.Field
		UpdatedAt     respjson.Field
		ExtraFields   map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

The payment request, as returned by `GET /v3/payment_requests/{paymentRequestId}`.

func (ConnectionCreatedWebhookEventData) RawJSON added in v0.49.0

Returns the unmodified JSON received from the API

func (*ConnectionCreatedWebhookEventData) UnmarshalJSON added in v0.49.0

func (r *ConnectionCreatedWebhookEventData) UnmarshalJSON(data []byte) error

type ConnectionCreatedWebhookEventDataDiscount added in v0.49.0

type ConnectionCreatedWebhookEventDataDiscount struct {
	Coupon string `json:"coupon"`
	// Name of the coupon/promo code displayed to customers.
	Label         string `json:"label"`
	PromotionCode string `json:"promotion_code"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Coupon        respjson.Field
		Label         respjson.Field
		PromotionCode respjson.Field
		ExtraFields   map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Subscription mode — the discount Stripe applied, read back from the coupon. Absent when none was applied.

func (ConnectionCreatedWebhookEventDataDiscount) RawJSON added in v0.49.0

Returns the unmodified JSON received from the API

func (*ConnectionCreatedWebhookEventDataDiscount) UnmarshalJSON added in v0.49.0

func (r *ConnectionCreatedWebhookEventDataDiscount) UnmarshalJSON(data []byte) error

type ConnectionCreatedWebhookEventDataNatural added in v0.49.0

type ConnectionCreatedWebhookEventDataNatural struct {
	// The Natural payment request (`prq_...`).
	PaymentRequestID string `json:"payment_request_id"`
	// The settled transaction (`txn_...`).
	TransactionID string `json:"transaction_id"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		PaymentRequestID respjson.Field
		TransactionID    respjson.Field
		ExtraFields      map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Natural-rail join keys, present when `rail: natural`.

func (ConnectionCreatedWebhookEventDataNatural) RawJSON added in v0.49.0

Returns the unmodified JSON received from the API

func (*ConnectionCreatedWebhookEventDataNatural) UnmarshalJSON added in v0.49.0

func (r *ConnectionCreatedWebhookEventDataNatural) UnmarshalJSON(data []byte) error

type ConnectionCreatedWebhookEventDataStripe added in v0.49.0

type ConnectionCreatedWebhookEventDataStripe struct {
	// The Customer the request is attached to (`cus_...`). Always set in subscription
	// mode; set in payment mode only when the request was created with a
	// `customer_id`.
	CustomerID string `json:"customer_id"`
	// The PaymentIntent collected at checkout (`pi_...`).
	PaymentIntentID string `json:"payment_intent_id"`
	// Subscription mode — the Subscription (`sub_...`).
	SubscriptionID string `json:"subscription_id"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		CustomerID      respjson.Field
		PaymentIntentID respjson.Field
		SubscriptionID  respjson.Field
		ExtraFields     map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Ids of the Stripe objects on your connected account — join keys into your own Stripe Dashboard/API. Manage a subscription's post-checkout lifecycle with `subscription_id`.

func (ConnectionCreatedWebhookEventDataStripe) RawJSON added in v0.49.0

Returns the unmodified JSON received from the API

func (*ConnectionCreatedWebhookEventDataStripe) UnmarshalJSON added in v0.49.0

func (r *ConnectionCreatedWebhookEventDataStripe) UnmarshalJSON(data []byte) error

type ConnectionCreatedWebhookEventEventType added in v0.49.0

type ConnectionCreatedWebhookEventEventType string
const (
	ConnectionCreatedWebhookEventEventTypePaymentSucceeded           ConnectionCreatedWebhookEventEventType = "payment.succeeded"
	ConnectionCreatedWebhookEventEventTypePaymentCanceled            ConnectionCreatedWebhookEventEventType = "payment.canceled"
	ConnectionCreatedWebhookEventEventTypePaymentExpired             ConnectionCreatedWebhookEventEventType = "payment.expired"
	ConnectionCreatedWebhookEventEventTypeMessageSent                ConnectionCreatedWebhookEventEventType = "message.sent"
	ConnectionCreatedWebhookEventEventTypeMessageReceived            ConnectionCreatedWebhookEventEventType = "message.received"
	ConnectionCreatedWebhookEventEventTypeMessageRead                ConnectionCreatedWebhookEventEventType = "message.read"
	ConnectionCreatedWebhookEventEventTypeMessageDelivered           ConnectionCreatedWebhookEventEventType = "message.delivered"
	ConnectionCreatedWebhookEventEventTypeMessageFailed              ConnectionCreatedWebhookEventEventType = "message.failed"
	ConnectionCreatedWebhookEventEventTypeMessageEdited              ConnectionCreatedWebhookEventEventType = "message.edited"
	ConnectionCreatedWebhookEventEventTypeReactionAdded              ConnectionCreatedWebhookEventEventType = "reaction.added"
	ConnectionCreatedWebhookEventEventTypeReactionRemoved            ConnectionCreatedWebhookEventEventType = "reaction.removed"
	ConnectionCreatedWebhookEventEventTypePollReceived               ConnectionCreatedWebhookEventEventType = "poll.received"
	ConnectionCreatedWebhookEventEventTypePollFailed                 ConnectionCreatedWebhookEventEventType = "poll.failed"
	ConnectionCreatedWebhookEventEventTypePollSent                   ConnectionCreatedWebhookEventEventType = "poll.sent"
	ConnectionCreatedWebhookEventEventTypePollDelivered              ConnectionCreatedWebhookEventEventType = "poll.delivered"
	ConnectionCreatedWebhookEventEventTypePollRead                   ConnectionCreatedWebhookEventEventType = "poll.read"
	ConnectionCreatedWebhookEventEventTypePollUpdated                ConnectionCreatedWebhookEventEventType = "poll.updated"
	ConnectionCreatedWebhookEventEventTypePollVoteAdded              ConnectionCreatedWebhookEventEventType = "poll.vote.added"
	ConnectionCreatedWebhookEventEventTypePollVoteRemoved            ConnectionCreatedWebhookEventEventType = "poll.vote.removed"
	ConnectionCreatedWebhookEventEventTypePollReactionAdded          ConnectionCreatedWebhookEventEventType = "poll.reaction.added"
	ConnectionCreatedWebhookEventEventTypeParticipantAdded           ConnectionCreatedWebhookEventEventType = "participant.added"
	ConnectionCreatedWebhookEventEventTypeParticipantRemoved         ConnectionCreatedWebhookEventEventType = "participant.removed"
	ConnectionCreatedWebhookEventEventTypeChatCreated                ConnectionCreatedWebhookEventEventType = "chat.created"
	ConnectionCreatedWebhookEventEventTypeChatGroupNameUpdated       ConnectionCreatedWebhookEventEventType = "chat.group_name_updated"
	ConnectionCreatedWebhookEventEventTypeChatGroupIconUpdated       ConnectionCreatedWebhookEventEventType = "chat.group_icon_updated"
	ConnectionCreatedWebhookEventEventTypeChatGroupNameUpdateFailed  ConnectionCreatedWebhookEventEventType = "chat.group_name_update_failed"
	ConnectionCreatedWebhookEventEventTypeChatGroupIconUpdateFailed  ConnectionCreatedWebhookEventEventType = "chat.group_icon_update_failed"
	ConnectionCreatedWebhookEventEventTypeChatBackgroundUpdated      ConnectionCreatedWebhookEventEventType = "chat.background_updated"
	ConnectionCreatedWebhookEventEventTypeChatBackgroundUpdateFailed ConnectionCreatedWebhookEventEventType = "chat.background_update_failed"
	ConnectionCreatedWebhookEventEventTypeChatTypingIndicatorStarted ConnectionCreatedWebhookEventEventType = "chat.typing_indicator.started"
	ConnectionCreatedWebhookEventEventTypeChatTypingIndicatorStopped ConnectionCreatedWebhookEventEventType = "chat.typing_indicator.stopped"
	ConnectionCreatedWebhookEventEventTypePhoneNumberStatusUpdated   ConnectionCreatedWebhookEventEventType = "phone_number.status_updated"
	ConnectionCreatedWebhookEventEventTypeContactCardReceived        ConnectionCreatedWebhookEventEventType = "contact_card.received"
	ConnectionCreatedWebhookEventEventTypeCallInitiated              ConnectionCreatedWebhookEventEventType = "call.initiated"
	ConnectionCreatedWebhookEventEventTypeCallRinging                ConnectionCreatedWebhookEventEventType = "call.ringing"
	ConnectionCreatedWebhookEventEventTypeCallAnswered               ConnectionCreatedWebhookEventEventType = "call.answered"
	ConnectionCreatedWebhookEventEventTypeCallEnded                  ConnectionCreatedWebhookEventEventType = "call.ended"
	ConnectionCreatedWebhookEventEventTypeCallFailed                 ConnectionCreatedWebhookEventEventType = "call.failed"
	ConnectionCreatedWebhookEventEventTypeCallDeclined               ConnectionCreatedWebhookEventEventType = "call.declined"
	ConnectionCreatedWebhookEventEventTypeCallNoAnswer               ConnectionCreatedWebhookEventEventType = "call.no_answer"
	ConnectionCreatedWebhookEventEventTypeLocationSharingStarted     ConnectionCreatedWebhookEventEventType = "location.sharing.started"
	ConnectionCreatedWebhookEventEventTypeLocationSharingStopped     ConnectionCreatedWebhookEventEventType = "location.sharing.stopped"
	ConnectionCreatedWebhookEventEventTypePaymentDeclined            ConnectionCreatedWebhookEventEventType = "payment.declined"
	ConnectionCreatedWebhookEventEventTypePaymentAuthorized          ConnectionCreatedWebhookEventEventType = "payment.authorized"
	ConnectionCreatedWebhookEventEventTypeConnectionCreated          ConnectionCreatedWebhookEventEventType = "connection.created"
	ConnectionCreatedWebhookEventEventTypeConnectionRevoked          ConnectionCreatedWebhookEventEventType = "connection.revoked"
)

type ConnectionRevokedWebhookEvent added in v0.49.0

type ConnectionRevokedWebhookEvent struct {
	// API version for the webhook payload format
	APIVersion string `json:"api_version" api:"required"`
	// When the event was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// The payment request, as returned by
	// `GET /v3/payment_requests/{paymentRequestId}`.
	Data ConnectionRevokedWebhookEventData `json:"data" api:"required"`
	// Unique identifier for this event (for deduplication)
	EventID string `json:"event_id" api:"required" format:"uuid"`
	// Any of "payment.succeeded", "payment.canceled", "payment.expired",
	// "message.sent", "message.received", "message.read", "message.delivered",
	// "message.failed", "message.edited", "reaction.added", "reaction.removed",
	// "poll.received", "poll.failed", "poll.sent", "poll.delivered", "poll.read",
	// "poll.updated", "poll.vote.added", "poll.vote.removed", "poll.reaction.added",
	// "participant.added", "participant.removed", "chat.created",
	// "chat.group_name_updated", "chat.group_icon_updated",
	// "chat.group_name_update_failed", "chat.group_icon_update_failed",
	// "chat.background_updated", "chat.background_update_failed",
	// "chat.typing_indicator.started", "chat.typing_indicator.stopped",
	// "phone_number.status_updated", "contact_card.received", "call.initiated",
	// "call.ringing", "call.answered", "call.ended", "call.failed", "call.declined",
	// "call.no_answer", "location.sharing.started", "location.sharing.stopped",
	// "payment.declined", "payment.authorized", "connection.created",
	// "connection.revoked".
	EventType ConnectionRevokedWebhookEventEventType `json:"event_type" api:"required"`
	// Partner identifier. Present on all webhooks for cross-referencing.
	PartnerID string `json:"partner_id" api:"required"`
	// Trace ID for debugging and correlation across systems.
	TraceID string `json:"trace_id" api:"required"`
	// Date-based webhook payload version. Determined by the `?version=` query
	// parameter in your webhook subscription URL. If no version parameter is
	// specified, defaults based on subscription creation date.
	WebhookVersion string `json:"webhook_version" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		APIVersion     respjson.Field
		CreatedAt      respjson.Field
		Data           respjson.Field
		EventID        respjson.Field
		EventType      respjson.Field
		PartnerID      respjson.Field
		TraceID        respjson.Field
		WebhookVersion respjson.Field
		ExtraFields    map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (ConnectionRevokedWebhookEvent) RawJSON added in v0.49.0

Returns the unmodified JSON received from the API

func (*ConnectionRevokedWebhookEvent) UnmarshalJSON added in v0.49.0

func (r *ConnectionRevokedWebhookEvent) UnmarshalJSON(data []byte) error

type ConnectionRevokedWebhookEventData added in v0.49.0

type ConnectionRevokedWebhookEventData struct {
	// The payment request id.
	ID string `json:"id" api:"required" format:"uuid"`
	// What was charged at checkout, in the currency's minor units. In `subscription`
	// mode this is the first invoice's total — all items after any discounts are
	// applied.
	Amount int64 `json:"amount" api:"required"`
	// URL the recipient opens to pay
	// (`https://zero.linqapp.com/pay/{slug}?session=...`).
	CheckoutURL string    `json:"checkout_url" api:"required"`
	CreatedAt   time.Time `json:"created_at" api:"required" format:"date-time"`
	Currency    string    `json:"currency" api:"required"`
	Object      string    `json:"object" api:"required"`
	// Any of "succeeded", "failed", "canceled", "expired".
	Status      string `json:"status" api:"required"`
	Description string `json:"description"`
	// Subscription mode — the discount Stripe applied, read back from the coupon.
	// Absent when none was applied.
	Discount ConnectionRevokedWebhookEventDataDiscount `json:"discount"`
	// Subscription mode — how often the subscription renews.
	//
	// Any of "day", "week", "month", "year".
	Interval string `json:"interval"`
	// Subscription mode — intervals per renewal.
	IntervalCount int64             `json:"interval_count"`
	Metadata      map[string]string `json:"metadata"`
	// Whether the request collected a one-time charge or started a subscription.
	//
	// Any of "payment", "subscription".
	Mode string `json:"mode"`
	// Natural-rail join keys, present when `rail: natural`.
	Natural ConnectionRevokedWebhookEventDataNatural `json:"natural"`
	// Subscription mode — the recurring price subscribed to.
	PriceID string `json:"price_id"`
	// Subscription mode — units of the price subscribed to.
	Quantity int64 `json:"quantity"`
	// The rail this request settled on.
	//
	// Any of "stripe", "natural".
	Rail string `json:"rail"`
	// Ids of the Stripe objects on your connected account — join keys into your own
	// Stripe Dashboard/API. Manage a subscription's post-checkout lifecycle with
	// `subscription_id`.
	Stripe ConnectionRevokedWebhookEventDataStripe `json:"stripe"`
	// Subscription mode — when the free trial ends and the first charge happens. On a
	// trial request, `payment.succeeded` means the payment method was collected ($0
	// moved).
	TrialEnd  time.Time `json:"trial_end" format:"date-time"`
	UpdatedAt time.Time `json:"updated_at" format:"date-time"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ID            respjson.Field
		Amount        respjson.Field
		CheckoutURL   respjson.Field
		CreatedAt     respjson.Field
		Currency      respjson.Field
		Object        respjson.Field
		Status        respjson.Field
		Description   respjson.Field
		Discount      respjson.Field
		Interval      respjson.Field
		IntervalCount respjson.Field
		Metadata      respjson.Field
		Mode          respjson.Field
		Natural       respjson.Field
		PriceID       respjson.Field
		Quantity      respjson.Field
		Rail          respjson.Field
		Stripe        respjson.Field
		TrialEnd      respjson.Field
		UpdatedAt     respjson.Field
		ExtraFields   map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

The payment request, as returned by `GET /v3/payment_requests/{paymentRequestId}`.

func (ConnectionRevokedWebhookEventData) RawJSON added in v0.49.0

Returns the unmodified JSON received from the API

func (*ConnectionRevokedWebhookEventData) UnmarshalJSON added in v0.49.0

func (r *ConnectionRevokedWebhookEventData) UnmarshalJSON(data []byte) error

type ConnectionRevokedWebhookEventDataDiscount added in v0.49.0

type ConnectionRevokedWebhookEventDataDiscount struct {
	Coupon string `json:"coupon"`
	// Name of the coupon/promo code displayed to customers.
	Label         string `json:"label"`
	PromotionCode string `json:"promotion_code"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Coupon        respjson.Field
		Label         respjson.Field
		PromotionCode respjson.Field
		ExtraFields   map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Subscription mode — the discount Stripe applied, read back from the coupon. Absent when none was applied.

func (ConnectionRevokedWebhookEventDataDiscount) RawJSON added in v0.49.0

Returns the unmodified JSON received from the API

func (*ConnectionRevokedWebhookEventDataDiscount) UnmarshalJSON added in v0.49.0

func (r *ConnectionRevokedWebhookEventDataDiscount) UnmarshalJSON(data []byte) error

type ConnectionRevokedWebhookEventDataNatural added in v0.49.0

type ConnectionRevokedWebhookEventDataNatural struct {
	// The Natural payment request (`prq_...`).
	PaymentRequestID string `json:"payment_request_id"`
	// The settled transaction (`txn_...`).
	TransactionID string `json:"transaction_id"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		PaymentRequestID respjson.Field
		TransactionID    respjson.Field
		ExtraFields      map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Natural-rail join keys, present when `rail: natural`.

func (ConnectionRevokedWebhookEventDataNatural) RawJSON added in v0.49.0

Returns the unmodified JSON received from the API

func (*ConnectionRevokedWebhookEventDataNatural) UnmarshalJSON added in v0.49.0

func (r *ConnectionRevokedWebhookEventDataNatural) UnmarshalJSON(data []byte) error

type ConnectionRevokedWebhookEventDataStripe added in v0.49.0

type ConnectionRevokedWebhookEventDataStripe struct {
	// The Customer the request is attached to (`cus_...`). Always set in subscription
	// mode; set in payment mode only when the request was created with a
	// `customer_id`.
	CustomerID string `json:"customer_id"`
	// The PaymentIntent collected at checkout (`pi_...`).
	PaymentIntentID string `json:"payment_intent_id"`
	// Subscription mode — the Subscription (`sub_...`).
	SubscriptionID string `json:"subscription_id"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		CustomerID      respjson.Field
		PaymentIntentID respjson.Field
		SubscriptionID  respjson.Field
		ExtraFields     map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Ids of the Stripe objects on your connected account — join keys into your own Stripe Dashboard/API. Manage a subscription's post-checkout lifecycle with `subscription_id`.

func (ConnectionRevokedWebhookEventDataStripe) RawJSON added in v0.49.0

Returns the unmodified JSON received from the API

func (*ConnectionRevokedWebhookEventDataStripe) UnmarshalJSON added in v0.49.0

func (r *ConnectionRevokedWebhookEventDataStripe) UnmarshalJSON(data []byte) error

type ConnectionRevokedWebhookEventEventType added in v0.49.0

type ConnectionRevokedWebhookEventEventType string
const (
	ConnectionRevokedWebhookEventEventTypePaymentSucceeded           ConnectionRevokedWebhookEventEventType = "payment.succeeded"
	ConnectionRevokedWebhookEventEventTypePaymentCanceled            ConnectionRevokedWebhookEventEventType = "payment.canceled"
	ConnectionRevokedWebhookEventEventTypePaymentExpired             ConnectionRevokedWebhookEventEventType = "payment.expired"
	ConnectionRevokedWebhookEventEventTypeMessageSent                ConnectionRevokedWebhookEventEventType = "message.sent"
	ConnectionRevokedWebhookEventEventTypeMessageReceived            ConnectionRevokedWebhookEventEventType = "message.received"
	ConnectionRevokedWebhookEventEventTypeMessageRead                ConnectionRevokedWebhookEventEventType = "message.read"
	ConnectionRevokedWebhookEventEventTypeMessageDelivered           ConnectionRevokedWebhookEventEventType = "message.delivered"
	ConnectionRevokedWebhookEventEventTypeMessageFailed              ConnectionRevokedWebhookEventEventType = "message.failed"
	ConnectionRevokedWebhookEventEventTypeMessageEdited              ConnectionRevokedWebhookEventEventType = "message.edited"
	ConnectionRevokedWebhookEventEventTypeReactionAdded              ConnectionRevokedWebhookEventEventType = "reaction.added"
	ConnectionRevokedWebhookEventEventTypeReactionRemoved            ConnectionRevokedWebhookEventEventType = "reaction.removed"
	ConnectionRevokedWebhookEventEventTypePollReceived               ConnectionRevokedWebhookEventEventType = "poll.received"
	ConnectionRevokedWebhookEventEventTypePollFailed                 ConnectionRevokedWebhookEventEventType = "poll.failed"
	ConnectionRevokedWebhookEventEventTypePollSent                   ConnectionRevokedWebhookEventEventType = "poll.sent"
	ConnectionRevokedWebhookEventEventTypePollDelivered              ConnectionRevokedWebhookEventEventType = "poll.delivered"
	ConnectionRevokedWebhookEventEventTypePollRead                   ConnectionRevokedWebhookEventEventType = "poll.read"
	ConnectionRevokedWebhookEventEventTypePollUpdated                ConnectionRevokedWebhookEventEventType = "poll.updated"
	ConnectionRevokedWebhookEventEventTypePollVoteAdded              ConnectionRevokedWebhookEventEventType = "poll.vote.added"
	ConnectionRevokedWebhookEventEventTypePollVoteRemoved            ConnectionRevokedWebhookEventEventType = "poll.vote.removed"
	ConnectionRevokedWebhookEventEventTypePollReactionAdded          ConnectionRevokedWebhookEventEventType = "poll.reaction.added"
	ConnectionRevokedWebhookEventEventTypeParticipantAdded           ConnectionRevokedWebhookEventEventType = "participant.added"
	ConnectionRevokedWebhookEventEventTypeParticipantRemoved         ConnectionRevokedWebhookEventEventType = "participant.removed"
	ConnectionRevokedWebhookEventEventTypeChatCreated                ConnectionRevokedWebhookEventEventType = "chat.created"
	ConnectionRevokedWebhookEventEventTypeChatGroupNameUpdated       ConnectionRevokedWebhookEventEventType = "chat.group_name_updated"
	ConnectionRevokedWebhookEventEventTypeChatGroupIconUpdated       ConnectionRevokedWebhookEventEventType = "chat.group_icon_updated"
	ConnectionRevokedWebhookEventEventTypeChatGroupNameUpdateFailed  ConnectionRevokedWebhookEventEventType = "chat.group_name_update_failed"
	ConnectionRevokedWebhookEventEventTypeChatGroupIconUpdateFailed  ConnectionRevokedWebhookEventEventType = "chat.group_icon_update_failed"
	ConnectionRevokedWebhookEventEventTypeChatBackgroundUpdated      ConnectionRevokedWebhookEventEventType = "chat.background_updated"
	ConnectionRevokedWebhookEventEventTypeChatBackgroundUpdateFailed ConnectionRevokedWebhookEventEventType = "chat.background_update_failed"
	ConnectionRevokedWebhookEventEventTypeChatTypingIndicatorStarted ConnectionRevokedWebhookEventEventType = "chat.typing_indicator.started"
	ConnectionRevokedWebhookEventEventTypeChatTypingIndicatorStopped ConnectionRevokedWebhookEventEventType = "chat.typing_indicator.stopped"
	ConnectionRevokedWebhookEventEventTypePhoneNumberStatusUpdated   ConnectionRevokedWebhookEventEventType = "phone_number.status_updated"
	ConnectionRevokedWebhookEventEventTypeContactCardReceived        ConnectionRevokedWebhookEventEventType = "contact_card.received"
	ConnectionRevokedWebhookEventEventTypeCallInitiated              ConnectionRevokedWebhookEventEventType = "call.initiated"
	ConnectionRevokedWebhookEventEventTypeCallRinging                ConnectionRevokedWebhookEventEventType = "call.ringing"
	ConnectionRevokedWebhookEventEventTypeCallAnswered               ConnectionRevokedWebhookEventEventType = "call.answered"
	ConnectionRevokedWebhookEventEventTypeCallEnded                  ConnectionRevokedWebhookEventEventType = "call.ended"
	ConnectionRevokedWebhookEventEventTypeCallFailed                 ConnectionRevokedWebhookEventEventType = "call.failed"
	ConnectionRevokedWebhookEventEventTypeCallDeclined               ConnectionRevokedWebhookEventEventType = "call.declined"
	ConnectionRevokedWebhookEventEventTypeCallNoAnswer               ConnectionRevokedWebhookEventEventType = "call.no_answer"
	ConnectionRevokedWebhookEventEventTypeLocationSharingStarted     ConnectionRevokedWebhookEventEventType = "location.sharing.started"
	ConnectionRevokedWebhookEventEventTypeLocationSharingStopped     ConnectionRevokedWebhookEventEventType = "location.sharing.stopped"
	ConnectionRevokedWebhookEventEventTypePaymentDeclined            ConnectionRevokedWebhookEventEventType = "payment.declined"
	ConnectionRevokedWebhookEventEventTypePaymentAuthorized          ConnectionRevokedWebhookEventEventType = "payment.authorized"
	ConnectionRevokedWebhookEventEventTypeConnectionCreated          ConnectionRevokedWebhookEventEventType = "connection.created"
	ConnectionRevokedWebhookEventEventTypeConnectionRevoked          ConnectionRevokedWebhookEventEventType = "connection.revoked"
)

type ContactCardGetParams added in v0.8.0

type ContactCardGetParams struct {
	// E.164 phone number to filter by. If omitted, all my cards for the partner are
	// returned.
	PhoneNumber param.Opt[string] `query:"phone_number,omitzero" json:"-"`
	// contains filtered or unexported fields
}

func (ContactCardGetParams) URLQuery added in v0.8.0

func (r ContactCardGetParams) URLQuery() (v url.Values, err error)

URLQuery serializes ContactCardGetParams's query parameters as `url.Values`.

type ContactCardGetResponse added in v0.8.0

type ContactCardGetResponse struct {
	ContactCards []ContactCardGetResponseContactCard `json:"contact_cards" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ContactCards respjson.Field
		ExtraFields  map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (ContactCardGetResponse) RawJSON added in v0.8.0

func (r ContactCardGetResponse) RawJSON() string

Returns the unmodified JSON received from the API

func (*ContactCardGetResponse) UnmarshalJSON added in v0.8.0

func (r *ContactCardGetResponse) UnmarshalJSON(data []byte) error

type ContactCardGetResponseContactCard added in v0.8.0

type ContactCardGetResponseContactCard struct {
	FirstName   string `json:"first_name" api:"required"`
	IsActive    bool   `json:"is_active" api:"required"`
	PhoneNumber string `json:"phone_number" api:"required"`
	ImageURL    string `json:"image_url"`
	LastName    string `json:"last_name"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		FirstName   respjson.Field
		IsActive    respjson.Field
		PhoneNumber respjson.Field
		ImageURL    respjson.Field
		LastName    respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (ContactCardGetResponseContactCard) RawJSON added in v0.8.0

Returns the unmodified JSON received from the API

func (*ContactCardGetResponseContactCard) UnmarshalJSON added in v0.8.0

func (r *ContactCardGetResponseContactCard) UnmarshalJSON(data []byte) error

type ContactCardNewParams added in v0.8.0

type ContactCardNewParams struct {
	// First name for the contact card. Required.
	FirstName string `json:"first_name" api:"required"`
	// E.164 phone number to associate the contact card with
	PhoneNumber string `json:"phone_number" api:"required"`
	// Profile image URL for the contact card.
	ImageURL param.Opt[string] `json:"image_url,omitzero"`
	// Last name for the contact card. Optional.
	LastName param.Opt[string] `json:"last_name,omitzero"`
	// contains filtered or unexported fields
}

func (ContactCardNewParams) MarshalJSON added in v0.8.0

func (r ContactCardNewParams) MarshalJSON() (data []byte, err error)

func (*ContactCardNewParams) UnmarshalJSON added in v0.8.0

func (r *ContactCardNewParams) UnmarshalJSON(data []byte) error

type ContactCardReceivedWebhookEvent added in v0.47.0

type ContactCardReceivedWebhookEvent struct {
	// API version for the webhook payload format
	APIVersion string `json:"api_version" api:"required"`
	// When the event was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// Payload for contact_card.received webhook events.
	//
	// A contact belongs to a line, not to an individual chat. You receive one event
	// per person who shares their contact, regardless of how many chats they have in
	// common with your line.
	//
	// The event fires again whenever the shared contact's name or media changes.
	Data ContactCardReceivedWebhookEventData `json:"data" api:"required"`
	// Unique identifier for this event (for deduplication)
	EventID string `json:"event_id" api:"required" format:"uuid"`
	// Valid webhook event types that can be subscribed to.
	//
	// **Note:** `message.edited` is only delivered to subscriptions using
	// `webhook_version: "2026-02-03"`. Subscribing to this event on a v2025
	// subscription will not produce any deliveries.
	//
	// Any of "message.sent", "message.received", "message.read", "message.delivered",
	// "message.failed", "message.edited", "reaction.added", "reaction.removed",
	// "poll.received", "poll.failed", "poll.sent", "poll.delivered", "poll.read",
	// "poll.updated", "poll.vote.added", "poll.vote.removed", "poll.reaction.added",
	// "participant.added", "participant.removed", "chat.created",
	// "chat.group_name_updated", "chat.group_icon_updated",
	// "chat.group_name_update_failed", "chat.group_icon_update_failed",
	// "chat.background_updated", "chat.background_update_failed",
	// "chat.typing_indicator.started", "chat.typing_indicator.stopped",
	// "phone_number.status_updated", "contact_card.received", "call.initiated",
	// "call.ringing", "call.answered", "call.ended", "call.failed", "call.declined",
	// "call.no_answer", "location.sharing.started", "location.sharing.stopped",
	// "payment.succeeded", "payment.canceled", "payment.expired", "payment.declined",
	// "payment.authorized", "connection.created", "connection.revoked".
	EventType WebhookEventType `json:"event_type" api:"required"`
	// Partner identifier. Present on all webhooks for cross-referencing.
	PartnerID string `json:"partner_id" api:"required"`
	// Trace ID for debugging and correlation across systems.
	TraceID string `json:"trace_id" api:"required"`
	// Date-based webhook payload version. Determined by the `?version=` query
	// parameter in your webhook subscription URL. If no version parameter is
	// specified, defaults based on subscription creation date.
	WebhookVersion string `json:"webhook_version" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		APIVersion     respjson.Field
		CreatedAt      respjson.Field
		Data           respjson.Field
		EventID        respjson.Field
		EventType      respjson.Field
		PartnerID      respjson.Field
		TraceID        respjson.Field
		WebhookVersion respjson.Field
		ExtraFields    map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Complete webhook payload for contact_card.received events

func (ContactCardReceivedWebhookEvent) RawJSON added in v0.47.0

Returns the unmodified JSON received from the API

func (*ContactCardReceivedWebhookEvent) UnmarshalJSON added in v0.47.0

func (r *ContactCardReceivedWebhookEvent) UnmarshalJSON(data []byte) error

type ContactCardReceivedWebhookEventData added in v0.47.0

type ContactCardReceivedWebhookEventData struct {
	// First name from the shared contact card
	FirstName string `json:"first_name" api:"required"`
	// Last name from the shared contact card (may be empty)
	LastName string `json:"last_name" api:"required"`
	// Which of your lines they shared it with.
	OwnerHandle string `json:"owner_handle" api:"required"`
	// The person who shared their card — a phone number or email address.
	SenderHandle string `json:"sender_handle" api:"required"`
	// URL of the contact's media, served from `cdn.linqapp.com`. `null` when the
	// contact shared no media, and also when media was shared but could not be
	// retrieved — this field does not distinguish the two.
	//
	// Download the media and store it yourself. The URL may be signed and expire, in
	// as little as 45 minutes, and altering its query string invalidates it
	// immediately.
	MediaURL string `json:"media_url" api:"nullable"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		FirstName    respjson.Field
		LastName     respjson.Field
		OwnerHandle  respjson.Field
		SenderHandle respjson.Field
		MediaURL     respjson.Field
		ExtraFields  map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Payload for contact_card.received webhook events.

A contact belongs to a line, not to an individual chat. You receive one event per person who shares their contact, regardless of how many chats they have in common with your line.

The event fires again whenever the shared contact's name or media changes.

func (ContactCardReceivedWebhookEventData) RawJSON added in v0.47.0

Returns the unmodified JSON received from the API

func (*ContactCardReceivedWebhookEventData) UnmarshalJSON added in v0.47.0

func (r *ContactCardReceivedWebhookEventData) UnmarshalJSON(data []byte) error

type ContactCardService added in v0.8.0

type ContactCardService struct {
	Options []option.RequestOption
}

Contact Card lets you set and share your contact information (name and profile photo) with chat participants via iMessage Name and Photo Sharing.

Use `POST /v3/contact_card` to create or update a card for a phone number. Use `PATCH /v3/contact_card` to update an existing active card. Use `GET /v3/contact_card` to retrieve the active card(s) for your partner account.

**Sharing behavior:** Sharing may not take effect in every chat due to limitations outside our control. We recommend calling the share endpoint once per day, after the first outbound activity.

ContactCardService contains methods and other services that help with interacting with the linq-api-v3 API.

Note, unlike clients, this service does not read variables from the environment automatically. You should not instantiate this service directly, and instead use the NewContactCardService method instead.

func NewContactCardService added in v0.8.0

func NewContactCardService(opts ...option.RequestOption) (r ContactCardService)

NewContactCardService generates a new service that applies the given options to each request. These options are applied after the parent client's options (if there is one), and before any request-specific options.

func (*ContactCardService) Get added in v0.8.0

Returns the contact card for a specific phone number, or all contact cards for the authenticated partner if no `phone_number` is provided.

func (*ContactCardService) New added in v0.8.0

Creates a contact card for a phone number. This endpoint is intended for initial, one-time setup only.

If setup does not complete, the response is `500` (`2022`) — call this endpoint again.

**Note:** once a card is active, this endpoint returns `409` (`2014`) so an existing card is never overwritten by accident. Use `PATCH /v3/contact_card` to change it.

func (*ContactCardService) Update added in v0.8.0

Partially updates the contact card for a phone number.

Fetches the current contact card and merges the provided fields. Only fields present in the request body are updated; omitted fields retain their existing values.

If the update does not complete, the response is `500` (`2022`) — call this endpoint again.

type ContactCardUpdateParams added in v0.8.0

type ContactCardUpdateParams struct {
	// E.164 phone number of the contact card to update
	PhoneNumber string `query:"phone_number" api:"required" json:"-"`
	// Updated first name. If omitted, the existing value is kept.
	FirstName param.Opt[string] `json:"first_name,omitzero"`
	// Updated profile image URL. If omitted, the existing image is kept.
	ImageURL param.Opt[string] `json:"image_url,omitzero"`
	// Updated last name. If omitted, the existing value is kept.
	LastName param.Opt[string] `json:"last_name,omitzero"`
	// contains filtered or unexported fields
}

func (ContactCardUpdateParams) MarshalJSON added in v0.8.0

func (r ContactCardUpdateParams) MarshalJSON() (data []byte, err error)

func (ContactCardUpdateParams) URLQuery added in v0.8.0

func (r ContactCardUpdateParams) URLQuery() (v url.Values, err error)

URLQuery serializes ContactCardUpdateParams's query parameters as `url.Values`.

func (*ContactCardUpdateParams) UnmarshalJSON added in v0.8.0

func (r *ContactCardUpdateParams) UnmarshalJSON(data []byte) error

type Error

type Error = apierror.Error

type ExperienceGetResponse added in v0.29.0

type ExperienceGetResponse struct {
	Actions     []ExperienceGetResponseAction `json:"actions"`
	DisplayName string                        `json:"display_name"`
	Experience  string                        `json:"experience"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Actions     respjson.Field
		DisplayName respjson.Field
		Experience  respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

What an experience offers you. Deliberately a projection: where its templates live and how they are built is not yours to depend on, so it is not here.

func (ExperienceGetResponse) RawJSON added in v0.29.0

func (r ExperienceGetResponse) RawJSON() string

Returns the unmodified JSON received from the API

func (*ExperienceGetResponse) UnmarshalJSON added in v0.29.0

func (r *ExperienceGetResponse) UnmarshalJSON(data []byte) error

type ExperienceGetResponseAction added in v0.29.0

type ExperienceGetResponseAction struct {
	// Fields you may send in `params`, keyed by the exact name to use.
	Fields  map[string]ExperienceGetResponseActionField `json:"fields"`
	Name    string                                      `json:"name"`
	Summary string                                      `json:"summary"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Fields      respjson.Field
		Name        respjson.Field
		Summary     respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (ExperienceGetResponseAction) RawJSON added in v0.29.0

func (r ExperienceGetResponseAction) RawJSON() string

Returns the unmodified JSON received from the API

func (*ExperienceGetResponseAction) UnmarshalJSON added in v0.29.0

func (r *ExperienceGetResponseAction) UnmarshalJSON(data []byte) error

type ExperienceGetResponseActionField added in v0.29.0

type ExperienceGetResponseActionField struct {
	// Maximum length, for strings.
	Max      int64 `json:"max"`
	Required bool  `json:"required"`
	// Any of "string", "cents", "int", "url".
	Type string `json:"type"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Max         respjson.Field
		Required    respjson.Field
		Type        respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (ExperienceGetResponseActionField) RawJSON added in v0.29.0

Returns the unmodified JSON received from the API

func (*ExperienceGetResponseActionField) UnmarshalJSON added in v0.29.0

func (r *ExperienceGetResponseActionField) UnmarshalJSON(data []byte) error

type ExperienceListResponse added in v0.29.0

type ExperienceListResponse struct {
	Experiences []ExperienceListResponseExperience `json:"experiences"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Experiences respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (ExperienceListResponse) RawJSON added in v0.29.0

func (r ExperienceListResponse) RawJSON() string

Returns the unmodified JSON received from the API

func (*ExperienceListResponse) UnmarshalJSON added in v0.29.0

func (r *ExperienceListResponse) UnmarshalJSON(data []byte) error

type ExperienceListResponseExperience added in v0.29.0

type ExperienceListResponseExperience struct {
	Actions     []ExperienceListResponseExperienceAction `json:"actions"`
	DisplayName string                                   `json:"display_name"`
	Experience  string                                   `json:"experience"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Actions     respjson.Field
		DisplayName respjson.Field
		Experience  respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

What an experience offers you. Deliberately a projection: where its templates live and how they are built is not yours to depend on, so it is not here.

func (ExperienceListResponseExperience) RawJSON added in v0.29.0

Returns the unmodified JSON received from the API

func (*ExperienceListResponseExperience) UnmarshalJSON added in v0.29.0

func (r *ExperienceListResponseExperience) UnmarshalJSON(data []byte) error

type ExperienceListResponseExperienceAction added in v0.29.0

type ExperienceListResponseExperienceAction struct {
	// Fields you may send in `params`, keyed by the exact name to use.
	Fields  map[string]ExperienceListResponseExperienceActionField `json:"fields"`
	Name    string                                                 `json:"name"`
	Summary string                                                 `json:"summary"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Fields      respjson.Field
		Name        respjson.Field
		Summary     respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (ExperienceListResponseExperienceAction) RawJSON added in v0.29.0

Returns the unmodified JSON received from the API

func (*ExperienceListResponseExperienceAction) UnmarshalJSON added in v0.29.0

func (r *ExperienceListResponseExperienceAction) UnmarshalJSON(data []byte) error

type ExperienceListResponseExperienceActionField added in v0.29.0

type ExperienceListResponseExperienceActionField struct {
	// Maximum length, for strings.
	Max      int64 `json:"max"`
	Required bool  `json:"required"`
	// Any of "string", "cents", "int", "url".
	Type string `json:"type"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Max         respjson.Field
		Required    respjson.Field
		Type        respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (ExperienceListResponseExperienceActionField) RawJSON added in v0.29.0

Returns the unmodified JSON received from the API

func (*ExperienceListResponseExperienceActionField) UnmarshalJSON added in v0.29.0

func (r *ExperienceListResponseExperienceActionField) UnmarshalJSON(data []byte) error

type ExperienceService added in v0.29.0

type ExperienceService struct {
	Options []option.RequestOption
}

An **experience** renders inside Linq's iMessage app as a native card, instead of as text or a link. You invoke one by name; Linq resolves the recipient, mints any session it needs, composes the card and sends it.

Send it to `POST /v3/chats/{chatId}/messages`:

```json

{
  "message": {
    "experience": {
      "name": "agentpay",
      "action": "request_payment",
      "params": {
        "checkout_url": "https://zero.linqapp.com/pay/acme?session=tok_..."
      }
    }
  }
}

```

The key is `experience` — what you're invoking. Nested under it is its `name`, the action you're invoking on it, and that action's params. A card **is** the whole message on Apple's side, so a message carries either `experience` or `parts`, never both, and an action goes to exactly one recipient.

## What you can invoke

| Experience | Action | What the customer sees | | ----------- | ----------------- | --------------------------------------------------------------------------------------------- | | `agentpay` | `request_payment` | A payment request they can pay in the app. Turns itself into "Paid" in place once it settles. | | `agentcard` | `attach_card` | A prompt to add a card to their wallet. | | `agentcard` | `approve_card` | A passkey approval for a virtual card. | | `link` | `open` | A card that opens a URL you supply. |

`GET /v3/experiences` is the list to build against, with every action and the fields each accepts — anything not described there is unsupported. Fields are display copy unless documented otherwise.

## Params are checked before the card is sent

Unknown fields are **rejected rather than ignored**, so copy that would never have rendered fails for you now instead of arriving wrong on somebody's phone. Some fields are read rather than sent: `agentpay`'s `request_payment` takes only a `checkout_url` and resolves the amount and reason from that payment request, so a card can never claim a figure the checkout will not charge.

Cards are **iMessage-only**. Recipients without the app see a static version built from the same copy; SMS and RCS recipients cannot receive one at all (error codes 2018 and 4005).

ExperienceService contains methods and other services that help with interacting with the linq-api-v3 API.

Note, unlike clients, this service does not read variables from the environment automatically. You should not instantiate this service directly, and instead use the NewExperienceService method instead.

func NewExperienceService added in v0.29.0

func NewExperienceService(opts ...option.RequestOption) (r ExperienceService)

NewExperienceService generates a new service that applies the given options to each request. These options are applied after the parent client's options (if there is one), and before any request-specific options.

func (*ExperienceService) Get added in v0.29.0

func (r *ExperienceService) Get(ctx context.Context, experience string, opts ...option.RequestOption) (res *ExperienceGetResponse, err error)

Get one experience

func (*ExperienceService) List added in v0.29.0

The experiences enabled for your account, with the actions you may invoke on each and the fields each action accepts. Treat it as the list to build against: anything not described here is unsupported and may change or stop working without notice.

type GetChatLocationResponse added in v0.23.0

type GetChatLocationResponse struct {
	Data    GetChatLocationResponseData `json:"data" api:"required"`
	Success bool                        `json:"success" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Data        respjson.Field
		Success     respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (GetChatLocationResponse) RawJSON added in v0.23.0

func (r GetChatLocationResponse) RawJSON() string

Returns the unmodified JSON received from the API

func (*GetChatLocationResponse) UnmarshalJSON added in v0.23.0

func (r *GetChatLocationResponse) UnmarshalJSON(data []byte) error

type GetChatLocationResponseData added in v0.23.0

type GetChatLocationResponseData struct {
	Features []GetChatLocationResponseDataFeature `json:"features" api:"required"`
	// Any of "FeatureCollection".
	Type string `json:"type" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Features    respjson.Field
		Type        respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (GetChatLocationResponseData) RawJSON added in v0.23.0

func (r GetChatLocationResponseData) RawJSON() string

Returns the unmodified JSON received from the API

func (*GetChatLocationResponseData) UnmarshalJSON added in v0.23.0

func (r *GetChatLocationResponseData) UnmarshalJSON(data []byte) error

type GetChatLocationResponseDataFeature added in v0.23.0

type GetChatLocationResponseDataFeature struct {
	Geometry   GetChatLocationResponseDataFeatureGeometry   `json:"geometry" api:"required"`
	Properties GetChatLocationResponseDataFeatureProperties `json:"properties" api:"required"`
	// Any of "Feature".
	Type string `json:"type" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Geometry    respjson.Field
		Properties  respjson.Field
		Type        respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (GetChatLocationResponseDataFeature) RawJSON added in v0.23.0

Returns the unmodified JSON received from the API

func (*GetChatLocationResponseDataFeature) UnmarshalJSON added in v0.23.0

func (r *GetChatLocationResponseDataFeature) UnmarshalJSON(data []byte) error

type GetChatLocationResponseDataFeatureGeometry added in v0.23.0

type GetChatLocationResponseDataFeatureGeometry struct {
	// [longitude, latitude]
	Coordinates []float64 `json:"coordinates" api:"required"`
	// Any of "Point".
	Type string `json:"type" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Coordinates respjson.Field
		Type        respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (GetChatLocationResponseDataFeatureGeometry) RawJSON added in v0.23.0

Returns the unmodified JSON received from the API

func (*GetChatLocationResponseDataFeatureGeometry) UnmarshalJSON added in v0.23.0

func (r *GetChatLocationResponseDataFeatureGeometry) UnmarshalJSON(data []byte) error

type GetChatLocationResponseDataFeatureProperties added in v0.23.0

type GetChatLocationResponseDataFeatureProperties struct {
	// Phone number or email of the person sharing their location
	Handle string `json:"handle" api:"required"`
	// Full street address
	Address string `json:"address"`
	// City or locality name
	Locality string `json:"locality"`
	// When the location was last updated
	UpdatedAt time.Time `json:"updated_at" format:"date-time"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Handle      respjson.Field
		Address     respjson.Field
		Locality    respjson.Field
		UpdatedAt   respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (GetChatLocationResponseDataFeatureProperties) RawJSON added in v0.23.0

Returns the unmodified JSON received from the API

func (*GetChatLocationResponseDataFeatureProperties) UnmarshalJSON added in v0.23.0

func (r *GetChatLocationResponseDataFeatureProperties) UnmarshalJSON(data []byte) error

type HandleCheckParam added in v0.8.0

type HandleCheckParam struct {
	// The recipient address to check. `check_imessage` accepts an E.164 phone number
	// or an email address; `check_rcs` accepts an E.164 phone number only and rejects
	// an email with a `400`, since RCS has no email addressing.
	Address string `json:"address" api:"required"`
	// Optional sender phone number. If omitted, an available phone from your pool is
	// used automatically.
	From param.Opt[string] `json:"from,omitzero"`
	// contains filtered or unexported fields
}

The property Address is required.

func (HandleCheckParam) MarshalJSON added in v0.8.0

func (r HandleCheckParam) MarshalJSON() (data []byte, err error)

func (*HandleCheckParam) UnmarshalJSON added in v0.8.0

func (r *HandleCheckParam) UnmarshalJSON(data []byte) error

type HandleCheckResponse added in v0.8.0

type HandleCheckResponse struct {
	// The recipient address that was checked
	Address string `json:"address" api:"required"`
	// Whether the recipient supports the checked messaging service
	Available bool `json:"available" api:"required"`
	// Why `available` is `false`. Only present on a negative result.
	//
	// `not_supported` is the only value returned with a `200`, and it means the check
	// completed and the recipient is genuinely not reachable over this service. On
	// `check_rcs`, sender-side faults do not return `200` — they return `503` with a
	// specific error code. `check_imessage` does not use this mapping.
	//
	// Any of "not_supported".
	Reason HandleCheckResponseReason `json:"reason"`
	// The service that would actually carry a message to this address right now, which
	// is not always the service you checked — a recipient without RCS resolves to
	// `SMS`. Absent when the check could not determine one.
	SelectedService string `json:"selected_service"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Address         respjson.Field
		Available       respjson.Field
		Reason          respjson.Field
		SelectedService respjson.Field
		ExtraFields     map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (HandleCheckResponse) RawJSON added in v0.8.0

func (r HandleCheckResponse) RawJSON() string

Returns the unmodified JSON received from the API

func (*HandleCheckResponse) UnmarshalJSON added in v0.8.0

func (r *HandleCheckResponse) UnmarshalJSON(data []byte) error

type HandleCheckResponseReason added in v0.32.0

type HandleCheckResponseReason string

Why `available` is `false`. Only present on a negative result.

`not_supported` is the only value returned with a `200`, and it means the check completed and the recipient is genuinely not reachable over this service. On `check_rcs`, sender-side faults do not return `200` — they return `503` with a specific error code. `check_imessage` does not use this mapping.

const (
	HandleCheckResponseReasonNotSupported HandleCheckResponseReason = "not_supported"
)

type LinkConnectionService added in v0.42.0

type LinkConnectionService struct {
	Options []option.RequestOption
}

LinkConnectionService contains methods and other services that help with interacting with the linq-api-v3 API.

Note, unlike clients, this service does not read variables from the environment automatically. You should not instantiate this service directly, and instead use the NewLinkConnectionService method instead.

func NewLinkConnectionService added in v0.42.0

func NewLinkConnectionService(opts ...option.RequestOption) (r LinkConnectionService)

NewLinkConnectionService generates a new service that applies the given options to each request. These options are applied after the parent client's options (if there is one), and before any request-specific options.

type LinkPartParam added in v0.8.0

type LinkPartParam struct {
	// Indicates this is a rich link preview part
	//
	// Any of "link".
	Type LinkPartType `json:"type,omitzero" api:"required"`
	// URL to send with a rich link preview. The recipient will see an inline card with
	// the page's title, description, and preview image (when available).
	//
	// A `link` part must be the **only** part in the message. To send a URL as plain
	// text (no preview card), use a `text` part instead.
	Value string `json:"value" api:"required" format:"uri"`
	// contains filtered or unexported fields
}

The properties Type, Value are required.

func (LinkPartParam) MarshalJSON added in v0.8.0

func (r LinkPartParam) MarshalJSON() (data []byte, err error)

func (*LinkPartParam) UnmarshalJSON added in v0.8.0

func (r *LinkPartParam) UnmarshalJSON(data []byte) error

type LinkPartResponse added in v0.13.0

type LinkPartResponse = shared.LinkPartResponse

A rich link preview part

This is an alias to an internal type.

type LinkPartResponseType added in v0.13.0

type LinkPartResponseType = shared.LinkPartResponseType

Indicates this is a rich link preview part

This is an alias to an internal type.

type LinkPartType added in v0.8.0

type LinkPartType string

Indicates this is a rich link preview part

const (
	LinkPartTypeLink LinkPartType = "link"
)

type LinkPaymentService added in v0.42.0

type LinkPaymentService struct {
	Options []option.RequestOption
}

LinkPaymentService contains methods and other services that help with interacting with the linq-api-v3 API.

Note, unlike clients, this service does not read variables from the environment automatically. You should not instantiate this service directly, and instead use the NewLinkPaymentService method instead.

func NewLinkPaymentService added in v0.42.0

func NewLinkPaymentService(opts ...option.RequestOption) (r LinkPaymentService)

NewLinkPaymentService generates a new service that applies the given options to each request. These options are applied after the parent client's options (if there is one), and before any request-specific options.

type LocationRequestResponse added in v0.23.0

type LocationRequestResponse struct {
	Message string `json:"message" api:"required"`
	Success bool   `json:"success" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Message     respjson.Field
		Success     respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (LocationRequestResponse) RawJSON added in v0.23.0

func (r LocationRequestResponse) RawJSON() string

Returns the unmodified JSON received from the API

func (*LocationRequestResponse) UnmarshalJSON added in v0.23.0

func (r *LocationRequestResponse) UnmarshalJSON(data []byte) error

type LocationSharingStartedWebhookEvent added in v0.49.0

type LocationSharingStartedWebhookEvent struct {
	// API version for the webhook payload format
	APIVersion string `json:"api_version" api:"required"`
	// When the event was created
	CreatedAt time.Time                              `json:"created_at" api:"required" format:"date-time"`
	Data      LocationSharingStartedWebhookEventData `json:"data" api:"required"`
	// Unique identifier for this event (for deduplication)
	EventID string `json:"event_id" api:"required" format:"uuid"`
	// Any of "location.sharing.started", "message.sent", "message.received",
	// "message.read", "message.delivered", "message.failed", "message.edited",
	// "reaction.added", "reaction.removed", "poll.received", "poll.failed",
	// "poll.sent", "poll.delivered", "poll.read", "poll.updated", "poll.vote.added",
	// "poll.vote.removed", "poll.reaction.added", "participant.added",
	// "participant.removed", "chat.created", "chat.group_name_updated",
	// "chat.group_icon_updated", "chat.group_name_update_failed",
	// "chat.group_icon_update_failed", "chat.background_updated",
	// "chat.background_update_failed", "chat.typing_indicator.started",
	// "chat.typing_indicator.stopped", "phone_number.status_updated",
	// "contact_card.received", "call.initiated", "call.ringing", "call.answered",
	// "call.ended", "call.failed", "call.declined", "call.no_answer",
	// "location.sharing.stopped", "payment.succeeded", "payment.canceled",
	// "payment.expired", "payment.declined", "payment.authorized",
	// "connection.created", "connection.revoked".
	EventType LocationSharingStartedWebhookEventEventType `json:"event_type" api:"required"`
	// Partner identifier. Present on all webhooks for cross-referencing.
	PartnerID string `json:"partner_id" api:"required"`
	// Trace ID for debugging and correlation across systems.
	TraceID string `json:"trace_id" api:"required"`
	// Date-based webhook payload version. Determined by the `?version=` query
	// parameter in your webhook subscription URL. If no version parameter is
	// specified, defaults based on subscription creation date.
	WebhookVersion string `json:"webhook_version" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		APIVersion     respjson.Field
		CreatedAt      respjson.Field
		Data           respjson.Field
		EventID        respjson.Field
		EventType      respjson.Field
		PartnerID      respjson.Field
		TraceID        respjson.Field
		WebhookVersion respjson.Field
		ExtraFields    map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (LocationSharingStartedWebhookEvent) RawJSON added in v0.49.0

Returns the unmodified JSON received from the API

func (*LocationSharingStartedWebhookEvent) UnmarshalJSON added in v0.49.0

func (r *LocationSharingStartedWebhookEvent) UnmarshalJSON(data []byte) error

type LocationSharingStartedWebhookEventData added in v0.49.0

type LocationSharingStartedWebhookEventData struct {
	// When location sharing started. Always present: falls back to when the share was
	// first observed if the device reported no start time.
	BeganAt time.Time `json:"began_at" api:"required" format:"date-time"`
	// The chat this share was first sent to. Location sharing is per-contact rather
	// than per-chat, so the location may also be visible in other chats with the same
	// handle; this identifies where the share originated and does not change if the
	// contact later shares into another chat. Null when the originating chat could not
	// be determined.
	ChatID string `json:"chat_id" api:"required" format:"uuid"`
	// When location sharing will expire. Null when sharing indefinitely.
	EndsAt time.Time `json:"ends_at" api:"required" format:"date-time"`
	// Phone number of the person sharing their location
	SharedBy string `json:"shared_by" api:"required"`
	// Your phone number receiving the location
	SharedWith string `json:"shared_with" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		BeganAt     respjson.Field
		ChatID      respjson.Field
		EndsAt      respjson.Field
		SharedBy    respjson.Field
		SharedWith  respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (LocationSharingStartedWebhookEventData) RawJSON added in v0.49.0

Returns the unmodified JSON received from the API

func (*LocationSharingStartedWebhookEventData) UnmarshalJSON added in v0.49.0

func (r *LocationSharingStartedWebhookEventData) UnmarshalJSON(data []byte) error

type LocationSharingStartedWebhookEventEventType added in v0.49.0

type LocationSharingStartedWebhookEventEventType string
const (
	LocationSharingStartedWebhookEventEventTypeLocationSharingStarted     LocationSharingStartedWebhookEventEventType = "location.sharing.started"
	LocationSharingStartedWebhookEventEventTypeMessageSent                LocationSharingStartedWebhookEventEventType = "message.sent"
	LocationSharingStartedWebhookEventEventTypeMessageReceived            LocationSharingStartedWebhookEventEventType = "message.received"
	LocationSharingStartedWebhookEventEventTypeMessageRead                LocationSharingStartedWebhookEventEventType = "message.read"
	LocationSharingStartedWebhookEventEventTypeMessageDelivered           LocationSharingStartedWebhookEventEventType = "message.delivered"
	LocationSharingStartedWebhookEventEventTypeMessageFailed              LocationSharingStartedWebhookEventEventType = "message.failed"
	LocationSharingStartedWebhookEventEventTypeMessageEdited              LocationSharingStartedWebhookEventEventType = "message.edited"
	LocationSharingStartedWebhookEventEventTypeReactionAdded              LocationSharingStartedWebhookEventEventType = "reaction.added"
	LocationSharingStartedWebhookEventEventTypeReactionRemoved            LocationSharingStartedWebhookEventEventType = "reaction.removed"
	LocationSharingStartedWebhookEventEventTypePollReceived               LocationSharingStartedWebhookEventEventType = "poll.received"
	LocationSharingStartedWebhookEventEventTypePollFailed                 LocationSharingStartedWebhookEventEventType = "poll.failed"
	LocationSharingStartedWebhookEventEventTypePollSent                   LocationSharingStartedWebhookEventEventType = "poll.sent"
	LocationSharingStartedWebhookEventEventTypePollDelivered              LocationSharingStartedWebhookEventEventType = "poll.delivered"
	LocationSharingStartedWebhookEventEventTypePollRead                   LocationSharingStartedWebhookEventEventType = "poll.read"
	LocationSharingStartedWebhookEventEventTypePollUpdated                LocationSharingStartedWebhookEventEventType = "poll.updated"
	LocationSharingStartedWebhookEventEventTypePollVoteAdded              LocationSharingStartedWebhookEventEventType = "poll.vote.added"
	LocationSharingStartedWebhookEventEventTypePollVoteRemoved            LocationSharingStartedWebhookEventEventType = "poll.vote.removed"
	LocationSharingStartedWebhookEventEventTypePollReactionAdded          LocationSharingStartedWebhookEventEventType = "poll.reaction.added"
	LocationSharingStartedWebhookEventEventTypeParticipantAdded           LocationSharingStartedWebhookEventEventType = "participant.added"
	LocationSharingStartedWebhookEventEventTypeParticipantRemoved         LocationSharingStartedWebhookEventEventType = "participant.removed"
	LocationSharingStartedWebhookEventEventTypeChatCreated                LocationSharingStartedWebhookEventEventType = "chat.created"
	LocationSharingStartedWebhookEventEventTypeChatGroupNameUpdated       LocationSharingStartedWebhookEventEventType = "chat.group_name_updated"
	LocationSharingStartedWebhookEventEventTypeChatGroupIconUpdated       LocationSharingStartedWebhookEventEventType = "chat.group_icon_updated"
	LocationSharingStartedWebhookEventEventTypeChatGroupNameUpdateFailed  LocationSharingStartedWebhookEventEventType = "chat.group_name_update_failed"
	LocationSharingStartedWebhookEventEventTypeChatGroupIconUpdateFailed  LocationSharingStartedWebhookEventEventType = "chat.group_icon_update_failed"
	LocationSharingStartedWebhookEventEventTypeChatBackgroundUpdated      LocationSharingStartedWebhookEventEventType = "chat.background_updated"
	LocationSharingStartedWebhookEventEventTypeChatBackgroundUpdateFailed LocationSharingStartedWebhookEventEventType = "chat.background_update_failed"
	LocationSharingStartedWebhookEventEventTypeChatTypingIndicatorStarted LocationSharingStartedWebhookEventEventType = "chat.typing_indicator.started"
	LocationSharingStartedWebhookEventEventTypeChatTypingIndicatorStopped LocationSharingStartedWebhookEventEventType = "chat.typing_indicator.stopped"
	LocationSharingStartedWebhookEventEventTypePhoneNumberStatusUpdated   LocationSharingStartedWebhookEventEventType = "phone_number.status_updated"
	LocationSharingStartedWebhookEventEventTypeContactCardReceived        LocationSharingStartedWebhookEventEventType = "contact_card.received"
	LocationSharingStartedWebhookEventEventTypeCallInitiated              LocationSharingStartedWebhookEventEventType = "call.initiated"
	LocationSharingStartedWebhookEventEventTypeCallRinging                LocationSharingStartedWebhookEventEventType = "call.ringing"
	LocationSharingStartedWebhookEventEventTypeCallAnswered               LocationSharingStartedWebhookEventEventType = "call.answered"
	LocationSharingStartedWebhookEventEventTypeCallEnded                  LocationSharingStartedWebhookEventEventType = "call.ended"
	LocationSharingStartedWebhookEventEventTypeCallFailed                 LocationSharingStartedWebhookEventEventType = "call.failed"
	LocationSharingStartedWebhookEventEventTypeCallDeclined               LocationSharingStartedWebhookEventEventType = "call.declined"
	LocationSharingStartedWebhookEventEventTypeCallNoAnswer               LocationSharingStartedWebhookEventEventType = "call.no_answer"
	LocationSharingStartedWebhookEventEventTypeLocationSharingStopped     LocationSharingStartedWebhookEventEventType = "location.sharing.stopped"
	LocationSharingStartedWebhookEventEventTypePaymentSucceeded           LocationSharingStartedWebhookEventEventType = "payment.succeeded"
	LocationSharingStartedWebhookEventEventTypePaymentCanceled            LocationSharingStartedWebhookEventEventType = "payment.canceled"
	LocationSharingStartedWebhookEventEventTypePaymentExpired             LocationSharingStartedWebhookEventEventType = "payment.expired"
	LocationSharingStartedWebhookEventEventTypePaymentDeclined            LocationSharingStartedWebhookEventEventType = "payment.declined"
	LocationSharingStartedWebhookEventEventTypePaymentAuthorized          LocationSharingStartedWebhookEventEventType = "payment.authorized"
	LocationSharingStartedWebhookEventEventTypeConnectionCreated          LocationSharingStartedWebhookEventEventType = "connection.created"
	LocationSharingStartedWebhookEventEventTypeConnectionRevoked          LocationSharingStartedWebhookEventEventType = "connection.revoked"
)

type LocationSharingStoppedWebhookEvent added in v0.49.0

type LocationSharingStoppedWebhookEvent struct {
	// API version for the webhook payload format
	APIVersion string `json:"api_version" api:"required"`
	// When the event was created
	CreatedAt time.Time                              `json:"created_at" api:"required" format:"date-time"`
	Data      LocationSharingStoppedWebhookEventData `json:"data" api:"required"`
	// Unique identifier for this event (for deduplication)
	EventID string `json:"event_id" api:"required" format:"uuid"`
	// Any of "location.sharing.stopped", "message.sent", "message.received",
	// "message.read", "message.delivered", "message.failed", "message.edited",
	// "reaction.added", "reaction.removed", "poll.received", "poll.failed",
	// "poll.sent", "poll.delivered", "poll.read", "poll.updated", "poll.vote.added",
	// "poll.vote.removed", "poll.reaction.added", "participant.added",
	// "participant.removed", "chat.created", "chat.group_name_updated",
	// "chat.group_icon_updated", "chat.group_name_update_failed",
	// "chat.group_icon_update_failed", "chat.background_updated",
	// "chat.background_update_failed", "chat.typing_indicator.started",
	// "chat.typing_indicator.stopped", "phone_number.status_updated",
	// "contact_card.received", "call.initiated", "call.ringing", "call.answered",
	// "call.ended", "call.failed", "call.declined", "call.no_answer",
	// "location.sharing.started", "payment.succeeded", "payment.canceled",
	// "payment.expired", "payment.declined", "payment.authorized",
	// "connection.created", "connection.revoked".
	EventType LocationSharingStoppedWebhookEventEventType `json:"event_type" api:"required"`
	// Partner identifier. Present on all webhooks for cross-referencing.
	PartnerID string `json:"partner_id" api:"required"`
	// Trace ID for debugging and correlation across systems.
	TraceID string `json:"trace_id" api:"required"`
	// Date-based webhook payload version. Determined by the `?version=` query
	// parameter in your webhook subscription URL. If no version parameter is
	// specified, defaults based on subscription creation date.
	WebhookVersion string `json:"webhook_version" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		APIVersion     respjson.Field
		CreatedAt      respjson.Field
		Data           respjson.Field
		EventID        respjson.Field
		EventType      respjson.Field
		PartnerID      respjson.Field
		TraceID        respjson.Field
		WebhookVersion respjson.Field
		ExtraFields    map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (LocationSharingStoppedWebhookEvent) RawJSON added in v0.49.0

Returns the unmodified JSON received from the API

func (*LocationSharingStoppedWebhookEvent) UnmarshalJSON added in v0.49.0

func (r *LocationSharingStoppedWebhookEvent) UnmarshalJSON(data []byte) error

type LocationSharingStoppedWebhookEventData added in v0.49.0

type LocationSharingStoppedWebhookEventData struct {
	// When the sharing session started, matching began_at on its started event. Always
	// present.
	BeganAt time.Time `json:"began_at" api:"required" format:"date-time"`
	// The chat the ended share was first sent to, matching the chat_id on its started
	// event. Sharing always stops for the contact as a whole, never for a single chat,
	// so this is the session's origin rather than the chat it stopped in. Null when
	// the originating chat could not be determined.
	ChatID string `json:"chat_id" api:"required" format:"uuid"`
	// When the sharing session was observed to stop.
	EndedAt time.Time `json:"ended_at" api:"required" format:"date-time"`
	// Phone number of the person who stopped sharing
	SharedBy string `json:"shared_by" api:"required"`
	// Your phone number that was receiving the location
	SharedWith string `json:"shared_with" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		BeganAt     respjson.Field
		ChatID      respjson.Field
		EndedAt     respjson.Field
		SharedBy    respjson.Field
		SharedWith  respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (LocationSharingStoppedWebhookEventData) RawJSON added in v0.49.0

Returns the unmodified JSON received from the API

func (*LocationSharingStoppedWebhookEventData) UnmarshalJSON added in v0.49.0

func (r *LocationSharingStoppedWebhookEventData) UnmarshalJSON(data []byte) error

type LocationSharingStoppedWebhookEventEventType added in v0.49.0

type LocationSharingStoppedWebhookEventEventType string
const (
	LocationSharingStoppedWebhookEventEventTypeLocationSharingStopped     LocationSharingStoppedWebhookEventEventType = "location.sharing.stopped"
	LocationSharingStoppedWebhookEventEventTypeMessageSent                LocationSharingStoppedWebhookEventEventType = "message.sent"
	LocationSharingStoppedWebhookEventEventTypeMessageReceived            LocationSharingStoppedWebhookEventEventType = "message.received"
	LocationSharingStoppedWebhookEventEventTypeMessageRead                LocationSharingStoppedWebhookEventEventType = "message.read"
	LocationSharingStoppedWebhookEventEventTypeMessageDelivered           LocationSharingStoppedWebhookEventEventType = "message.delivered"
	LocationSharingStoppedWebhookEventEventTypeMessageFailed              LocationSharingStoppedWebhookEventEventType = "message.failed"
	LocationSharingStoppedWebhookEventEventTypeMessageEdited              LocationSharingStoppedWebhookEventEventType = "message.edited"
	LocationSharingStoppedWebhookEventEventTypeReactionAdded              LocationSharingStoppedWebhookEventEventType = "reaction.added"
	LocationSharingStoppedWebhookEventEventTypeReactionRemoved            LocationSharingStoppedWebhookEventEventType = "reaction.removed"
	LocationSharingStoppedWebhookEventEventTypePollReceived               LocationSharingStoppedWebhookEventEventType = "poll.received"
	LocationSharingStoppedWebhookEventEventTypePollFailed                 LocationSharingStoppedWebhookEventEventType = "poll.failed"
	LocationSharingStoppedWebhookEventEventTypePollSent                   LocationSharingStoppedWebhookEventEventType = "poll.sent"
	LocationSharingStoppedWebhookEventEventTypePollDelivered              LocationSharingStoppedWebhookEventEventType = "poll.delivered"
	LocationSharingStoppedWebhookEventEventTypePollRead                   LocationSharingStoppedWebhookEventEventType = "poll.read"
	LocationSharingStoppedWebhookEventEventTypePollUpdated                LocationSharingStoppedWebhookEventEventType = "poll.updated"
	LocationSharingStoppedWebhookEventEventTypePollVoteAdded              LocationSharingStoppedWebhookEventEventType = "poll.vote.added"
	LocationSharingStoppedWebhookEventEventTypePollVoteRemoved            LocationSharingStoppedWebhookEventEventType = "poll.vote.removed"
	LocationSharingStoppedWebhookEventEventTypePollReactionAdded          LocationSharingStoppedWebhookEventEventType = "poll.reaction.added"
	LocationSharingStoppedWebhookEventEventTypeParticipantAdded           LocationSharingStoppedWebhookEventEventType = "participant.added"
	LocationSharingStoppedWebhookEventEventTypeParticipantRemoved         LocationSharingStoppedWebhookEventEventType = "participant.removed"
	LocationSharingStoppedWebhookEventEventTypeChatCreated                LocationSharingStoppedWebhookEventEventType = "chat.created"
	LocationSharingStoppedWebhookEventEventTypeChatGroupNameUpdated       LocationSharingStoppedWebhookEventEventType = "chat.group_name_updated"
	LocationSharingStoppedWebhookEventEventTypeChatGroupIconUpdated       LocationSharingStoppedWebhookEventEventType = "chat.group_icon_updated"
	LocationSharingStoppedWebhookEventEventTypeChatGroupNameUpdateFailed  LocationSharingStoppedWebhookEventEventType = "chat.group_name_update_failed"
	LocationSharingStoppedWebhookEventEventTypeChatGroupIconUpdateFailed  LocationSharingStoppedWebhookEventEventType = "chat.group_icon_update_failed"
	LocationSharingStoppedWebhookEventEventTypeChatBackgroundUpdated      LocationSharingStoppedWebhookEventEventType = "chat.background_updated"
	LocationSharingStoppedWebhookEventEventTypeChatBackgroundUpdateFailed LocationSharingStoppedWebhookEventEventType = "chat.background_update_failed"
	LocationSharingStoppedWebhookEventEventTypeChatTypingIndicatorStarted LocationSharingStoppedWebhookEventEventType = "chat.typing_indicator.started"
	LocationSharingStoppedWebhookEventEventTypeChatTypingIndicatorStopped LocationSharingStoppedWebhookEventEventType = "chat.typing_indicator.stopped"
	LocationSharingStoppedWebhookEventEventTypePhoneNumberStatusUpdated   LocationSharingStoppedWebhookEventEventType = "phone_number.status_updated"
	LocationSharingStoppedWebhookEventEventTypeContactCardReceived        LocationSharingStoppedWebhookEventEventType = "contact_card.received"
	LocationSharingStoppedWebhookEventEventTypeCallInitiated              LocationSharingStoppedWebhookEventEventType = "call.initiated"
	LocationSharingStoppedWebhookEventEventTypeCallRinging                LocationSharingStoppedWebhookEventEventType = "call.ringing"
	LocationSharingStoppedWebhookEventEventTypeCallAnswered               LocationSharingStoppedWebhookEventEventType = "call.answered"
	LocationSharingStoppedWebhookEventEventTypeCallEnded                  LocationSharingStoppedWebhookEventEventType = "call.ended"
	LocationSharingStoppedWebhookEventEventTypeCallFailed                 LocationSharingStoppedWebhookEventEventType = "call.failed"
	LocationSharingStoppedWebhookEventEventTypeCallDeclined               LocationSharingStoppedWebhookEventEventType = "call.declined"
	LocationSharingStoppedWebhookEventEventTypeCallNoAnswer               LocationSharingStoppedWebhookEventEventType = "call.no_answer"
	LocationSharingStoppedWebhookEventEventTypeLocationSharingStarted     LocationSharingStoppedWebhookEventEventType = "location.sharing.started"
	LocationSharingStoppedWebhookEventEventTypePaymentSucceeded           LocationSharingStoppedWebhookEventEventType = "payment.succeeded"
	LocationSharingStoppedWebhookEventEventTypePaymentCanceled            LocationSharingStoppedWebhookEventEventType = "payment.canceled"
	LocationSharingStoppedWebhookEventEventTypePaymentExpired             LocationSharingStoppedWebhookEventEventType = "payment.expired"
	LocationSharingStoppedWebhookEventEventTypePaymentDeclined            LocationSharingStoppedWebhookEventEventType = "payment.declined"
	LocationSharingStoppedWebhookEventEventTypePaymentAuthorized          LocationSharingStoppedWebhookEventEventType = "payment.authorized"
	LocationSharingStoppedWebhookEventEventTypeConnectionCreated          LocationSharingStoppedWebhookEventEventType = "connection.created"
	LocationSharingStoppedWebhookEventEventTypeConnectionRevoked          LocationSharingStoppedWebhookEventEventType = "connection.revoked"
)

type MediaPartParam added in v0.2.0

type MediaPartParam struct {
	// Indicates this is a media attachment part
	//
	// Any of "media".
	Type MediaPartType `json:"type,omitzero" api:"required"`
	// Reference to a file pre-uploaded via `POST /v3/attachments` (optional). The file
	// is already stored, so sends using this ID skip the download step — useful when
	// sending the same file to many recipients.
	//
	// Either `url` or `attachment_id` must be provided, but not both.
	AttachmentID param.Opt[string] `json:"attachment_id,omitzero" format:"uuid"`
	// Send this image as a **sticker** rather than a photo. The recipient can peel it
	// off and place it on any message in the conversation, and it renders without a
	// bubble.
	//
	// An opaque photo is cut out automatically — the subject is lifted from its
	// background, the same way "Add Sticker" does on iOS. An image that already has
	// transparency is sent as-is. If no subject can be found, the image sends as an
	// ordinary photo.
	//
	// **iMessage only.** On SMS/RCS the flag is ignored and the image sends as a
	// photo.
	//
	// Stickers can be combined with a `text` part in the same message; the text
	// arrives as its own bubble. To place a sticker _onto_ an existing message
	// instead, use `POST /v3/messages/{messageId}/reactions` with `type: "sticker"`.
	Sticker param.Opt[bool] `json:"sticker,omitzero"`
	// Any publicly accessible HTTPS URL to the media file. The server downloads and
	// sends the file automatically — no pre-upload step required.
	//
	// **Size limit:** 10MB maximum for URL-based downloads. For larger files (up to
	// 100MB), use the pre-upload flow: `POST /v3/attachments` to get a presigned URL,
	// upload directly, then reference by `attachment_id`.
	//
	// **Requirements:**
	//
	//   - URL must use HTTPS
	//   - File content must be a supported format (the server validates the actual file
	//     content)
	//
	// **Supported formats:**
	//
	//   - Images: .jpg, .jpeg, .png, .gif, .heic, .heif, .tif, .tiff, .bmp
	//   - Videos: .mp4, .mov, .m4v, .mpeg, .mpg, .3gp
	//   - Audio: .m4a, .mp3, .aac, .caf, .wav, .aiff, .amr
	//   - Documents: .pdf, .txt, .rtf, .csv, .doc, .docx, .xls, .xlsx, .ppt, .pptx,
	//     .pages, .numbers, .key, .epub, .zip, .html, .htm
	//   - Contact & Calendar: .vcf, .ics
	//
	// **Tip:** Audio sent here appears as a regular file attachment. To send audio as
	// an iMessage voice memo bubble (with inline playback), use
	// `/v3/chats/{chatId}/voicememo`. For repeated sends of the same file, use
	// `attachment_id` to avoid redundant downloads.
	//
	// Either `url` or `attachment_id` must be provided, but not both.
	URL param.Opt[string] `json:"url,omitzero" format:"uri"`
	// contains filtered or unexported fields
}

The property Type is required.

func (MediaPartParam) MarshalJSON added in v0.2.0

func (r MediaPartParam) MarshalJSON() (data []byte, err error)

func (*MediaPartParam) UnmarshalJSON added in v0.2.0

func (r *MediaPartParam) UnmarshalJSON(data []byte) error

type MediaPartResponse added in v0.2.0

type MediaPartResponse = shared.MediaPartResponse

A media attachment part

This is an alias to an internal type.

type MediaPartResponseType added in v0.2.0

type MediaPartResponseType = shared.MediaPartResponseType

Indicates this is a media attachment part

This is an alias to an internal type.

type MediaPartType

type MediaPartType string

Indicates this is a media attachment part

const (
	MediaPartTypeMedia MediaPartType = "media"
)

type Message

type Message struct {
	// Unique identifier for the message
	ID string `json:"id" api:"required" format:"uuid"`
	// ID of the chat this message belongs to
	ChatID string `json:"chat_id" api:"required" format:"uuid"`
	// When the message was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// Current delivery status of a message
	//
	// Any of "pending", "queued", "sent", "delivered", "received", "read", "failed".
	DeliveryStatus MessageDeliveryStatus `json:"delivery_status" api:"required"`
	// DEPRECATED: Use `delivery_status` instead (true when `delivery_status` is
	// `delivered` or `read`). Whether the message has been delivered.
	//
	// Deprecated: deprecated
	IsDelivered bool `json:"is_delivered" api:"required"`
	// Whether this message was sent by the authenticated user
	IsFromMe bool `json:"is_from_me" api:"required"`
	// DEPRECATED: Use `delivery_status == "read"` instead. Whether the message has
	// been read.
	//
	// Deprecated: deprecated
	IsRead bool `json:"is_read" api:"required"`
	// When the message was last updated
	UpdatedAt time.Time `json:"updated_at" api:"required" format:"date-time"`
	// When the message was delivered
	DeliveredAt time.Time `json:"delivered_at" api:"nullable" format:"date-time"`
	// iMessage effect applied to a message (screen or bubble effect)
	Effect MessageEffect `json:"effect" api:"nullable"`
	// DEPRECATED: Use from_handle instead. Phone number of the message sender.
	//
	// Deprecated: deprecated
	From string `json:"from" api:"nullable"`
	// The sender of this message as a full handle object
	FromHandle shared.ChatHandle `json:"from_handle" api:"nullable"`
	// Message parts in order (text, media, and link)
	Parts []MessagePartUnion `json:"parts" api:"nullable"`
	// Messaging service type
	//
	// Any of "iMessage", "SMS", "RCS".
	PreferredService shared.ServiceType `json:"preferred_service" api:"nullable"`
	// When the message was read
	ReadAt time.Time `json:"read_at" api:"nullable" format:"date-time"`
	// Present only when this message was recovered by reconciliation rather than
	// delivered live, and set to the time of that recovery. The field is omitted
	// entirely for normally-delivered messages, which is the overwhelming majority.
	// When present, expect `sent_at` to be substantially earlier — the message is
	// genuine but was ingested late, so it may not have appeared in earlier reads of
	// this conversation.
	ReconciledAt time.Time `json:"reconciled_at" format:"date-time"`
	// Indicates this message is a threaded reply to another message
	ReplyTo ReplyTo `json:"reply_to" api:"nullable"`
	// When the message was sent
	SentAt time.Time `json:"sent_at" api:"nullable" format:"date-time"`
	// Messaging service type
	//
	// Any of "iMessage", "SMS", "RCS".
	Service shared.ServiceType `json:"service" api:"nullable"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ID               respjson.Field
		ChatID           respjson.Field
		CreatedAt        respjson.Field
		DeliveryStatus   respjson.Field
		IsDelivered      respjson.Field
		IsFromMe         respjson.Field
		IsRead           respjson.Field
		UpdatedAt        respjson.Field
		DeliveredAt      respjson.Field
		Effect           respjson.Field
		From             respjson.Field
		FromHandle       respjson.Field
		Parts            respjson.Field
		PreferredService respjson.Field
		ReadAt           respjson.Field
		ReconciledAt     respjson.Field
		ReplyTo          respjson.Field
		SentAt           respjson.Field
		Service          respjson.Field
		ExtraFields      map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (Message) RawJSON

func (r Message) RawJSON() string

Returns the unmodified JSON received from the API

func (*Message) UnmarshalJSON

func (r *Message) UnmarshalJSON(data []byte) error

type MessageAddReactionParams

type MessageAddReactionParams struct {
	// Whether to add or remove the reaction
	//
	// Any of "add", "remove".
	Operation MessageAddReactionParamsOperation `json:"operation,omitzero" api:"required"`
	// Type of reaction. Standard iMessage tapbacks are love, like, dislike, laugh,
	// emphasize, question. Custom emoji reactions have type "custom" with the actual
	// emoji in the custom_emoji field. Sticker reactions have type "sticker" with
	// sticker attachment details in the sticker field.
	//
	// Any of "love", "like", "dislike", "laugh", "emphasize", "question", "custom",
	// "sticker".
	Type shared.ReactionType `json:"type,omitzero" api:"required"`
	// Reference to a sticker image pre-uploaded via `POST /v3/attachments`. Only valid
	// when type is "sticker".
	//
	// Either `url` or `attachment_id` must be provided when type is "sticker", but not
	// both.
	AttachmentID param.Opt[string] `json:"attachment_id,omitzero" format:"uuid"`
	// Custom emoji string. Required when type is "custom".
	CustomEmoji param.Opt[string] `json:"custom_emoji,omitzero"`
	// Optional index of the message part to react to. If not provided, reacts to the
	// entire message (part 0).
	PartIndex param.Opt[int64] `json:"part_index,omitzero"`
	// Linq attachment URL of the sticker image — the `download_url` returned by
	// `POST /v3/attachments`. Only valid when type is "sticker".
	//
	// Unlike a media part, this does **not** accept an arbitrary host: reactions have
	// no download step, so the image must already be stored. To send a sticker from
	// elsewhere, upload it with `POST /v3/attachments` first and pass `attachment_id`.
	//
	// Either `url` or `attachment_id` must be provided when type is "sticker", but not
	// both.
	URL param.Opt[string] `json:"url,omitzero" format:"uri"`
	// Optional position, size and rotation of a sticker on the target bubble. Only
	// valid when type is "sticker".
	//
	// Every field is independent and optional — omit the object entirely, or any field
	// within it, to keep the default (centred, default size, unrotated).
	Placement MessageAddReactionParamsPlacement `json:"placement,omitzero"`
	// contains filtered or unexported fields
}

func (MessageAddReactionParams) MarshalJSON

func (r MessageAddReactionParams) MarshalJSON() (data []byte, err error)

func (*MessageAddReactionParams) UnmarshalJSON

func (r *MessageAddReactionParams) UnmarshalJSON(data []byte) error

type MessageAddReactionParamsOperation

type MessageAddReactionParamsOperation string

Whether to add or remove the reaction

const (
	MessageAddReactionParamsOperationAdd    MessageAddReactionParamsOperation = "add"
	MessageAddReactionParamsOperationRemove MessageAddReactionParamsOperation = "remove"
)

type MessageAddReactionParamsPlacement added in v0.51.0

type MessageAddReactionParamsPlacement struct {
	// Clockwise rotation in degrees.
	Rotation param.Opt[float64] `json:"rotation,omitzero"`
	// Size relative to the default, where 1 matches the size a sticker gets natively.
	//
	// Values outside 0.5–1.5 are clamped rather than rejected. The upper bound keeps a
	// sticker within the size range iMessage itself displays: its own limit is larger,
	// but that allowance assumes the transparent padding Apple's stickers carry, which
	// a full-bleed image does not have.
	//
	// Scale is linear, so 1.5 is a little over twice the area.
	Scale param.Opt[float64] `json:"scale,omitzero"`
	// Horizontal position on the target bubble, from -1 (far left) to 1 (far right). 0
	// is centred.
	X param.Opt[float64] `json:"x,omitzero"`
	// Vertical position on the target bubble, from -1 (top) to 1 (bottom). 0 is
	// centred.
	Y param.Opt[float64] `json:"y,omitzero"`
	// contains filtered or unexported fields
}

Optional position, size and rotation of a sticker on the target bubble. Only valid when type is "sticker".

Every field is independent and optional — omit the object entirely, or any field within it, to keep the default (centred, default size, unrotated).

func (MessageAddReactionParamsPlacement) MarshalJSON added in v0.51.0

func (r MessageAddReactionParamsPlacement) MarshalJSON() (data []byte, err error)

func (*MessageAddReactionParamsPlacement) UnmarshalJSON added in v0.51.0

func (r *MessageAddReactionParamsPlacement) UnmarshalJSON(data []byte) error

type MessageAddReactionResponse added in v0.1.2

type MessageAddReactionResponse struct {
	Message string `json:"message"`
	Status  string `json:"status"`
	TraceID string `json:"trace_id"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Message     respjson.Field
		Status      respjson.Field
		TraceID     respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (MessageAddReactionResponse) RawJSON added in v0.1.2

func (r MessageAddReactionResponse) RawJSON() string

Returns the unmodified JSON received from the API

func (*MessageAddReactionResponse) UnmarshalJSON added in v0.1.2

func (r *MessageAddReactionResponse) UnmarshalJSON(data []byte) error

type MessageContentExperienceParam added in v0.31.0

type MessageContentExperienceParam struct {
	// Which of its actions, e.g. `attach_card`.
	Action string `json:"action" api:"required"`
	// The experience to invoke, e.g. `agentcard` or `agentpay`.
	Name string `json:"name" api:"required"`
	// Values for the fields this action exposes. Keys are exactly the field names
	// listed for the action — no mapping, no nesting.
	//
	// Display copy only, except a `url`-type field — that value sets the destination,
	// and must be an absolute `https` URL.
	//
	// Some fields are read rather than sent: `agentpay`'s `request_payment` takes only
	// a `checkout_url` and resolves the amount and reason from that payment request
	// itself, so the card cannot state a figure the checkout will not charge.
	Params map[string]any `json:"params,omitzero"`
	// contains filtered or unexported fields
}

Invokes an action on an experience — a third party that renders inside Linq's iMessage app. Linq resolves the recipient's connection, mints any session the action needs, composes the card and sends it; none of that is visible to you.

Call `GET /v3/experiences/{experience}` for the actions you may invoke and the fields each accepts.

The properties Action, Name are required.

func (MessageContentExperienceParam) MarshalJSON added in v0.31.0

func (r MessageContentExperienceParam) MarshalJSON() (data []byte, err error)

func (*MessageContentExperienceParam) UnmarshalJSON added in v0.31.0

func (r *MessageContentExperienceParam) UnmarshalJSON(data []byte) error

type MessageContentParam

type MessageContentParam struct {
	// Optional idempotency key for this message. Use this to prevent duplicate sends
	// of the same message. Reusing a key whose message was deleted — or was an
	// ephemeral message that has since expired — returns 404; the message is never
	// resent.
	IdempotencyKey param.Opt[string] `json:"idempotency_key,omitzero"`
	// iMessage effect to apply to this message (screen or bubble effect)
	Effect MessageEffectParam `json:"effect,omitzero"`
	// Invokes an action on an experience — a third party that renders inside Linq's
	// iMessage app. Linq resolves the recipient's connection, mints any session the
	// action needs, composes the card and sends it; none of that is visible to you.
	//
	// Call `GET /v3/experiences/{experience}` for the actions you may invoke and the
	// fields each accepts.
	Experience MessageContentExperienceParam `json:"experience,omitzero"`
	// Array of message parts. Each part can be text, media, or link. Parts are
	// displayed in order. Text and media can be mixed freely, but a `link` part must
	// be the only part in the message.
	//
	// **Rich Link Previews:**
	//
	// - Use a `link` part to send a URL with a rich preview card
	// - A `link` part must be the **only** part in the message
	// - To send a URL as plain text (no preview), use a `text` part instead
	//
	// **App Clip Payment Cards:**
	//
	//   - Use an `app_clip` part to send a Linq checkout link as an Apple Pay App Clip
	//     card (the payment preview with the Open button)
	//   - An `app_clip` part must be the **only** part in the message
	//   - iMessage-only: unlike `link`, it never downgrades to SMS/RCS — the send fails
	//     instead of delivering a bare URL
	//
	// **Supported Media:**
	//
	//   - Images: .jpg, .jpeg, .png, .gif, .heic, .heif, .tif, .tiff, .bmp
	//   - Videos: .mp4, .mov, .m4v, .mpeg, .mpg, .3gp
	//   - Audio: .m4a, .mp3, .aac, .caf, .wav, .aiff, .amr
	//   - Documents: .pdf, .txt, .rtf, .csv, .doc, .docx, .xls, .xlsx, .ppt, .pptx,
	//     .pages, .numbers, .key, .epub, .zip, .html, .htm
	//   - Contact & Calendar: .vcf, .ics
	//
	// **Audio:**
	//
	//   - Audio files (.m4a, .mp3, .aac, .caf, .wav, .aiff, .amr) are fully supported as
	//     media parts
	//   - To send audio as an **iMessage voice memo bubble** (inline playback UI), use
	//     the dedicated `/v3/chats/{chatId}/voicememo` endpoint instead
	//
	// **Validation Rules:**
	//
	//   - A `link` part must be the **only** part in the message. It cannot be combined
	//     with text or media parts.
	//   - An `app_clip` part must be the **only** part in the message. Its `value` must
	//     be a Linq checkout link (e.g. from `POST /v3/payment_requests`); any other URL
	//     is rejected.
	//   - Consecutive text parts are not allowed. Text parts must be separated by media
	//     parts. For example, [text, text] is invalid, but [text, media, text] is valid.
	//   - Maximum of **100 parts** total.
	//   - Media parts using a public `url` (downloaded by the server on send) are capped
	//     at **40**. Parts using `attachment_id` or presigned URLs are exempt from this
	//     sub-limit. For bulk media sends exceeding 40 files, pre-upload via
	//     `POST /v3/attachments` and reference by `attachment_id` or `download_url`.
	Parts []MessageContentPartUnionParam `json:"parts,omitzero"`
	// Messaging service type
	//
	// Any of "iMessage", "SMS", "RCS".
	PreferredService shared.ServiceType `json:"preferred_service,omitzero"`
	// Reply to another message to create a threaded conversation
	ReplyTo ReplyToParam `json:"reply_to,omitzero"`
	// contains filtered or unexported fields
}

Message content container. Groups all message-related fields together, separating the "what" (message content) from the "where" (routing fields like from/to).

A message carries EITHER `parts` — text and attachments, which compose into one bubble — or a single `experience` invocation, which renders an experience inside Linq's iMessage app. Never both: an app card is the whole message (Apple's `MSMessage` cannot coexist with text), so copy and a card are two sends, not one.

func (MessageContentParam) MarshalJSON

func (r MessageContentParam) MarshalJSON() (data []byte, err error)

func (*MessageContentParam) UnmarshalJSON

func (r *MessageContentParam) UnmarshalJSON(data []byte) error

type MessageContentPartAppClipParam added in v0.36.0

type MessageContentPartAppClipParam struct {
	// An https link whose page is a registered App Clip — Linq's checkout link (e.g.
	// the `checkout_url` from `POST /v3/payment_requests`) or a partner's own App Clip
	// URL. A URL that doesn't resolve to a sendable App Clip page is rejected.
	Value string `json:"value" api:"required" format:"uri"`
	// Optional caption for the card's **Open** button row. Omit it and the card uses
	// the App Clip's own default (`Tap open`). Set it to override that with your own
	// short call to action.
	Caption param.Opt[string] `json:"caption,omitzero"`
	// Indicates this is an App Clip card
	//
	// This field can be elided, and will marshal its zero value as "app_clip".
	Type constant.AppClip `json:"type" default:"app_clip"`
	// contains filtered or unexported fields
}

Sends a **registered App Clip** — not only Linq's Apple Pay checkout, but any partner's own App Clip. `caption` is optional.

An `app_clip` part must be the **only** part in the message.

**iMessage only**, and it never downgrades. A `service_preference` of `sms` or `rcs` is rejected (`AppClipServiceUnsupported`, 2028). A recipient who can't receive it fails the send rather than being sent a plain link in its place.

The properties Type, Value are required.

func (MessageContentPartAppClipParam) MarshalJSON added in v0.36.0

func (r MessageContentPartAppClipParam) MarshalJSON() (data []byte, err error)

func (*MessageContentPartAppClipParam) UnmarshalJSON added in v0.36.0

func (r *MessageContentPartAppClipParam) UnmarshalJSON(data []byte) error

type MessageContentPartIMessageAppAppParam added in v0.25.0

type MessageContentPartIMessageAppAppParam struct {
	// Bundle identifier of the Messages app extension. Must not contain `:`.
	BundleID string `json:"bundle_id" api:"required"`
	// Display name of the app, shown by Messages' fallback UI.
	Name string `json:"name" api:"required"`
	// The app's 10-character uppercase alphanumeric team identifier.
	TeamID string `json:"team_id" api:"required"`
	// The owning app's App Store id (optional). When set, recipients without the
	// iMessage app installed see a "Get the app" affordance.
	AppStoreID param.Opt[int64] `json:"app_store_id,omitzero"`
	// contains filtered or unexported fields
}

Identifies the iMessage app (Messages app extension) that backs the card.

The properties BundleID, Name, TeamID are required.

func (MessageContentPartIMessageAppAppParam) MarshalJSON added in v0.25.0

func (r MessageContentPartIMessageAppAppParam) MarshalJSON() (data []byte, err error)

func (*MessageContentPartIMessageAppAppParam) UnmarshalJSON added in v0.25.0

func (r *MessageContentPartIMessageAppAppParam) UnmarshalJSON(data []byte) error

type MessageContentPartIMessageAppLayoutParam added in v0.25.0

type MessageContentPartIMessageAppLayoutParam struct {
	// Primary label, top-left and bold.
	Caption param.Opt[string] `json:"caption,omitzero"`
	// Text shown below `image_title`, overlaid on the card image. Requires
	// `image_url`.
	ImageSubtitle param.Opt[string] `json:"image_subtitle,omitzero"`
	// Bold text overlaid on the card image. Requires `image_url` (rejected without
	// it).
	ImageTitle param.Opt[string] `json:"image_title,omitzero"`
	// URL of an image (JPEG, PNG, HEIF, or WebP) to display as the card's preview
	// image; an unreachable or non-image URL returns a validation error. Renders for
	// all recipients regardless of whether they have the app. Note - requires a
	// trusted chat w/ inbound activity. In responses, this is the re-hosted
	// `cdn.linqapp.com` copy of the image you supplied, not your original URL.
	ImageURL param.Opt[string] `json:"image_url,omitzero" format:"uri"`
	// Secondary label, below `caption` on the left.
	Subcaption param.Opt[string] `json:"subcaption,omitzero"`
	// Label shown top-right.
	TrailingCaption param.Opt[string] `json:"trailing_caption,omitzero"`
	// Label shown below `trailing_caption`, on the right.
	TrailingSubcaption param.Opt[string] `json:"trailing_subcaption,omitzero"`
	// contains filtered or unexported fields
}

Visible layout of the card. At least one of `caption`, `subcaption`, `trailing_caption`, `trailing_subcaption`, or `image_url` must be set, otherwise the card renders as an empty bubble.

`image_url` displays a preview image at the top of the card. The image renders on the recipient's card whether or not they have your app installed. The small icon beside the caption is the app's own icon and is not settable here.

`* Note - requires a trusted chat w/ inbound activity`

`image_title` and `image_subtitle` render as text overlaid on the image (title bold, subtitle beneath it). They only appear when `image_url` is set — without an image there is nothing to overlay — so setting either without `image_url` is rejected.

func (MessageContentPartIMessageAppLayoutParam) MarshalJSON added in v0.25.0

func (r MessageContentPartIMessageAppLayoutParam) MarshalJSON() (data []byte, err error)

func (*MessageContentPartIMessageAppLayoutParam) UnmarshalJSON added in v0.25.0

func (r *MessageContentPartIMessageAppLayoutParam) UnmarshalJSON(data []byte) error

type MessageContentPartIMessageAppParam added in v0.25.0

type MessageContentPartIMessageAppParam struct {
	// Identifies the iMessage app (Messages app extension) that backs the card.
	App MessageContentPartIMessageAppAppParam `json:"app,omitzero" api:"required"`
	// Visible layout of the card. At least one of `caption`, `subcaption`,
	// `trailing_caption`, `trailing_subcaption`, or `image_url` must be set, otherwise
	// the card renders as an empty bubble.
	//
	// `image_url` displays a preview image at the top of the card. The image renders
	// on the recipient's card whether or not they have your app installed. The small
	// icon beside the caption is the app's own icon and is not settable here.
	//
	// `* Note - requires a trusted chat w/ inbound activity`
	//
	// `image_title` and `image_subtitle` render as text overlaid on the image (title
	// bold, subtitle beneath it). They only appear when `image_url` is set — without
	// an image there is nothing to overlay — so setting either without `image_url` is
	// rejected.
	Layout MessageContentPartIMessageAppLayoutParam `json:"layout,omitzero" api:"required"`
	// Text shown on surfaces that cannot render the card (notifications, lock screen).
	// Defaults to the caption when omitted.
	FallbackText param.Opt[string] `json:"fallback_text,omitzero"`
	// Whether the card renders as your app's interactive balloon for recipients who
	// have your iMessage app installed. `true` (default) lets your installed extension
	// draw its live, interactive view for those recipients; everyone else sees the
	// static card built from `layout`. `false` always shows the static `layout` card,
	// even to recipients who have the app installed. Recipients without your app
	// always see the static card regardless of this flag.
	Interactive param.Opt[bool] `json:"interactive,omitzero"`
	// URL the recipient's app opens when they tap the card. Either an absolute
	// `https://` URL (capped at 2048 characters) or a `data:` URL carrying inline app
	// state, e.g. a game's encoded state (capped at 16384 characters).
	URL param.Opt[string] `json:"url,omitzero" format:"uri"`
	// Indicates this is an iMessage app card part.
	//
	// This field can be elided, and will marshal its zero value as "imessage_app".
	Type constant.IMessageApp `json:"type" default:"imessage_app"`
	// contains filtered or unexported fields
}

An iMessage app card, backed by a Messages app extension. iMessage only — an `imessage_app` part must be the **only** part in the message and is never delivered over SMS/RCS. See the IMessageAppServiceUnsupported (2018) and RecipientUnsupportedMessageType (4005) error codes.

The properties App, Layout, Type are required.

func (MessageContentPartIMessageAppParam) MarshalJSON added in v0.25.0

func (r MessageContentPartIMessageAppParam) MarshalJSON() (data []byte, err error)

func (*MessageContentPartIMessageAppParam) UnmarshalJSON added in v0.25.0

func (r *MessageContentPartIMessageAppParam) UnmarshalJSON(data []byte) error

type MessageContentPartUnionParam

type MessageContentPartUnionParam struct {
	OfText        *TextPartParam                      `json:",omitzero,inline"`
	OfMedia       *MediaPartParam                     `json:",omitzero,inline"`
	OfLink        *LinkPartParam                      `json:",omitzero,inline"`
	OfIMessageApp *MessageContentPartIMessageAppParam `json:",omitzero,inline"`
	OfAppClip     *MessageContentPartAppClipParam     `json:",omitzero,inline"`
	// contains filtered or unexported fields
}

Only one field can be non-zero.

Use param.IsOmitted to confirm if a field is set.

func (MessageContentPartUnionParam) MarshalJSON

func (u MessageContentPartUnionParam) MarshalJSON() ([]byte, error)

func (*MessageContentPartUnionParam) UnmarshalJSON

func (u *MessageContentPartUnionParam) UnmarshalJSON(data []byte) error

type MessageDeliveredWebhookEvent added in v0.12.0

type MessageDeliveredWebhookEvent struct {
	// API version for the webhook payload format
	APIVersion string `json:"api_version" api:"required"`
	// When the event was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// Unified payload for message webhooks when using `webhook_version: "2026-02-03"`.
	//
	// This schema is used for message.sent, message.received, message.delivered, and
	// message.read events when the subscription URL includes `?version=2026-02-03`.
	//
	// Key differences from V1 (2025-01-01):
	//
	//   - `direction`: "inbound" or "outbound" instead of `is_from_me` boolean
	//   - `sender_handle`: Full handle object for the sender
	//   - `chat`: Nested object with `id`, `is_group`, and `owner_handle`
	//   - Message fields (`id`, `parts`, `effect`, etc.) are at the top level, not
	//     nested in `message`
	//
	// Timestamps indicate the message state:
	//
	// - `message.sent`: sent_at set, delivered_at=null, read_at=null
	// - `message.received`: sent_at set, delivered_at=null, read_at=null
	// - `message.delivered`: sent_at set, delivered_at set, read_at=null
	// - `message.read`: sent_at set, delivered_at set, read_at set
	Data MessageEventV2 `json:"data" api:"required"`
	// Unique identifier for this event (for deduplication)
	EventID string `json:"event_id" api:"required" format:"uuid"`
	// Valid webhook event types that can be subscribed to.
	//
	// **Note:** `message.edited` is only delivered to subscriptions using
	// `webhook_version: "2026-02-03"`. Subscribing to this event on a v2025
	// subscription will not produce any deliveries.
	//
	// Any of "message.sent", "message.received", "message.read", "message.delivered",
	// "message.failed", "message.edited", "reaction.added", "reaction.removed",
	// "poll.received", "poll.failed", "poll.sent", "poll.delivered", "poll.read",
	// "poll.updated", "poll.vote.added", "poll.vote.removed", "poll.reaction.added",
	// "participant.added", "participant.removed", "chat.created",
	// "chat.group_name_updated", "chat.group_icon_updated",
	// "chat.group_name_update_failed", "chat.group_icon_update_failed",
	// "chat.background_updated", "chat.background_update_failed",
	// "chat.typing_indicator.started", "chat.typing_indicator.stopped",
	// "phone_number.status_updated", "contact_card.received", "call.initiated",
	// "call.ringing", "call.answered", "call.ended", "call.failed", "call.declined",
	// "call.no_answer", "location.sharing.started", "location.sharing.stopped",
	// "payment.succeeded", "payment.canceled", "payment.expired", "payment.declined",
	// "payment.authorized", "connection.created", "connection.revoked".
	EventType WebhookEventType `json:"event_type" api:"required"`
	// Partner identifier. Present on all webhooks for cross-referencing.
	PartnerID string `json:"partner_id" api:"required"`
	// Trace ID for debugging and correlation across systems.
	TraceID string `json:"trace_id" api:"required"`
	// Date-based webhook payload version. Determined by the `?version=` query
	// parameter in your webhook subscription URL. If no version parameter is
	// specified, defaults based on subscription creation date.
	WebhookVersion string `json:"webhook_version" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		APIVersion     respjson.Field
		CreatedAt      respjson.Field
		Data           respjson.Field
		EventID        respjson.Field
		EventType      respjson.Field
		PartnerID      respjson.Field
		TraceID        respjson.Field
		WebhookVersion respjson.Field
		ExtraFields    map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Complete webhook payload for message.delivered events (2026-02-03 format)

func (MessageDeliveredWebhookEvent) RawJSON added in v0.12.0

Returns the unmodified JSON received from the API

func (*MessageDeliveredWebhookEvent) UnmarshalJSON added in v0.12.0

func (r *MessageDeliveredWebhookEvent) UnmarshalJSON(data []byte) error

type MessageDeliveryStatus added in v0.24.0

type MessageDeliveryStatus string

Current delivery status of a message

const (
	MessageDeliveryStatusPending   MessageDeliveryStatus = "pending"
	MessageDeliveryStatusQueued    MessageDeliveryStatus = "queued"
	MessageDeliveryStatusSent      MessageDeliveryStatus = "sent"
	MessageDeliveryStatusDelivered MessageDeliveryStatus = "delivered"
	MessageDeliveryStatusReceived  MessageDeliveryStatus = "received"
	MessageDeliveryStatusRead      MessageDeliveryStatus = "read"
	MessageDeliveryStatusFailed    MessageDeliveryStatus = "failed"
)

type MessageEditedWebhookEvent added in v0.12.0

type MessageEditedWebhookEvent struct {
	// API version for the webhook payload format
	APIVersion string `json:"api_version" api:"required"`
	// When the event was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// Payload for `message.edited` events (2026-02-03 format).
	//
	// Describes which part of a message was edited and when. Only text parts can be
	// edited. Only available for subscriptions using `webhook_version: "2026-02-03"`.
	Data MessageEditedWebhookEventData `json:"data" api:"required"`
	// Unique identifier for this event (for deduplication)
	EventID string `json:"event_id" api:"required" format:"uuid"`
	// Valid webhook event types that can be subscribed to.
	//
	// **Note:** `message.edited` is only delivered to subscriptions using
	// `webhook_version: "2026-02-03"`. Subscribing to this event on a v2025
	// subscription will not produce any deliveries.
	//
	// Any of "message.sent", "message.received", "message.read", "message.delivered",
	// "message.failed", "message.edited", "reaction.added", "reaction.removed",
	// "poll.received", "poll.failed", "poll.sent", "poll.delivered", "poll.read",
	// "poll.updated", "poll.vote.added", "poll.vote.removed", "poll.reaction.added",
	// "participant.added", "participant.removed", "chat.created",
	// "chat.group_name_updated", "chat.group_icon_updated",
	// "chat.group_name_update_failed", "chat.group_icon_update_failed",
	// "chat.background_updated", "chat.background_update_failed",
	// "chat.typing_indicator.started", "chat.typing_indicator.stopped",
	// "phone_number.status_updated", "contact_card.received", "call.initiated",
	// "call.ringing", "call.answered", "call.ended", "call.failed", "call.declined",
	// "call.no_answer", "location.sharing.started", "location.sharing.stopped",
	// "payment.succeeded", "payment.canceled", "payment.expired", "payment.declined",
	// "payment.authorized", "connection.created", "connection.revoked".
	EventType WebhookEventType `json:"event_type" api:"required"`
	// Partner identifier. Present on all webhooks for cross-referencing.
	PartnerID string `json:"partner_id" api:"required"`
	// Trace ID for debugging and correlation across systems.
	TraceID string `json:"trace_id" api:"required"`
	// Date-based webhook payload version. Determined by the `?version=` query
	// parameter in your webhook subscription URL. If no version parameter is
	// specified, defaults based on subscription creation date.
	WebhookVersion string `json:"webhook_version" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		APIVersion     respjson.Field
		CreatedAt      respjson.Field
		Data           respjson.Field
		EventID        respjson.Field
		EventType      respjson.Field
		PartnerID      respjson.Field
		TraceID        respjson.Field
		WebhookVersion respjson.Field
		ExtraFields    map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Complete webhook payload for message.edited events (2026-02-03 format only)

func (MessageEditedWebhookEvent) RawJSON added in v0.12.0

func (r MessageEditedWebhookEvent) RawJSON() string

Returns the unmodified JSON received from the API

func (*MessageEditedWebhookEvent) UnmarshalJSON added in v0.12.0

func (r *MessageEditedWebhookEvent) UnmarshalJSON(data []byte) error

type MessageEditedWebhookEventData added in v0.12.0

type MessageEditedWebhookEventData struct {
	// Message identifier
	ID string `json:"id" api:"required" format:"uuid"`
	// Chat context
	Chat MessageEditedWebhookEventDataChat `json:"chat" api:"required"`
	// "outbound" if you sent the original message, "inbound" if you received it
	//
	// Any of "outbound", "inbound".
	Direction string `json:"direction" api:"required"`
	// When the edit occurred
	EditedAt time.Time `json:"edited_at" api:"required" format:"date-time"`
	// The edited part
	Part MessageEditedWebhookEventDataPart `json:"part" api:"required"`
	// The handle that sent (and edited) this message
	SenderHandle shared.ChatHandle `json:"sender_handle" api:"required"`
	// True when the edited message is on a zero-day-retention line. Behavior differs
	// by `direction`: on an outbound edit, `part.text` is empty — you already saw the
	// real edited text once, synchronously, in the edit API response, and Linq never
	// persists it. On an inbound edit, `part.text` is still the real text as received;
	// zero-day-retention only means Linq never persists it.
	ZeroRetention bool `json:"zero_retention"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ID            respjson.Field
		Chat          respjson.Field
		Direction     respjson.Field
		EditedAt      respjson.Field
		Part          respjson.Field
		SenderHandle  respjson.Field
		ZeroRetention respjson.Field
		ExtraFields   map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Payload for `message.edited` events (2026-02-03 format).

Describes which part of a message was edited and when. Only text parts can be edited. Only available for subscriptions using `webhook_version: "2026-02-03"`.

func (MessageEditedWebhookEventData) RawJSON added in v0.12.0

Returns the unmodified JSON received from the API

func (*MessageEditedWebhookEventData) UnmarshalJSON added in v0.12.0

func (r *MessageEditedWebhookEventData) UnmarshalJSON(data []byte) error

type MessageEditedWebhookEventDataChat added in v0.12.0

type MessageEditedWebhookEventDataChat struct {
	// Chat identifier
	ID string `json:"id" api:"required" format:"uuid"`
	// **[BETA]** Current health for a chat. Always present — chats start at `HEALTHY`
	// and may shift based on engagement and delivery signals on the conversation. Many
	// `AT_RISK` or `CRITICAL` chats on a single line increase the risk of line
	// flagging.
	//
	// Switch on `status` to surface chat and line health in your UI — the enum is the
	// long-term contract. Each status carries a `doc_url` that deep-links to the
	// relevant section of the Chat Health guide. To gate a send, act on the response
	// rather than the status: a `403` is the authoritative answer.
	//
	// See the [Chat Health guide](/channel/imessage/guides/chats/chat-health) for what
	// each status means and how to react.
	HealthStatus MessageEditedWebhookEventDataChatHealthStatus `json:"health_status" api:"required"`
	// Whether this is a group chat
	IsGroup bool `json:"is_group" api:"required"`
	// The handle that owns this chat (your phone number)
	OwnerHandle shared.ChatHandle `json:"owner_handle" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ID           respjson.Field
		HealthStatus respjson.Field
		IsGroup      respjson.Field
		OwnerHandle  respjson.Field
		ExtraFields  map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Chat context

func (MessageEditedWebhookEventDataChat) RawJSON added in v0.12.0

Returns the unmodified JSON received from the API

func (*MessageEditedWebhookEventDataChat) UnmarshalJSON added in v0.12.0

func (r *MessageEditedWebhookEventDataChat) UnmarshalJSON(data []byte) error

type MessageEditedWebhookEventDataChatHealthStatus added in v0.19.0

type MessageEditedWebhookEventDataChatHealthStatus struct {
	// Deep-link to the relevant section of the Chat Health guide for this status.
	DocURL string `json:"doc_url" api:"required" format:"uri"`
	// Current health bucket for the chat. See the
	// [Chat Health guide](/channel/imessage/guides/chats/chat-health) for what each
	// value means and how to react. `doc_url` deep-links to the relevant section.
	//
	// `OPTED_OUT` — the recipient sent `STOP`, `UNSUBSCRIBE`, `OPTOUT`, `CANCEL`,
	// `END`, or `QUIT`. The keyword must be the whole trimmed message, never part of a
	// longer one: `STOP` counts, `please stop` does not. Most keywords must match
	// exactly, including case. `OPT OUT` is the exception — it matches in any casing,
	// with or without the space or a hyphen, so `opt out`, `Opt-Out` and `optout` all
	// count. It clears as soon as they reply again: any later message from them that
	// is not itself an opt-out keyword opts them back in immediately — a reply in any
	// conversation with you counts, the same way the block does.
	//
	// `OPTED_OUT` marks only the conversation the keyword arrived in. The block below
	// is wider than the mark, so a conversation still reading `HEALTHY` can be blocked
	// as well — gate on the `403`, not on the status. Group threads are never marked
	// and are never blocked.
	//
	// Linq enforces this: while a recipient is opted out, every send to them is
	// rejected with `403` (error code `2024`) before the message is queued, across
	// every chat and every line on your account. Nothing is delivered, including a
	// final courtesy message — to send one, set `override_optout: true` on that single
	// request.
	//
	// Any of "HEALTHY", "AT_RISK", "CRITICAL", "OPTED_OUT".
	Status string `json:"status" api:"required"`
	// When this status last changed.
	UpdatedAt time.Time `json:"updated_at" api:"required" format:"date-time"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		DocURL      respjson.Field
		Status      respjson.Field
		UpdatedAt   respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

**[BETA]** Current health for a chat. Always present — chats start at `HEALTHY` and may shift based on engagement and delivery signals on the conversation. Many `AT_RISK` or `CRITICAL` chats on a single line increase the risk of line flagging.

Switch on `status` to surface chat and line health in your UI — the enum is the long-term contract. Each status carries a `doc_url` that deep-links to the relevant section of the Chat Health guide. To gate a send, act on the response rather than the status: a `403` is the authoritative answer.

See the [Chat Health guide](/channel/imessage/guides/chats/chat-health) for what each status means and how to react.

func (MessageEditedWebhookEventDataChatHealthStatus) RawJSON added in v0.19.0

Returns the unmodified JSON received from the API

func (*MessageEditedWebhookEventDataChatHealthStatus) UnmarshalJSON added in v0.19.0

func (r *MessageEditedWebhookEventDataChatHealthStatus) UnmarshalJSON(data []byte) error

type MessageEditedWebhookEventDataPart added in v0.12.0

type MessageEditedWebhookEventDataPart struct {
	// Zero-based index of the edited part within the message
	Index int64 `json:"index" api:"required"`
	// New text content of the part
	Text string `json:"text" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Index       respjson.Field
		Text        respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

The edited part

func (MessageEditedWebhookEventDataPart) RawJSON added in v0.12.0

Returns the unmodified JSON received from the API

func (*MessageEditedWebhookEventDataPart) UnmarshalJSON added in v0.12.0

func (r *MessageEditedWebhookEventDataPart) UnmarshalJSON(data []byte) error

type MessageEffect

type MessageEffect struct {
	// Name of the effect. Common values:
	//
	//   - Screen effects: confetti, fireworks, lasers, sparkles, celebration, hearts,
	//     love, balloons, happy_birthday, echo, spotlight
	//   - Bubble effects: slam, loud, gentle, invisible
	Name string `json:"name"`
	// Type of effect
	//
	// Any of "screen", "bubble".
	Type MessageEffectType `json:"type"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Name        respjson.Field
		Type        respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

iMessage effect applied to a message (screen or bubble effect)

func (MessageEffect) RawJSON

func (r MessageEffect) RawJSON() string

Returns the unmodified JSON received from the API

func (MessageEffect) ToParam

func (r MessageEffect) ToParam() MessageEffectParam

ToParam converts this MessageEffect to a MessageEffectParam.

Warning: the fields of the param type will not be present. ToParam should only be used at the last possible moment before sending a request. Test for this with MessageEffectParam.Overrides()

func (*MessageEffect) UnmarshalJSON

func (r *MessageEffect) UnmarshalJSON(data []byte) error

type MessageEffectParam

type MessageEffectParam struct {
	// Name of the effect. Common values:
	//
	//   - Screen effects: confetti, fireworks, lasers, sparkles, celebration, hearts,
	//     love, balloons, happy_birthday, echo, spotlight
	//   - Bubble effects: slam, loud, gentle, invisible
	Name param.Opt[string] `json:"name,omitzero"`
	// Type of effect
	//
	// Any of "screen", "bubble".
	Type MessageEffectType `json:"type,omitzero"`
	// contains filtered or unexported fields
}

iMessage effect applied to a message (screen or bubble effect)

func (MessageEffectParam) MarshalJSON

func (r MessageEffectParam) MarshalJSON() (data []byte, err error)

func (*MessageEffectParam) UnmarshalJSON

func (r *MessageEffectParam) UnmarshalJSON(data []byte) error

type MessageEffectType

type MessageEffectType string

Type of effect

const (
	MessageEffectTypeScreen MessageEffectType = "screen"
	MessageEffectTypeBubble MessageEffectType = "bubble"
)

type MessageEventV2 added in v0.2.0

type MessageEventV2 struct {
	// Message identifier
	ID string `json:"id" api:"required" format:"uuid"`
	// Chat information
	Chat MessageEventV2Chat `json:"chat" api:"required"`
	// Message direction - "outbound" if sent by you, "inbound" if received
	//
	// Any of "inbound", "outbound".
	Direction MessageEventV2Direction `json:"direction" api:"required"`
	// Message parts (text and/or media)
	Parts []MessageEventV2PartUnion `json:"parts" api:"required"`
	// The handle that sent this message
	SenderHandle shared.ChatHandle `json:"sender_handle" api:"required"`
	// Messaging service type
	//
	// Any of "iMessage", "SMS", "RCS".
	Service shared.ServiceType `json:"service" api:"required"`
	// When the message was delivered. Null if not yet delivered.
	DeliveredAt time.Time `json:"delivered_at" api:"nullable" format:"date-time"`
	// iMessage effect applied to a message (screen or bubble animation)
	Effect SchemasMessageEffect `json:"effect" api:"nullable"`
	// Idempotency key for deduplication of outbound messages.
	IdempotencyKey string `json:"idempotency_key" api:"nullable"`
	// Preferred messaging service type. Includes "auto" for default fallback behavior.
	//
	// Any of "iMessage", "SMS", "RCS", "auto".
	PreferredService MessageEventV2PreferredService `json:"preferred_service" api:"nullable"`
	// When the message was read. Null if not yet read.
	ReadAt time.Time `json:"read_at" api:"nullable" format:"date-time"`
	// Present only when this message was recovered by reconciliation rather than
	// delivered live, and set to the time of that recovery. The field is omitted
	// entirely for normally-delivered messages, which is the overwhelming majority.
	// When present, expect `sent_at` to be substantially earlier than delivery of this
	// event: the message is genuine but is arriving late and out of real-time order,
	// so treat it as history rather than as a live inbound (for example, suppress
	// auto-replies).
	ReconciledAt time.Time `json:"reconciled_at" format:"date-time"`
	// Reference to the message this is replying to (for threaded replies)
	ReplyTo MessageEventV2ReplyTo `json:"reply_to" api:"nullable"`
	// When the message was sent. Null if not yet sent.
	SentAt time.Time `json:"sent_at" api:"nullable" format:"date-time"`
	// True when this message was sent on a zero-day-retention line. `parts` is always
	// empty in that case — Linq never persists this message's content, so there is
	// nothing to include here, not even a count or type of what was sent.
	ZeroRetention bool `json:"zero_retention"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ID               respjson.Field
		Chat             respjson.Field
		Direction        respjson.Field
		Parts            respjson.Field
		SenderHandle     respjson.Field
		Service          respjson.Field
		DeliveredAt      respjson.Field
		Effect           respjson.Field
		IdempotencyKey   respjson.Field
		PreferredService respjson.Field
		ReadAt           respjson.Field
		ReconciledAt     respjson.Field
		ReplyTo          respjson.Field
		SentAt           respjson.Field
		ZeroRetention    respjson.Field
		ExtraFields      map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Unified payload for message webhooks when using `webhook_version: "2026-02-03"`.

This schema is used for message.sent, message.received, message.delivered, and message.read events when the subscription URL includes `?version=2026-02-03`.

Key differences from V1 (2025-01-01):

  • `direction`: "inbound" or "outbound" instead of `is_from_me` boolean
  • `sender_handle`: Full handle object for the sender
  • `chat`: Nested object with `id`, `is_group`, and `owner_handle`
  • Message fields (`id`, `parts`, `effect`, etc.) are at the top level, not nested in `message`

Timestamps indicate the message state:

- `message.sent`: sent_at set, delivered_at=null, read_at=null - `message.received`: sent_at set, delivered_at=null, read_at=null - `message.delivered`: sent_at set, delivered_at set, read_at=null - `message.read`: sent_at set, delivered_at set, read_at set

func (MessageEventV2) RawJSON added in v0.2.0

func (r MessageEventV2) RawJSON() string

Returns the unmodified JSON received from the API

func (*MessageEventV2) UnmarshalJSON added in v0.2.0

func (r *MessageEventV2) UnmarshalJSON(data []byte) error

type MessageEventV2Chat added in v0.2.0

type MessageEventV2Chat struct {
	// Chat identifier
	ID string `json:"id" api:"required" format:"uuid"`
	// **[BETA]** Current health for a chat. Always present — chats start at `HEALTHY`
	// and may shift based on engagement and delivery signals on the conversation. Many
	// `AT_RISK` or `CRITICAL` chats on a single line increase the risk of line
	// flagging.
	//
	// Switch on `status` to surface chat and line health in your UI — the enum is the
	// long-term contract. Each status carries a `doc_url` that deep-links to the
	// relevant section of the Chat Health guide. To gate a send, act on the response
	// rather than the status: a `403` is the authoritative answer.
	//
	// See the [Chat Health guide](/channel/imessage/guides/chats/chat-health) for what
	// each status means and how to react.
	HealthStatus MessageEventV2ChatHealthStatus `json:"health_status" api:"required"`
	// Whether this is a group chat
	IsGroup bool `json:"is_group" api:"nullable"`
	// Your phone number's handle. Always has is_me=true.
	OwnerHandle shared.ChatHandle `json:"owner_handle" api:"nullable"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ID           respjson.Field
		HealthStatus respjson.Field
		IsGroup      respjson.Field
		OwnerHandle  respjson.Field
		ExtraFields  map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Chat information

func (MessageEventV2Chat) RawJSON added in v0.2.0

func (r MessageEventV2Chat) RawJSON() string

Returns the unmodified JSON received from the API

func (*MessageEventV2Chat) UnmarshalJSON added in v0.2.0

func (r *MessageEventV2Chat) UnmarshalJSON(data []byte) error

type MessageEventV2ChatHealthStatus added in v0.19.0

type MessageEventV2ChatHealthStatus struct {
	// Deep-link to the relevant section of the Chat Health guide for this status.
	DocURL string `json:"doc_url" api:"required" format:"uri"`
	// Current health bucket for the chat. See the
	// [Chat Health guide](/channel/imessage/guides/chats/chat-health) for what each
	// value means and how to react. `doc_url` deep-links to the relevant section.
	//
	// `OPTED_OUT` — the recipient sent `STOP`, `UNSUBSCRIBE`, `OPTOUT`, `CANCEL`,
	// `END`, or `QUIT`. The keyword must be the whole trimmed message, never part of a
	// longer one: `STOP` counts, `please stop` does not. Most keywords must match
	// exactly, including case. `OPT OUT` is the exception — it matches in any casing,
	// with or without the space or a hyphen, so `opt out`, `Opt-Out` and `optout` all
	// count. It clears as soon as they reply again: any later message from them that
	// is not itself an opt-out keyword opts them back in immediately — a reply in any
	// conversation with you counts, the same way the block does.
	//
	// `OPTED_OUT` marks only the conversation the keyword arrived in. The block below
	// is wider than the mark, so a conversation still reading `HEALTHY` can be blocked
	// as well — gate on the `403`, not on the status. Group threads are never marked
	// and are never blocked.
	//
	// Linq enforces this: while a recipient is opted out, every send to them is
	// rejected with `403` (error code `2024`) before the message is queued, across
	// every chat and every line on your account. Nothing is delivered, including a
	// final courtesy message — to send one, set `override_optout: true` on that single
	// request.
	//
	// Any of "HEALTHY", "AT_RISK", "CRITICAL", "OPTED_OUT".
	Status string `json:"status" api:"required"`
	// When this status last changed.
	UpdatedAt time.Time `json:"updated_at" api:"required" format:"date-time"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		DocURL      respjson.Field
		Status      respjson.Field
		UpdatedAt   respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

**[BETA]** Current health for a chat. Always present — chats start at `HEALTHY` and may shift based on engagement and delivery signals on the conversation. Many `AT_RISK` or `CRITICAL` chats on a single line increase the risk of line flagging.

Switch on `status` to surface chat and line health in your UI — the enum is the long-term contract. Each status carries a `doc_url` that deep-links to the relevant section of the Chat Health guide. To gate a send, act on the response rather than the status: a `403` is the authoritative answer.

See the [Chat Health guide](/channel/imessage/guides/chats/chat-health) for what each status means and how to react.

func (MessageEventV2ChatHealthStatus) RawJSON added in v0.19.0

Returns the unmodified JSON received from the API

func (*MessageEventV2ChatHealthStatus) UnmarshalJSON added in v0.19.0

func (r *MessageEventV2ChatHealthStatus) UnmarshalJSON(data []byte) error

type MessageEventV2Direction added in v0.2.0

type MessageEventV2Direction string

Message direction - "outbound" if sent by you, "inbound" if received

const (
	MessageEventV2DirectionInbound  MessageEventV2Direction = "inbound"
	MessageEventV2DirectionOutbound MessageEventV2Direction = "outbound"
)

type MessageEventV2PartAppClip added in v0.41.0

type MessageEventV2PartAppClip struct {
	// Indicates this is an App Clip payment card part
	Type constant.AppClip `json:"type" default:"app_clip"`
	// The checkout link the card opens
	Value string `json:"value" api:"required"`
	// The card's summary line, composed by Linq from the checkout session
	Description string `json:"description"`
	// The card's preview image
	ImageURL string `json:"image_url"`
	// The card's headline, composed by Linq from the checkout session
	Title string `json:"title"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Type        respjson.Field
		Value       respjson.Field
		Description respjson.Field
		ImageURL    respjson.Field
		Title       respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

An Apple Pay App Clip payment card part

func (MessageEventV2PartAppClip) RawJSON added in v0.41.0

func (r MessageEventV2PartAppClip) RawJSON() string

Returns the unmodified JSON received from the API

func (*MessageEventV2PartAppClip) UnmarshalJSON added in v0.41.0

func (r *MessageEventV2PartAppClip) UnmarshalJSON(data []byte) error

type MessageEventV2PartIMessageApp added in v0.25.0

type MessageEventV2PartIMessageApp struct {
	// Identifies the iMessage app (Messages app extension) that backs the card.
	App MessageEventV2PartIMessageAppApp `json:"app" api:"required"`
	// Visible layout of the card.
	Layout MessageEventV2PartIMessageAppLayout `json:"layout" api:"required"`
	// Indicates this is an iMessage app card part.
	Type constant.IMessageApp `json:"type" default:"imessage_app"`
	// The URL the recipient's app opens when the user taps the card.
	URL string `json:"url" api:"required" format:"uri"`
	// Fallback text for surfaces that cannot render the card.
	FallbackText string `json:"fallback_text" api:"nullable"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		App          respjson.Field
		Layout       respjson.Field
		Type         respjson.Field
		URL          respjson.Field
		FallbackText respjson.Field
		ExtraFields  map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

An iMessage app card part.

func (MessageEventV2PartIMessageApp) RawJSON added in v0.25.0

Returns the unmodified JSON received from the API

func (*MessageEventV2PartIMessageApp) UnmarshalJSON added in v0.25.0

func (r *MessageEventV2PartIMessageApp) UnmarshalJSON(data []byte) error

type MessageEventV2PartIMessageAppApp added in v0.25.0

type MessageEventV2PartIMessageAppApp struct {
	// Bundle identifier of the Messages app extension.
	BundleID string `json:"bundle_id" api:"required"`
	// Display name of the app.
	Name string `json:"name" api:"required"`
	// The app's 10-character team identifier.
	TeamID string `json:"team_id" api:"required"`
	// The owning app's App Store id, when known.
	AppStoreID int64 `json:"app_store_id" api:"nullable"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		BundleID    respjson.Field
		Name        respjson.Field
		TeamID      respjson.Field
		AppStoreID  respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Identifies the iMessage app (Messages app extension) that backs the card.

func (MessageEventV2PartIMessageAppApp) RawJSON added in v0.25.0

Returns the unmodified JSON received from the API

func (*MessageEventV2PartIMessageAppApp) UnmarshalJSON added in v0.25.0

func (r *MessageEventV2PartIMessageAppApp) UnmarshalJSON(data []byte) error

type MessageEventV2PartIMessageAppLayout added in v0.25.0

type MessageEventV2PartIMessageAppLayout struct {
	// Primary label, top-left and bold.
	Caption string `json:"caption" api:"nullable"`
	// Secondary label, below caption on the left.
	Subcaption string `json:"subcaption" api:"nullable"`
	// Label shown top-right.
	TrailingCaption string `json:"trailing_caption" api:"nullable"`
	// Label shown below trailing_caption.
	TrailingSubcaption string `json:"trailing_subcaption" api:"nullable"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Caption            respjson.Field
		Subcaption         respjson.Field
		TrailingCaption    respjson.Field
		TrailingSubcaption respjson.Field
		ExtraFields        map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Visible layout of the card.

func (MessageEventV2PartIMessageAppLayout) RawJSON added in v0.25.0

Returns the unmodified JSON received from the API

func (*MessageEventV2PartIMessageAppLayout) UnmarshalJSON added in v0.25.0

func (r *MessageEventV2PartIMessageAppLayout) UnmarshalJSON(data []byte) error
type MessageEventV2PartLink struct {
	// Indicates this is a rich link preview part
	Type constant.Link `json:"type" default:"link"`
	// The URL
	Value string `json:"value" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Type        respjson.Field
		Value       respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

A rich link preview part

func (MessageEventV2PartLink) RawJSON added in v0.9.0

func (r MessageEventV2PartLink) RawJSON() string

Returns the unmodified JSON received from the API

func (*MessageEventV2PartLink) UnmarshalJSON added in v0.9.0

func (r *MessageEventV2PartLink) UnmarshalJSON(data []byte) error

type MessageEventV2PartUnion added in v0.2.0

type MessageEventV2PartUnion struct {
	// Any of "text", "media", "link", "imessage_app", "app_clip".
	Type  string `json:"type"`
	Value string `json:"value"`
	// This field is from variant [SchemasTextPartResponse].
	Mention string `json:"mention"`
	// This field is from variant [SchemasTextPartResponse].
	MentionRange []int64 `json:"mention_range"`
	// This field is from variant [SchemasTextPartResponse].
	Mentions []SchemasTextPartResponseMention `json:"mentions"`
	// This field is from variant [SchemasTextPartResponse].
	TextDecorations []shared.TextDecoration `json:"text_decorations"`
	// This field is from variant [SchemasMediaPartResponse].
	ID string `json:"id"`
	// This field is from variant [SchemasMediaPartResponse].
	Filename string `json:"filename"`
	// This field is from variant [SchemasMediaPartResponse].
	MimeType string `json:"mime_type"`
	// This field is from variant [SchemasMediaPartResponse].
	SizeBytes int64  `json:"size_bytes"`
	URL       string `json:"url"`
	// This field is from variant [MessageEventV2PartIMessageApp].
	App MessageEventV2PartIMessageAppApp `json:"app"`
	// This field is from variant [MessageEventV2PartIMessageApp].
	Layout MessageEventV2PartIMessageAppLayout `json:"layout"`
	// This field is from variant [MessageEventV2PartIMessageApp].
	FallbackText string `json:"fallback_text"`
	// This field is from variant [MessageEventV2PartAppClip].
	Description string `json:"description"`
	// This field is from variant [MessageEventV2PartAppClip].
	ImageURL string `json:"image_url"`
	// This field is from variant [MessageEventV2PartAppClip].
	Title string `json:"title"`
	JSON  struct {
		Type            respjson.Field
		Value           respjson.Field
		Mention         respjson.Field
		MentionRange    respjson.Field
		Mentions        respjson.Field
		TextDecorations respjson.Field
		ID              respjson.Field
		Filename        respjson.Field
		MimeType        respjson.Field
		SizeBytes       respjson.Field
		URL             respjson.Field
		App             respjson.Field
		Layout          respjson.Field
		FallbackText    respjson.Field
		Description     respjson.Field
		ImageURL        respjson.Field
		Title           respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

MessageEventV2PartUnion contains all possible properties and values from SchemasTextPartResponse, SchemasMediaPartResponse, MessageEventV2PartLink, MessageEventV2PartIMessageApp, MessageEventV2PartAppClip.

Use the MessageEventV2PartUnion.AsAny method to switch on the variant.

Use the methods beginning with 'As' to cast the union to one of its variants.

func (MessageEventV2PartUnion) AsAny added in v0.2.0

func (u MessageEventV2PartUnion) AsAny() anyMessageEventV2Part

Use the following switch statement to find the correct variant

switch variant := MessageEventV2PartUnion.AsAny().(type) {
case linqgo.SchemasTextPartResponse:
case linqgo.SchemasMediaPartResponse:
case linqgo.MessageEventV2PartLink:
case linqgo.MessageEventV2PartIMessageApp:
case linqgo.MessageEventV2PartAppClip:
default:
  fmt.Errorf("no variant present")
}

func (MessageEventV2PartUnion) AsAppClip added in v0.41.0

func (MessageEventV2PartUnion) AsIMessageApp added in v0.25.0

func (MessageEventV2PartUnion) AsMedia added in v0.2.0

func (MessageEventV2PartUnion) AsText added in v0.2.0

func (MessageEventV2PartUnion) RawJSON added in v0.2.0

func (u MessageEventV2PartUnion) RawJSON() string

Returns the unmodified JSON received from the API

func (*MessageEventV2PartUnion) UnmarshalJSON added in v0.2.0

func (r *MessageEventV2PartUnion) UnmarshalJSON(data []byte) error

type MessageEventV2PreferredService added in v0.2.0

type MessageEventV2PreferredService string

Preferred messaging service type. Includes "auto" for default fallback behavior.

const (
	MessageEventV2PreferredServiceIMessage MessageEventV2PreferredService = "iMessage"
	MessageEventV2PreferredServiceSMS      MessageEventV2PreferredService = "SMS"
	MessageEventV2PreferredServiceRCS      MessageEventV2PreferredService = "RCS"
	MessageEventV2PreferredServiceAuto     MessageEventV2PreferredService = "auto"
)

type MessageEventV2ReplyTo added in v0.2.0

type MessageEventV2ReplyTo struct {
	// ID of the message being replied to
	MessageID string `json:"message_id" format:"uuid"`
	// Index of the part being replied to
	PartIndex int64 `json:"part_index"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		MessageID   respjson.Field
		PartIndex   respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Reference to the message this is replying to (for threaded replies)

func (MessageEventV2ReplyTo) RawJSON added in v0.2.0

func (r MessageEventV2ReplyTo) RawJSON() string

Returns the unmodified JSON received from the API

func (*MessageEventV2ReplyTo) UnmarshalJSON added in v0.2.0

func (r *MessageEventV2ReplyTo) UnmarshalJSON(data []byte) error

type MessageFailedWebhookEvent added in v0.12.0

type MessageFailedWebhookEvent struct {
	// API version for the webhook payload format
	APIVersion string `json:"api_version" api:"required"`
	// When the event was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// Error details for message.failed webhook events. See
	// [WebhookErrorCode](#/components/schemas/WebhookErrorCode) for the full error
	// code reference.
	//
	// In rare cases the message can still be delivered after this event fires — a
	// `message.delivered` webhook for the same message ID may follow.
	Data MessageFailedWebhookEventData `json:"data" api:"required"`
	// Unique identifier for this event (for deduplication)
	EventID string `json:"event_id" api:"required" format:"uuid"`
	// Valid webhook event types that can be subscribed to.
	//
	// **Note:** `message.edited` is only delivered to subscriptions using
	// `webhook_version: "2026-02-03"`. Subscribing to this event on a v2025
	// subscription will not produce any deliveries.
	//
	// Any of "message.sent", "message.received", "message.read", "message.delivered",
	// "message.failed", "message.edited", "reaction.added", "reaction.removed",
	// "poll.received", "poll.failed", "poll.sent", "poll.delivered", "poll.read",
	// "poll.updated", "poll.vote.added", "poll.vote.removed", "poll.reaction.added",
	// "participant.added", "participant.removed", "chat.created",
	// "chat.group_name_updated", "chat.group_icon_updated",
	// "chat.group_name_update_failed", "chat.group_icon_update_failed",
	// "chat.background_updated", "chat.background_update_failed",
	// "chat.typing_indicator.started", "chat.typing_indicator.stopped",
	// "phone_number.status_updated", "contact_card.received", "call.initiated",
	// "call.ringing", "call.answered", "call.ended", "call.failed", "call.declined",
	// "call.no_answer", "location.sharing.started", "location.sharing.stopped",
	// "payment.succeeded", "payment.canceled", "payment.expired", "payment.declined",
	// "payment.authorized", "connection.created", "connection.revoked".
	EventType WebhookEventType `json:"event_type" api:"required"`
	// Partner identifier. Present on all webhooks for cross-referencing.
	PartnerID string `json:"partner_id" api:"required"`
	// Trace ID for debugging and correlation across systems.
	TraceID string `json:"trace_id" api:"required"`
	// Date-based webhook payload version. Determined by the `?version=` query
	// parameter in your webhook subscription URL. If no version parameter is
	// specified, defaults based on subscription creation date.
	WebhookVersion string `json:"webhook_version" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		APIVersion     respjson.Field
		CreatedAt      respjson.Field
		Data           respjson.Field
		EventID        respjson.Field
		EventType      respjson.Field
		PartnerID      respjson.Field
		TraceID        respjson.Field
		WebhookVersion respjson.Field
		ExtraFields    map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Complete webhook payload for message.failed events

func (MessageFailedWebhookEvent) RawJSON added in v0.12.0

func (r MessageFailedWebhookEvent) RawJSON() string

Returns the unmodified JSON received from the API

func (*MessageFailedWebhookEvent) UnmarshalJSON added in v0.12.0

func (r *MessageFailedWebhookEvent) UnmarshalJSON(data []byte) error

type MessageFailedWebhookEventData added in v0.12.0

type MessageFailedWebhookEventData struct {
	// Error codes in webhook failure events. The possible set varies by event:
	// message.failed and poll.failed can carry 3007, 4001, 4002, 4005, 4006, 4007, or
	// 4008; the group update failure events (chat.group_name_update_failed,
	// chat.group_icon_update_failed) carry 3007 or 4001; chat.background_update_failed
	// carries 1005, 2011, 4001, or 5002.
	Code int64 `json:"code" api:"required"`
	// When the failure was detected
	FailedAt time.Time `json:"failed_at" api:"required" format:"date-time"`
	// Chat identifier (UUID)
	ChatID string `json:"chat_id"`
	// Opaque diagnostic code identifying the specific failure class within `code`.
	// Values are not enumerated and may change without notice — log it and include it
	// in support requests, but do not branch on it.
	DetailCode int64 `json:"detail_code" api:"nullable"`
	// Message identifier (UUID)
	MessageID string `json:"message_id"`
	// Preferred messaging service type. Includes "auto" for default fallback behavior.
	//
	// Any of "iMessage", "SMS", "RCS", "auto".
	PreferredService string `json:"preferred_service" api:"nullable"`
	// Human-readable description of the failure
	Reason string `json:"reason"`
	// Messaging service type
	//
	// Any of "iMessage", "SMS", "RCS".
	Service shared.ServiceType `json:"service" api:"nullable"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Code             respjson.Field
		FailedAt         respjson.Field
		ChatID           respjson.Field
		DetailCode       respjson.Field
		MessageID        respjson.Field
		PreferredService respjson.Field
		Reason           respjson.Field
		Service          respjson.Field
		ExtraFields      map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Error details for message.failed webhook events. See [WebhookErrorCode](#/components/schemas/WebhookErrorCode) for the full error code reference.

In rare cases the message can still be delivered after this event fires — a `message.delivered` webhook for the same message ID may follow.

func (MessageFailedWebhookEventData) RawJSON added in v0.12.0

Returns the unmodified JSON received from the API

func (*MessageFailedWebhookEventData) UnmarshalJSON added in v0.12.0

func (r *MessageFailedWebhookEventData) UnmarshalJSON(data []byte) error

type MessageListMessagesThreadParams added in v0.2.0

type MessageListMessagesThreadParams struct {
	// Pagination cursor from previous next_cursor response
	Cursor param.Opt[string] `query:"cursor,omitzero" json:"-"`
	// Maximum number of messages to return
	Limit param.Opt[int64] `query:"limit,omitzero" json:"-"`
	// Sort order for messages (asc = oldest first, desc = newest first)
	//
	// Any of "asc", "desc".
	Order MessageListMessagesThreadParamsOrder `query:"order,omitzero" json:"-"`
	// contains filtered or unexported fields
}

func (MessageListMessagesThreadParams) URLQuery added in v0.2.0

func (r MessageListMessagesThreadParams) URLQuery() (v url.Values, err error)

URLQuery serializes MessageListMessagesThreadParams's query parameters as `url.Values`.

type MessageListMessagesThreadParamsOrder added in v0.2.0

type MessageListMessagesThreadParamsOrder string

Sort order for messages (asc = oldest first, desc = newest first)

const (
	MessageListMessagesThreadParamsOrderAsc  MessageListMessagesThreadParamsOrder = "asc"
	MessageListMessagesThreadParamsOrderDesc MessageListMessagesThreadParamsOrder = "desc"
)

type MessageNewParams added in v0.26.1

type MessageNewParams struct {
	// Message content container. Groups all message-related fields together,
	// separating the "what" (message content) from the "where" (routing fields like
	// from/to).
	//
	// A message carries EITHER `parts` — text and attachments, which compose into one
	// bubble — or a single `experience` invocation, which renders an experience inside
	// Linq's iMessage app. Never both: an app card is the whole message (Apple's
	// `MSMessage` cannot coexist with text), so copy and a card are two sends, not
	// one.
	Message MessageContentParam `json:"message,omitzero" api:"required"`
	// Recipient handles (E.164 phone numbers or email addresses). One handle is a
	// direct chat; multiple handles a group chat. Order-independent — the set
	// identifies the chat.
	To []string `json:"to,omitzero" api:"required"`
	// Send even though the recipient asked you to stop (`403`, error code `2024`).
	// Applies to this request only: the opt-out stays in place, so the next send
	// without this flag is rejected again. Every override is recorded against your API
	// key.
	OverrideOptout param.Opt[bool]   `json:"override_optout,omitzero"`
	IdempotencyKey param.Opt[string] `header:"Idempotency-Key,omitzero" json:"-"`
	// Text-only fallback that **replaces** `message` ONLY on the failover branch —
	// when a chat with these recipients already existed but its line was flagged, so a
	// new chat is created on a fresh line. On that branch this text is sent as the
	// single message instead of `message` (the recipient is on a new number, so you
	// typically want a fresh-number-appropriate opener rather than the original
	// content). Ignored otherwise (a healthy reuse, or genuine first contact). Carries
	// no parts, media, or effects — exactly one message is ever sent.
	ContinuationMessage MessageNewParamsContinuationMessage `json:"continuation_message,omitzero"`
	// Lines (E.164) not to pick for this send. Applies for this request only — nothing
	// is remembered between calls.
	//
	// **Exclusion only affects picking a line for a new chat.** If `to` already has a
	// chat, that chat is reused on its own line, and a chat on a non-excluded line is
	// preferred when there is more than one. If the only chat these recipients have is
	// on an excluded line, it is still reused — an exclusion never abandons a live
	// chat or moves it to a new number. Check `from` in the response to see the line
	// that was actually used.
	//
	// Numbers that are not your lines are ignored. Every entry must be E.164 — a value
	// like `4155551234` is rejected rather than silently skipped. Excluding every one
	// of your available lines returns 400 when a line has to be picked.
	ExcludeFrom []string `json:"exclude_from,omitzero"`
	// contains filtered or unexported fields
}

func (MessageNewParams) MarshalJSON added in v0.26.1

func (r MessageNewParams) MarshalJSON() (data []byte, err error)

func (*MessageNewParams) UnmarshalJSON added in v0.26.1

func (r *MessageNewParams) UnmarshalJSON(data []byte) error

type MessageNewParamsContinuationMessage added in v0.26.1

type MessageNewParamsContinuationMessage struct {
	// The replacement message text, sent as the single message on failover.
	Text string `json:"text" api:"required"`
	// contains filtered or unexported fields
}

Text-only fallback that **replaces** `message` ONLY on the failover branch — when a chat with these recipients already existed but its line was flagged, so a new chat is created on a fresh line. On that branch this text is sent as the single message instead of `message` (the recipient is on a new number, so you typically want a fresh-number-appropriate opener rather than the original content). Ignored otherwise (a healthy reuse, or genuine first contact). Carries no parts, media, or effects — exactly one message is ever sent.

The property Text is required.

func (MessageNewParamsContinuationMessage) MarshalJSON added in v0.26.1

func (r MessageNewParamsContinuationMessage) MarshalJSON() (data []byte, err error)

func (*MessageNewParamsContinuationMessage) UnmarshalJSON added in v0.26.1

func (r *MessageNewParamsContinuationMessage) UnmarshalJSON(data []byte) error

type MessageNewResponse added in v0.26.1

type MessageNewResponse struct {
	// The resolved chat (reused or newly created) the message landed in.
	ChatID string `json:"chat_id" api:"required" format:"uuid"`
	// True when a new chat was created (new or failover), false on reuse.
	CreatedNewChat bool `json:"created_new_chat" api:"required"`
	// The line (E.164) the message was actually sent from.
	From string `json:"from" api:"required"`
	// Why this line/chat was chosen.
	FromSelection MessageNewResponseFromSelection `json:"from_selection" api:"required"`
	// Participants of the resolved chat.
	Handles []shared.ChatHandle `json:"handles" api:"required"`
	// Whether the resolved chat is a group chat.
	IsGroup bool `json:"is_group" api:"required"`
	// A message that was sent (used in CreateChat and SendMessage responses)
	Message SentMessage `json:"message" api:"required"`
	// Messaging service type
	//
	// Any of "iMessage", "SMS", "RCS".
	Service shared.ServiceType `json:"service" api:"required"`
	// Set ONLY on `failover_flagged`: the abandoned flagged chat that was NOT sent
	// into. Null otherwise.
	PreviousChatID string `json:"previous_chat_id" api:"nullable" format:"uuid"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ChatID         respjson.Field
		CreatedNewChat respjson.Field
		From           respjson.Field
		FromSelection  respjson.Field
		Handles        respjson.Field
		IsGroup        respjson.Field
		Message        respjson.Field
		Service        respjson.Field
		PreviousChatID respjson.Field
		ExtraFields    map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Result of an auto-from send. Self-describing: which line was used, which chat the message landed in, whether a new chat was created, and the resulting message id(s).

func (MessageNewResponse) RawJSON added in v0.26.1

func (r MessageNewResponse) RawJSON() string

Returns the unmodified JSON received from the API

func (*MessageNewResponse) UnmarshalJSON added in v0.26.1

func (r *MessageNewResponse) UnmarshalJSON(data []byte) error

type MessageNewResponseFromSelection added in v0.26.1

type MessageNewResponseFromSelection struct {
	//   - `reused_active_chat` — reused an existing chat on its healthy line
	//   - `new_best_number` — created a new chat on the best available line
	//   - `failover_flagged` — no existing chat for these recipients was on a line that
	//     could send; created a new chat on a fresh line
	//
	// Any of "reused_active_chat", "new_best_number", "failover_flagged".
	Reason string `json:"reason" api:"required"`
	// True only when an existing chat was reused.
	ReusedExistingChat bool `json:"reused_existing_chat" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Reason             respjson.Field
		ReusedExistingChat respjson.Field
		ExtraFields        map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Why this line/chat was chosen.

func (MessageNewResponseFromSelection) RawJSON added in v0.26.1

Returns the unmodified JSON received from the API

func (*MessageNewResponseFromSelection) UnmarshalJSON added in v0.26.1

func (r *MessageNewResponseFromSelection) UnmarshalJSON(data []byte) error

type MessagePartAppClipPartResponse added in v0.36.0

type MessagePartAppClipPartResponse struct {
	// Reactions on this message part
	Reactions []shared.Reaction `json:"reactions" api:"required"`
	// Indicates this is an App Clip card part
	//
	// Any of "app_clip".
	Type string `json:"type" api:"required"`
	// The App Clip link the card opens
	Value string `json:"value" api:"required"`
	// The card's summary line, composed by Linq from the App Clip page
	Description string `json:"description"`
	// The card's preview image
	ImageURL string `json:"image_url"`
	// The card's headline, composed by Linq from the App Clip page
	Title string `json:"title"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Reactions   respjson.Field
		Type        respjson.Field
		Value       respjson.Field
		Description respjson.Field
		ImageURL    respjson.Field
		Title       respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

An App Clip card part

func (MessagePartAppClipPartResponse) RawJSON added in v0.36.0

Returns the unmodified JSON received from the API

func (*MessagePartAppClipPartResponse) UnmarshalJSON added in v0.36.0

func (r *MessagePartAppClipPartResponse) UnmarshalJSON(data []byte) error

type MessagePartIMessageAppPartResponse added in v0.25.0

type MessagePartIMessageAppPartResponse struct {
	// Identifies the iMessage app (Messages app extension) that backs the card.
	App MessagePartIMessageAppPartResponseApp `json:"app" api:"required"`
	// Visible layout of the card. At least one of `caption`, `subcaption`,
	// `trailing_caption`, `trailing_subcaption`, or `image_url` must be set, otherwise
	// the card renders as an empty bubble.
	//
	// `image_url` displays a preview image at the top of the card. The image renders
	// on the recipient's card whether or not they have your app installed. The small
	// icon beside the caption is the app's own icon and is not settable here.
	//
	// `* Note - requires a trusted chat w/ inbound activity`
	//
	// `image_title` and `image_subtitle` render as text overlaid on the image (title
	// bold, subtitle beneath it). They only appear when `image_url` is set — without
	// an image there is nothing to overlay — so setting either without `image_url` is
	// rejected.
	Layout MessagePartIMessageAppPartResponseLayout `json:"layout" api:"required"`
	// Reactions on this message part
	Reactions []shared.Reaction `json:"reactions" api:"required"`
	// Indicates this is an iMessage app card part.
	//
	// Any of "imessage_app".
	Type string `json:"type" api:"required"`
	// The URL delivered to the iMessage app on tap.
	URL string `json:"url" api:"required" format:"uri"`
	// Fallback text for surfaces that cannot render the card.
	FallbackText string `json:"fallback_text" api:"nullable"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		App          respjson.Field
		Layout       respjson.Field
		Reactions    respjson.Field
		Type         respjson.Field
		URL          respjson.Field
		FallbackText respjson.Field
		ExtraFields  map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

An iMessage app card part.

func (MessagePartIMessageAppPartResponse) RawJSON added in v0.25.0

Returns the unmodified JSON received from the API

func (*MessagePartIMessageAppPartResponse) UnmarshalJSON added in v0.25.0

func (r *MessagePartIMessageAppPartResponse) UnmarshalJSON(data []byte) error

type MessagePartIMessageAppPartResponseApp added in v0.25.0

type MessagePartIMessageAppPartResponseApp struct {
	// Bundle identifier of the Messages app extension. Must not contain `:`.
	BundleID string `json:"bundle_id" api:"required"`
	// Display name of the app, shown by Messages' fallback UI.
	Name string `json:"name" api:"required"`
	// The app's 10-character uppercase alphanumeric team identifier.
	TeamID string `json:"team_id" api:"required"`
	// The owning app's App Store id (optional). When set, recipients without the
	// iMessage app installed see a "Get the app" affordance.
	AppStoreID int64 `json:"app_store_id"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		BundleID    respjson.Field
		Name        respjson.Field
		TeamID      respjson.Field
		AppStoreID  respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Identifies the iMessage app (Messages app extension) that backs the card.

func (MessagePartIMessageAppPartResponseApp) RawJSON added in v0.25.0

Returns the unmodified JSON received from the API

func (*MessagePartIMessageAppPartResponseApp) UnmarshalJSON added in v0.25.0

func (r *MessagePartIMessageAppPartResponseApp) UnmarshalJSON(data []byte) error

type MessagePartIMessageAppPartResponseLayout added in v0.25.0

type MessagePartIMessageAppPartResponseLayout struct {
	// Primary label, top-left and bold.
	Caption string `json:"caption"`
	// Text shown below `image_title`, overlaid on the card image. Requires
	// `image_url`.
	ImageSubtitle string `json:"image_subtitle"`
	// Bold text overlaid on the card image. Requires `image_url` (rejected without
	// it).
	ImageTitle string `json:"image_title"`
	// URL of an image (JPEG, PNG, HEIF, or WebP) to display as the card's preview
	// image; an unreachable or non-image URL returns a validation error. Renders for
	// all recipients regardless of whether they have the app. Note - requires a
	// trusted chat w/ inbound activity. In responses, this is the re-hosted
	// `cdn.linqapp.com` copy of the image you supplied, not your original URL.
	ImageURL string `json:"image_url" format:"uri"`
	// Secondary label, below `caption` on the left.
	Subcaption string `json:"subcaption"`
	// Label shown top-right.
	TrailingCaption string `json:"trailing_caption"`
	// Label shown below `trailing_caption`, on the right.
	TrailingSubcaption string `json:"trailing_subcaption"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Caption            respjson.Field
		ImageSubtitle      respjson.Field
		ImageTitle         respjson.Field
		ImageURL           respjson.Field
		Subcaption         respjson.Field
		TrailingCaption    respjson.Field
		TrailingSubcaption respjson.Field
		ExtraFields        map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Visible layout of the card. At least one of `caption`, `subcaption`, `trailing_caption`, `trailing_subcaption`, or `image_url` must be set, otherwise the card renders as an empty bubble.

`image_url` displays a preview image at the top of the card. The image renders on the recipient's card whether or not they have your app installed. The small icon beside the caption is the app's own icon and is not settable here.

`* Note - requires a trusted chat w/ inbound activity`

`image_title` and `image_subtitle` render as text overlaid on the image (title bold, subtitle beneath it). They only appear when `image_url` is set — without an image there is nothing to overlay — so setting either without `image_url` is rejected.

func (MessagePartIMessageAppPartResponseLayout) RawJSON added in v0.25.0

Returns the unmodified JSON received from the API

func (*MessagePartIMessageAppPartResponseLayout) UnmarshalJSON added in v0.25.0

func (r *MessagePartIMessageAppPartResponseLayout) UnmarshalJSON(data []byte) error

type MessagePartUnion

type MessagePartUnion struct {
	Reactions []shared.Reaction `json:"reactions"`
	Type      string            `json:"type"`
	Value     string            `json:"value"`
	// This field is from variant [shared.TextPartResponse].
	Mention string `json:"mention"`
	// This field is from variant [shared.TextPartResponse].
	MentionRange []int64 `json:"mention_range"`
	// This field is from variant [shared.TextPartResponse].
	Mentions []shared.TextPartResponseMention `json:"mentions"`
	// This field is from variant [shared.TextPartResponse].
	TextDecorations []shared.TextDecoration `json:"text_decorations"`
	// This field is from variant [shared.MediaPartResponse].
	ID string `json:"id"`
	// This field is from variant [shared.MediaPartResponse].
	Filename string `json:"filename"`
	// This field is from variant [shared.MediaPartResponse].
	MimeType string `json:"mime_type"`
	// This field is from variant [shared.MediaPartResponse].
	SizeBytes int64  `json:"size_bytes"`
	URL       string `json:"url"`
	// This field is from variant [MessagePartIMessageAppPartResponse].
	App MessagePartIMessageAppPartResponseApp `json:"app"`
	// This field is from variant [MessagePartIMessageAppPartResponse].
	Layout MessagePartIMessageAppPartResponseLayout `json:"layout"`
	// This field is from variant [MessagePartIMessageAppPartResponse].
	FallbackText string `json:"fallback_text"`
	// This field is from variant [MessagePartAppClipPartResponse].
	Description string `json:"description"`
	// This field is from variant [MessagePartAppClipPartResponse].
	ImageURL string `json:"image_url"`
	// This field is from variant [MessagePartAppClipPartResponse].
	Title string `json:"title"`
	JSON  struct {
		Reactions       respjson.Field
		Type            respjson.Field
		Value           respjson.Field
		Mention         respjson.Field
		MentionRange    respjson.Field
		Mentions        respjson.Field
		TextDecorations respjson.Field
		ID              respjson.Field
		Filename        respjson.Field
		MimeType        respjson.Field
		SizeBytes       respjson.Field
		URL             respjson.Field
		App             respjson.Field
		Layout          respjson.Field
		FallbackText    respjson.Field
		Description     respjson.Field
		ImageURL        respjson.Field
		Title           respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

MessagePartUnion contains all possible properties and values from shared.TextPartResponse, shared.MediaPartResponse, shared.LinkPartResponse, MessagePartIMessageAppPartResponse, MessagePartAppClipPartResponse.

Use the methods beginning with 'As' to cast the union to one of its variants.

func (MessagePartUnion) AsLinkPartResponse added in v0.13.0

func (u MessagePartUnion) AsLinkPartResponse() (v shared.LinkPartResponse)

func (MessagePartUnion) AsMediaPartResponse added in v0.2.0

func (u MessagePartUnion) AsMediaPartResponse() (v shared.MediaPartResponse)

func (MessagePartUnion) AsMessagePartAppClipPartResponse added in v0.36.0

func (u MessagePartUnion) AsMessagePartAppClipPartResponse() (v MessagePartAppClipPartResponse)

func (MessagePartUnion) AsMessagePartIMessageAppPartResponse added in v0.25.0

func (u MessagePartUnion) AsMessagePartIMessageAppPartResponse() (v MessagePartIMessageAppPartResponse)

func (MessagePartUnion) AsTextPartResponse added in v0.2.0

func (u MessagePartUnion) AsTextPartResponse() (v shared.TextPartResponse)

func (MessagePartUnion) RawJSON

func (u MessagePartUnion) RawJSON() string

Returns the unmodified JSON received from the API

func (*MessagePartUnion) UnmarshalJSON

func (r *MessagePartUnion) UnmarshalJSON(data []byte) error

type MessagePollAddOptionsParams added in v0.29.1

type MessagePollAddOptionsParams struct {
	Options []MessagePollAddOptionsParamsOption `json:"options,omitzero" api:"required"`
	// contains filtered or unexported fields
}

func (MessagePollAddOptionsParams) MarshalJSON added in v0.29.1

func (r MessagePollAddOptionsParams) MarshalJSON() (data []byte, err error)

func (*MessagePollAddOptionsParams) UnmarshalJSON added in v0.29.1

func (r *MessagePollAddOptionsParams) UnmarshalJSON(data []byte) error

type MessagePollAddOptionsParamsOption added in v0.29.1

type MessagePollAddOptionsParamsOption struct {
	Text string `json:"text" api:"required"`
	// contains filtered or unexported fields
}

The property Text is required.

func (MessagePollAddOptionsParamsOption) MarshalJSON added in v0.29.1

func (r MessagePollAddOptionsParamsOption) MarshalJSON() (data []byte, err error)

func (*MessagePollAddOptionsParamsOption) UnmarshalJSON added in v0.29.1

func (r *MessagePollAddOptionsParamsOption) UnmarshalJSON(data []byte) error

type MessagePollService added in v0.29.1

type MessagePollService struct {
	Options []option.RequestOption
}

Messages are individual communications within a chat thread.

Messages can include text, media attachments, rich link previews, special effects (like confetti or fireworks), and reactions. All messages are associated with a specific chat and sent from a phone number you own.

Messages support delivery status tracking, read receipts, and editing capabilities.

## Rich Link Previews

Send a URL as a `link` part to deliver it with a rich preview card showing the page's title, description, and image (when available). A `link` part must be the **only** part in the message — it cannot be combined with text or media parts. To send a URL without a preview card, include it in a `text` part instead.

**Limitations:**

- A `link` part cannot be combined with other parts in the same message. - Maximum URL length: 2,048 characters.

## App Clips

An `app_clip` part sends a **registered App Clip** — not only Linq's Apple Pay checkout, but any partner's own App Clip. Like a `link` part it must be the **only** part in the message, and it is **iMessage only** — it never downgrades to SMS or RCS. The payment-checkout use of this part is covered in the **Payments** section.

## Ephemeral Messages (Privacy Tier)

For regulated or sensitive conversations, opt in to the **ephemeral messages** tier by contacting your Linq support contact. When enabled, every message on the covered phone numbers is given a **retention window configured for your account**. After that window, the message's text, formatting, and attachment references are no longer retrievable through the API — see the Attachments row below for how the attachment media itself is handled. Metadata about the message is retained: message identifiers, timestamps, phone numbers, and delivery state. Metadata retention is not bounded by this window. Bounded operational copies, such as backups and delivery queues, expire on their own separate schedules. There is no per-message flag; ephemerality is applied automatically based on your configuration.

The window can be set anywhere from **60 minutes to 24 hours**, and defaults to **24 hours**. Ask your Linq support contact to configure a shorter window; it cannot be changed through the API.

You can request it at two scopes:

| Scope | Effect | | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Partner-wide** | Every outbound and inbound message on every phone number under your account has its content removed from the API surface after your configured window. Metadata is retained. | | **Per phone number** | Only the specified phone numbers have message content removed from the API surface this way. The rest follow the standard message-retention policy. |

**Behavioral differences vs the standard default:**

| Aspect | Standard | Ephemeral | | ----------------------- | -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Retention | Retained per the standard message-retention policy | **Hard backstop: your configured window** (60 minutes – 24 hours, default 24 hours) from when the message is created | | After expiry | Message stays retrievable | Message content is no longer retrievable — `GET /v3/messages/{messageId}` returns `404` and it no longer appears in `GET /v3/chats/{chatId}/messages` | | Content on expiry | N/A | Text, formatting, and attachment references are removed from the API surface, not blanked out in place. Metadata (identifiers, timestamps, phone numbers, delivery state) is retained; its retention is not bounded by this window | | Attachments | Retained | Media sent on the **ephemeral attachments tier** is removed on its own storage backstop — within roughly 24–48 hours of upload — independently of the message window, so it can outlast a window shorter than a day. Attachments on the persistent tier (including pre-uploads via `POST /v3/attachments`) are kept until you `DELETE` them | | Cross-partner isolation | Enforced | Enforced |

**How the retention window works:**

  • The window runs from **message creation** (`created_at`). It is configured for your account (60 minutes – 24 hours, default 24 hours) and cannot be set per message.
  • Attachment media follows its own storage backstop rather than the message window — see the Attachments row above.
  • Expiry is delivery-independent — the clock starts when the message is created, not when it is delivered or read.
  • **Deletion happens shortly _after_ the window, not exactly at it.** A background sweep runs every ~5 minutes, so a message typically stops being retrievable within about 5 minutes of its expiry, and longer while a backlog is being worked through. Treat the window as the guaranteed _minimum_ retention, never as an exact deletion time or an upper bound.

**What you observe:**

  • **No expiry timestamp is exposed.** API responses and webhook payloads do not include the deletion time, and they do not report your configured window either — so if you are on a window shorter than 24 hours you cannot derive a message's expiry from the API today. Track the window you agreed with your Linq support contact and compute `created_at + window` yourself.
  • **No deletion webhook is sent.** There is no `message.deleted` event — a message simply stops being retrievable once its window passes.
  • **The attachment backstop is separate from the message window.** API retrievability (the `404` behavior above) ends at your configured window. Ephemeral-tier media objects are removed on their own storage backstop — within roughly 24–48 hours of upload — which is independent of the message window and can outlast a window shorter than a day. Removal of the corresponding entries from the sending device happens asynchronously and can complete after the backstop.
  • **Delivery is unaffected.** Ephemeral messages send, deliver, and fire the usual `message.sent` / `message.received` and status webhooks exactly like standard messages. Only retention changes.

**When to choose ephemeral:**

  • You have a compliance requirement that the platform must not retain message content beyond a short window.
  • The conversation is high-sensitivity (PHI, financial, identity verification) and you do not want it sitting in storage long-term.
  • Your application is the system of record — you capture what you need from the delivery webhook in real time and do not rely on reading message history back from Linq later.

**Important:** ephemeral applies in _both directions_ — messages you send **and** messages received by the phone numbers in that scope. Because Linq can no longer return the message once its window passes, persist anything you need to keep from the webhook payload at the time it is delivered.

MessagePollService contains methods and other services that help with interacting with the linq-api-v3 API.

Note, unlike clients, this service does not read variables from the environment automatically. You should not instantiate this service directly, and instead use the NewMessagePollService method instead.

func NewMessagePollService added in v0.29.1

func NewMessagePollService(opts ...option.RequestOption) (r MessagePollService)

NewMessagePollService generates a new service that applies the given options to each request. These options are applied after the parent client's options (if there is one), and before any request-specific options.

func (*MessagePollService) AddOptions added in v0.29.1

func (r *MessagePollService) AddOptions(ctx context.Context, messageID string, body MessagePollAddOptionsParams, opts ...option.RequestOption) (res *PollEnvelope, err error)

Add one or more options to an existing poll. Options are **add-only and immutable** — you can append options but never edit or remove them (Apple constraint). Returns the full poll.

**On a zero-day-retention line, `options` must include every existing option (in the order they were originally created) followed by the new one(s)**, not just the new option(s). Zero-day-retention polls never store option text, so this request is the only place that text still exists — it's required to correctly render the poll's existing options on the recipient's device when the update is sent. Omitting an existing option returns `400`.

func (*MessagePollService) Get added in v0.29.1

func (r *MessagePollService) Get(ctx context.Context, messageID string, opts ...option.RequestOption) (res *PollEnvelope, err error)

Return a poll's current results — its options, each option's voters, and the distinct total number of voters — by the poll-definition message's ID.

func (*MessagePollService) Vote added in v0.29.1

func (r *MessagePollService) Vote(ctx context.Context, messageID string, body MessagePollVoteParams, opts ...option.RequestOption) (res *PollEnvelope, err error)

Add or remove your line's vote on **one** poll option (per-option toggle — iMessage polls are toggled one option at a time). Returns the poll reflecting the toggle.

type MessagePollVoteParams added in v0.29.1

type MessagePollVoteParams struct {
	// Add or remove your line's vote on the option.
	//
	// Any of "add", "remove".
	Operation MessagePollVoteParamsOperation `json:"operation,omitzero" api:"required"`
	// The option to toggle a vote on.
	OptionID string `json:"option_id" api:"required" format:"uuid"`
	// contains filtered or unexported fields
}

func (MessagePollVoteParams) MarshalJSON added in v0.29.1

func (r MessagePollVoteParams) MarshalJSON() (data []byte, err error)

func (*MessagePollVoteParams) UnmarshalJSON added in v0.29.1

func (r *MessagePollVoteParams) UnmarshalJSON(data []byte) error

type MessagePollVoteParamsOperation added in v0.29.1

type MessagePollVoteParamsOperation string

Add or remove your line's vote on the option.

const (
	MessagePollVoteParamsOperationAdd    MessagePollVoteParamsOperation = "add"
	MessagePollVoteParamsOperationRemove MessagePollVoteParamsOperation = "remove"
)

type MessageReadWebhookEvent added in v0.12.0

type MessageReadWebhookEvent struct {
	// API version for the webhook payload format
	APIVersion string `json:"api_version" api:"required"`
	// When the event was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// Unified payload for message webhooks when using `webhook_version: "2026-02-03"`.
	//
	// This schema is used for message.sent, message.received, message.delivered, and
	// message.read events when the subscription URL includes `?version=2026-02-03`.
	//
	// Key differences from V1 (2025-01-01):
	//
	//   - `direction`: "inbound" or "outbound" instead of `is_from_me` boolean
	//   - `sender_handle`: Full handle object for the sender
	//   - `chat`: Nested object with `id`, `is_group`, and `owner_handle`
	//   - Message fields (`id`, `parts`, `effect`, etc.) are at the top level, not
	//     nested in `message`
	//
	// Timestamps indicate the message state:
	//
	// - `message.sent`: sent_at set, delivered_at=null, read_at=null
	// - `message.received`: sent_at set, delivered_at=null, read_at=null
	// - `message.delivered`: sent_at set, delivered_at set, read_at=null
	// - `message.read`: sent_at set, delivered_at set, read_at set
	Data MessageEventV2 `json:"data" api:"required"`
	// Unique identifier for this event (for deduplication)
	EventID string `json:"event_id" api:"required" format:"uuid"`
	// Valid webhook event types that can be subscribed to.
	//
	// **Note:** `message.edited` is only delivered to subscriptions using
	// `webhook_version: "2026-02-03"`. Subscribing to this event on a v2025
	// subscription will not produce any deliveries.
	//
	// Any of "message.sent", "message.received", "message.read", "message.delivered",
	// "message.failed", "message.edited", "reaction.added", "reaction.removed",
	// "poll.received", "poll.failed", "poll.sent", "poll.delivered", "poll.read",
	// "poll.updated", "poll.vote.added", "poll.vote.removed", "poll.reaction.added",
	// "participant.added", "participant.removed", "chat.created",
	// "chat.group_name_updated", "chat.group_icon_updated",
	// "chat.group_name_update_failed", "chat.group_icon_update_failed",
	// "chat.background_updated", "chat.background_update_failed",
	// "chat.typing_indicator.started", "chat.typing_indicator.stopped",
	// "phone_number.status_updated", "contact_card.received", "call.initiated",
	// "call.ringing", "call.answered", "call.ended", "call.failed", "call.declined",
	// "call.no_answer", "location.sharing.started", "location.sharing.stopped",
	// "payment.succeeded", "payment.canceled", "payment.expired", "payment.declined",
	// "payment.authorized", "connection.created", "connection.revoked".
	EventType WebhookEventType `json:"event_type" api:"required"`
	// Partner identifier. Present on all webhooks for cross-referencing.
	PartnerID string `json:"partner_id" api:"required"`
	// Trace ID for debugging and correlation across systems.
	TraceID string `json:"trace_id" api:"required"`
	// Date-based webhook payload version. Determined by the `?version=` query
	// parameter in your webhook subscription URL. If no version parameter is
	// specified, defaults based on subscription creation date.
	WebhookVersion string `json:"webhook_version" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		APIVersion     respjson.Field
		CreatedAt      respjson.Field
		Data           respjson.Field
		EventID        respjson.Field
		EventType      respjson.Field
		PartnerID      respjson.Field
		TraceID        respjson.Field
		WebhookVersion respjson.Field
		ExtraFields    map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Complete webhook payload for message.read events (2026-02-03 format)

func (MessageReadWebhookEvent) RawJSON added in v0.12.0

func (r MessageReadWebhookEvent) RawJSON() string

Returns the unmodified JSON received from the API

func (*MessageReadWebhookEvent) UnmarshalJSON added in v0.12.0

func (r *MessageReadWebhookEvent) UnmarshalJSON(data []byte) error

type MessageReceivedWebhookEvent added in v0.12.0

type MessageReceivedWebhookEvent struct {
	// API version for the webhook payload format
	APIVersion string `json:"api_version" api:"required"`
	// When the event was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// Unified payload for message webhooks when using `webhook_version: "2026-02-03"`.
	//
	// This schema is used for message.sent, message.received, message.delivered, and
	// message.read events when the subscription URL includes `?version=2026-02-03`.
	//
	// Key differences from V1 (2025-01-01):
	//
	//   - `direction`: "inbound" or "outbound" instead of `is_from_me` boolean
	//   - `sender_handle`: Full handle object for the sender
	//   - `chat`: Nested object with `id`, `is_group`, and `owner_handle`
	//   - Message fields (`id`, `parts`, `effect`, etc.) are at the top level, not
	//     nested in `message`
	//
	// Timestamps indicate the message state:
	//
	// - `message.sent`: sent_at set, delivered_at=null, read_at=null
	// - `message.received`: sent_at set, delivered_at=null, read_at=null
	// - `message.delivered`: sent_at set, delivered_at set, read_at=null
	// - `message.read`: sent_at set, delivered_at set, read_at set
	Data MessageEventV2 `json:"data" api:"required"`
	// Unique identifier for this event (for deduplication)
	EventID string `json:"event_id" api:"required" format:"uuid"`
	// Valid webhook event types that can be subscribed to.
	//
	// **Note:** `message.edited` is only delivered to subscriptions using
	// `webhook_version: "2026-02-03"`. Subscribing to this event on a v2025
	// subscription will not produce any deliveries.
	//
	// Any of "message.sent", "message.received", "message.read", "message.delivered",
	// "message.failed", "message.edited", "reaction.added", "reaction.removed",
	// "poll.received", "poll.failed", "poll.sent", "poll.delivered", "poll.read",
	// "poll.updated", "poll.vote.added", "poll.vote.removed", "poll.reaction.added",
	// "participant.added", "participant.removed", "chat.created",
	// "chat.group_name_updated", "chat.group_icon_updated",
	// "chat.group_name_update_failed", "chat.group_icon_update_failed",
	// "chat.background_updated", "chat.background_update_failed",
	// "chat.typing_indicator.started", "chat.typing_indicator.stopped",
	// "phone_number.status_updated", "contact_card.received", "call.initiated",
	// "call.ringing", "call.answered", "call.ended", "call.failed", "call.declined",
	// "call.no_answer", "location.sharing.started", "location.sharing.stopped",
	// "payment.succeeded", "payment.canceled", "payment.expired", "payment.declined",
	// "payment.authorized", "connection.created", "connection.revoked".
	EventType WebhookEventType `json:"event_type" api:"required"`
	// Partner identifier. Present on all webhooks for cross-referencing.
	PartnerID string `json:"partner_id" api:"required"`
	// Trace ID for debugging and correlation across systems.
	TraceID string `json:"trace_id" api:"required"`
	// Date-based webhook payload version. Determined by the `?version=` query
	// parameter in your webhook subscription URL. If no version parameter is
	// specified, defaults based on subscription creation date.
	WebhookVersion string `json:"webhook_version" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		APIVersion     respjson.Field
		CreatedAt      respjson.Field
		Data           respjson.Field
		EventID        respjson.Field
		EventType      respjson.Field
		PartnerID      respjson.Field
		TraceID        respjson.Field
		WebhookVersion respjson.Field
		ExtraFields    map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Complete webhook payload for message.received events (2026-02-03 format)

func (MessageReceivedWebhookEvent) RawJSON added in v0.12.0

func (r MessageReceivedWebhookEvent) RawJSON() string

Returns the unmodified JSON received from the API

func (*MessageReceivedWebhookEvent) UnmarshalJSON added in v0.12.0

func (r *MessageReceivedWebhookEvent) UnmarshalJSON(data []byte) error

type MessageSentWebhookEvent added in v0.12.0

type MessageSentWebhookEvent struct {
	// API version for the webhook payload format
	APIVersion string `json:"api_version" api:"required"`
	// When the event was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// Unified payload for message webhooks when using `webhook_version: "2026-02-03"`.
	//
	// This schema is used for message.sent, message.received, message.delivered, and
	// message.read events when the subscription URL includes `?version=2026-02-03`.
	//
	// Key differences from V1 (2025-01-01):
	//
	//   - `direction`: "inbound" or "outbound" instead of `is_from_me` boolean
	//   - `sender_handle`: Full handle object for the sender
	//   - `chat`: Nested object with `id`, `is_group`, and `owner_handle`
	//   - Message fields (`id`, `parts`, `effect`, etc.) are at the top level, not
	//     nested in `message`
	//
	// Timestamps indicate the message state:
	//
	// - `message.sent`: sent_at set, delivered_at=null, read_at=null
	// - `message.received`: sent_at set, delivered_at=null, read_at=null
	// - `message.delivered`: sent_at set, delivered_at set, read_at=null
	// - `message.read`: sent_at set, delivered_at set, read_at set
	Data MessageEventV2 `json:"data" api:"required"`
	// Unique identifier for this event (for deduplication)
	EventID string `json:"event_id" api:"required" format:"uuid"`
	// Valid webhook event types that can be subscribed to.
	//
	// **Note:** `message.edited` is only delivered to subscriptions using
	// `webhook_version: "2026-02-03"`. Subscribing to this event on a v2025
	// subscription will not produce any deliveries.
	//
	// Any of "message.sent", "message.received", "message.read", "message.delivered",
	// "message.failed", "message.edited", "reaction.added", "reaction.removed",
	// "poll.received", "poll.failed", "poll.sent", "poll.delivered", "poll.read",
	// "poll.updated", "poll.vote.added", "poll.vote.removed", "poll.reaction.added",
	// "participant.added", "participant.removed", "chat.created",
	// "chat.group_name_updated", "chat.group_icon_updated",
	// "chat.group_name_update_failed", "chat.group_icon_update_failed",
	// "chat.background_updated", "chat.background_update_failed",
	// "chat.typing_indicator.started", "chat.typing_indicator.stopped",
	// "phone_number.status_updated", "contact_card.received", "call.initiated",
	// "call.ringing", "call.answered", "call.ended", "call.failed", "call.declined",
	// "call.no_answer", "location.sharing.started", "location.sharing.stopped",
	// "payment.succeeded", "payment.canceled", "payment.expired", "payment.declined",
	// "payment.authorized", "connection.created", "connection.revoked".
	EventType WebhookEventType `json:"event_type" api:"required"`
	// Partner identifier. Present on all webhooks for cross-referencing.
	PartnerID string `json:"partner_id" api:"required"`
	// Trace ID for debugging and correlation across systems.
	TraceID string `json:"trace_id" api:"required"`
	// Date-based webhook payload version. Determined by the `?version=` query
	// parameter in your webhook subscription URL. If no version parameter is
	// specified, defaults based on subscription creation date.
	WebhookVersion string `json:"webhook_version" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		APIVersion     respjson.Field
		CreatedAt      respjson.Field
		Data           respjson.Field
		EventID        respjson.Field
		EventType      respjson.Field
		PartnerID      respjson.Field
		TraceID        respjson.Field
		WebhookVersion respjson.Field
		ExtraFields    map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Complete webhook payload for message.sent events (2026-02-03 format)

func (MessageSentWebhookEvent) RawJSON added in v0.12.0

func (r MessageSentWebhookEvent) RawJSON() string

Returns the unmodified JSON received from the API

func (*MessageSentWebhookEvent) UnmarshalJSON added in v0.12.0

func (r *MessageSentWebhookEvent) UnmarshalJSON(data []byte) error

type MessageService

type MessageService struct {
	Options []option.RequestOption
	// Messages are individual communications within a chat thread.
	//
	// Messages can include text, media attachments, rich link previews, special
	// effects (like confetti or fireworks), and reactions. All messages are associated
	// with a specific chat and sent from a phone number you own.
	//
	// Messages support delivery status tracking, read receipts, and editing
	// capabilities.
	//
	// ## Rich Link Previews
	//
	// Send a URL as a `link` part to deliver it with a rich preview card showing the
	// page's title, description, and image (when available). A `link` part must be the
	// **only** part in the message — it cannot be combined with text or media parts.
	// To send a URL without a preview card, include it in a `text` part instead.
	//
	// **Limitations:**
	//
	// - A `link` part cannot be combined with other parts in the same message.
	// - Maximum URL length: 2,048 characters.
	//
	// ## App Clips
	//
	// An `app_clip` part sends a **registered App Clip** — not only Linq's Apple Pay
	// checkout, but any partner's own App Clip. Like a `link` part it must be the
	// **only** part in the message, and it is **iMessage only** — it never downgrades
	// to SMS or RCS. The payment-checkout use of this part is covered in the
	// **Payments** section.
	//
	// ## Ephemeral Messages (Privacy Tier)
	//
	// For regulated or sensitive conversations, opt in to the **ephemeral messages**
	// tier by contacting your Linq support contact. When enabled, every message on the
	// covered phone numbers is given a **retention window configured for your
	// account**. After that window, the message's text, formatting, and attachment
	// references are no longer retrievable through the API — see the Attachments row
	// below for how the attachment media itself is handled. Metadata about the message
	// is retained: message identifiers, timestamps, phone numbers, and delivery state.
	// Metadata retention is not bounded by this window. Bounded operational copies,
	// such as backups and delivery queues, expire on their own separate schedules.
	// There is no per-message flag; ephemerality is applied automatically based on
	// your configuration.
	//
	// The window can be set anywhere from **60 minutes to 24 hours**, and defaults to
	// **24 hours**. Ask your Linq support contact to configure a shorter window; it
	// cannot be changed through the API.
	//
	// You can request it at two scopes:
	//
	// | Scope                | Effect                                                                                                                                                                       |
	// | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
	// | **Partner-wide**     | Every outbound and inbound message on every phone number under your account has its content removed from the API surface after your configured window. Metadata is retained. |
	// | **Per phone number** | Only the specified phone numbers have message content removed from the API surface this way. The rest follow the standard message-retention policy.                          |
	//
	// **Behavioral differences vs the standard default:**
	//
	// | Aspect                  | Standard                                           | Ephemeral                                                                                                                                                                                                                                                                                                                                   |
	// | ----------------------- | -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
	// | Retention               | Retained per the standard message-retention policy | **Hard backstop: your configured window** (60 minutes – 24 hours, default 24 hours) from when the message is created                                                                                                                                                                                                                        |
	// | After expiry            | Message stays retrievable                          | Message content is no longer retrievable — `GET /v3/messages/{messageId}` returns `404` and it no longer appears in `GET /v3/chats/{chatId}/messages`                                                                                                                                                                                       |
	// | Content on expiry       | N/A                                                | Text, formatting, and attachment references are removed from the API surface, not blanked out in place. Metadata (identifiers, timestamps, phone numbers, delivery state) is retained; its retention is not bounded by this window                                                                                                          |
	// | Attachments             | Retained                                           | Media sent on the **ephemeral attachments tier** is removed on its own storage backstop — within roughly 24–48 hours of upload — independently of the message window, so it can outlast a window shorter than a day. Attachments on the persistent tier (including pre-uploads via `POST /v3/attachments`) are kept until you `DELETE` them |
	// | Cross-partner isolation | Enforced                                           | Enforced                                                                                                                                                                                                                                                                                                                                    |
	//
	// **How the retention window works:**
	//
	//   - The window runs from **message creation** (`created_at`). It is configured for
	//     your account (60 minutes – 24 hours, default 24 hours) and cannot be set per
	//     message.
	//   - Attachment media follows its own storage backstop rather than the message
	//     window — see the Attachments row above.
	//   - Expiry is delivery-independent — the clock starts when the message is created,
	//     not when it is delivered or read.
	//   - **Deletion happens shortly _after_ the window, not exactly at it.** A
	//     background sweep runs every ~5 minutes, so a message typically stops being
	//     retrievable within about 5 minutes of its expiry, and longer while a backlog
	//     is being worked through. Treat the window as the guaranteed _minimum_
	//     retention, never as an exact deletion time or an upper bound.
	//
	// **What you observe:**
	//
	//   - **No expiry timestamp is exposed.** API responses and webhook payloads do not
	//     include the deletion time, and they do not report your configured window
	//     either — so if you are on a window shorter than 24 hours you cannot derive a
	//     message's expiry from the API today. Track the window you agreed with your
	//     Linq support contact and compute `created_at + window` yourself.
	//   - **No deletion webhook is sent.** There is no `message.deleted` event — a
	//     message simply stops being retrievable once its window passes.
	//   - **The attachment backstop is separate from the message window.** API
	//     retrievability (the `404` behavior above) ends at your configured window.
	//     Ephemeral-tier media objects are removed on their own storage backstop —
	//     within roughly 24–48 hours of upload — which is independent of the message
	//     window and can outlast a window shorter than a day. Removal of the
	//     corresponding entries from the sending device happens asynchronously and can
	//     complete after the backstop.
	//   - **Delivery is unaffected.** Ephemeral messages send, deliver, and fire the
	//     usual `message.sent` / `message.received` and status webhooks exactly like
	//     standard messages. Only retention changes.
	//
	// **When to choose ephemeral:**
	//
	//   - You have a compliance requirement that the platform must not retain message
	//     content beyond a short window.
	//   - The conversation is high-sensitivity (PHI, financial, identity verification)
	//     and you do not want it sitting in storage long-term.
	//   - Your application is the system of record — you capture what you need from the
	//     delivery webhook in real time and do not rely on reading message history back
	//     from Linq later.
	//
	// **Important:** ephemeral applies in _both directions_ — messages you send
	// **and** messages received by the phone numbers in that scope. Because Linq can
	// no longer return the message once its window passes, persist anything you need
	// to keep from the webhook payload at the time it is delivered.
	Poll MessagePollService
}

Messages are individual communications within a chat thread.

Messages can include text, media attachments, rich link previews, special effects (like confetti or fireworks), and reactions. All messages are associated with a specific chat and sent from a phone number you own.

Messages support delivery status tracking, read receipts, and editing capabilities.

## Rich Link Previews

Send a URL as a `link` part to deliver it with a rich preview card showing the page's title, description, and image (when available). A `link` part must be the **only** part in the message — it cannot be combined with text or media parts. To send a URL without a preview card, include it in a `text` part instead.

**Limitations:**

- A `link` part cannot be combined with other parts in the same message. - Maximum URL length: 2,048 characters.

## App Clips

An `app_clip` part sends a **registered App Clip** — not only Linq's Apple Pay checkout, but any partner's own App Clip. Like a `link` part it must be the **only** part in the message, and it is **iMessage only** — it never downgrades to SMS or RCS. The payment-checkout use of this part is covered in the **Payments** section.

## Ephemeral Messages (Privacy Tier)

For regulated or sensitive conversations, opt in to the **ephemeral messages** tier by contacting your Linq support contact. When enabled, every message on the covered phone numbers is given a **retention window configured for your account**. After that window, the message's text, formatting, and attachment references are no longer retrievable through the API — see the Attachments row below for how the attachment media itself is handled. Metadata about the message is retained: message identifiers, timestamps, phone numbers, and delivery state. Metadata retention is not bounded by this window. Bounded operational copies, such as backups and delivery queues, expire on their own separate schedules. There is no per-message flag; ephemerality is applied automatically based on your configuration.

The window can be set anywhere from **60 minutes to 24 hours**, and defaults to **24 hours**. Ask your Linq support contact to configure a shorter window; it cannot be changed through the API.

You can request it at two scopes:

| Scope | Effect | | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Partner-wide** | Every outbound and inbound message on every phone number under your account has its content removed from the API surface after your configured window. Metadata is retained. | | **Per phone number** | Only the specified phone numbers have message content removed from the API surface this way. The rest follow the standard message-retention policy. |

**Behavioral differences vs the standard default:**

| Aspect | Standard | Ephemeral | | ----------------------- | -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Retention | Retained per the standard message-retention policy | **Hard backstop: your configured window** (60 minutes – 24 hours, default 24 hours) from when the message is created | | After expiry | Message stays retrievable | Message content is no longer retrievable — `GET /v3/messages/{messageId}` returns `404` and it no longer appears in `GET /v3/chats/{chatId}/messages` | | Content on expiry | N/A | Text, formatting, and attachment references are removed from the API surface, not blanked out in place. Metadata (identifiers, timestamps, phone numbers, delivery state) is retained; its retention is not bounded by this window | | Attachments | Retained | Media sent on the **ephemeral attachments tier** is removed on its own storage backstop — within roughly 24–48 hours of upload — independently of the message window, so it can outlast a window shorter than a day. Attachments on the persistent tier (including pre-uploads via `POST /v3/attachments`) are kept until you `DELETE` them | | Cross-partner isolation | Enforced | Enforced |

**How the retention window works:**

  • The window runs from **message creation** (`created_at`). It is configured for your account (60 minutes – 24 hours, default 24 hours) and cannot be set per message.
  • Attachment media follows its own storage backstop rather than the message window — see the Attachments row above.
  • Expiry is delivery-independent — the clock starts when the message is created, not when it is delivered or read.
  • **Deletion happens shortly _after_ the window, not exactly at it.** A background sweep runs every ~5 minutes, so a message typically stops being retrievable within about 5 minutes of its expiry, and longer while a backlog is being worked through. Treat the window as the guaranteed _minimum_ retention, never as an exact deletion time or an upper bound.

**What you observe:**

  • **No expiry timestamp is exposed.** API responses and webhook payloads do not include the deletion time, and they do not report your configured window either — so if you are on a window shorter than 24 hours you cannot derive a message's expiry from the API today. Track the window you agreed with your Linq support contact and compute `created_at + window` yourself.
  • **No deletion webhook is sent.** There is no `message.deleted` event — a message simply stops being retrievable once its window passes.
  • **The attachment backstop is separate from the message window.** API retrievability (the `404` behavior above) ends at your configured window. Ephemeral-tier media objects are removed on their own storage backstop — within roughly 24–48 hours of upload — which is independent of the message window and can outlast a window shorter than a day. Removal of the corresponding entries from the sending device happens asynchronously and can complete after the backstop.
  • **Delivery is unaffected.** Ephemeral messages send, deliver, and fire the usual `message.sent` / `message.received` and status webhooks exactly like standard messages. Only retention changes.

**When to choose ephemeral:**

  • You have a compliance requirement that the platform must not retain message content beyond a short window.
  • The conversation is high-sensitivity (PHI, financial, identity verification) and you do not want it sitting in storage long-term.
  • Your application is the system of record — you capture what you need from the delivery webhook in real time and do not rely on reading message history back from Linq later.

**Important:** ephemeral applies in _both directions_ — messages you send **and** messages received by the phone numbers in that scope. Because Linq can no longer return the message once its window passes, persist anything you need to keep from the webhook payload at the time it is delivered.

MessageService contains methods and other services that help with interacting with the linq-api-v3 API.

Note, unlike clients, this service does not read variables from the environment automatically. You should not instantiate this service directly, and instead use the NewMessageService method instead.

func NewMessageService

func NewMessageService(opts ...option.RequestOption) (r MessageService)

NewMessageService generates a new service that applies the given options to each request. These options are applied after the parent client's options (if there is one), and before any request-specific options.

func (*MessageService) AddReaction

func (r *MessageService) AddReaction(ctx context.Context, messageID string, body MessageAddReactionParams, opts ...option.RequestOption) (res *MessageAddReactionResponse, err error)

Add or remove emoji reactions to messages. Reactions let users express their response to a message without sending a new message.

**Supported Reactions:**

- love ❤️ - like 👍 - dislike 👎 - laugh 😂 - emphasize ‼️ - question ❓ - custom - any emoji (use `custom_emoji` field to specify) - sticker - an image peeled onto the message (use `url` or `attachment_id`)

**Stickers** are iMessage-only and cannot be removed — iMessage has no unpeel operation, so `operation: "remove"` with `type: "sticker"` is rejected. Position, size and rotation are optional via `placement`, and can be changed afterwards with `PATCH /v3/messages/{messageId}/reactions/{reactionId}`.

func (*MessageService) Delete

func (r *MessageService) Delete(ctx context.Context, messageID string, opts ...option.RequestOption) (err error)

Deletes a message from the Linq API only. This does NOT unsend or remove the message from the actual chat — recipients will still see the message. Re-sending with a deleted message's idempotency key returns 404 — a deleted message is never resent.

func (*MessageService) Get

func (r *MessageService) Get(ctx context.Context, messageID string, opts ...option.RequestOption) (res *Message, err error)

Retrieve a specific message by its ID. This endpoint returns the full message details including text, attachments, reactions, and metadata.

func (*MessageService) ListMessagesThread added in v0.2.0

func (r *MessageService) ListMessagesThread(ctx context.Context, messageID string, query MessageListMessagesThreadParams, opts ...option.RequestOption) (res *pagination.ListMessagesPagination[Message], err error)

Retrieve all messages in a conversation thread. Given any message ID in the thread, returns the originator message and all replies in chronological order.

If the message is not part of a thread, returns just that single message.

Supports pagination and configurable ordering.

func (*MessageService) ListMessagesThreadAutoPaging added in v0.2.0

Retrieve all messages in a conversation thread. Given any message ID in the thread, returns the originator message and all replies in chronological order.

If the message is not part of a thread, returns just that single message.

Supports pagination and configurable ordering.

func (*MessageService) New added in v0.26.1

Send a message to one or more recipients **without supplying a `from` number**. Linq resolves both the sending line and the target chat for you, then returns exactly which line was used, which chat the message landed in, whether a new chat was created, and every resulting message id.

This fuses "create chat" and "send message" behind a single message-centric resource. Provide only the recipients (`to`) and the `message`; the platform decides the rest.

## How the from-number and chat are chosen

  • **Reuse** — if a chat with exactly these recipients already exists on a line that can still send, the message is sent into that chat on its existing line (`from_selection.reason = reused_active_chat`). The most-recently-active such chat wins; chats stranded on flagged lines (e.g. by an earlier failover) are skipped.
  • **New** — if no such chat exists, a new chat is created on the best available line (`from_selection.reason = new_best_number`).
  • **Failover** — if matching chats exist but none is on a line that can send, a **new** chat is created on a fresh best line and the flagged chat is abandoned (`from_selection.reason = failover_flagged`, `previous_chat_id` set). If you supply `continuation_message`, that text is sent as the single message INSTEAD of `message` (useful as a fresh-number-appropriate opener). Exactly one message is sent either way.

Recipients (`to`) are an order-independent set: a single handle is a direct chat, multiple handles a group chat.

## Excluding lines

`exclude_from` keeps specific lines out of **this** send's line pick. It only affects picking a line for a new chat — an existing chat is always reused on its own line, preferring a chat on a non-excluded line when the recipients have more than one. An exclusion never abandons a live chat or moves it to a new number, so if the only chat these recipients have is on an excluded line, that chat is still used. `from` tells you the line that was actually used.

## Differences from POST /v3/chats

  • The first message **may contain a link** (including for a newly created chat). Note: sending a link as the very first message on a freshly selected line can elevate that line's flagging risk — it is allowed, not recommended.
  • Voice memos are **not** supported here. To send an iMessage voice-memo bubble, use `POST /v3/chats/{chatId}/voicememo` with a known chat id.

## Service preference, effects, decorations

Set `message.preferred_service` (`iMessage` | `RCS` | `SMS`), `message.effect`, and per-part `text_decorations` exactly as on the other send endpoints.

Always responds `202 Accepted` — chat creation is incidental to the send.

func (*MessageService) Update added in v0.3.0

func (r *MessageService) Update(ctx context.Context, messageID string, body MessageUpdateParams, opts ...option.RequestOption) (res *Message, err error)

Edit the text content of a specific part of a previously sent message.

**Note:** A message can be edited up to 5 times, and only within 15 minutes of when it was originally sent.

func (*MessageService) UpdateAppCard added in v0.26.1

func (r *MessageService) UpdateAppCard(ctx context.Context, messageID string, body MessageUpdateAppCardParams, opts ...option.RequestOption) (res *MessageUpdateAppCardResponse, err error)

Replaces a previously delivered `imessage_app` card on the recipient's screen with new content, instead of posting a new bubble (like a game move redrawing the board).

The update is delivered as a **new message** with its own id and delivery lifecycle (`message.sent` / `message.delivered` / `message.failed` webhooks fire for the new id). To update the card again, reference the message id returned by this call.

Constraints:

  • The referenced message must be an `imessage_app` card sent by you (`400` otherwise — inbound cards cannot be updated).
  • The referenced card must already be delivered (`409` otherwise — retry after the `message.delivered` webhook for it).
  • The app identity (`team_id`, `bundle_id`, name) is inherited from the original card and cannot change; only `url`, `fallback_text`, and `layout` are replaced.
  • iMessage-only, like all app cards.
  • Concurrent updates against the same card are not serialized server-side; the last one delivered wins on the recipient's screen. Serialize updates by always referencing the message id returned by the previous call.

func (*MessageService) UpdateStickerPlacement added in v0.51.0

func (r *MessageService) UpdateStickerPlacement(ctx context.Context, reactionID string, params MessageUpdateStickerPlacementParams, opts ...option.RequestOption) (res *MessageUpdateStickerPlacementResponse, err error)

Move, resize or rotate a sticker that has already been peeled onto a message. The change is sent to every device in the conversation, exactly as dragging the sticker by hand would.

Only stickers can be repositioned — a tapback has no placement, so a non-sticker `reactionId` is rejected. Any field omitted from `placement` keeps its current value.

`reactionId` is the `id` from the reaction on the message, or from the `reaction.added` webhook. Stickers stack, so this id is what distinguishes one sticker from another on the same message.

Stickers peeled before this endpoint existed cannot be moved: addressing one requires an identifier that was not recorded at the time, and it returns 404.

type MessageUpdateAppCardParams added in v0.26.1

type MessageUpdateAppCardParams struct {
	// Visible layout of the card. At least one of `caption`, `subcaption`,
	// `trailing_caption`, `trailing_subcaption`, or `image_url` must be set, otherwise
	// the card renders as an empty bubble.
	//
	// `image_url` displays a preview image at the top of the card. The image renders
	// on the recipient's card whether or not they have your app installed. The small
	// icon beside the caption is the app's own icon and is not settable here.
	//
	// `* Note - requires a trusted chat w/ inbound activity`
	//
	// `image_title` and `image_subtitle` render as text overlaid on the image (title
	// bold, subtitle beneath it). They only appear when `image_url` is set — without
	// an image there is nothing to overlay — so setting either without `image_url` is
	// rejected.
	Layout MessageUpdateAppCardParamsLayout `json:"layout,omitzero" api:"required"`
	// Text shown on surfaces that cannot render the card (notifications, lock screen).
	// Defaults to the caption when omitted.
	FallbackText param.Opt[string] `json:"fallback_text,omitzero"`
	// Whether the updated card renders as your app's interactive balloon for
	// recipients who have your iMessage app installed. `true` (default) lets your
	// installed extension draw its live view; `false` always shows the static `layout`
	// card. Recipients without your app always see the static card regardless of this
	// flag.
	//
	// Defaults to `true` when omitted — it is **not** inherited from the original
	// card. To keep a card static across updates, re-send `interactive: false` on each
	// update.
	Interactive param.Opt[bool] `json:"interactive,omitzero"`
	// URL the recipient's app opens when they tap the updated card.
	//
	// Mutually exclusive with `experience` and `raw_payload_data`.
	URL param.Opt[string] `json:"url,omitzero" format:"uri"`
	// Identifies the iMessage app (Messages app extension) that backs the card.
	App MessageUpdateAppCardParamsApp `json:"app,omitzero"`
	// Invokes an action on an experience — a third party that renders inside Linq's
	// iMessage app. Linq resolves the recipient's connection, mints any session the
	// action needs, composes the card and sends it; none of that is visible to you.
	//
	// Call `GET /v3/experiences/{experience}` for the actions you may invoke and the
	// fields each accepts.
	Experience MessageUpdateAppCardParamsExperience `json:"experience,omitzero"`
	// contains filtered or unexported fields
}

func (MessageUpdateAppCardParams) MarshalJSON added in v0.26.1

func (r MessageUpdateAppCardParams) MarshalJSON() (data []byte, err error)

func (*MessageUpdateAppCardParams) UnmarshalJSON added in v0.26.1

func (r *MessageUpdateAppCardParams) UnmarshalJSON(data []byte) error

type MessageUpdateAppCardParamsApp added in v0.55.0

type MessageUpdateAppCardParamsApp struct {
	// Bundle identifier of the Messages app extension. Must not contain `:`.
	BundleID string `json:"bundle_id" api:"required"`
	// Display name of the app, shown by Messages' fallback UI.
	Name string `json:"name" api:"required"`
	// The app's 10-character uppercase alphanumeric team identifier.
	TeamID string `json:"team_id" api:"required"`
	// The owning app's App Store id (optional). When set, recipients without the
	// iMessage app installed see a "Get the app" affordance.
	AppStoreID param.Opt[int64] `json:"app_store_id,omitzero"`
	// contains filtered or unexported fields
}

Identifies the iMessage app (Messages app extension) that backs the card.

The properties BundleID, Name, TeamID are required.

func (MessageUpdateAppCardParamsApp) MarshalJSON added in v0.55.0

func (r MessageUpdateAppCardParamsApp) MarshalJSON() (data []byte, err error)

func (*MessageUpdateAppCardParamsApp) UnmarshalJSON added in v0.55.0

func (r *MessageUpdateAppCardParamsApp) UnmarshalJSON(data []byte) error

type MessageUpdateAppCardParamsExperience added in v0.31.0

type MessageUpdateAppCardParamsExperience struct {
	// Which of its actions, e.g. `attach_card`.
	Action string `json:"action" api:"required"`
	// The experience to invoke, e.g. `agentcard` or `agentpay`.
	Name string `json:"name" api:"required"`
	// Values for the fields this action exposes. Keys are exactly the field names
	// listed for the action — no mapping, no nesting.
	//
	// Display copy only, except a `url`-type field — that value sets the destination,
	// and must be an absolute `https` URL.
	//
	// Some fields are read rather than sent: `agentpay`'s `request_payment` takes only
	// a `checkout_url` and resolves the amount and reason from that payment request
	// itself, so the card cannot state a figure the checkout will not charge.
	Params map[string]any `json:"params,omitzero"`
	// contains filtered or unexported fields
}

Invokes an action on an experience — a third party that renders inside Linq's iMessage app. Linq resolves the recipient's connection, mints any session the action needs, composes the card and sends it; none of that is visible to you.

Call `GET /v3/experiences/{experience}` for the actions you may invoke and the fields each accepts.

The properties Action, Name are required.

func (MessageUpdateAppCardParamsExperience) MarshalJSON added in v0.31.0

func (r MessageUpdateAppCardParamsExperience) MarshalJSON() (data []byte, err error)

func (*MessageUpdateAppCardParamsExperience) UnmarshalJSON added in v0.31.0

func (r *MessageUpdateAppCardParamsExperience) UnmarshalJSON(data []byte) error

type MessageUpdateAppCardParamsLayout added in v0.26.1

type MessageUpdateAppCardParamsLayout struct {
	// Primary label, top-left and bold.
	Caption param.Opt[string] `json:"caption,omitzero"`
	// Text shown below `image_title`, overlaid on the card image. Requires
	// `image_url`.
	ImageSubtitle param.Opt[string] `json:"image_subtitle,omitzero"`
	// Bold text overlaid on the card image. Requires `image_url` (rejected without
	// it).
	ImageTitle param.Opt[string] `json:"image_title,omitzero"`
	// URL of an image (JPEG, PNG, HEIF, or WebP) to display as the card's preview
	// image; an unreachable or non-image URL returns a validation error. Renders for
	// all recipients regardless of whether they have the app. Note - requires a
	// trusted chat w/ inbound activity. In responses, this is the re-hosted
	// `cdn.linqapp.com` copy of the image you supplied, not your original URL.
	ImageURL param.Opt[string] `json:"image_url,omitzero" format:"uri"`
	// Secondary label, below `caption` on the left.
	Subcaption param.Opt[string] `json:"subcaption,omitzero"`
	// Label shown top-right.
	TrailingCaption param.Opt[string] `json:"trailing_caption,omitzero"`
	// Label shown below `trailing_caption`, on the right.
	TrailingSubcaption param.Opt[string] `json:"trailing_subcaption,omitzero"`
	// contains filtered or unexported fields
}

Visible layout of the card. At least one of `caption`, `subcaption`, `trailing_caption`, `trailing_subcaption`, or `image_url` must be set, otherwise the card renders as an empty bubble.

`image_url` displays a preview image at the top of the card. The image renders on the recipient's card whether or not they have your app installed. The small icon beside the caption is the app's own icon and is not settable here.

`* Note - requires a trusted chat w/ inbound activity`

`image_title` and `image_subtitle` render as text overlaid on the image (title bold, subtitle beneath it). They only appear when `image_url` is set — without an image there is nothing to overlay — so setting either without `image_url` is rejected.

func (MessageUpdateAppCardParamsLayout) MarshalJSON added in v0.26.1

func (r MessageUpdateAppCardParamsLayout) MarshalJSON() (data []byte, err error)

func (*MessageUpdateAppCardParamsLayout) UnmarshalJSON added in v0.26.1

func (r *MessageUpdateAppCardParamsLayout) UnmarshalJSON(data []byte) error

type MessageUpdateAppCardResponse added in v0.26.1

type MessageUpdateAppCardResponse struct {
	// Unique identifier of the chat this message was sent to
	ChatID string `json:"chat_id" api:"required" format:"uuid"`
	// A message that was sent (used in CreateChat and SendMessage responses)
	Message SentMessage `json:"message" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ChatID      respjson.Field
		Message     respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Response for sending a message to a chat

func (MessageUpdateAppCardResponse) RawJSON added in v0.26.1

Returns the unmodified JSON received from the API

func (*MessageUpdateAppCardResponse) UnmarshalJSON added in v0.26.1

func (r *MessageUpdateAppCardResponse) UnmarshalJSON(data []byte) error

type MessageUpdateParams added in v0.3.0

type MessageUpdateParams struct {
	// New text content for the message part
	Text string `json:"text" api:"required"`
	// Index of the message part to edit. Defaults to 0.
	PartIndex param.Opt[int64] `json:"part_index,omitzero"`
	// contains filtered or unexported fields
}

func (MessageUpdateParams) MarshalJSON added in v0.3.0

func (r MessageUpdateParams) MarshalJSON() (data []byte, err error)

func (*MessageUpdateParams) UnmarshalJSON added in v0.3.0

func (r *MessageUpdateParams) UnmarshalJSON(data []byte) error

type MessageUpdateStickerPlacementParams added in v0.51.0

type MessageUpdateStickerPlacementParams struct {
	MessageID string `path:"messageId" api:"required" format:"uuid" json:"-"`
	// Optional position, size and rotation of a sticker on the target bubble. Only
	// valid when type is "sticker".
	//
	// Every field is independent and optional — omit the object entirely, or any field
	// within it, to keep the default (centred, default size, unrotated).
	Placement MessageUpdateStickerPlacementParamsPlacement `json:"placement,omitzero" api:"required"`
	// contains filtered or unexported fields
}

func (MessageUpdateStickerPlacementParams) MarshalJSON added in v0.51.0

func (r MessageUpdateStickerPlacementParams) MarshalJSON() (data []byte, err error)

func (*MessageUpdateStickerPlacementParams) UnmarshalJSON added in v0.51.0

func (r *MessageUpdateStickerPlacementParams) UnmarshalJSON(data []byte) error

type MessageUpdateStickerPlacementParamsPlacement added in v0.51.0

type MessageUpdateStickerPlacementParamsPlacement struct {
	// Clockwise rotation in degrees.
	Rotation param.Opt[float64] `json:"rotation,omitzero"`
	// Size relative to the default, where 1 matches the size a sticker gets natively.
	//
	// Values outside 0.5–1.5 are clamped rather than rejected. The upper bound keeps a
	// sticker within the size range iMessage itself displays: its own limit is larger,
	// but that allowance assumes the transparent padding Apple's stickers carry, which
	// a full-bleed image does not have.
	//
	// Scale is linear, so 1.5 is a little over twice the area.
	Scale param.Opt[float64] `json:"scale,omitzero"`
	// Horizontal position on the target bubble, from -1 (far left) to 1 (far right). 0
	// is centred.
	X param.Opt[float64] `json:"x,omitzero"`
	// Vertical position on the target bubble, from -1 (top) to 1 (bottom). 0 is
	// centred.
	Y param.Opt[float64] `json:"y,omitzero"`
	// contains filtered or unexported fields
}

Optional position, size and rotation of a sticker on the target bubble. Only valid when type is "sticker".

Every field is independent and optional — omit the object entirely, or any field within it, to keep the default (centred, default size, unrotated).

func (MessageUpdateStickerPlacementParamsPlacement) MarshalJSON added in v0.51.0

func (r MessageUpdateStickerPlacementParamsPlacement) MarshalJSON() (data []byte, err error)

func (*MessageUpdateStickerPlacementParamsPlacement) UnmarshalJSON added in v0.51.0

func (r *MessageUpdateStickerPlacementParamsPlacement) UnmarshalJSON(data []byte) error

type MessageUpdateStickerPlacementResponse added in v0.51.0

type MessageUpdateStickerPlacementResponse struct {
	Status  string `json:"status"`
	Success bool   `json:"success"`
	TraceID string `json:"trace_id"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Status      respjson.Field
		Success     respjson.Field
		TraceID     respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (MessageUpdateStickerPlacementResponse) RawJSON added in v0.51.0

Returns the unmodified JSON received from the API

func (*MessageUpdateStickerPlacementResponse) UnmarshalJSON added in v0.51.0

func (r *MessageUpdateStickerPlacementResponse) UnmarshalJSON(data []byte) error

type ParticipantAddedWebhookEvent added in v0.12.0

type ParticipantAddedWebhookEvent struct {
	// API version for the webhook payload format
	APIVersion string `json:"api_version" api:"required"`
	// When the event was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// Payload for participant.added webhook events
	Data ParticipantAddedWebhookEventData `json:"data" api:"required"`
	// Unique identifier for this event (for deduplication)
	EventID string `json:"event_id" api:"required" format:"uuid"`
	// Valid webhook event types that can be subscribed to.
	//
	// **Note:** `message.edited` is only delivered to subscriptions using
	// `webhook_version: "2026-02-03"`. Subscribing to this event on a v2025
	// subscription will not produce any deliveries.
	//
	// Any of "message.sent", "message.received", "message.read", "message.delivered",
	// "message.failed", "message.edited", "reaction.added", "reaction.removed",
	// "poll.received", "poll.failed", "poll.sent", "poll.delivered", "poll.read",
	// "poll.updated", "poll.vote.added", "poll.vote.removed", "poll.reaction.added",
	// "participant.added", "participant.removed", "chat.created",
	// "chat.group_name_updated", "chat.group_icon_updated",
	// "chat.group_name_update_failed", "chat.group_icon_update_failed",
	// "chat.background_updated", "chat.background_update_failed",
	// "chat.typing_indicator.started", "chat.typing_indicator.stopped",
	// "phone_number.status_updated", "contact_card.received", "call.initiated",
	// "call.ringing", "call.answered", "call.ended", "call.failed", "call.declined",
	// "call.no_answer", "location.sharing.started", "location.sharing.stopped",
	// "payment.succeeded", "payment.canceled", "payment.expired", "payment.declined",
	// "payment.authorized", "connection.created", "connection.revoked".
	EventType WebhookEventType `json:"event_type" api:"required"`
	// Partner identifier. Present on all webhooks for cross-referencing.
	PartnerID string `json:"partner_id" api:"required"`
	// Trace ID for debugging and correlation across systems.
	TraceID string `json:"trace_id" api:"required"`
	// Date-based webhook payload version. Determined by the `?version=` query
	// parameter in your webhook subscription URL. If no version parameter is
	// specified, defaults based on subscription creation date.
	WebhookVersion string `json:"webhook_version" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		APIVersion     respjson.Field
		CreatedAt      respjson.Field
		Data           respjson.Field
		EventID        respjson.Field
		EventType      respjson.Field
		PartnerID      respjson.Field
		TraceID        respjson.Field
		WebhookVersion respjson.Field
		ExtraFields    map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Complete webhook payload for participant.added events

func (ParticipantAddedWebhookEvent) RawJSON added in v0.12.0

Returns the unmodified JSON received from the API

func (*ParticipantAddedWebhookEvent) UnmarshalJSON added in v0.12.0

func (r *ParticipantAddedWebhookEvent) UnmarshalJSON(data []byte) error

type ParticipantAddedWebhookEventData added in v0.12.0

type ParticipantAddedWebhookEventData struct {
	// DEPRECATED: Use participant instead. Handle (phone number or email address) of
	// the added participant.
	//
	// Deprecated: deprecated
	Handle string `json:"handle" api:"required"`
	// When the participant was added
	AddedAt time.Time `json:"added_at" format:"date-time"`
	// Chat identifier (UUID) of the group chat
	ChatID string `json:"chat_id"`
	// The added participant as a full handle object
	Participant shared.ChatHandle `json:"participant"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Handle      respjson.Field
		AddedAt     respjson.Field
		ChatID      respjson.Field
		Participant respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Payload for participant.added webhook events

func (ParticipantAddedWebhookEventData) RawJSON added in v0.12.0

Returns the unmodified JSON received from the API

func (*ParticipantAddedWebhookEventData) UnmarshalJSON added in v0.12.0

func (r *ParticipantAddedWebhookEventData) UnmarshalJSON(data []byte) error

type ParticipantRemovedWebhookEvent added in v0.12.0

type ParticipantRemovedWebhookEvent struct {
	// API version for the webhook payload format
	APIVersion string `json:"api_version" api:"required"`
	// When the event was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// Payload for participant.removed webhook events
	Data ParticipantRemovedWebhookEventData `json:"data" api:"required"`
	// Unique identifier for this event (for deduplication)
	EventID string `json:"event_id" api:"required" format:"uuid"`
	// Valid webhook event types that can be subscribed to.
	//
	// **Note:** `message.edited` is only delivered to subscriptions using
	// `webhook_version: "2026-02-03"`. Subscribing to this event on a v2025
	// subscription will not produce any deliveries.
	//
	// Any of "message.sent", "message.received", "message.read", "message.delivered",
	// "message.failed", "message.edited", "reaction.added", "reaction.removed",
	// "poll.received", "poll.failed", "poll.sent", "poll.delivered", "poll.read",
	// "poll.updated", "poll.vote.added", "poll.vote.removed", "poll.reaction.added",
	// "participant.added", "participant.removed", "chat.created",
	// "chat.group_name_updated", "chat.group_icon_updated",
	// "chat.group_name_update_failed", "chat.group_icon_update_failed",
	// "chat.background_updated", "chat.background_update_failed",
	// "chat.typing_indicator.started", "chat.typing_indicator.stopped",
	// "phone_number.status_updated", "contact_card.received", "call.initiated",
	// "call.ringing", "call.answered", "call.ended", "call.failed", "call.declined",
	// "call.no_answer", "location.sharing.started", "location.sharing.stopped",
	// "payment.succeeded", "payment.canceled", "payment.expired", "payment.declined",
	// "payment.authorized", "connection.created", "connection.revoked".
	EventType WebhookEventType `json:"event_type" api:"required"`
	// Partner identifier. Present on all webhooks for cross-referencing.
	PartnerID string `json:"partner_id" api:"required"`
	// Trace ID for debugging and correlation across systems.
	TraceID string `json:"trace_id" api:"required"`
	// Date-based webhook payload version. Determined by the `?version=` query
	// parameter in your webhook subscription URL. If no version parameter is
	// specified, defaults based on subscription creation date.
	WebhookVersion string `json:"webhook_version" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		APIVersion     respjson.Field
		CreatedAt      respjson.Field
		Data           respjson.Field
		EventID        respjson.Field
		EventType      respjson.Field
		PartnerID      respjson.Field
		TraceID        respjson.Field
		WebhookVersion respjson.Field
		ExtraFields    map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Complete webhook payload for participant.removed events

func (ParticipantRemovedWebhookEvent) RawJSON added in v0.12.0

Returns the unmodified JSON received from the API

func (*ParticipantRemovedWebhookEvent) UnmarshalJSON added in v0.12.0

func (r *ParticipantRemovedWebhookEvent) UnmarshalJSON(data []byte) error

type ParticipantRemovedWebhookEventData added in v0.12.0

type ParticipantRemovedWebhookEventData struct {
	// DEPRECATED: Use participant instead. Handle (phone number or email address) of
	// the removed participant.
	//
	// Deprecated: deprecated
	Handle string `json:"handle" api:"required"`
	// Chat identifier (UUID) of the group chat
	ChatID string `json:"chat_id"`
	// The removed participant as a full handle object
	Participant shared.ChatHandle `json:"participant"`
	// When the participant was removed
	RemovedAt time.Time `json:"removed_at" format:"date-time"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Handle      respjson.Field
		ChatID      respjson.Field
		Participant respjson.Field
		RemovedAt   respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Payload for participant.removed webhook events

func (ParticipantRemovedWebhookEventData) RawJSON added in v0.12.0

Returns the unmodified JSON received from the API

func (*ParticipantRemovedWebhookEventData) UnmarshalJSON added in v0.12.0

func (r *ParticipantRemovedWebhookEventData) UnmarshalJSON(data []byte) error

type Payment added in v0.29.0

type Payment struct {
	ID          string `json:"id"`
	AmountCents int64  `json:"amount_cents"`
	// Present on `awaiting_user_action` once a card is on file and the charge needs
	// the customer's passkey. Re-send the create request with the same
	// `Idempotency-Key` to collect the payment after they approve.
	ApprovalURL string `json:"approval_url"`
	// Present on `awaiting_user_action` when the customer has no card on file yet. A
	// hosted page — open it for them; it stays valid for about 48 hours. Not returned
	// on `needs_connection`: connect the handle first.
	AttachURL   string `json:"attach_url"`
	Currency    string `json:"currency"`
	Description string `json:"description"`
	Handle      string `json:"handle"`
	// The merchant the card is minted against, echoed from the request.
	Merchant PaymentMerchant `json:"merchant"`
	// Your own key/values, echoed back from the request.
	Metadata map[string]string `json:"metadata"`
	// Any of "needs_connection", "connecting", "awaiting_user_action", "ready",
	// "authorized", "succeeded", "declined", "canceled", "expired".
	Status PaymentStatus `json:"status"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ID          respjson.Field
		AmountCents respjson.Field
		ApprovalURL respjson.Field
		AttachURL   respjson.Field
		Currency    respjson.Field
		Description respjson.Field
		Handle      respjson.Field
		Merchant    respjson.Field
		Metadata    respjson.Field
		Status      respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (Payment) RawJSON added in v0.29.0

func (r Payment) RawJSON() string

Returns the unmodified JSON received from the API

func (*Payment) UnmarshalJSON added in v0.29.0

func (r *Payment) UnmarshalJSON(data []byte) error

type PaymentAuthorizedWebhookEvent added in v0.49.0

type PaymentAuthorizedWebhookEvent struct {
	// API version for the webhook payload format
	APIVersion string `json:"api_version" api:"required"`
	// When the event was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// The payment request, as returned by
	// `GET /v3/payment_requests/{paymentRequestId}`.
	Data PaymentAuthorizedWebhookEventData `json:"data" api:"required"`
	// Unique identifier for this event (for deduplication)
	EventID string `json:"event_id" api:"required" format:"uuid"`
	// Any of "payment.succeeded", "payment.canceled", "payment.expired",
	// "message.sent", "message.received", "message.read", "message.delivered",
	// "message.failed", "message.edited", "reaction.added", "reaction.removed",
	// "poll.received", "poll.failed", "poll.sent", "poll.delivered", "poll.read",
	// "poll.updated", "poll.vote.added", "poll.vote.removed", "poll.reaction.added",
	// "participant.added", "participant.removed", "chat.created",
	// "chat.group_name_updated", "chat.group_icon_updated",
	// "chat.group_name_update_failed", "chat.group_icon_update_failed",
	// "chat.background_updated", "chat.background_update_failed",
	// "chat.typing_indicator.started", "chat.typing_indicator.stopped",
	// "phone_number.status_updated", "contact_card.received", "call.initiated",
	// "call.ringing", "call.answered", "call.ended", "call.failed", "call.declined",
	// "call.no_answer", "location.sharing.started", "location.sharing.stopped",
	// "payment.declined", "payment.authorized", "connection.created",
	// "connection.revoked".
	EventType PaymentAuthorizedWebhookEventEventType `json:"event_type" api:"required"`
	// Partner identifier. Present on all webhooks for cross-referencing.
	PartnerID string `json:"partner_id" api:"required"`
	// Trace ID for debugging and correlation across systems.
	TraceID string `json:"trace_id" api:"required"`
	// Date-based webhook payload version. Determined by the `?version=` query
	// parameter in your webhook subscription URL. If no version parameter is
	// specified, defaults based on subscription creation date.
	WebhookVersion string `json:"webhook_version" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		APIVersion     respjson.Field
		CreatedAt      respjson.Field
		Data           respjson.Field
		EventID        respjson.Field
		EventType      respjson.Field
		PartnerID      respjson.Field
		TraceID        respjson.Field
		WebhookVersion respjson.Field
		ExtraFields    map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (PaymentAuthorizedWebhookEvent) RawJSON added in v0.49.0

Returns the unmodified JSON received from the API

func (*PaymentAuthorizedWebhookEvent) UnmarshalJSON added in v0.49.0

func (r *PaymentAuthorizedWebhookEvent) UnmarshalJSON(data []byte) error

type PaymentAuthorizedWebhookEventData added in v0.49.0

type PaymentAuthorizedWebhookEventData struct {
	// The payment request id.
	ID string `json:"id" api:"required" format:"uuid"`
	// What was charged at checkout, in the currency's minor units. In `subscription`
	// mode this is the first invoice's total — all items after any discounts are
	// applied.
	Amount int64 `json:"amount" api:"required"`
	// URL the recipient opens to pay
	// (`https://zero.linqapp.com/pay/{slug}?session=...`).
	CheckoutURL string    `json:"checkout_url" api:"required"`
	CreatedAt   time.Time `json:"created_at" api:"required" format:"date-time"`
	Currency    string    `json:"currency" api:"required"`
	Object      string    `json:"object" api:"required"`
	// Any of "succeeded", "failed", "canceled", "expired".
	Status      string `json:"status" api:"required"`
	Description string `json:"description"`
	// Subscription mode — the discount Stripe applied, read back from the coupon.
	// Absent when none was applied.
	Discount PaymentAuthorizedWebhookEventDataDiscount `json:"discount"`
	// Subscription mode — how often the subscription renews.
	//
	// Any of "day", "week", "month", "year".
	Interval string `json:"interval"`
	// Subscription mode — intervals per renewal.
	IntervalCount int64             `json:"interval_count"`
	Metadata      map[string]string `json:"metadata"`
	// Whether the request collected a one-time charge or started a subscription.
	//
	// Any of "payment", "subscription".
	Mode string `json:"mode"`
	// Natural-rail join keys, present when `rail: natural`.
	Natural PaymentAuthorizedWebhookEventDataNatural `json:"natural"`
	// Subscription mode — the recurring price subscribed to.
	PriceID string `json:"price_id"`
	// Subscription mode — units of the price subscribed to.
	Quantity int64 `json:"quantity"`
	// The rail this request settled on.
	//
	// Any of "stripe", "natural".
	Rail string `json:"rail"`
	// Ids of the Stripe objects on your connected account — join keys into your own
	// Stripe Dashboard/API. Manage a subscription's post-checkout lifecycle with
	// `subscription_id`.
	Stripe PaymentAuthorizedWebhookEventDataStripe `json:"stripe"`
	// Subscription mode — when the free trial ends and the first charge happens. On a
	// trial request, `payment.succeeded` means the payment method was collected ($0
	// moved).
	TrialEnd  time.Time `json:"trial_end" format:"date-time"`
	UpdatedAt time.Time `json:"updated_at" format:"date-time"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ID            respjson.Field
		Amount        respjson.Field
		CheckoutURL   respjson.Field
		CreatedAt     respjson.Field
		Currency      respjson.Field
		Object        respjson.Field
		Status        respjson.Field
		Description   respjson.Field
		Discount      respjson.Field
		Interval      respjson.Field
		IntervalCount respjson.Field
		Metadata      respjson.Field
		Mode          respjson.Field
		Natural       respjson.Field
		PriceID       respjson.Field
		Quantity      respjson.Field
		Rail          respjson.Field
		Stripe        respjson.Field
		TrialEnd      respjson.Field
		UpdatedAt     respjson.Field
		ExtraFields   map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

The payment request, as returned by `GET /v3/payment_requests/{paymentRequestId}`.

func (PaymentAuthorizedWebhookEventData) RawJSON added in v0.49.0

Returns the unmodified JSON received from the API

func (*PaymentAuthorizedWebhookEventData) UnmarshalJSON added in v0.49.0

func (r *PaymentAuthorizedWebhookEventData) UnmarshalJSON(data []byte) error

type PaymentAuthorizedWebhookEventDataDiscount added in v0.49.0

type PaymentAuthorizedWebhookEventDataDiscount struct {
	Coupon string `json:"coupon"`
	// Name of the coupon/promo code displayed to customers.
	Label         string `json:"label"`
	PromotionCode string `json:"promotion_code"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Coupon        respjson.Field
		Label         respjson.Field
		PromotionCode respjson.Field
		ExtraFields   map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Subscription mode — the discount Stripe applied, read back from the coupon. Absent when none was applied.

func (PaymentAuthorizedWebhookEventDataDiscount) RawJSON added in v0.49.0

Returns the unmodified JSON received from the API

func (*PaymentAuthorizedWebhookEventDataDiscount) UnmarshalJSON added in v0.49.0

func (r *PaymentAuthorizedWebhookEventDataDiscount) UnmarshalJSON(data []byte) error

type PaymentAuthorizedWebhookEventDataNatural added in v0.49.0

type PaymentAuthorizedWebhookEventDataNatural struct {
	// The Natural payment request (`prq_...`).
	PaymentRequestID string `json:"payment_request_id"`
	// The settled transaction (`txn_...`).
	TransactionID string `json:"transaction_id"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		PaymentRequestID respjson.Field
		TransactionID    respjson.Field
		ExtraFields      map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Natural-rail join keys, present when `rail: natural`.

func (PaymentAuthorizedWebhookEventDataNatural) RawJSON added in v0.49.0

Returns the unmodified JSON received from the API

func (*PaymentAuthorizedWebhookEventDataNatural) UnmarshalJSON added in v0.49.0

func (r *PaymentAuthorizedWebhookEventDataNatural) UnmarshalJSON(data []byte) error

type PaymentAuthorizedWebhookEventDataStripe added in v0.49.0

type PaymentAuthorizedWebhookEventDataStripe struct {
	// The Customer the request is attached to (`cus_...`). Always set in subscription
	// mode; set in payment mode only when the request was created with a
	// `customer_id`.
	CustomerID string `json:"customer_id"`
	// The PaymentIntent collected at checkout (`pi_...`).
	PaymentIntentID string `json:"payment_intent_id"`
	// Subscription mode — the Subscription (`sub_...`).
	SubscriptionID string `json:"subscription_id"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		CustomerID      respjson.Field
		PaymentIntentID respjson.Field
		SubscriptionID  respjson.Field
		ExtraFields     map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Ids of the Stripe objects on your connected account — join keys into your own Stripe Dashboard/API. Manage a subscription's post-checkout lifecycle with `subscription_id`.

func (PaymentAuthorizedWebhookEventDataStripe) RawJSON added in v0.49.0

Returns the unmodified JSON received from the API

func (*PaymentAuthorizedWebhookEventDataStripe) UnmarshalJSON added in v0.49.0

func (r *PaymentAuthorizedWebhookEventDataStripe) UnmarshalJSON(data []byte) error

type PaymentAuthorizedWebhookEventEventType added in v0.49.0

type PaymentAuthorizedWebhookEventEventType string
const (
	PaymentAuthorizedWebhookEventEventTypePaymentSucceeded           PaymentAuthorizedWebhookEventEventType = "payment.succeeded"
	PaymentAuthorizedWebhookEventEventTypePaymentCanceled            PaymentAuthorizedWebhookEventEventType = "payment.canceled"
	PaymentAuthorizedWebhookEventEventTypePaymentExpired             PaymentAuthorizedWebhookEventEventType = "payment.expired"
	PaymentAuthorizedWebhookEventEventTypeMessageSent                PaymentAuthorizedWebhookEventEventType = "message.sent"
	PaymentAuthorizedWebhookEventEventTypeMessageReceived            PaymentAuthorizedWebhookEventEventType = "message.received"
	PaymentAuthorizedWebhookEventEventTypeMessageRead                PaymentAuthorizedWebhookEventEventType = "message.read"
	PaymentAuthorizedWebhookEventEventTypeMessageDelivered           PaymentAuthorizedWebhookEventEventType = "message.delivered"
	PaymentAuthorizedWebhookEventEventTypeMessageFailed              PaymentAuthorizedWebhookEventEventType = "message.failed"
	PaymentAuthorizedWebhookEventEventTypeMessageEdited              PaymentAuthorizedWebhookEventEventType = "message.edited"
	PaymentAuthorizedWebhookEventEventTypeReactionAdded              PaymentAuthorizedWebhookEventEventType = "reaction.added"
	PaymentAuthorizedWebhookEventEventTypeReactionRemoved            PaymentAuthorizedWebhookEventEventType = "reaction.removed"
	PaymentAuthorizedWebhookEventEventTypePollReceived               PaymentAuthorizedWebhookEventEventType = "poll.received"
	PaymentAuthorizedWebhookEventEventTypePollFailed                 PaymentAuthorizedWebhookEventEventType = "poll.failed"
	PaymentAuthorizedWebhookEventEventTypePollSent                   PaymentAuthorizedWebhookEventEventType = "poll.sent"
	PaymentAuthorizedWebhookEventEventTypePollDelivered              PaymentAuthorizedWebhookEventEventType = "poll.delivered"
	PaymentAuthorizedWebhookEventEventTypePollRead                   PaymentAuthorizedWebhookEventEventType = "poll.read"
	PaymentAuthorizedWebhookEventEventTypePollUpdated                PaymentAuthorizedWebhookEventEventType = "poll.updated"
	PaymentAuthorizedWebhookEventEventTypePollVoteAdded              PaymentAuthorizedWebhookEventEventType = "poll.vote.added"
	PaymentAuthorizedWebhookEventEventTypePollVoteRemoved            PaymentAuthorizedWebhookEventEventType = "poll.vote.removed"
	PaymentAuthorizedWebhookEventEventTypePollReactionAdded          PaymentAuthorizedWebhookEventEventType = "poll.reaction.added"
	PaymentAuthorizedWebhookEventEventTypeParticipantAdded           PaymentAuthorizedWebhookEventEventType = "participant.added"
	PaymentAuthorizedWebhookEventEventTypeParticipantRemoved         PaymentAuthorizedWebhookEventEventType = "participant.removed"
	PaymentAuthorizedWebhookEventEventTypeChatCreated                PaymentAuthorizedWebhookEventEventType = "chat.created"
	PaymentAuthorizedWebhookEventEventTypeChatGroupNameUpdated       PaymentAuthorizedWebhookEventEventType = "chat.group_name_updated"
	PaymentAuthorizedWebhookEventEventTypeChatGroupIconUpdated       PaymentAuthorizedWebhookEventEventType = "chat.group_icon_updated"
	PaymentAuthorizedWebhookEventEventTypeChatGroupNameUpdateFailed  PaymentAuthorizedWebhookEventEventType = "chat.group_name_update_failed"
	PaymentAuthorizedWebhookEventEventTypeChatGroupIconUpdateFailed  PaymentAuthorizedWebhookEventEventType = "chat.group_icon_update_failed"
	PaymentAuthorizedWebhookEventEventTypeChatBackgroundUpdated      PaymentAuthorizedWebhookEventEventType = "chat.background_updated"
	PaymentAuthorizedWebhookEventEventTypeChatBackgroundUpdateFailed PaymentAuthorizedWebhookEventEventType = "chat.background_update_failed"
	PaymentAuthorizedWebhookEventEventTypeChatTypingIndicatorStarted PaymentAuthorizedWebhookEventEventType = "chat.typing_indicator.started"
	PaymentAuthorizedWebhookEventEventTypeChatTypingIndicatorStopped PaymentAuthorizedWebhookEventEventType = "chat.typing_indicator.stopped"
	PaymentAuthorizedWebhookEventEventTypePhoneNumberStatusUpdated   PaymentAuthorizedWebhookEventEventType = "phone_number.status_updated"
	PaymentAuthorizedWebhookEventEventTypeContactCardReceived        PaymentAuthorizedWebhookEventEventType = "contact_card.received"
	PaymentAuthorizedWebhookEventEventTypeCallInitiated              PaymentAuthorizedWebhookEventEventType = "call.initiated"
	PaymentAuthorizedWebhookEventEventTypeCallRinging                PaymentAuthorizedWebhookEventEventType = "call.ringing"
	PaymentAuthorizedWebhookEventEventTypeCallAnswered               PaymentAuthorizedWebhookEventEventType = "call.answered"
	PaymentAuthorizedWebhookEventEventTypeCallEnded                  PaymentAuthorizedWebhookEventEventType = "call.ended"
	PaymentAuthorizedWebhookEventEventTypeCallFailed                 PaymentAuthorizedWebhookEventEventType = "call.failed"
	PaymentAuthorizedWebhookEventEventTypeCallDeclined               PaymentAuthorizedWebhookEventEventType = "call.declined"
	PaymentAuthorizedWebhookEventEventTypeCallNoAnswer               PaymentAuthorizedWebhookEventEventType = "call.no_answer"
	PaymentAuthorizedWebhookEventEventTypeLocationSharingStarted     PaymentAuthorizedWebhookEventEventType = "location.sharing.started"
	PaymentAuthorizedWebhookEventEventTypeLocationSharingStopped     PaymentAuthorizedWebhookEventEventType = "location.sharing.stopped"
	PaymentAuthorizedWebhookEventEventTypePaymentDeclined            PaymentAuthorizedWebhookEventEventType = "payment.declined"
	PaymentAuthorizedWebhookEventEventTypePaymentAuthorized          PaymentAuthorizedWebhookEventEventType = "payment.authorized"
	PaymentAuthorizedWebhookEventEventTypeConnectionCreated          PaymentAuthorizedWebhookEventEventType = "connection.created"
	PaymentAuthorizedWebhookEventEventTypeConnectionRevoked          PaymentAuthorizedWebhookEventEventType = "connection.revoked"
)

type PaymentCanceledWebhookEvent added in v0.49.0

type PaymentCanceledWebhookEvent struct {
	// API version for the webhook payload format
	APIVersion string `json:"api_version" api:"required"`
	// When the event was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// The payment request, as returned by
	// `GET /v3/payment_requests/{paymentRequestId}`.
	Data PaymentCanceledWebhookEventData `json:"data" api:"required"`
	// Unique identifier for this event (for deduplication)
	EventID string `json:"event_id" api:"required" format:"uuid"`
	// Any of "payment.succeeded", "payment.canceled", "payment.expired",
	// "message.sent", "message.received", "message.read", "message.delivered",
	// "message.failed", "message.edited", "reaction.added", "reaction.removed",
	// "poll.received", "poll.failed", "poll.sent", "poll.delivered", "poll.read",
	// "poll.updated", "poll.vote.added", "poll.vote.removed", "poll.reaction.added",
	// "participant.added", "participant.removed", "chat.created",
	// "chat.group_name_updated", "chat.group_icon_updated",
	// "chat.group_name_update_failed", "chat.group_icon_update_failed",
	// "chat.background_updated", "chat.background_update_failed",
	// "chat.typing_indicator.started", "chat.typing_indicator.stopped",
	// "phone_number.status_updated", "contact_card.received", "call.initiated",
	// "call.ringing", "call.answered", "call.ended", "call.failed", "call.declined",
	// "call.no_answer", "location.sharing.started", "location.sharing.stopped",
	// "payment.declined", "payment.authorized", "connection.created",
	// "connection.revoked".
	EventType PaymentCanceledWebhookEventEventType `json:"event_type" api:"required"`
	// Partner identifier. Present on all webhooks for cross-referencing.
	PartnerID string `json:"partner_id" api:"required"`
	// Trace ID for debugging and correlation across systems.
	TraceID string `json:"trace_id" api:"required"`
	// Date-based webhook payload version. Determined by the `?version=` query
	// parameter in your webhook subscription URL. If no version parameter is
	// specified, defaults based on subscription creation date.
	WebhookVersion string `json:"webhook_version" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		APIVersion     respjson.Field
		CreatedAt      respjson.Field
		Data           respjson.Field
		EventID        respjson.Field
		EventType      respjson.Field
		PartnerID      respjson.Field
		TraceID        respjson.Field
		WebhookVersion respjson.Field
		ExtraFields    map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (PaymentCanceledWebhookEvent) RawJSON added in v0.49.0

func (r PaymentCanceledWebhookEvent) RawJSON() string

Returns the unmodified JSON received from the API

func (*PaymentCanceledWebhookEvent) UnmarshalJSON added in v0.49.0

func (r *PaymentCanceledWebhookEvent) UnmarshalJSON(data []byte) error

type PaymentCanceledWebhookEventData added in v0.49.0

type PaymentCanceledWebhookEventData struct {
	// The payment request id.
	ID string `json:"id" api:"required" format:"uuid"`
	// What was charged at checkout, in the currency's minor units. In `subscription`
	// mode this is the first invoice's total — all items after any discounts are
	// applied.
	Amount int64 `json:"amount" api:"required"`
	// URL the recipient opens to pay
	// (`https://zero.linqapp.com/pay/{slug}?session=...`).
	CheckoutURL string    `json:"checkout_url" api:"required"`
	CreatedAt   time.Time `json:"created_at" api:"required" format:"date-time"`
	Currency    string    `json:"currency" api:"required"`
	Object      string    `json:"object" api:"required"`
	// Any of "succeeded", "failed", "canceled", "expired".
	Status      string `json:"status" api:"required"`
	Description string `json:"description"`
	// Subscription mode — the discount Stripe applied, read back from the coupon.
	// Absent when none was applied.
	Discount PaymentCanceledWebhookEventDataDiscount `json:"discount"`
	// Subscription mode — how often the subscription renews.
	//
	// Any of "day", "week", "month", "year".
	Interval string `json:"interval"`
	// Subscription mode — intervals per renewal.
	IntervalCount int64             `json:"interval_count"`
	Metadata      map[string]string `json:"metadata"`
	// Whether the request collected a one-time charge or started a subscription.
	//
	// Any of "payment", "subscription".
	Mode string `json:"mode"`
	// Natural-rail join keys, present when `rail: natural`.
	Natural PaymentCanceledWebhookEventDataNatural `json:"natural"`
	// Subscription mode — the recurring price subscribed to.
	PriceID string `json:"price_id"`
	// Subscription mode — units of the price subscribed to.
	Quantity int64 `json:"quantity"`
	// The rail this request settled on.
	//
	// Any of "stripe", "natural".
	Rail string `json:"rail"`
	// Ids of the Stripe objects on your connected account — join keys into your own
	// Stripe Dashboard/API. Manage a subscription's post-checkout lifecycle with
	// `subscription_id`.
	Stripe PaymentCanceledWebhookEventDataStripe `json:"stripe"`
	// Subscription mode — when the free trial ends and the first charge happens. On a
	// trial request, `payment.succeeded` means the payment method was collected ($0
	// moved).
	TrialEnd  time.Time `json:"trial_end" format:"date-time"`
	UpdatedAt time.Time `json:"updated_at" format:"date-time"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ID            respjson.Field
		Amount        respjson.Field
		CheckoutURL   respjson.Field
		CreatedAt     respjson.Field
		Currency      respjson.Field
		Object        respjson.Field
		Status        respjson.Field
		Description   respjson.Field
		Discount      respjson.Field
		Interval      respjson.Field
		IntervalCount respjson.Field
		Metadata      respjson.Field
		Mode          respjson.Field
		Natural       respjson.Field
		PriceID       respjson.Field
		Quantity      respjson.Field
		Rail          respjson.Field
		Stripe        respjson.Field
		TrialEnd      respjson.Field
		UpdatedAt     respjson.Field
		ExtraFields   map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

The payment request, as returned by `GET /v3/payment_requests/{paymentRequestId}`.

func (PaymentCanceledWebhookEventData) RawJSON added in v0.49.0

Returns the unmodified JSON received from the API

func (*PaymentCanceledWebhookEventData) UnmarshalJSON added in v0.49.0

func (r *PaymentCanceledWebhookEventData) UnmarshalJSON(data []byte) error

type PaymentCanceledWebhookEventDataDiscount added in v0.49.0

type PaymentCanceledWebhookEventDataDiscount struct {
	Coupon string `json:"coupon"`
	// Name of the coupon/promo code displayed to customers.
	Label         string `json:"label"`
	PromotionCode string `json:"promotion_code"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Coupon        respjson.Field
		Label         respjson.Field
		PromotionCode respjson.Field
		ExtraFields   map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Subscription mode — the discount Stripe applied, read back from the coupon. Absent when none was applied.

func (PaymentCanceledWebhookEventDataDiscount) RawJSON added in v0.49.0

Returns the unmodified JSON received from the API

func (*PaymentCanceledWebhookEventDataDiscount) UnmarshalJSON added in v0.49.0

func (r *PaymentCanceledWebhookEventDataDiscount) UnmarshalJSON(data []byte) error

type PaymentCanceledWebhookEventDataNatural added in v0.49.0

type PaymentCanceledWebhookEventDataNatural struct {
	// The Natural payment request (`prq_...`).
	PaymentRequestID string `json:"payment_request_id"`
	// The settled transaction (`txn_...`).
	TransactionID string `json:"transaction_id"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		PaymentRequestID respjson.Field
		TransactionID    respjson.Field
		ExtraFields      map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Natural-rail join keys, present when `rail: natural`.

func (PaymentCanceledWebhookEventDataNatural) RawJSON added in v0.49.0

Returns the unmodified JSON received from the API

func (*PaymentCanceledWebhookEventDataNatural) UnmarshalJSON added in v0.49.0

func (r *PaymentCanceledWebhookEventDataNatural) UnmarshalJSON(data []byte) error

type PaymentCanceledWebhookEventDataStripe added in v0.49.0

type PaymentCanceledWebhookEventDataStripe struct {
	// The Customer the request is attached to (`cus_...`). Always set in subscription
	// mode; set in payment mode only when the request was created with a
	// `customer_id`.
	CustomerID string `json:"customer_id"`
	// The PaymentIntent collected at checkout (`pi_...`).
	PaymentIntentID string `json:"payment_intent_id"`
	// Subscription mode — the Subscription (`sub_...`).
	SubscriptionID string `json:"subscription_id"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		CustomerID      respjson.Field
		PaymentIntentID respjson.Field
		SubscriptionID  respjson.Field
		ExtraFields     map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Ids of the Stripe objects on your connected account — join keys into your own Stripe Dashboard/API. Manage a subscription's post-checkout lifecycle with `subscription_id`.

func (PaymentCanceledWebhookEventDataStripe) RawJSON added in v0.49.0

Returns the unmodified JSON received from the API

func (*PaymentCanceledWebhookEventDataStripe) UnmarshalJSON added in v0.49.0

func (r *PaymentCanceledWebhookEventDataStripe) UnmarshalJSON(data []byte) error

type PaymentCanceledWebhookEventEventType added in v0.49.0

type PaymentCanceledWebhookEventEventType string
const (
	PaymentCanceledWebhookEventEventTypePaymentSucceeded           PaymentCanceledWebhookEventEventType = "payment.succeeded"
	PaymentCanceledWebhookEventEventTypePaymentCanceled            PaymentCanceledWebhookEventEventType = "payment.canceled"
	PaymentCanceledWebhookEventEventTypePaymentExpired             PaymentCanceledWebhookEventEventType = "payment.expired"
	PaymentCanceledWebhookEventEventTypeMessageSent                PaymentCanceledWebhookEventEventType = "message.sent"
	PaymentCanceledWebhookEventEventTypeMessageReceived            PaymentCanceledWebhookEventEventType = "message.received"
	PaymentCanceledWebhookEventEventTypeMessageRead                PaymentCanceledWebhookEventEventType = "message.read"
	PaymentCanceledWebhookEventEventTypeMessageDelivered           PaymentCanceledWebhookEventEventType = "message.delivered"
	PaymentCanceledWebhookEventEventTypeMessageFailed              PaymentCanceledWebhookEventEventType = "message.failed"
	PaymentCanceledWebhookEventEventTypeMessageEdited              PaymentCanceledWebhookEventEventType = "message.edited"
	PaymentCanceledWebhookEventEventTypeReactionAdded              PaymentCanceledWebhookEventEventType = "reaction.added"
	PaymentCanceledWebhookEventEventTypeReactionRemoved            PaymentCanceledWebhookEventEventType = "reaction.removed"
	PaymentCanceledWebhookEventEventTypePollReceived               PaymentCanceledWebhookEventEventType = "poll.received"
	PaymentCanceledWebhookEventEventTypePollFailed                 PaymentCanceledWebhookEventEventType = "poll.failed"
	PaymentCanceledWebhookEventEventTypePollSent                   PaymentCanceledWebhookEventEventType = "poll.sent"
	PaymentCanceledWebhookEventEventTypePollDelivered              PaymentCanceledWebhookEventEventType = "poll.delivered"
	PaymentCanceledWebhookEventEventTypePollRead                   PaymentCanceledWebhookEventEventType = "poll.read"
	PaymentCanceledWebhookEventEventTypePollUpdated                PaymentCanceledWebhookEventEventType = "poll.updated"
	PaymentCanceledWebhookEventEventTypePollVoteAdded              PaymentCanceledWebhookEventEventType = "poll.vote.added"
	PaymentCanceledWebhookEventEventTypePollVoteRemoved            PaymentCanceledWebhookEventEventType = "poll.vote.removed"
	PaymentCanceledWebhookEventEventTypePollReactionAdded          PaymentCanceledWebhookEventEventType = "poll.reaction.added"
	PaymentCanceledWebhookEventEventTypeParticipantAdded           PaymentCanceledWebhookEventEventType = "participant.added"
	PaymentCanceledWebhookEventEventTypeParticipantRemoved         PaymentCanceledWebhookEventEventType = "participant.removed"
	PaymentCanceledWebhookEventEventTypeChatCreated                PaymentCanceledWebhookEventEventType = "chat.created"
	PaymentCanceledWebhookEventEventTypeChatGroupNameUpdated       PaymentCanceledWebhookEventEventType = "chat.group_name_updated"
	PaymentCanceledWebhookEventEventTypeChatGroupIconUpdated       PaymentCanceledWebhookEventEventType = "chat.group_icon_updated"
	PaymentCanceledWebhookEventEventTypeChatGroupNameUpdateFailed  PaymentCanceledWebhookEventEventType = "chat.group_name_update_failed"
	PaymentCanceledWebhookEventEventTypeChatGroupIconUpdateFailed  PaymentCanceledWebhookEventEventType = "chat.group_icon_update_failed"
	PaymentCanceledWebhookEventEventTypeChatBackgroundUpdated      PaymentCanceledWebhookEventEventType = "chat.background_updated"
	PaymentCanceledWebhookEventEventTypeChatBackgroundUpdateFailed PaymentCanceledWebhookEventEventType = "chat.background_update_failed"
	PaymentCanceledWebhookEventEventTypeChatTypingIndicatorStarted PaymentCanceledWebhookEventEventType = "chat.typing_indicator.started"
	PaymentCanceledWebhookEventEventTypeChatTypingIndicatorStopped PaymentCanceledWebhookEventEventType = "chat.typing_indicator.stopped"
	PaymentCanceledWebhookEventEventTypePhoneNumberStatusUpdated   PaymentCanceledWebhookEventEventType = "phone_number.status_updated"
	PaymentCanceledWebhookEventEventTypeContactCardReceived        PaymentCanceledWebhookEventEventType = "contact_card.received"
	PaymentCanceledWebhookEventEventTypeCallInitiated              PaymentCanceledWebhookEventEventType = "call.initiated"
	PaymentCanceledWebhookEventEventTypeCallRinging                PaymentCanceledWebhookEventEventType = "call.ringing"
	PaymentCanceledWebhookEventEventTypeCallAnswered               PaymentCanceledWebhookEventEventType = "call.answered"
	PaymentCanceledWebhookEventEventTypeCallEnded                  PaymentCanceledWebhookEventEventType = "call.ended"
	PaymentCanceledWebhookEventEventTypeCallFailed                 PaymentCanceledWebhookEventEventType = "call.failed"
	PaymentCanceledWebhookEventEventTypeCallDeclined               PaymentCanceledWebhookEventEventType = "call.declined"
	PaymentCanceledWebhookEventEventTypeCallNoAnswer               PaymentCanceledWebhookEventEventType = "call.no_answer"
	PaymentCanceledWebhookEventEventTypeLocationSharingStarted     PaymentCanceledWebhookEventEventType = "location.sharing.started"
	PaymentCanceledWebhookEventEventTypeLocationSharingStopped     PaymentCanceledWebhookEventEventType = "location.sharing.stopped"
	PaymentCanceledWebhookEventEventTypePaymentDeclined            PaymentCanceledWebhookEventEventType = "payment.declined"
	PaymentCanceledWebhookEventEventTypePaymentAuthorized          PaymentCanceledWebhookEventEventType = "payment.authorized"
	PaymentCanceledWebhookEventEventTypeConnectionCreated          PaymentCanceledWebhookEventEventType = "connection.created"
	PaymentCanceledWebhookEventEventTypeConnectionRevoked          PaymentCanceledWebhookEventEventType = "connection.revoked"
)

type PaymentCredentialsResponse added in v0.29.0

type PaymentCredentialsResponse struct {
	// Fetch the card directly from the provider with these — never through Linq.
	Handoff PaymentCredentialsResponseHandoff `json:"handoff"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Handoff     respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (PaymentCredentialsResponse) RawJSON added in v0.29.0

func (r PaymentCredentialsResponse) RawJSON() string

Returns the unmodified JSON received from the API

func (*PaymentCredentialsResponse) UnmarshalJSON added in v0.29.0

func (r *PaymentCredentialsResponse) UnmarshalJSON(data []byte) error

type PaymentCredentialsResponseHandoff added in v0.29.0

type PaymentCredentialsResponseHandoff struct {
	CardRef  string `json:"card_ref"`
	FetchURL string `json:"fetch_url"`
	Provider string `json:"provider"`
	// Short-lived bearer to fetch the card from the provider.
	UserToken string `json:"user_token"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		CardRef     respjson.Field
		FetchURL    respjson.Field
		Provider    respjson.Field
		UserToken   respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Fetch the card directly from the provider with these — never through Linq.

func (PaymentCredentialsResponseHandoff) RawJSON added in v0.29.0

Returns the unmodified JSON received from the API

func (*PaymentCredentialsResponseHandoff) UnmarshalJSON added in v0.29.0

func (r *PaymentCredentialsResponseHandoff) UnmarshalJSON(data []byte) error

type PaymentDeclinedWebhookEvent added in v0.49.0

type PaymentDeclinedWebhookEvent struct {
	// API version for the webhook payload format
	APIVersion string `json:"api_version" api:"required"`
	// When the event was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// The payment request, as returned by
	// `GET /v3/payment_requests/{paymentRequestId}`.
	Data PaymentDeclinedWebhookEventData `json:"data" api:"required"`
	// Unique identifier for this event (for deduplication)
	EventID string `json:"event_id" api:"required" format:"uuid"`
	// Any of "payment.succeeded", "payment.canceled", "payment.expired",
	// "message.sent", "message.received", "message.read", "message.delivered",
	// "message.failed", "message.edited", "reaction.added", "reaction.removed",
	// "poll.received", "poll.failed", "poll.sent", "poll.delivered", "poll.read",
	// "poll.updated", "poll.vote.added", "poll.vote.removed", "poll.reaction.added",
	// "participant.added", "participant.removed", "chat.created",
	// "chat.group_name_updated", "chat.group_icon_updated",
	// "chat.group_name_update_failed", "chat.group_icon_update_failed",
	// "chat.background_updated", "chat.background_update_failed",
	// "chat.typing_indicator.started", "chat.typing_indicator.stopped",
	// "phone_number.status_updated", "contact_card.received", "call.initiated",
	// "call.ringing", "call.answered", "call.ended", "call.failed", "call.declined",
	// "call.no_answer", "location.sharing.started", "location.sharing.stopped",
	// "payment.declined", "payment.authorized", "connection.created",
	// "connection.revoked".
	EventType PaymentDeclinedWebhookEventEventType `json:"event_type" api:"required"`
	// Partner identifier. Present on all webhooks for cross-referencing.
	PartnerID string `json:"partner_id" api:"required"`
	// Trace ID for debugging and correlation across systems.
	TraceID string `json:"trace_id" api:"required"`
	// Date-based webhook payload version. Determined by the `?version=` query
	// parameter in your webhook subscription URL. If no version parameter is
	// specified, defaults based on subscription creation date.
	WebhookVersion string `json:"webhook_version" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		APIVersion     respjson.Field
		CreatedAt      respjson.Field
		Data           respjson.Field
		EventID        respjson.Field
		EventType      respjson.Field
		PartnerID      respjson.Field
		TraceID        respjson.Field
		WebhookVersion respjson.Field
		ExtraFields    map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (PaymentDeclinedWebhookEvent) RawJSON added in v0.49.0

func (r PaymentDeclinedWebhookEvent) RawJSON() string

Returns the unmodified JSON received from the API

func (*PaymentDeclinedWebhookEvent) UnmarshalJSON added in v0.49.0

func (r *PaymentDeclinedWebhookEvent) UnmarshalJSON(data []byte) error

type PaymentDeclinedWebhookEventData added in v0.49.0

type PaymentDeclinedWebhookEventData struct {
	// The payment request id.
	ID string `json:"id" api:"required" format:"uuid"`
	// What was charged at checkout, in the currency's minor units. In `subscription`
	// mode this is the first invoice's total — all items after any discounts are
	// applied.
	Amount int64 `json:"amount" api:"required"`
	// URL the recipient opens to pay
	// (`https://zero.linqapp.com/pay/{slug}?session=...`).
	CheckoutURL string    `json:"checkout_url" api:"required"`
	CreatedAt   time.Time `json:"created_at" api:"required" format:"date-time"`
	Currency    string    `json:"currency" api:"required"`
	Object      string    `json:"object" api:"required"`
	// Any of "succeeded", "failed", "canceled", "expired".
	Status      string `json:"status" api:"required"`
	Description string `json:"description"`
	// Subscription mode — the discount Stripe applied, read back from the coupon.
	// Absent when none was applied.
	Discount PaymentDeclinedWebhookEventDataDiscount `json:"discount"`
	// Subscription mode — how often the subscription renews.
	//
	// Any of "day", "week", "month", "year".
	Interval string `json:"interval"`
	// Subscription mode — intervals per renewal.
	IntervalCount int64             `json:"interval_count"`
	Metadata      map[string]string `json:"metadata"`
	// Whether the request collected a one-time charge or started a subscription.
	//
	// Any of "payment", "subscription".
	Mode string `json:"mode"`
	// Natural-rail join keys, present when `rail: natural`.
	Natural PaymentDeclinedWebhookEventDataNatural `json:"natural"`
	// Subscription mode — the recurring price subscribed to.
	PriceID string `json:"price_id"`
	// Subscription mode — units of the price subscribed to.
	Quantity int64 `json:"quantity"`
	// The rail this request settled on.
	//
	// Any of "stripe", "natural".
	Rail string `json:"rail"`
	// Ids of the Stripe objects on your connected account — join keys into your own
	// Stripe Dashboard/API. Manage a subscription's post-checkout lifecycle with
	// `subscription_id`.
	Stripe PaymentDeclinedWebhookEventDataStripe `json:"stripe"`
	// Subscription mode — when the free trial ends and the first charge happens. On a
	// trial request, `payment.succeeded` means the payment method was collected ($0
	// moved).
	TrialEnd  time.Time `json:"trial_end" format:"date-time"`
	UpdatedAt time.Time `json:"updated_at" format:"date-time"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ID            respjson.Field
		Amount        respjson.Field
		CheckoutURL   respjson.Field
		CreatedAt     respjson.Field
		Currency      respjson.Field
		Object        respjson.Field
		Status        respjson.Field
		Description   respjson.Field
		Discount      respjson.Field
		Interval      respjson.Field
		IntervalCount respjson.Field
		Metadata      respjson.Field
		Mode          respjson.Field
		Natural       respjson.Field
		PriceID       respjson.Field
		Quantity      respjson.Field
		Rail          respjson.Field
		Stripe        respjson.Field
		TrialEnd      respjson.Field
		UpdatedAt     respjson.Field
		ExtraFields   map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

The payment request, as returned by `GET /v3/payment_requests/{paymentRequestId}`.

func (PaymentDeclinedWebhookEventData) RawJSON added in v0.49.0

Returns the unmodified JSON received from the API

func (*PaymentDeclinedWebhookEventData) UnmarshalJSON added in v0.49.0

func (r *PaymentDeclinedWebhookEventData) UnmarshalJSON(data []byte) error

type PaymentDeclinedWebhookEventDataDiscount added in v0.49.0

type PaymentDeclinedWebhookEventDataDiscount struct {
	Coupon string `json:"coupon"`
	// Name of the coupon/promo code displayed to customers.
	Label         string `json:"label"`
	PromotionCode string `json:"promotion_code"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Coupon        respjson.Field
		Label         respjson.Field
		PromotionCode respjson.Field
		ExtraFields   map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Subscription mode — the discount Stripe applied, read back from the coupon. Absent when none was applied.

func (PaymentDeclinedWebhookEventDataDiscount) RawJSON added in v0.49.0

Returns the unmodified JSON received from the API

func (*PaymentDeclinedWebhookEventDataDiscount) UnmarshalJSON added in v0.49.0

func (r *PaymentDeclinedWebhookEventDataDiscount) UnmarshalJSON(data []byte) error

type PaymentDeclinedWebhookEventDataNatural added in v0.49.0

type PaymentDeclinedWebhookEventDataNatural struct {
	// The Natural payment request (`prq_...`).
	PaymentRequestID string `json:"payment_request_id"`
	// The settled transaction (`txn_...`).
	TransactionID string `json:"transaction_id"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		PaymentRequestID respjson.Field
		TransactionID    respjson.Field
		ExtraFields      map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Natural-rail join keys, present when `rail: natural`.

func (PaymentDeclinedWebhookEventDataNatural) RawJSON added in v0.49.0

Returns the unmodified JSON received from the API

func (*PaymentDeclinedWebhookEventDataNatural) UnmarshalJSON added in v0.49.0

func (r *PaymentDeclinedWebhookEventDataNatural) UnmarshalJSON(data []byte) error

type PaymentDeclinedWebhookEventDataStripe added in v0.49.0

type PaymentDeclinedWebhookEventDataStripe struct {
	// The Customer the request is attached to (`cus_...`). Always set in subscription
	// mode; set in payment mode only when the request was created with a
	// `customer_id`.
	CustomerID string `json:"customer_id"`
	// The PaymentIntent collected at checkout (`pi_...`).
	PaymentIntentID string `json:"payment_intent_id"`
	// Subscription mode — the Subscription (`sub_...`).
	SubscriptionID string `json:"subscription_id"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		CustomerID      respjson.Field
		PaymentIntentID respjson.Field
		SubscriptionID  respjson.Field
		ExtraFields     map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Ids of the Stripe objects on your connected account — join keys into your own Stripe Dashboard/API. Manage a subscription's post-checkout lifecycle with `subscription_id`.

func (PaymentDeclinedWebhookEventDataStripe) RawJSON added in v0.49.0

Returns the unmodified JSON received from the API

func (*PaymentDeclinedWebhookEventDataStripe) UnmarshalJSON added in v0.49.0

func (r *PaymentDeclinedWebhookEventDataStripe) UnmarshalJSON(data []byte) error

type PaymentDeclinedWebhookEventEventType added in v0.49.0

type PaymentDeclinedWebhookEventEventType string
const (
	PaymentDeclinedWebhookEventEventTypePaymentSucceeded           PaymentDeclinedWebhookEventEventType = "payment.succeeded"
	PaymentDeclinedWebhookEventEventTypePaymentCanceled            PaymentDeclinedWebhookEventEventType = "payment.canceled"
	PaymentDeclinedWebhookEventEventTypePaymentExpired             PaymentDeclinedWebhookEventEventType = "payment.expired"
	PaymentDeclinedWebhookEventEventTypeMessageSent                PaymentDeclinedWebhookEventEventType = "message.sent"
	PaymentDeclinedWebhookEventEventTypeMessageReceived            PaymentDeclinedWebhookEventEventType = "message.received"
	PaymentDeclinedWebhookEventEventTypeMessageRead                PaymentDeclinedWebhookEventEventType = "message.read"
	PaymentDeclinedWebhookEventEventTypeMessageDelivered           PaymentDeclinedWebhookEventEventType = "message.delivered"
	PaymentDeclinedWebhookEventEventTypeMessageFailed              PaymentDeclinedWebhookEventEventType = "message.failed"
	PaymentDeclinedWebhookEventEventTypeMessageEdited              PaymentDeclinedWebhookEventEventType = "message.edited"
	PaymentDeclinedWebhookEventEventTypeReactionAdded              PaymentDeclinedWebhookEventEventType = "reaction.added"
	PaymentDeclinedWebhookEventEventTypeReactionRemoved            PaymentDeclinedWebhookEventEventType = "reaction.removed"
	PaymentDeclinedWebhookEventEventTypePollReceived               PaymentDeclinedWebhookEventEventType = "poll.received"
	PaymentDeclinedWebhookEventEventTypePollFailed                 PaymentDeclinedWebhookEventEventType = "poll.failed"
	PaymentDeclinedWebhookEventEventTypePollSent                   PaymentDeclinedWebhookEventEventType = "poll.sent"
	PaymentDeclinedWebhookEventEventTypePollDelivered              PaymentDeclinedWebhookEventEventType = "poll.delivered"
	PaymentDeclinedWebhookEventEventTypePollRead                   PaymentDeclinedWebhookEventEventType = "poll.read"
	PaymentDeclinedWebhookEventEventTypePollUpdated                PaymentDeclinedWebhookEventEventType = "poll.updated"
	PaymentDeclinedWebhookEventEventTypePollVoteAdded              PaymentDeclinedWebhookEventEventType = "poll.vote.added"
	PaymentDeclinedWebhookEventEventTypePollVoteRemoved            PaymentDeclinedWebhookEventEventType = "poll.vote.removed"
	PaymentDeclinedWebhookEventEventTypePollReactionAdded          PaymentDeclinedWebhookEventEventType = "poll.reaction.added"
	PaymentDeclinedWebhookEventEventTypeParticipantAdded           PaymentDeclinedWebhookEventEventType = "participant.added"
	PaymentDeclinedWebhookEventEventTypeParticipantRemoved         PaymentDeclinedWebhookEventEventType = "participant.removed"
	PaymentDeclinedWebhookEventEventTypeChatCreated                PaymentDeclinedWebhookEventEventType = "chat.created"
	PaymentDeclinedWebhookEventEventTypeChatGroupNameUpdated       PaymentDeclinedWebhookEventEventType = "chat.group_name_updated"
	PaymentDeclinedWebhookEventEventTypeChatGroupIconUpdated       PaymentDeclinedWebhookEventEventType = "chat.group_icon_updated"
	PaymentDeclinedWebhookEventEventTypeChatGroupNameUpdateFailed  PaymentDeclinedWebhookEventEventType = "chat.group_name_update_failed"
	PaymentDeclinedWebhookEventEventTypeChatGroupIconUpdateFailed  PaymentDeclinedWebhookEventEventType = "chat.group_icon_update_failed"
	PaymentDeclinedWebhookEventEventTypeChatBackgroundUpdated      PaymentDeclinedWebhookEventEventType = "chat.background_updated"
	PaymentDeclinedWebhookEventEventTypeChatBackgroundUpdateFailed PaymentDeclinedWebhookEventEventType = "chat.background_update_failed"
	PaymentDeclinedWebhookEventEventTypeChatTypingIndicatorStarted PaymentDeclinedWebhookEventEventType = "chat.typing_indicator.started"
	PaymentDeclinedWebhookEventEventTypeChatTypingIndicatorStopped PaymentDeclinedWebhookEventEventType = "chat.typing_indicator.stopped"
	PaymentDeclinedWebhookEventEventTypePhoneNumberStatusUpdated   PaymentDeclinedWebhookEventEventType = "phone_number.status_updated"
	PaymentDeclinedWebhookEventEventTypeContactCardReceived        PaymentDeclinedWebhookEventEventType = "contact_card.received"
	PaymentDeclinedWebhookEventEventTypeCallInitiated              PaymentDeclinedWebhookEventEventType = "call.initiated"
	PaymentDeclinedWebhookEventEventTypeCallRinging                PaymentDeclinedWebhookEventEventType = "call.ringing"
	PaymentDeclinedWebhookEventEventTypeCallAnswered               PaymentDeclinedWebhookEventEventType = "call.answered"
	PaymentDeclinedWebhookEventEventTypeCallEnded                  PaymentDeclinedWebhookEventEventType = "call.ended"
	PaymentDeclinedWebhookEventEventTypeCallFailed                 PaymentDeclinedWebhookEventEventType = "call.failed"
	PaymentDeclinedWebhookEventEventTypeCallDeclined               PaymentDeclinedWebhookEventEventType = "call.declined"
	PaymentDeclinedWebhookEventEventTypeCallNoAnswer               PaymentDeclinedWebhookEventEventType = "call.no_answer"
	PaymentDeclinedWebhookEventEventTypeLocationSharingStarted     PaymentDeclinedWebhookEventEventType = "location.sharing.started"
	PaymentDeclinedWebhookEventEventTypeLocationSharingStopped     PaymentDeclinedWebhookEventEventType = "location.sharing.stopped"
	PaymentDeclinedWebhookEventEventTypePaymentDeclined            PaymentDeclinedWebhookEventEventType = "payment.declined"
	PaymentDeclinedWebhookEventEventTypePaymentAuthorized          PaymentDeclinedWebhookEventEventType = "payment.authorized"
	PaymentDeclinedWebhookEventEventTypeConnectionCreated          PaymentDeclinedWebhookEventEventType = "connection.created"
	PaymentDeclinedWebhookEventEventTypeConnectionRevoked          PaymentDeclinedWebhookEventEventType = "connection.revoked"
)

type PaymentExpiredWebhookEvent added in v0.49.0

type PaymentExpiredWebhookEvent struct {
	// API version for the webhook payload format
	APIVersion string `json:"api_version" api:"required"`
	// When the event was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// The payment request, as returned by
	// `GET /v3/payment_requests/{paymentRequestId}`.
	Data PaymentExpiredWebhookEventData `json:"data" api:"required"`
	// Unique identifier for this event (for deduplication)
	EventID string `json:"event_id" api:"required" format:"uuid"`
	// Any of "payment.succeeded", "payment.canceled", "payment.expired",
	// "message.sent", "message.received", "message.read", "message.delivered",
	// "message.failed", "message.edited", "reaction.added", "reaction.removed",
	// "poll.received", "poll.failed", "poll.sent", "poll.delivered", "poll.read",
	// "poll.updated", "poll.vote.added", "poll.vote.removed", "poll.reaction.added",
	// "participant.added", "participant.removed", "chat.created",
	// "chat.group_name_updated", "chat.group_icon_updated",
	// "chat.group_name_update_failed", "chat.group_icon_update_failed",
	// "chat.background_updated", "chat.background_update_failed",
	// "chat.typing_indicator.started", "chat.typing_indicator.stopped",
	// "phone_number.status_updated", "contact_card.received", "call.initiated",
	// "call.ringing", "call.answered", "call.ended", "call.failed", "call.declined",
	// "call.no_answer", "location.sharing.started", "location.sharing.stopped",
	// "payment.declined", "payment.authorized", "connection.created",
	// "connection.revoked".
	EventType PaymentExpiredWebhookEventEventType `json:"event_type" api:"required"`
	// Partner identifier. Present on all webhooks for cross-referencing.
	PartnerID string `json:"partner_id" api:"required"`
	// Trace ID for debugging and correlation across systems.
	TraceID string `json:"trace_id" api:"required"`
	// Date-based webhook payload version. Determined by the `?version=` query
	// parameter in your webhook subscription URL. If no version parameter is
	// specified, defaults based on subscription creation date.
	WebhookVersion string `json:"webhook_version" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		APIVersion     respjson.Field
		CreatedAt      respjson.Field
		Data           respjson.Field
		EventID        respjson.Field
		EventType      respjson.Field
		PartnerID      respjson.Field
		TraceID        respjson.Field
		WebhookVersion respjson.Field
		ExtraFields    map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (PaymentExpiredWebhookEvent) RawJSON added in v0.49.0

func (r PaymentExpiredWebhookEvent) RawJSON() string

Returns the unmodified JSON received from the API

func (*PaymentExpiredWebhookEvent) UnmarshalJSON added in v0.49.0

func (r *PaymentExpiredWebhookEvent) UnmarshalJSON(data []byte) error

type PaymentExpiredWebhookEventData added in v0.49.0

type PaymentExpiredWebhookEventData struct {
	// The payment request id.
	ID string `json:"id" api:"required" format:"uuid"`
	// What was charged at checkout, in the currency's minor units. In `subscription`
	// mode this is the first invoice's total — all items after any discounts are
	// applied.
	Amount int64 `json:"amount" api:"required"`
	// URL the recipient opens to pay
	// (`https://zero.linqapp.com/pay/{slug}?session=...`).
	CheckoutURL string    `json:"checkout_url" api:"required"`
	CreatedAt   time.Time `json:"created_at" api:"required" format:"date-time"`
	Currency    string    `json:"currency" api:"required"`
	Object      string    `json:"object" api:"required"`
	// Any of "succeeded", "failed", "canceled", "expired".
	Status      string `json:"status" api:"required"`
	Description string `json:"description"`
	// Subscription mode — the discount Stripe applied, read back from the coupon.
	// Absent when none was applied.
	Discount PaymentExpiredWebhookEventDataDiscount `json:"discount"`
	// Subscription mode — how often the subscription renews.
	//
	// Any of "day", "week", "month", "year".
	Interval string `json:"interval"`
	// Subscription mode — intervals per renewal.
	IntervalCount int64             `json:"interval_count"`
	Metadata      map[string]string `json:"metadata"`
	// Whether the request collected a one-time charge or started a subscription.
	//
	// Any of "payment", "subscription".
	Mode string `json:"mode"`
	// Natural-rail join keys, present when `rail: natural`.
	Natural PaymentExpiredWebhookEventDataNatural `json:"natural"`
	// Subscription mode — the recurring price subscribed to.
	PriceID string `json:"price_id"`
	// Subscription mode — units of the price subscribed to.
	Quantity int64 `json:"quantity"`
	// The rail this request settled on.
	//
	// Any of "stripe", "natural".
	Rail string `json:"rail"`
	// Ids of the Stripe objects on your connected account — join keys into your own
	// Stripe Dashboard/API. Manage a subscription's post-checkout lifecycle with
	// `subscription_id`.
	Stripe PaymentExpiredWebhookEventDataStripe `json:"stripe"`
	// Subscription mode — when the free trial ends and the first charge happens. On a
	// trial request, `payment.succeeded` means the payment method was collected ($0
	// moved).
	TrialEnd  time.Time `json:"trial_end" format:"date-time"`
	UpdatedAt time.Time `json:"updated_at" format:"date-time"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ID            respjson.Field
		Amount        respjson.Field
		CheckoutURL   respjson.Field
		CreatedAt     respjson.Field
		Currency      respjson.Field
		Object        respjson.Field
		Status        respjson.Field
		Description   respjson.Field
		Discount      respjson.Field
		Interval      respjson.Field
		IntervalCount respjson.Field
		Metadata      respjson.Field
		Mode          respjson.Field
		Natural       respjson.Field
		PriceID       respjson.Field
		Quantity      respjson.Field
		Rail          respjson.Field
		Stripe        respjson.Field
		TrialEnd      respjson.Field
		UpdatedAt     respjson.Field
		ExtraFields   map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

The payment request, as returned by `GET /v3/payment_requests/{paymentRequestId}`.

func (PaymentExpiredWebhookEventData) RawJSON added in v0.49.0

Returns the unmodified JSON received from the API

func (*PaymentExpiredWebhookEventData) UnmarshalJSON added in v0.49.0

func (r *PaymentExpiredWebhookEventData) UnmarshalJSON(data []byte) error

type PaymentExpiredWebhookEventDataDiscount added in v0.49.0

type PaymentExpiredWebhookEventDataDiscount struct {
	Coupon string `json:"coupon"`
	// Name of the coupon/promo code displayed to customers.
	Label         string `json:"label"`
	PromotionCode string `json:"promotion_code"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Coupon        respjson.Field
		Label         respjson.Field
		PromotionCode respjson.Field
		ExtraFields   map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Subscription mode — the discount Stripe applied, read back from the coupon. Absent when none was applied.

func (PaymentExpiredWebhookEventDataDiscount) RawJSON added in v0.49.0

Returns the unmodified JSON received from the API

func (*PaymentExpiredWebhookEventDataDiscount) UnmarshalJSON added in v0.49.0

func (r *PaymentExpiredWebhookEventDataDiscount) UnmarshalJSON(data []byte) error

type PaymentExpiredWebhookEventDataNatural added in v0.49.0

type PaymentExpiredWebhookEventDataNatural struct {
	// The Natural payment request (`prq_...`).
	PaymentRequestID string `json:"payment_request_id"`
	// The settled transaction (`txn_...`).
	TransactionID string `json:"transaction_id"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		PaymentRequestID respjson.Field
		TransactionID    respjson.Field
		ExtraFields      map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Natural-rail join keys, present when `rail: natural`.

func (PaymentExpiredWebhookEventDataNatural) RawJSON added in v0.49.0

Returns the unmodified JSON received from the API

func (*PaymentExpiredWebhookEventDataNatural) UnmarshalJSON added in v0.49.0

func (r *PaymentExpiredWebhookEventDataNatural) UnmarshalJSON(data []byte) error

type PaymentExpiredWebhookEventDataStripe added in v0.49.0

type PaymentExpiredWebhookEventDataStripe struct {
	// The Customer the request is attached to (`cus_...`). Always set in subscription
	// mode; set in payment mode only when the request was created with a
	// `customer_id`.
	CustomerID string `json:"customer_id"`
	// The PaymentIntent collected at checkout (`pi_...`).
	PaymentIntentID string `json:"payment_intent_id"`
	// Subscription mode — the Subscription (`sub_...`).
	SubscriptionID string `json:"subscription_id"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		CustomerID      respjson.Field
		PaymentIntentID respjson.Field
		SubscriptionID  respjson.Field
		ExtraFields     map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Ids of the Stripe objects on your connected account — join keys into your own Stripe Dashboard/API. Manage a subscription's post-checkout lifecycle with `subscription_id`.

func (PaymentExpiredWebhookEventDataStripe) RawJSON added in v0.49.0

Returns the unmodified JSON received from the API

func (*PaymentExpiredWebhookEventDataStripe) UnmarshalJSON added in v0.49.0

func (r *PaymentExpiredWebhookEventDataStripe) UnmarshalJSON(data []byte) error

type PaymentExpiredWebhookEventEventType added in v0.49.0

type PaymentExpiredWebhookEventEventType string
const (
	PaymentExpiredWebhookEventEventTypePaymentSucceeded           PaymentExpiredWebhookEventEventType = "payment.succeeded"
	PaymentExpiredWebhookEventEventTypePaymentCanceled            PaymentExpiredWebhookEventEventType = "payment.canceled"
	PaymentExpiredWebhookEventEventTypePaymentExpired             PaymentExpiredWebhookEventEventType = "payment.expired"
	PaymentExpiredWebhookEventEventTypeMessageSent                PaymentExpiredWebhookEventEventType = "message.sent"
	PaymentExpiredWebhookEventEventTypeMessageReceived            PaymentExpiredWebhookEventEventType = "message.received"
	PaymentExpiredWebhookEventEventTypeMessageRead                PaymentExpiredWebhookEventEventType = "message.read"
	PaymentExpiredWebhookEventEventTypeMessageDelivered           PaymentExpiredWebhookEventEventType = "message.delivered"
	PaymentExpiredWebhookEventEventTypeMessageFailed              PaymentExpiredWebhookEventEventType = "message.failed"
	PaymentExpiredWebhookEventEventTypeMessageEdited              PaymentExpiredWebhookEventEventType = "message.edited"
	PaymentExpiredWebhookEventEventTypeReactionAdded              PaymentExpiredWebhookEventEventType = "reaction.added"
	PaymentExpiredWebhookEventEventTypeReactionRemoved            PaymentExpiredWebhookEventEventType = "reaction.removed"
	PaymentExpiredWebhookEventEventTypePollReceived               PaymentExpiredWebhookEventEventType = "poll.received"
	PaymentExpiredWebhookEventEventTypePollFailed                 PaymentExpiredWebhookEventEventType = "poll.failed"
	PaymentExpiredWebhookEventEventTypePollSent                   PaymentExpiredWebhookEventEventType = "poll.sent"
	PaymentExpiredWebhookEventEventTypePollDelivered              PaymentExpiredWebhookEventEventType = "poll.delivered"
	PaymentExpiredWebhookEventEventTypePollRead                   PaymentExpiredWebhookEventEventType = "poll.read"
	PaymentExpiredWebhookEventEventTypePollUpdated                PaymentExpiredWebhookEventEventType = "poll.updated"
	PaymentExpiredWebhookEventEventTypePollVoteAdded              PaymentExpiredWebhookEventEventType = "poll.vote.added"
	PaymentExpiredWebhookEventEventTypePollVoteRemoved            PaymentExpiredWebhookEventEventType = "poll.vote.removed"
	PaymentExpiredWebhookEventEventTypePollReactionAdded          PaymentExpiredWebhookEventEventType = "poll.reaction.added"
	PaymentExpiredWebhookEventEventTypeParticipantAdded           PaymentExpiredWebhookEventEventType = "participant.added"
	PaymentExpiredWebhookEventEventTypeParticipantRemoved         PaymentExpiredWebhookEventEventType = "participant.removed"
	PaymentExpiredWebhookEventEventTypeChatCreated                PaymentExpiredWebhookEventEventType = "chat.created"
	PaymentExpiredWebhookEventEventTypeChatGroupNameUpdated       PaymentExpiredWebhookEventEventType = "chat.group_name_updated"
	PaymentExpiredWebhookEventEventTypeChatGroupIconUpdated       PaymentExpiredWebhookEventEventType = "chat.group_icon_updated"
	PaymentExpiredWebhookEventEventTypeChatGroupNameUpdateFailed  PaymentExpiredWebhookEventEventType = "chat.group_name_update_failed"
	PaymentExpiredWebhookEventEventTypeChatGroupIconUpdateFailed  PaymentExpiredWebhookEventEventType = "chat.group_icon_update_failed"
	PaymentExpiredWebhookEventEventTypeChatBackgroundUpdated      PaymentExpiredWebhookEventEventType = "chat.background_updated"
	PaymentExpiredWebhookEventEventTypeChatBackgroundUpdateFailed PaymentExpiredWebhookEventEventType = "chat.background_update_failed"
	PaymentExpiredWebhookEventEventTypeChatTypingIndicatorStarted PaymentExpiredWebhookEventEventType = "chat.typing_indicator.started"
	PaymentExpiredWebhookEventEventTypeChatTypingIndicatorStopped PaymentExpiredWebhookEventEventType = "chat.typing_indicator.stopped"
	PaymentExpiredWebhookEventEventTypePhoneNumberStatusUpdated   PaymentExpiredWebhookEventEventType = "phone_number.status_updated"
	PaymentExpiredWebhookEventEventTypeContactCardReceived        PaymentExpiredWebhookEventEventType = "contact_card.received"
	PaymentExpiredWebhookEventEventTypeCallInitiated              PaymentExpiredWebhookEventEventType = "call.initiated"
	PaymentExpiredWebhookEventEventTypeCallRinging                PaymentExpiredWebhookEventEventType = "call.ringing"
	PaymentExpiredWebhookEventEventTypeCallAnswered               PaymentExpiredWebhookEventEventType = "call.answered"
	PaymentExpiredWebhookEventEventTypeCallEnded                  PaymentExpiredWebhookEventEventType = "call.ended"
	PaymentExpiredWebhookEventEventTypeCallFailed                 PaymentExpiredWebhookEventEventType = "call.failed"
	PaymentExpiredWebhookEventEventTypeCallDeclined               PaymentExpiredWebhookEventEventType = "call.declined"
	PaymentExpiredWebhookEventEventTypeCallNoAnswer               PaymentExpiredWebhookEventEventType = "call.no_answer"
	PaymentExpiredWebhookEventEventTypeLocationSharingStarted     PaymentExpiredWebhookEventEventType = "location.sharing.started"
	PaymentExpiredWebhookEventEventTypeLocationSharingStopped     PaymentExpiredWebhookEventEventType = "location.sharing.stopped"
	PaymentExpiredWebhookEventEventTypePaymentDeclined            PaymentExpiredWebhookEventEventType = "payment.declined"
	PaymentExpiredWebhookEventEventTypePaymentAuthorized          PaymentExpiredWebhookEventEventType = "payment.authorized"
	PaymentExpiredWebhookEventEventTypeConnectionCreated          PaymentExpiredWebhookEventEventType = "connection.created"
	PaymentExpiredWebhookEventEventTypeConnectionRevoked          PaymentExpiredWebhookEventEventType = "connection.revoked"
)

type PaymentHandleConnection added in v0.29.0

type PaymentHandleConnection struct {
	// Returned only by `connect`, and only while the ceremony is pending. Nothing on
	// our side persists it — it comes back from the provider and is required again to
	// verify — so hold it until you submit the code.
	ConnectID string `json:"connect_id"`
	Handle    string `json:"handle"`
	// Any of "not_connected", "pending", "connected", "revoked".
	Status PaymentHandleConnectionStatus `json:"status"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ConnectID   respjson.Field
		Handle      respjson.Field
		Status      respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (PaymentHandleConnection) RawJSON added in v0.29.0

func (r PaymentHandleConnection) RawJSON() string

Returns the unmodified JSON received from the API

func (*PaymentHandleConnection) UnmarshalJSON added in v0.29.0

func (r *PaymentHandleConnection) UnmarshalJSON(data []byte) error

type PaymentHandleConnectionStatus added in v0.29.0

type PaymentHandleConnectionStatus string
const (
	PaymentHandleConnectionStatusNotConnected PaymentHandleConnectionStatus = "not_connected"
	PaymentHandleConnectionStatusPending      PaymentHandleConnectionStatus = "pending"
	PaymentHandleConnectionStatusConnected    PaymentHandleConnectionStatus = "connected"
	PaymentHandleConnectionStatusRevoked      PaymentHandleConnectionStatus = "revoked"
)

type PaymentHandleService added in v0.29.0

type PaymentHandleService struct {
	Options []option.RequestOption
}

Let an agent pay on a customer's behalf with a single-use virtual card. Connect a customer once, then create a payment — a virtual card is minted scoped to that purchase and the card details are handed back for checkout.

PaymentHandleService contains methods and other services that help with interacting with the linq-api-v3 API.

Note, unlike clients, this service does not read variables from the environment automatically. You should not instantiate this service directly, and instead use the NewPaymentHandleService method instead.

func NewPaymentHandleService added in v0.29.0

func NewPaymentHandleService(opts ...option.RequestOption) (r PaymentHandleService)

NewPaymentHandleService generates a new service that applies the given options to each request. These options are applied after the parent client's options (if there is one), and before any request-specific options.

func (*PaymentHandleService) Connect added in v0.29.0

func (r *PaymentHandleService) Connect(ctx context.Context, handle string, opts ...option.RequestOption) (res *PaymentHandleConnection, err error)

Starts connecting a customer (by phone/email) so an agent can pay on their behalf. Linq drives the OTP + consent ceremony through the messaging channel; this returns `pending` and a `connection.created` webhook fires once the customer completes it.

func (*PaymentHandleService) Connection added in v0.29.0

func (r *PaymentHandleService) Connection(ctx context.Context, handle string, opts ...option.RequestOption) (res *PaymentHandleConnection, err error)

Get a handle's connection status

func (*PaymentHandleService) Revoke added in v0.29.0

func (r *PaymentHandleService) Revoke(ctx context.Context, handle string, opts ...option.RequestOption) (res *PaymentHandleConnection, err error)

Revokes this partner's grant for the customer. Only your grant is removed; the customer's wallet at the provider is untouched.

func (*PaymentHandleService) Verify added in v0.29.0

Completes the ceremony `connect` started: verifies the code, records the customer's consent, and stores the connection. Returns `connected` on success, after which payments for this handle no longer need the customer present.

The code reaches you however your channel works — typically the customer replies with it in the thread. Codes are single-use and short-lived; if one has expired, call `connect` again for a fresh `connect_id`.

type PaymentHandleVerifyParams added in v0.29.0

type PaymentHandleVerifyParams struct {
	// The one-time code the customer received.
	Code string `json:"code" api:"required"`
	// The id returned by `connect`.
	ConnectID string `json:"connect_id" api:"required"`
	// contains filtered or unexported fields
}

func (PaymentHandleVerifyParams) MarshalJSON added in v0.29.0

func (r PaymentHandleVerifyParams) MarshalJSON() (data []byte, err error)

func (*PaymentHandleVerifyParams) UnmarshalJSON added in v0.29.0

func (r *PaymentHandleVerifyParams) UnmarshalJSON(data []byte) error

type PaymentMerchant added in v0.48.0

type PaymentMerchant struct {
	Name string `json:"name"`
	URL  string `json:"url"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Name        respjson.Field
		URL         respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

The merchant the card is minted against, echoed from the request.

func (PaymentMerchant) RawJSON added in v0.48.0

func (r PaymentMerchant) RawJSON() string

Returns the unmodified JSON received from the API

func (*PaymentMerchant) UnmarshalJSON added in v0.48.0

func (r *PaymentMerchant) UnmarshalJSON(data []byte) error

type PaymentNewParams added in v0.29.0

type PaymentNewParams struct {
	AmountCents int64  `json:"amount_cents" api:"required"`
	Currency    string `json:"currency" api:"required"`
	// Customer phone (E.164) or email.
	Handle      string                   `json:"handle" api:"required"`
	Description param.Opt[string]        `json:"description,omitzero"`
	Merchant    PaymentNewParamsMerchant `json:"merchant,omitzero"`
	Metadata    map[string]string        `json:"metadata,omitzero"`
	// contains filtered or unexported fields
}

func (PaymentNewParams) MarshalJSON added in v0.29.0

func (r PaymentNewParams) MarshalJSON() (data []byte, err error)

func (*PaymentNewParams) UnmarshalJSON added in v0.29.0

func (r *PaymentNewParams) UnmarshalJSON(data []byte) error

type PaymentNewParamsMerchant added in v0.29.0

type PaymentNewParamsMerchant struct {
	Name param.Opt[string] `json:"name,omitzero"`
	URL  param.Opt[string] `json:"url,omitzero"`
	// contains filtered or unexported fields
}

func (PaymentNewParamsMerchant) MarshalJSON added in v0.29.0

func (r PaymentNewParamsMerchant) MarshalJSON() (data []byte, err error)

func (*PaymentNewParamsMerchant) UnmarshalJSON added in v0.29.0

func (r *PaymentNewParamsMerchant) UnmarshalJSON(data []byte) error

type PaymentProvider added in v0.29.0

type PaymentProvider struct {
	Provider string `json:"provider"`
	// Any of "onboarding", "ready", "disabled".
	Status PaymentProviderStatus `json:"status"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Provider    respjson.Field
		Status      respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (PaymentProvider) RawJSON added in v0.29.0

func (r PaymentProvider) RawJSON() string

Returns the unmodified JSON received from the API

func (*PaymentProvider) UnmarshalJSON added in v0.29.0

func (r *PaymentProvider) UnmarshalJSON(data []byte) error

type PaymentProviderConnectParams added in v0.29.0

type PaymentProviderConnectParams struct {
	// Where to send the admin after they authorize the connection.
	ReturnURL string `json:"return_url" api:"required"`
	// contains filtered or unexported fields
}

func (PaymentProviderConnectParams) MarshalJSON added in v0.29.0

func (r PaymentProviderConnectParams) MarshalJSON() (data []byte, err error)

func (*PaymentProviderConnectParams) UnmarshalJSON added in v0.29.0

func (r *PaymentProviderConnectParams) UnmarshalJSON(data []byte) error

type PaymentProviderConnectResponse added in v0.29.0

type PaymentProviderConnectResponse struct {
	// Send the admin here to authorize the connection.
	HostedURL string `json:"hosted_url"`
	SessionID string `json:"session_id"`
	Status    string `json:"status"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		HostedURL   respjson.Field
		SessionID   respjson.Field
		Status      respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (PaymentProviderConnectResponse) RawJSON added in v0.29.0

Returns the unmodified JSON received from the API

func (*PaymentProviderConnectResponse) UnmarshalJSON added in v0.29.0

func (r *PaymentProviderConnectResponse) UnmarshalJSON(data []byte) error

type PaymentProviderService added in v0.29.0

type PaymentProviderService struct {
	Options []option.RequestOption
}

Let an agent pay on a customer's behalf with a single-use virtual card. Connect a customer once, then create a payment — a virtual card is minted scoped to that purchase and the card details are handed back for checkout.

PaymentProviderService contains methods and other services that help with interacting with the linq-api-v3 API.

Note, unlike clients, this service does not read variables from the environment automatically. You should not instantiate this service directly, and instead use the NewPaymentProviderService method instead.

func NewPaymentProviderService added in v0.29.0

func NewPaymentProviderService(opts ...option.RequestOption) (r PaymentProviderService)

NewPaymentProviderService generates a new service that applies the given options to each request. These options are applied after the parent client's options (if there is one), and before any request-specific options.

func (*PaymentProviderService) Connect added in v0.29.0

Begins connecting your organization to a payment provider (e.g. `agentcard`). Returns a hosted URL where an admin authorizes the connection; on completion the provider redirects back and Linq stores your connected credentials.

func (*PaymentProviderService) Get added in v0.29.0

func (r *PaymentProviderService) Get(ctx context.Context, provider string, opts ...option.RequestOption) (res *PaymentProvider, err error)

Returns your organization's onboarding status for a payment provider.

type PaymentProviderStatus added in v0.29.0

type PaymentProviderStatus string
const (
	PaymentProviderStatusOnboarding PaymentProviderStatus = "onboarding"
	PaymentProviderStatusReady      PaymentProviderStatus = "ready"
	PaymentProviderStatusDisabled   PaymentProviderStatus = "disabled"
)

type PaymentRequest added in v0.27.0

type PaymentRequest struct {
	// Unique identifier of the payment request.
	ID string `json:"id" api:"required" format:"uuid"`
	// What the recipient is charged at checkout, in the currency's minor units. In
	// `subscription` mode this is the first invoice's amount due — all items after any
	// discounts are applied — so a discount that covers the whole invoice returns `0`
	// and checkout shows $0.00.
	Amount int64 `json:"amount" api:"required"`
	// URL the recipient opens to pay:
	// `https://zero.linqapp.com/pay/{slug}?session=...`, where `{slug}` is your
	// partner checkout slug.
	CheckoutURL string    `json:"checkout_url" api:"required"`
	CreatedAt   time.Time `json:"created_at" api:"required" format:"date-time"`
	Currency    string    `json:"currency" api:"required"`
	// Whether this request collects a one-time charge or starts a subscription.
	//
	// Any of "payment", "subscription".
	Mode   PaymentRequestMode `json:"mode" api:"required"`
	Object string             `json:"object" api:"required"`
	// Lifecycle status of the payment request.
	//
	// Any of "requested", "succeeded", "canceled", "expired".
	Status      PaymentRequestStatus `json:"status" api:"required"`
	Description string               `json:"description"`
	// Subscription mode — the discount applied, as Stripe applied it.
	Discount PaymentRequestDiscount `json:"discount"`
	// When an unpaid request auto-expires.
	ExpiresAt time.Time `json:"expires_at" format:"date-time"`
	// Subscription mode — how often the subscription renews.
	//
	// Any of "day", "week", "month", "year".
	Interval PaymentRequestInterval `json:"interval"`
	// Subscription mode — intervals per renewal (e.g. `3` + `month` = quarterly).
	IntervalCount int64             `json:"interval_count"`
	Metadata      map[string]string `json:"metadata"`
	// Natural-rail join keys, present when `rail: natural`.
	Natural PaymentRequestNatural `json:"natural"`
	// When the request was paid. Absent until it succeeds.
	PaidAt time.Time `json:"paid_at" format:"date-time"`
	// Subscription mode — the recurring price this request subscribes to.
	PriceID string `json:"price_id"`
	// Subscription mode — units of the price subscribed to.
	Quantity int64 `json:"quantity"`
	// The rail this request settled on.
	//
	// Any of "stripe", "natural".
	Rail PaymentRequestRail `json:"rail"`
	// Ids of the Stripe objects created **on your connected account** — your join keys
	// into your own Stripe Dashboard, webhooks, and API. After a subscription's first
	// payment succeeds, its ongoing lifecycle (renewals, plan changes, cancellation)
	// is managed in your Stripe account using `subscription_id`.
	Stripe PaymentRequestStripe `json:"stripe"`
	// Subscription mode — when the free trial ends and the first charge happens.
	// Present only on trial requests; `paid_at`/`succeeded` mean the payment method
	// was collected (no funds move until this time).
	TrialEnd  time.Time `json:"trial_end" format:"date-time"`
	UpdatedAt time.Time `json:"updated_at" format:"date-time"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ID            respjson.Field
		Amount        respjson.Field
		CheckoutURL   respjson.Field
		CreatedAt     respjson.Field
		Currency      respjson.Field
		Mode          respjson.Field
		Object        respjson.Field
		Status        respjson.Field
		Description   respjson.Field
		Discount      respjson.Field
		ExpiresAt     respjson.Field
		Interval      respjson.Field
		IntervalCount respjson.Field
		Metadata      respjson.Field
		Natural       respjson.Field
		PaidAt        respjson.Field
		PriceID       respjson.Field
		Quantity      respjson.Field
		Rail          respjson.Field
		Stripe        respjson.Field
		TrialEnd      respjson.Field
		UpdatedAt     respjson.Field
		ExtraFields   map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (PaymentRequest) RawJSON added in v0.27.0

func (r PaymentRequest) RawJSON() string

Returns the unmodified JSON received from the API

func (*PaymentRequest) UnmarshalJSON added in v0.27.0

func (r *PaymentRequest) UnmarshalJSON(data []byte) error

type PaymentRequestDiscount added in v0.44.0

type PaymentRequestDiscount struct {
	// The ID of the coupon applied.
	Coupon string `json:"coupon"`
	// The customer-facing discount description shown at checkout.
	Label string `json:"label"`
	// The ID of the promotion code applied, if you passed one.
	PromotionCode string `json:"promotion_code"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Coupon        respjson.Field
		Label         respjson.Field
		PromotionCode respjson.Field
		ExtraFields   map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Subscription mode — the discount applied, as Stripe applied it.

func (PaymentRequestDiscount) RawJSON added in v0.44.0

func (r PaymentRequestDiscount) RawJSON() string

Returns the unmodified JSON received from the API

func (*PaymentRequestDiscount) UnmarshalJSON added in v0.44.0

func (r *PaymentRequestDiscount) UnmarshalJSON(data []byte) error

type PaymentRequestInterval added in v0.27.0

type PaymentRequestInterval string

Subscription mode — how often the subscription renews.

const (
	PaymentRequestIntervalDay   PaymentRequestInterval = "day"
	PaymentRequestIntervalWeek  PaymentRequestInterval = "week"
	PaymentRequestIntervalMonth PaymentRequestInterval = "month"
	PaymentRequestIntervalYear  PaymentRequestInterval = "year"
)

type PaymentRequestListParams added in v0.27.0

type PaymentRequestListParams struct {
	// Max results to return (default 20, max 100).
	Limit param.Opt[int64] `query:"limit,omitzero" json:"-"`
	// Number of results to skip.
	Offset param.Opt[int64] `query:"offset,omitzero" json:"-"`
	// Filter by lifecycle status.
	//
	// Any of "requested", "authorized", "succeeded", "canceled", "expired",
	// "declined".
	Status PaymentRequestListParamsStatus `query:"status,omitzero" json:"-"`
	// contains filtered or unexported fields
}

func (PaymentRequestListParams) URLQuery added in v0.27.0

func (r PaymentRequestListParams) URLQuery() (v url.Values, err error)

URLQuery serializes PaymentRequestListParams's query parameters as `url.Values`.

type PaymentRequestListParamsStatus added in v0.27.0

type PaymentRequestListParamsStatus string

Filter by lifecycle status.

const (
	PaymentRequestListParamsStatusRequested  PaymentRequestListParamsStatus = "requested"
	PaymentRequestListParamsStatusAuthorized PaymentRequestListParamsStatus = "authorized"
	PaymentRequestListParamsStatusSucceeded  PaymentRequestListParamsStatus = "succeeded"
	PaymentRequestListParamsStatusCanceled   PaymentRequestListParamsStatus = "canceled"
	PaymentRequestListParamsStatusExpired    PaymentRequestListParamsStatus = "expired"
	PaymentRequestListParamsStatusDeclined   PaymentRequestListParamsStatus = "declined"
)

type PaymentRequestListResponse added in v0.27.0

type PaymentRequestListResponse struct {
	Data []PaymentRequest `json:"data" api:"required"`
	// Whether more results exist beyond this page.
	HasMore bool `json:"has_more" api:"required"`
	// Any of "list".
	Object PaymentRequestListResponseObject `json:"object" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Data        respjson.Field
		HasMore     respjson.Field
		Object      respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (PaymentRequestListResponse) RawJSON added in v0.27.0

func (r PaymentRequestListResponse) RawJSON() string

Returns the unmodified JSON received from the API

func (*PaymentRequestListResponse) UnmarshalJSON added in v0.27.0

func (r *PaymentRequestListResponse) UnmarshalJSON(data []byte) error

type PaymentRequestListResponseObject added in v0.27.0

type PaymentRequestListResponseObject string
const (
	PaymentRequestListResponseObjectList PaymentRequestListResponseObject = "list"
)

type PaymentRequestMode added in v0.27.0

type PaymentRequestMode string

Whether this request collects a one-time charge or starts a subscription.

const (
	PaymentRequestModePayment      PaymentRequestMode = "payment"
	PaymentRequestModeSubscription PaymentRequestMode = "subscription"
)

type PaymentRequestNatural added in v0.27.0

type PaymentRequestNatural struct {
	// The Natural payment request (`prq_...`).
	PaymentRequestID string `json:"payment_request_id"`
	// The settled transaction (`txn_...`).
	TransactionID string `json:"transaction_id"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		PaymentRequestID respjson.Field
		TransactionID    respjson.Field
		ExtraFields      map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Natural-rail join keys, present when `rail: natural`.

func (PaymentRequestNatural) RawJSON added in v0.27.0

func (r PaymentRequestNatural) RawJSON() string

Returns the unmodified JSON received from the API

func (*PaymentRequestNatural) UnmarshalJSON added in v0.27.0

func (r *PaymentRequestNatural) UnmarshalJSON(data []byte) error

type PaymentRequestNewParams added in v0.27.0

type PaymentRequestNewParams struct {
	// Amount to charge, in the currency's minor units (e.g. cents). Must be at least
	// the payment provider's minimum (50 for `usd`). Required in `payment` mode; must
	// be omitted in `subscription` mode (the amount comes from the price).
	Amount param.Opt[int64] `json:"amount,omitzero"`
	// Three-letter ISO 4217 currency code. Only `usd` is currently supported. Required
	// in `payment` mode; must be omitted in `subscription` mode (the currency comes
	// from the price).
	Currency param.Opt[string] `json:"currency,omitzero"`
	// Optional id of an **existing Customer** on your connected Stripe account
	// (`cus_...`) to attach this request to, instead of a new Customer being created.
	// In `payment` mode the charge lands on that customer's payment history; in
	// `subscription` mode the subscription is created on them. The customer must exist
	// (and not be deleted) on your connected account.
	CustomerID param.Opt[string] `json:"customer_id,omitzero"`
	// Optional description shown to the recipient at checkout.
	Description param.Opt[string] `json:"description,omitzero"`
	// Required for `rail: natural`. The line the request is sent from, in E.164
	// format. Must be a phone number your organization owns.
	From param.Opt[string] `json:"from,omitzero"`
	// Required for `rail: natural`. The payer to bill, in E.164 format.
	PayerHandle param.Opt[string] `json:"payer_handle,omitzero"`
	// Subscription mode only (required there): id of an **active recurring Price** on
	// your connected Stripe account (`price_...`). If you sell through Stripe Payment
	// Links today, pass the same price the link was built from to get the native
	// iMessage checkout for it.
	PriceID param.Opt[string] `json:"price_id,omitzero"`
	// Subscription mode only — units of the price to subscribe to.
	Quantity param.Opt[int64] `json:"quantity,omitzero"`
	// Subscription mode only — end the free trial at a fixed timestamp (must be in the
	// future) instead of a day count. Mutually exclusive with `trial_period_days`.
	TrialEnd param.Opt[time.Time] `json:"trial_end,omitzero" format:"date-time"`
	// Subscription mode only — start with a free trial of this many days. The
	// recipient's card is still collected at checkout (Apple Pay or card), saved to
	// the subscription, and first charged when the trial ends. Mutually exclusive with
	// `trial_end`.
	TrialPeriodDays param.Opt[int64]  `json:"trial_period_days,omitzero"`
	IdempotencyKey  param.Opt[string] `header:"Idempotency-Key,omitzero" json:"-"`
	// Subscription mode only. The coupon or promotion code to apply to this
	// subscription payment. Currently, only accept one coupon or one promo code.
	Discount PaymentRequestNewParamsDiscount `json:"discount,omitzero"`
	// Optional key/value metadata (up to 49 keys) echoed back on retrieval and on
	// `payment.*` webhooks, and stamped on the Stripe objects we create on your
	// connected account (the PaymentIntent, and in subscription mode the Subscription
	// and any Customer created for you — a customer you pass via `customer_id` is
	// never modified) — use it to correlate a request with your own records (e.g. a
	// chat id). Keys starting with `linq_` are reserved.
	Metadata map[string]string `json:"metadata,omitzero"`
	// `payment` (default) collects a one-time charge for `amount` + `currency`.
	// `subscription` starts an auto-renewing subscription from a recurring `price_id`
	// on your connected Stripe account: the recipient pays the first invoice at
	// checkout and Stripe renews it automatically from then on.
	//
	// Any of "payment", "subscription".
	Mode PaymentRequestNewParamsMode `json:"mode,omitzero"`
	// Payment rail. `stripe` (default) is the direct-charge flow that settles to your
	// connected Stripe account. `natural` collects through the Natural custodial
	// wallet; it requires `from` + `payer_handle` and that your organization has
	// completed Natural merchant onboarding.
	//
	// Any of "stripe", "natural".
	Rail PaymentRequestNewParamsRail `json:"rail,omitzero"`
	// contains filtered or unexported fields
}

func (PaymentRequestNewParams) MarshalJSON added in v0.27.0

func (r PaymentRequestNewParams) MarshalJSON() (data []byte, err error)

func (*PaymentRequestNewParams) UnmarshalJSON added in v0.27.0

func (r *PaymentRequestNewParams) UnmarshalJSON(data []byte) error

type PaymentRequestNewParamsDiscount added in v0.44.0

type PaymentRequestNewParamsDiscount struct {
	// The ID of the coupon to apply to this subscription.
	Coupon param.Opt[string] `json:"coupon,omitzero"`
	// Name of the coupon/promo code displayed to customers.
	Label param.Opt[string] `json:"label,omitzero"`
	// The ID of a promotion code to apply to this subscription.
	PromotionCode param.Opt[string] `json:"promotion_code,omitzero"`
	// contains filtered or unexported fields
}

Subscription mode only. The coupon or promotion code to apply to this subscription payment. Currently, only accept one coupon or one promo code.

func (PaymentRequestNewParamsDiscount) MarshalJSON added in v0.44.0

func (r PaymentRequestNewParamsDiscount) MarshalJSON() (data []byte, err error)

func (*PaymentRequestNewParamsDiscount) UnmarshalJSON added in v0.44.0

func (r *PaymentRequestNewParamsDiscount) UnmarshalJSON(data []byte) error

type PaymentRequestNewParamsMode added in v0.27.0

type PaymentRequestNewParamsMode string

`payment` (default) collects a one-time charge for `amount` + `currency`. `subscription` starts an auto-renewing subscription from a recurring `price_id` on your connected Stripe account: the recipient pays the first invoice at checkout and Stripe renews it automatically from then on.

const (
	PaymentRequestNewParamsModePayment      PaymentRequestNewParamsMode = "payment"
	PaymentRequestNewParamsModeSubscription PaymentRequestNewParamsMode = "subscription"
)

type PaymentRequestNewParamsRail added in v0.27.0

type PaymentRequestNewParamsRail string

Payment rail. `stripe` (default) is the direct-charge flow that settles to your connected Stripe account. `natural` collects through the Natural custodial wallet; it requires `from` + `payer_handle` and that your organization has completed Natural merchant onboarding.

const (
	PaymentRequestNewParamsRailStripe  PaymentRequestNewParamsRail = "stripe"
	PaymentRequestNewParamsRailNatural PaymentRequestNewParamsRail = "natural"
)

type PaymentRequestRail added in v0.27.0

type PaymentRequestRail string

The rail this request settled on.

const (
	PaymentRequestRailStripe  PaymentRequestRail = "stripe"
	PaymentRequestRailNatural PaymentRequestRail = "natural"
)

type PaymentRequestService added in v0.27.0

type PaymentRequestService struct {
	Options []option.RequestOption
}

Request a payment from a recipient over iMessage. You create a payment request, send its `checkout_url` to the recipient, and they pay with Apple Pay or card. Funds settle **directly to your own Stripe account** — Linq never holds the money.

## How it works

  1. **Create** a payment request with an amount and currency. You get back a `checkout_url` and a `status` of `requested`.
  2. **Send** the `checkout_url` to the recipient as a `link` message part so it arrives as a tappable card (see _Sending the link_ below).
  3. The recipient **pays** on the hosted checkout (Apple Pay App Clip on a supported iPhone, web checkout everywhere else).
  4. You receive a **`payment.succeeded`** webhook and the request's `status` becomes `succeeded`. Requests you don't collect eventually `expire`.

## Connected accounts (Stripe Standard, direct charges)

Payments run on **Stripe Connect Standard accounts** using **direct charges**: the charge is created on _your_ connected account and **you are the merchant of record**. That means the money, the payout schedule, the customer relationship, and the compliance surface are all yours — Linq orchestrates the request and the checkout but is never in the funds flow.

**Refunds, disputes, and chargebacks are handled by you, in your own Stripe Dashboard.** Because charges settle directly to your account, Linq has no custody of the funds and cannot issue refunds or contest disputes on your behalf — and there is no refund/dispute endpoint in this API by design. Use the Stripe Dashboard (or the Stripe API on your own account) for the money lifecycle after a payment succeeds.

## Getting set up

Open **Agent Pay** in your Linq dashboard (`https://zero.linqapp.com/organization/payments`), click **Connect Stripe**, and complete Stripe's onboarding (business details + a bank account). When your account reaches `charges_enabled`, request creation unlocks; until you connect Stripe, `POST /v3/payment_requests` returns `403`. You can keep collecting even while Stripe finishes background verification.

## Subscriptions

Set `mode: subscription` on `POST /v3/payment_requests` to start an **auto-renewing subscription** instead of a one-time charge. Instead of an amount, you pass a `price_id` — an active **recurring Price** on your connected Stripe account (create one in your Stripe Dashboard under Product catalog; if you sell through Stripe Payment Links today, reuse the price your link is built from). The recipient pays the first invoice at the same checkout, and their payment method is saved to the subscription for automatic renewals.

The division of labor is deliberate: **Linq handles the first payment, your Stripe account handles the rest.** The request reaches `succeeded` when the first invoice is paid; from then on the subscription lives entirely on your connected account. The response's `stripe` object gives you the join keys — `customer_id` and `subscription_id` — so renewals, plan changes, dunning, and cancellation are managed with your own Stripe Dashboard/API and your own Stripe webhooks. Your `metadata` is stamped on the Customer and Subscription, so correlating in either direction is trivial. There are no renewal webhooks from Linq by design.

### Discounts

Pass a `discount` with a **coupon** or **promotion code** from your connected Stripe account to apply it to the subscription. Create either in your Stripe Dashboard under Product catalog → Coupons; Linq only forwards the id.

```json

{
  "mode": "subscription",
  "price_id": "price_1QAbCdEfGhIjKlMn",
  "discount": {
    "coupon": "7fKCMvBh",
    "label": "50% OFF FIRST MONTH"
  }
}

```

Stripe applies the coupon and prices the first invoice; the `amount` we return is that invoice's amount due, so a `$50.00/month` price with a 50%-off-first-month coupon comes back as `2500` and the recipient is charged **$25.00** at checkout. A coupon that covers the whole first invoice returns `amount: 0`; checkout shows $0.00 and collects the card for the renewal rather than charging now. Renewals bill at the full price automatically — how long a discount lasts is the coupon's `duration`, enforced by Stripe on your account, and Linq never re-prices anything.

Use `promotion_code` instead of `coupon` to apply a promotion code by id (`promo_...`, not the customer-facing code string); pass one or the other, never both.

`label` is the customer-facing promotion name displayed at checkout instead of the coupon or promotion code ID. The label is displayed exactly as provided, so include important terms such as "FIRST MONTH" or "FIRST 3 MONTHS" when applicable. These terms are not displayed elsewhere on the checkout screen.

If omitted, Stripe uses the coupon's name as the promotion label.

### Free trials

Add `trial_period_days` (or a fixed `trial_end` timestamp) to start the subscription with a free trial. The checkout still collects the recipient's payment method — the pay sheet shows "$0 due today" with the first charge date — and saves it to the subscription; Stripe bills it automatically when the trial ends. The request reaches `succeeded` when the card is collected, and the response carries `trial_end`. If the trial would end without a payment method on file, the subscription cancels rather than generating unpayable invoices. Trial lifecycle after checkout (extending, ending early) is managed in your own Stripe account via `stripe.subscription_id`.

A subscription request you cancel (or that expires unpaid) cancels the incomplete Stripe subscription — nothing lingers on your account.

## Pre-created customers

By default each request stands alone: payment mode attaches no Customer, and subscription mode creates a fresh one. If you already manage Customers on your connected account, pass their id as `customer_id` (`cus_...`) on create — in payment mode the charge lands on that customer's payment history, and in subscription mode the subscription is created on them instead of on a new Customer. The id must reference an existing, non-deleted customer on your connected account or the request fails with `400`. We never modify a customer you pass — no metadata is stamped on it.

## Sending the link

Deliver the `checkout_url` as a **`link` message part** via `POST /v3/chats/{chatId}/messages` — it renders as a rich card with your branding (title, amount, image) instead of a bare URL, which converts far better. A `link` part must be the only part in the message. See [Rich Link Previews](/channel/imessage/guides/messaging/sending-messages).

On a supported iPhone the link opens an **Apple Pay App Clip** — a native, no-install checkout sheet. Everywhere else (Android, desktop, iPhones without the App Clip yet) the same URL opens the web checkout, so the link always works. The App Clip experience for your payment links is registered automatically by Linq and refreshed whenever you update your payments branding; a newly registered experience can take up to ~24 hours to activate on Apple's side, during which links open the web checkout.

## Sending it as a card instead

A `link` part is one way to deliver a request. The other is the **`agentpay` experience**, which sends the same request as a native card in Linq's iMessage app — the amount and reason are drawn in the bubble, and it turns itself into "Paid" in place once the payment succeeds, without a second message.

Send it to `POST /v3/chats/{chatId}/messages`:

```json

{
  "message": {
    "experience": {
      "name": "agentpay",
      "action": "request_payment",
      "params": {
        "checkout_url": "https://zero.linqapp.com/pay/acme?session=tok_..."
      }
    }
  }
}

```

`checkout_url` is the only required field — pass back exactly what `POST /v3/payment_requests` returned. **The amount and reason are read from that request, never from you**, so the card can never claim a different figure than the checkout will charge. Optional `title` and `note` override the copy only. The link must be one of your own payment requests; another partner's is rejected.

The trade-off against a `link` part: a card is an app card, so it is iMessage-only, and recipients without the app see a static version of it. A link works everywhere and is what opens the Apple Pay App Clip. Send whichever suits the conversation — both settle the same payment request and fire the same webhooks.

## Webhooks

Subscribe to payment lifecycle events to reconcile server-side rather than polling: `payment.succeeded`, `payment.canceled`, and `payment.expired`. Each event carries the payment request id, amount, currency, and your `metadata`. See [Webhooks](/channel/imessage/guides/webhooks).

PaymentRequestService contains methods and other services that help with interacting with the linq-api-v3 API.

Note, unlike clients, this service does not read variables from the environment automatically. You should not instantiate this service directly, and instead use the NewPaymentRequestService method instead.

func NewPaymentRequestService added in v0.27.0

func NewPaymentRequestService(opts ...option.RequestOption) (r PaymentRequestService)

NewPaymentRequestService generates a new service that applies the given options to each request. These options are applied after the parent client's options (if there is one), and before any request-specific options.

func (*PaymentRequestService) Cancel added in v0.27.0

func (r *PaymentRequestService) Cancel(ctx context.Context, paymentRequestID string, opts ...option.RequestOption) (res *PaymentRequest, err error)

Cancels an unpaid payment request: the underlying payment intent is canceled and the request moves to `canceled`. A request that is already paid, canceled, or expired returns 409.

func (*PaymentRequestService) Get added in v0.27.0

func (r *PaymentRequestService) Get(ctx context.Context, paymentRequestID string, opts ...option.RequestOption) (res *PaymentRequest, err error)

Returns a payment request's status and details.

func (*PaymentRequestService) List added in v0.27.0

Lists your payment requests, newest first, for reconciliation. Paginate with `limit` + `offset`; `has_more` indicates whether another page exists.

func (*PaymentRequestService) New added in v0.27.0

Creates a payment request and returns a `checkout_url` the recipient opens to pay with Apple Pay or card. Funds settle directly to your connected Stripe account. A payment request is independent of any chat; to associate one with a chat for your records, store the chat id in `metadata`. Requires your connected account to be `charges_enabled` (returns `403` otherwise).

Set `mode: subscription` with a recurring `price_id` from your connected Stripe account to start an **auto-renewing subscription** instead of a one-time charge — the recipient pays the first invoice at checkout and the response's `stripe` object carries the customer and subscription ids for the ongoing lifecycle in your own Stripe account. See the _Subscriptions_ section of the tag overview.

In either mode, pass `customer_id` to attach the request to an **existing Customer** on your connected account instead of creating a new one — see _Pre-created customers_ in the tag overview.

type PaymentRequestStatus added in v0.27.0

type PaymentRequestStatus string

Lifecycle status of the payment request.

const (
	PaymentRequestStatusRequested PaymentRequestStatus = "requested"
	PaymentRequestStatusSucceeded PaymentRequestStatus = "succeeded"
	PaymentRequestStatusCanceled  PaymentRequestStatus = "canceled"
	PaymentRequestStatusExpired   PaymentRequestStatus = "expired"
)

type PaymentRequestStripe added in v0.27.0

type PaymentRequestStripe struct {
	// The Customer this request is attached to (`cus_...`). Always set in subscription
	// mode (created for you unless you passed `customer_id`); set in payment mode only
	// when you passed one.
	CustomerID string `json:"customer_id"`
	// The PaymentIntent collected at checkout (`pi_...`).
	PaymentIntentID string `json:"payment_intent_id"`
	// Subscription mode — the Subscription (`sub_...`).
	SubscriptionID string `json:"subscription_id"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		CustomerID      respjson.Field
		PaymentIntentID respjson.Field
		SubscriptionID  respjson.Field
		ExtraFields     map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Ids of the Stripe objects created **on your connected account** — your join keys into your own Stripe Dashboard, webhooks, and API. After a subscription's first payment succeeds, its ongoing lifecycle (renewals, plan changes, cancellation) is managed in your Stripe account using `subscription_id`.

func (PaymentRequestStripe) RawJSON added in v0.27.0

func (r PaymentRequestStripe) RawJSON() string

Returns the unmodified JSON received from the API

func (*PaymentRequestStripe) UnmarshalJSON added in v0.27.0

func (r *PaymentRequestStripe) UnmarshalJSON(data []byte) error

type PaymentService added in v0.29.0

type PaymentService struct {
	Options []option.RequestOption
}

Let an agent pay on a customer's behalf with a single-use virtual card. Connect a customer once, then create a payment — a virtual card is minted scoped to that purchase and the card details are handed back for checkout.

PaymentService contains methods and other services that help with interacting with the linq-api-v3 API.

Note, unlike clients, this service does not read variables from the environment automatically. You should not instantiate this service directly, and instead use the NewPaymentService method instead.

func NewPaymentService added in v0.29.0

func NewPaymentService(opts ...option.RequestOption) (r PaymentService)

NewPaymentService generates a new service that applies the given options to each request. These options are applied after the parent client's options (if there is one), and before any request-specific options.

func (*PaymentService) Cancel added in v0.29.0

func (r *PaymentService) Cancel(ctx context.Context, paymentID string, opts ...option.RequestOption) (res *Payment, err error)

Closes the virtual card and cancels the payment.

func (*PaymentService) Credentials added in v0.29.0

func (r *PaymentService) Credentials(ctx context.Context, paymentID string, opts ...option.RequestOption) (res *PaymentCredentialsResponse, err error)

Returns a short-lived handoff for a `ready` payment. Fetch the card credentials **directly from the provider** with the returned `user_token` at `fetch_url` — the card number never passes through Linq. Do not persist PAN/CVC.

func (*PaymentService) Get added in v0.29.0

func (r *PaymentService) Get(ctx context.Context, paymentID string, opts ...option.RequestOption) (res *Payment, err error)

Get a payment

func (*PaymentService) New added in v0.29.0

func (r *PaymentService) New(ctx context.Context, body PaymentNewParams, opts ...option.RequestOption) (res *Payment, err error)

Advances the pay flow for a connected customer handle and returns a `status` describing where it is (`needs_connection`, `awaiting_user_action`, `ready`, ...). A payment `id` appears once a card is minted. Idempotent on the `Idempotency-Key` header.

type PaymentStatus added in v0.29.0

type PaymentStatus string
const (
	PaymentStatusNeedsConnection    PaymentStatus = "needs_connection"
	PaymentStatusConnecting         PaymentStatus = "connecting"
	PaymentStatusAwaitingUserAction PaymentStatus = "awaiting_user_action"
	PaymentStatusReady              PaymentStatus = "ready"
	PaymentStatusAuthorized         PaymentStatus = "authorized"
	PaymentStatusSucceeded          PaymentStatus = "succeeded"
	PaymentStatusDeclined           PaymentStatus = "declined"
	PaymentStatusCanceled           PaymentStatus = "canceled"
	PaymentStatusExpired            PaymentStatus = "expired"
)

type PaymentSucceededWebhookEvent added in v0.49.0

type PaymentSucceededWebhookEvent struct {
	// API version for the webhook payload format
	APIVersion string `json:"api_version" api:"required"`
	// When the event was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// The payment request, as returned by
	// `GET /v3/payment_requests/{paymentRequestId}`.
	Data PaymentSucceededWebhookEventData `json:"data" api:"required"`
	// Unique identifier for this event (for deduplication)
	EventID string `json:"event_id" api:"required" format:"uuid"`
	// Any of "payment.succeeded", "payment.canceled", "payment.expired",
	// "message.sent", "message.received", "message.read", "message.delivered",
	// "message.failed", "message.edited", "reaction.added", "reaction.removed",
	// "poll.received", "poll.failed", "poll.sent", "poll.delivered", "poll.read",
	// "poll.updated", "poll.vote.added", "poll.vote.removed", "poll.reaction.added",
	// "participant.added", "participant.removed", "chat.created",
	// "chat.group_name_updated", "chat.group_icon_updated",
	// "chat.group_name_update_failed", "chat.group_icon_update_failed",
	// "chat.background_updated", "chat.background_update_failed",
	// "chat.typing_indicator.started", "chat.typing_indicator.stopped",
	// "phone_number.status_updated", "contact_card.received", "call.initiated",
	// "call.ringing", "call.answered", "call.ended", "call.failed", "call.declined",
	// "call.no_answer", "location.sharing.started", "location.sharing.stopped",
	// "payment.declined", "payment.authorized", "connection.created",
	// "connection.revoked".
	EventType PaymentSucceededWebhookEventEventType `json:"event_type" api:"required"`
	// Partner identifier. Present on all webhooks for cross-referencing.
	PartnerID string `json:"partner_id" api:"required"`
	// Trace ID for debugging and correlation across systems.
	TraceID string `json:"trace_id" api:"required"`
	// Date-based webhook payload version. Determined by the `?version=` query
	// parameter in your webhook subscription URL. If no version parameter is
	// specified, defaults based on subscription creation date.
	WebhookVersion string `json:"webhook_version" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		APIVersion     respjson.Field
		CreatedAt      respjson.Field
		Data           respjson.Field
		EventID        respjson.Field
		EventType      respjson.Field
		PartnerID      respjson.Field
		TraceID        respjson.Field
		WebhookVersion respjson.Field
		ExtraFields    map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (PaymentSucceededWebhookEvent) RawJSON added in v0.49.0

Returns the unmodified JSON received from the API

func (*PaymentSucceededWebhookEvent) UnmarshalJSON added in v0.49.0

func (r *PaymentSucceededWebhookEvent) UnmarshalJSON(data []byte) error

type PaymentSucceededWebhookEventData added in v0.49.0

type PaymentSucceededWebhookEventData struct {
	// The payment request id.
	ID string `json:"id" api:"required" format:"uuid"`
	// What was charged at checkout, in the currency's minor units. In `subscription`
	// mode this is the first invoice's total — all items after any discounts are
	// applied.
	Amount int64 `json:"amount" api:"required"`
	// URL the recipient opens to pay
	// (`https://zero.linqapp.com/pay/{slug}?session=...`).
	CheckoutURL string    `json:"checkout_url" api:"required"`
	CreatedAt   time.Time `json:"created_at" api:"required" format:"date-time"`
	Currency    string    `json:"currency" api:"required"`
	Object      string    `json:"object" api:"required"`
	// Any of "succeeded", "failed", "canceled", "expired".
	Status      string `json:"status" api:"required"`
	Description string `json:"description"`
	// Subscription mode — the discount Stripe applied, read back from the coupon.
	// Absent when none was applied.
	Discount PaymentSucceededWebhookEventDataDiscount `json:"discount"`
	// Subscription mode — how often the subscription renews.
	//
	// Any of "day", "week", "month", "year".
	Interval string `json:"interval"`
	// Subscription mode — intervals per renewal.
	IntervalCount int64             `json:"interval_count"`
	Metadata      map[string]string `json:"metadata"`
	// Whether the request collected a one-time charge or started a subscription.
	//
	// Any of "payment", "subscription".
	Mode string `json:"mode"`
	// Natural-rail join keys, present when `rail: natural`.
	Natural PaymentSucceededWebhookEventDataNatural `json:"natural"`
	// Subscription mode — the recurring price subscribed to.
	PriceID string `json:"price_id"`
	// Subscription mode — units of the price subscribed to.
	Quantity int64 `json:"quantity"`
	// The rail this request settled on.
	//
	// Any of "stripe", "natural".
	Rail string `json:"rail"`
	// Ids of the Stripe objects on your connected account — join keys into your own
	// Stripe Dashboard/API. Manage a subscription's post-checkout lifecycle with
	// `subscription_id`.
	Stripe PaymentSucceededWebhookEventDataStripe `json:"stripe"`
	// Subscription mode — when the free trial ends and the first charge happens. On a
	// trial request, `payment.succeeded` means the payment method was collected ($0
	// moved).
	TrialEnd  time.Time `json:"trial_end" format:"date-time"`
	UpdatedAt time.Time `json:"updated_at" format:"date-time"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ID            respjson.Field
		Amount        respjson.Field
		CheckoutURL   respjson.Field
		CreatedAt     respjson.Field
		Currency      respjson.Field
		Object        respjson.Field
		Status        respjson.Field
		Description   respjson.Field
		Discount      respjson.Field
		Interval      respjson.Field
		IntervalCount respjson.Field
		Metadata      respjson.Field
		Mode          respjson.Field
		Natural       respjson.Field
		PriceID       respjson.Field
		Quantity      respjson.Field
		Rail          respjson.Field
		Stripe        respjson.Field
		TrialEnd      respjson.Field
		UpdatedAt     respjson.Field
		ExtraFields   map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

The payment request, as returned by `GET /v3/payment_requests/{paymentRequestId}`.

func (PaymentSucceededWebhookEventData) RawJSON added in v0.49.0

Returns the unmodified JSON received from the API

func (*PaymentSucceededWebhookEventData) UnmarshalJSON added in v0.49.0

func (r *PaymentSucceededWebhookEventData) UnmarshalJSON(data []byte) error

type PaymentSucceededWebhookEventDataDiscount added in v0.49.0

type PaymentSucceededWebhookEventDataDiscount struct {
	Coupon string `json:"coupon"`
	// Name of the coupon/promo code displayed to customers.
	Label         string `json:"label"`
	PromotionCode string `json:"promotion_code"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Coupon        respjson.Field
		Label         respjson.Field
		PromotionCode respjson.Field
		ExtraFields   map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Subscription mode — the discount Stripe applied, read back from the coupon. Absent when none was applied.

func (PaymentSucceededWebhookEventDataDiscount) RawJSON added in v0.49.0

Returns the unmodified JSON received from the API

func (*PaymentSucceededWebhookEventDataDiscount) UnmarshalJSON added in v0.49.0

func (r *PaymentSucceededWebhookEventDataDiscount) UnmarshalJSON(data []byte) error

type PaymentSucceededWebhookEventDataNatural added in v0.49.0

type PaymentSucceededWebhookEventDataNatural struct {
	// The Natural payment request (`prq_...`).
	PaymentRequestID string `json:"payment_request_id"`
	// The settled transaction (`txn_...`).
	TransactionID string `json:"transaction_id"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		PaymentRequestID respjson.Field
		TransactionID    respjson.Field
		ExtraFields      map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Natural-rail join keys, present when `rail: natural`.

func (PaymentSucceededWebhookEventDataNatural) RawJSON added in v0.49.0

Returns the unmodified JSON received from the API

func (*PaymentSucceededWebhookEventDataNatural) UnmarshalJSON added in v0.49.0

func (r *PaymentSucceededWebhookEventDataNatural) UnmarshalJSON(data []byte) error

type PaymentSucceededWebhookEventDataStripe added in v0.49.0

type PaymentSucceededWebhookEventDataStripe struct {
	// The Customer the request is attached to (`cus_...`). Always set in subscription
	// mode; set in payment mode only when the request was created with a
	// `customer_id`.
	CustomerID string `json:"customer_id"`
	// The PaymentIntent collected at checkout (`pi_...`).
	PaymentIntentID string `json:"payment_intent_id"`
	// Subscription mode — the Subscription (`sub_...`).
	SubscriptionID string `json:"subscription_id"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		CustomerID      respjson.Field
		PaymentIntentID respjson.Field
		SubscriptionID  respjson.Field
		ExtraFields     map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Ids of the Stripe objects on your connected account — join keys into your own Stripe Dashboard/API. Manage a subscription's post-checkout lifecycle with `subscription_id`.

func (PaymentSucceededWebhookEventDataStripe) RawJSON added in v0.49.0

Returns the unmodified JSON received from the API

func (*PaymentSucceededWebhookEventDataStripe) UnmarshalJSON added in v0.49.0

func (r *PaymentSucceededWebhookEventDataStripe) UnmarshalJSON(data []byte) error

type PaymentSucceededWebhookEventEventType added in v0.49.0

type PaymentSucceededWebhookEventEventType string
const (
	PaymentSucceededWebhookEventEventTypePaymentSucceeded           PaymentSucceededWebhookEventEventType = "payment.succeeded"
	PaymentSucceededWebhookEventEventTypePaymentCanceled            PaymentSucceededWebhookEventEventType = "payment.canceled"
	PaymentSucceededWebhookEventEventTypePaymentExpired             PaymentSucceededWebhookEventEventType = "payment.expired"
	PaymentSucceededWebhookEventEventTypeMessageSent                PaymentSucceededWebhookEventEventType = "message.sent"
	PaymentSucceededWebhookEventEventTypeMessageReceived            PaymentSucceededWebhookEventEventType = "message.received"
	PaymentSucceededWebhookEventEventTypeMessageRead                PaymentSucceededWebhookEventEventType = "message.read"
	PaymentSucceededWebhookEventEventTypeMessageDelivered           PaymentSucceededWebhookEventEventType = "message.delivered"
	PaymentSucceededWebhookEventEventTypeMessageFailed              PaymentSucceededWebhookEventEventType = "message.failed"
	PaymentSucceededWebhookEventEventTypeMessageEdited              PaymentSucceededWebhookEventEventType = "message.edited"
	PaymentSucceededWebhookEventEventTypeReactionAdded              PaymentSucceededWebhookEventEventType = "reaction.added"
	PaymentSucceededWebhookEventEventTypeReactionRemoved            PaymentSucceededWebhookEventEventType = "reaction.removed"
	PaymentSucceededWebhookEventEventTypePollReceived               PaymentSucceededWebhookEventEventType = "poll.received"
	PaymentSucceededWebhookEventEventTypePollFailed                 PaymentSucceededWebhookEventEventType = "poll.failed"
	PaymentSucceededWebhookEventEventTypePollSent                   PaymentSucceededWebhookEventEventType = "poll.sent"
	PaymentSucceededWebhookEventEventTypePollDelivered              PaymentSucceededWebhookEventEventType = "poll.delivered"
	PaymentSucceededWebhookEventEventTypePollRead                   PaymentSucceededWebhookEventEventType = "poll.read"
	PaymentSucceededWebhookEventEventTypePollUpdated                PaymentSucceededWebhookEventEventType = "poll.updated"
	PaymentSucceededWebhookEventEventTypePollVoteAdded              PaymentSucceededWebhookEventEventType = "poll.vote.added"
	PaymentSucceededWebhookEventEventTypePollVoteRemoved            PaymentSucceededWebhookEventEventType = "poll.vote.removed"
	PaymentSucceededWebhookEventEventTypePollReactionAdded          PaymentSucceededWebhookEventEventType = "poll.reaction.added"
	PaymentSucceededWebhookEventEventTypeParticipantAdded           PaymentSucceededWebhookEventEventType = "participant.added"
	PaymentSucceededWebhookEventEventTypeParticipantRemoved         PaymentSucceededWebhookEventEventType = "participant.removed"
	PaymentSucceededWebhookEventEventTypeChatCreated                PaymentSucceededWebhookEventEventType = "chat.created"
	PaymentSucceededWebhookEventEventTypeChatGroupNameUpdated       PaymentSucceededWebhookEventEventType = "chat.group_name_updated"
	PaymentSucceededWebhookEventEventTypeChatGroupIconUpdated       PaymentSucceededWebhookEventEventType = "chat.group_icon_updated"
	PaymentSucceededWebhookEventEventTypeChatGroupNameUpdateFailed  PaymentSucceededWebhookEventEventType = "chat.group_name_update_failed"
	PaymentSucceededWebhookEventEventTypeChatGroupIconUpdateFailed  PaymentSucceededWebhookEventEventType = "chat.group_icon_update_failed"
	PaymentSucceededWebhookEventEventTypeChatBackgroundUpdated      PaymentSucceededWebhookEventEventType = "chat.background_updated"
	PaymentSucceededWebhookEventEventTypeChatBackgroundUpdateFailed PaymentSucceededWebhookEventEventType = "chat.background_update_failed"
	PaymentSucceededWebhookEventEventTypeChatTypingIndicatorStarted PaymentSucceededWebhookEventEventType = "chat.typing_indicator.started"
	PaymentSucceededWebhookEventEventTypeChatTypingIndicatorStopped PaymentSucceededWebhookEventEventType = "chat.typing_indicator.stopped"
	PaymentSucceededWebhookEventEventTypePhoneNumberStatusUpdated   PaymentSucceededWebhookEventEventType = "phone_number.status_updated"
	PaymentSucceededWebhookEventEventTypeContactCardReceived        PaymentSucceededWebhookEventEventType = "contact_card.received"
	PaymentSucceededWebhookEventEventTypeCallInitiated              PaymentSucceededWebhookEventEventType = "call.initiated"
	PaymentSucceededWebhookEventEventTypeCallRinging                PaymentSucceededWebhookEventEventType = "call.ringing"
	PaymentSucceededWebhookEventEventTypeCallAnswered               PaymentSucceededWebhookEventEventType = "call.answered"
	PaymentSucceededWebhookEventEventTypeCallEnded                  PaymentSucceededWebhookEventEventType = "call.ended"
	PaymentSucceededWebhookEventEventTypeCallFailed                 PaymentSucceededWebhookEventEventType = "call.failed"
	PaymentSucceededWebhookEventEventTypeCallDeclined               PaymentSucceededWebhookEventEventType = "call.declined"
	PaymentSucceededWebhookEventEventTypeCallNoAnswer               PaymentSucceededWebhookEventEventType = "call.no_answer"
	PaymentSucceededWebhookEventEventTypeLocationSharingStarted     PaymentSucceededWebhookEventEventType = "location.sharing.started"
	PaymentSucceededWebhookEventEventTypeLocationSharingStopped     PaymentSucceededWebhookEventEventType = "location.sharing.stopped"
	PaymentSucceededWebhookEventEventTypePaymentDeclined            PaymentSucceededWebhookEventEventType = "payment.declined"
	PaymentSucceededWebhookEventEventTypePaymentAuthorized          PaymentSucceededWebhookEventEventType = "payment.authorized"
	PaymentSucceededWebhookEventEventTypeConnectionCreated          PaymentSucceededWebhookEventEventType = "connection.created"
	PaymentSucceededWebhookEventEventTypeConnectionRevoked          PaymentSucceededWebhookEventEventType = "connection.revoked"
)

type PhoneNumberGetReputationAuditParams added in v0.31.0

type PhoneNumberGetReputationAuditParams struct {
	PhoneNumber string `path:"phoneNumber" api:"required" json:"-"`
	// contains filtered or unexported fields
}

type PhoneNumberListResponse

type PhoneNumberListResponse struct {
	// List of phone numbers assigned to the partner
	PhoneNumbers []PhoneNumberListResponsePhoneNumber `json:"phone_numbers" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		PhoneNumbers respjson.Field
		ExtraFields  map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (PhoneNumberListResponse) RawJSON

func (r PhoneNumberListResponse) RawJSON() string

Returns the unmodified JSON received from the API

func (*PhoneNumberListResponse) UnmarshalJSON

func (r *PhoneNumberListResponse) UnmarshalJSON(data []byte) error

type PhoneNumberListResponsePhoneNumber

type PhoneNumberListResponsePhoneNumber struct {
	// Unique identifier for the phone number
	ID string `json:"id" api:"required" format:"uuid"`
	// Phone number in E.164 format
	PhoneNumber string `json:"phone_number" api:"required"`
	// **[BETA]** Current reputation for a phone line. Always present — lines start at
	// `HEALTHY` and may shift based on aggregate engagement and delivery signals
	// across all conversations on the line.
	//
	// Unlike chat health, line reputation does not include `opted_out` — opt-out
	// applies to individual recipients, not the whole line.
	//
	// See the
	// [Phone Reputation guide](/channel/imessage/guides/phone-numbers/phone-reputation)
	// for what each status means and how to react.
	Reputation PhoneNumberListResponsePhoneNumberReputation `json:"reputation" api:"required"`
	// The forwarding number associated with this phone number, in E.164 format. Null
	// when no forwarding number is configured.
	ForwardingNumber string `json:"forwarding_number" api:"nullable"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ID               respjson.Field
		PhoneNumber      respjson.Field
		Reputation       respjson.Field
		ForwardingNumber respjson.Field
		ExtraFields      map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (PhoneNumberListResponsePhoneNumber) RawJSON

Returns the unmodified JSON received from the API

func (*PhoneNumberListResponsePhoneNumber) UnmarshalJSON

func (r *PhoneNumberListResponsePhoneNumber) UnmarshalJSON(data []byte) error

type PhoneNumberListResponsePhoneNumberReputation added in v0.26.0

type PhoneNumberListResponsePhoneNumberReputation struct {
	// Deep-link to the relevant section of the Phone Reputation guide for this status.
	DocURL string `json:"doc_url" api:"required" format:"uri"`
	// Current reputation of this phone line.
	//
	//   - `HEALTHY` — The line is in good standing. Send normally.
	//   - `AT_RISK` — Warning signs on the line: engagement is low across many of its
	//     conversations, or it's starting too many brand-new conversations in a single
	//     day — and a spike in send volume can add to either. Slow the line's send pace,
	//     avoid opening many new conversations at once, and review your messaging
	//     patterns.
	//   - `CRITICAL` — Strong signals that messages from this line aren't landing well.
	//     Pause outbound on the line until it recovers.
	//
	// Defaults to `HEALTHY` for lines that have not yet been scored.
	//
	// Any of "HEALTHY", "AT_RISK", "CRITICAL".
	Status string `json:"status" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		DocURL      respjson.Field
		Status      respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

**[BETA]** Current reputation for a phone line. Always present — lines start at `HEALTHY` and may shift based on aggregate engagement and delivery signals across all conversations on the line.

Unlike chat health, line reputation does not include `opted_out` — opt-out applies to individual recipients, not the whole line.

See the [Phone Reputation guide](/channel/imessage/guides/phone-numbers/phone-reputation) for what each status means and how to react.

func (PhoneNumberListResponsePhoneNumberReputation) RawJSON added in v0.26.0

Returns the unmodified JSON received from the API

func (*PhoneNumberListResponsePhoneNumberReputation) UnmarshalJSON added in v0.26.0

func (r *PhoneNumberListResponsePhoneNumberReputation) UnmarshalJSON(data []byte) error

type PhoneNumberService

type PhoneNumberService struct {
	Options []option.RequestOption
}

Phone Numbers represent the phone numbers assigned to your partner account.

Use the list phone numbers endpoint to discover which phone numbers are available for sending messages.

When creating chats, listing chats, or sending a voice memo, use one of your assigned phone numbers in the `from` field.

**Ineligible numbers.** A number can temporarily lose the ability to deliver messages. While it is in that state, requests that would produce new activity on it — sending a message, creating a chat, reacting, typing, group actions — are rejected with `403` (error code `2027`) before anything is created. Reads keep working, so your existing chats, messages, and history stay available. Omit `from` on `POST /v3/messages` and we pick an eligible number for you, skipping ineligible ones; if none of your assigned numbers are eligible, you get `409` (no `from` number was ever chosen, so there's no specific number to blame with a `403`).

PhoneNumberService contains methods and other services that help with interacting with the linq-api-v3 API.

Note, unlike clients, this service does not read variables from the environment automatically. You should not instantiate this service directly, and instead use the NewPhoneNumberService method instead.

func NewPhoneNumberService

func NewPhoneNumberService(opts ...option.RequestOption) (r PhoneNumberService)

NewPhoneNumberService generates a new service that applies the given options to each request. These options are applied after the parent client's options (if there is one), and before any request-specific options.

func (*PhoneNumberService) GetReputationAudit added in v0.31.0

func (r *PhoneNumberService) GetReputationAudit(ctx context.Context, auditID string, query PhoneNumberGetReputationAuditParams, opts ...option.RequestOption) (res *ReputationAudit, err error)

Returns the audit's status and, once complete, the report. Audits are scoped to the line in the URL — an `auditId` started on a different line returns `404`.

func (*PhoneNumberService) List

Returns all phone numbers assigned to the authenticated partner. Use this endpoint to discover which phone numbers are available for use as the `from` field when creating a chat, listing chats, or sending a voice memo.

func (*PhoneNumberService) StartReputationAudit added in v0.31.0

func (r *PhoneNumberService) StartReputationAudit(ctx context.Context, phoneNumber string, opts ...option.RequestOption) (res *ReputationAuditStarted, err error)

Starts an asynchronous reputation audit for a line and returns an `audit_id`. Poll the GET endpoint for the result.

Rate limited per line: only one audit may run at a time. Starting one while another is still running returns `202` with the running audit's `audit_id` rather than an error, so a retried start picks that audit back up instead of losing it — poll the id you were given.

Once an audit finishes, a new one can't be started for the same line until a cooldown elapses (`429`, with `Retry-After` carrying the wait). Keep the `audit_id` from the original `202`: it stays readable on the GET endpoint for 24 hours, and the cooldown response does not repeat it.

func (*PhoneNumberService) Update added in v0.26.1

func (r *PhoneNumberService) Update(ctx context.Context, phoneNumberID string, body PhoneNumberUpdateParams, opts ...option.RequestOption) (res *PhoneNumberUpdateResponse, err error)

Updates the forwarding number for a phone number. The forwarding number is where inbound calls will be forwarded to.

Pass an empty string to clear the forwarding number.

type PhoneNumberStatusUpdatedWebhookEvent added in v0.12.0

type PhoneNumberStatusUpdatedWebhookEvent struct {
	// API version for the webhook payload format
	APIVersion string `json:"api_version" api:"required"`
	// When the event was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// Payload for phone_number.status_updated webhook events
	Data PhoneNumberStatusUpdatedWebhookEventData `json:"data" api:"required"`
	// Unique identifier for this event (for deduplication)
	EventID string `json:"event_id" api:"required" format:"uuid"`
	// The type of event
	//
	// Any of "message.sent", "message.received", "message.read", "message.delivered",
	// "message.failed", "message.edited", "reaction.added", "reaction.removed",
	// "poll.received", "poll.failed", "poll.sent", "poll.delivered", "poll.read",
	// "poll.updated", "poll.vote.added", "poll.vote.removed", "poll.reaction.added",
	// "participant.added", "participant.removed", "chat.created",
	// "chat.group_name_updated", "chat.group_icon_updated",
	// "chat.group_name_update_failed", "chat.group_icon_update_failed",
	// "chat.background_updated", "chat.background_update_failed",
	// "chat.typing_indicator.started", "chat.typing_indicator.stopped",
	// "phone_number.status_updated", "contact_card.received", "call.initiated",
	// "call.ringing", "call.answered", "call.ended", "call.failed", "call.declined",
	// "call.no_answer", "location.sharing.started", "location.sharing.stopped",
	// "payment.succeeded", "payment.canceled", "payment.expired", "payment.declined",
	// "payment.authorized", "connection.created", "connection.revoked".
	EventType PhoneNumberStatusUpdatedWebhookEventEventType `json:"event_type" api:"required"`
	// Partner identifier. Present on all webhooks for cross-referencing.
	PartnerID string `json:"partner_id" api:"required"`
	// Trace ID for debugging and correlation across systems.
	TraceID string `json:"trace_id" api:"required"`
	// Date-based webhook payload version. Determined by the `?version=` query
	// parameter in your webhook subscription URL. If no version parameter is
	// specified, defaults based on subscription creation date.
	WebhookVersion string `json:"webhook_version" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		APIVersion     respjson.Field
		CreatedAt      respjson.Field
		Data           respjson.Field
		EventID        respjson.Field
		EventType      respjson.Field
		PartnerID      respjson.Field
		TraceID        respjson.Field
		WebhookVersion respjson.Field
		ExtraFields    map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Complete webhook payload for phone_number.status_updated events

func (PhoneNumberStatusUpdatedWebhookEvent) RawJSON added in v0.12.0

Returns the unmodified JSON received from the API

func (*PhoneNumberStatusUpdatedWebhookEvent) UnmarshalJSON added in v0.12.0

func (r *PhoneNumberStatusUpdatedWebhookEvent) UnmarshalJSON(data []byte) error

type PhoneNumberStatusUpdatedWebhookEventData added in v0.12.0

type PhoneNumberStatusUpdatedWebhookEventData struct {
	// When the status change occurred
	ChangedAt time.Time `json:"changed_at" api:"required" format:"date-time"`
	// The new line reputation
	//
	// Any of "HEALTHY", "AT_RISK", "CRITICAL".
	NewReputation string `json:"new_reputation" api:"required"`
	// The new service status
	//
	// Any of "ACTIVE", "FLAGGED".
	NewStatus string `json:"new_status" api:"required"`
	// Phone number in E.164 format
	PhoneNumber string `json:"phone_number" api:"required"`
	// The previous line reputation
	//
	// Any of "HEALTHY", "AT_RISK", "CRITICAL".
	PreviousReputation string `json:"previous_reputation" api:"required"`
	// The previous service status
	//
	// Any of "ACTIVE", "FLAGGED".
	PreviousStatus string `json:"previous_status" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ChangedAt          respjson.Field
		NewReputation      respjson.Field
		NewStatus          respjson.Field
		PhoneNumber        respjson.Field
		PreviousReputation respjson.Field
		PreviousStatus     respjson.Field
		ExtraFields        map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Payload for phone_number.status_updated webhook events

func (PhoneNumberStatusUpdatedWebhookEventData) RawJSON added in v0.12.0

Returns the unmodified JSON received from the API

func (*PhoneNumberStatusUpdatedWebhookEventData) UnmarshalJSON added in v0.12.0

func (r *PhoneNumberStatusUpdatedWebhookEventData) UnmarshalJSON(data []byte) error

type PhoneNumberStatusUpdatedWebhookEventEventType added in v0.12.0

type PhoneNumberStatusUpdatedWebhookEventEventType string

The type of event

const (
	PhoneNumberStatusUpdatedWebhookEventEventTypeMessageSent                PhoneNumberStatusUpdatedWebhookEventEventType = "message.sent"
	PhoneNumberStatusUpdatedWebhookEventEventTypeMessageReceived            PhoneNumberStatusUpdatedWebhookEventEventType = "message.received"
	PhoneNumberStatusUpdatedWebhookEventEventTypeMessageRead                PhoneNumberStatusUpdatedWebhookEventEventType = "message.read"
	PhoneNumberStatusUpdatedWebhookEventEventTypeMessageDelivered           PhoneNumberStatusUpdatedWebhookEventEventType = "message.delivered"
	PhoneNumberStatusUpdatedWebhookEventEventTypeMessageFailed              PhoneNumberStatusUpdatedWebhookEventEventType = "message.failed"
	PhoneNumberStatusUpdatedWebhookEventEventTypeMessageEdited              PhoneNumberStatusUpdatedWebhookEventEventType = "message.edited"
	PhoneNumberStatusUpdatedWebhookEventEventTypeReactionAdded              PhoneNumberStatusUpdatedWebhookEventEventType = "reaction.added"
	PhoneNumberStatusUpdatedWebhookEventEventTypeReactionRemoved            PhoneNumberStatusUpdatedWebhookEventEventType = "reaction.removed"
	PhoneNumberStatusUpdatedWebhookEventEventTypePollReceived               PhoneNumberStatusUpdatedWebhookEventEventType = "poll.received"
	PhoneNumberStatusUpdatedWebhookEventEventTypePollFailed                 PhoneNumberStatusUpdatedWebhookEventEventType = "poll.failed"
	PhoneNumberStatusUpdatedWebhookEventEventTypePollSent                   PhoneNumberStatusUpdatedWebhookEventEventType = "poll.sent"
	PhoneNumberStatusUpdatedWebhookEventEventTypePollDelivered              PhoneNumberStatusUpdatedWebhookEventEventType = "poll.delivered"
	PhoneNumberStatusUpdatedWebhookEventEventTypePollRead                   PhoneNumberStatusUpdatedWebhookEventEventType = "poll.read"
	PhoneNumberStatusUpdatedWebhookEventEventTypePollUpdated                PhoneNumberStatusUpdatedWebhookEventEventType = "poll.updated"
	PhoneNumberStatusUpdatedWebhookEventEventTypePollVoteAdded              PhoneNumberStatusUpdatedWebhookEventEventType = "poll.vote.added"
	PhoneNumberStatusUpdatedWebhookEventEventTypePollVoteRemoved            PhoneNumberStatusUpdatedWebhookEventEventType = "poll.vote.removed"
	PhoneNumberStatusUpdatedWebhookEventEventTypePollReactionAdded          PhoneNumberStatusUpdatedWebhookEventEventType = "poll.reaction.added"
	PhoneNumberStatusUpdatedWebhookEventEventTypeParticipantAdded           PhoneNumberStatusUpdatedWebhookEventEventType = "participant.added"
	PhoneNumberStatusUpdatedWebhookEventEventTypeParticipantRemoved         PhoneNumberStatusUpdatedWebhookEventEventType = "participant.removed"
	PhoneNumberStatusUpdatedWebhookEventEventTypeChatCreated                PhoneNumberStatusUpdatedWebhookEventEventType = "chat.created"
	PhoneNumberStatusUpdatedWebhookEventEventTypeChatGroupNameUpdated       PhoneNumberStatusUpdatedWebhookEventEventType = "chat.group_name_updated"
	PhoneNumberStatusUpdatedWebhookEventEventTypeChatGroupIconUpdated       PhoneNumberStatusUpdatedWebhookEventEventType = "chat.group_icon_updated"
	PhoneNumberStatusUpdatedWebhookEventEventTypeChatGroupNameUpdateFailed  PhoneNumberStatusUpdatedWebhookEventEventType = "chat.group_name_update_failed"
	PhoneNumberStatusUpdatedWebhookEventEventTypeChatGroupIconUpdateFailed  PhoneNumberStatusUpdatedWebhookEventEventType = "chat.group_icon_update_failed"
	PhoneNumberStatusUpdatedWebhookEventEventTypeChatBackgroundUpdated      PhoneNumberStatusUpdatedWebhookEventEventType = "chat.background_updated"
	PhoneNumberStatusUpdatedWebhookEventEventTypeChatBackgroundUpdateFailed PhoneNumberStatusUpdatedWebhookEventEventType = "chat.background_update_failed"
	PhoneNumberStatusUpdatedWebhookEventEventTypeChatTypingIndicatorStarted PhoneNumberStatusUpdatedWebhookEventEventType = "chat.typing_indicator.started"
	PhoneNumberStatusUpdatedWebhookEventEventTypeChatTypingIndicatorStopped PhoneNumberStatusUpdatedWebhookEventEventType = "chat.typing_indicator.stopped"
	PhoneNumberStatusUpdatedWebhookEventEventTypePhoneNumberStatusUpdated   PhoneNumberStatusUpdatedWebhookEventEventType = "phone_number.status_updated"
	PhoneNumberStatusUpdatedWebhookEventEventTypeContactCardReceived        PhoneNumberStatusUpdatedWebhookEventEventType = "contact_card.received"
	PhoneNumberStatusUpdatedWebhookEventEventTypeCallInitiated              PhoneNumberStatusUpdatedWebhookEventEventType = "call.initiated"
	PhoneNumberStatusUpdatedWebhookEventEventTypeCallRinging                PhoneNumberStatusUpdatedWebhookEventEventType = "call.ringing"
	PhoneNumberStatusUpdatedWebhookEventEventTypeCallAnswered               PhoneNumberStatusUpdatedWebhookEventEventType = "call.answered"
	PhoneNumberStatusUpdatedWebhookEventEventTypeCallEnded                  PhoneNumberStatusUpdatedWebhookEventEventType = "call.ended"
	PhoneNumberStatusUpdatedWebhookEventEventTypeCallFailed                 PhoneNumberStatusUpdatedWebhookEventEventType = "call.failed"
	PhoneNumberStatusUpdatedWebhookEventEventTypeCallDeclined               PhoneNumberStatusUpdatedWebhookEventEventType = "call.declined"
	PhoneNumberStatusUpdatedWebhookEventEventTypeCallNoAnswer               PhoneNumberStatusUpdatedWebhookEventEventType = "call.no_answer"
	PhoneNumberStatusUpdatedWebhookEventEventTypeLocationSharingStarted     PhoneNumberStatusUpdatedWebhookEventEventType = "location.sharing.started"
	PhoneNumberStatusUpdatedWebhookEventEventTypeLocationSharingStopped     PhoneNumberStatusUpdatedWebhookEventEventType = "location.sharing.stopped"
	PhoneNumberStatusUpdatedWebhookEventEventTypePaymentSucceeded           PhoneNumberStatusUpdatedWebhookEventEventType = "payment.succeeded"
	PhoneNumberStatusUpdatedWebhookEventEventTypePaymentCanceled            PhoneNumberStatusUpdatedWebhookEventEventType = "payment.canceled"
	PhoneNumberStatusUpdatedWebhookEventEventTypePaymentExpired             PhoneNumberStatusUpdatedWebhookEventEventType = "payment.expired"
	PhoneNumberStatusUpdatedWebhookEventEventTypePaymentDeclined            PhoneNumberStatusUpdatedWebhookEventEventType = "payment.declined"
	PhoneNumberStatusUpdatedWebhookEventEventTypePaymentAuthorized          PhoneNumberStatusUpdatedWebhookEventEventType = "payment.authorized"
	PhoneNumberStatusUpdatedWebhookEventEventTypeConnectionCreated          PhoneNumberStatusUpdatedWebhookEventEventType = "connection.created"
	PhoneNumberStatusUpdatedWebhookEventEventTypeConnectionRevoked          PhoneNumberStatusUpdatedWebhookEventEventType = "connection.revoked"
)

type PhoneNumberUpdateParams added in v0.26.1

type PhoneNumberUpdateParams struct {
	// The forwarding number in E.164 format. Set to null or empty string to clear.
	ForwardingNumber param.Opt[string] `json:"forwarding_number,omitzero" api:"required"`
	// contains filtered or unexported fields
}

func (PhoneNumberUpdateParams) MarshalJSON added in v0.26.1

func (r PhoneNumberUpdateParams) MarshalJSON() (data []byte, err error)

func (*PhoneNumberUpdateParams) UnmarshalJSON added in v0.26.1

func (r *PhoneNumberUpdateParams) UnmarshalJSON(data []byte) error

type PhoneNumberUpdateResponse added in v0.26.1

type PhoneNumberUpdateResponse struct {
	// Unique identifier for the phone number
	ID string `json:"id" api:"required" format:"uuid"`
	// The forwarding number after the update. Null when cleared.
	ForwardingNumber string `json:"forwarding_number" api:"required"`
	// Phone number in E.164 format
	PhoneNumber string `json:"phone_number" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ID               respjson.Field
		ForwardingNumber respjson.Field
		PhoneNumber      respjson.Field
		ExtraFields      map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (PhoneNumberUpdateResponse) RawJSON added in v0.26.1

func (r PhoneNumberUpdateResponse) RawJSON() string

Returns the unmodified JSON received from the API

func (*PhoneNumberUpdateResponse) UnmarshalJSON added in v0.26.1

func (r *PhoneNumberUpdateResponse) UnmarshalJSON(data []byte) error

type PhonenumberListResponse

type PhonenumberListResponse struct {
	// List of phone numbers assigned to the partner
	PhoneNumbers []PhonenumberListResponsePhoneNumber `json:"phone_numbers" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		PhoneNumbers respjson.Field
		ExtraFields  map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (PhonenumberListResponse) RawJSON

func (r PhonenumberListResponse) RawJSON() string

Returns the unmodified JSON received from the API

func (*PhonenumberListResponse) UnmarshalJSON

func (r *PhonenumberListResponse) UnmarshalJSON(data []byte) error

type PhonenumberListResponsePhoneNumber

type PhonenumberListResponsePhoneNumber struct {
	// Unique identifier for the phone number
	ID string `json:"id" api:"required" format:"uuid"`
	// Phone number in E.164 format
	PhoneNumber  string                                         `json:"phone_number" api:"required"`
	Capabilities PhonenumberListResponsePhoneNumberCapabilities `json:"capabilities"`
	// Deprecated. Always null.
	CountryCode string `json:"country_code"`
	// Deprecated. Always null.
	Type string `json:"type" api:"nullable"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ID           respjson.Field
		PhoneNumber  respjson.Field
		Capabilities respjson.Field
		CountryCode  respjson.Field
		Type         respjson.Field
		ExtraFields  map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (PhonenumberListResponsePhoneNumber) RawJSON

Returns the unmodified JSON received from the API

func (*PhonenumberListResponsePhoneNumber) UnmarshalJSON

func (r *PhonenumberListResponsePhoneNumber) UnmarshalJSON(data []byte) error

type PhonenumberListResponsePhoneNumberCapabilities

type PhonenumberListResponsePhoneNumberCapabilities struct {
	// Whether MMS messaging is supported
	Mms bool `json:"mms" api:"required"`
	// Whether SMS messaging is supported
	SMS bool `json:"sms" api:"required"`
	// Whether voice calls are supported
	Voice bool `json:"voice" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Mms         respjson.Field
		SMS         respjson.Field
		Voice       respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (PhonenumberListResponsePhoneNumberCapabilities) RawJSON

Returns the unmodified JSON received from the API

func (*PhonenumberListResponsePhoneNumberCapabilities) UnmarshalJSON

type PhonenumberService

type PhonenumberService struct {
	Options []option.RequestOption
}

Phone Numbers represent the phone numbers assigned to your partner account.

Use the list phone numbers endpoint to discover which phone numbers are available for sending messages.

When creating chats, listing chats, or sending a voice memo, use one of your assigned phone numbers in the `from` field.

**Ineligible numbers.** A number can temporarily lose the ability to deliver messages. While it is in that state, requests that would produce new activity on it — sending a message, creating a chat, reacting, typing, group actions — are rejected with `403` (error code `2027`) before anything is created. Reads keep working, so your existing chats, messages, and history stay available. Omit `from` on `POST /v3/messages` and we pick an eligible number for you, skipping ineligible ones; if none of your assigned numbers are eligible, you get `409` (no `from` number was ever chosen, so there's no specific number to blame with a `403`).

PhonenumberService contains methods and other services that help with interacting with the linq-api-v3 API.

Note, unlike clients, this service does not read variables from the environment automatically. You should not instantiate this service directly, and instead use the NewPhonenumberService method instead.

func NewPhonenumberService

func NewPhonenumberService(opts ...option.RequestOption) (r PhonenumberService)

NewPhonenumberService generates a new service that applies the given options to each request. These options are applied after the parent client's options (if there is one), and before any request-specific options.

func (*PhonenumberService) List deprecated

**Deprecated.** Use `GET /v3/phone_numbers` instead.

Deprecated: deprecated

type Poll added in v0.29.1

type Poll struct {
	Options []PollOption `json:"options" api:"required"`
	// Distinct participants across the whole poll (a voter picking two options counts
	// once).
	TotalVoters int64 `json:"total_voters" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Options     respjson.Field
		TotalVoters respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Poll content — options and the aggregate voter count.

func (Poll) RawJSON added in v0.29.1

func (r Poll) RawJSON() string

Returns the unmodified JSON received from the API

func (*Poll) UnmarshalJSON added in v0.29.1

func (r *Poll) UnmarshalJSON(data []byte) error

type PollDeliveredWebhookEvent added in v0.34.0

type PollDeliveredWebhookEvent struct {
	// API version for the webhook payload format
	APIVersion string `json:"api_version" api:"required"`
	// When the event was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// Payload for poll.sent, poll.delivered, and poll.read webhook events. Timestamps
	// indicate state (null = not yet happened): sent → sent_at; delivered →
	// +delivered_at; read → +read_at.
	Data PollDeliveredWebhookEventData `json:"data" api:"required"`
	// Unique identifier for this event (for deduplication)
	EventID string `json:"event_id" api:"required" format:"uuid"`
	// Valid webhook event types that can be subscribed to.
	//
	// **Note:** `message.edited` is only delivered to subscriptions using
	// `webhook_version: "2026-02-03"`. Subscribing to this event on a v2025
	// subscription will not produce any deliveries.
	//
	// Any of "message.sent", "message.received", "message.read", "message.delivered",
	// "message.failed", "message.edited", "reaction.added", "reaction.removed",
	// "poll.received", "poll.failed", "poll.sent", "poll.delivered", "poll.read",
	// "poll.updated", "poll.vote.added", "poll.vote.removed", "poll.reaction.added",
	// "participant.added", "participant.removed", "chat.created",
	// "chat.group_name_updated", "chat.group_icon_updated",
	// "chat.group_name_update_failed", "chat.group_icon_update_failed",
	// "chat.background_updated", "chat.background_update_failed",
	// "chat.typing_indicator.started", "chat.typing_indicator.stopped",
	// "phone_number.status_updated", "contact_card.received", "call.initiated",
	// "call.ringing", "call.answered", "call.ended", "call.failed", "call.declined",
	// "call.no_answer", "location.sharing.started", "location.sharing.stopped",
	// "payment.succeeded", "payment.canceled", "payment.expired", "payment.declined",
	// "payment.authorized", "connection.created", "connection.revoked".
	EventType WebhookEventType `json:"event_type" api:"required"`
	// Partner identifier. Present on all webhooks for cross-referencing.
	PartnerID string `json:"partner_id" api:"required"`
	// Trace ID for debugging and correlation across systems.
	TraceID string `json:"trace_id" api:"required"`
	// Date-based webhook payload version. Determined by the `?version=` query
	// parameter in your webhook subscription URL. If no version parameter is
	// specified, defaults based on subscription creation date.
	WebhookVersion string `json:"webhook_version" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		APIVersion     respjson.Field
		CreatedAt      respjson.Field
		Data           respjson.Field
		EventID        respjson.Field
		EventType      respjson.Field
		PartnerID      respjson.Field
		TraceID        respjson.Field
		WebhookVersion respjson.Field
		ExtraFields    map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Complete webhook payload for poll.delivered events

func (PollDeliveredWebhookEvent) RawJSON added in v0.34.0

func (r PollDeliveredWebhookEvent) RawJSON() string

Returns the unmodified JSON received from the API

func (*PollDeliveredWebhookEvent) UnmarshalJSON added in v0.34.0

func (r *PollDeliveredWebhookEvent) UnmarshalJSON(data []byte) error

type PollDeliveredWebhookEventData added in v0.34.0

type PollDeliveredWebhookEventData struct {
	// Chat info for poll webhook events.
	Chat      PollDeliveredWebhookEventDataChat `json:"chat" api:"required"`
	CreatedAt time.Time                         `json:"created_at" api:"required" format:"date-time"`
	// Any of "inbound", "outbound".
	Direction   string                            `json:"direction" api:"required"`
	MessageID   string                            `json:"message_id" api:"required" format:"uuid"`
	Poll        PollDeliveredWebhookEventDataPoll `json:"poll" api:"required"`
	Service     string                            `json:"service" api:"required"`
	UpdatedAt   time.Time                         `json:"updated_at" api:"required" format:"date-time"`
	DeliveredAt time.Time                         `json:"delivered_at" api:"nullable" format:"date-time"`
	ReadAt      time.Time                         `json:"read_at" api:"nullable" format:"date-time"`
	// The handle that sent the poll.
	SenderHandle shared.ChatHandle `json:"sender_handle" api:"nullable"`
	SentAt       time.Time         `json:"sent_at" api:"nullable" format:"date-time"`
	// True when this poll was sent on a zero-day-retention line. Every option's `text`
	// is empty in that case — Linq never persists poll option text, so there is
	// nothing to include here. The real text was only ever shown once, synchronously,
	// in the API response when the poll was created or added to.
	ZeroRetention bool `json:"zero_retention"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Chat          respjson.Field
		CreatedAt     respjson.Field
		Direction     respjson.Field
		MessageID     respjson.Field
		Poll          respjson.Field
		Service       respjson.Field
		UpdatedAt     respjson.Field
		DeliveredAt   respjson.Field
		ReadAt        respjson.Field
		SenderHandle  respjson.Field
		SentAt        respjson.Field
		ZeroRetention respjson.Field
		ExtraFields   map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Payload for poll.sent, poll.delivered, and poll.read webhook events. Timestamps indicate state (null = not yet happened): sent → sent_at; delivered → +delivered_at; read → +read_at.

func (PollDeliveredWebhookEventData) RawJSON added in v0.34.0

Returns the unmodified JSON received from the API

func (*PollDeliveredWebhookEventData) UnmarshalJSON added in v0.34.0

func (r *PollDeliveredWebhookEventData) UnmarshalJSON(data []byte) error

type PollDeliveredWebhookEventDataChat added in v0.34.0

type PollDeliveredWebhookEventDataChat struct {
	ID          string            `json:"id" api:"required" format:"uuid"`
	IsGroup     bool              `json:"is_group" api:"nullable"`
	OwnerHandle shared.ChatHandle `json:"owner_handle" api:"nullable"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ID          respjson.Field
		IsGroup     respjson.Field
		OwnerHandle respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Chat info for poll webhook events.

func (PollDeliveredWebhookEventDataChat) RawJSON added in v0.34.0

Returns the unmodified JSON received from the API

func (*PollDeliveredWebhookEventDataChat) UnmarshalJSON added in v0.34.0

func (r *PollDeliveredWebhookEventDataChat) UnmarshalJSON(data []byte) error

type PollDeliveredWebhookEventDataPoll added in v0.34.0

type PollDeliveredWebhookEventDataPoll struct {
	Options []PollDeliveredWebhookEventDataPollOption `json:"options" api:"required"`
	// Distinct participants across the whole poll.
	TotalVoters int64 `json:"total_voters" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Options     respjson.Field
		TotalVoters respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (PollDeliveredWebhookEventDataPoll) RawJSON added in v0.34.0

Returns the unmodified JSON received from the API

func (*PollDeliveredWebhookEventDataPoll) UnmarshalJSON added in v0.34.0

func (r *PollDeliveredWebhookEventDataPoll) UnmarshalJSON(data []byte) error

type PollDeliveredWebhookEventDataPollOption added in v0.34.0

type PollDeliveredWebhookEventDataPollOption struct {
	CanBeEdited bool `json:"can_be_edited" api:"required"`
	// The participant who added this option (poll creator for the initial options;
	// whoever added later ones). On a poll.updated this differs from the event's
	// `sender_handle` whenever a remote participant added the option. Null when
	// unknown.
	CreatorHandle shared.ChatHandle                              `json:"creator_handle" api:"required"`
	OptionID      string                                         `json:"option_id" api:"required" format:"uuid"`
	Text          string                                         `json:"text" api:"required"`
	Voters        []PollDeliveredWebhookEventDataPollOptionVoter `json:"voters" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		CanBeEdited   respjson.Field
		CreatorHandle respjson.Field
		OptionID      respjson.Field
		Text          respjson.Field
		Voters        respjson.Field
		ExtraFields   map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (PollDeliveredWebhookEventDataPollOption) RawJSON added in v0.34.0

Returns the unmodified JSON received from the API

func (*PollDeliveredWebhookEventDataPollOption) UnmarshalJSON added in v0.34.0

func (r *PollDeliveredWebhookEventDataPollOption) UnmarshalJSON(data []byte) error

type PollDeliveredWebhookEventDataPollOptionVoter added in v0.34.0

type PollDeliveredWebhookEventDataPollOptionVoter struct {
	Handle  string    `json:"handle" api:"required"`
	VotedAt time.Time `json:"voted_at" api:"required" format:"date-time"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Handle      respjson.Field
		VotedAt     respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (PollDeliveredWebhookEventDataPollOptionVoter) RawJSON added in v0.34.0

Returns the unmodified JSON received from the API

func (*PollDeliveredWebhookEventDataPollOptionVoter) UnmarshalJSON added in v0.34.0

func (r *PollDeliveredWebhookEventDataPollOptionVoter) UnmarshalJSON(data []byte) error

type PollEnvelope added in v0.29.1

type PollEnvelope struct {
	ChatID    string    `json:"chat_id" api:"required" format:"uuid"`
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// The poll-definition message's ID — reference this poll by it.
	MessageID string `json:"message_id" api:"required" format:"uuid"`
	// Poll content — options and the aggregate voter count.
	Poll Poll `json:"poll" api:"required"`
	// Tapbacks/stickers on the whole poll (message part 0).
	Reactions []shared.Reaction `json:"reactions" api:"required"`
	UpdatedAt time.Time         `json:"updated_at" api:"required" format:"date-time"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ChatID      respjson.Field
		CreatedAt   respjson.Field
		MessageID   respjson.Field
		Poll        respjson.Field
		Reactions   respjson.Field
		UpdatedAt   respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Message-level envelope returned by every poll endpoint.

func (PollEnvelope) RawJSON added in v0.29.1

func (r PollEnvelope) RawJSON() string

Returns the unmodified JSON received from the API

func (*PollEnvelope) UnmarshalJSON added in v0.29.1

func (r *PollEnvelope) UnmarshalJSON(data []byte) error

type PollFailedWebhookEvent added in v0.34.0

type PollFailedWebhookEvent struct {
	// API version for the webhook payload format
	APIVersion string `json:"api_version" api:"required"`
	// When the event was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// Payload for poll.failed — an outbound poll (or poll action) that failed to send.
	// Carries the poll snapshot at failure time plus the error and when it failed.
	Data PollFailedWebhookEventData `json:"data" api:"required"`
	// Unique identifier for this event (for deduplication)
	EventID string `json:"event_id" api:"required" format:"uuid"`
	// Valid webhook event types that can be subscribed to.
	//
	// **Note:** `message.edited` is only delivered to subscriptions using
	// `webhook_version: "2026-02-03"`. Subscribing to this event on a v2025
	// subscription will not produce any deliveries.
	//
	// Any of "message.sent", "message.received", "message.read", "message.delivered",
	// "message.failed", "message.edited", "reaction.added", "reaction.removed",
	// "poll.received", "poll.failed", "poll.sent", "poll.delivered", "poll.read",
	// "poll.updated", "poll.vote.added", "poll.vote.removed", "poll.reaction.added",
	// "participant.added", "participant.removed", "chat.created",
	// "chat.group_name_updated", "chat.group_icon_updated",
	// "chat.group_name_update_failed", "chat.group_icon_update_failed",
	// "chat.background_updated", "chat.background_update_failed",
	// "chat.typing_indicator.started", "chat.typing_indicator.stopped",
	// "phone_number.status_updated", "contact_card.received", "call.initiated",
	// "call.ringing", "call.answered", "call.ended", "call.failed", "call.declined",
	// "call.no_answer", "location.sharing.started", "location.sharing.stopped",
	// "payment.succeeded", "payment.canceled", "payment.expired", "payment.declined",
	// "payment.authorized", "connection.created", "connection.revoked".
	EventType WebhookEventType `json:"event_type" api:"required"`
	// Partner identifier. Present on all webhooks for cross-referencing.
	PartnerID string `json:"partner_id" api:"required"`
	// Trace ID for debugging and correlation across systems.
	TraceID string `json:"trace_id" api:"required"`
	// Date-based webhook payload version. Determined by the `?version=` query
	// parameter in your webhook subscription URL. If no version parameter is
	// specified, defaults based on subscription creation date.
	WebhookVersion string `json:"webhook_version" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		APIVersion     respjson.Field
		CreatedAt      respjson.Field
		Data           respjson.Field
		EventID        respjson.Field
		EventType      respjson.Field
		PartnerID      respjson.Field
		TraceID        respjson.Field
		WebhookVersion respjson.Field
		ExtraFields    map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Complete webhook payload for poll.failed events

func (PollFailedWebhookEvent) RawJSON added in v0.34.0

func (r PollFailedWebhookEvent) RawJSON() string

Returns the unmodified JSON received from the API

func (*PollFailedWebhookEvent) UnmarshalJSON added in v0.34.0

func (r *PollFailedWebhookEvent) UnmarshalJSON(data []byte) error

type PollFailedWebhookEventData added in v0.34.0

type PollFailedWebhookEventData struct {
	// Chat info for poll webhook events.
	Chat PollFailedWebhookEventDataChat `json:"chat" api:"required"`
	// Any of "inbound", "outbound".
	Direction string                          `json:"direction" api:"required"`
	Error     PollFailedWebhookEventDataError `json:"error" api:"required"`
	FailedAt  time.Time                       `json:"failed_at" api:"required" format:"date-time"`
	MessageID string                          `json:"message_id" api:"required" format:"uuid"`
	Poll      PollFailedWebhookEventDataPoll  `json:"poll" api:"required"`
	Service   string                          `json:"service" api:"required"`
	// Null on failure (the send never landed).
	SenderHandle shared.ChatHandle `json:"sender_handle" api:"nullable"`
	// True when this poll was sent on a zero-day-retention line. `poll` is built from
	// the same database read as poll.sent/delivered/read, so every option's `text` is
	// empty.
	ZeroRetention bool `json:"zero_retention"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Chat          respjson.Field
		Direction     respjson.Field
		Error         respjson.Field
		FailedAt      respjson.Field
		MessageID     respjson.Field
		Poll          respjson.Field
		Service       respjson.Field
		SenderHandle  respjson.Field
		ZeroRetention respjson.Field
		ExtraFields   map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Payload for poll.failed — an outbound poll (or poll action) that failed to send. Carries the poll snapshot at failure time plus the error and when it failed.

func (PollFailedWebhookEventData) RawJSON added in v0.34.0

func (r PollFailedWebhookEventData) RawJSON() string

Returns the unmodified JSON received from the API

func (*PollFailedWebhookEventData) UnmarshalJSON added in v0.34.0

func (r *PollFailedWebhookEventData) UnmarshalJSON(data []byte) error

type PollFailedWebhookEventDataChat added in v0.34.0

type PollFailedWebhookEventDataChat struct {
	ID          string            `json:"id" api:"required" format:"uuid"`
	IsGroup     bool              `json:"is_group" api:"nullable"`
	OwnerHandle shared.ChatHandle `json:"owner_handle" api:"nullable"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ID          respjson.Field
		IsGroup     respjson.Field
		OwnerHandle respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Chat info for poll webhook events.

func (PollFailedWebhookEventDataChat) RawJSON added in v0.34.0

Returns the unmodified JSON received from the API

func (*PollFailedWebhookEventDataChat) UnmarshalJSON added in v0.34.0

func (r *PollFailedWebhookEventDataChat) UnmarshalJSON(data []byte) error

type PollFailedWebhookEventDataError added in v0.34.0

type PollFailedWebhookEventDataError struct {
	// Error codes in webhook failure events. The possible set varies by event:
	// message.failed and poll.failed can carry 3007, 4001, 4002, 4005, 4006, 4007, or
	// 4008; the group update failure events (chat.group_name_update_failed,
	// chat.group_icon_update_failed) carry 3007 or 4001; chat.background_update_failed
	// carries 1005, 2011, 4001, or 5002.
	Code    int64  `json:"code" api:"required"`
	Message string `json:"message" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Code        respjson.Field
		Message     respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (PollFailedWebhookEventDataError) RawJSON added in v0.34.0

Returns the unmodified JSON received from the API

func (*PollFailedWebhookEventDataError) UnmarshalJSON added in v0.34.0

func (r *PollFailedWebhookEventDataError) UnmarshalJSON(data []byte) error

type PollFailedWebhookEventDataPoll added in v0.34.0

type PollFailedWebhookEventDataPoll struct {
	Options []PollFailedWebhookEventDataPollOption `json:"options" api:"required"`
	// Distinct participants across the whole poll.
	TotalVoters int64 `json:"total_voters" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Options     respjson.Field
		TotalVoters respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (PollFailedWebhookEventDataPoll) RawJSON added in v0.34.0

Returns the unmodified JSON received from the API

func (*PollFailedWebhookEventDataPoll) UnmarshalJSON added in v0.34.0

func (r *PollFailedWebhookEventDataPoll) UnmarshalJSON(data []byte) error

type PollFailedWebhookEventDataPollOption added in v0.34.0

type PollFailedWebhookEventDataPollOption struct {
	CanBeEdited bool `json:"can_be_edited" api:"required"`
	// The participant who added this option (poll creator for the initial options;
	// whoever added later ones). On a poll.updated this differs from the event's
	// `sender_handle` whenever a remote participant added the option. Null when
	// unknown.
	CreatorHandle shared.ChatHandle                           `json:"creator_handle" api:"required"`
	OptionID      string                                      `json:"option_id" api:"required" format:"uuid"`
	Text          string                                      `json:"text" api:"required"`
	Voters        []PollFailedWebhookEventDataPollOptionVoter `json:"voters" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		CanBeEdited   respjson.Field
		CreatorHandle respjson.Field
		OptionID      respjson.Field
		Text          respjson.Field
		Voters        respjson.Field
		ExtraFields   map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (PollFailedWebhookEventDataPollOption) RawJSON added in v0.34.0

Returns the unmodified JSON received from the API

func (*PollFailedWebhookEventDataPollOption) UnmarshalJSON added in v0.34.0

func (r *PollFailedWebhookEventDataPollOption) UnmarshalJSON(data []byte) error

type PollFailedWebhookEventDataPollOptionVoter added in v0.34.0

type PollFailedWebhookEventDataPollOptionVoter struct {
	Handle  string    `json:"handle" api:"required"`
	VotedAt time.Time `json:"voted_at" api:"required" format:"date-time"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Handle      respjson.Field
		VotedAt     respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (PollFailedWebhookEventDataPollOptionVoter) RawJSON added in v0.34.0

Returns the unmodified JSON received from the API

func (*PollFailedWebhookEventDataPollOptionVoter) UnmarshalJSON added in v0.34.0

func (r *PollFailedWebhookEventDataPollOptionVoter) UnmarshalJSON(data []byte) error

type PollOption added in v0.29.1

type PollOption struct {
	CanBeEdited bool `json:"can_be_edited" api:"required"`
	// The participant who added this option (poll creator for the initial options;
	// whoever added later ones).
	CreatorHandle shared.ChatHandle `json:"creator_handle" api:"required"`
	OptionID      string            `json:"option_id" api:"required" format:"uuid"`
	Text          string            `json:"text" api:"required"`
	// Participants who voted for this option (vote_count = voters.length).
	Voters []PollOptionVoter `json:"voters" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		CanBeEdited   respjson.Field
		CreatorHandle respjson.Field
		OptionID      respjson.Field
		Text          respjson.Field
		Voters        respjson.Field
		ExtraFields   map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (PollOption) RawJSON added in v0.29.1

func (r PollOption) RawJSON() string

Returns the unmodified JSON received from the API

func (*PollOption) UnmarshalJSON added in v0.29.1

func (r *PollOption) UnmarshalJSON(data []byte) error

type PollOptionVoter added in v0.29.1

type PollOptionVoter struct {
	Handle  string    `json:"handle" api:"required"`
	VotedAt time.Time `json:"voted_at" api:"required" format:"date-time"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Handle      respjson.Field
		VotedAt     respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (PollOptionVoter) RawJSON added in v0.29.1

func (r PollOptionVoter) RawJSON() string

Returns the unmodified JSON received from the API

func (*PollOptionVoter) UnmarshalJSON added in v0.29.1

func (r *PollOptionVoter) UnmarshalJSON(data []byte) error

type PollReactionAddedWebhookEvent added in v0.34.0

type PollReactionAddedWebhookEvent struct {
	// API version for the webhook payload format
	APIVersion string `json:"api_version" api:"required"`
	// When the event was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// Payload for poll.reaction.added — a reaction on a poll message. Same shape as
	// reaction.added; `message_id` is the poll-definition message's ID. Poll reactions
	// are stickers, which iMessage cannot remove, so there is no removal counterpart.
	Data ReactionEventBase `json:"data" api:"required"`
	// Unique identifier for this event (for deduplication)
	EventID string `json:"event_id" api:"required" format:"uuid"`
	// Valid webhook event types that can be subscribed to.
	//
	// **Note:** `message.edited` is only delivered to subscriptions using
	// `webhook_version: "2026-02-03"`. Subscribing to this event on a v2025
	// subscription will not produce any deliveries.
	//
	// Any of "message.sent", "message.received", "message.read", "message.delivered",
	// "message.failed", "message.edited", "reaction.added", "reaction.removed",
	// "poll.received", "poll.failed", "poll.sent", "poll.delivered", "poll.read",
	// "poll.updated", "poll.vote.added", "poll.vote.removed", "poll.reaction.added",
	// "participant.added", "participant.removed", "chat.created",
	// "chat.group_name_updated", "chat.group_icon_updated",
	// "chat.group_name_update_failed", "chat.group_icon_update_failed",
	// "chat.background_updated", "chat.background_update_failed",
	// "chat.typing_indicator.started", "chat.typing_indicator.stopped",
	// "phone_number.status_updated", "contact_card.received", "call.initiated",
	// "call.ringing", "call.answered", "call.ended", "call.failed", "call.declined",
	// "call.no_answer", "location.sharing.started", "location.sharing.stopped",
	// "payment.succeeded", "payment.canceled", "payment.expired", "payment.declined",
	// "payment.authorized", "connection.created", "connection.revoked".
	EventType WebhookEventType `json:"event_type" api:"required"`
	// Partner identifier. Present on all webhooks for cross-referencing.
	PartnerID string `json:"partner_id" api:"required"`
	// Trace ID for debugging and correlation across systems.
	TraceID string `json:"trace_id" api:"required"`
	// Date-based webhook payload version. Determined by the `?version=` query
	// parameter in your webhook subscription URL. If no version parameter is
	// specified, defaults based on subscription creation date.
	WebhookVersion string `json:"webhook_version" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		APIVersion     respjson.Field
		CreatedAt      respjson.Field
		Data           respjson.Field
		EventID        respjson.Field
		EventType      respjson.Field
		PartnerID      respjson.Field
		TraceID        respjson.Field
		WebhookVersion respjson.Field
		ExtraFields    map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Complete webhook payload for poll.reaction.added events

func (PollReactionAddedWebhookEvent) RawJSON added in v0.34.0

Returns the unmodified JSON received from the API

func (*PollReactionAddedWebhookEvent) UnmarshalJSON added in v0.34.0

func (r *PollReactionAddedWebhookEvent) UnmarshalJSON(data []byte) error

type PollReadWebhookEvent added in v0.34.0

type PollReadWebhookEvent struct {
	// API version for the webhook payload format
	APIVersion string `json:"api_version" api:"required"`
	// When the event was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// Payload for poll.sent, poll.delivered, and poll.read webhook events. Timestamps
	// indicate state (null = not yet happened): sent → sent_at; delivered →
	// +delivered_at; read → +read_at.
	Data PollReadWebhookEventData `json:"data" api:"required"`
	// Unique identifier for this event (for deduplication)
	EventID string `json:"event_id" api:"required" format:"uuid"`
	// Valid webhook event types that can be subscribed to.
	//
	// **Note:** `message.edited` is only delivered to subscriptions using
	// `webhook_version: "2026-02-03"`. Subscribing to this event on a v2025
	// subscription will not produce any deliveries.
	//
	// Any of "message.sent", "message.received", "message.read", "message.delivered",
	// "message.failed", "message.edited", "reaction.added", "reaction.removed",
	// "poll.received", "poll.failed", "poll.sent", "poll.delivered", "poll.read",
	// "poll.updated", "poll.vote.added", "poll.vote.removed", "poll.reaction.added",
	// "participant.added", "participant.removed", "chat.created",
	// "chat.group_name_updated", "chat.group_icon_updated",
	// "chat.group_name_update_failed", "chat.group_icon_update_failed",
	// "chat.background_updated", "chat.background_update_failed",
	// "chat.typing_indicator.started", "chat.typing_indicator.stopped",
	// "phone_number.status_updated", "contact_card.received", "call.initiated",
	// "call.ringing", "call.answered", "call.ended", "call.failed", "call.declined",
	// "call.no_answer", "location.sharing.started", "location.sharing.stopped",
	// "payment.succeeded", "payment.canceled", "payment.expired", "payment.declined",
	// "payment.authorized", "connection.created", "connection.revoked".
	EventType WebhookEventType `json:"event_type" api:"required"`
	// Partner identifier. Present on all webhooks for cross-referencing.
	PartnerID string `json:"partner_id" api:"required"`
	// Trace ID for debugging and correlation across systems.
	TraceID string `json:"trace_id" api:"required"`
	// Date-based webhook payload version. Determined by the `?version=` query
	// parameter in your webhook subscription URL. If no version parameter is
	// specified, defaults based on subscription creation date.
	WebhookVersion string `json:"webhook_version" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		APIVersion     respjson.Field
		CreatedAt      respjson.Field
		Data           respjson.Field
		EventID        respjson.Field
		EventType      respjson.Field
		PartnerID      respjson.Field
		TraceID        respjson.Field
		WebhookVersion respjson.Field
		ExtraFields    map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Complete webhook payload for poll.read events

func (PollReadWebhookEvent) RawJSON added in v0.34.0

func (r PollReadWebhookEvent) RawJSON() string

Returns the unmodified JSON received from the API

func (*PollReadWebhookEvent) UnmarshalJSON added in v0.34.0

func (r *PollReadWebhookEvent) UnmarshalJSON(data []byte) error

type PollReadWebhookEventData added in v0.34.0

type PollReadWebhookEventData struct {
	// Chat info for poll webhook events.
	Chat      PollReadWebhookEventDataChat `json:"chat" api:"required"`
	CreatedAt time.Time                    `json:"created_at" api:"required" format:"date-time"`
	// Any of "inbound", "outbound".
	Direction   string                       `json:"direction" api:"required"`
	MessageID   string                       `json:"message_id" api:"required" format:"uuid"`
	Poll        PollReadWebhookEventDataPoll `json:"poll" api:"required"`
	Service     string                       `json:"service" api:"required"`
	UpdatedAt   time.Time                    `json:"updated_at" api:"required" format:"date-time"`
	DeliveredAt time.Time                    `json:"delivered_at" api:"nullable" format:"date-time"`
	ReadAt      time.Time                    `json:"read_at" api:"nullable" format:"date-time"`
	// The handle that sent the poll.
	SenderHandle shared.ChatHandle `json:"sender_handle" api:"nullable"`
	SentAt       time.Time         `json:"sent_at" api:"nullable" format:"date-time"`
	// True when this poll was sent on a zero-day-retention line. Every option's `text`
	// is empty in that case — Linq never persists poll option text, so there is
	// nothing to include here. The real text was only ever shown once, synchronously,
	// in the API response when the poll was created or added to.
	ZeroRetention bool `json:"zero_retention"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Chat          respjson.Field
		CreatedAt     respjson.Field
		Direction     respjson.Field
		MessageID     respjson.Field
		Poll          respjson.Field
		Service       respjson.Field
		UpdatedAt     respjson.Field
		DeliveredAt   respjson.Field
		ReadAt        respjson.Field
		SenderHandle  respjson.Field
		SentAt        respjson.Field
		ZeroRetention respjson.Field
		ExtraFields   map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Payload for poll.sent, poll.delivered, and poll.read webhook events. Timestamps indicate state (null = not yet happened): sent → sent_at; delivered → +delivered_at; read → +read_at.

func (PollReadWebhookEventData) RawJSON added in v0.34.0

func (r PollReadWebhookEventData) RawJSON() string

Returns the unmodified JSON received from the API

func (*PollReadWebhookEventData) UnmarshalJSON added in v0.34.0

func (r *PollReadWebhookEventData) UnmarshalJSON(data []byte) error

type PollReadWebhookEventDataChat added in v0.34.0

type PollReadWebhookEventDataChat struct {
	ID          string            `json:"id" api:"required" format:"uuid"`
	IsGroup     bool              `json:"is_group" api:"nullable"`
	OwnerHandle shared.ChatHandle `json:"owner_handle" api:"nullable"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ID          respjson.Field
		IsGroup     respjson.Field
		OwnerHandle respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Chat info for poll webhook events.

func (PollReadWebhookEventDataChat) RawJSON added in v0.34.0

Returns the unmodified JSON received from the API

func (*PollReadWebhookEventDataChat) UnmarshalJSON added in v0.34.0

func (r *PollReadWebhookEventDataChat) UnmarshalJSON(data []byte) error

type PollReadWebhookEventDataPoll added in v0.34.0

type PollReadWebhookEventDataPoll struct {
	Options []PollReadWebhookEventDataPollOption `json:"options" api:"required"`
	// Distinct participants across the whole poll.
	TotalVoters int64 `json:"total_voters" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Options     respjson.Field
		TotalVoters respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (PollReadWebhookEventDataPoll) RawJSON added in v0.34.0

Returns the unmodified JSON received from the API

func (*PollReadWebhookEventDataPoll) UnmarshalJSON added in v0.34.0

func (r *PollReadWebhookEventDataPoll) UnmarshalJSON(data []byte) error

type PollReadWebhookEventDataPollOption added in v0.34.0

type PollReadWebhookEventDataPollOption struct {
	CanBeEdited bool `json:"can_be_edited" api:"required"`
	// The participant who added this option (poll creator for the initial options;
	// whoever added later ones). On a poll.updated this differs from the event's
	// `sender_handle` whenever a remote participant added the option. Null when
	// unknown.
	CreatorHandle shared.ChatHandle                         `json:"creator_handle" api:"required"`
	OptionID      string                                    `json:"option_id" api:"required" format:"uuid"`
	Text          string                                    `json:"text" api:"required"`
	Voters        []PollReadWebhookEventDataPollOptionVoter `json:"voters" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		CanBeEdited   respjson.Field
		CreatorHandle respjson.Field
		OptionID      respjson.Field
		Text          respjson.Field
		Voters        respjson.Field
		ExtraFields   map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (PollReadWebhookEventDataPollOption) RawJSON added in v0.34.0

Returns the unmodified JSON received from the API

func (*PollReadWebhookEventDataPollOption) UnmarshalJSON added in v0.34.0

func (r *PollReadWebhookEventDataPollOption) UnmarshalJSON(data []byte) error

type PollReadWebhookEventDataPollOptionVoter added in v0.34.0

type PollReadWebhookEventDataPollOptionVoter struct {
	Handle  string    `json:"handle" api:"required"`
	VotedAt time.Time `json:"voted_at" api:"required" format:"date-time"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Handle      respjson.Field
		VotedAt     respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (PollReadWebhookEventDataPollOptionVoter) RawJSON added in v0.34.0

Returns the unmodified JSON received from the API

func (*PollReadWebhookEventDataPollOptionVoter) UnmarshalJSON added in v0.34.0

func (r *PollReadWebhookEventDataPollOptionVoter) UnmarshalJSON(data []byte) error

type PollReceivedWebhookEvent added in v0.34.0

type PollReceivedWebhookEvent struct {
	// API version for the webhook payload format
	APIVersion string `json:"api_version" api:"required"`
	// When the event was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// Payload for poll.received — a poll created by someone else and delivered to your
	// line. Carries the full poll snapshot (options, no voters yet) at receipt time.
	Data PollReceivedWebhookEventData `json:"data" api:"required"`
	// Unique identifier for this event (for deduplication)
	EventID string `json:"event_id" api:"required" format:"uuid"`
	// Valid webhook event types that can be subscribed to.
	//
	// **Note:** `message.edited` is only delivered to subscriptions using
	// `webhook_version: "2026-02-03"`. Subscribing to this event on a v2025
	// subscription will not produce any deliveries.
	//
	// Any of "message.sent", "message.received", "message.read", "message.delivered",
	// "message.failed", "message.edited", "reaction.added", "reaction.removed",
	// "poll.received", "poll.failed", "poll.sent", "poll.delivered", "poll.read",
	// "poll.updated", "poll.vote.added", "poll.vote.removed", "poll.reaction.added",
	// "participant.added", "participant.removed", "chat.created",
	// "chat.group_name_updated", "chat.group_icon_updated",
	// "chat.group_name_update_failed", "chat.group_icon_update_failed",
	// "chat.background_updated", "chat.background_update_failed",
	// "chat.typing_indicator.started", "chat.typing_indicator.stopped",
	// "phone_number.status_updated", "contact_card.received", "call.initiated",
	// "call.ringing", "call.answered", "call.ended", "call.failed", "call.declined",
	// "call.no_answer", "location.sharing.started", "location.sharing.stopped",
	// "payment.succeeded", "payment.canceled", "payment.expired", "payment.declined",
	// "payment.authorized", "connection.created", "connection.revoked".
	EventType WebhookEventType `json:"event_type" api:"required"`
	// Partner identifier. Present on all webhooks for cross-referencing.
	PartnerID string `json:"partner_id" api:"required"`
	// Trace ID for debugging and correlation across systems.
	TraceID string `json:"trace_id" api:"required"`
	// Date-based webhook payload version. Determined by the `?version=` query
	// parameter in your webhook subscription URL. If no version parameter is
	// specified, defaults based on subscription creation date.
	WebhookVersion string `json:"webhook_version" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		APIVersion     respjson.Field
		CreatedAt      respjson.Field
		Data           respjson.Field
		EventID        respjson.Field
		EventType      respjson.Field
		PartnerID      respjson.Field
		TraceID        respjson.Field
		WebhookVersion respjson.Field
		ExtraFields    map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Complete webhook payload for poll.received events

func (PollReceivedWebhookEvent) RawJSON added in v0.34.0

func (r PollReceivedWebhookEvent) RawJSON() string

Returns the unmodified JSON received from the API

func (*PollReceivedWebhookEvent) UnmarshalJSON added in v0.34.0

func (r *PollReceivedWebhookEvent) UnmarshalJSON(data []byte) error

type PollReceivedWebhookEventData added in v0.34.0

type PollReceivedWebhookEventData struct {
	// Chat info for poll webhook events.
	Chat      PollReceivedWebhookEventDataChat `json:"chat" api:"required"`
	CreatedAt time.Time                        `json:"created_at" api:"required" format:"date-time"`
	// Any of "inbound", "outbound".
	Direction  string                           `json:"direction" api:"required"`
	MessageID  string                           `json:"message_id" api:"required" format:"uuid"`
	Poll       PollReceivedWebhookEventDataPoll `json:"poll" api:"required"`
	ReceivedAt time.Time                        `json:"received_at" api:"required" format:"date-time"`
	Service    string                           `json:"service" api:"required"`
	UpdatedAt  time.Time                        `json:"updated_at" api:"required" format:"date-time"`
	// The line that created the poll (is_me=false for an inbound poll).
	SenderHandle shared.ChatHandle `json:"sender_handle" api:"nullable"`
	// True when your line has zero-day-retention enabled. Unlike other poll webhooks,
	// option `text` here is still the real, unstripped text as received — Linq never
	// persists it in the database, but this webhook fires from the live inbound event,
	// not a database read, so this is the one place it's shown.
	ZeroRetention bool `json:"zero_retention"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Chat          respjson.Field
		CreatedAt     respjson.Field
		Direction     respjson.Field
		MessageID     respjson.Field
		Poll          respjson.Field
		ReceivedAt    respjson.Field
		Service       respjson.Field
		UpdatedAt     respjson.Field
		SenderHandle  respjson.Field
		ZeroRetention respjson.Field
		ExtraFields   map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Payload for poll.received — a poll created by someone else and delivered to your line. Carries the full poll snapshot (options, no voters yet) at receipt time.

func (PollReceivedWebhookEventData) RawJSON added in v0.34.0

Returns the unmodified JSON received from the API

func (*PollReceivedWebhookEventData) UnmarshalJSON added in v0.34.0

func (r *PollReceivedWebhookEventData) UnmarshalJSON(data []byte) error

type PollReceivedWebhookEventDataChat added in v0.34.0

type PollReceivedWebhookEventDataChat struct {
	ID          string            `json:"id" api:"required" format:"uuid"`
	IsGroup     bool              `json:"is_group" api:"nullable"`
	OwnerHandle shared.ChatHandle `json:"owner_handle" api:"nullable"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ID          respjson.Field
		IsGroup     respjson.Field
		OwnerHandle respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Chat info for poll webhook events.

func (PollReceivedWebhookEventDataChat) RawJSON added in v0.34.0

Returns the unmodified JSON received from the API

func (*PollReceivedWebhookEventDataChat) UnmarshalJSON added in v0.34.0

func (r *PollReceivedWebhookEventDataChat) UnmarshalJSON(data []byte) error

type PollReceivedWebhookEventDataPoll added in v0.34.0

type PollReceivedWebhookEventDataPoll struct {
	Options []PollReceivedWebhookEventDataPollOption `json:"options" api:"required"`
	// Distinct participants across the whole poll.
	TotalVoters int64 `json:"total_voters" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Options     respjson.Field
		TotalVoters respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (PollReceivedWebhookEventDataPoll) RawJSON added in v0.34.0

Returns the unmodified JSON received from the API

func (*PollReceivedWebhookEventDataPoll) UnmarshalJSON added in v0.34.0

func (r *PollReceivedWebhookEventDataPoll) UnmarshalJSON(data []byte) error

type PollReceivedWebhookEventDataPollOption added in v0.34.0

type PollReceivedWebhookEventDataPollOption struct {
	CanBeEdited bool `json:"can_be_edited" api:"required"`
	// The participant who added this option (poll creator for the initial options;
	// whoever added later ones). On a poll.updated this differs from the event's
	// `sender_handle` whenever a remote participant added the option. Null when
	// unknown.
	CreatorHandle shared.ChatHandle                             `json:"creator_handle" api:"required"`
	OptionID      string                                        `json:"option_id" api:"required" format:"uuid"`
	Text          string                                        `json:"text" api:"required"`
	Voters        []PollReceivedWebhookEventDataPollOptionVoter `json:"voters" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		CanBeEdited   respjson.Field
		CreatorHandle respjson.Field
		OptionID      respjson.Field
		Text          respjson.Field
		Voters        respjson.Field
		ExtraFields   map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (PollReceivedWebhookEventDataPollOption) RawJSON added in v0.34.0

Returns the unmodified JSON received from the API

func (*PollReceivedWebhookEventDataPollOption) UnmarshalJSON added in v0.34.0

func (r *PollReceivedWebhookEventDataPollOption) UnmarshalJSON(data []byte) error

type PollReceivedWebhookEventDataPollOptionVoter added in v0.34.0

type PollReceivedWebhookEventDataPollOptionVoter struct {
	Handle  string    `json:"handle" api:"required"`
	VotedAt time.Time `json:"voted_at" api:"required" format:"date-time"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Handle      respjson.Field
		VotedAt     respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (PollReceivedWebhookEventDataPollOptionVoter) RawJSON added in v0.34.0

Returns the unmodified JSON received from the API

func (*PollReceivedWebhookEventDataPollOptionVoter) UnmarshalJSON added in v0.34.0

func (r *PollReceivedWebhookEventDataPollOptionVoter) UnmarshalJSON(data []byte) error

type PollSentWebhookEvent added in v0.34.0

type PollSentWebhookEvent struct {
	// API version for the webhook payload format
	APIVersion string `json:"api_version" api:"required"`
	// When the event was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// Payload for poll.sent, poll.delivered, and poll.read webhook events. Timestamps
	// indicate state (null = not yet happened): sent → sent_at; delivered →
	// +delivered_at; read → +read_at.
	Data PollSentWebhookEventData `json:"data" api:"required"`
	// Unique identifier for this event (for deduplication)
	EventID string `json:"event_id" api:"required" format:"uuid"`
	// Valid webhook event types that can be subscribed to.
	//
	// **Note:** `message.edited` is only delivered to subscriptions using
	// `webhook_version: "2026-02-03"`. Subscribing to this event on a v2025
	// subscription will not produce any deliveries.
	//
	// Any of "message.sent", "message.received", "message.read", "message.delivered",
	// "message.failed", "message.edited", "reaction.added", "reaction.removed",
	// "poll.received", "poll.failed", "poll.sent", "poll.delivered", "poll.read",
	// "poll.updated", "poll.vote.added", "poll.vote.removed", "poll.reaction.added",
	// "participant.added", "participant.removed", "chat.created",
	// "chat.group_name_updated", "chat.group_icon_updated",
	// "chat.group_name_update_failed", "chat.group_icon_update_failed",
	// "chat.background_updated", "chat.background_update_failed",
	// "chat.typing_indicator.started", "chat.typing_indicator.stopped",
	// "phone_number.status_updated", "contact_card.received", "call.initiated",
	// "call.ringing", "call.answered", "call.ended", "call.failed", "call.declined",
	// "call.no_answer", "location.sharing.started", "location.sharing.stopped",
	// "payment.succeeded", "payment.canceled", "payment.expired", "payment.declined",
	// "payment.authorized", "connection.created", "connection.revoked".
	EventType WebhookEventType `json:"event_type" api:"required"`
	// Partner identifier. Present on all webhooks for cross-referencing.
	PartnerID string `json:"partner_id" api:"required"`
	// Trace ID for debugging and correlation across systems.
	TraceID string `json:"trace_id" api:"required"`
	// Date-based webhook payload version. Determined by the `?version=` query
	// parameter in your webhook subscription URL. If no version parameter is
	// specified, defaults based on subscription creation date.
	WebhookVersion string `json:"webhook_version" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		APIVersion     respjson.Field
		CreatedAt      respjson.Field
		Data           respjson.Field
		EventID        respjson.Field
		EventType      respjson.Field
		PartnerID      respjson.Field
		TraceID        respjson.Field
		WebhookVersion respjson.Field
		ExtraFields    map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Complete webhook payload for poll.sent events

func (PollSentWebhookEvent) RawJSON added in v0.34.0

func (r PollSentWebhookEvent) RawJSON() string

Returns the unmodified JSON received from the API

func (*PollSentWebhookEvent) UnmarshalJSON added in v0.34.0

func (r *PollSentWebhookEvent) UnmarshalJSON(data []byte) error

type PollSentWebhookEventData added in v0.34.0

type PollSentWebhookEventData struct {
	// Chat info for poll webhook events.
	Chat      PollSentWebhookEventDataChat `json:"chat" api:"required"`
	CreatedAt time.Time                    `json:"created_at" api:"required" format:"date-time"`
	// Any of "inbound", "outbound".
	Direction   string                       `json:"direction" api:"required"`
	MessageID   string                       `json:"message_id" api:"required" format:"uuid"`
	Poll        PollSentWebhookEventDataPoll `json:"poll" api:"required"`
	Service     string                       `json:"service" api:"required"`
	UpdatedAt   time.Time                    `json:"updated_at" api:"required" format:"date-time"`
	DeliveredAt time.Time                    `json:"delivered_at" api:"nullable" format:"date-time"`
	ReadAt      time.Time                    `json:"read_at" api:"nullable" format:"date-time"`
	// The handle that sent the poll.
	SenderHandle shared.ChatHandle `json:"sender_handle" api:"nullable"`
	SentAt       time.Time         `json:"sent_at" api:"nullable" format:"date-time"`
	// True when this poll was sent on a zero-day-retention line. Every option's `text`
	// is empty in that case — Linq never persists poll option text, so there is
	// nothing to include here. The real text was only ever shown once, synchronously,
	// in the API response when the poll was created or added to.
	ZeroRetention bool `json:"zero_retention"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Chat          respjson.Field
		CreatedAt     respjson.Field
		Direction     respjson.Field
		MessageID     respjson.Field
		Poll          respjson.Field
		Service       respjson.Field
		UpdatedAt     respjson.Field
		DeliveredAt   respjson.Field
		ReadAt        respjson.Field
		SenderHandle  respjson.Field
		SentAt        respjson.Field
		ZeroRetention respjson.Field
		ExtraFields   map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Payload for poll.sent, poll.delivered, and poll.read webhook events. Timestamps indicate state (null = not yet happened): sent → sent_at; delivered → +delivered_at; read → +read_at.

func (PollSentWebhookEventData) RawJSON added in v0.34.0

func (r PollSentWebhookEventData) RawJSON() string

Returns the unmodified JSON received from the API

func (*PollSentWebhookEventData) UnmarshalJSON added in v0.34.0

func (r *PollSentWebhookEventData) UnmarshalJSON(data []byte) error

type PollSentWebhookEventDataChat added in v0.34.0

type PollSentWebhookEventDataChat struct {
	ID          string            `json:"id" api:"required" format:"uuid"`
	IsGroup     bool              `json:"is_group" api:"nullable"`
	OwnerHandle shared.ChatHandle `json:"owner_handle" api:"nullable"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ID          respjson.Field
		IsGroup     respjson.Field
		OwnerHandle respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Chat info for poll webhook events.

func (PollSentWebhookEventDataChat) RawJSON added in v0.34.0

Returns the unmodified JSON received from the API

func (*PollSentWebhookEventDataChat) UnmarshalJSON added in v0.34.0

func (r *PollSentWebhookEventDataChat) UnmarshalJSON(data []byte) error

type PollSentWebhookEventDataPoll added in v0.34.0

type PollSentWebhookEventDataPoll struct {
	Options []PollSentWebhookEventDataPollOption `json:"options" api:"required"`
	// Distinct participants across the whole poll.
	TotalVoters int64 `json:"total_voters" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Options     respjson.Field
		TotalVoters respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (PollSentWebhookEventDataPoll) RawJSON added in v0.34.0

Returns the unmodified JSON received from the API

func (*PollSentWebhookEventDataPoll) UnmarshalJSON added in v0.34.0

func (r *PollSentWebhookEventDataPoll) UnmarshalJSON(data []byte) error

type PollSentWebhookEventDataPollOption added in v0.34.0

type PollSentWebhookEventDataPollOption struct {
	CanBeEdited bool `json:"can_be_edited" api:"required"`
	// The participant who added this option (poll creator for the initial options;
	// whoever added later ones). On a poll.updated this differs from the event's
	// `sender_handle` whenever a remote participant added the option. Null when
	// unknown.
	CreatorHandle shared.ChatHandle                         `json:"creator_handle" api:"required"`
	OptionID      string                                    `json:"option_id" api:"required" format:"uuid"`
	Text          string                                    `json:"text" api:"required"`
	Voters        []PollSentWebhookEventDataPollOptionVoter `json:"voters" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		CanBeEdited   respjson.Field
		CreatorHandle respjson.Field
		OptionID      respjson.Field
		Text          respjson.Field
		Voters        respjson.Field
		ExtraFields   map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (PollSentWebhookEventDataPollOption) RawJSON added in v0.34.0

Returns the unmodified JSON received from the API

func (*PollSentWebhookEventDataPollOption) UnmarshalJSON added in v0.34.0

func (r *PollSentWebhookEventDataPollOption) UnmarshalJSON(data []byte) error

type PollSentWebhookEventDataPollOptionVoter added in v0.34.0

type PollSentWebhookEventDataPollOptionVoter struct {
	Handle  string    `json:"handle" api:"required"`
	VotedAt time.Time `json:"voted_at" api:"required" format:"date-time"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Handle      respjson.Field
		VotedAt     respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (PollSentWebhookEventDataPollOptionVoter) RawJSON added in v0.34.0

Returns the unmodified JSON received from the API

func (*PollSentWebhookEventDataPollOptionVoter) UnmarshalJSON added in v0.34.0

func (r *PollSentWebhookEventDataPollOptionVoter) UnmarshalJSON(data []byte) error

type PollUpdatedWebhookEvent added in v0.34.0

type PollUpdatedWebhookEvent struct {
	// API version for the webhook payload format
	APIVersion string `json:"api_version" api:"required"`
	// When the event was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// Payload for poll.updated (option(s) added — add-only).
	Data PollUpdatedWebhookEventData `json:"data" api:"required"`
	// Unique identifier for this event (for deduplication)
	EventID string `json:"event_id" api:"required" format:"uuid"`
	// Valid webhook event types that can be subscribed to.
	//
	// **Note:** `message.edited` is only delivered to subscriptions using
	// `webhook_version: "2026-02-03"`. Subscribing to this event on a v2025
	// subscription will not produce any deliveries.
	//
	// Any of "message.sent", "message.received", "message.read", "message.delivered",
	// "message.failed", "message.edited", "reaction.added", "reaction.removed",
	// "poll.received", "poll.failed", "poll.sent", "poll.delivered", "poll.read",
	// "poll.updated", "poll.vote.added", "poll.vote.removed", "poll.reaction.added",
	// "participant.added", "participant.removed", "chat.created",
	// "chat.group_name_updated", "chat.group_icon_updated",
	// "chat.group_name_update_failed", "chat.group_icon_update_failed",
	// "chat.background_updated", "chat.background_update_failed",
	// "chat.typing_indicator.started", "chat.typing_indicator.stopped",
	// "phone_number.status_updated", "contact_card.received", "call.initiated",
	// "call.ringing", "call.answered", "call.ended", "call.failed", "call.declined",
	// "call.no_answer", "location.sharing.started", "location.sharing.stopped",
	// "payment.succeeded", "payment.canceled", "payment.expired", "payment.declined",
	// "payment.authorized", "connection.created", "connection.revoked".
	EventType WebhookEventType `json:"event_type" api:"required"`
	// Partner identifier. Present on all webhooks for cross-referencing.
	PartnerID string `json:"partner_id" api:"required"`
	// Trace ID for debugging and correlation across systems.
	TraceID string `json:"trace_id" api:"required"`
	// Date-based webhook payload version. Determined by the `?version=` query
	// parameter in your webhook subscription URL. If no version parameter is
	// specified, defaults based on subscription creation date.
	WebhookVersion string `json:"webhook_version" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		APIVersion     respjson.Field
		CreatedAt      respjson.Field
		Data           respjson.Field
		EventID        respjson.Field
		EventType      respjson.Field
		PartnerID      respjson.Field
		TraceID        respjson.Field
		WebhookVersion respjson.Field
		ExtraFields    map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Complete webhook payload for poll.updated events

func (PollUpdatedWebhookEvent) RawJSON added in v0.34.0

func (r PollUpdatedWebhookEvent) RawJSON() string

Returns the unmodified JSON received from the API

func (*PollUpdatedWebhookEvent) UnmarshalJSON added in v0.34.0

func (r *PollUpdatedWebhookEvent) UnmarshalJSON(data []byte) error

type PollUpdatedWebhookEventData added in v0.34.0

type PollUpdatedWebhookEventData struct {
	// Only the options this update added — never the ones the poll already had. Fetch
	// the poll to read its full option set.
	AddedOptions []PollUpdatedWebhookEventDataAddedOption `json:"added_options" api:"required"`
	// Chat info for poll webhook events.
	Chat PollUpdatedWebhookEventDataChat `json:"chat" api:"required"`
	// Any of "inbound", "outbound".
	Direction string `json:"direction" api:"required"`
	MessageID string `json:"message_id" api:"required" format:"uuid"`
	// Your line — the one that received or sent this update. Always present. On an
	// inbound update this is NOT who added the option: use
	// `added_options[].creator_handle` for that, which will be the remote participant.
	SenderHandle shared.ChatHandle `json:"sender_handle" api:"required"`
	Service      string            `json:"service" api:"required"`
	// True when zero-day-retention applies to this update. Behavior differs by
	// `direction`: on an inbound update, `added_options[].text` is the real text a
	// participant just added; on an outbound update, it is empty — you already saw the
	// real text once, synchronously, in the API response when you made the add, and
	// this webhook is built from a database read, which never stored it.
	ZeroRetention bool `json:"zero_retention"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		AddedOptions  respjson.Field
		Chat          respjson.Field
		Direction     respjson.Field
		MessageID     respjson.Field
		SenderHandle  respjson.Field
		Service       respjson.Field
		ZeroRetention respjson.Field
		ExtraFields   map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Payload for poll.updated (option(s) added — add-only).

func (PollUpdatedWebhookEventData) RawJSON added in v0.34.0

func (r PollUpdatedWebhookEventData) RawJSON() string

Returns the unmodified JSON received from the API

func (*PollUpdatedWebhookEventData) UnmarshalJSON added in v0.34.0

func (r *PollUpdatedWebhookEventData) UnmarshalJSON(data []byte) error

type PollUpdatedWebhookEventDataAddedOption added in v0.34.0

type PollUpdatedWebhookEventDataAddedOption struct {
	CanBeEdited bool `json:"can_be_edited" api:"required"`
	// The participant who added this option (poll creator for the initial options;
	// whoever added later ones). On a poll.updated this differs from the event's
	// `sender_handle` whenever a remote participant added the option. Null when
	// unknown.
	CreatorHandle shared.ChatHandle                             `json:"creator_handle" api:"required"`
	OptionID      string                                        `json:"option_id" api:"required" format:"uuid"`
	Text          string                                        `json:"text" api:"required"`
	Voters        []PollUpdatedWebhookEventDataAddedOptionVoter `json:"voters" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		CanBeEdited   respjson.Field
		CreatorHandle respjson.Field
		OptionID      respjson.Field
		Text          respjson.Field
		Voters        respjson.Field
		ExtraFields   map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (PollUpdatedWebhookEventDataAddedOption) RawJSON added in v0.34.0

Returns the unmodified JSON received from the API

func (*PollUpdatedWebhookEventDataAddedOption) UnmarshalJSON added in v0.34.0

func (r *PollUpdatedWebhookEventDataAddedOption) UnmarshalJSON(data []byte) error

type PollUpdatedWebhookEventDataAddedOptionVoter added in v0.34.0

type PollUpdatedWebhookEventDataAddedOptionVoter struct {
	Handle  string    `json:"handle" api:"required"`
	VotedAt time.Time `json:"voted_at" api:"required" format:"date-time"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Handle      respjson.Field
		VotedAt     respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (PollUpdatedWebhookEventDataAddedOptionVoter) RawJSON added in v0.34.0

Returns the unmodified JSON received from the API

func (*PollUpdatedWebhookEventDataAddedOptionVoter) UnmarshalJSON added in v0.34.0

func (r *PollUpdatedWebhookEventDataAddedOptionVoter) UnmarshalJSON(data []byte) error

type PollUpdatedWebhookEventDataChat added in v0.34.0

type PollUpdatedWebhookEventDataChat struct {
	ID          string            `json:"id" api:"required" format:"uuid"`
	IsGroup     bool              `json:"is_group" api:"nullable"`
	OwnerHandle shared.ChatHandle `json:"owner_handle" api:"nullable"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ID          respjson.Field
		IsGroup     respjson.Field
		OwnerHandle respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Chat info for poll webhook events.

func (PollUpdatedWebhookEventDataChat) RawJSON added in v0.34.0

Returns the unmodified JSON received from the API

func (*PollUpdatedWebhookEventDataChat) UnmarshalJSON added in v0.34.0

func (r *PollUpdatedWebhookEventDataChat) UnmarshalJSON(data []byte) error

type PollVoteAddedWebhookEvent added in v0.34.0

type PollVoteAddedWebhookEvent struct {
	// API version for the webhook payload format
	APIVersion string `json:"api_version" api:"required"`
	// When the event was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// Payload for poll.vote.added and poll.vote.removed (one option toggled).
	Data PollVoteAddedWebhookEventData `json:"data" api:"required"`
	// Unique identifier for this event (for deduplication)
	EventID string `json:"event_id" api:"required" format:"uuid"`
	// Valid webhook event types that can be subscribed to.
	//
	// **Note:** `message.edited` is only delivered to subscriptions using
	// `webhook_version: "2026-02-03"`. Subscribing to this event on a v2025
	// subscription will not produce any deliveries.
	//
	// Any of "message.sent", "message.received", "message.read", "message.delivered",
	// "message.failed", "message.edited", "reaction.added", "reaction.removed",
	// "poll.received", "poll.failed", "poll.sent", "poll.delivered", "poll.read",
	// "poll.updated", "poll.vote.added", "poll.vote.removed", "poll.reaction.added",
	// "participant.added", "participant.removed", "chat.created",
	// "chat.group_name_updated", "chat.group_icon_updated",
	// "chat.group_name_update_failed", "chat.group_icon_update_failed",
	// "chat.background_updated", "chat.background_update_failed",
	// "chat.typing_indicator.started", "chat.typing_indicator.stopped",
	// "phone_number.status_updated", "contact_card.received", "call.initiated",
	// "call.ringing", "call.answered", "call.ended", "call.failed", "call.declined",
	// "call.no_answer", "location.sharing.started", "location.sharing.stopped",
	// "payment.succeeded", "payment.canceled", "payment.expired", "payment.declined",
	// "payment.authorized", "connection.created", "connection.revoked".
	EventType WebhookEventType `json:"event_type" api:"required"`
	// Partner identifier. Present on all webhooks for cross-referencing.
	PartnerID string `json:"partner_id" api:"required"`
	// Trace ID for debugging and correlation across systems.
	TraceID string `json:"trace_id" api:"required"`
	// Date-based webhook payload version. Determined by the `?version=` query
	// parameter in your webhook subscription URL. If no version parameter is
	// specified, defaults based on subscription creation date.
	WebhookVersion string `json:"webhook_version" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		APIVersion     respjson.Field
		CreatedAt      respjson.Field
		Data           respjson.Field
		EventID        respjson.Field
		EventType      respjson.Field
		PartnerID      respjson.Field
		TraceID        respjson.Field
		WebhookVersion respjson.Field
		ExtraFields    map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Complete webhook payload for poll.vote.added events

func (PollVoteAddedWebhookEvent) RawJSON added in v0.34.0

func (r PollVoteAddedWebhookEvent) RawJSON() string

Returns the unmodified JSON received from the API

func (*PollVoteAddedWebhookEvent) UnmarshalJSON added in v0.34.0

func (r *PollVoteAddedWebhookEvent) UnmarshalJSON(data []byte) error

type PollVoteAddedWebhookEventData added in v0.34.0

type PollVoteAddedWebhookEventData struct {
	// Chat info for poll webhook events.
	Chat PollVoteAddedWebhookEventDataChat `json:"chat" api:"required"`
	// Any of "inbound", "outbound".
	Direction string `json:"direction" api:"required"`
	MessageID string `json:"message_id" api:"required" format:"uuid"`
	OptionID  string `json:"option_id" api:"required" format:"uuid"`
	// The voter — always present.
	SenderHandle shared.ChatHandle `json:"sender_handle" api:"required"`
	Service      string            `json:"service" api:"required"`
	// True when this poll is on a zero-day-retention line. Votes are unaffected by
	// zero-day-retention — a vote choice is always persisted and delivered regardless
	// — this flag is informational only, telling you why this poll's other webhooks
	// (poll.sent, poll.updated, etc.) may carry empty option text.
	ZeroRetention bool `json:"zero_retention"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Chat          respjson.Field
		Direction     respjson.Field
		MessageID     respjson.Field
		OptionID      respjson.Field
		SenderHandle  respjson.Field
		Service       respjson.Field
		ZeroRetention respjson.Field
		ExtraFields   map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Payload for poll.vote.added and poll.vote.removed (one option toggled).

func (PollVoteAddedWebhookEventData) RawJSON added in v0.34.0

Returns the unmodified JSON received from the API

func (*PollVoteAddedWebhookEventData) UnmarshalJSON added in v0.34.0

func (r *PollVoteAddedWebhookEventData) UnmarshalJSON(data []byte) error

type PollVoteAddedWebhookEventDataChat added in v0.34.0

type PollVoteAddedWebhookEventDataChat struct {
	ID          string            `json:"id" api:"required" format:"uuid"`
	IsGroup     bool              `json:"is_group" api:"nullable"`
	OwnerHandle shared.ChatHandle `json:"owner_handle" api:"nullable"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ID          respjson.Field
		IsGroup     respjson.Field
		OwnerHandle respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Chat info for poll webhook events.

func (PollVoteAddedWebhookEventDataChat) RawJSON added in v0.34.0

Returns the unmodified JSON received from the API

func (*PollVoteAddedWebhookEventDataChat) UnmarshalJSON added in v0.34.0

func (r *PollVoteAddedWebhookEventDataChat) UnmarshalJSON(data []byte) error

type PollVoteRemovedWebhookEvent added in v0.34.0

type PollVoteRemovedWebhookEvent struct {
	// API version for the webhook payload format
	APIVersion string `json:"api_version" api:"required"`
	// When the event was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// Payload for poll.vote.added and poll.vote.removed (one option toggled).
	Data PollVoteRemovedWebhookEventData `json:"data" api:"required"`
	// Unique identifier for this event (for deduplication)
	EventID string `json:"event_id" api:"required" format:"uuid"`
	// Valid webhook event types that can be subscribed to.
	//
	// **Note:** `message.edited` is only delivered to subscriptions using
	// `webhook_version: "2026-02-03"`. Subscribing to this event on a v2025
	// subscription will not produce any deliveries.
	//
	// Any of "message.sent", "message.received", "message.read", "message.delivered",
	// "message.failed", "message.edited", "reaction.added", "reaction.removed",
	// "poll.received", "poll.failed", "poll.sent", "poll.delivered", "poll.read",
	// "poll.updated", "poll.vote.added", "poll.vote.removed", "poll.reaction.added",
	// "participant.added", "participant.removed", "chat.created",
	// "chat.group_name_updated", "chat.group_icon_updated",
	// "chat.group_name_update_failed", "chat.group_icon_update_failed",
	// "chat.background_updated", "chat.background_update_failed",
	// "chat.typing_indicator.started", "chat.typing_indicator.stopped",
	// "phone_number.status_updated", "contact_card.received", "call.initiated",
	// "call.ringing", "call.answered", "call.ended", "call.failed", "call.declined",
	// "call.no_answer", "location.sharing.started", "location.sharing.stopped",
	// "payment.succeeded", "payment.canceled", "payment.expired", "payment.declined",
	// "payment.authorized", "connection.created", "connection.revoked".
	EventType WebhookEventType `json:"event_type" api:"required"`
	// Partner identifier. Present on all webhooks for cross-referencing.
	PartnerID string `json:"partner_id" api:"required"`
	// Trace ID for debugging and correlation across systems.
	TraceID string `json:"trace_id" api:"required"`
	// Date-based webhook payload version. Determined by the `?version=` query
	// parameter in your webhook subscription URL. If no version parameter is
	// specified, defaults based on subscription creation date.
	WebhookVersion string `json:"webhook_version" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		APIVersion     respjson.Field
		CreatedAt      respjson.Field
		Data           respjson.Field
		EventID        respjson.Field
		EventType      respjson.Field
		PartnerID      respjson.Field
		TraceID        respjson.Field
		WebhookVersion respjson.Field
		ExtraFields    map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Complete webhook payload for poll.vote.removed events

func (PollVoteRemovedWebhookEvent) RawJSON added in v0.34.0

func (r PollVoteRemovedWebhookEvent) RawJSON() string

Returns the unmodified JSON received from the API

func (*PollVoteRemovedWebhookEvent) UnmarshalJSON added in v0.34.0

func (r *PollVoteRemovedWebhookEvent) UnmarshalJSON(data []byte) error

type PollVoteRemovedWebhookEventData added in v0.34.0

type PollVoteRemovedWebhookEventData struct {
	// Chat info for poll webhook events.
	Chat PollVoteRemovedWebhookEventDataChat `json:"chat" api:"required"`
	// Any of "inbound", "outbound".
	Direction string `json:"direction" api:"required"`
	MessageID string `json:"message_id" api:"required" format:"uuid"`
	OptionID  string `json:"option_id" api:"required" format:"uuid"`
	// The voter — always present.
	SenderHandle shared.ChatHandle `json:"sender_handle" api:"required"`
	Service      string            `json:"service" api:"required"`
	// True when this poll is on a zero-day-retention line. Votes are unaffected by
	// zero-day-retention — a vote choice is always persisted and delivered regardless
	// — this flag is informational only, telling you why this poll's other webhooks
	// (poll.sent, poll.updated, etc.) may carry empty option text.
	ZeroRetention bool `json:"zero_retention"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Chat          respjson.Field
		Direction     respjson.Field
		MessageID     respjson.Field
		OptionID      respjson.Field
		SenderHandle  respjson.Field
		Service       respjson.Field
		ZeroRetention respjson.Field
		ExtraFields   map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Payload for poll.vote.added and poll.vote.removed (one option toggled).

func (PollVoteRemovedWebhookEventData) RawJSON added in v0.34.0

Returns the unmodified JSON received from the API

func (*PollVoteRemovedWebhookEventData) UnmarshalJSON added in v0.34.0

func (r *PollVoteRemovedWebhookEventData) UnmarshalJSON(data []byte) error

type PollVoteRemovedWebhookEventDataChat added in v0.34.0

type PollVoteRemovedWebhookEventDataChat struct {
	ID          string            `json:"id" api:"required" format:"uuid"`
	IsGroup     bool              `json:"is_group" api:"nullable"`
	OwnerHandle shared.ChatHandle `json:"owner_handle" api:"nullable"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ID          respjson.Field
		IsGroup     respjson.Field
		OwnerHandle respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Chat info for poll webhook events.

func (PollVoteRemovedWebhookEventDataChat) RawJSON added in v0.34.0

Returns the unmodified JSON received from the API

func (*PollVoteRemovedWebhookEventDataChat) UnmarshalJSON added in v0.34.0

func (r *PollVoteRemovedWebhookEventDataChat) UnmarshalJSON(data []byte) error

type Reaction

type Reaction = shared.Reaction

This is an alias to an internal type.

type ReactionAddedWebhookEvent added in v0.12.0

type ReactionAddedWebhookEvent struct {
	// API version for the webhook payload format
	APIVersion string `json:"api_version" api:"required"`
	// When the event was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// Payload for reaction.added webhook events
	Data ReactionEventBase `json:"data" api:"required"`
	// Unique identifier for this event (for deduplication)
	EventID string `json:"event_id" api:"required" format:"uuid"`
	// Valid webhook event types that can be subscribed to.
	//
	// **Note:** `message.edited` is only delivered to subscriptions using
	// `webhook_version: "2026-02-03"`. Subscribing to this event on a v2025
	// subscription will not produce any deliveries.
	//
	// Any of "message.sent", "message.received", "message.read", "message.delivered",
	// "message.failed", "message.edited", "reaction.added", "reaction.removed",
	// "poll.received", "poll.failed", "poll.sent", "poll.delivered", "poll.read",
	// "poll.updated", "poll.vote.added", "poll.vote.removed", "poll.reaction.added",
	// "participant.added", "participant.removed", "chat.created",
	// "chat.group_name_updated", "chat.group_icon_updated",
	// "chat.group_name_update_failed", "chat.group_icon_update_failed",
	// "chat.background_updated", "chat.background_update_failed",
	// "chat.typing_indicator.started", "chat.typing_indicator.stopped",
	// "phone_number.status_updated", "contact_card.received", "call.initiated",
	// "call.ringing", "call.answered", "call.ended", "call.failed", "call.declined",
	// "call.no_answer", "location.sharing.started", "location.sharing.stopped",
	// "payment.succeeded", "payment.canceled", "payment.expired", "payment.declined",
	// "payment.authorized", "connection.created", "connection.revoked".
	EventType WebhookEventType `json:"event_type" api:"required"`
	// Partner identifier. Present on all webhooks for cross-referencing.
	PartnerID string `json:"partner_id" api:"required"`
	// Trace ID for debugging and correlation across systems.
	TraceID string `json:"trace_id" api:"required"`
	// Date-based webhook payload version. Determined by the `?version=` query
	// parameter in your webhook subscription URL. If no version parameter is
	// specified, defaults based on subscription creation date.
	WebhookVersion string `json:"webhook_version" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		APIVersion     respjson.Field
		CreatedAt      respjson.Field
		Data           respjson.Field
		EventID        respjson.Field
		EventType      respjson.Field
		PartnerID      respjson.Field
		TraceID        respjson.Field
		WebhookVersion respjson.Field
		ExtraFields    map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Complete webhook payload for reaction.added events

func (ReactionAddedWebhookEvent) RawJSON added in v0.12.0

func (r ReactionAddedWebhookEvent) RawJSON() string

Returns the unmodified JSON received from the API

func (*ReactionAddedWebhookEvent) UnmarshalJSON added in v0.12.0

func (r *ReactionAddedWebhookEvent) UnmarshalJSON(data []byte) error

type ReactionEventBase added in v0.2.0

type ReactionEventBase struct {
	// Whether this reaction was from the owner of the phone number (true) or from
	// someone else (false)
	IsFromMe bool `json:"is_from_me" api:"required"`
	// Type of reaction. Standard iMessage tapbacks are love, like, dislike, laugh,
	// emphasize, question. Custom emoji reactions have type "custom" with the actual
	// emoji in the custom_emoji field. Sticker reactions have type "sticker" with
	// sticker attachment details in the sticker field.
	//
	// Any of "love", "like", "dislike", "laugh", "emphasize", "question", "custom",
	// "sticker".
	ReactionType shared.ReactionType `json:"reaction_type" api:"required"`
	// Chat identifier (UUID)
	ChatID string `json:"chat_id"`
	// The actual emoji when reaction_type is "custom". Null for standard tapbacks.
	CustomEmoji string `json:"custom_emoji" api:"nullable"`
	// DEPRECATED: Use from_handle instead. Phone number or email address of the person
	// who added/removed the reaction.
	//
	// Deprecated: deprecated
	From string `json:"from"`
	// The person who added/removed the reaction as a full handle object
	FromHandle shared.ChatHandle `json:"from_handle"`
	// Message identifier (UUID) that the reaction was added to or removed from
	MessageID string `json:"message_id"`
	// Index of the message part that was reacted to (0-based)
	PartIndex int64 `json:"part_index"`
	// When the reaction was added or removed
	ReactedAt time.Time `json:"reacted_at" format:"date-time"`
	// Identifier for this reaction. Pass it to
	// `PATCH /v3/messages/{messageId}/reactions/{reactionId}` to move a sticker.
	// Stickers stack, so this is what distinguishes one sticker from another on the
	// same message.
	ReactionID string `json:"reaction_id" format:"uuid"`
	// Messaging service type
	//
	// Any of "iMessage", "SMS", "RCS".
	Service shared.ServiceType `json:"service"`
	// Sticker attachment details when reaction_type is "sticker". Null for non-sticker
	// reactions.
	Sticker ReactionEventBaseSticker `json:"sticker" api:"nullable"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		IsFromMe     respjson.Field
		ReactionType respjson.Field
		ChatID       respjson.Field
		CustomEmoji  respjson.Field
		From         respjson.Field
		FromHandle   respjson.Field
		MessageID    respjson.Field
		PartIndex    respjson.Field
		ReactedAt    respjson.Field
		ReactionID   respjson.Field
		Service      respjson.Field
		Sticker      respjson.Field
		ExtraFields  map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (ReactionEventBase) RawJSON added in v0.2.0

func (r ReactionEventBase) RawJSON() string

Returns the unmodified JSON received from the API

func (*ReactionEventBase) UnmarshalJSON added in v0.2.0

func (r *ReactionEventBase) UnmarshalJSON(data []byte) error

type ReactionEventBaseSticker added in v0.2.0

type ReactionEventBaseSticker struct {
	// Filename of the sticker
	FileName string `json:"file_name"`
	// Sticker image height in pixels
	Height int64 `json:"height"`
	// MIME type of the sticker image
	MimeType string `json:"mime_type"`
	// Presigned URL for downloading the sticker image (expires in 1 hour).
	URL string `json:"url" format:"uri"`
	// Sticker image width in pixels
	Width int64 `json:"width"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		FileName    respjson.Field
		Height      respjson.Field
		MimeType    respjson.Field
		URL         respjson.Field
		Width       respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Sticker attachment details when reaction_type is "sticker". Null for non-sticker reactions.

func (ReactionEventBaseSticker) RawJSON added in v0.2.0

func (r ReactionEventBaseSticker) RawJSON() string

Returns the unmodified JSON received from the API

func (*ReactionEventBaseSticker) UnmarshalJSON added in v0.2.0

func (r *ReactionEventBaseSticker) UnmarshalJSON(data []byte) error

type ReactionRemovedWebhookEvent added in v0.12.0

type ReactionRemovedWebhookEvent struct {
	// API version for the webhook payload format
	APIVersion string `json:"api_version" api:"required"`
	// When the event was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// Payload for reaction.removed webhook events
	Data ReactionEventBase `json:"data" api:"required"`
	// Unique identifier for this event (for deduplication)
	EventID string `json:"event_id" api:"required" format:"uuid"`
	// Valid webhook event types that can be subscribed to.
	//
	// **Note:** `message.edited` is only delivered to subscriptions using
	// `webhook_version: "2026-02-03"`. Subscribing to this event on a v2025
	// subscription will not produce any deliveries.
	//
	// Any of "message.sent", "message.received", "message.read", "message.delivered",
	// "message.failed", "message.edited", "reaction.added", "reaction.removed",
	// "poll.received", "poll.failed", "poll.sent", "poll.delivered", "poll.read",
	// "poll.updated", "poll.vote.added", "poll.vote.removed", "poll.reaction.added",
	// "participant.added", "participant.removed", "chat.created",
	// "chat.group_name_updated", "chat.group_icon_updated",
	// "chat.group_name_update_failed", "chat.group_icon_update_failed",
	// "chat.background_updated", "chat.background_update_failed",
	// "chat.typing_indicator.started", "chat.typing_indicator.stopped",
	// "phone_number.status_updated", "contact_card.received", "call.initiated",
	// "call.ringing", "call.answered", "call.ended", "call.failed", "call.declined",
	// "call.no_answer", "location.sharing.started", "location.sharing.stopped",
	// "payment.succeeded", "payment.canceled", "payment.expired", "payment.declined",
	// "payment.authorized", "connection.created", "connection.revoked".
	EventType WebhookEventType `json:"event_type" api:"required"`
	// Partner identifier. Present on all webhooks for cross-referencing.
	PartnerID string `json:"partner_id" api:"required"`
	// Trace ID for debugging and correlation across systems.
	TraceID string `json:"trace_id" api:"required"`
	// Date-based webhook payload version. Determined by the `?version=` query
	// parameter in your webhook subscription URL. If no version parameter is
	// specified, defaults based on subscription creation date.
	WebhookVersion string `json:"webhook_version" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		APIVersion     respjson.Field
		CreatedAt      respjson.Field
		Data           respjson.Field
		EventID        respjson.Field
		EventType      respjson.Field
		PartnerID      respjson.Field
		TraceID        respjson.Field
		WebhookVersion respjson.Field
		ExtraFields    map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Complete webhook payload for reaction.removed events

func (ReactionRemovedWebhookEvent) RawJSON added in v0.12.0

func (r ReactionRemovedWebhookEvent) RawJSON() string

Returns the unmodified JSON received from the API

func (*ReactionRemovedWebhookEvent) UnmarshalJSON added in v0.12.0

func (r *ReactionRemovedWebhookEvent) UnmarshalJSON(data []byte) error

type ReactionSticker added in v0.1.1

type ReactionSticker = shared.ReactionSticker

Sticker attachment details when reaction_type is "sticker". Null for non-sticker reactions.

This is an alias to an internal type.

type ReactionType

type ReactionType = shared.ReactionType

Type of reaction. Standard iMessage tapbacks are love, like, dislike, laugh, emphasize, question. Custom emoji reactions have type "custom" with the actual emoji in the custom_emoji field. Sticker reactions have type "sticker" with sticker attachment details in the sticker field.

This is an alias to an internal type.

type ReplyTo

type ReplyTo struct {
	// The ID of the message to reply to
	MessageID string `json:"message_id" api:"required" format:"uuid"`
	// The specific message part to reply to (0-based index). Defaults to 0 (first
	// part) if not provided. Use this when replying to a specific part of a multipart
	// message.
	PartIndex int64 `json:"part_index"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		MessageID   respjson.Field
		PartIndex   respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Indicates this message is a threaded reply to another message

func (ReplyTo) RawJSON

func (r ReplyTo) RawJSON() string

Returns the unmodified JSON received from the API

func (ReplyTo) ToParam

func (r ReplyTo) ToParam() ReplyToParam

ToParam converts this ReplyTo to a ReplyToParam.

Warning: the fields of the param type will not be present. ToParam should only be used at the last possible moment before sending a request. Test for this with ReplyToParam.Overrides()

func (*ReplyTo) UnmarshalJSON

func (r *ReplyTo) UnmarshalJSON(data []byte) error

type ReplyToParam

type ReplyToParam struct {
	// The ID of the message to reply to
	MessageID string `json:"message_id" api:"required" format:"uuid"`
	// The specific message part to reply to (0-based index). Defaults to 0 (first
	// part) if not provided. Use this when replying to a specific part of a multipart
	// message.
	PartIndex param.Opt[int64] `json:"part_index,omitzero"`
	// contains filtered or unexported fields
}

Indicates this message is a threaded reply to another message

The property MessageID is required.

func (ReplyToParam) MarshalJSON

func (r ReplyToParam) MarshalJSON() (data []byte, err error)

func (*ReplyToParam) UnmarshalJSON

func (r *ReplyToParam) UnmarshalJSON(data []byte) error

type ReputationActionItem added in v0.31.1

type ReputationActionItem struct {
	Detail string `json:"detail"`
	// Any of "high", "medium", "low".
	ExpectedImpact ReputationActionItemExpectedImpact `json:"expected_impact"`
	// 1 = do first
	Priority int64  `json:"priority"`
	Title    string `json:"title"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Detail         respjson.Field
		ExpectedImpact respjson.Field
		Priority       respjson.Field
		Title          respjson.Field
		ExtraFields    map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (ReputationActionItem) RawJSON added in v0.31.1

func (r ReputationActionItem) RawJSON() string

Returns the unmodified JSON received from the API

func (*ReputationActionItem) UnmarshalJSON added in v0.31.1

func (r *ReputationActionItem) UnmarshalJSON(data []byte) error

type ReputationActionItemExpectedImpact added in v0.31.1

type ReputationActionItemExpectedImpact string
const (
	ReputationActionItemExpectedImpactHigh   ReputationActionItemExpectedImpact = "high"
	ReputationActionItemExpectedImpactMedium ReputationActionItemExpectedImpact = "medium"
	ReputationActionItemExpectedImpactLow    ReputationActionItemExpectedImpact = "low"
)

type ReputationAudit added in v0.31.0

type ReputationAudit struct {
	AuditID string `json:"audit_id" api:"required"`
	// `pending` until the report is ready — poll until `complete` or `error`.
	//
	// Any of "pending", "complete", "error".
	Status ReputationAuditStatus `json:"status" api:"required"`
	// Present only when `status` is `error`. Short, generic reason safe to display.
	Error string `json:"error"`
	// When the report was generated; signals reflect the line at this moment.
	GeneratedAt time.Time `json:"generated_at" format:"date-time"`
	// The line audited, E.164.
	Phone string `json:"phone"`
	// Present only when `status` is `complete`.
	Report ReputationReport `json:"report"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		AuditID     respjson.Field
		Status      respjson.Field
		Error       respjson.Field
		GeneratedAt respjson.Field
		Phone       respjson.Field
		Report      respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (ReputationAudit) RawJSON added in v0.31.0

func (r ReputationAudit) RawJSON() string

Returns the unmodified JSON received from the API

func (*ReputationAudit) UnmarshalJSON added in v0.31.0

func (r *ReputationAudit) UnmarshalJSON(data []byte) error

type ReputationAuditStarted added in v0.31.1

type ReputationAuditStarted struct {
	// Identifier for this audit. Poll
	// `GET /v3/phone_numbers/{phoneNumber}/reputation_audit/{auditId}` until `status`
	// is `complete` or `error`.
	AuditID string `json:"audit_id" api:"required"`
	// A newly started audit is `pending`.
	//
	// Any of "pending", "complete", "error".
	Status ReputationAuditStartedStatus `json:"status" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		AuditID     respjson.Field
		Status      respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (ReputationAuditStarted) RawJSON added in v0.31.1

func (r ReputationAuditStarted) RawJSON() string

Returns the unmodified JSON received from the API

func (*ReputationAuditStarted) UnmarshalJSON added in v0.31.1

func (r *ReputationAuditStarted) UnmarshalJSON(data []byte) error

type ReputationAuditStartedStatus added in v0.31.1

type ReputationAuditStartedStatus string

A newly started audit is `pending`.

const (
	ReputationAuditStartedStatusPending  ReputationAuditStartedStatus = "pending"
	ReputationAuditStartedStatusComplete ReputationAuditStartedStatus = "complete"
	ReputationAuditStartedStatusError    ReputationAuditStartedStatus = "error"
)

type ReputationAuditStatus added in v0.31.0

type ReputationAuditStatus string

`pending` until the report is ready — poll until `complete` or `error`.

const (
	ReputationAuditStatusPending  ReputationAuditStatus = "pending"
	ReputationAuditStatusComplete ReputationAuditStatus = "complete"
	ReputationAuditStatusError    ReputationAuditStatus = "error"
)

type ReputationDriver added in v0.31.0

type ReputationDriver struct {
	// Stable driver-category identifier — what is dragging the line, or one of its
	// conversations, down.
	//
	//   - `low_engagement` — The conversation is one-sided: several messages sent, few
	//     or no replies back. Pause or rework outreach where recipients are not
	//     replying, and lead with messages that invite a response. Conversation-level:
	//     it appears on `evidence.unhealthy_chats[].driver_keys`, never in `drivers`.
	//   - `overall_conversation_health` — A large share of the line's active
	//     conversations are trending unhealthy. Fix the unhealthy conversations first —
	//     review their content and timing, and whether recipients are engaging.
	//   - `volume_spike` — The line's daily sending volume jumped far above its own
	//     normal level while few recipients were replying, or exceeded the recommended
	//     daily volume for a single line. Ramp volume gradually instead of spiking,
	//     prioritize people who have already engaged with you, and spread sustained high
	//     volume across additional lines.
	//   - `new_conversation_rate` — The line is starting too many brand-new
	//     conversations in a single day. Spread new conversations out over time instead
	//     of starting many at once.
	//   - `opt_out_handling` — Recipients asked this line to stop. Honor every stop
	//     request immediately: send nothing further to that recipient unless they opt
	//     back in. Every send to them is rejected with `403` (error code `2024`),
	//     including a final courtesy message — to send one telling them they can reply
	//     to resume, set `override_optout: true` on that single request.
	//   - `flagged` — The line is currently restricted and its messages may not be
	//     reaching recipients. Move active traffic to a healthy line now, and let this
	//     one recover before sending more.
	//   - `other` — Fallback for a signal without dedicated partner copy.
	//
	// Any of "low_engagement", "overall_conversation_health", "volume_spike",
	// "new_conversation_rate", "opt_out_handling", "flagged", "other".
	Key ReputationDriverKey `json:"key"`
	// A specific observed figure when available; otherwise a short qualitative note.
	Metric string `json:"metric"`
	// One plain-English sentence.
	Summary string `json:"summary"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Key         respjson.Field
		Metric      respjson.Field
		Summary     respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (ReputationDriver) RawJSON added in v0.31.0

func (r ReputationDriver) RawJSON() string

Returns the unmodified JSON received from the API

func (*ReputationDriver) UnmarshalJSON added in v0.31.0

func (r *ReputationDriver) UnmarshalJSON(data []byte) error

type ReputationDriverKey added in v0.31.0

type ReputationDriverKey string

Stable driver-category identifier — what is dragging the line, or one of its conversations, down.

  • `low_engagement` — The conversation is one-sided: several messages sent, few or no replies back. Pause or rework outreach where recipients are not replying, and lead with messages that invite a response. Conversation-level: it appears on `evidence.unhealthy_chats[].driver_keys`, never in `drivers`.
  • `overall_conversation_health` — A large share of the line's active conversations are trending unhealthy. Fix the unhealthy conversations first — review their content and timing, and whether recipients are engaging.
  • `volume_spike` — The line's daily sending volume jumped far above its own normal level while few recipients were replying, or exceeded the recommended daily volume for a single line. Ramp volume gradually instead of spiking, prioritize people who have already engaged with you, and spread sustained high volume across additional lines.
  • `new_conversation_rate` — The line is starting too many brand-new conversations in a single day. Spread new conversations out over time instead of starting many at once.
  • `opt_out_handling` — Recipients asked this line to stop. Honor every stop request immediately: send nothing further to that recipient unless they opt back in. Every send to them is rejected with `403` (error code `2024`), including a final courtesy message — to send one telling them they can reply to resume, set `override_optout: true` on that single request.
  • `flagged` — The line is currently restricted and its messages may not be reaching recipients. Move active traffic to a healthy line now, and let this one recover before sending more.
  • `other` — Fallback for a signal without dedicated partner copy.
const (
	ReputationDriverKeyLowEngagement             ReputationDriverKey = "low_engagement"
	ReputationDriverKeyOverallConversationHealth ReputationDriverKey = "overall_conversation_health"
	ReputationDriverKeyVolumeSpike               ReputationDriverKey = "volume_spike"
	ReputationDriverKeyNewConversationRate       ReputationDriverKey = "new_conversation_rate"
	ReputationDriverKeyOptOutHandling            ReputationDriverKey = "opt_out_handling"
	ReputationDriverKeyFlagged                   ReputationDriverKey = "flagged"
	ReputationDriverKeyOther                     ReputationDriverKey = "other"
)

type ReputationEvidence added in v0.31.0

type ReputationEvidence struct {
	// Worst first — most messages sent after the stop request; honor these
	// immediately.
	OptOutChats []ReputationOptOutChat `json:"opt_out_chats"`
	// Up to 15, worst first.
	UnhealthyChats []ReputationUnhealthyChat `json:"unhealthy_chats"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		OptOutChats    respjson.Field
		UnhealthyChats respjson.Field
		ExtraFields    map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

The specific conversations behind the drivers, so partners can verify every claim against their own send logs. Each `chat_id` can be fetched via `GET /v3/chats/{chatId}` — its current health appears there.

func (ReputationEvidence) RawJSON added in v0.31.0

func (r ReputationEvidence) RawJSON() string

Returns the unmodified JSON received from the API

func (*ReputationEvidence) UnmarshalJSON added in v0.31.0

func (r *ReputationEvidence) UnmarshalJSON(data []byte) error

type ReputationOptOutChat added in v0.31.1

type ReputationOptOutChat struct {
	ChatID string `json:"chat_id"`
	// Outbound messages sent after the recipient asked to stop.
	MessagesAfterStop int64 `json:"messages_after_stop"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ChatID            respjson.Field
		MessagesAfterStop respjson.Field
		ExtraFields       map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (ReputationOptOutChat) RawJSON added in v0.31.1

func (r ReputationOptOutChat) RawJSON() string

Returns the unmodified JSON received from the API

func (*ReputationOptOutChat) UnmarshalJSON added in v0.31.1

func (r *ReputationOptOutChat) UnmarshalJSON(data []byte) error

type ReputationReport added in v0.31.0

type ReputationReport struct {
	// Ordered by `priority`; 1 = do first.
	ActionItems []ReputationActionItem `json:"action_items"`
	// Ranked, highest impact first.
	Drivers []ReputationDriver `json:"drivers"`
	// The specific conversations behind the drivers, so partners can verify every
	// claim against their own send logs. Each `chat_id` can be fetched via
	// `GET /v3/chats/{chatId}` — its current health appears there.
	Evidence ReputationEvidence `json:"evidence"`
	// The `key` of the most important driver. Empty string when the line has nothing
	// to act on — the report then carries a single reassurance action item. Its values
	// are the `ReputationDriverKey` vocabulary — see that schema for what each means
	// and what to do about it.
	PrimaryDriver string `json:"primary_driver"`
	// Current reputation of this phone line.
	//
	//   - `HEALTHY` — The line is in good standing. Send normally.
	//   - `AT_RISK` — Warning signs on the line: engagement is low across many of its
	//     conversations, or it's starting too many brand-new conversations in a single
	//     day — and a spike in send volume can add to either. Slow the line's send pace,
	//     avoid opening many new conversations at once, and review your messaging
	//     patterns.
	//   - `CRITICAL` — Strong signals that messages from this line aren't landing well.
	//     Pause outbound on the line until it recovers.
	//
	// Defaults to `HEALTHY` for lines that have not yet been scored.
	//
	// Any of "HEALTHY", "AT_RISK", "CRITICAL".
	Severity ReputationReportSeverity `json:"severity"`
	// Deterministic markdown rendering of this report, suitable for feeding directly
	// to automated systems and AI agents as investigation context. Rendered from the
	// structured fields above, which remain the source of truth.
	SummaryMarkdown string `json:"summary_markdown"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ActionItems     respjson.Field
		Drivers         respjson.Field
		Evidence        respjson.Field
		PrimaryDriver   respjson.Field
		Severity        respjson.Field
		SummaryMarkdown respjson.Field
		ExtraFields     map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (ReputationReport) RawJSON added in v0.31.0

func (r ReputationReport) RawJSON() string

Returns the unmodified JSON received from the API

func (*ReputationReport) UnmarshalJSON added in v0.31.0

func (r *ReputationReport) UnmarshalJSON(data []byte) error

type ReputationReportSeverity added in v0.31.0

type ReputationReportSeverity string

Current reputation of this phone line.

  • `HEALTHY` — The line is in good standing. Send normally.
  • `AT_RISK` — Warning signs on the line: engagement is low across many of its conversations, or it's starting too many brand-new conversations in a single day — and a spike in send volume can add to either. Slow the line's send pace, avoid opening many new conversations at once, and review your messaging patterns.
  • `CRITICAL` — Strong signals that messages from this line aren't landing well. Pause outbound on the line until it recovers.

Defaults to `HEALTHY` for lines that have not yet been scored.

const (
	ReputationReportSeverityHealthy  ReputationReportSeverity = "HEALTHY"
	ReputationReportSeverityAtRisk   ReputationReportSeverity = "AT_RISK"
	ReputationReportSeverityCritical ReputationReportSeverity = "CRITICAL"
)

type ReputationUnhealthyChat added in v0.31.1

type ReputationUnhealthyChat struct {
	ChatID string `json:"chat_id"`
	// What is dragging this conversation down, in the same vocabulary as the report's
	// drivers. Each key's meaning and the fix for it are documented on
	// `ReputationDriverKey`.
	DriverKeys []ReputationDriverKey `json:"driver_keys"`
	// The conversation's current health — the same value `GET /v3/chats/{chatId}`
	// reports for it.
	//
	// Any of "AT_RISK", "CRITICAL", "OPTED_OUT".
	Status ReputationUnhealthyChatStatus `json:"status"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ChatID      respjson.Field
		DriverKeys  respjson.Field
		Status      respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (ReputationUnhealthyChat) RawJSON added in v0.31.1

func (r ReputationUnhealthyChat) RawJSON() string

Returns the unmodified JSON received from the API

func (*ReputationUnhealthyChat) UnmarshalJSON added in v0.31.1

func (r *ReputationUnhealthyChat) UnmarshalJSON(data []byte) error

type ReputationUnhealthyChatStatus added in v0.31.1

type ReputationUnhealthyChatStatus string

The conversation's current health — the same value `GET /v3/chats/{chatId}` reports for it.

const (
	ReputationUnhealthyChatStatusAtRisk   ReputationUnhealthyChatStatus = "AT_RISK"
	ReputationUnhealthyChatStatusCritical ReputationUnhealthyChatStatus = "CRITICAL"
	ReputationUnhealthyChatStatusOptedOut ReputationUnhealthyChatStatus = "OPTED_OUT"
)

type SchemasMediaPartResponse added in v0.2.0

type SchemasMediaPartResponse struct {
	// Unique attachment identifier
	ID string `json:"id" api:"required" format:"uuid"`
	// Original filename
	Filename string `json:"filename" api:"required"`
	// MIME type of the file
	MimeType string `json:"mime_type" api:"required"`
	// File size in bytes
	SizeBytes int64 `json:"size_bytes" api:"required"`
	// Indicates this is a media attachment part
	//
	// Any of "media".
	Type SchemasMediaPartResponseType `json:"type" api:"required"`
	// Presigned URL for downloading the attachment (expires in 1 hour).
	URL string `json:"url" api:"required" format:"uri"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ID          respjson.Field
		Filename    respjson.Field
		MimeType    respjson.Field
		SizeBytes   respjson.Field
		Type        respjson.Field
		URL         respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

A media attachment part

func (SchemasMediaPartResponse) RawJSON added in v0.2.0

func (r SchemasMediaPartResponse) RawJSON() string

Returns the unmodified JSON received from the API

func (*SchemasMediaPartResponse) UnmarshalJSON added in v0.2.0

func (r *SchemasMediaPartResponse) UnmarshalJSON(data []byte) error

type SchemasMediaPartResponseType added in v0.2.0

type SchemasMediaPartResponseType string

Indicates this is a media attachment part

const (
	SchemasMediaPartResponseTypeMedia SchemasMediaPartResponseType = "media"
)

type SchemasMessageEffect added in v0.2.0

type SchemasMessageEffect struct {
	// Effect name (confetti, fireworks, slam, gentle, etc.)
	Name string `json:"name"`
	// Effect category
	//
	// Any of "screen", "bubble".
	Type SchemasMessageEffectType `json:"type"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Name        respjson.Field
		Type        respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

iMessage effect applied to a message (screen or bubble animation)

func (SchemasMessageEffect) RawJSON added in v0.2.0

func (r SchemasMessageEffect) RawJSON() string

Returns the unmodified JSON received from the API

func (*SchemasMessageEffect) UnmarshalJSON added in v0.2.0

func (r *SchemasMessageEffect) UnmarshalJSON(data []byte) error

type SchemasMessageEffectType added in v0.2.0

type SchemasMessageEffectType string

Effect category

const (
	SchemasMessageEffectTypeScreen SchemasMessageEffectType = "screen"
	SchemasMessageEffectTypeBubble SchemasMessageEffectType = "bubble"
)

type SchemasTextPartResponse added in v0.2.0

type SchemasTextPartResponse struct {
	// Indicates this is a text message part
	//
	// Any of "text".
	Type SchemasTextPartResponseType `json:"type" api:"required"`
	// The text content
	Value string `json:"value" api:"required"`
	// DEPRECATED: Use `mentions` instead. Handle (E.164 phone number or Apple ID
	// email) of the **first** mention on this part. A part may carry several mentions;
	// this field shows only the first in `value` order, so it cannot be used to
	// determine whether a given participant was mentioned. `null` when the part
	// carries no mention.
	//
	// Deprecated: deprecated
	Mention string `json:"mention" api:"nullable"`
	// DEPRECATED: Use `mentions[].range` instead. Character range `[start, end)` in
	// `value` highlighted as the **first** mention only. `null` when the range was
	// omitted (the whole `value` is highlighted) or the part carries no mention.
	// _Characters are measured as UTF-16 code units. Most characters count as 1; some
	// emoji count as 2._
	//
	// Deprecated: deprecated
	MentionRange []int64 `json:"mention_range" api:"nullable"`
	// Every mention on this part, in the order they appear in `value`. `null` when the
	// part carries no mention. A part can carry several mentions of different people —
	// check `is_me` to tell whether this line was one of them.
	//
	// Only iMessage carries mentions. On a received message this is populated when the
	// sender was on iMessage; SMS and RCS have no way to mark a mention, so a message
	// from an SMS or RCS participant arrives as plain text with `mentions` null, even
	// in a group where other participants are on iMessage.
	Mentions []SchemasTextPartResponseMention `json:"mentions" api:"nullable"`
	// Text decorations applied to character ranges in the value
	TextDecorations []shared.TextDecoration `json:"text_decorations" api:"nullable"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Type            respjson.Field
		Value           respjson.Field
		Mention         respjson.Field
		MentionRange    respjson.Field
		Mentions        respjson.Field
		TextDecorations respjson.Field
		ExtraFields     map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

A text message part

func (SchemasTextPartResponse) RawJSON added in v0.2.0

func (r SchemasTextPartResponse) RawJSON() string

Returns the unmodified JSON received from the API

func (*SchemasTextPartResponse) UnmarshalJSON added in v0.2.0

func (r *SchemasTextPartResponse) UnmarshalJSON(data []byte) error

type SchemasTextPartResponseMention added in v0.43.0

type SchemasTextPartResponseMention struct {
	// Address of the mentioned participant, exactly as the device recorded it — an
	// E.164 phone number or an email address.
	Handle string `json:"handle" api:"required"`
	// Whether the mentioned participant is this line.
	IsMe bool `json:"is_me" api:"required"`
	// Character range `[start, end)` in `value` highlighted as this mention.
	// _Characters are measured as UTF-16 code units. Most characters count as 1; some
	// emoji count as 2._
	Range []int64 `json:"range" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Handle      respjson.Field
		IsMe        respjson.Field
		Range       respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

One mention on a text part — who was mentioned, and which characters of `value` are the mention. A part carries one of these per mention, in the order they appear in the text, so a message naming two people has two entries.

func (SchemasTextPartResponseMention) RawJSON added in v0.43.0

Returns the unmodified JSON received from the API

func (*SchemasTextPartResponseMention) UnmarshalJSON added in v0.43.0

func (r *SchemasTextPartResponseMention) UnmarshalJSON(data []byte) error

type SchemasTextPartResponseType added in v0.2.0

type SchemasTextPartResponseType string

Indicates this is a text message part

const (
	SchemasTextPartResponseTypeText SchemasTextPartResponseType = "text"
)

type SentMessage

type SentMessage struct {
	// Message identifier (UUID)
	ID string `json:"id" api:"required" format:"uuid"`
	// When the message was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// Current delivery status of a message
	//
	// Any of "pending", "queued", "sent", "delivered", "received", "read", "failed".
	DeliveryStatus SentMessageDeliveryStatus `json:"delivery_status" api:"required"`
	// DEPRECATED: Use `delivery_status == "read"` instead. Whether the message has
	// been read.
	//
	// Deprecated: deprecated
	IsRead bool `json:"is_read" api:"required"`
	// Message parts in order (text, media, and link)
	Parts []SentMessagePartUnion `json:"parts" api:"required"`
	// When the message was actually sent (null if still queued)
	SentAt time.Time `json:"sent_at" api:"required" format:"date-time"`
	// When the message was delivered
	DeliveredAt time.Time `json:"delivered_at" api:"nullable" format:"date-time"`
	// iMessage effect applied to a message (screen or bubble effect)
	Effect MessageEffect `json:"effect" api:"nullable"`
	// The sender of this message as a full handle object
	FromHandle shared.ChatHandle `json:"from_handle" api:"nullable"`
	// Messaging service type
	//
	// Any of "iMessage", "SMS", "RCS".
	PreferredService shared.ServiceType `json:"preferred_service" api:"nullable"`
	// Indicates this message is a threaded reply to another message
	ReplyTo ReplyTo `json:"reply_to" api:"nullable"`
	// Messaging service type
	//
	// Any of "iMessage", "SMS", "RCS".
	Service shared.ServiceType `json:"service" api:"nullable"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ID               respjson.Field
		CreatedAt        respjson.Field
		DeliveryStatus   respjson.Field
		IsRead           respjson.Field
		Parts            respjson.Field
		SentAt           respjson.Field
		DeliveredAt      respjson.Field
		Effect           respjson.Field
		FromHandle       respjson.Field
		PreferredService respjson.Field
		ReplyTo          respjson.Field
		Service          respjson.Field
		ExtraFields      map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

A message that was sent (used in CreateChat and SendMessage responses)

func (SentMessage) RawJSON

func (r SentMessage) RawJSON() string

Returns the unmodified JSON received from the API

func (*SentMessage) UnmarshalJSON

func (r *SentMessage) UnmarshalJSON(data []byte) error

type SentMessageDeliveryStatus

type SentMessageDeliveryStatus string

Current delivery status of a message

const (
	SentMessageDeliveryStatusPending   SentMessageDeliveryStatus = "pending"
	SentMessageDeliveryStatusQueued    SentMessageDeliveryStatus = "queued"
	SentMessageDeliveryStatusSent      SentMessageDeliveryStatus = "sent"
	SentMessageDeliveryStatusDelivered SentMessageDeliveryStatus = "delivered"
	SentMessageDeliveryStatusReceived  SentMessageDeliveryStatus = "received"
	SentMessageDeliveryStatusRead      SentMessageDeliveryStatus = "read"
	SentMessageDeliveryStatusFailed    SentMessageDeliveryStatus = "failed"
)

type SentMessagePartAppClipPartResponse added in v0.36.0

type SentMessagePartAppClipPartResponse struct {
	// Reactions on this message part
	Reactions []shared.Reaction `json:"reactions" api:"required"`
	// Indicates this is an App Clip card part
	//
	// Any of "app_clip".
	Type string `json:"type" api:"required"`
	// The App Clip link the card opens
	Value string `json:"value" api:"required"`
	// The card's summary line, composed by Linq from the App Clip page
	Description string `json:"description"`
	// The card's preview image
	ImageURL string `json:"image_url"`
	// The card's headline, composed by Linq from the App Clip page
	Title string `json:"title"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Reactions   respjson.Field
		Type        respjson.Field
		Value       respjson.Field
		Description respjson.Field
		ImageURL    respjson.Field
		Title       respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

An App Clip card part

func (SentMessagePartAppClipPartResponse) RawJSON added in v0.36.0

Returns the unmodified JSON received from the API

func (*SentMessagePartAppClipPartResponse) UnmarshalJSON added in v0.36.0

func (r *SentMessagePartAppClipPartResponse) UnmarshalJSON(data []byte) error

type SentMessagePartIMessageAppPartResponse added in v0.25.0

type SentMessagePartIMessageAppPartResponse struct {
	// Identifies the iMessage app (Messages app extension) that backs the card.
	App SentMessagePartIMessageAppPartResponseApp `json:"app" api:"required"`
	// Visible layout of the card. At least one of `caption`, `subcaption`,
	// `trailing_caption`, `trailing_subcaption`, or `image_url` must be set, otherwise
	// the card renders as an empty bubble.
	//
	// `image_url` displays a preview image at the top of the card. The image renders
	// on the recipient's card whether or not they have your app installed. The small
	// icon beside the caption is the app's own icon and is not settable here.
	//
	// `* Note - requires a trusted chat w/ inbound activity`
	//
	// `image_title` and `image_subtitle` render as text overlaid on the image (title
	// bold, subtitle beneath it). They only appear when `image_url` is set — without
	// an image there is nothing to overlay — so setting either without `image_url` is
	// rejected.
	Layout SentMessagePartIMessageAppPartResponseLayout `json:"layout" api:"required"`
	// Reactions on this message part
	Reactions []shared.Reaction `json:"reactions" api:"required"`
	// Indicates this is an iMessage app card part.
	//
	// Any of "imessage_app".
	Type string `json:"type" api:"required"`
	// The URL delivered to the iMessage app on tap.
	URL string `json:"url" api:"required" format:"uri"`
	// Fallback text for surfaces that cannot render the card.
	FallbackText string `json:"fallback_text" api:"nullable"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		App          respjson.Field
		Layout       respjson.Field
		Reactions    respjson.Field
		Type         respjson.Field
		URL          respjson.Field
		FallbackText respjson.Field
		ExtraFields  map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

An iMessage app card part.

func (SentMessagePartIMessageAppPartResponse) RawJSON added in v0.25.0

Returns the unmodified JSON received from the API

func (*SentMessagePartIMessageAppPartResponse) UnmarshalJSON added in v0.25.0

func (r *SentMessagePartIMessageAppPartResponse) UnmarshalJSON(data []byte) error

type SentMessagePartIMessageAppPartResponseApp added in v0.25.0

type SentMessagePartIMessageAppPartResponseApp struct {
	// Bundle identifier of the Messages app extension. Must not contain `:`.
	BundleID string `json:"bundle_id" api:"required"`
	// Display name of the app, shown by Messages' fallback UI.
	Name string `json:"name" api:"required"`
	// The app's 10-character uppercase alphanumeric team identifier.
	TeamID string `json:"team_id" api:"required"`
	// The owning app's App Store id (optional). When set, recipients without the
	// iMessage app installed see a "Get the app" affordance.
	AppStoreID int64 `json:"app_store_id"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		BundleID    respjson.Field
		Name        respjson.Field
		TeamID      respjson.Field
		AppStoreID  respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Identifies the iMessage app (Messages app extension) that backs the card.

func (SentMessagePartIMessageAppPartResponseApp) RawJSON added in v0.25.0

Returns the unmodified JSON received from the API

func (*SentMessagePartIMessageAppPartResponseApp) UnmarshalJSON added in v0.25.0

func (r *SentMessagePartIMessageAppPartResponseApp) UnmarshalJSON(data []byte) error

type SentMessagePartIMessageAppPartResponseLayout added in v0.25.0

type SentMessagePartIMessageAppPartResponseLayout struct {
	// Primary label, top-left and bold.
	Caption string `json:"caption"`
	// Text shown below `image_title`, overlaid on the card image. Requires
	// `image_url`.
	ImageSubtitle string `json:"image_subtitle"`
	// Bold text overlaid on the card image. Requires `image_url` (rejected without
	// it).
	ImageTitle string `json:"image_title"`
	// URL of an image (JPEG, PNG, HEIF, or WebP) to display as the card's preview
	// image; an unreachable or non-image URL returns a validation error. Renders for
	// all recipients regardless of whether they have the app. Note - requires a
	// trusted chat w/ inbound activity. In responses, this is the re-hosted
	// `cdn.linqapp.com` copy of the image you supplied, not your original URL.
	ImageURL string `json:"image_url" format:"uri"`
	// Secondary label, below `caption` on the left.
	Subcaption string `json:"subcaption"`
	// Label shown top-right.
	TrailingCaption string `json:"trailing_caption"`
	// Label shown below `trailing_caption`, on the right.
	TrailingSubcaption string `json:"trailing_subcaption"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Caption            respjson.Field
		ImageSubtitle      respjson.Field
		ImageTitle         respjson.Field
		ImageURL           respjson.Field
		Subcaption         respjson.Field
		TrailingCaption    respjson.Field
		TrailingSubcaption respjson.Field
		ExtraFields        map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Visible layout of the card. At least one of `caption`, `subcaption`, `trailing_caption`, `trailing_subcaption`, or `image_url` must be set, otherwise the card renders as an empty bubble.

`image_url` displays a preview image at the top of the card. The image renders on the recipient's card whether or not they have your app installed. The small icon beside the caption is the app's own icon and is not settable here.

`* Note - requires a trusted chat w/ inbound activity`

`image_title` and `image_subtitle` render as text overlaid on the image (title bold, subtitle beneath it). They only appear when `image_url` is set — without an image there is nothing to overlay — so setting either without `image_url` is rejected.

func (SentMessagePartIMessageAppPartResponseLayout) RawJSON added in v0.25.0

Returns the unmodified JSON received from the API

func (*SentMessagePartIMessageAppPartResponseLayout) UnmarshalJSON added in v0.25.0

func (r *SentMessagePartIMessageAppPartResponseLayout) UnmarshalJSON(data []byte) error

type SentMessagePartUnion

type SentMessagePartUnion struct {
	Reactions []shared.Reaction `json:"reactions"`
	Type      string            `json:"type"`
	Value     string            `json:"value"`
	// This field is from variant [shared.TextPartResponse].
	Mention string `json:"mention"`
	// This field is from variant [shared.TextPartResponse].
	MentionRange []int64 `json:"mention_range"`
	// This field is from variant [shared.TextPartResponse].
	Mentions []shared.TextPartResponseMention `json:"mentions"`
	// This field is from variant [shared.TextPartResponse].
	TextDecorations []shared.TextDecoration `json:"text_decorations"`
	// This field is from variant [shared.MediaPartResponse].
	ID string `json:"id"`
	// This field is from variant [shared.MediaPartResponse].
	Filename string `json:"filename"`
	// This field is from variant [shared.MediaPartResponse].
	MimeType string `json:"mime_type"`
	// This field is from variant [shared.MediaPartResponse].
	SizeBytes int64  `json:"size_bytes"`
	URL       string `json:"url"`
	// This field is from variant [SentMessagePartIMessageAppPartResponse].
	App SentMessagePartIMessageAppPartResponseApp `json:"app"`
	// This field is from variant [SentMessagePartIMessageAppPartResponse].
	Layout SentMessagePartIMessageAppPartResponseLayout `json:"layout"`
	// This field is from variant [SentMessagePartIMessageAppPartResponse].
	FallbackText string `json:"fallback_text"`
	// This field is from variant [SentMessagePartAppClipPartResponse].
	Description string `json:"description"`
	// This field is from variant [SentMessagePartAppClipPartResponse].
	ImageURL string `json:"image_url"`
	// This field is from variant [SentMessagePartAppClipPartResponse].
	Title string `json:"title"`
	JSON  struct {
		Reactions       respjson.Field
		Type            respjson.Field
		Value           respjson.Field
		Mention         respjson.Field
		MentionRange    respjson.Field
		Mentions        respjson.Field
		TextDecorations respjson.Field
		ID              respjson.Field
		Filename        respjson.Field
		MimeType        respjson.Field
		SizeBytes       respjson.Field
		URL             respjson.Field
		App             respjson.Field
		Layout          respjson.Field
		FallbackText    respjson.Field
		Description     respjson.Field
		ImageURL        respjson.Field
		Title           respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

SentMessagePartUnion contains all possible properties and values from shared.TextPartResponse, shared.MediaPartResponse, shared.LinkPartResponse, SentMessagePartIMessageAppPartResponse, SentMessagePartAppClipPartResponse.

Use the methods beginning with 'As' to cast the union to one of its variants.

func (SentMessagePartUnion) AsLinkPartResponse added in v0.13.0

func (u SentMessagePartUnion) AsLinkPartResponse() (v shared.LinkPartResponse)

func (SentMessagePartUnion) AsMediaPartResponse added in v0.2.0

func (u SentMessagePartUnion) AsMediaPartResponse() (v shared.MediaPartResponse)

func (SentMessagePartUnion) AsSentMessagePartAppClipPartResponse added in v0.36.0

func (u SentMessagePartUnion) AsSentMessagePartAppClipPartResponse() (v SentMessagePartAppClipPartResponse)

func (SentMessagePartUnion) AsSentMessagePartIMessageAppPartResponse added in v0.25.0

func (u SentMessagePartUnion) AsSentMessagePartIMessageAppPartResponse() (v SentMessagePartIMessageAppPartResponse)

func (SentMessagePartUnion) AsTextPartResponse added in v0.2.0

func (u SentMessagePartUnion) AsTextPartResponse() (v shared.TextPartResponse)

func (SentMessagePartUnion) RawJSON

func (u SentMessagePartUnion) RawJSON() string

Returns the unmodified JSON received from the API

func (*SentMessagePartUnion) UnmarshalJSON

func (r *SentMessagePartUnion) UnmarshalJSON(data []byte) error

type ServiceType

type ServiceType = shared.ServiceType

Messaging service type

This is an alias to an internal type.

type SetContactCard added in v0.8.0

type SetContactCard struct {
	// First name on the contact card
	FirstName string `json:"first_name" api:"required"`
	// Whether the contact card was successfully applied to the device
	IsActive bool `json:"is_active" api:"required"`
	// The phone number the contact card is associated with
	PhoneNumber string `json:"phone_number" api:"required"`
	// Image URL on the contact card
	ImageURL string `json:"image_url"`
	// Last name on the contact card
	LastName string `json:"last_name"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		FirstName   respjson.Field
		IsActive    respjson.Field
		PhoneNumber respjson.Field
		ImageURL    respjson.Field
		LastName    respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (SetContactCard) RawJSON added in v0.8.0

func (r SetContactCard) RawJSON() string

Returns the unmodified JSON received from the API

func (*SetContactCard) UnmarshalJSON added in v0.8.0

func (r *SetContactCard) UnmarshalJSON(data []byte) error

type SupportedContentType

type SupportedContentType string

Supported MIME types for file attachments and media URLs.

**Images:** image/jpeg, image/png, image/gif, image/heic, image/heif, image/tiff, image/bmp, image/svg+xml, image/webp, image/x-icon

**Videos:** video/mp4, video/quicktime, video/mpeg, video/mpeg2, video/x-msvideo, video/3gpp

**Audio:** audio/mpeg, audio/x-m4a, audio/x-caf, audio/x-wav, audio/x-aiff, audio/aac, audio/midi, audio/amr

**Wallet passes:** application/vnd.apple.pkpass

**Documents:** application/pdf, text/plain, text/markdown, text/vcard, text/rtf, text/csv, text/html, text/calendar, text/xml, application/json, application/msword, application/vnd.openxmlformats-officedocument.wordprocessingml.document, application/vnd.ms-excel, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-powerpoint, application/vnd.openxmlformats-officedocument.presentationml.presentation, application/x-iwork-pages-sffpages, application/x-iwork-numbers-sffnumbers, application/x-iwork-keynote-sffkey, application/epub+zip, application/zip, application/x-gzip

**Transcoded on delivery:**

- `audio/x-caf` — CAF files are transcoded to `audio/mp4` for delivery.

**Deprecated (accepted but transcoded):**

  • `audio/mp3` — Deprecated. Use `audio/mpeg` instead. Files sent as audio/mp3 will be delivered as audio/mpeg.
  • `audio/mp4` — Deprecated. Use `audio/x-m4a` instead. Files sent as audio/mp4 will be delivered as audio/x-m4a.
  • `audio/aiff` — Deprecated. Use `audio/x-aiff` instead. Files sent as audio/aiff will be delivered as audio/x-aiff.
  • `image/tiff` — Accepted, but TIFF images are transcoded to JPEG for delivery.

**Unsupported:** FLAC, OGG, and executable files are explicitly rejected.

const (
	SupportedContentTypeImageJpeg                                                            SupportedContentType = "image/jpeg"
	SupportedContentTypeImagePng                                                             SupportedContentType = "image/png"
	SupportedContentTypeImageGif                                                             SupportedContentType = "image/gif"
	SupportedContentTypeImageHeic                                                            SupportedContentType = "image/heic"
	SupportedContentTypeImageHeif                                                            SupportedContentType = "image/heif"
	SupportedContentTypeImageTiff                                                            SupportedContentType = "image/tiff"
	SupportedContentTypeImageBmp                                                             SupportedContentType = "image/bmp"
	SupportedContentTypeImageSvgXml                                                          SupportedContentType = "image/svg+xml"
	SupportedContentTypeImageWebp                                                            SupportedContentType = "image/webp"
	SupportedContentTypeImageXIcon                                                           SupportedContentType = "image/x-icon"
	SupportedContentTypeVideoMP4                                                             SupportedContentType = "video/mp4"
	SupportedContentTypeVideoQuicktime                                                       SupportedContentType = "video/quicktime"
	SupportedContentTypeVideoMpeg                                                            SupportedContentType = "video/mpeg"
	SupportedContentTypeVideoMpeg2                                                           SupportedContentType = "video/mpeg2"
	SupportedContentTypeVideoXM4v                                                            SupportedContentType = "video/x-m4v"
	SupportedContentTypeVideoXMsvideo                                                        SupportedContentType = "video/x-msvideo"
	SupportedContentTypeVideo3gpp                                                            SupportedContentType = "video/3gpp"
	SupportedContentTypeAudioMpeg                                                            SupportedContentType = "audio/mpeg"
	SupportedContentTypeAudioMP3                                                             SupportedContentType = "audio/mp3"
	SupportedContentTypeAudioXM4a                                                            SupportedContentType = "audio/x-m4a"
	SupportedContentTypeAudioMP4                                                             SupportedContentType = "audio/mp4"
	SupportedContentTypeAudioXCaf                                                            SupportedContentType = "audio/x-caf"
	SupportedContentTypeAudioXWav                                                            SupportedContentType = "audio/x-wav"
	SupportedContentTypeAudioXAiff                                                           SupportedContentType = "audio/x-aiff"
	SupportedContentTypeAudioAiff                                                            SupportedContentType = "audio/aiff"
	SupportedContentTypeAudioAac                                                             SupportedContentType = "audio/aac"
	SupportedContentTypeAudioMidi                                                            SupportedContentType = "audio/midi"
	SupportedContentTypeAudioAmr                                                             SupportedContentType = "audio/amr"
	SupportedContentTypeApplicationPdf                                                       SupportedContentType = "application/pdf"
	SupportedContentTypeApplicationVndApplePkpass                                            SupportedContentType = "application/vnd.apple.pkpass"
	SupportedContentTypeTextPlain                                                            SupportedContentType = "text/plain"
	SupportedContentTypeTextMarkdown                                                         SupportedContentType = "text/markdown"
	SupportedContentTypeTextVcard                                                            SupportedContentType = "text/vcard"
	SupportedContentTypeTextRtf                                                              SupportedContentType = "text/rtf"
	SupportedContentTypeTextCsv                                                              SupportedContentType = "text/csv"
	SupportedContentTypeTextHTML                                                             SupportedContentType = "text/html"
	SupportedContentTypeTextCalendar                                                         SupportedContentType = "text/calendar"
	SupportedContentTypeApplicationMsword                                                    SupportedContentType = "application/msword"
	SupportedContentTypeApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlDocument   SupportedContentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
	SupportedContentTypeApplicationVndMsExcel                                                SupportedContentType = "application/vnd.ms-excel"
	SupportedContentTypeApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlSheet         SupportedContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
	SupportedContentTypeApplicationVndMsPowerpoint                                           SupportedContentType = "application/vnd.ms-powerpoint"
	SupportedContentTypeApplicationVndOpenxmlformatsOfficedocumentPresentationmlPresentation SupportedContentType = "application/vnd.openxmlformats-officedocument.presentationml.presentation"
	SupportedContentTypeApplicationXIworkPagesSffpages                                       SupportedContentType = "application/x-iwork-pages-sffpages"
	SupportedContentTypeApplicationXIworkNumbersSffnumbers                                   SupportedContentType = "application/x-iwork-numbers-sffnumbers"
	SupportedContentTypeApplicationXIworkKeynoteSffkey                                       SupportedContentType = "application/x-iwork-keynote-sffkey"
	SupportedContentTypeApplicationEpubZip                                                   SupportedContentType = "application/epub+zip"
	SupportedContentTypeTextXml                                                              SupportedContentType = "text/xml"
	SupportedContentTypeApplicationJson                                                      SupportedContentType = "application/json"
	SupportedContentTypeApplicationZip                                                       SupportedContentType = "application/zip"
	SupportedContentTypeApplicationXGzip                                                     SupportedContentType = "application/x-gzip"
)

type TextDecoration added in v0.8.0

type TextDecoration = shared.TextDecoration

This is an alias to an internal type.

type TextDecorationAnimation added in v0.8.0

type TextDecorationAnimation = shared.TextDecorationAnimation

Animated text effect to apply. Mutually exclusive with `style`.

This is an alias to an internal type.

type TextDecorationParam added in v0.8.0

type TextDecorationParam = shared.TextDecorationParam

This is an alias to an internal type.

type TextDecorationStyle added in v0.8.0

type TextDecorationStyle = shared.TextDecorationStyle

Text style to apply. Mutually exclusive with `animation`.

This is an alias to an internal type.

type TextPartParam added in v0.2.0

type TextPartParam struct {
	// Indicates this is a text message part
	//
	// Any of "text".
	Type TextPartType `json:"type,omitzero" api:"required"`
	// The text content of the message. This value is sent as-is with no parsing or
	// transformation — Markdown syntax will be delivered as plain text. Use
	// `text_decorations` to apply inline formatting and animations (iMessage only).
	Value string `json:"value" api:"required"`
	// Mention a chat participant. Group chats only — sending a mention to a direct
	// chat is rejected with `409` / `2023`. The chat's service is not a constraint: a
	// mention is accepted in any group, including one with SMS/RCS participants.
	//
	// Set to their handle — E.164 phone number or Apple ID email. `value` is the
	// display text; use the bare name (`"Juan"`, not `"@Juan"`). By default the entire
	// `value` renders as the mention; use `mention_range` to highlight only part of
	// it.
	//
	// Rendering is per recipient, not per message. iMessage recipients see the mention
	// highlighted and are notified even if they have muted the chat. SMS and RCS
	// recipients receive the same message as plain text — no highlight, and no mute
	// override. One send, two experiences.
	Mention param.Opt[string] `json:"mention,omitzero"`
	// Optional character range `[start, end)` in `value` that renders as the `mention`
	// highlight (e.g. just the name in `"Hey Kevin, can you look at this?"`). Requires
	// `mention`. Without it, the entire `value` is highlighted. `start` is inclusive,
	// `end` is exclusive. _Characters are measured as UTF-16 code units. Most
	// characters count as 1; some emoji count as 2._
	//
	// Applies to iMessage recipients only, matching `mention` — SMS and RCS recipients
	// receive the text with no highlight.
	MentionRange []int64 `json:"mention_range,omitzero"`
	// Optional array of text decorations applied to character ranges in the `value`
	// field (iMessage only).
	//
	// Each decoration specifies a character range `[start, end)` and exactly one of
	// `style` or `animation`.
	//
	// **Styles:** `bold`, `italic`, `strikethrough`, `underline` **Animations:**
	// `big`, `small`, `shake`, `nod`, `explode`, `ripple`, `bloom`, `jitter`
	//
	// Style ranges may overlap (e.g. bold + italic on the same text), but animation
	// ranges must not overlap with other animations or styles.
	//
	// _Characters are measured as UTF-16 code units. Most characters count as 1; some
	// emoji count as 2._
	//
	// **Note:** decorations render per recipient, not per message. In a group
	// containing both iMessage and SMS/RCS participants, iMessage recipients see the
	// decorations and SMS/RCS recipients receive the same message as plain text.
	TextDecorations []shared.TextDecorationParam `json:"text_decorations,omitzero"`
	// contains filtered or unexported fields
}

The properties Type, Value are required.

func (TextPartParam) MarshalJSON added in v0.2.0

func (r TextPartParam) MarshalJSON() (data []byte, err error)

func (*TextPartParam) UnmarshalJSON added in v0.2.0

func (r *TextPartParam) UnmarshalJSON(data []byte) error

type TextPartResponse added in v0.2.0

type TextPartResponse = shared.TextPartResponse

A text message part

This is an alias to an internal type.

type TextPartResponseMention added in v0.43.0

type TextPartResponseMention = shared.TextPartResponseMention

One mention on a text part — who was mentioned, and which characters of `value` are the mention. A part carries one of these per mention, in the order they appear in the text, so a message naming two people has two entries.

This is an alias to an internal type.

type TextPartResponseType added in v0.2.0

type TextPartResponseType = shared.TextPartResponseType

Indicates this is a text message part

This is an alias to an internal type.

type TextPartType

type TextPartType string

Indicates this is a text message part

const (
	TextPartTypeText TextPartType = "text"
)

type UnwrapWebhookEventUnion added in v0.24.0

type UnwrapWebhookEventUnion struct {
	APIVersion string    `json:"api_version"`
	CreatedAt  time.Time `json:"created_at"`
	// This field is a union of [MessageEventV2], [MessageFailedWebhookEventData],
	// [MessageEditedWebhookEventData], [ReactionEventBase],
	// [PollReceivedWebhookEventData], [PollSentWebhookEventData],
	// [PollDeliveredWebhookEventData], [PollReadWebhookEventData],
	// [PollUpdatedWebhookEventData], [PollFailedWebhookEventData],
	// [PollVoteAddedWebhookEventData], [PollVoteRemovedWebhookEventData],
	// [ParticipantAddedWebhookEventData], [ParticipantRemovedWebhookEventData],
	// [ChatCreatedWebhookEventData], [ChatGroupNameUpdatedWebhookEventData],
	// [ChatGroupIconUpdatedWebhookEventData],
	// [ChatGroupNameUpdateFailedWebhookEventData],
	// [ChatGroupIconUpdateFailedWebhookEventData],
	// [ChatTypingIndicatorStartedWebhookEventData],
	// [ChatTypingIndicatorStoppedWebhookEventData],
	// [ChatBackgroundUpdatedWebhookEventData],
	// [ChatBackgroundUpdateFailedWebhookEventData],
	// [ContactCardReceivedWebhookEventData],
	// [PhoneNumberStatusUpdatedWebhookEventData], [ConnectionCreatedWebhookEventData],
	// [ConnectionRevokedWebhookEventData], [LocationSharingStartedWebhookEventData],
	// [LocationSharingStoppedWebhookEventData], [PaymentAuthorizedWebhookEventData],
	// [PaymentCanceledWebhookEventData], [PaymentDeclinedWebhookEventData],
	// [PaymentExpiredWebhookEventData], [PaymentSucceededWebhookEventData]
	Data    UnwrapWebhookEventUnionData `json:"data"`
	EventID string                      `json:"event_id"`
	// Any of nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
	// nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
	// nil, nil, nil, nil, nil, nil, nil, nil, nil.
	EventType      string `json:"event_type"`
	PartnerID      string `json:"partner_id"`
	TraceID        string `json:"trace_id"`
	WebhookVersion string `json:"webhook_version"`
	JSON           struct {
		APIVersion     respjson.Field
		CreatedAt      respjson.Field
		Data           respjson.Field
		EventID        respjson.Field
		EventType      respjson.Field
		PartnerID      respjson.Field
		TraceID        respjson.Field
		WebhookVersion respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

UnwrapWebhookEventUnion contains all possible properties and values from MessageSentWebhookEvent, MessageReceivedWebhookEvent, MessageReadWebhookEvent, MessageDeliveredWebhookEvent, MessageFailedWebhookEvent, MessageEditedWebhookEvent, ReactionAddedWebhookEvent, ReactionRemovedWebhookEvent, PollReceivedWebhookEvent, PollSentWebhookEvent, PollDeliveredWebhookEvent, PollReadWebhookEvent, PollUpdatedWebhookEvent, PollFailedWebhookEvent, PollVoteAddedWebhookEvent, PollVoteRemovedWebhookEvent, PollReactionAddedWebhookEvent, ParticipantAddedWebhookEvent, ParticipantRemovedWebhookEvent, ChatCreatedWebhookEvent, ChatGroupNameUpdatedWebhookEvent, ChatGroupIconUpdatedWebhookEvent, ChatGroupNameUpdateFailedWebhookEvent, ChatGroupIconUpdateFailedWebhookEvent, ChatTypingIndicatorStartedWebhookEvent, ChatTypingIndicatorStoppedWebhookEvent, ChatBackgroundUpdatedWebhookEvent, ChatBackgroundUpdateFailedWebhookEvent, ContactCardReceivedWebhookEvent, PhoneNumberStatusUpdatedWebhookEvent, ConnectionCreatedWebhookEvent, ConnectionRevokedWebhookEvent, LocationSharingStartedWebhookEvent, LocationSharingStoppedWebhookEvent, PaymentAuthorizedWebhookEvent, PaymentCanceledWebhookEvent, PaymentDeclinedWebhookEvent, PaymentExpiredWebhookEvent, PaymentSucceededWebhookEvent.

Use the [UnwrapWebhookEventUnion.AsAny] method to switch on the variant.

Use the methods beginning with 'As' to cast the union to one of its variants.

func (UnwrapWebhookEventUnion) AsChatBackgroundUpdateFailedWebhookEvent added in v0.41.0

func (u UnwrapWebhookEventUnion) AsChatBackgroundUpdateFailedWebhookEvent() (v ChatBackgroundUpdateFailedWebhookEvent)

func (UnwrapWebhookEventUnion) AsChatBackgroundUpdatedWebhookEvent added in v0.34.0

func (u UnwrapWebhookEventUnion) AsChatBackgroundUpdatedWebhookEvent() (v ChatBackgroundUpdatedWebhookEvent)

func (UnwrapWebhookEventUnion) AsChatCreatedWebhookEvent added in v0.24.0

func (u UnwrapWebhookEventUnion) AsChatCreatedWebhookEvent() (v ChatCreatedWebhookEvent)

func (UnwrapWebhookEventUnion) AsChatGroupIconUpdateFailedWebhookEvent added in v0.24.0

func (u UnwrapWebhookEventUnion) AsChatGroupIconUpdateFailedWebhookEvent() (v ChatGroupIconUpdateFailedWebhookEvent)

func (UnwrapWebhookEventUnion) AsChatGroupIconUpdatedWebhookEvent added in v0.24.0

func (u UnwrapWebhookEventUnion) AsChatGroupIconUpdatedWebhookEvent() (v ChatGroupIconUpdatedWebhookEvent)

func (UnwrapWebhookEventUnion) AsChatGroupNameUpdateFailedWebhookEvent added in v0.24.0

func (u UnwrapWebhookEventUnion) AsChatGroupNameUpdateFailedWebhookEvent() (v ChatGroupNameUpdateFailedWebhookEvent)

func (UnwrapWebhookEventUnion) AsChatGroupNameUpdatedWebhookEvent added in v0.24.0

func (u UnwrapWebhookEventUnion) AsChatGroupNameUpdatedWebhookEvent() (v ChatGroupNameUpdatedWebhookEvent)

func (UnwrapWebhookEventUnion) AsChatTypingIndicatorStartedWebhookEvent added in v0.24.0

func (u UnwrapWebhookEventUnion) AsChatTypingIndicatorStartedWebhookEvent() (v ChatTypingIndicatorStartedWebhookEvent)

func (UnwrapWebhookEventUnion) AsChatTypingIndicatorStoppedWebhookEvent added in v0.24.0

func (u UnwrapWebhookEventUnion) AsChatTypingIndicatorStoppedWebhookEvent() (v ChatTypingIndicatorStoppedWebhookEvent)

func (UnwrapWebhookEventUnion) AsConnectionCreatedWebhookEvent added in v0.49.0

func (u UnwrapWebhookEventUnion) AsConnectionCreatedWebhookEvent() (v ConnectionCreatedWebhookEvent)

func (UnwrapWebhookEventUnion) AsConnectionRevokedWebhookEvent added in v0.49.0

func (u UnwrapWebhookEventUnion) AsConnectionRevokedWebhookEvent() (v ConnectionRevokedWebhookEvent)

func (UnwrapWebhookEventUnion) AsContactCardReceivedWebhookEvent added in v0.47.0

func (u UnwrapWebhookEventUnion) AsContactCardReceivedWebhookEvent() (v ContactCardReceivedWebhookEvent)

func (UnwrapWebhookEventUnion) AsLocationSharingStartedWebhookEvent added in v0.49.0

func (u UnwrapWebhookEventUnion) AsLocationSharingStartedWebhookEvent() (v LocationSharingStartedWebhookEvent)

func (UnwrapWebhookEventUnion) AsLocationSharingStoppedWebhookEvent added in v0.49.0

func (u UnwrapWebhookEventUnion) AsLocationSharingStoppedWebhookEvent() (v LocationSharingStoppedWebhookEvent)

func (UnwrapWebhookEventUnion) AsMessageDeliveredWebhookEvent added in v0.24.0

func (u UnwrapWebhookEventUnion) AsMessageDeliveredWebhookEvent() (v MessageDeliveredWebhookEvent)

func (UnwrapWebhookEventUnion) AsMessageEditedWebhookEvent added in v0.24.0

func (u UnwrapWebhookEventUnion) AsMessageEditedWebhookEvent() (v MessageEditedWebhookEvent)

func (UnwrapWebhookEventUnion) AsMessageFailedWebhookEvent added in v0.24.0

func (u UnwrapWebhookEventUnion) AsMessageFailedWebhookEvent() (v MessageFailedWebhookEvent)

func (UnwrapWebhookEventUnion) AsMessageReadWebhookEvent added in v0.24.0

func (u UnwrapWebhookEventUnion) AsMessageReadWebhookEvent() (v MessageReadWebhookEvent)

func (UnwrapWebhookEventUnion) AsMessageReceivedWebhookEvent added in v0.24.0

func (u UnwrapWebhookEventUnion) AsMessageReceivedWebhookEvent() (v MessageReceivedWebhookEvent)

func (UnwrapWebhookEventUnion) AsMessageSentWebhookEvent added in v0.24.0

func (u UnwrapWebhookEventUnion) AsMessageSentWebhookEvent() (v MessageSentWebhookEvent)

func (UnwrapWebhookEventUnion) AsParticipantAddedWebhookEvent added in v0.24.0

func (u UnwrapWebhookEventUnion) AsParticipantAddedWebhookEvent() (v ParticipantAddedWebhookEvent)

func (UnwrapWebhookEventUnion) AsParticipantRemovedWebhookEvent added in v0.24.0

func (u UnwrapWebhookEventUnion) AsParticipantRemovedWebhookEvent() (v ParticipantRemovedWebhookEvent)

func (UnwrapWebhookEventUnion) AsPaymentAuthorizedWebhookEvent added in v0.49.0

func (u UnwrapWebhookEventUnion) AsPaymentAuthorizedWebhookEvent() (v PaymentAuthorizedWebhookEvent)

func (UnwrapWebhookEventUnion) AsPaymentCanceledWebhookEvent added in v0.49.0

func (u UnwrapWebhookEventUnion) AsPaymentCanceledWebhookEvent() (v PaymentCanceledWebhookEvent)

func (UnwrapWebhookEventUnion) AsPaymentDeclinedWebhookEvent added in v0.49.0

func (u UnwrapWebhookEventUnion) AsPaymentDeclinedWebhookEvent() (v PaymentDeclinedWebhookEvent)

func (UnwrapWebhookEventUnion) AsPaymentExpiredWebhookEvent added in v0.49.0

func (u UnwrapWebhookEventUnion) AsPaymentExpiredWebhookEvent() (v PaymentExpiredWebhookEvent)

func (UnwrapWebhookEventUnion) AsPaymentSucceededWebhookEvent added in v0.49.0

func (u UnwrapWebhookEventUnion) AsPaymentSucceededWebhookEvent() (v PaymentSucceededWebhookEvent)

func (UnwrapWebhookEventUnion) AsPhoneNumberStatusUpdatedWebhookEvent added in v0.24.0

func (u UnwrapWebhookEventUnion) AsPhoneNumberStatusUpdatedWebhookEvent() (v PhoneNumberStatusUpdatedWebhookEvent)

func (UnwrapWebhookEventUnion) AsPollDeliveredWebhookEvent added in v0.34.0

func (u UnwrapWebhookEventUnion) AsPollDeliveredWebhookEvent() (v PollDeliveredWebhookEvent)

func (UnwrapWebhookEventUnion) AsPollFailedWebhookEvent added in v0.34.0

func (u UnwrapWebhookEventUnion) AsPollFailedWebhookEvent() (v PollFailedWebhookEvent)

func (UnwrapWebhookEventUnion) AsPollReactionAddedWebhookEvent added in v0.34.0

func (u UnwrapWebhookEventUnion) AsPollReactionAddedWebhookEvent() (v PollReactionAddedWebhookEvent)

func (UnwrapWebhookEventUnion) AsPollReadWebhookEvent added in v0.34.0

func (u UnwrapWebhookEventUnion) AsPollReadWebhookEvent() (v PollReadWebhookEvent)

func (UnwrapWebhookEventUnion) AsPollReceivedWebhookEvent added in v0.34.0

func (u UnwrapWebhookEventUnion) AsPollReceivedWebhookEvent() (v PollReceivedWebhookEvent)

func (UnwrapWebhookEventUnion) AsPollSentWebhookEvent added in v0.34.0

func (u UnwrapWebhookEventUnion) AsPollSentWebhookEvent() (v PollSentWebhookEvent)

func (UnwrapWebhookEventUnion) AsPollUpdatedWebhookEvent added in v0.34.0

func (u UnwrapWebhookEventUnion) AsPollUpdatedWebhookEvent() (v PollUpdatedWebhookEvent)

func (UnwrapWebhookEventUnion) AsPollVoteAddedWebhookEvent added in v0.34.0

func (u UnwrapWebhookEventUnion) AsPollVoteAddedWebhookEvent() (v PollVoteAddedWebhookEvent)

func (UnwrapWebhookEventUnion) AsPollVoteRemovedWebhookEvent added in v0.34.0

func (u UnwrapWebhookEventUnion) AsPollVoteRemovedWebhookEvent() (v PollVoteRemovedWebhookEvent)

func (UnwrapWebhookEventUnion) AsReactionAddedWebhookEvent added in v0.24.0

func (u UnwrapWebhookEventUnion) AsReactionAddedWebhookEvent() (v ReactionAddedWebhookEvent)

func (UnwrapWebhookEventUnion) AsReactionRemovedWebhookEvent added in v0.24.0

func (u UnwrapWebhookEventUnion) AsReactionRemovedWebhookEvent() (v ReactionRemovedWebhookEvent)

func (UnwrapWebhookEventUnion) RawJSON added in v0.24.0

func (u UnwrapWebhookEventUnion) RawJSON() string

Returns the unmodified JSON received from the API

func (*UnwrapWebhookEventUnion) UnmarshalJSON added in v0.24.0

func (r *UnwrapWebhookEventUnion) UnmarshalJSON(data []byte) error

type UnwrapWebhookEventUnionData added in v0.24.0

type UnwrapWebhookEventUnionData struct {
	ID string `json:"id"`
	// This field is a union of [MessageEventV2Chat],
	// [MessageEditedWebhookEventDataChat], [PollReceivedWebhookEventDataChat],
	// [PollSentWebhookEventDataChat], [PollDeliveredWebhookEventDataChat],
	// [PollReadWebhookEventDataChat], [PollUpdatedWebhookEventDataChat],
	// [PollFailedWebhookEventDataChat], [PollVoteAddedWebhookEventDataChat],
	// [PollVoteRemovedWebhookEventDataChat],
	// [ChatBackgroundUpdatedWebhookEventDataChat]
	Chat      UnwrapWebhookEventUnionDataChat `json:"chat"`
	Direction string                          `json:"direction"`
	// This field is from variant [MessageEventV2].
	Parts []MessageEventV2PartUnion `json:"parts"`
	// This field is a union of [shared.ChatHandle], [string]
	SenderHandle UnwrapWebhookEventUnionDataSenderHandle `json:"sender_handle"`
	Service      string                                  `json:"service"`
	DeliveredAt  time.Time                               `json:"delivered_at"`
	// This field is from variant [MessageEventV2].
	Effect SchemasMessageEffect `json:"effect"`
	// This field is from variant [MessageEventV2].
	IdempotencyKey   string    `json:"idempotency_key"`
	PreferredService string    `json:"preferred_service"`
	ReadAt           time.Time `json:"read_at"`
	// This field is from variant [MessageEventV2].
	ReconciledAt time.Time `json:"reconciled_at"`
	// This field is from variant [MessageEventV2].
	ReplyTo       MessageEventV2ReplyTo `json:"reply_to"`
	SentAt        time.Time             `json:"sent_at"`
	ZeroRetention bool                  `json:"zero_retention"`
	// This field is from variant [MessageFailedWebhookEventData].
	Code     int64     `json:"code"`
	FailedAt time.Time `json:"failed_at"`
	ChatID   string    `json:"chat_id"`
	// This field is from variant [MessageFailedWebhookEventData].
	DetailCode int64  `json:"detail_code"`
	MessageID  string `json:"message_id"`
	// This field is from variant [MessageFailedWebhookEventData].
	Reason string `json:"reason"`
	// This field is from variant [MessageEditedWebhookEventData].
	EditedAt time.Time `json:"edited_at"`
	// This field is from variant [MessageEditedWebhookEventData].
	Part MessageEditedWebhookEventDataPart `json:"part"`
	// This field is from variant [ReactionEventBase].
	IsFromMe bool `json:"is_from_me"`
	// This field is from variant [ReactionEventBase].
	ReactionType shared.ReactionType `json:"reaction_type"`
	// This field is from variant [ReactionEventBase].
	CustomEmoji string `json:"custom_emoji"`
	// This field is from variant [ReactionEventBase].
	From string `json:"from"`
	// This field is from variant [ReactionEventBase].
	FromHandle shared.ChatHandle `json:"from_handle"`
	// This field is from variant [ReactionEventBase].
	PartIndex int64 `json:"part_index"`
	// This field is from variant [ReactionEventBase].
	ReactedAt time.Time `json:"reacted_at"`
	// This field is from variant [ReactionEventBase].
	ReactionID string `json:"reaction_id"`
	// This field is from variant [ReactionEventBase].
	Sticker   ReactionEventBaseSticker `json:"sticker"`
	CreatedAt time.Time                `json:"created_at"`
	// This field is a union of [PollReceivedWebhookEventDataPoll],
	// [PollSentWebhookEventDataPoll], [PollDeliveredWebhookEventDataPoll],
	// [PollReadWebhookEventDataPoll], [PollFailedWebhookEventDataPoll]
	Poll UnwrapWebhookEventUnionDataPoll `json:"poll"`
	// This field is from variant [PollReceivedWebhookEventData].
	ReceivedAt time.Time `json:"received_at"`
	UpdatedAt  time.Time `json:"updated_at"`
	// This field is from variant [PollUpdatedWebhookEventData].
	AddedOptions []PollUpdatedWebhookEventDataAddedOption `json:"added_options"`
	// This field is from variant [PollFailedWebhookEventData].
	Error    PollFailedWebhookEventDataError `json:"error"`
	OptionID string                          `json:"option_id"`
	Handle   string                          `json:"handle"`
	// This field is from variant [ParticipantAddedWebhookEventData].
	AddedAt time.Time `json:"added_at"`
	// This field is from variant [ParticipantAddedWebhookEventData].
	Participant shared.ChatHandle `json:"participant"`
	// This field is from variant [ParticipantRemovedWebhookEventData].
	RemovedAt time.Time `json:"removed_at"`
	// This field is from variant [ChatCreatedWebhookEventData].
	DisplayName string `json:"display_name"`
	// This field is from variant [ChatCreatedWebhookEventData].
	Handles []shared.ChatHandle `json:"handles"`
	// This field is from variant [ChatCreatedWebhookEventData].
	HealthStatus ChatCreatedWebhookEventDataHealthStatus `json:"health_status"`
	// This field is from variant [ChatCreatedWebhookEventData].
	IsGroup bool `json:"is_group"`
	// This field is from variant [ChatGroupNameUpdatedWebhookEventData].
	ChangedByHandle shared.ChatHandle `json:"changed_by_handle"`
	NewValue        string            `json:"new_value"`
	OldValue        string            `json:"old_value"`
	ErrorCode       int64             `json:"error_code"`
	// This field is from variant [ChatBackgroundUpdatedWebhookEventData].
	ActorHandle shared.ChatHandle `json:"actor_handle"`
	// This field is from variant [ChatBackgroundUpdatedWebhookEventData].
	Background ChatBackgroundUpdatedWebhookEventDataBackground `json:"background"`
	// This field is from variant [ContactCardReceivedWebhookEventData].
	FirstName string `json:"first_name"`
	// This field is from variant [ContactCardReceivedWebhookEventData].
	LastName string `json:"last_name"`
	// This field is from variant [ContactCardReceivedWebhookEventData].
	OwnerHandle string `json:"owner_handle"`
	// This field is from variant [ContactCardReceivedWebhookEventData].
	MediaURL string `json:"media_url"`
	// This field is from variant [PhoneNumberStatusUpdatedWebhookEventData].
	ChangedAt time.Time `json:"changed_at"`
	// This field is from variant [PhoneNumberStatusUpdatedWebhookEventData].
	NewReputation string `json:"new_reputation"`
	// This field is from variant [PhoneNumberStatusUpdatedWebhookEventData].
	NewStatus string `json:"new_status"`
	// This field is from variant [PhoneNumberStatusUpdatedWebhookEventData].
	PhoneNumber string `json:"phone_number"`
	// This field is from variant [PhoneNumberStatusUpdatedWebhookEventData].
	PreviousReputation string `json:"previous_reputation"`
	// This field is from variant [PhoneNumberStatusUpdatedWebhookEventData].
	PreviousStatus string `json:"previous_status"`
	Amount         int64  `json:"amount"`
	CheckoutURL    string `json:"checkout_url"`
	Currency       string `json:"currency"`
	Object         string `json:"object"`
	Status         string `json:"status"`
	Description    string `json:"description"`
	// This field is a union of [ConnectionCreatedWebhookEventDataDiscount],
	// [ConnectionRevokedWebhookEventDataDiscount],
	// [PaymentAuthorizedWebhookEventDataDiscount],
	// [PaymentCanceledWebhookEventDataDiscount],
	// [PaymentDeclinedWebhookEventDataDiscount],
	// [PaymentExpiredWebhookEventDataDiscount],
	// [PaymentSucceededWebhookEventDataDiscount]
	Discount      UnwrapWebhookEventUnionDataDiscount `json:"discount"`
	Interval      string                              `json:"interval"`
	IntervalCount int64                               `json:"interval_count"`
	Metadata      string                              `json:"metadata"`
	Mode          string                              `json:"mode"`
	// This field is a union of [ConnectionCreatedWebhookEventDataNatural],
	// [ConnectionRevokedWebhookEventDataNatural],
	// [PaymentAuthorizedWebhookEventDataNatural],
	// [PaymentCanceledWebhookEventDataNatural],
	// [PaymentDeclinedWebhookEventDataNatural],
	// [PaymentExpiredWebhookEventDataNatural],
	// [PaymentSucceededWebhookEventDataNatural]
	Natural  UnwrapWebhookEventUnionDataNatural `json:"natural"`
	PriceID  string                             `json:"price_id"`
	Quantity int64                              `json:"quantity"`
	Rail     string                             `json:"rail"`
	// This field is a union of [ConnectionCreatedWebhookEventDataStripe],
	// [ConnectionRevokedWebhookEventDataStripe],
	// [PaymentAuthorizedWebhookEventDataStripe],
	// [PaymentCanceledWebhookEventDataStripe],
	// [PaymentDeclinedWebhookEventDataStripe], [PaymentExpiredWebhookEventDataStripe],
	// [PaymentSucceededWebhookEventDataStripe]
	Stripe   UnwrapWebhookEventUnionDataStripe `json:"stripe"`
	TrialEnd time.Time                         `json:"trial_end"`
	BeganAt  time.Time                         `json:"began_at"`
	// This field is from variant [LocationSharingStartedWebhookEventData].
	EndsAt     time.Time `json:"ends_at"`
	SharedBy   string    `json:"shared_by"`
	SharedWith string    `json:"shared_with"`
	// This field is from variant [LocationSharingStoppedWebhookEventData].
	EndedAt time.Time `json:"ended_at"`
	JSON    struct {
		ID                 respjson.Field
		Chat               respjson.Field
		Direction          respjson.Field
		Parts              respjson.Field
		SenderHandle       respjson.Field
		Service            respjson.Field
		DeliveredAt        respjson.Field
		Effect             respjson.Field
		IdempotencyKey     respjson.Field
		PreferredService   respjson.Field
		ReadAt             respjson.Field
		ReconciledAt       respjson.Field
		ReplyTo            respjson.Field
		SentAt             respjson.Field
		ZeroRetention      respjson.Field
		Code               respjson.Field
		FailedAt           respjson.Field
		ChatID             respjson.Field
		DetailCode         respjson.Field
		MessageID          respjson.Field
		Reason             respjson.Field
		EditedAt           respjson.Field
		Part               respjson.Field
		IsFromMe           respjson.Field
		ReactionType       respjson.Field
		CustomEmoji        respjson.Field
		From               respjson.Field
		FromHandle         respjson.Field
		PartIndex          respjson.Field
		ReactedAt          respjson.Field
		ReactionID         respjson.Field
		Sticker            respjson.Field
		CreatedAt          respjson.Field
		Poll               respjson.Field
		ReceivedAt         respjson.Field
		UpdatedAt          respjson.Field
		AddedOptions       respjson.Field
		Error              respjson.Field
		OptionID           respjson.Field
		Handle             respjson.Field
		AddedAt            respjson.Field
		Participant        respjson.Field
		RemovedAt          respjson.Field
		DisplayName        respjson.Field
		Handles            respjson.Field
		HealthStatus       respjson.Field
		IsGroup            respjson.Field
		ChangedByHandle    respjson.Field
		NewValue           respjson.Field
		OldValue           respjson.Field
		ErrorCode          respjson.Field
		ActorHandle        respjson.Field
		Background         respjson.Field
		FirstName          respjson.Field
		LastName           respjson.Field
		OwnerHandle        respjson.Field
		MediaURL           respjson.Field
		ChangedAt          respjson.Field
		NewReputation      respjson.Field
		NewStatus          respjson.Field
		PhoneNumber        respjson.Field
		PreviousReputation respjson.Field
		PreviousStatus     respjson.Field
		Amount             respjson.Field
		CheckoutURL        respjson.Field
		Currency           respjson.Field
		Object             respjson.Field
		Status             respjson.Field
		Description        respjson.Field
		Discount           respjson.Field
		Interval           respjson.Field
		IntervalCount      respjson.Field
		Metadata           respjson.Field
		Mode               respjson.Field
		Natural            respjson.Field
		PriceID            respjson.Field
		Quantity           respjson.Field
		Rail               respjson.Field
		Stripe             respjson.Field
		TrialEnd           respjson.Field
		BeganAt            respjson.Field
		EndsAt             respjson.Field
		SharedBy           respjson.Field
		SharedWith         respjson.Field
		EndedAt            respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

UnwrapWebhookEventUnionData is an implicit subunion of UnwrapWebhookEventUnion. UnwrapWebhookEventUnionData provides convenient access to the sub-properties of the union.

For type safety it is recommended to directly use a variant of the UnwrapWebhookEventUnion.

func (*UnwrapWebhookEventUnionData) UnmarshalJSON added in v0.24.0

func (r *UnwrapWebhookEventUnionData) UnmarshalJSON(data []byte) error

type UnwrapWebhookEventUnionDataChat added in v0.24.0

type UnwrapWebhookEventUnionDataChat struct {
	ID string `json:"id"`
	// This field is a union of [MessageEventV2ChatHealthStatus],
	// [MessageEditedWebhookEventDataChatHealthStatus]
	HealthStatus UnwrapWebhookEventUnionDataChatHealthStatus `json:"health_status"`
	IsGroup      bool                                        `json:"is_group"`
	// This field is from variant [MessageEventV2Chat].
	OwnerHandle shared.ChatHandle `json:"owner_handle"`
	JSON        struct {
		ID           respjson.Field
		HealthStatus respjson.Field
		IsGroup      respjson.Field
		OwnerHandle  respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

UnwrapWebhookEventUnionDataChat is an implicit subunion of UnwrapWebhookEventUnion. UnwrapWebhookEventUnionDataChat provides convenient access to the sub-properties of the union.

For type safety it is recommended to directly use a variant of the UnwrapWebhookEventUnion.

func (*UnwrapWebhookEventUnionDataChat) UnmarshalJSON added in v0.24.0

func (r *UnwrapWebhookEventUnionDataChat) UnmarshalJSON(data []byte) error

type UnwrapWebhookEventUnionDataChatHealthStatus added in v0.24.0

type UnwrapWebhookEventUnionDataChatHealthStatus struct {
	DocURL    string    `json:"doc_url"`
	Status    string    `json:"status"`
	UpdatedAt time.Time `json:"updated_at"`
	JSON      struct {
		DocURL    respjson.Field
		Status    respjson.Field
		UpdatedAt respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

UnwrapWebhookEventUnionDataChatHealthStatus is an implicit subunion of UnwrapWebhookEventUnion. UnwrapWebhookEventUnionDataChatHealthStatus provides convenient access to the sub-properties of the union.

For type safety it is recommended to directly use a variant of the UnwrapWebhookEventUnion.

func (*UnwrapWebhookEventUnionDataChatHealthStatus) UnmarshalJSON added in v0.24.0

func (r *UnwrapWebhookEventUnionDataChatHealthStatus) UnmarshalJSON(data []byte) error

type UnwrapWebhookEventUnionDataDiscount added in v0.49.0

type UnwrapWebhookEventUnionDataDiscount struct {
	Coupon        string `json:"coupon"`
	Label         string `json:"label"`
	PromotionCode string `json:"promotion_code"`
	JSON          struct {
		Coupon        respjson.Field
		Label         respjson.Field
		PromotionCode respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

UnwrapWebhookEventUnionDataDiscount is an implicit subunion of UnwrapWebhookEventUnion. UnwrapWebhookEventUnionDataDiscount provides convenient access to the sub-properties of the union.

For type safety it is recommended to directly use a variant of the UnwrapWebhookEventUnion.

func (*UnwrapWebhookEventUnionDataDiscount) UnmarshalJSON added in v0.49.0

func (r *UnwrapWebhookEventUnionDataDiscount) UnmarshalJSON(data []byte) error

type UnwrapWebhookEventUnionDataNatural added in v0.49.0

type UnwrapWebhookEventUnionDataNatural struct {
	PaymentRequestID string `json:"payment_request_id"`
	TransactionID    string `json:"transaction_id"`
	JSON             struct {
		PaymentRequestID respjson.Field
		TransactionID    respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

UnwrapWebhookEventUnionDataNatural is an implicit subunion of UnwrapWebhookEventUnion. UnwrapWebhookEventUnionDataNatural provides convenient access to the sub-properties of the union.

For type safety it is recommended to directly use a variant of the UnwrapWebhookEventUnion.

func (*UnwrapWebhookEventUnionDataNatural) UnmarshalJSON added in v0.49.0

func (r *UnwrapWebhookEventUnionDataNatural) UnmarshalJSON(data []byte) error

type UnwrapWebhookEventUnionDataPoll added in v0.34.0

type UnwrapWebhookEventUnionDataPoll struct {
	// This field is a union of [[]PollReceivedWebhookEventDataPollOption],
	// [[]PollSentWebhookEventDataPollOption],
	// [[]PollDeliveredWebhookEventDataPollOption],
	// [[]PollReadWebhookEventDataPollOption], [[]PollFailedWebhookEventDataPollOption]
	Options     UnwrapWebhookEventUnionDataPollOptions `json:"options"`
	TotalVoters int64                                  `json:"total_voters"`
	JSON        struct {
		Options     respjson.Field
		TotalVoters respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

UnwrapWebhookEventUnionDataPoll is an implicit subunion of UnwrapWebhookEventUnion. UnwrapWebhookEventUnionDataPoll provides convenient access to the sub-properties of the union.

For type safety it is recommended to directly use a variant of the UnwrapWebhookEventUnion.

func (*UnwrapWebhookEventUnionDataPoll) UnmarshalJSON added in v0.34.0

func (r *UnwrapWebhookEventUnionDataPoll) UnmarshalJSON(data []byte) error

type UnwrapWebhookEventUnionDataPollOptions added in v0.34.0

type UnwrapWebhookEventUnionDataPollOptions struct {
	// This field will be present if the value is a
	// [[]PollReceivedWebhookEventDataPollOption] instead of an object.
	OfPollReceivedWebhookEventDataPollOptions []PollReceivedWebhookEventDataPollOption `json:",inline"`
	// This field will be present if the value is a
	// [[]PollSentWebhookEventDataPollOption] instead of an object.
	OfPollSentWebhookEventDataPollOptions []PollSentWebhookEventDataPollOption `json:",inline"`
	// This field will be present if the value is a
	// [[]PollDeliveredWebhookEventDataPollOption] instead of an object.
	OfPollDeliveredWebhookEventDataPollOptions []PollDeliveredWebhookEventDataPollOption `json:",inline"`
	// This field will be present if the value is a
	// [[]PollReadWebhookEventDataPollOption] instead of an object.
	OfPollReadWebhookEventDataPollOptions []PollReadWebhookEventDataPollOption `json:",inline"`
	// This field will be present if the value is a
	// [[]PollFailedWebhookEventDataPollOption] instead of an object.
	OfPollFailedWebhookEventDataPollOptions []PollFailedWebhookEventDataPollOption `json:",inline"`
	JSON                                    struct {
		OfPollReceivedWebhookEventDataPollOptions  respjson.Field
		OfPollSentWebhookEventDataPollOptions      respjson.Field
		OfPollDeliveredWebhookEventDataPollOptions respjson.Field
		OfPollReadWebhookEventDataPollOptions      respjson.Field
		OfPollFailedWebhookEventDataPollOptions    respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

UnwrapWebhookEventUnionDataPollOptions is an implicit subunion of UnwrapWebhookEventUnion. UnwrapWebhookEventUnionDataPollOptions provides convenient access to the sub-properties of the union.

For type safety it is recommended to directly use a variant of the UnwrapWebhookEventUnion.

If the underlying value is not a json object, one of the following properties will be valid: OfPollReceivedWebhookEventDataPollOptions OfPollSentWebhookEventDataPollOptions OfPollDeliveredWebhookEventDataPollOptions OfPollReadWebhookEventDataPollOptions OfPollFailedWebhookEventDataPollOptions]

func (*UnwrapWebhookEventUnionDataPollOptions) UnmarshalJSON added in v0.34.0

func (r *UnwrapWebhookEventUnionDataPollOptions) UnmarshalJSON(data []byte) error

type UnwrapWebhookEventUnionDataSenderHandle added in v0.47.0

type UnwrapWebhookEventUnionDataSenderHandle struct {
	// This field will be present if the value is a [string] instead of an object.
	OfString string `json:",inline"`
	// This field is from variant [shared.ChatHandle].
	ID string `json:"id"`
	// This field is from variant [shared.ChatHandle].
	Handle string `json:"handle"`
	// This field is from variant [shared.ChatHandle].
	JoinedAt time.Time `json:"joined_at"`
	// This field is from variant [shared.ChatHandle].
	Service shared.ServiceType `json:"service"`
	// This field is from variant [shared.ChatHandle].
	IsMe bool `json:"is_me"`
	// This field is from variant [shared.ChatHandle].
	LeftAt time.Time `json:"left_at"`
	// This field is from variant [shared.ChatHandle].
	Status shared.ChatHandleStatus `json:"status"`
	JSON   struct {
		OfString respjson.Field
		ID       respjson.Field
		Handle   respjson.Field
		JoinedAt respjson.Field
		Service  respjson.Field
		IsMe     respjson.Field
		LeftAt   respjson.Field
		Status   respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

UnwrapWebhookEventUnionDataSenderHandle is an implicit subunion of UnwrapWebhookEventUnion. UnwrapWebhookEventUnionDataSenderHandle provides convenient access to the sub-properties of the union.

For type safety it is recommended to directly use a variant of the UnwrapWebhookEventUnion.

If the underlying value is not a json object, one of the following properties will be valid: OfString]

func (*UnwrapWebhookEventUnionDataSenderHandle) UnmarshalJSON added in v0.47.0

func (r *UnwrapWebhookEventUnionDataSenderHandle) UnmarshalJSON(data []byte) error

type UnwrapWebhookEventUnionDataStripe added in v0.49.0

type UnwrapWebhookEventUnionDataStripe struct {
	CustomerID      string `json:"customer_id"`
	PaymentIntentID string `json:"payment_intent_id"`
	SubscriptionID  string `json:"subscription_id"`
	JSON            struct {
		CustomerID      respjson.Field
		PaymentIntentID respjson.Field
		SubscriptionID  respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

UnwrapWebhookEventUnionDataStripe is an implicit subunion of UnwrapWebhookEventUnion. UnwrapWebhookEventUnionDataStripe provides convenient access to the sub-properties of the union.

For type safety it is recommended to directly use a variant of the UnwrapWebhookEventUnion.

func (*UnwrapWebhookEventUnionDataStripe) UnmarshalJSON added in v0.49.0

func (r *UnwrapWebhookEventUnionDataStripe) UnmarshalJSON(data []byte) error

type WebhookEventListResponse

type WebhookEventListResponse struct {
	// URL to the webhook events documentation
	DocURL constant.HTTPSDocsLinqappComChannelIMessageGuidesWebhooksEvents `json:"doc_url" default:"https://docs.linqapp.com/channel/imessage/guides/webhooks/events"`
	// List of all available webhook event types
	Events []WebhookEventType `json:"events" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		DocURL      respjson.Field
		Events      respjson.Field
		ExtraFields map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (WebhookEventListResponse) RawJSON

func (r WebhookEventListResponse) RawJSON() string

Returns the unmodified JSON received from the API

func (*WebhookEventListResponse) UnmarshalJSON

func (r *WebhookEventListResponse) UnmarshalJSON(data []byte) error

type WebhookEventService

type WebhookEventService struct {
	Options []option.RequestOption
}

Webhook Subscriptions allow you to receive real-time notifications when events occur on your account.

Configure webhook endpoints to receive events such as messages sent/received, delivery status changes, reactions, typing indicators, and more.

Failed deliveries (5xx, 429, network errors) are retried up to 10 times over ~25 minutes with exponential backoff. Each event includes a unique ID for deduplication.

## Webhook Headers

All webhook requests include two sets of headers. **If you have an existing integration using the `X-Webhook-*` headers, nothing changes** — those headers are still sent on every delivery and work exactly as before. The new `webhook-*` headers follow the [Standard Webhooks](https://github.com/standard-webhooks/standard-webhooks) specification. You can safely ignore them if your current verification code works and you don't want to use this convention.

### Standard Webhooks Headers (Recommended)

Used by [our SDK](https://github.com/linq-team/linq-node) and any [Standard Webhooks library](https://github.com/standard-webhooks/standard-webhooks).

| Header | Description | | ------------------- | -------------------------------------------------- | | `webhook-id` | Unique event identifier (use as idempotency key) | | `webhook-timestamp` | Unix timestamp (seconds) when the webhook was sent | | `webhook-signature` | Standard Webhooks signature (`v1,{base64}` format) |

### Legacy Headers (Deprecated)

Still sent on every delivery for backwards compatibility. Existing verification code using these headers continues to work — no changes required.

| Header | Description | | --------------------------- | -------------------------------------------------- | | `X-Webhook-Event` | _(deprecated)_ Event type (e.g., `message.sent`) | | `X-Webhook-Subscription-ID` | _(deprecated)_ Webhook subscription ID | | `X-Webhook-Timestamp` | _(deprecated)_ Unix timestamp (seconds) | | `X-Webhook-Signature` | _(deprecated)_ HMAC-SHA256 signature (hex-encoded) |

## Signing Secrets

Signing secrets use the Standard Webhooks format: a `whsec_` prefix followed by base64-encoded random bytes (e.g., `whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw7Jxx2Oll+OE=`).

Strip the `whsec_` prefix and base64-decode the remainder to get the raw key bytes.

## Verifying Webhook Signatures

Webhooks are signed following the [Standard Webhooks specification](https://github.com/standard-webhooks/standard-webhooks). You can use any [Standard Webhooks library](https://github.com/standard-webhooks/standard-webhooks) to verify signatures, or implement verification manually:

**Signed content:** `{webhook-id}.{webhook-timestamp}.{body}`

**Verification Steps:**

  1. Extract the `webhook-id`, `webhook-timestamp`, and `webhook-signature` headers
  2. Reject if the timestamp is more than 5 minutes old (replay protection)
  3. Get the raw request body bytes (do not parse and re-serialize)
  4. Construct signed content: `"{webhook-id}.{webhook-timestamp}.{body}"`
  5. Strip the `whsec_` prefix from your secret and base64-decode to get key bytes
  6. Compute HMAC-SHA256 using the key bytes over the signed content
  7. Base64-encode the result and compare with the value after `v1,` in `webhook-signature`
  8. Use constant-time comparison to prevent timing attacks

**Example (Python):**

```python import base64, hmac, hashlib

def verify_webhook(secret, body, headers):

msg_id = headers['webhook-id']
timestamp = headers['webhook-timestamp']
signature = headers['webhook-signature']

secret_str = secret.removeprefix('whsec_')
key = base64.b64decode(secret_str)

signed_content = f"{msg_id}.{timestamp}.{body}"
expected = base64.b64encode(
    hmac.new(key, signed_content.encode(), hashlib.sha256).digest()
).decode()

for sig in signature.split(' '):
    if sig.startswith('v1,') and hmac.compare_digest(expected, sig[3:]):
        return True
return False

```

**Example (Node.js):**

```javascript const crypto = require("crypto");

function verifyWebhook(secret, rawBody, headers) {
  const msgId = headers["webhook-id"];
  const timestamp = headers["webhook-timestamp"];
  const signature = headers["webhook-signature"];

  const secretStr = secret.startsWith("whsec_") ? secret.slice(6) : secret;
  const keyBytes = Buffer.from(secretStr, "base64");
  const signedContent = `${msgId}.${timestamp}.${rawBody}`;
  const expected = crypto
    .createHmac("sha256", keyBytes)
    .update(signedContent)
    .digest("base64");

  return signature.split(" ").some((sig) => {
    if (!sig.startsWith("v1,")) return false;
    try {
      return crypto.timingSafeEqual(
        Buffer.from(expected, "base64"),
        Buffer.from(sig.slice(3), "base64")
      );
    } catch {
      return false;
    }
  });
}

```

**Security Best Practices:**

  • Reject webhooks with timestamps older than 5 minutes to prevent replay attacks
  • Always use constant-time comparison for signature verification
  • Store your signing secret securely (e.g., environment variable, secrets manager)
  • Return a 2xx status code quickly, then process the webhook asynchronously

WebhookEventService contains methods and other services that help with interacting with the linq-api-v3 API.

Note, unlike clients, this service does not read variables from the environment automatically. You should not instantiate this service directly, and instead use the NewWebhookEventService method instead.

func NewWebhookEventService

func NewWebhookEventService(opts ...option.RequestOption) (r WebhookEventService)

NewWebhookEventService generates a new service that applies the given options to each request. These options are applied after the parent client's options (if there is one), and before any request-specific options.

func (*WebhookEventService) List

Returns all available webhook event types that can be subscribed to. Use this endpoint to discover valid values for the `subscribed_events` field when creating or updating webhook subscriptions.

type WebhookEventType

type WebhookEventType string

Valid webhook event types that can be subscribed to.

**Note:** `message.edited` is only delivered to subscriptions using `webhook_version: "2026-02-03"`. Subscribing to this event on a v2025 subscription will not produce any deliveries.

const (
	WebhookEventTypeMessageSent                WebhookEventType = "message.sent"
	WebhookEventTypeMessageReceived            WebhookEventType = "message.received"
	WebhookEventTypeMessageRead                WebhookEventType = "message.read"
	WebhookEventTypeMessageDelivered           WebhookEventType = "message.delivered"
	WebhookEventTypeMessageFailed              WebhookEventType = "message.failed"
	WebhookEventTypeMessageEdited              WebhookEventType = "message.edited"
	WebhookEventTypeReactionAdded              WebhookEventType = "reaction.added"
	WebhookEventTypeReactionRemoved            WebhookEventType = "reaction.removed"
	WebhookEventTypePollReceived               WebhookEventType = "poll.received"
	WebhookEventTypePollFailed                 WebhookEventType = "poll.failed"
	WebhookEventTypePollSent                   WebhookEventType = "poll.sent"
	WebhookEventTypePollDelivered              WebhookEventType = "poll.delivered"
	WebhookEventTypePollRead                   WebhookEventType = "poll.read"
	WebhookEventTypePollUpdated                WebhookEventType = "poll.updated"
	WebhookEventTypePollVoteAdded              WebhookEventType = "poll.vote.added"
	WebhookEventTypePollVoteRemoved            WebhookEventType = "poll.vote.removed"
	WebhookEventTypePollReactionAdded          WebhookEventType = "poll.reaction.added"
	WebhookEventTypeParticipantAdded           WebhookEventType = "participant.added"
	WebhookEventTypeParticipantRemoved         WebhookEventType = "participant.removed"
	WebhookEventTypeChatCreated                WebhookEventType = "chat.created"
	WebhookEventTypeChatGroupNameUpdated       WebhookEventType = "chat.group_name_updated"
	WebhookEventTypeChatGroupIconUpdated       WebhookEventType = "chat.group_icon_updated"
	WebhookEventTypeChatGroupNameUpdateFailed  WebhookEventType = "chat.group_name_update_failed"
	WebhookEventTypeChatGroupIconUpdateFailed  WebhookEventType = "chat.group_icon_update_failed"
	WebhookEventTypeChatBackgroundUpdated      WebhookEventType = "chat.background_updated"
	WebhookEventTypeChatBackgroundUpdateFailed WebhookEventType = "chat.background_update_failed"
	WebhookEventTypeChatTypingIndicatorStarted WebhookEventType = "chat.typing_indicator.started"
	WebhookEventTypeChatTypingIndicatorStopped WebhookEventType = "chat.typing_indicator.stopped"
	WebhookEventTypePhoneNumberStatusUpdated   WebhookEventType = "phone_number.status_updated"
	WebhookEventTypeContactCardReceived        WebhookEventType = "contact_card.received"
	WebhookEventTypeCallInitiated              WebhookEventType = "call.initiated"
	WebhookEventTypeCallRinging                WebhookEventType = "call.ringing"
	WebhookEventTypeCallAnswered               WebhookEventType = "call.answered"
	WebhookEventTypeCallEnded                  WebhookEventType = "call.ended"
	WebhookEventTypeCallFailed                 WebhookEventType = "call.failed"
	WebhookEventTypeCallDeclined               WebhookEventType = "call.declined"
	WebhookEventTypeCallNoAnswer               WebhookEventType = "call.no_answer"
	WebhookEventTypeLocationSharingStarted     WebhookEventType = "location.sharing.started"
	WebhookEventTypeLocationSharingStopped     WebhookEventType = "location.sharing.stopped"
	WebhookEventTypePaymentSucceeded           WebhookEventType = "payment.succeeded"
	WebhookEventTypePaymentCanceled            WebhookEventType = "payment.canceled"
	WebhookEventTypePaymentExpired             WebhookEventType = "payment.expired"
	WebhookEventTypePaymentDeclined            WebhookEventType = "payment.declined"
	WebhookEventTypePaymentAuthorized          WebhookEventType = "payment.authorized"
	WebhookEventTypeConnectionCreated          WebhookEventType = "connection.created"
	WebhookEventTypeConnectionRevoked          WebhookEventType = "connection.revoked"
)

type WebhookService added in v0.2.0

type WebhookService struct {
	Options []option.RequestOption
}

WebhookService contains methods and other services that help with interacting with the linq-api-v3 API.

Note, unlike clients, this service does not read variables from the environment automatically. You should not instantiate this service directly, and instead use the NewWebhookService method instead.

func NewWebhookService added in v0.2.0

func NewWebhookService(opts ...option.RequestOption) (r WebhookService)

NewWebhookService generates a new service that applies the given options to each request. These options are applied after the parent client's options (if there is one), and before any request-specific options.

func (*WebhookService) Unwrap added in v0.24.0

func (r *WebhookService) Unwrap(payload []byte, headers http.Header, opts ...option.RequestOption) (*UnwrapWebhookEventUnion, error)

type WebhookSubscription

type WebhookSubscription struct {
	// Unique identifier for the webhook subscription
	ID string `json:"id" api:"required"`
	// When the subscription was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// Whether this subscription is currently active
	IsActive bool `json:"is_active" api:"required"`
	// List of event types this subscription receives
	SubscribedEvents []WebhookEventType `json:"subscribed_events" api:"required"`
	// URL where webhook events will be sent
	TargetURL string `json:"target_url" api:"required" format:"uri"`
	// When the subscription was last updated
	UpdatedAt time.Time `json:"updated_at" api:"required" format:"date-time"`
	// Phone numbers this subscription filters for. If null or empty, events from all
	// phone numbers are delivered.
	PhoneNumbers []string `json:"phone_numbers" api:"nullable"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ID               respjson.Field
		CreatedAt        respjson.Field
		IsActive         respjson.Field
		SubscribedEvents respjson.Field
		TargetURL        respjson.Field
		UpdatedAt        respjson.Field
		PhoneNumbers     respjson.Field
		ExtraFields      map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (WebhookSubscription) RawJSON

func (r WebhookSubscription) RawJSON() string

Returns the unmodified JSON received from the API

func (*WebhookSubscription) UnmarshalJSON

func (r *WebhookSubscription) UnmarshalJSON(data []byte) error

type WebhookSubscriptionListResponse

type WebhookSubscriptionListResponse struct {
	// List of webhook subscriptions
	Subscriptions []WebhookSubscription `json:"subscriptions" api:"required"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		Subscriptions respjson.Field
		ExtraFields   map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

func (WebhookSubscriptionListResponse) RawJSON

Returns the unmodified JSON received from the API

func (*WebhookSubscriptionListResponse) UnmarshalJSON

func (r *WebhookSubscriptionListResponse) UnmarshalJSON(data []byte) error

type WebhookSubscriptionNewParams

type WebhookSubscriptionNewParams struct {
	// List of event types to subscribe to
	SubscribedEvents []WebhookEventType `json:"subscribed_events,omitzero" api:"required"`
	// URL where webhook events will be sent. Must be HTTPS.
	TargetURL string `json:"target_url" api:"required" format:"uri"`
	// Optional list of phone numbers to filter events for. Only events originating
	// from these phone numbers will be delivered to this subscription. If omitted or
	// empty, events from all phone numbers are delivered. Phone numbers must be in
	// E.164 format.
	PhoneNumbers []string `json:"phone_numbers,omitzero"`
	// contains filtered or unexported fields
}

func (WebhookSubscriptionNewParams) MarshalJSON

func (r WebhookSubscriptionNewParams) MarshalJSON() (data []byte, err error)

func (*WebhookSubscriptionNewParams) UnmarshalJSON

func (r *WebhookSubscriptionNewParams) UnmarshalJSON(data []byte) error

type WebhookSubscriptionNewResponse

type WebhookSubscriptionNewResponse struct {
	// Unique identifier for the webhook subscription
	ID string `json:"id" api:"required"`
	// When the subscription was created
	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
	// Whether this subscription is currently active
	IsActive bool `json:"is_active" api:"required"`
	// Secret for verifying webhook signatures. Store this securely - it cannot be
	// retrieved again.
	SigningSecret string `json:"signing_secret" api:"required"`
	// List of event types this subscription receives
	SubscribedEvents []WebhookEventType `json:"subscribed_events" api:"required"`
	// URL where webhook events will be sent
	TargetURL string `json:"target_url" api:"required" format:"uri"`
	// When the subscription was last updated
	UpdatedAt time.Time `json:"updated_at" api:"required" format:"date-time"`
	// Phone numbers this subscription filters for. If null or empty, events from all
	// phone numbers are delivered.
	PhoneNumbers []string `json:"phone_numbers" api:"nullable"`
	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
	JSON struct {
		ID               respjson.Field
		CreatedAt        respjson.Field
		IsActive         respjson.Field
		SigningSecret    respjson.Field
		SubscribedEvents respjson.Field
		TargetURL        respjson.Field
		UpdatedAt        respjson.Field
		PhoneNumbers     respjson.Field
		ExtraFields      map[string]respjson.Field
		// contains filtered or unexported fields
	} `json:"-"`
}

Response returned when creating a webhook subscription. Includes the signing secret which is only shown once.

func (WebhookSubscriptionNewResponse) RawJSON

Returns the unmodified JSON received from the API

func (*WebhookSubscriptionNewResponse) UnmarshalJSON

func (r *WebhookSubscriptionNewResponse) UnmarshalJSON(data []byte) error

type WebhookSubscriptionService

type WebhookSubscriptionService struct {
	Options []option.RequestOption
}

Webhook Subscriptions allow you to receive real-time notifications when events occur on your account.

Configure webhook endpoints to receive events such as messages sent/received, delivery status changes, reactions, typing indicators, and more.

Failed deliveries (5xx, 429, network errors) are retried up to 10 times over ~25 minutes with exponential backoff. Each event includes a unique ID for deduplication.

## Webhook Headers

All webhook requests include two sets of headers. **If you have an existing integration using the `X-Webhook-*` headers, nothing changes** — those headers are still sent on every delivery and work exactly as before. The new `webhook-*` headers follow the [Standard Webhooks](https://github.com/standard-webhooks/standard-webhooks) specification. You can safely ignore them if your current verification code works and you don't want to use this convention.

### Standard Webhooks Headers (Recommended)

Used by [our SDK](https://github.com/linq-team/linq-node) and any [Standard Webhooks library](https://github.com/standard-webhooks/standard-webhooks).

| Header | Description | | ------------------- | -------------------------------------------------- | | `webhook-id` | Unique event identifier (use as idempotency key) | | `webhook-timestamp` | Unix timestamp (seconds) when the webhook was sent | | `webhook-signature` | Standard Webhooks signature (`v1,{base64}` format) |

### Legacy Headers (Deprecated)

Still sent on every delivery for backwards compatibility. Existing verification code using these headers continues to work — no changes required.

| Header | Description | | --------------------------- | -------------------------------------------------- | | `X-Webhook-Event` | _(deprecated)_ Event type (e.g., `message.sent`) | | `X-Webhook-Subscription-ID` | _(deprecated)_ Webhook subscription ID | | `X-Webhook-Timestamp` | _(deprecated)_ Unix timestamp (seconds) | | `X-Webhook-Signature` | _(deprecated)_ HMAC-SHA256 signature (hex-encoded) |

## Signing Secrets

Signing secrets use the Standard Webhooks format: a `whsec_` prefix followed by base64-encoded random bytes (e.g., `whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw7Jxx2Oll+OE=`).

Strip the `whsec_` prefix and base64-decode the remainder to get the raw key bytes.

## Verifying Webhook Signatures

Webhooks are signed following the [Standard Webhooks specification](https://github.com/standard-webhooks/standard-webhooks). You can use any [Standard Webhooks library](https://github.com/standard-webhooks/standard-webhooks) to verify signatures, or implement verification manually:

**Signed content:** `{webhook-id}.{webhook-timestamp}.{body}`

**Verification Steps:**

  1. Extract the `webhook-id`, `webhook-timestamp`, and `webhook-signature` headers
  2. Reject if the timestamp is more than 5 minutes old (replay protection)
  3. Get the raw request body bytes (do not parse and re-serialize)
  4. Construct signed content: `"{webhook-id}.{webhook-timestamp}.{body}"`
  5. Strip the `whsec_` prefix from your secret and base64-decode to get key bytes
  6. Compute HMAC-SHA256 using the key bytes over the signed content
  7. Base64-encode the result and compare with the value after `v1,` in `webhook-signature`
  8. Use constant-time comparison to prevent timing attacks

**Example (Python):**

```python import base64, hmac, hashlib

def verify_webhook(secret, body, headers):

msg_id = headers['webhook-id']
timestamp = headers['webhook-timestamp']
signature = headers['webhook-signature']

secret_str = secret.removeprefix('whsec_')
key = base64.b64decode(secret_str)

signed_content = f"{msg_id}.{timestamp}.{body}"
expected = base64.b64encode(
    hmac.new(key, signed_content.encode(), hashlib.sha256).digest()
).decode()

for sig in signature.split(' '):
    if sig.startswith('v1,') and hmac.compare_digest(expected, sig[3:]):
        return True
return False

```

**Example (Node.js):**

```javascript const crypto = require("crypto");

function verifyWebhook(secret, rawBody, headers) {
  const msgId = headers["webhook-id"];
  const timestamp = headers["webhook-timestamp"];
  const signature = headers["webhook-signature"];

  const secretStr = secret.startsWith("whsec_") ? secret.slice(6) : secret;
  const keyBytes = Buffer.from(secretStr, "base64");
  const signedContent = `${msgId}.${timestamp}.${rawBody}`;
  const expected = crypto
    .createHmac("sha256", keyBytes)
    .update(signedContent)
    .digest("base64");

  return signature.split(" ").some((sig) => {
    if (!sig.startsWith("v1,")) return false;
    try {
      return crypto.timingSafeEqual(
        Buffer.from(expected, "base64"),
        Buffer.from(sig.slice(3), "base64")
      );
    } catch {
      return false;
    }
  });
}

```

**Security Best Practices:**

  • Reject webhooks with timestamps older than 5 minutes to prevent replay attacks
  • Always use constant-time comparison for signature verification
  • Store your signing secret securely (e.g., environment variable, secrets manager)
  • Return a 2xx status code quickly, then process the webhook asynchronously

WebhookSubscriptionService contains methods and other services that help with interacting with the linq-api-v3 API.

Note, unlike clients, this service does not read variables from the environment automatically. You should not instantiate this service directly, and instead use the NewWebhookSubscriptionService method instead.

func NewWebhookSubscriptionService

func NewWebhookSubscriptionService(opts ...option.RequestOption) (r WebhookSubscriptionService)

NewWebhookSubscriptionService generates a new service that applies the given options to each request. These options are applied after the parent client's options (if there is one), and before any request-specific options.

func (*WebhookSubscriptionService) Delete

func (r *WebhookSubscriptionService) Delete(ctx context.Context, subscriptionID string, opts ...option.RequestOption) (err error)

Delete a webhook subscription.

func (*WebhookSubscriptionService) Get

func (r *WebhookSubscriptionService) Get(ctx context.Context, subscriptionID string, opts ...option.RequestOption) (res *WebhookSubscription, err error)

Retrieve details for a specific webhook subscription including its target URL, subscribed events, and current status.

func (*WebhookSubscriptionService) List

Retrieve all webhook subscriptions for the authenticated partner. Returns a list of active and inactive subscriptions with their configuration and status.

func (*WebhookSubscriptionService) New

Create a new webhook subscription to receive events at a target URL. Upon creation, a signing secret is generated for verifying webhook authenticity. **Store this secret securely — it cannot be retrieved later.**

**Phone Number Filtering:**

  • Optionally specify `phone_numbers` to only receive events for specific lines
  • If omitted, events from all phone numbers are delivered (default behavior)
  • Use multiple subscriptions with different `phone_numbers` to route different lines to different endpoints
  • Each `target_url` can only be used once per account. To route different lines to different destinations, use a unique URL per subscription (e.g., append a query parameter: `https://example.com/webhook?line=1`)

**Webhook Delivery:**

func (*WebhookSubscriptionService) Update

Update an existing webhook subscription. You can modify the target URL, subscribed events, or activate/deactivate the subscription.

**Note:** The signing secret cannot be changed via this endpoint.

type WebhookSubscriptionUpdateParams

type WebhookSubscriptionUpdateParams struct {
	// Activate or deactivate the subscription
	IsActive param.Opt[bool] `json:"is_active,omitzero"`
	// New target URL for webhook events
	TargetURL param.Opt[string] `json:"target_url,omitzero" format:"uri"`
	// Updated list of phone numbers to filter events for. Set to a non-empty array to
	// filter events to specific phone numbers. Set to an empty array or null to remove
	// the filter and receive events from all phone numbers. Phone numbers must be in
	// E.164 format.
	PhoneNumbers []string `json:"phone_numbers,omitzero"`
	// Updated list of event types to subscribe to
	SubscribedEvents []WebhookEventType `json:"subscribed_events,omitzero"`
	// contains filtered or unexported fields
}

func (WebhookSubscriptionUpdateParams) MarshalJSON

func (r WebhookSubscriptionUpdateParams) MarshalJSON() (data []byte, err error)

func (*WebhookSubscriptionUpdateParams) UnmarshalJSON

func (r *WebhookSubscriptionUpdateParams) UnmarshalJSON(data []byte) error

Directories

Path Synopsis
encoding/json
Package json implements encoding and decoding of JSON as defined in RFC 7159.
Package json implements encoding and decoding of JSON as defined in RFC 7159.
encoding/json/shims
This package provides shims over Go 1.2{2,3} APIs which are missing from Go 1.22, and used by the Go 1.24 encoding/json package.
This package provides shims over Go 1.2{2,3} APIs which are missing from Go 1.22, and used by the Go 1.24 encoding/json package.
packages

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL