> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kirafin.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# POST /users migration guide — KYC/KYB required fields

> What changed in the POST /v1/users payload: every field added, changed, or removed as Portage and ACT converge on one unified field set, by user category.

export const C = {
  blue: '#2F7FE0',
  green: '#0E8A63',
  amber: '#B4690E',
  red: '#CF3030',
  muted: '#8C959F',
  surface: 'rgba(127,127,127,0.05)',
  border: 'rgba(127,127,127,0.25)',
  borderSoft: 'rgba(127,127,127,0.18)',
  mono: 'ui-monospace, SFMono-Regular, Menlo, monospace'
};

export const badgeTones = {
  new: {
    bg: C.green,
    fg: '#fff'
  },
  portage: {
    bg: C.blue,
    fg: '#fff'
  },
  act: {
    bg: C.amber,
    fg: '#fff'
  },
  removed: {
    bg: C.red,
    fg: '#fff'
  },
  na: {
    bg: C.red,
    fg: '#fff'
  },
  ok: {
    bg: C.green,
    fg: '#fff'
  }
};

export const Badge = ({tone = 'same', children}) => {
  if (tone === 'same') return <span style={{
    color: C.muted,
    fontFamily: C.mono,
    fontSize: '13px'
  }}>{children}</span>;
  const t = badgeTones[tone] || badgeTones.new;
  return <span style={{
    display: 'inline-block',
    fontFamily: C.mono,
    fontSize: '10.5px',
    fontWeight: 700,
    letterSpacing: '0.04em',
    padding: '3px 8px',
    borderRadius: '4px',
    textTransform: 'uppercase',
    whiteSpace: 'nowrap',
    background: t.bg,
    color: t.fg
  }}>{children}</span>;
};

export const pillTones = {
  new: C.green,
  changed: C.amber,
  removed: C.red,
  neutral: C.muted
};
export const Pill = ({tone = 'neutral', children}) => <span style={{
  display: 'inline-block',
  borderRadius: '20px',
  padding: '4px 12px',
  fontFamily: C.mono,
  fontSize: '12px',
  border: `1px solid ${pillTones[tone]}`,
  color: pillTones[tone],
  background: C.surface,
  margin: '0 6px 6px 0'
}}>{children}</span>;

export const Val = ({children}) => <code style={{
  fontSize: '12px',
  background: 'rgba(47,127,224,0.12)',
  color: C.blue,
  borderRadius: '3px',
  padding: '1px 5px',
  margin: '1px 3px 1px 0',
  whiteSpace: 'nowrap',
  display: 'inline-block'
}}>{children}</code>;

export const Hint = ({children}) => <em style={{
  display: 'block',
  fontSize: '12px',
  opacity: 0.6,
  fontStyle: 'italic',
  marginTop: '4px'
}}>{children}</em>;

export const FieldGroup = ({title, children}) => <div style={{
  margin: '10px 0 26px'
}}>
    <div style={{
  fontFamily: C.mono,
  fontSize: '12px',
  fontWeight: 700,
  letterSpacing: '0.08em',
  textTransform: 'uppercase',
  opacity: 0.6,
  padding: '6px 0',
  borderBottom: `1px solid ${C.border}`,
  marginBottom: '4px'
}}>{title}</div>
    {children}
  </div>;

export const FieldRow = ({name, cond, badge, children}) => <div style={{
  display: 'grid',
  gridTemplateColumns: 'minmax(180px, 1.4fr) 150px minmax(180px, 2fr)',
  gap: '12px',
  alignItems: 'start',
  padding: '9px 0',
  borderBottom: `1px solid ${C.borderSoft}`
}}>
    <div style={{
  fontFamily: C.mono,
  fontSize: '13px',
  color: C.blue,
  lineHeight: 1.5
}}>{name}{cond ? <em style={{
  display: 'block',
  fontStyle: 'italic',
  fontSize: '12px',
  opacity: 0.65,
  fontFamily: 'inherit'
}}>{cond}</em> : null}</div>
    <div>{badge}</div>
    <div style={{
  fontSize: '13px',
  opacity: 0.9,
  lineHeight: 1.6
}}>{children}</div>
  </div>;

export const Subsection = ({children}) => <div style={{
  fontWeight: 700,
  fontSize: '16px',
  padding: '14px 0 8px',
  margin: '20px 0 8px',
  borderTop: `2px solid ${C.amber}`
}}>{children}</div>;

export const Chip = ({tone = 'edd', children}) => {
  const map = {
    blocked: {
      bg: 'rgba(207,34,46,0.10)',
      fg: C.red,
      bd: 'rgba(207,34,46,0.35)'
    },
    edd: {
      bg: 'rgba(180,105,14,0.12)',
      fg: C.amber,
      bd: 'rgba(180,105,14,0.35)'
    }
  };
  const c = map[tone] || map.edd;
  return <span style={{
    fontFamily: C.mono,
    fontSize: '11px',
    padding: '3px 8px',
    borderRadius: '4px',
    border: `1px solid ${c.bd}`,
    color: c.fg,
    background: c.bg,
    whiteSpace: 'nowrap',
    display: 'inline-block',
    margin: '3px 4px 0 0'
  }}>{children}</span>;
};

export const ChipGrid = ({items, tone}) => <div style={{
  display: 'flex',
  flexWrap: 'wrap',
  padding: '4px 0 8px'
}}>{items.map(x => <Chip key={x} tone={tone}>{x}</Chip>)}</div>;

export const DiffWrap = ({children}) => <div style={{
  display: 'flex',
  flexWrap: 'wrap',
  gap: '1px',
  border: `1px solid ${C.border}`,
  borderRadius: '8px',
  overflow: 'hidden',
  margin: '16px 0',
  background: C.border
}}>{children}</div>;

