salesforceid

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Feb 16, 2026 License: MIT Imports: 3 Imported by: 0

README

salesforceid

GoDoc Reference

This is a library that enables handling and manipulation of Salesforce Identifiers. Specifically it enables converting identifiers between 15 character (case-sensitive) and 18 character (case-insensitive) versions.

This library parses a Salesforce identifier for the user and provides some convenience methods for handling interactions with the identifier.

For explanations of how the identifier works see:

Changelog

v1.0.0 - 2026-02-13
  • Fix parsing for SalesforceID in New to correct number of bytes Reserved and number of bytes used in the NumericIdentifier fields.

    Previously, we allocated one of the reserved bytes to the numeric identifier incorrectly.

  • Add SalesfoceIDV2 and NewV2 for Salesforce Object Identifiers. These reflect the changes to Salesforce Object IDs to use 3 bytes (using the 6th byte that was previously reserved) to represent Instances (Servers).

    This also renames PodIdentifier from SalesforceID to InstanceIdentifier on SalesforceIDV2 reflect the new language used.

Examples

It's possible to have different versions of a Salesforce identifier. 15 character identifiers are case-sensitive while 18 character identifiers are not. As a result, this library always checks and adjusts the casing of identifiers and always produces 18 character identifiers. This allows users to confidently use which ever form they prefer.

package main

import (
	"fmt"
	"os"

	"github.com/sigmavirus24/salesforceid"
)

func main() {
	// Note that we're using an 18-character, entirely lower-cased Salesforce identifier here
	sfid, err := salesforceid.New("00d000000000062eaa")
	if err != nil {
		fmt.Printf("encountered unexpected error: %q", err)
		os.Exit(1)
	}
	fmt.Println(sfid)
}

Furthermore, one can use this library to perform arithmetic on the identifiers. For an example of where this might be useful see the example in this project.

Documentation

Index

Examples

Constants

View Source
const (
	FifteenCharacterFormat Format = iota + 1
	EighteenCharacterFormat

	PreSummer23IdentifierEdition IdentifierEdition = iota + 1
	PostSummer23IdentifierEdition
)
View Source
const (

	// oldMaxID  = 13_537_086_546_263_552 // == 62 ^ 9
	MaxIdentifierValue = 218_340_105_584_896 // == 62 ^ 8

)

Variables

View Source
var ErrInvalidAddition = fmt.Errorf("addition would overflow maximum value: %d", MaxIdentifierValue)

ErrInvalidAddition is returned when the NumericIdentifier is already the largest allowed in a 9 digit base62 encoded number

View Source
var ErrInvalidEdition = errors.New("invalid edition provided")
View Source
var ErrInvalidLengthSFID = errors.New("sfids should be 15 or 18 characters")

ErrInvalidLengthSFID indicates when an SFID is not a known good length

View Source
var ErrInvalidNumericIdentifier = errors.New("numeric identifier being decoded is invalid")

ErrInvalidNumericIdentifier is returned when attempting to decode a numeric identifier more than 9 bytes long or has invalid bytes

View Source
var ErrInvalidSFID = errors.New("check bytes do not match identifier")

ErrInvalidSFID is returned when an 18 character identifier is provided whose check bytes do not make sense with the 15 character identifier

View Source
var ErrInvalidSubtraction = errors.New("subtraction would result in a negative identifier")

ErrInvalidSubtraction is returned when the amount to subtract from the identifier is greater than the decoded value of the NumericIdentifier

View Source
var ErrValueTooLarge = fmt.Errorf("value is larger than %d", MaxIdentifierValue)

ErrValueTooLarge is returned when attempting to encode a Base62 value larger than will fit in a NumericIdentifier

Functions

func Decode

func Decode(src []byte) (uint64, error)

Decode converts bytes to an unsigned integer. This returns ErrInvalidNumericIdentifier if the length of [src] is not 8 or if one of the bytes is not a valid Base62 identifier.

Example
package main

import (
	"fmt"

	sfid "github.com/sigmavirus24/salesforceid"
)

