propgate docs

CLIprofiles

profiles

A profile is an array of up to twenty objects with nine possible fields each, which is more structure than a flag naturally carries. profiles create takes it three ways, and they exist for three different callers.

profiles create --require, for a one-liner

curl -s -X POST https://api.propgate.dev/v1/profiles \
  -H "authorization: Bearer pg_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H 'content-type: application/json' -d '{
    "key": "sending",
    "requirements": [
      { "key": "ns", "check": "delegation" },
      { "key": "spf", "check": "spf", "include": "_spf.google.com" },
      {
        "key": "dkim",
        "check": "dkim",
        "selector": "google",
        "requiredPerDomain": ["expectedPublicKey"]
      },
      { "key": "dmarc", "check": "dmarc" },
      { "key": "mail", "check": "mx", "expectsMail": true }
    ]
  }'
Created sending.

sending  version 1

  ns     delegation
  spf    spf         include=_spf.google.com
  dkim   dkim        selector=google, per domain: expectedPublicKey
  dmarc  dmarc
  mail   mx          expectsMail=true

Each --require is <key>:<check>[:field=value,field=value], repeatable up to the twenty the API allows.

The field names are the API's own body field names, verbatim. Not --dkim-selector but selector; not --spf-include but include. That is deliberate: when the server refuses a definition it names the field, and an alias here would mean the error and the input never quite match.

CheckFields
delegationnone
spfinclude
dkimselector (required), expectedPublicKey
dmarcnone
mxexpectsMail
caacaaIssuer (required)

Every check also takes requiredPerDomain, naming a field each domain supplies rather than this profile. A DKIM key is issued per domain, so that is almost always where it belongs:

--require 'dkim:dkim:selector=google,requiredPerDomain=expectedPublicKey'

Repeat the assignment to name more than one — requiredPerDomain=selector,requiredPerDomain=expectedPublicKey — because a comma already separates fields within a --require, and a second separator to learn is worse than repeating the word. Which names are legal is the server's to say. Supplying the values is domains add --expect.

Values keep everything after the first =, so a base64 key retains its padding — a DKIM key that quietly lost its == is one that never matches for a reason nobody can see.

What is checked here, and what is not

Two rules are enforced before anything is sent: dkim needs a selector and caa needs an issuer — from this profile, or from every domain via requiredPerDomain. Deferring one still keeps the promise, just somewhere else: registration refuses a domain that supplies no value for it.

$ propgate profiles create --key sending --require 'k1:dkim'
propgate: k1: dkim needs a selector, as k1:dkim:selector=<name>, or requiredPerDomain=selector

Those two are not a second copy of the server's validation — they are the two that decide which question the guided flow asks next, so this code needs them anyway. Everything else about a valid profile stays on the server: duplicate keys, more than twenty requirements, two of a kind that may only appear once, and which field names requiredPerDomain may hold. A second implementation of a rule is a second thing that can disagree, and the API's 422 is already the better message.

profiles create --file, for something generated

propgate profiles create --file profile.json

# or from a generator, over stdin
your-generator | propgate profiles create --file -

Takes the POST /v1/profiles body exactly — { "key": …, "requirements": […] } — and - reads stdin. It carries the key too, so it is refused alongside --key and --require rather than leaving a reader to guess which wins.

No flags at all, for a person

$ propgate profiles create

│  What should this profile be called?
│  sending

│  Name this requirement
│  dkim

│  What should "dkim" check?
│  ○ delegation  ○ spf  ● dkim  ○ dmarc  ○ mx  ○ caa

│  Which DKIM selector?
│  google

│  Is the public key different for every domain?
│  ● Yes / ○ No

│  Add another requirement?
│  ● No / ○ Yes

One requirement at a time, asking only the fields that check actually has. mx offers three answers rather than a yes/no, because expectsMail is tri-state: unstated makes no claim, and false asserts the domain receives no mail — which makes a null MX correct rather than a fault.

dkim asks whether the public key differs for every domain, and defaults to yes. A profile holding one literal key is a profile that works for exactly one domain; someone reaching this prompt with ten thousand of them needs the default to be the shape that scales, and the other answer is one keypress away. Answering yes sets requiredPerDomain and skips the question about the key itself, because there is no single key to ask for.

profiles get

propgate profiles get sending

Returns the current version — the one a new registration against this key would pin to. Domains already registered keep their own version regardless. See Profiles and versions.