export const DiffCol = ({title, tone, children}) => <div style={{
  flex: '1 1 300px',
  minWidth: '260px',
  background: C.surface
}}>
    <div style={{
  display: 'flex',
  alignItems: 'center',
  gap: '8px',
  padding: '9px 14px',
  fontSize: '12px',
  fontWeight: 700,
  letterSpacing: '0.06em',
  borderBottom: `1px solid ${C.border}`
}}>
      <span style={{
  width: '7px',
  height: '7px',
  borderRadius: '50%',
  background: tone === 'after' ? C.green : C.red
}} />{title}
    </div>
    <div style={{
  padding: '10px 0',
  fontFamily: C.mono,
  fontSize: '12px',
  lineHeight: 1.9,
  overflowX: 'auto'
}}>{children}</div>
  </div>;

export const L = ({tone = 'neutral', children}) => {
  const c = tone === 'add' ? {
    color: C.green,
    background: 'rgba(11,110,79,0.12)'
  } : tone === 'rem' ? {
    color: C.red,
    background: 'rgba(207,34,46,0.10)'
  } : {
    opacity: 0.85
  };
  return <div style={{
    whiteSpace: 'pre',
    padding: '1px 14px',
    ...c
  }}>{children}</div>;
};

export const VLine = ({h = 18, dashed = false}) => <div style={{
  width: dashed ? '0' : '1.5px',
  height: `${h}px`,
  margin: '0 auto',
  borderLeft: dashed ? `1.5px dashed ${C.border}` : 'none',
  background: dashed ? 'none' : C.border
}} />;

export const Fork = () => <div style={{
  position: 'relative',
  height: '20px',
  width: '100%'
}}>
    <div style={{
  position: 'absolute',
  top: 0,
  left: '25%',
  right: '25%',
  height: '1.5px',
  background: C.border
}} />
    <div style={{
  position: 'absolute',
  top: 0,
  left: 'calc(25% - 0.75px)',
  width: '1.5px',
  height: '20px',
  background: C.border
}} />
    <div style={{
  position: 'absolute',
  top: 0,
  left: 'calc(75% - 0.75px)',
  width: '1.5px',
  height: '20px',
  background: C.border
}} />
  </div>;

export const TNode = ({tone = 'blue', title, sub, dashed = false}) => {
  const col = C[tone] || C.blue;
  return <div style={{
    border: `1.5px ${dashed ? 'dashed' : 'solid'} ${col}`,
    borderRadius: '8px',
    padding: '10px 14px',
    textAlign: 'center',
    background: C.surface
  }}>
      <div style={{
    fontFamily: C.mono,
    fontWeight: 700,
    fontSize: '12px',
    color: col
  }}>{title}</div>
      {sub ? <div style={{
    fontSize: '12px',
    opacity: 0.7,
    marginTop: '4px'
  }}>{sub}</div> : null}
    </div>;
};

export const Diamond = ({children}) => <div style={{
  clipPath: 'polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%)',
  background: 'rgba(180,105,14,0.18)',
  color: C.amber,
  fontFamily: C.mono,
  fontWeight: 700,
  fontSize: '13px',
  width: '300px',
  maxWidth: '90%',
  minHeight: '84px',
  display: 'flex',
  alignItems: 'center',
  justifyContent: 'center',
  textAlign: 'center',
  margin: '0 auto',
  padding: '0 24px'
}}>{children}</div>;

export const TreePanel = ({label, tone, children}) => <div style={{
  flex: '1 1 320px',
  minWidth: '280px',
  background: C.surface,
  border: `1px solid ${C.border}`,
  borderRadius: '8px',
  padding: '20px'
}}>
    <div style={{
  fontFamily: C.mono,
  fontSize: '12px',
  fontWeight: 700,
  letterSpacing: '0.08em',
  textTransform: 'uppercase',
  color: C[tone],
  marginBottom: '14px'
}}>{label}</div>
    <div style={{
  display: 'flex',
  flexDirection: 'column',
  alignItems: 'stretch',
  maxWidth: '720px',
  margin: '0 auto'
}}>{children}</div>
  </div>;

export const BLOCKED = ['🇦🇫 AFG', '🇧🇾 BLR', '🇲🇲 MMR', '🇨🇫 CAF', '🇨🇮 CIV', '🇨🇺 CUB', '🇨🇩 COD', '🇮🇷 IRN', '🇮🇶 IRQ', '🇱🇷 LBR', '🇱🇾 LBY', '🇰🇵 PRK', '🇷🇺 RUS', '🇸🇦 SAU', '🇸🇴 SOM', '🇸🇩 SDN', '🇸🇾 SYR', '🇺🇦 UKR', '🇾🇪 YEM', '🇻🇪 VEN', '🇿🇼 ZWE'];
export const EDD_IND = ['🇩🇿 DZA', '🇦🇴 AGO', '🇦🇲 ARM', '🇦🇿 AZE', '🇧🇸 BHS', '🇧🇭 BHR', '🇧🇩 BGD', '🇧🇲 BMU', '🇧🇴 BOL', '🇻🇬 VGB', '🇧🇳 BRN', '🇧🇫 BFA', '🇰🇭 KHM', '🇨🇲 CMR', '🇨🇽 CXR', '🇨🇨 CCK', '🇨🇷 CRI', '🇨🇾 CYP', '🇪🇬 EGY', '🇸🇻 SLV', '🇬🇮 GIB', '🇬🇷 GRC', '🇬🇹 GTM', '🇬🇬 GGY', '🇭🇹 HTI', '🇭🇳 HND', '🇮🇩 IDN', '🇮🇲 IMN', '🇯🇪 JEY', '🇯🇴 JOR', '🇰🇿 KAZ', '🇰🇪 KEN', '🇰🇼 KWT', '🇱🇧 LBN', '🇱🇮 LIE', '🇲🇾 MYS', '🇲🇨 MCO', '🇲🇳 MNG', '🇲🇿 MOZ', '🇳🇮 NIC', '🇳🇬 NGA', '🇴🇲 OMN', '🇵🇬 PNG', '🇵🇾 PRY', '🇵🇭 PHL', '🇿🇦 ZAF', '🇱🇰 LKA', '🇹🇭 THA', '🇹🇹 TTO', '🇹🇳 TUN', '🇺🇬 UGA', '🇺🇿 UZB', '🇻🇳 VNM'];
export const EDD_BIZ = EDD_IND.filter(s => !s.includes('GTM') && !s.includes('CCK'));