func main() {
	id, _ := sfid.New("00D000000000062")
	val, _ := sfid.Decode(id.NumericIdentifier)
	fmt.Printf("%s == %d", string(id.NumericIdentifier), val)
}
Output:
00000062 == 374
Example (Second)
package main

import (
	"fmt"

	sfid "github.com/sigmavirus24/salesforceid"
)

func main() {
	id, _ := sfid.New("00d000000000062eaa")
	val, _ := sfid.Decode(id.NumericIdentifier)
	fmt.Printf("%s == %d", string(id.NumericIdentifier), val)
}
Output:
00000062 == 374

func Encode

func Encode(u uint64) (string, error)

Encode converts an unsigned integer to Base62 for use as a NumericIdentifier. This can only handle 62^8. This returns ErrValueTooLarge if u is larger than MaxIdentifierValue.

Example
package main

import (
	"fmt"

	sfid "github.com/sigmavirus24/salesforceid"
)

func main() {
	id, _ := sfid.New("00d000000000062eaa")
	val, _ := sfid.Decode(id.NumericIdentifier)
	encoded, _ := sfid.Encode(val + 238328) // 238328 == 62 * 62 * 62
	fmt.Printf("%s + 238328 == %s", string(id.NumericIdentifier), encoded)
}
Output:
00000062 + 238328 == 00001062
Example (Second)
package main

import (
	"fmt"

	sfid "github.com/sigmavirus24/salesforceid"
)

func main() {
	id, _ := sfid.New("00d000000000062eaa")
	val, _ := sfid.Decode(id.NumericIdentifier)
	encoded, _ := sfid.Encode(val)
	fmt.Printf("%s == %s", string(id.NumericIdentifier), encoded)
}
Output:
00000062 == 00000062

Types

type Format

type Format uint8

Format is used to select the identifier format for representing a SalesforceID.

type IdentifierEdition

type IdentifierEdition uint8

IdentifierEdition is used to indicate the format for the identifier. Prior to the Summer '23 release, identifiers used two characters to identify the Salesforce Pod (a.k.a., Instance, Server). Starting with Summer '23 and enforced with Winter '24, one of the two reserved characters was used to expand the identifier to three characters.

type SalesforceID

type SalesforceID struct {
	KeyPrefix         []byte // KeyPrefix consists of the first 3 bytes of an id. It is used to identify the object
	PodIdentifier     []byte // PodIdentifier consists of the fourth and fifth bytes prior to Summer '23, or fourth, fifth, and sixth bytes starting with Summer '23. It maps to the pod on which the record was created
	Reserved          []byte // Reserved consists of the sixth and seventh bytes reserved for future use prior to Summer '23 or just the seventh byte starting with Summer '23. It should always be either `[]byte{'0', '0'}` or `[]byte{'0'}`
	NumericIdentifier []byte // NumericIdentifier is a Base 62 encoded number that auto-increments for each record. You can decode it with Decode. It may not be negative or lager than [MaxIdentifierValue].
	Suffix            []byte // Suffix are the three bytes at the end of an 18 character identifier. These help determine the casing of a 15 character identifier
	Edition           IdentifierEdition
	// contains filtered or unexported fields
}

SalesforceID stores and manages the Salesforce Identifier and its components. The full identifier is not an accessible attribute. To retrieve it, use the SalesforceID.String method or SalesforceID.Format method. See also: * https://codebycody.com/salesforce-ids-explained/ * https://help.salesforce.com/s/articleView?id=release-notes.rn_hyperforce_object_id.htm&release=246&type=5

Example
package main

import (
	"fmt"

	sfid "github.com/sigmavirus24/salesforceid"
)

func GenerateChunks(starting *sfid.SalesforceID, chunkSize uint64) func() (*sfid.SalesforceID, *sfid.SalesforceID) {
	next := starting
	return func() (*sfid.SalesforceID, *sfid.SalesforceID) {
		current := next
		end, _ := current.Add(chunkSize)
		next, _ = end.Add(1)
		return current, end
	}
}

