{
  "title": "SFMC Developer Certification - Flashcards",
  "total_cards": 82,
  "categories": [
    "Numbers",
    "AMPscript",
    "SQL",
    "API",
    "Data Modeling",
    "Data Management",
    "Security"
  ],
  "category_counts": {
    "Numbers": 12,
    "AMPscript": 22,
    "SQL": 10,
    "API": 12,
    "Data Modeling": 10,
    "Data Management": 8,
    "Security": 8
  },
  "flashcards": [
    {
      "id": 1,
      "category": "Numbers",
      "front": "Maximum number of Populations per SFMC account?",
      "back": "3 Populations maximum. More than 3 causes significant system-wide performance degradation.",
      "memory_tip": "Three is the magic number. The doctor's office example (staff, patients, vendors) = exactly 3."
    },
    {
      "id": 2,
      "category": "Numbers",
      "front": "Contact Delete: default suppression period?",
      "back": "14 days (2 weeks) by default. Can be reduced to 0 for immediate deletion.",
      "memory_tip": "2 weeks of suppression before permanent deletion. Like a waiting period."
    },
    {
      "id": 3,
      "category": "Numbers",
      "front": "Contact Delete: maximum batch size per request?",
      "back": "1 million contacts per batch. For larger volumes, submit multiple batch requests.",
      "memory_tip": "1M per batch. 10M contacts = 10 separate batch requests."
    },
    {
      "id": 4,
      "category": "Numbers",
      "front": "LookupRows(): default maximum rows returned?",
      "back": "2,000 rows maximum. LookupOrderedRows with count < 1 also defaults to 2,000.",
      "memory_tip": "2K rows = LookupRows ceiling. Need more? Use a SQL Query Activity."
    },
    {
      "id": 5,
      "category": "Numbers",
      "front": "SQL Query Activity: auto-kill timeout?",
      "back": "30 minutes. Queries exceeding this limit are automatically terminated by SFMC.",
      "memory_tip": "30 min = half hour max. Break large queries into smaller steps."
    },
    {
      "id": 6,
      "category": "Numbers",
      "front": "Maximum SQL Query Activities per Automation Studio step?",
      "back": "20 Query Activities per step. Activities within the same step run in PARALLEL.",
      "memory_tip": "20 per step. Same step = parallel. Need sequence? = separate steps."
    },
    {
      "id": 7,
      "category": "Numbers",
      "front": "System data views (_Sent, _Open, _Click, _Bounce): maximum lookback period?",
      "back": "6 months maximum. Queries filtering on events older than 6 months return no results.",
      "memory_tip": "6-month rolling window. Data falls off automatically after 6 months."
    },
    {
      "id": 8,
      "category": "Numbers",
      "front": "Marketing Cloud OAuth v2 access token: how long is it valid?",
      "back": "Approximately 20 minutes. Store the token, reuse it, request a new one before expiry or on 401.",
      "memory_tip": "~20 minutes. Get once, use many, refresh when expired."
    },
    {
      "id": 9,
      "category": "Numbers",
      "front": "REST API maximum payload size per request?",
      "back": "4 MB maximum per REST API request payload.",
      "memory_tip": "4 MB max. Split larger payloads into multiple smaller requests."
    },
    {
      "id": 10,
      "category": "Numbers",
      "front": "Send Log DE: best practice maximum number of custom fields?",
      "back": "10 or fewer custom fields recommended for optimal send performance.",
      "memory_tip": "≤10 custom fields in the Send Log DE. More fields = slower sends."
    },
    {
      "id": 11,
      "category": "Numbers",
      "front": "SOAP API: how many records returned per batch Retrieve call?",
      "back": "2,500 records per batch (most objects). Use ContinueRequest to paginate through larger datasets.",
      "memory_tip": "2.5K per SOAP batch. Use ContinueRequest for pagination."
    },
    {
      "id": 12,
      "category": "Numbers",
      "front": "Best practice: maximum Lookup() function calls per email?",
      "back": "3 or fewer Lookup() calls per email. Each Lookup = a database query × every subscriber.",
      "memory_tip": "3 Lookups × 1M subscribers = 3M DB queries. Keep it minimal."
    },
    {
      "id": 13,
      "category": "AMPscript",
      "front": "What is the AMPscript processing order in an email?",
      "back": "1st: HTML Body → 2nd: Text Body → 3rd: Subject Line (LAST). Variables set in HTML body ARE available in the Subject Line.",
      "memory_tip": "H-T-S: 'Hungry Tigers Snack' — HTML, Text, Subject."
    },
    {
      "id": 14,
      "category": "AMPscript",
      "front": "Exclusion Script: what threshold is correct — > 0 or > 1?",
      "back": "> 0. Even ONE record in the suppression DE = exclude the subscriber. > 1 would miss subscribers with exactly one record.",
      "memory_tip": "ZERO tolerance: > 0 not > 1. Even one record means exclude."
    },
    {
      "id": 15,
      "category": "AMPscript",
      "front": "Exclusion Scripts: use @variables or personalization strings?",
      "back": "Must use personalization strings: emailaddr and _subscriberkey (no @ prefix). AMPscript @variables are NOT valid in exclusion scripts.",
      "memory_tip": "No @ in exclusion scripts. Use emailaddr not @email. Use _subscriberkey not @subKey."
    },
    {
      "id": 16,
      "category": "AMPscript",
      "front": "IIF function: which operator for comparison?",
      "back": "IIF uses = or == for comparison (not !=). Syntax: IIF(condition, true_value, false_value). IF...IS is not valid.",
      "memory_tip": "IIF(test, yes, no). Use = or == to compare. Never IF...IS."
    },
    {
      "id": 17,
      "category": "AMPscript",
      "front": "Lookup() vs LookupRows(): key difference?",
      "back": "Lookup() = returns ONE field value from the FIRST matching row. LookupRows() = returns ALL matching rows as a RowSet (max 2,000).",
      "memory_tip": "LookupROWS = ROWS plural. The 'S' = Several. Lookup = singular."
    },
    {
      "id": 18,
      "category": "AMPscript",
      "front": "LookupOrderedRows() with count parameter < 1: what happens?",
      "back": "Returns the default maximum of 2,000 rows. Count of 0 or negative is treated as 'use the max default', NOT return nothing.",
      "memory_tip": "Count < 1 = fallback to 2,000 max. Zero limit = no limit = use max."
    },
    {
      "id": 19,
      "category": "AMPscript",
      "front": "DateAdd() unit abbreviations — what are they?",
      "back": "Y=Year, M=Month, D=Day, H=Hour, MI=Minute, S=Second. Abbreviations ONLY — 'Month' as a full word is WRONG and causes errors.",
      "memory_tip": "Y-M-D-H-MI-S. Short codes only. DateAdd(Now(),1,'M') ✓ DateAdd(Now(),1,'Month') ✗"
    },
    {
      "id": 20,
      "category": "AMPscript",
      "front": "Empty() vs IsNull(): what is the difference?",
      "back": "Empty() = true for null AND empty string ''. IsNull() = true ONLY for null. Empty is more permissive.",
      "memory_tip": "Empty = null OR empty string. IsNull = ONLY null. Empty is wider."
    },
    {
      "id": 21,
      "category": "AMPscript",
      "front": "AMPscript function names and == comparisons: case sensitive?",
      "back": "Both are case-INSENSITIVE. lookup() = LOOKUP() = Lookup(). 'GOLD' == 'gold' evaluates to TRUE in AMPscript.",
      "memory_tip": "Everything case-insensitive. 'GOLD' == 'gold' = TRUE. Use CS variants for case-sensitive matching."
    },
    {
      "id": 22,
      "category": "AMPscript",
      "front": "Best practice: what to check BEFORE using a RowSet in a FOR loop?",
      "back": "Always check RowCount(@rowset) > 0 before entering a FOR loop. Prevents rendering empty HTML tags when no rows exist.",
      "memory_tip": "Check before Loop. RowCount > 0 = safe to loop. No data = no loop."
    },
    {
      "id": 23,
      "category": "AMPscript",
      "front": "FOR loop row indexing: 0-based or 1-based?",
      "back": "1-based. Row(@rows, 1) = first row. Loop structure: FOR @i = 1 TO RowCount(@rows) DO ... NEXT @i",
      "memory_tip": "AMPscript counts from 1, not 0. Row(1) = first row. Human counting."
    },
    {
      "id": 24,
      "category": "AMPscript",
      "front": "InsertDE() at send time causes 'duplicate primary key' error. Why?",
      "back": "At send time, SFMC automatically creates the DE row FIRST. InsertDE() then runs and finds the record already exists. Use UpsertDE() instead.",
      "memory_tip": "SFMC inserts first, your code runs after. UpsertDE = insert OR update. InsertDE = fails if exists."
    },
    {
      "id": 25,
      "category": "AMPscript",
      "front": "AttributeValue() function: what does it do?",
      "back": "Reads the value of a profile attribute or Sendable DE field for the current subscriber at send time. NOT a string literal.",
      "memory_tip": "AttributeValue = 'Get the ACTUAL value'. Reaches into the subscriber record at send time."
    },
    {
      "id": 26,
      "category": "AMPscript",
      "front": "Can SSJS be used in an email body?",
      "back": "NO. SSJS cannot be used in email body, subject line, or text body. Only AMPscript works inside emails. SSJS is for CloudPages and Script Activities only.",
      "memory_tip": "Email = AMPscript ONLY. SSJS = CloudPages + Script Activities. Never SSJS in email content."
    },
    {
      "id": 27,
      "category": "AMPscript",
      "front": "RedirectTo() function: when and why is it needed?",
      "back": "Required when the href attribute of a link contains AMPscript variables. Without RedirectTo(), SFMC cannot track clicks on dynamically built URLs.",
      "memory_tip": "Dynamic URL = invisible to tracker. RedirectTo() = makes it trackable."
    },
    {
      "id": 28,
      "category": "AMPscript",
      "front": "TreatAsContent() vs v(@var): what is the difference?",
      "back": "TreatAsContent(@var) EXECUTES the value as AMPscript/HTML code. v(@var) outputs the value as plain text — it does NOT execute code within it.",
      "memory_tip": "TreatAsContent = EXECUTE string as code. v(@var) = output as plain text. Key difference."
    },
    {
      "id": 29,
      "category": "AMPscript",
      "front": "ContentBlockByKey() vs ContentAreaByName(): when to use each?",
      "back": "ContentBlockByKey('externalKey') = Content Builder blocks. ContentAreaByName('folder\\\\name') = Classic Content (legacy). Different studios.",
      "memory_tip": "Content BUILDER = ContentBlockByKey. Classic CONTENT = ContentAreaByName."
    },
    {
      "id": 30,
      "category": "AMPscript",
      "front": "ADD() function: how to sum 4 values in AMPscript?",
      "back": "Nest ADD() calls: SET @total = ADD(@jan, ADD(@feb, ADD(@mar, @apr))). The + operator does NOT work for arithmetic in AMPscript. SUM() does not exist.",
      "memory_tip": "ADD() nested like Russian dolls. No + operator. No SUM(). ADD(a, ADD(b, ADD(c, d)))."
    },
    {
      "id": 31,
      "category": "AMPscript",
      "front": "MOD() function: how to create alternating row colors in a FOR loop?",
      "back": "IF MOD(@i, 2) = 1 THEN SET @color = 'Red' ELSE SET @color = 'White'. MOD returns remainder: 1=odd=Red, 0=even=White.",
      "memory_tip": "MOD(3,2)=1=odd=Red. MOD(4,2)=0=even=White. MOD = remainder = odd/even detector."
    },
    {
      "id": 32,
      "category": "AMPscript",
      "front": "ClaimRow() function: what is it used for?",
      "back": "Atomically claims a row in a DE, preventing two concurrent sends from claiming the same row. Used for unique coupon/offer distribution.",
      "memory_tip": "ClaimRow = atomic reservation. Like a ticket system — each ticket issued only once, even with concurrent sends."
    },
    {
      "id": 33,
      "category": "AMPscript",
      "front": "GetJWTByKeyName() function: what does it do?",
      "back": "Creates a JWT (JSON Web Token) using a key stored in SFMC Key Management, identified by the key's name.",
      "memory_tip": "GetJWTByKeyName = get a JWT using this Key Management entry name. Function name = exactly what it does."
    },
    {
      "id": 34,
      "category": "AMPscript",
      "front": "DataExtensionRowCount() vs RowCount(): difference?",
      "back": "DataExtensionRowCount('DE_ExternalKey') = total rows in an entire DE. RowCount(@rowset) = count rows in a LookupRows RowSet object. Different contexts.",
      "memory_tip": "DataExtensionRowCount = entire DE count. RowCount = RowSet count. DE vs RowSet."
    },
    {
      "id": 35,
      "category": "SQL",
      "front": "Is SELECT * with a JOIN allowed in SFMC SQL Query Activities?",
      "back": "NOT PERMITTED. SELECT * with a JOIN will fail in SFMC Query Activities. You must explicitly name every field you need.",
      "memory_tip": "SFMC punishes lazy SELECT * with JOINs. Name all fields explicitly. Required, not optional."
    },
    {
      "id": 36,
      "category": "SQL",
      "front": "LIKE vs = for pattern matching in SFMC SQL?",
      "back": "LIKE for pattern matching with wildcard %: WHERE EmailName LIKE 'TEST%'. Using = 'TEST%' would look for the LITERAL name 'TEST%'.",
      "memory_tip": "LIKE = pattern match. = means EXACT. 'TEST%' with LIKE = starts with TEST. With = it's literal."
    },
    {
      "id": 37,
      "category": "SQL",
      "front": "What is the correct T-SQL function for current date/time in SFMC SQL?",
      "back": "GETDATE(). SFMC uses Microsoft SQL Server T-SQL dialect. NOW() is MySQL and AMPscript — NOT valid in SFMC SQL.",
      "memory_tip": "T-SQL = GETDATE(). MySQL = NOW(). AMPscript = Now(). SFMC SQL = T-SQL = GETDATE()."
    },
    {
      "id": 38,
      "category": "SQL",
      "front": "Does the _Bounce data view contain an EmailAddress field?",
      "back": "NO. _Bounce has no EmailAddress field. Contains SubscriberKey, SubscriberID, JobID, EventDate, BounceCategory, SMTPBounceReason. Join on SubscriberID.",
      "memory_tip": "_Bounce = address was REJECTED. SFMC doesn't store it. Join on SubscriberKey or SubscriberID."
    },
    {
      "id": 39,
      "category": "SQL",
      "front": "SQL for most recent click date per subscriber?",
      "back": "SELECT SubscriberKey, MAX(EventDate) AS MostRecentClick FROM _Click GROUP BY SubscriberKey. MAX = most recent. MIN = oldest.",
      "memory_tip": "MAX = most recent (largest date). MIN = oldest. Bigger date value = more recent event."
    },
    {
      "id": 40,
      "category": "SQL",
      "front": "Anti-join pattern in SFMC SQL: how to find subscribers NOT in another table?",
      "back": "LEFT JOIN [table] ON [key] WHERE [joined_table.key] IS NULL. Returns rows from the left table with NO matching row in the right table.",
      "memory_tip": "LEFT JOIN + WHERE IS NULL = 'everyone with NO match'. Get all, filter for nulls = non-matches."
    },
    {
      "id": 41,
      "category": "SQL",
      "front": "Random sample query pattern in SFMC SQL?",
      "back": "SELECT TOP [N] PERCENT [fields] FROM [DE] ORDER BY NEWID(). NEWID() generates a random GUID per row creating a random order.",
      "memory_tip": "NEWID() randomizes order. TOP PERCENT takes first N%. Without ORDER BY NEWID() = NOT random."
    },
    {
      "id": 42,
      "category": "SQL",
      "front": "ENT. prefix in SQL: when is it needed?",
      "back": "Required in SQL FROM clause to access a Parent/Enterprise BU shared DE from a child BU: FROM ent.SharedDEName. NOT required in AMPscript LookupRows.",
      "memory_tip": "ENT. = Enterprise parent. SQL needs it. AMPscript LookupRows does NOT need ENT."
    },
    {
      "id": 43,
      "category": "SQL",
      "front": "LEFT() function in SFMC SQL: what does it do?",
      "back": "LEFT(columnName, n) returns the first n characters from the start of the string. RIGHT gives the last n characters. Useful for truncating fields to 4000 chars.",
      "memory_tip": "LEFT = beginning. RIGHT = end. First 4000 chars = LEFT(field, 4000)."
    },
    {
      "id": 44,
      "category": "SQL",
      "front": "_EnterpriseAttribute vs _Subscribers data view: difference?",
      "back": "_EnterpriseAttribute = custom profile attributes (Age, Gender, custom fields). _Subscribers = standard subscriber fields (email address, status, lists).",
      "memory_tip": "_EnterpriseAttribute = custom profile data. _Subscribers = standard email/status fields."
    },
    {
      "id": 45,
      "category": "API",
      "front": "HTTP status codes 401, 403, 429, 500 in SFMC API context?",
      "back": "401=token expired/invalid (request new token). 403=forbidden (insufficient scope). 429=REST rate limit exceeded. 500=server error or SOAP rate limit.",
      "memory_tip": "401=Who are you? 403=I know you but NO. 429=Slow down! 500=Something broke."
    },
    {
      "id": 46,
      "category": "API",
      "front": "SOAP Error Code 5: what does it mean?",
      "back": "Cannot perform [method] on objects of type [object]. Tracking objects (SentEvent, OpenEvent, ClickEvent, BounceEvent) are READ-ONLY — Retrieve only.",
      "memory_tip": "Error 5 = Wrong method for this object type. Tracking events = read receipt. History cannot be changed."
    },
    {
      "id": 47,
      "category": "API",
      "front": "REST endpoint to inject a contact into a Journey Builder journey?",
      "back": "POST /interaction/v1/events with payload: ContactKey, EventDefinitionKey, and optional Data object with attribute values.",
      "memory_tip": "Journey EVENTS = /interaction/v1/EVENTS. The word 'events' appears in both the feature name and endpoint."
    },
    {
      "id": 48,
      "category": "API",
      "front": "DataExtension vs DataExtensionObject SOAP API objects: difference?",
      "back": "DataExtension = manages DE structure (schema, field definitions, retention). DataExtensionObject = manages DE rows (Create=insert, Retrieve=query, Update, Delete).",
      "memory_tip": "DataExtension = the TABLE. DataExtensionOBJECT = the ROWS inside the table."
    },
    {
      "id": 49,
      "category": "API",
      "front": "TriggeredSend.Create vs TriggeredSendDefinition.Create: difference?",
      "back": "TriggeredSendDefinition.Create = sets up the definition template only (no sends fired). TriggeredSend.Create = actually fires the email send to a subscriber.",
      "memory_tip": "DEFINITION = configure the gun. TriggeredSend.Create = PULL THE TRIGGER. Two different objects."
    },
    {
      "id": 50,
      "category": "API",
      "front": "LogUnsubEvent SOAP call: what three parameters are required in the Job Context?",
      "back": "JobID (which email job) + ListID (which subscriber list) + BatchID (which batch of the send). Together they uniquely identify the specific send.",
      "memory_tip": "Job + List + Batch = JLB. Three IDs to pinpoint the exact send that prompted the unsubscribe."
    },
    {
      "id": 51,
      "category": "API",
      "front": "TSE (Tenant Specific Endpoints): what is the benefit?",
      "back": "Improved API performance by routing requests directly to your tenant's specific infrastructure, bypassing the shared routing layer. NOT 'calls will no longer fail'.",
      "memory_tip": "TSE = direct route = FASTER. 'No longer fail' is always the wrong answer. Never accept it."
    },
    {
      "id": 52,
      "category": "API",
      "front": "REST API format vs SOAP API format?",
      "back": "REST API = JSON format. SOAP API = XML format (with SOAP envelope). Both use OAuth 2.0 Bearer token for authentication.",
      "memory_tip": "REST = JSON (modern, readable). SOAP = XML (legacy, verbose envelopes). New features = REST."
    },
    {
      "id": 53,
      "category": "API",
      "front": "ErrorDescription vs ErrorCode vs OverallStatus in SOAP responses?",
      "back": "ErrorDescription = human-readable actionable detail (what to fix). ErrorCode = numeric code only. OverallStatus = high-level 'OK' or 'Error' summary.",
      "memory_tip": "ErrorDESCRIPTION = the full explanation you actually need. OverallStatus = just OK/Error. Code = just a number."
    },
    {
      "id": 54,
      "category": "API",
      "front": "OAuth token management best practice?",
      "back": "Request one token → store with expiry timestamp → reuse for ALL calls → request a new one when near expiry or on 401. Never one token per call.",
      "memory_tip": "Get once, use many, refresh when needed. Like a daily bus pass — don't buy a new one every stop."
    },
    {
      "id": 55,
      "category": "API",
      "front": "How should the OAuth access token be included in a REST API request?",
      "back": "In the Authorization header: 'Authorization: Bearer {access_token}'. Never in query parameters (exposes in logs) or request body.",
      "memory_tip": "Authorization: Bearer {token}. BEARER before the token value. Always in the header, never in URL."
    },
    {
      "id": 56,
      "category": "API",
      "front": "Installed Package API scope: how is it determined?",
      "back": "Scope must be specifically and explicitly granted when creating the API Integration component. It does NOT automatically inherit from the creating user's role.",
      "memory_tip": "EXPLICIT GRANT only. No automatic inheritance from user role. You must choose each scope manually."
    },
    {
      "id": 57,
      "category": "Data Modeling",
      "front": "Filtered Data Extension: read-only or writable?",
      "back": "READ-ONLY. Filtered DEs are automatically populated based on filter criteria applied to a source Standard DE. You cannot import into or write to them directly.",
      "memory_tip": "Filtered DE = database view (read-only). Insert into the SOURCE Standard DE — Filtered DE auto-updates."
    },
    {
      "id": 58,
      "category": "Data Modeling",
      "front": "Where are Filtered Data Extensions created: Email Studio or Contact Builder?",
      "back": "Email Studio (via the Filter Activity). NOT in Contact Builder. Contact Builder is for data relationships, not filtered DE creation.",
      "memory_tip": "Filtered DE = Email Studio. Contact Builder = data model relationships. Different tools."
    },
    {
      "id": 59,
      "category": "Data Modeling",
      "front": "What two things are required to make a Data Extension sendable for email?",
      "back": "1) A field of type EmailAddress to store the recipient's email. 2) A Send Relationship mapping one DE field to the Subscriber Key.",
      "memory_tip": "EmailAddress field + Send Relationship = sendable. Missing either = cannot use for sends."
    },
    {
      "id": 60,
      "category": "Data Modeling",
      "front": "Can data retention be added to an existing DE that was created without it?",
      "back": "NO, if the DE was created without retention it cannot be added. YES, if retention WAS set at creation it can be modified. Retention must be configured at creation time.",
      "memory_tip": "Retention = set at birth or never. Can modify if set at creation. Can't add to a DE that had none."
    },
    {
      "id": 61,
      "category": "Data Modeling",
      "front": "Contact Delete: what data is removed when it completes?",
      "back": "Removes from: All Contacts, subscriber lists, AND rows in SENDABLE DEs. NON-sendable DEs are completely untouched. Import files on SFTP are untouched.",
      "memory_tip": "SENDABLE = eligible for cleanup. Non-sendable = untouched. SFTP files = untouched."
    },
    {
      "id": 62,
      "category": "Data Modeling",
      "front": "Can Synchronized Data Extensions be deleted from within SFMC?",
      "back": "NO. Synchronized DEs must be deleted from the source Salesforce CRM. You cannot delete them from the SFMC side.",
      "memory_tip": "Sync DE = lives in CRM. Delete from CRM source, not SFMC. SFMC just mirrors what CRM has."
    },
    {
      "id": 63,
      "category": "Data Modeling",
      "front": "Field type for a Purchase_Price column that contains values like '$6.96' and '$100'?",
      "back": "Text data type. The $ symbol means these values cannot be stored as Number or Decimal — those types only accept numeric characters.",
      "memory_tip": "$ symbol = Text type required. Number/Decimal can't store '$'. Text is the only safe choice for non-numeric characters."
    },
    {
      "id": 64,
      "category": "Data Modeling",
      "front": "Numeric Subscriber Key in Data Designer: what step is required?",
      "back": "Convert the Subscriber Key field to TEXT data type before creating the Data Designer relationship. Contact Key in SFMC is text/string type — types must match.",
      "memory_tip": "Contact Key = TEXT always. Numeric key? → CONVERT TO TEXT first. Like phone numbers stored as text."
    },
    {
      "id": 65,
      "category": "Data Modeling",
      "front": "Cardinality types available in Contact Builder Data Designer?",
      "back": "Three types: One-to-One (1:1), One-to-Many (1:M), and Many-to-Many (M:M). All three are supported for linking DEs in Attribute Groups.",
      "memory_tip": "Three cardinality types: 1:1, 1:M, M:M. Directly tested on the exam."
    },
    {
      "id": 66,
      "category": "Data Modeling",
      "front": "Contact Delete: from which business unit can it be initiated in Enterprise 2.0?",
      "back": "The TOP LEVEL (parent) business unit only. Contact Delete is not available from child business units in an Enterprise 2.0 account.",
      "memory_tip": "Contact Delete = top-level BU ONLY in Enterprise 2.0. Child BUs cannot initiate Contact Delete."
    },
    {
      "id": 67,
      "category": "Data Management",
      "front": "Correct flow to import an encrypted file from SFTP into a DE?",
      "back": "Enhanced FTP → File Transfer Activity (move to Safehouse + decrypt) → Import File Activity → Data Extension.",
      "memory_tip": "FTP → Transfer (decrypt here) → Safehouse → Import → DE. File Transfer = moves AND transforms."
    },
    {
      "id": 68,
      "category": "Data Management",
      "front": "Correct flow to export DE data to an external SFTP?",
      "back": "Data Extension → Data Extract Activity (exports to Safehouse) → File Transfer Activity (moves to FTP).",
      "memory_tip": "DE → Extract (Safehouse) → Transfer (FTP). Extract packages it. Transfer ships it."
    },
    {
      "id": 69,
      "category": "Data Management",
      "front": "What is the Safehouse in SFMC?",
      "back": "SFMC's internal temporary file storage. NOT externally accessible. Acts as an intermediary between Enhanced FTP and Import/Extract Activities.",
      "memory_tip": "Safehouse = internal staging. FTP = external. File Transfer bridges them."
    },
    {
      "id": 70,
      "category": "Data Management",
      "front": "Does Import File Activity have a 30-minute timeout like SQL Query Activity?",
      "back": "NO. Import File Activity has no 30-minute auto-kill. Only SQL Query Activities have the 30-minute timeout limit.",
      "memory_tip": "Import = no timeout. SQL = 30 min limit. They are different activity types with different rules."
    },
    {
      "id": 71,
      "category": "Data Management",
      "front": "Automation Studio: do Steps run sequentially or in parallel? What about Activities within a Step?",
      "back": "Steps run SEQUENTIALLY (one after another). Activities WITHIN one step run in PARALLEL (all at once). To enforce order, use separate steps.",
      "memory_tip": "Steps = sequential (one by one). Activities in same step = parallel (all at once). Need order? = separate steps."
    },
    {
      "id": 72,
      "category": "Data Management",
      "front": "Send Log: are Content Builder test sends recorded in the Send Log?",
      "back": "NO. Content Builder test sends are NOT recorded in the Send Log DE. Only actual production sends are logged.",
      "memory_tip": "Test = not real = not logged. Send Log = production sends ONLY."
    },
    {
      "id": 73,
      "category": "Data Management",
      "front": "%%FILENAME_FROM_TRIGGER%%: what does this substitution string represent?",
      "back": "The actual filename of the file that triggered a File Drop Automation. Used in subsequent Import File Activities to reference the triggering file.",
      "memory_tip": "%%FILENAME_FROM_TRIGGER%% = the file that landed on SFTP and triggered the automation."
    },
    {
      "id": 74,
      "category": "Data Management",
      "front": "File Drop vs Scheduled trigger in Automation Studio: when to use each?",
      "back": "File Drop: triggers immediately WHEN a file matching the pattern arrives (any time). Scheduled: runs at fixed predefined times regardless of file presence.",
      "memory_tip": "File Drop = reactive (responds to file). Schedule = proactive (runs on clock). File arrives anytime = File Drop."
    },
    {
      "id": 75,
      "category": "Security",
      "front": "TDE vs FLE vs Tokenized Sending: where is data stored in each?",
      "back": "TDE: stored in SFMC, encrypted at disk level (visible in app). FLE: stored in SFMC, specific fields encrypted (not searchable). Tokenized: PII NEVER enters SFMC — only tokens stored.",
      "memory_tip": "TDE = in SFMC, encrypted disk. FLE = in SFMC, field locked. Tokenized = PII stays OUTSIDE SFMC entirely."
    },
    {
      "id": 76,
      "category": "Security",
      "front": "FLE (Field-Level Encryption): can encrypted fields be filtered, sorted, or searched?",
      "back": "NO. FLE-encrypted fields CANNOT be filtered, sorted, segmented, or used in SQL WHERE clauses or JOINs. The data is stored but not queryable.",
      "memory_tip": "FLE = locked box in the database. You can store it but you cannot search inside it."
    },
    {
      "id": 77,
      "category": "Security",
      "front": "TDE (Transparent Data Encryption): what are its limitations in SFMC?",
      "back": "TDE does NOT work with Einstein/Predictive Intelligence, Audience Builder, or Social Studio. These features need to read data to function — TDE blocks that at disk level.",
      "memory_tip": "TDE + AI features = incompatible. AI needs to read data. TDE encrypts at disk. They conflict."
    },
    {
      "id": 78,
      "category": "Security",
      "front": "Tokenized Sending: how does it work?",
      "back": "Your external system stores real PII and gives SFMC only tokens (placeholders). At send time, SFMC calls your Token Resolve API in real-time to get the actual value for personalization — never stored.",
      "memory_tip": "SFMC only sees tokens. At send time: calls YOUR server for real value. Maximum privacy protection."
    },
    {
      "id": 79,
      "category": "Security",
      "front": "SSL certificates: minimum required for a CloudPage with images in Content Builder?",
      "back": "Minimum 2: Content SSL (for the CloudPage domain) + CDN/Portfolio SSL (for images served from SFMC CDN). Full tracking coverage = 4 total.",
      "memory_tip": "CloudPage = 1 SSL. Images = 1 SSL. Minimum = 2. Full coverage with click+open tracking = 4."
    },
    {
      "id": 80,
      "category": "Security",
      "front": "Supported file encryption formats for SFMC import/export?",
      "back": "PGP (Pretty Good Privacy) and GPG (GNU Privacy Guard). RSA and AES are encryption algorithms but NOT supported as file-level formats for SFMC file imports.",
      "memory_tip": "File import encryption = PGP and GPG ONLY. RSA/AES are algorithms not file-level formats SFMC supports."
    },
    {
      "id": 81,
      "category": "Security",
      "front": "Key Management in SFMC: what key types are supported?",
      "back": "Asymmetric (Certificate), Symmetric (Passphrase/AES), Initialization Vector (IV), Salt, and SAML. Five key types total.",
      "memory_tip": "5 key types: Asymmetric=certificate, Symmetric=passphrase, IV=randomizer, Salt=entropy, SAML=SSO."
    },
    {
      "id": 82,
      "category": "Security",
      "front": "API integration security best practices: what should be applied?",
      "back": "Least privilege scope only. One Installed Package per integration. Never use admin role for API. Store client secret in KMS. Child BU access = separate package/token.",
      "memory_tip": "Minimum permissions + separate packages + KMS storage. Never admin role for API integrations."
    }
  ]
}