<div style={{ paddingBottom: '22px', borderBottom: `1px solid ${C.border}`, marginBottom: '8px' }}>
  <div style={{ fontFamily: C.mono, fontSize: '12px', letterSpacing: '0.08em', textTransform: 'uppercase', color: C.amber, marginBottom: '10px' }}>Migration guide · Virtual accounts</div>
  <p style={{ opacity: 0.85, maxWidth: '640px', marginBottom: '18px' }}>Portage and ACT previously required different payloads. <strong>The products converge on one unified field set</strong> — one correctly filled <code>POST /v1/users</code> body covers everything. This guide lists every field that was added, changed, or removed.</p>
  <div><Pill tone="new">+13 new fields</Pill><Pill tone="changed">20 fields unified across banks</Pill><Pill tone="removed">2 fields removed</Pill><Pill tone="neutral">4 user categories</Pill></div>
</div>

<Note>
  This is the **migration changelog** — what moved and why. For the canonical, version-accurate field reference (enums aligned to the live spec), see [Creating users](/guides/creating-users) and the [Create a user](/api-reference/users/create-a-user) API reference. The authoritative per-user "what's still missing" list is always the `missing_fields` map on `GET /v1/users/{id}`.
</Note>

## Badge key

<div style={{ display: 'flex', flexWrap: 'wrap', gap: '10px 20px', alignItems: 'center', padding: '14px 16px', border: `1px solid ${C.border}`, borderRadius: '8px', margin: '8px 0 4px', fontSize: '12px' }}>
  <span style={{ display: 'flex', alignItems: 'center', gap: '7px' }}><Badge tone="new">new</Badge> didn't exist before — add it</span>
  <span style={{ display: 'flex', alignItems: 'center', gap: '7px' }}><Badge tone="portage">was Portage only</Badge> ACT users: add this field</span>
  <span style={{ display: 'flex', alignItems: 'center', gap: '7px' }}><Badge tone="act">was ACT only</Badge> Portage users: add this field</span>
  <span style={{ display: 'flex', alignItems: 'center', gap: '7px' }}><Badge tone="removed">removed</Badge> no longer required</span>
  <span style={{ display: 'flex', alignItems: 'center', gap: '7px' }}><Badge tone="na">N/A</Badge> not applicable for this category</span>
  <span style={{ display: 'flex', alignItems: 'center', gap: '7px' }}><Badge tone="same">—</Badge> no change needed</span>
</div>

## What changed per bank

Pick the bank you integrated with before. The right-hand column is the unified payload you send now.

<Tabs>
  <Tab title="🏦 I used Portage">
    <DiffWrap>
      <DiffCol title="Before — Portage individual" tone="before">
        <L>
          {'{'}
        </L>

        <L>
          {'  "type": "individual",'}
        </L>

        <L>
          {'  "first_name": "Ana",'}
        </L>

        <L>
          {'  "address_country": "USA",'}
        </L>

        <L>
          {'  "employment_status": "employed",'}
        </L>

        <L>
          {'  "account_purpose": "receive_payments",'}
        </L>

        <L>
          {'  "document_country": "USA",'}
        </L>

        <L tone="rem">
          {'  // ✗ no expected_monthly_volume'}
        </L>

        <L tone="rem">
          {'  // ✗ no expected_transaction_count'}
        </L>

        <L tone="rem">
          {'  // ✗ no current_employer'}
        </L>

        <L tone="rem">
          {'  // ✗ no income_source'}
        </L>

        <L>
          {'}'}
        </L>
      </DiffCol>

      <DiffCol title="After — unified individual" tone="after">
        <L>
          {'{'}
        </L>

        <L>
          {'  "type": "individual",'}
        </L>

        <L>
          {'  "first_name": "Ana",'}
        </L>

        <L>
          {'  "address_country": "USA",'}
        </L>

        <L>
          {'  "document_country": "USA",'}
        </L>

        <L>
          {'  "employment_status": "employed",'}
        </L>

        <L>
          {'  "account_purpose": "receive_payments",'}
        </L>

        <L tone="add">
          {'  "expected_monthly_volume": "10000_to_49999",'}
        </L>

        <L tone="add">
          {'  "expected_transaction_count": "11_to_50",'}
        </L>

        <L tone="add">
          {'  "current_employer": "Acme Corp",'}
        </L>

        <L>
          {'  "occupation": "Engineer",'}
        </L>

        <L>
          {'}'}
        </L>
      </DiffCol>
    </DiffWrap>
  </Tab>

  <Tab title="🏦 I used ACT">
    <DiffWrap>
      <DiffCol title="Before — ACT individual" tone="before">
        <L>
          {'{'}
        </L>

        <L>
          {'  "type": "individual",'}
        </L>

        <L>
          {'  "first_name": "Ana",'}
        </L>

        <L>
          {'  "address_country": "USA",'}
        </L>

        <L>
          {'  "document_country": "MEX",'}
        </L>

        <L>
          {'  "employment_status": "employed",'}
        </L>

        <L>
          {'  "immigration_status": "Non-Resident of U.S.",'}
        </L>

        <L tone="rem">
          {'  // ✗ no account_purpose'}
        </L>

        <L tone="rem">
          {'  // ✗ no expected_monthly_volume'}
        </L>

        <L tone="rem">
          {'  // ✗ no expected_transaction_count'}
        </L>

        <L tone="rem">
          {'  // ✗ no income_source'}
        </L>

        <L>
          {'}'}
        </L>
      </DiffCol>

      <DiffCol title="After — unified individual" tone="after">
        <L>
          {'{'}
        </L>

        <L>
          {'  "type": "individual",'}
        </L>

        <L>
          {'  "first_name": "Ana",'}
        </L>

        <L>
          {'  "address_country": "USA",'}
        </L>

        <L>
          {'  "document_country": "MEX",'}
        </L>

        <L>
          {'  "employment_status": "employed",'}
        </L>

        <L tone="add">
          {'  "account_purpose": "receive_payments",'}
        </L>

        <L tone="add">
          {'  "expected_monthly_volume": "10000_to_49999",'}
        </L>

        <L tone="add">
          {'  "expected_transaction_count": "11_to_50",'}
        </L>

        <L tone="add">
          {'  "current_employer": "Acme Corp",'}
        </L>

        <L>
          {'  "occupation": "Engineer",'}
        </L>

        <L>
          {'}'}
        </L>
      </DiffCol>
    </DiffWrap>
  </Tab>