func main() {
	s, _ := sfid.New("001000000000000")
	chunker := GenerateChunks(s, 250000)

	for range 15 {
		start, end := chunker()
		fmt.Printf("SELECT Id FROM Account WHERE Id >= %s AND Id <= %s\n", start, end)
	}
}
Output:
SELECT Id FROM Account WHERE Id >= 001000000000000AAA AND Id <= 00100000000132GAAQ
SELECT Id FROM Account WHERE Id >= 00100000000132HAAQ AND Id <= 00100000000264XAAQ
SELECT Id FROM Account WHERE Id >= 00100000000264YAAQ AND Id <= 00100000000396oAAA
SELECT Id FROM Account WHERE Id >= 00100000000396pAAA AND Id <= 001000000004C95AAE
SELECT Id FROM Account WHERE Id >= 001000000004C96AAE AND Id <= 001000000005FBMAA2
SELECT Id FROM Account WHERE Id >= 001000000005FBNAA2 AND Id <= 001000000006IDdAAM
SELECT Id FROM Account WHERE Id >= 001000000006IDeAAM AND Id <= 001000000007LFuAAM
SELECT Id FROM Account WHERE Id >= 001000000007LFvAAM AND Id <= 001000000008OIBAA2
SELECT Id FROM Account WHERE Id >= 001000000008OICAA2 AND Id <= 001000000009RKSAA2
SELECT Id FROM Account WHERE Id >= 001000000009RKTAA2 AND Id <= 00100000000AUMjAAO
SELECT Id FROM Account WHERE Id >= 00100000000AUMkAAO AND Id <= 00100000000BXP0AAO
SELECT Id FROM Account WHERE Id >= 00100000000BXP1AAO AND Id <= 00100000000CaRHAA0
SELECT Id FROM Account WHERE Id >= 00100000000CaRIAA0 AND Id <= 00100000000DdTYAA0
SELECT Id FROM Account WHERE Id >= 00100000000DdTZAA0 AND Id <= 00100000000EgVpAAK
SELECT Id FROM Account WHERE Id >= 00100000000EgVqAAK AND Id <= 00100000000FjY6AAK

func New

func New(id string) (*SalesforceID, error)

New generates a SalesforceID for usage. It assumes the edition to be PreSummer23IdentifierEdition for backwards compatibility.

Example
package main

import (
	"fmt"

	sfid "github.com/sigmavirus24/salesforceid"
)

func main() {
	id, err := sfid.New("00D000000000062")
	if err != nil {
		fmt.Println(err)
	}
	fmt.Printf("00D000000000062 => %s", id)
}
Output:
00D000000000062 => 00D000000000062EAA
Example (Second)
package main

import (
	"fmt"

	sfid "github.com/sigmavirus24/salesforceid"
)

func main() {
	id, err := sfid.New("00d000000000062eaa")
	if err != nil {
		fmt.Println(err)
	}
	fmt.Printf("00d000000000062eaa => %s", id)
}
Output:
00d000000000062eaa => 00D000000000062EAA

func Parse

func Parse(id string, edition IdentifierEdition) (*SalesforceID, error)
Example
package main

import (
	"fmt"

	sfid "github.com/sigmavirus24/salesforceid"
)

func main() {
	id, err := sfid.Parse("00D000000000062", sfid.PostSummer23IdentifierEdition)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Printf("00D000000000062 => %s", id)
}
Output:
00D000000000062 => 00D000000000062EAA
Example (Second)
package main

import (
	"fmt"

	sfid "github.com/sigmavirus24/salesforceid"
)

func main() {
	id, err := sfid.Parse("00D000000000062", sfid.PreSummer23IdentifierEdition)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Printf("00d000000000062eaa => %s", id)
}
Output:
00d000000000062eaa => 00D000000000062EAA

func (*SalesforceID) Add

func (s *SalesforceID) Add(i uint64) (*SalesforceID, error)

Add a value to the numeric identifier and ensure the resulting identifier is valid.

func (*SalesforceID) Format

func (s *SalesforceID) Format(f Format) string

func (*SalesforceID) String

func (s *SalesforceID) String() string

func (*SalesforceID) Subtract

func (s *SalesforceID) Subtract(i uint64) (*SalesforceID, error)

Subtract a value from the numeric identifier and ensure the resulting identifier is valid.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL