SDK › profiles
Profiles
A profile is what you expect of a domain's records. Domains pin the version they were registered against, so a profile is append-only from the outside: there is no update method, and writing a key that exists creates a new version.
const { data, error } = await propgate.profiles.create({
key: "sending",
requirements: [
{ key: "ns", check: "delegation" },
{ key: "spf", check: "spf", include: "_spf.google.com" },
{ key: "dkim", check: "dkim", selector: "google" },
{ key: "dmarc", check: "dmarc" },
{ key: "mail", check: "mx", expectsMail: true },
],
});
data?.version; // 1 the first time, 2 the next time you write this keyExisting domains keep being judged by the version they hold until something
re-points them — see domains.update.
That is the whole reason versions exist: editing a profile in place would
silently re-judge every domain on it, and a customer who was verified on Tuesday
would fail on Wednesday without their DNS having changed.
See Profiles and versions for the model, and create a profile for every field a requirement takes.
Values the domain supplies
A profile states the shape; a domain can supply the value. Name a field in
requiredPerDomain and every domain registered against the profile must send
it in expectations:
await propgate.profiles.create({
key: "sending",
requirements: [
{
key: "dkim",
check: "dkim",
selector: "pg1",
// The value is issued per customer, so the domain supplies it.
requiredPerDomain: ["expectedPublicKey"],
},
// Two names, one profile: SPF and MX at a bounce host beneath the domain.
{ key: "bounce-spf", check: "spf", label: "send", include: "spf.acme.com" },
{ key: "bounce-mx", check: "mx", label: "send", expectsMail: true },
{ key: "apex-mx", check: "mx", expectsMail: false },
],
});Without this a platform with ten thousand customers needs ten thousand profiles
and the versioning stops meaning anything. label is what lets one profile
describe two names — the domain itself and a bounce host beneath it — so a
customer's setup is one registered domain and one state rather than two.
A domain registered without a required value is refused at write time, naming the path. See register a domain.
Reading one back
propgate.profiles.get() returns the current version, which is not
necessarily the one a given domain is pinned to. domain.profileVersionId is
the id that was in force when it was registered.
const { data, error } = await propgate.profiles.get("sending");
if (error?.code === "not_found") {
// No profile by that key on this account.
}Typed requirements
import type { ProfileRequirement } from "@propgate/sdk";
// `check` is the same union the evaluators use, so a typo is a compile error
// rather than a 422 you find at runtime.
const dmarc: ProfileRequirement = { key: "dmarc", check: "dmarc" };ProfileRequirement["check"] is CheckKind from
@propgate/dns — the same union the evaluators are written
against. A check kind that does not exist fails tsc rather than the request.