</Tabs>

## How the user category is determined

Two fields drive the required set: `type` and `address_country`. The combination produces one of four categories.

<div style={{ display: 'flex', flexDirection: 'column', gap: '14px', margin: '16px 0' }}>
  <TreePanel label="KYC — type: &#x22;individual&#x22;" tone="blue">
    <TNode tone="blue" title="type: &#x22;individual&#x22;" />

    <VLine />

    <Diamond>address\_country?</Diamond>

    <VLine h={14} />

    <Fork />

    <div style={{ display: 'flex', gap: '12px' }}>
      <div style={{ flex: 1 }}>
        <div style={{ textAlign: 'center', fontFamily: C.mono, fontSize: '12px', fontWeight: 600, opacity: 0.7, marginBottom: '6px' }}>= USA</div>

        <TNode tone="blue" title="usa_individual" sub="Standard + SSN + photos" />
      </div>

      <div style={{ flex: 1 }}>
        <div style={{ textAlign: 'center', fontFamily: C.mono, fontSize: '12px', fontWeight: 600, opacity: 0.7, marginBottom: '6px' }}>≠ USA</div>

        <TNode tone="green" title="international_individual" sub="+ immigration_status, + bank flags" />

        <VLine dashed h={14} />

        <TNode tone="amber" title="+ POA if EDD country" dashed />
      </div>
    </div>
  </TreePanel>

  <TreePanel label="KYB — type: &#x22;business&#x22;" tone="green">
    <TNode tone="green" title="type: &#x22;business&#x22;" />

    <VLine />

    <Diamond>address\_country?</Diamond>

    <VLine h={14} />

    <Fork />

    <div style={{ display: 'flex', gap: '12px' }}>
      <div style={{ flex: 1 }}>
        <div style={{ textAlign: 'center', fontFamily: C.mono, fontSize: '12px', fontWeight: 600, opacity: 0.7, marginBottom: '6px' }}>= USA</div>

        <TNode tone="blue" title="usa_business" sub="EIN + state + UBO photos" />
      </div>

      <div style={{ flex: 1 }}>
        <div style={{ textAlign: 'center', fontFamily: C.mono, fontSize: '12px', fontWeight: 600, opacity: 0.7, marginBottom: '6px' }}>≠ USA</div>

        <TNode tone="green" title="international_business" sub="No EIN/state, + entity type + flags" />
      </div>
    </div>

    <VLine dashed h={14} />

    <TNode tone="amber" title="+ POA if EDD trigger (both)" sub="address/formation country in list OR company ≤ 180 days" dashed />
  </TreePanel>
</div>

## Required fields

Select the user type to see every required field, its accepted values, and what changed per bank.

<Note>
  The per-bank badges for the **identity and document fields tracked by the live `missing_fields` map** (`document_country`, the document photos, `immigration_status`, `additional_info`, `employment_status`) are reconciled against that map. Provenance for the **questionnaire fields** (`account_purpose`, `expected_*`, `current_employer`, `income_source`) and for the **KYB section** is illustrative — those fields aren't tracked by the map, so always confirm against `GET /v1/users/{id}` → `missing_fields`.
</Note>

