$method, 'timeout' => $timeout, 'headers' => array( 'Authorization' => 'Bearer ' . self::key(), 'Accept' => 'application/json', 'Content-Type' => 'application/json', 'User-Agent' => 'PostaraMail-WordPress/' . POSTARAMAIL_WP_VERSION, ), ); if ( null !== $body ) { $args['body'] = wp_json_encode( $body ); } $response = wp_remote_request( self::base() . $path, $args ); if ( is_wp_error( $response ) ) { // Network problem: worth retrying later. return self::result( false, 0, array(), 'network', $response->get_error_message(), true ); } $status = (int) wp_remote_retrieve_response_code( $response ); $data = json_decode( wp_remote_retrieve_body( $response ), true ); $data = is_array( $data ) ? $data : array(); if ( $status >= 200 && $status < 300 ) { return self::result( true, $status, $data, '', '', false ); } $code = isset( $data['error']['code'] ) ? (string) $data['error']['code'] : 'http_' . $status; $message = isset( $data['error']['message'] ) ? (string) $data['error']['message'] : sprintf( 'HTTP %d', $status ); // Server trouble and rate limits are temporary; everything else is a decision the API made. $retry = ( $status >= 500 || 429 === $status || 0 === $status ); return self::result( false, $status, $data, $code, $message, $retry ); } private static function result( $ok, $status, $data, $code, $message, $retry ) { return compact( 'ok', 'status', 'data', 'code', 'message', 'retry' ); } public static function me() { return self::request( 'GET', '/api/v1/me' ); } /** The plan and usage, cached for 5 minutes so the dashboard stays fast. */ public static function me_cached( $force = false ) { if ( ! $force ) { $c = get_transient( 'postaramail_me' ); if ( is_array( $c ) ) { return $c; } } $r = self::me(); if ( $r['ok'] ) { set_transient( 'postaramail_me', $r['data'], 5 * MINUTE_IN_SECONDS ); return $r['data']; } return null; } public static function automations() { return self::request( 'GET', '/api/v1/automations' ); } /** * Adds a contact. Consent is always true here: callers only reach this * after the person ticked a box or submitted a form that says so. */ /** * Adds a contact who agreed. consent_method is "optin" (tick box, "yes", form) or "notice" (told at * signup). PostaraMail uses it with the person's country for the EU / UK rules when sending. * Give either a country code or the visitor's IP address (turned into a country there, never stored). */ public static function add_contact( $email, $first = '', $last = '', $start_automations = true, $source = 'WordPress', $consent_text = '', $consent_method = 'optin', $country = '', $ip = '', $confirmed = false ) { $body = array( 'email' => $email, 'first_name' => $first, 'last_name' => $last, 'consent' => true, 'consent_text' => $consent_text, 'consent_method' => 'notice' === $consent_method ? 'notice' : 'optin', 'source' => $source, 'start_automations' => (bool) $start_automations, ); if ( $confirmed ) { $body['confirmed'] = true; // already confirmed (e.g. answered yes while logged in): no confirmation email needed } if ( $country ) { $body['country'] = $country; } elseif ( $ip ) { $body['ip'] = $ip; } return self::request( 'POST', '/api/v1/contacts', $body ); } /** Existing users: "not asked yet" (shown in PostaraMail, never emailed) and people who said no. */ public static function contacts_sync( $pending = array(), $declined = array(), $timeout = 25 ) { return self::request( 'POST', '/api/v1/contacts/sync', array( 'pending' => array_values( $pending ), 'declined' => array_values( $declined ), ), $timeout ); } /** Reports stats, receives the dashboard's settings when they changed. */ public static function heartbeat( $payload ) { return self::request( 'POST', '/api/v1/site/heartbeat', $payload, 10 ); } public static function put_settings( $settings, $base_rev ) { return self::request( 'PUT', '/api/v1/site/settings', array( 'settings' => $settings, 'base_rev' => (int) $base_rev, ), 10 ); } /** Trades the one-time code from the approval screen for this site's key (no key needed yet). */ public static function exchange( $code ) { $response = wp_remote_request( self::base() . '/api/connect/exchange', array( 'method' => 'POST', 'timeout' => 15, 'headers' => array( 'Content-Type' => 'application/json', 'Accept' => 'application/json', 'User-Agent' => 'PostaraMail-WordPress/' . POSTARAMAIL_WP_VERSION, ), 'body' => wp_json_encode( array( 'code' => $code, 'site' => untrailingslashit( home_url() ), ) ), ) ); if ( is_wp_error( $response ) ) { return self::result( false, 0, array(), 'network', $response->get_error_message(), true ); } $status = (int) wp_remote_retrieve_response_code( $response ); $data = json_decode( wp_remote_retrieve_body( $response ), true ); $data = is_array( $data ) ? $data : array(); if ( 200 === $status && ! empty( $data['key'] ) ) { return self::result( true, $status, $data, '', '', false ); } $msg = isset( $data['error']['message'] ) ? $data['error']['message'] : sprintf( 'HTTP %d', $status ); return self::result( false, $status, $data, isset( $data['error']['code'] ) ? $data['error']['code'] : 'http_' . $status, $msg, false ); } /** Tells PostaraMail to revoke this site's key (best effort). */ public static function disconnect() { return self::request( 'POST', '/api/v1/connect/disconnect', array() ); } public static function enroll( $automation_id, $email ) { return self::request( 'POST', '/api/v1/automations/' . (int) $automation_id . '/enroll', array( 'email' => $email ) ); } }