<Tabs>
  <Tab title="👤 KYC — Individual">
    Category is set by `address_country`: `"USA"` → usa\_individual, anything else → international\_individual.

    <Subsection>🇺🇸 USA Individual</Subsection>

    <FieldGroup title="Identity">
      <FieldRow name="first_name · last_name" badge={<Badge tone="same">—</Badge>}>Free text</FieldRow>
      <FieldRow name="birth_date" badge={<Badge tone="same">—</Badge>}>ISO 8601 — e.g. <Val>1990-01-15</Val></FieldRow>
      <FieldRow name="email · phone" badge={<Badge tone="same">—</Badge>}>Email string · phone string</FieldRow>
      <FieldRow name="nationality" badge={<Badge tone="same">—</Badge>}>ISO alpha-3 — e.g. <Val>USA</Val> <Val>MEX</Val> <Val>COL</Val></FieldRow>
      <FieldRow name="address_street · address_city · address_state · address_zip_code · address_country" badge={<Badge tone="same">—</Badge>}>Free text; <code>address\_country</code> = ISO alpha-3</FieldRow>
      <FieldRow name="document_type · document_number" badge={<Badge tone="same">—</Badge>}><Val>passport</Val> <Val>drivers\_license</Val> <Val>national\_id</Val></FieldRow>
      <FieldRow name="document_country" badge={<Badge tone="same">—</Badge>}>ISO alpha-3<Hint>Required by both Portage and ACT (per the live missing\_fields map)</Hint></FieldRow>
      <FieldRow name="ssn" cond="unless immigration_status = non-US citizen" badge={<Badge tone="same">—</Badge>}>Sent as <Val>{'identifying_information: [{type:"ssn", number:"..."}]'}</Val></FieldRow>
      <FieldRow name="identifying_information: front" badge={<Badge tone="portage">was Portage only</Badge>}>Document photo<Hint>Portage required it; ACT did not — now required for all banks</Hint></FieldRow>
      <FieldRow name="identifying_information: back" cond="unless document_type = passport" badge={<Badge tone="portage">was Portage only</Badge>}>Document photo<Hint>Portage required it; ACT did not — now required for all banks</Hint></FieldRow>
    </FieldGroup>

    <FieldGroup title="Questionnaire — virtualAccountsKycQ">
      <FieldRow name="account_purpose" badge={<Badge tone="portage">was Portage only</Badge>}><Val>receive\_payments</Val> <Val>manage\_professional\_income</Val> <Val>make\_payments</Val> <Val>manage\_personal\_funds</Val> <Val>investment\_trading</Val><Hint>Was excluded for ACT individuals — now required for all banks</Hint></FieldRow>
      <FieldRow name="employment_status" badge={<Badge tone="act">was ACT only</Badge>}><Val>employed</Val> <Val>self\_employed</Val> <Val>unemployed</Val> <Val>retired</Val> <Val>student</Val><Hint>ACT required it; Portage did not — now required for all banks</Hint></FieldRow>
      <FieldRow name="expected_monthly_volume" badge={<Badge tone="new">new</Badge>}><Val>less\_than\_10000</Val> <Val>10000\_to\_49999</Val> <Val>50000\_to\_199999</Val> <Val>200000\_to\_999999</Val> <Val>1000000\_or\_more</Val></FieldRow>
      <FieldRow name="expected_transaction_count" badge={<Badge tone="new">new</Badge>}><Val>1\_to\_10</Val> <Val>11\_to\_50</Val> <Val>51\_to\_200</Val> <Val>more\_than\_200</Val></FieldRow>
      <FieldRow name="occupation" cond="when employment_status = employed" badge={<Badge tone="same">—</Badge>}>Free text</FieldRow>
      <FieldRow name="current_employer" cond="when employment_status = employed" badge={<Badge tone="act">was ACT only</Badge>}>Free text<Hint>Was ACT-only — now required for all banks</Hint></FieldRow>
      <FieldRow name="income_source" cond="unless employment_status = employed" badge={<Badge tone="new">new</Badge>}>Free text — required for <Val>retired</Val> <Val>student</Val> <Val>unemployed</Val> <Val>self\_employed</Val></FieldRow>
    </FieldGroup>

    <FieldGroup title="EDD — only when address_country is in the EDD individual list">
      <FieldRow name="identifying_information: file_proof_of_address" cond="when address_country ∈ EDD list" badge={<Badge tone="portage">was Portage only</Badge>}>Proof of address document<Hint>Portage required it at base; for ACT and the unified flow it's required under EDD</Hint></FieldRow>
    </FieldGroup>

    <Subsection>🌎 International Individual</Subsection>

    <Info>All fields from **USA Individual** apply. The differences are listed below.</Info>

    <FieldGroup title="Differences from USA Individual">
      <FieldRow name="ssn" badge={<Badge tone="na">N/A</Badge>}>Not required for international individuals</FieldRow>
      <FieldRow name="immigration_status" badge={<Badge tone="act">was ACT only</Badge>}>Common values: <Val>U.S. Citizen</Val> <Val>Permanent U.S. Resident</Val> <Val>Non-Permanent U.S. Resident</Val> <Val>Non-Resident of U.S.</Val><Hint>Free text — these are the common values but not a strict enum</Hint></FieldRow>
      <FieldRow name="additional_info: has_us_bank_account" badge={<Badge tone="act">was ACT only</Badge>}><Val>Yes</Val> <Val>No</Val><Hint>Was ACT-only — now required for all banks</Hint></FieldRow>
      <FieldRow name="additional_info: has_denied_bank_account" badge={<Badge tone="act">was ACT only</Badge>}><Val>Yes</Val> <Val>No</Val><Hint>Was ACT-only — now required for all banks</Hint></FieldRow>
    </FieldGroup>
  </Tab>

  <Tab title="🏢 KYB — Business">
    Category is set by `address_country`: `"USA"` → usa\_business, anything else → international\_business.

    <Subsection>🇺🇸 USA Business</Subsection>

    <FieldGroup title="Entity identity">
      <FieldRow name="business_legal_name" badge={<Badge tone="same">—</Badge>}>Free text</FieldRow>
      <FieldRow name="business_type" badge={<Badge tone="same">—</Badge>}><Val>limited\_liability\_company</Val> <Val>corporation</Val> <Val>general\_partnership</Val> <Val>limited\_liability\_partnership</Val> <Val>sole\_proprietor</Val> <Val>non\_profit</Val> <Val>trust</Val> <Val>government\_organization</Val> <Val>publicly\_traded\_company</Val></FieldRow>
      <FieldRow name="formation_date" badge={<Badge tone="same">—</Badge>}>ISO 8601 — e.g. <Val>2019-03-01</Val></FieldRow>
      <FieldRow name="formation_country" badge={<Badge tone="portage">was Portage only</Badge>}>ISO alpha-3<Hint>Was missing in Portage — now required for all banks</Hint></FieldRow>
      <FieldRow name="email · phone" badge={<Badge tone="act">was ACT only</Badge>}>Email · phone string<Hint>phone was missing in ACT</Hint></FieldRow>
      <FieldRow name="address_street · address_city · address_state · address_zip_code · address_country" badge={<Badge tone="portage">was Portage only</Badge>}>Free text; country = ISO alpha-3<Hint>address\_state was missing in Portage</Hint></FieldRow>
      <FieldRow name="ein" badge={<Badge tone="same">—</Badge>}>Sent as <Val>{'identifying_information: [{type:"ein", number:"..."}]'}</Val></FieldRow>
      <FieldRow name="identifying_information: file_business_formation" badge={<Badge tone="act">was ACT only</Badge>}>Business formation document<Hint>Was missing in ACT — now required for all banks</Hint></FieldRow>
      <FieldRow name="doing_business_as" badge={<Badge tone="removed">removed</Badge>}>No longer required</FieldRow>
    </FieldGroup>

    <FieldGroup title="Questionnaire — virtualAccountsKybQ (mostly new)">
      <FieldRow name="account_purpose" badge={<Badge tone="same">—</Badge>}><Val>charitable\_donations</Val> <Val>ecommerce\_retail\_payments</Val> <Val>investment\_purposes</Val> <Val>purchase\_goods\_and\_services</Val> <Val>receive\_payments\_for\_goods\_and\_services</Val> <Val>internal\_treasury</Val> <Val>third\_party\_money\_transmission</Val></FieldRow>
      <FieldRow name="business_industry" badge={<Badge tone="act">was ACT only</Badge>}>NAICS codes — e.g. <Val>telecommunications</Val> <Val>real\_estate</Val> <Val>food\_manufacturing</Val><Hint>Was missing in ACT — now required for all banks</Hint></FieldRow>
      <FieldRow name="business_description" badge={<Badge tone="new">new</Badge>}>Free text</FieldRow>
      <FieldRow name="source_of_funds" badge={<Badge tone="new">new</Badge>}><Val>business\_loans</Val> <Val>inter\_company\_funds</Val> <Val>investment\_proceeds</Val> <Val>owners\_capital</Val> <Val>sales\_of\_goods\_and\_services</Val> <Val>tax\_refund</Val> <Val>third\_party\_funds</Val> <Val>treasury\_reserves</Val></FieldRow>
      <FieldRow name="high_risk_industries" badge={<Badge tone="new">new</Badge>}><Val>Yes</Val> <Val>No</Val></FieldRow>
      <FieldRow name="is_nbfi_vasp" badge={<Badge tone="new">new</Badge>}><Val>Yes</Val> <Val>No</Val></FieldRow>
      <FieldRow name="business_legal_history" badge={<Badge tone="new">new</Badge>}><Val>Yes</Val> <Val>No</Val></FieldRow>
      <FieldRow name="pep_status" badge={<Badge tone="new">new</Badge>}><Val>true</Val> <Val>false</Val> (boolean)</FieldRow>
      <FieldRow name="expected_monthly_volume" badge={<Badge tone="new">new</Badge>}><Val>less\_than\_50000</Val> <Val>50000\_to\_100000</Val> <Val>100000\_to\_500000</Val> <Val>500000\_to\_1000000</Val> <Val>1000000\_to\_5000000</Val> <Val>5000000\_to\_10000000</Val> <Val>more\_than\_10000000</Val></FieldRow>
      <FieldRow name="expected_transaction_count" badge={<Badge tone="new">new</Badge>}><Val>less\_than\_10</Val> <Val>10\_to\_25</Val> <Val>26\_to\_50</Val> <Val>51\_to\_100</Val> <Val>101\_to\_500</Val> <Val>more\_than\_500</Val></FieldRow>
    </FieldGroup>

    <FieldGroup title="Associated persons — UBOs & directors">
      <FieldRow name="associated_persons" badge={<Badge tone="same">—</Badge>}>Array of UBO/director objects</FieldRow>
      <FieldRow name="associated_persons: first_name · last_name" badge={<Badge tone="portage">was Portage only</Badge>}>Free text<Hint>Was missing in Portage</Hint></FieldRow>
      <FieldRow name="associated_persons: birth_date" badge={<Badge tone="portage">was Portage only</Badge>}>ISO 8601<Hint>Was missing in Portage</Hint></FieldRow>
      <FieldRow name="associated_persons: email" badge={<Badge tone="portage">was Portage only</Badge>}>Valid email<Hint>Was missing in Portage</Hint></FieldRow>
      <FieldRow name="associated_persons: nationality" badge={<Badge tone="portage">was Portage only</Badge>}>ISO alpha-3<Hint>Was missing in Portage</Hint></FieldRow>
      <FieldRow name="associated_persons: ssn" cond="unless nationality = non-US" badge={<Badge tone="portage">was Portage only</Badge>}>SSN string<Hint>Was missing in Portage</Hint></FieldRow>
      <FieldRow name="associated_persons: document_type" badge={<Badge tone="new">new</Badge>}>Free text</FieldRow>
      <FieldRow name="associated_persons: document_number" badge={<Badge tone="portage">was Portage only</Badge>}>Free text<Hint>Was missing in Portage</Hint></FieldRow>
      <FieldRow name="associated_persons: identifying_information: front" badge={<Badge tone="act">was ACT only</Badge>}>Document photo<Hint>Was missing in ACT</Hint></FieldRow>
      <FieldRow name="associated_persons: identifying_information: back" cond="unless document_type = passport" badge={<Badge tone="act">was ACT only</Badge>}>Document photo<Hint>Was missing in ACT</Hint></FieldRow>
    </FieldGroup>

    <FieldGroup title="EDD — only when an EDD trigger applies">
      <FieldRow name="identifying_information: file_proof_of_address" cond="address/formation country in EDD list OR company ≤ 180 days" badge={<Badge tone="new">new</Badge>}>Proof of address document</FieldRow>
    </FieldGroup>

    <Subsection>🌎 International Business</Subsection>

    <Info>All fields from **USA Business** apply. The differences are listed below.</Info>

    <FieldGroup title="Differences from USA Business">
      <FieldRow name="ein" badge={<Badge tone="na">N/A</Badge>}>Not required for international entities</FieldRow>
      <FieldRow name="address_state" badge={<Badge tone="ok">required</Badge>}>Still required for international entities — state / province / department of the business address</FieldRow>
      <FieldRow name="document_number" badge={<Badge tone="ok">required</Badge>}>Required for international entities — free text</FieldRow>
      <FieldRow name="document_country" badge={<Badge tone="new">new</Badge>}>ISO alpha-3</FieldRow>
      <FieldRow name="international_entity_type" badge={<Badge tone="act">was ACT only</Badge>}>Free text<Hint>Was ACT-only — now required for all banks</Hint></FieldRow>
      <FieldRow name="additional_info: has_us_bank_account" badge={<Badge tone="act">was ACT only</Badge>}><Val>Yes</Val> <Val>No</Val><Hint>Was ACT-only — now required for all banks</Hint></FieldRow>
      <FieldRow name="additional_info: has_denied_bank_account" badge={<Badge tone="act">was ACT only</Badge>}><Val>Yes</Val> <Val>No</Val><Hint>Was ACT-only — now required for all banks</Hint></FieldRow>
      <FieldRow name="associated_persons: document_country" badge={<Badge tone="act">was ACT only</Badge>}>ISO alpha-3 — required for international UBOs</FieldRow>
    </FieldGroup>
  </Tab>
</Tabs>

## Conditional field rules

Some fields are only required in specific situations. Here is what each condition means.

| Condition          | What it means                                                                                                                                                                    | Example                                                                         |
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- |
| `when X = Y`       | Include the field **only** if the condition is true; otherwise omit it.                                                                                                          | `occupation` is required only when `employment_status = "employed"`             |
| `unless X = Y`     | Include the field in all cases **except** when the condition is true.                                                                                                            | `ssn` is required for everyone except non-US citizens                           |
| **EDD individual** | If `address_country` is in the EDD list (53 countries), also upload a proof-of-address document.                                                                                 | User from `MEX` → add `file_proof_of_address` to `identifying_information`      |
| **EDD business**   | Proof of address is required if **any one** is true: `address_country` in the EDD list, `formation_country` in the EDD list, or the company was formed within the last 180 days. | Company formed 3 months ago → add `file_proof_of_address` regardless of country |

## Country restrictions

All codes are ISO 3166-1 alpha-3. Rules apply to `address_country` unless otherwise noted.

<div style={{ display: 'flex', alignItems: 'flex-start', gap: '10px', padding: '12px 14px', borderRadius: '8px', border: `1px solid ${C.border}`, borderLeft: `3px solid ${C.red}`, margin: '12px 0 6px' }}>
  <span style={{ fontSize: '16px' }}>🚫</span>

  <div>
    <div style={{ fontWeight: 600, fontSize: '13px' }}>Blocked — ineligible for all virtual-account products</div>
    <div style={{ fontSize: '12px', opacity: 0.7 }}>Users with <code>address\_country</code> in this list cannot create any virtual account.</div>
  </div>
</div>

<ChipGrid items={BLOCKED} tone="blocked" />

<div style={{ display: 'flex', alignItems: 'flex-start', gap: '10px', padding: '12px 14px', borderRadius: '8px', border: `1px solid ${C.border}`, borderLeft: `3px solid ${C.amber}`, margin: '16px 0 6px' }}>
  <span style={{ fontSize: '16px' }}>⚠️</span>

  <div>
    <div style={{ fontWeight: 600, fontSize: '13px' }}>EDD countries — individual users (53 countries)</div>
    <div style={{ fontSize: '12px', opacity: 0.7 }}>When <code>address\_country</code> matches, a <strong>proof-of-address document</strong> is additionally required.</div>
  </div>
</div>

<ChipGrid items={EDD_IND} tone="edd" />

<div style={{ display: 'flex', alignItems: 'flex-start', gap: '10px', padding: '12px 14px', borderRadius: '8px', border: `1px solid ${C.border}`, borderLeft: `3px solid ${C.amber}`, margin: '16px 0 6px' }}>
  <span style={{ fontSize: '16px' }}>⚠️</span>

  <div>
    <div style={{ fontWeight: 600, fontSize: '13px' }}>EDD countries — business users (51 countries)</div>
    <div style={{ fontSize: '12px', opacity: 0.7 }}>Same list minus <code>GTM</code> and <code>CCK</code>. Applies to <code>address\_country</code> AND <code>formation\_country</code> — also triggered if the company was formed within the last 180 days.</div>
  </div>
</div>

<ChipGrid items={EDD_BIZ} tone="edd" />

<div style={{ border: `1px solid ${C.border}`, borderRadius: '8px', padding: '20px', margin: '18px 0', background: C.surface }}>
  <div style={{ fontFamily: C.mono, fontSize: '12px', fontWeight: 700, letterSpacing: '0.08em', textTransform: 'uppercase', opacity: 0.6, marginBottom: '14px' }}>EDD trigger logic — business users</div>

  <div style={{ display: 'flex', alignItems: 'center', flexWrap: 'wrap', gap: '12px' }}>
    <div style={{ display: 'flex', flexDirection: 'column', gap: '6px' }}>
      <TNode tone="amber" title="address_country ∈ EDD list" />

      <div style={{ textAlign: 'center', fontFamily: C.mono, fontSize: '12px', fontWeight: 700, opacity: 0.6 }}>OR</div>

      <TNode tone="amber" title="formation_country ∈ EDD list" />

      <div style={{ textAlign: 'center', fontFamily: C.mono, fontSize: '12px', fontWeight: 700, opacity: 0.6 }}>OR</div>

      <TNode tone="amber" title="company age ≤ 180 days" />
    </div>

    <div style={{ fontSize: '20px', opacity: 0.5 }}>→</div>

    <TNode tone="green" title="REQUIRED: file_proof_of_address" />
  </div>
</div>

## Example payloads

Complete `POST /v1/users` bodies for each category. Use the copy button and adapt for your integration; `content` fields take base64-encoded images.

<CodeGroup>
  ```json 🇺🇸 KYC Individual theme={null}
  {
    "type": "individual",
    "first_name": "Ana",
    "last_name": "García",
    "birth_date": "1990-04-22",
    "email": "ana@example.com",
    "phone": "+15551234567",
    "nationality": "USA",
    "address_street": "123 Main St",
    "address_city": "Austin",
    "address_state": "TX",
    "address_zip_code": "78701",
    "address_country": "USA",
    "document_type": "drivers_license",
    "document_number": "DL-987654321",
    "document_country": "USA",
    "employment_status": "employed",
    "occupation": "Software Engineer",
    "current_employer": "Acme Corp",
    "account_purpose": "receive_payments",
    "expected_monthly_volume": "10000_to_49999",
    "expected_transaction_count": "11_to_50",
    "identifying_information": [
      { "type": "ssn", "number": "XXX-XX-XXXX" },
      { "type": "front", "content": "<base64>" },
      { "type": "back",  "content": "<base64>" }
    ]
  }
  ```

  ```json 🌎 KYC Intl Individual theme={null}
  {
    "type": "individual",
    "first_name": "Carlos",
    "last_name": "Mendez",
    "birth_date": "1988-11-03",
    "email": "carlos@example.com",
    "phone": "+521234567890",
    "nationality": "MEX",
    "address_street": "Av. Reforma 456",
    "address_city": "Mexico City",
    "address_state": "CDMX",
    "address_zip_code": "06600",
    "address_country": "MEX",
    "document_type": "passport",
    "document_number": "G12345678",
    "document_country": "MEX",
    "immigration_status": "Non-Resident of U.S.",
    "employment_status": "self_employed",
    "income_source": "Freelance consulting",
    "account_purpose": "manage_professional_income",
    "expected_monthly_volume": "50000_to_199999",
    "expected_transaction_count": "11_to_50",
    "additional_info": {
      "has_us_bank_account": "No",
      "has_denied_bank_account": "No"
    },
    "identifying_information": [
      { "type": "front", "content": "<base64>" }
    ]
  }
  ```

  ```json 🇺🇸 KYB Business theme={null}
  {
    "type": "business",
    "business_legal_name": "Acme Payments LLC",
    "business_type": "limited_liability_company",
    "formation_date": "2019-03-15",
    "formation_country": "USA",
    "email": "ops@acme.com",
    "phone": "+15551234567",
    "address_street": "100 Commerce Blvd",
    "address_city": "Austin",
    "address_state": "TX",
    "address_zip_code": "78701",
    "address_country": "USA",
    "account_purpose": "receive_payments_for_goods_and_services",
    "business_industry": ["telecommunications"],
    "business_description": "B2B SaaS payment processing platform",
    "source_of_funds": "sales_of_goods_and_services",
    "high_risk_industries": "No",
    "is_nbfi_vasp": "No",
    "business_legal_history": "No",
    "pep_status": false,
    "expected_monthly_volume": "100000_to_500000",
    "expected_transaction_count": "101_to_500",
    "identifying_information": [
      { "type": "ein", "number": "XX-XXXXXXX" },
      { "type": "file_business_formation", "content": "<base64>" }
    ],
    "associated_persons": [
      {
        "first_name": "Jane",
        "last_name": "Smith",
        "birth_date": "1985-07-20",
        "email": "jane@acme.com",
        "nationality": "USA",
        "document_type": "passport",
        "document_number": "US123456789",
        "identifying_information": [
          { "type": "ssn", "number": "XXX-XX-XXXX" },
          { "type": "front", "content": "<base64>" }
        ]
      }
    ]
  }
  ```

  ```json 🌎 KYB Intl Business theme={null}
  {
    "type": "business",
    "business_legal_name": "Global Trade SRL",
    "business_type": "corporation",
    "formation_date": "2021-06-01",
    "formation_country": "MEX",
    "email": "admin@globaltrade.mx",
    "phone": "+521234567890",
    "address_street": "Paseo de la Reforma 222",
    "address_city": "Mexico City",
    "address_zip_code": "06600",
    "address_country": "MEX",
    "document_number": "RFC-GLO210601ABC",
    "document_country": "MEX",
    "international_entity_type": "Sociedad de Responsabilidad Limitada",
    "account_purpose": "purchase_goods_and_services",
    "business_industry": ["real_estate"],
    "business_description": "Commercial real estate transactions across Latin America",
    "source_of_funds": "sales_of_goods_and_services",
    "high_risk_industries": "No",
    "is_nbfi_vasp": "No",
    "business_legal_history": "No",
    "pep_status": false,
    "expected_monthly_volume": "500000_to_1000000",
    "expected_transaction_count": "26_to_50",
    "additional_info": {
      "has_us_bank_account": "No",
      "has_denied_bank_account": "No"
    },
    "identifying_information": [
      { "type": "file_business_formation", "content": "<base64>" }
    ],
    "associated_persons": [
      {
        "first_name": "Luis",
        "last_name": "Torres",
        "birth_date": "1979-02-14",
        "email": "luis@globaltrade.mx",
        "nationality": "MEX",
        "document_type": "passport",
        "document_number": "G98765432",
        "document_country": "MEX",
        "identifying_information": [
          { "type": "front", "content": "<base64>" }
        ]
      }
    ]
  }
  ```
</CodeGroup>

## Related

* [Creating users](/guides/creating-users) — the canonical, version-accurate required-fields reference.
* [Create a user — API reference](/api-reference/users/create-a-user) — full schema and live "Try it".
* [For AI agents](/guides/for-ai-agents) — `eligible_products` / `missing_fields` and conditional tokens.
* [Known limitations](/guides/known-limitations) — sandbox auto-verification behavior and `status` vs `verification_status`.
